Compare commits

..

No commits in common. "master" and "v0.6.0" have entirely different histories.

350 changed files with 25115 additions and 42842 deletions

View File

@ -1,21 +0,0 @@
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

View File

@ -1,40 +0,0 @@
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

3
.gitignore vendored
View File

@ -5,7 +5,4 @@
Thumbs.db
build/
lib/
docs/
examples/
internal_docs
build.sh

View File

@ -1,481 +0,0 @@
# 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:
- Added support for the nfc:m/nfc:u service.
- Added support for the ssl:C service.
- Added support for the nwm::UDS service (Local wireless).
- Added support for the boss:P/boss:U service (SpotPass).
- Added support for using the err:f global port.
- Added support for using and parsing the shared system font.
- Added support for using the 3DS' built-in software keyboard applet.
- Added support for using Light Events, a lightweight alternative to normal events that doesn't consume handles.
- Added NDSP commands for setting up per-channel monopole & biquad filters.
* Major breaking changes:
- Major revamp of the APT code; some old deprecated functions were completely removed, homebrew code abiding by recent standards shouldn't be affected though.
- Major revamp of the HTTPC code, including both additions and bugfixes.
- Major revamp of the AM code, with some enhancements.
- Major revamp of FSUSER code, archive handle handling has been refactored. fs(End)UseSession replaced with fsExemptFromSession.
- Major revamp of MVD code to support video processing.
- Major revamp of the GPU shader code to fully support geometry shaders.
- The old deprecated GPU wrapper commands have been removed. Use direct GPU register writes or a separate GPU wrapper library (such as citro3d) instead.
- Major revamp and update of the SVC debugger API.
- Heap size management has been simplified and made more flexible. All applications now default to 32MB of linear heap and all remaining APPLICATION memory is allocated as the application heap, regardless of entrypoint or application format.
* Miscellaneous additions:
- Several enhancements to SOC:u support:
- Added getaddrinfo, getnameinfo, gethostname, gai_strerror.
- Added SOCU_ShutdownSockets, SOCU_CloseSockets, SOCU_GetIPInfo, SOCU_GetNetworkOpt, SOCU_AddGlobalSocket.
- Added several missing flags.
- Minor am:net corrections and additions.
- Added sdmcWriteSafe to disable copying data to temporary RW buffers before calling FSFILE_Write.
- Added sdmc_getmtime to retrieve the modification time for a file.
- Added opendir/readdir/rewinddir/closedir/stat support to romfs.
- Added support for multiple RomFS mounts.
- Added macros for console color codes (ANSI escape sequences).
- Added support for specifying a fallback RomFS path for when argv isn't available.
- Added aptIsSleepAllowed/aptSetSleepAllowed.
- Added ResetType enum for use with svcCreateEvent and svcCreateTimer.
- Added psInitHandle and psGetSessionHandle.
- Added AM commands: AM_ExportTwlBackup, AM_ImportTwlBackup, AM_ReadTwlBackupInfo, AM_DeleteAllDemoLaunchInfos, AM_FinishCiaInstallWithoutCommit, AM_CommitImportPrograms.
- Added AMPXI commands: AMPXI_WriteTWLSavedata, AMPXI_InstallTitlesFinish.
- Added APT commands: APT_ReceiveDeliverArg.
- Added CFG commands: CFG_GetConfigInfoBlk4, CFG_GetConfigInfoBlk8, CFG_SetConfigInfoBlk4, CFG_SetConfigInfoBlk8, CFG_UpdateConfigNANDSavegame.
- Added GSPLCD commands: GSPLCD_GetVendors
- Added FSUSER commands: FSUSER_UpdateSha256Context.
- Added NEWS commands: NEWS_GetTotalNotifications, NEWS_SetNotificationHeader, NEWS_GetNotificationHeader, NEWS_GetNotificationMessage, NEWS_GetNotificationImage, NEWS_SetNotificationMessage, NEWS_SetNotificationImage.
- Added NS commands: NS_TerminateProcessTID, NS_LaunchFIRM, NS_LaunchApplicationFIRM.
- Added PS commands: PS_SignRsaSha256, PS_VerifyRsaSha256.
- Added PTMSYSM commands: PTMSYSM_CheckNew3DS, PTMSYSM_ShutdownAsync, PTMSYSM_RebootAsync.
- Added PXIDEV commands: PXIDEV_SPIMultiWriteRead, PXIDEV_SPIWriteRead.
- Added system calls: svcCreateCodeSet, svcCreateProcess, svcGetResourceLimit, svcGetResourceLimitValues, svcGetResourceLimitCurrentValues, svcSetProcessAffinityMask, svcSetProcessIdealProcessor, svcRun, svcBindInterrupt, svcUnbindInterrupt, svcGetHandleInfo, svcBreakRO, svcGetThreadList.
- Added result module codes.
- Added GPU A4 texture format enum.
* Miscellaneous changes and bug fixes:
- Optimized sdmc's readdir to batch directory entries.
- APT, GSPGPU and NDSP code was tuned to take advantage of Light Events.
- Moved am:app init to a separate function.
- Several issues concerning IPC static buffer saving/restoring were fixed.
- Several issues concerning sdmc/RomFS devoptabs were fixed.
- Several issues concerning SOC:u were fixed.
- An issue concerning cam:u was fixed.
- An issue concerning HID was fixed.
- An issue concerning news:u was fixed.
- The GPU ETC1 texture format enums were fixed.
- usleep was fixed.
- Fixed incorrect bool return values from services.
- Fixed buffer overflow after gfxSetScreenFormat.
- Fixed home menu display of suspended 2D applications.
- Fixed buffer overrun in console code.
- Fixed PS_EncryptDecryptAes and PS_EncryptSignDecryptVerifyAesCcm.
- Fixed the implementation of svcGetProcessList.
- Corrected svcKernelSetState function signature.
## Version 1.1.0
* Additions:
- GSPGPU/GX code was revised and enhanced:
- Screens can be buffer-swapped independently using the new gfxConfigScreen function.
- Added gspSetEventCallback for running event code directly on the GSP thread.
- Added gspWaitForAnyEvent for waiting for any GSP event.
- Added gfxIs3D for retrieving 3D-enable status.
- Added AM_InstallFirm.
- Added __sync_get_arbiter.
- Added support for usleep.
* Changes:
- NDSP thread priority has been increased, therefore mitigating potential sound issues due to high CPU usage on the main thread.
- RomFS initialization no longer makes romfs:/ the default device.
* Bug fixes:
- Fixed the timeout parameter in svcArbitrateAddress.
- Fixed svcSetTimer.
## Version 1.0.0
* New features:
- libctru documentation is now available at http://smealum.github.io/ctrulib/
- Added the NDSP API, which allows the use of the DSP (audio).
- Added Inter Process Communication helpers.
- Added Result code helpers.
- Added support for lightweight synchronization primitives.
- Added support for making the C/C++ standard libraries thread safe.
- Added support for thread-local objects, with the use of standard C and C++ constructs (or GCC extensions).
- Added a new threading API that properly manages internal state. Direct usage of svcCreateThread is deprecated.
- Added a mappable address space allocator. Services which need to map shared memory blocks now use this allocator.
- Added support for embedded RomFS, embedded SMDH and GPU shader building in the template Makefiles.
* Changes and additions to the GPU code:
- Stateless wrapper functions (GPU_*) that merely masked GPU register usage were deprecated, in favour of external GPU wrapper libraries such as citro3d. A future release of libctru may remove them.
- The API set has therefore been simplified down to command list management.
- Synchronized register names with the 3dbrew Wiki.
- Added fragment lighting registers and enums.
- Added procedural texture registers and enums.
- Added shaderProgramSetGshInputPermutation, for configuring the wiring between the vertex shader and the geometry shader.
- Added shaderProgramSetGshMode, for configuring the geometry shader operation mode.
- Added shaderProgramConfigure, intended to be used by GPU wrapper libraries.
- SHBIN/shaderProgram code now correctly computes and sets the values of the GPUREG_SH_OUTATTR_MODE/CLOCK registers.
- GX function naming has been improved, and the initial GX command buffer parameter has been removed.
* Major changes and miscellaneous additions:
- Sweeping changes to make function/structure/enum naming more consistent across the whole library. This affects a lot of code.
- Compiler/linker flags have been tweaked to increase performance and reduce code size, through the garbage collection of unused functions.
- Service initialization is now reference counted in order to properly manage dependencies.
- Initial service handle parameters have been removed, since they were nearly always set to NULL.
- Completed coverage of srv and FSUSER service calls.
- Added fsUseSession and fsEndUseSession for overriding the FSUSER session used in commands in the current thread.
- Added osGet3DSliderState, osSetSpeedupEnable, osGetSystemVersionData and osGetSystemVersionDataString.
- Refactored the MICU service.
- NCCH versions of applications now detect the maximum amount of available memory on startup.
* Miscellaneous changes and bug fixes:
- Commits and pull requests are now built on travis to check that the library compiles, and to generate the documentation.
- General changes and improvements to overall code quality.
- Added the missing struct and functions for Y2R.
- Added srvGetServiceHandleDirect for bypassing the handle override mechanism.
- Usage of the CSND service in new applications is not recommended, however it is not deprecated. The usage of NDSP instead is advised.
- Usage of the HB service in new applications is not recommended due to its necessary removal in hax 2.x, however it is not deprecated.
- Several bugs affecting APT were fixed.
- Several bugs affecting C++ were fixed.
## Version 0 through 0.6.0
No changelog available.

View File

@ -1,27 +1,24 @@
# libctru - CTR User Library
ctrulib
=======
![Build Status](https://github.com/devkitPro/libctru/actions/workflows/build.yaml/badge.svg)
CTR User Library
Library for writing user mode ARM11 code for the 3DS (CTR)
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.
the goal with this is to create a very straightforward interface with the 3DS's OS.
it is not meant to provide higher level functions; to put things in perspective, the purpose of ctrulib 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
=======
# Setup
ctrulib is just a library and needs a toolchain to function. we built ctrulib to be used in conjunction with devkitARM. you may find instructions on how to install devkitARM here : http://devkitpro.org/wiki/Getting_Started
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 devkitARM (r43) includes 3DS support and a prebuilt libctru.
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.
To keep up to date with the most recent changes you'll want to checkout ctrulib, build it and install it.
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: https://devkitpro.github.io/libctru/
# License
license
=======
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any

3
examples/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
build/
*.3dsx
*.elf

26
examples/Makefile Normal file
View File

@ -0,0 +1,26 @@
SUBDIRS:= $(shell ls | egrep -v '^(CVS)$$')
DATESTRING := $(shell date +%Y)$(shell date +%m)$(shell date +%d)
#---------------------------------------------------------------------------------
all: examples
#---------------------------------------------------------------------------------
@rm -fr bin
@mkdir -p bin
@find . -name "*.3dsx" ! -path "./bin/*" -exec cp -fv {} bin \;
examples:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
#---------------------------------------------------------------------------------
clean:
#---------------------------------------------------------------------------------
@rm -fr bin
@rm -f *.bz2
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
#---------------------------------------------------------------------------------
dist: clean
#---------------------------------------------------------------------------------
@rm -fr bin
@tar --exclude=.svn --exclude=*CVS* -cvjf 3ds-examples-$(DATESTRING).tar.bz2 *

View File

@ -0,0 +1,170 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
.PHONY: all
all : $(OUTPUT).3dsx $(OUTPUT).smdh
endif
$(OUTPUT).3dsx : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,9 @@
app_launch
=======
Example for launching other apps/applets with ctrulib. Press the A button to launch the app or applet specified in the source.
Note: The title ID of the EUR Nintendo 3DS Camera app is hardcoded and you need to change it if your 3DS is not an european one. See here for title IDs: http://3dbrew.org/wiki/Title_list#00040010_-_System_Applications
This example only works if launched as regular app by the home menu. It will not work with the homebrew menu.

View File

@ -0,0 +1,49 @@
#include <stdio.h>
#include <string.h>
#include <3ds.h>
int main()
{
gfxInitDefault(); // Init graphic stuff
// We need these 2 buffers for APT_DoAppJump() later. They can be smaller too
u8 buf0[0x300];
u8 buf1[0x20];
// Loop as long as the status is not exit
while(aptMainLoop())
{
// Scan hid shared memory for input events
hidScanInput();
if(hidKeysDown() & KEY_A) // If the A button got pressed, start the app launch
{
// Clear both buffers
memset(buf0, 0, 0x300);
memset(buf1, 0, 0x20);
// Open an APT session so we can talk to the APT service
aptOpenSession();
// Prepare for the app launch
APT_PrepareToDoAppJump(NULL, 0, 0x0004001000022400LL, 0); // *EUR* camera app title ID
// Tell APT to trigger the app launch and set the status of this app to exit
APT_DoAppJump(NULL, 0x300 /* size of buf0 */, 0x20 /* size of buf1 */, buf0, buf1);
// Close the APT session because we don't need APT anymore
aptCloseSession();
}
// Flush + swap framebuffers and wait for VBlank. Not really needed in this example
gfxFlushBuffers();
gfxSwapBuffers();
gspWaitForVBlank();
}
gfxExit();
return 0;
}

170
examples/audio/mic/Makefile Normal file
View File

@ -0,0 +1,170 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
.PHONY: all
all : $(OUTPUT).3dsx $(OUTPUT).smdh
endif
$(OUTPUT).3dsx : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,5 @@
mic
=======
Example for using the microphone with ctrulib. Hold down the A button to record, the app will then play the recorded audio once the A button is released. Roughly 32 seconds of audio can be recorded with the default audiobuf size in this app.

View File

@ -0,0 +1,95 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <3ds.h>
int main()
{
u8 *framebuf;
u32 *sharedmem = NULL, sharedmem_size = 0x30000;
u8 *audiobuf;
u32 audiobuf_size = 0x100000, audiobuf_pos = 0;
u8 control=0x40;
u32 audio_initialized = 0;
gfxInitDefault();
consoleInit(GFX_BOTTOM, NULL);
if(csndInit()==0)
{
printf("Init success\n");
audio_initialized = 1;
}
sharedmem = (u32*)memalign(0x1000, sharedmem_size);
audiobuf = linearAlloc(audiobuf_size);
MIC_Initialize(sharedmem, sharedmem_size, control, 0, 3, 1, 1);//See mic.h.
while(aptMainLoop())
{
hidScanInput();
gspWaitForVBlank();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
if(audio_initialized)
{
framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
if(kDown & KEY_A)
{
audiobuf_pos = 0;
printf("Stopping audio playback\n");
CSND_SetPlayState(0x8, 0);//Stop audio playback.
CSND_UpdateInfo(0);
MIC_SetRecording(1);
memset(framebuf, 0x20, 0x46500);
printf("Now recording\n");
}
if((hidKeysHeld() & KEY_A) && audiobuf_pos < audiobuf_size)
{
audiobuf_pos+= MIC_ReadAudioData(&audiobuf[audiobuf_pos], audiobuf_size-audiobuf_pos, 1);
if(audiobuf_pos > audiobuf_size)audiobuf_pos = audiobuf_size;
memset(framebuf, 0x60, 0x46500);
}
if(hidKeysUp() & KEY_A)
{
printf("Playing the recorded sample\n");
MIC_SetRecording(0);
GSPGPU_FlushDataCache(NULL, audiobuf, audiobuf_pos);
csndPlaySound(0x8, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 16000, 1.0, 0.0, (u32*)audiobuf, NULL, audiobuf_pos);
memset(framebuf, 0xe0, 0x46500);
gfxFlushBuffers();
gfxSwapBuffers();
framebuf = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
memset(framebuf, 0xe0, 0x46500);
}
}
gfxFlushBuffers();
gfxSwapBuffers();
}
MIC_Shutdown();
if(audio_initialized)csndExit();
free(sharedmem);
linearFree(audiobuf);
gfxExit();
return 0;
}

View File

@ -0,0 +1,172 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := src
DATA := data
INCLUDES := include
APP_TITLE := 3D Camera Example
APP_DESCRIPTION := Example application that takes 3D pictures
APP_AUTHOR := wchill
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
.PHONY: all
all : $(OUTPUT).3dsx $(OUTPUT).smdh
endif
$(OUTPUT).3dsx : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,7 @@
image
=======
Example for using the camera to take 3D pictures with ctrulib. Press the R button to take a picture - it will be displayed on the top screen.
Currently this example does not make use of the 3DS camera's calibration data to get a correct 3D effect.

View File

@ -0,0 +1,3 @@
<targets selectable="false">
<title mediatype="0">0004001000021400</title>
</targets>

View File

@ -0,0 +1,190 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <setjmp.h>
#include <3ds.h>
#include <sys/dirent.h>
#include <sys/errno.h>
#include <sys/unistd.h>
#include <stdbool.h>
#define CONFIG_3D_SLIDERSTATE (*(volatile float*)0x1FF81080)
#define WAIT_TIMEOUT 300000000ULL
#define WIDTH 400
#define HEIGHT 240
#define SCREEN_SIZE WIDTH * HEIGHT * 2
#define BUF_SIZE SCREEN_SIZE * 2
static jmp_buf exitJmp;
inline void clearScreen(void) {
u8 *frame = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
memset(frame, 0, 320 * 240 * 3);
}
void hang(char *message) {
clearScreen();
printf("%s", message);
printf("Press start to exit");
while (aptMainLoop()) {
hidScanInput();
u32 kHeld = hidKeysHeld();
if (kHeld & KEY_START) longjmp(exitJmp, 1);
}
}
void cleanup() {
camExit();
gfxExit();
acExit();
}
void writePictureToFramebufferRGB565(void *fb, void *img, u16 x, u16 y, u16 width, u16 height) {
u8 *fb_8 = (u8*) fb;
u16 *img_16 = (u16*) img;
int i, j, draw_x, draw_y;
for(j = 0; j < height; j++) {
for(i = 0; i < width; i++) {
draw_y = y + height - j;
draw_x = x + i;
u32 v = (draw_y + draw_x * height) * 3;
u16 data = img_16[j * width + i];
uint8_t b = ((data >> 11) & 0x1F) << 3;
uint8_t g = ((data >> 5) & 0x3F) << 2;
uint8_t r = (data & 0x1F) << 3;
fb_8[v] = r;
fb_8[v+1] = g;
fb_8[v+2] = b;
}
}
}
// TODO: Figure out how to use CAMU_GetStereoCameraCalibrationData
void takePicture3D(u8 *buf) {
u32 bufSize;
printf("CAMU_GetMaxBytes: 0x%08X\n", (unsigned int) CAMU_GetMaxBytes(&bufSize, WIDTH, HEIGHT));
printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_BOTH, bufSize, WIDTH, HEIGHT));
printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_OUT1_OUT2));
Handle camReceiveEvent = 0;
Handle camReceiveEvent2 = 0;
printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_BOTH));
printf("CAMU_SynchronizeVsyncTiming: 0x%08X\n", (unsigned int) CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2));
printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_BOTH));
printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize));
printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT));
printf("CAMU_PlayShutterSound: 0x%08X\n", (unsigned int) CAMU_PlayShutterSound(SHUTTER_SOUND_TYPE_NORMAL));
printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_BOTH));
svcCloseHandle(camReceiveEvent);
svcCloseHandle(camReceiveEvent2);
printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_NONE));
}
int main() {
// Initializations
acInit();
gfxInitDefault();
consoleInit(GFX_BOTTOM, NULL);
// Enable double buffering to remove screen tearing
gfxSetDoubleBuffering(GFX_TOP, true);
gfxSetDoubleBuffering(GFX_BOTTOM, false);
// Save current stack frame for easy exit
if(setjmp(exitJmp)) {
cleanup();
return 0;
}
u32 kDown;
u32 kHeld;
printf("Initializing camera\n");
printf("camInit: 0x%08X\n", (unsigned int) camInit());
printf("CAMU_SetSize: 0x%08X\n", (unsigned int) CAMU_SetSize(SELECT_OUT1_OUT2, SIZE_CTR_TOP_LCD, CONTEXT_A));
printf("CAMU_SetOutputFormat: 0x%08X\n", (unsigned int) CAMU_SetOutputFormat(SELECT_OUT1_OUT2, OUTPUT_RGB_565, CONTEXT_A));
printf("CAMU_SetNoiseFilter: 0x%08X\n", (unsigned int) CAMU_SetNoiseFilter(SELECT_OUT1_OUT2, true));
printf("CAMU_SetAutoExposure: 0x%08X\n", (unsigned int) CAMU_SetAutoExposure(SELECT_OUT1_OUT2, true));
printf("CAMU_SetAutoWhiteBalance: 0x%08X\n", (unsigned int) CAMU_SetAutoWhiteBalance(SELECT_OUT1_OUT2, true));
//printf("CAMU_SetEffect: 0x%08X\n", (unsigned int) CAMU_SetEffect(SELECT_OUT1_OUT2, EFFECT_MONO, CONTEXT_A));
printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM1, false));
printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM2, false));
//printf("CAMU_SetTrimmingParamsCenter: 0x%08X\n", (unsigned int) CAMU_SetTrimmingParamsCenter(PORT_CAM1, 512, 240, 512, 384));
u8 *buf = malloc(BUF_SIZE);
if(!buf) {
hang("Failed to allocate memory!");
}
gfxFlushBuffers();
gspWaitForVBlank();
gfxSwapBuffers();
bool held_R = false;
printf("\nPress R to take a new picture\n");
printf("Use slider to enable/disable 3D\n");
printf("Press Start to exit to Homebrew Launcher\n");
// Main loop
while (aptMainLoop()) {
// Read which buttons are currently pressed or not
hidScanInput();
kDown = hidKeysDown();
kHeld = hidKeysHeld();
// If START button is pressed, break loop and quit
if (kDown & KEY_START) {
break;
}
if ((kHeld & KEY_R) && !held_R) {
printf("Capturing new image\n");
gfxFlushBuffers();
gspWaitForVBlank();
gfxSwapBuffers();
held_R = true;
takePicture3D(buf);
} else if (!(kHeld & KEY_R)) {
held_R = false;
}
if(CONFIG_3D_SLIDERSTATE > 0.0f) {
gfxSet3D(true);
writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), buf, 0, 0, WIDTH, HEIGHT);
writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), buf + SCREEN_SIZE, 0, 0, WIDTH, HEIGHT);
} else {
gfxSet3D(false);
writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), buf, 0, 0, WIDTH, HEIGHT);
}
// Flush and swap framebuffers
gfxFlushBuffers();
gspWaitForVBlank();
gfxSwapBuffers();
}
// Exit
free(buf);
cleanup();
// Return to hbmenu
return 0;
}

View File

@ -0,0 +1,172 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := src
DATA := data
INCLUDES := include
APP_TITLE := 3D Camera Example
APP_DESCRIPTION := Example application that takes 3D pictures
APP_AUTHOR := wchill
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
.PHONY: all
all : $(OUTPUT).3dsx $(OUTPUT).smdh
endif
$(OUTPUT).3dsx : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,7 @@
video
=======
Example for using the camera to capture 3D videos with ctrulib.
Currently this example does not make use of the 3DS camera's calibration data to get a correct 3D effect.

View File

@ -0,0 +1,206 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <setjmp.h>
#include <3ds.h>
#include <sys/dirent.h>
#include <sys/errno.h>
#include <sys/unistd.h>
#include <stdbool.h>
#define CONFIG_3D_SLIDERSTATE (*(volatile float*)0x1FF81080)
#define WAIT_TIMEOUT 1000000000ULL
#define WIDTH 400
#define HEIGHT 240
#define SCREEN_SIZE WIDTH * HEIGHT * 2
#define BUF_SIZE SCREEN_SIZE * 2
static jmp_buf exitJmp;
inline void clearScreen(void) {
u8 *frame = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
memset(frame, 0, 320 * 240 * 3);
}
void hang(char *message) {
clearScreen();
printf("%s", message);
printf("Press start to exit");
while (aptMainLoop()) {
hidScanInput();
u32 kHeld = hidKeysHeld();
if (kHeld & KEY_START) longjmp(exitJmp, 1);
}
}
void cleanup() {
camExit();
gfxExit();
acExit();
}
void writePictureToFramebufferRGB565(void *fb, void *img, u16 x, u16 y, u16 width, u16 height) {
u8 *fb_8 = (u8*) fb;
u16 *img_16 = (u16*) img;
int i, j, draw_x, draw_y;
for(j = 0; j < height; j++) {
for(i = 0; i < width; i++) {
draw_y = y + height - j;
draw_x = x + i;
u32 v = (draw_y + draw_x * height) * 3;
u16 data = img_16[j * width + i];
uint8_t b = ((data >> 11) & 0x1F) << 3;
uint8_t g = ((data >> 5) & 0x3F) << 2;
uint8_t r = (data & 0x1F) << 3;
fb_8[v] = r;
fb_8[v+1] = g;
fb_8[v+2] = b;
}
}
}
// TODO: Figure out how to use CAMU_GetStereoCameraCalibrationData
void takePicture3D(u8 *buf) {
u32 bufSize;
printf("CAMU_GetMaxBytes: 0x%08X\n", (unsigned int) CAMU_GetMaxBytes(&bufSize, WIDTH, HEIGHT));
printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_BOTH, bufSize, WIDTH, HEIGHT));
printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_OUT1_OUT2));
Handle camReceiveEvent = 0;
Handle camReceiveEvent2 = 0;
printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_BOTH));
printf("CAMU_SynchronizeVsyncTiming: 0x%08X\n", (unsigned int) CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2));
printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_BOTH));
printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize));
printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT));
printf("CAMU_PlayShutterSound: 0x%08X\n", (unsigned int) CAMU_PlayShutterSound(SHUTTER_SOUND_TYPE_NORMAL));
printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_BOTH));
svcCloseHandle(camReceiveEvent);
svcCloseHandle(camReceiveEvent2);
printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_NONE));
}
int main() {
// Initializations
acInit();
gfxInitDefault();
consoleInit(GFX_BOTTOM, NULL);
// Enable double buffering to remove screen tearing
gfxSetDoubleBuffering(GFX_TOP, true);
gfxSetDoubleBuffering(GFX_BOTTOM, false);
// Save current stack frame for easy exit
if(setjmp(exitJmp)) {
cleanup();
return 0;
}
u32 kDown;
printf("Initializing camera\n");
printf("camInit: 0x%08X\n", (unsigned int) camInit());
printf("CAMU_SetSize: 0x%08X\n", (unsigned int) CAMU_SetSize(SELECT_OUT1_OUT2, SIZE_CTR_TOP_LCD, CONTEXT_A));
printf("CAMU_SetOutputFormat: 0x%08X\n", (unsigned int) CAMU_SetOutputFormat(SELECT_OUT1_OUT2, OUTPUT_RGB_565, CONTEXT_A));
// TODO: For some reason frame grabbing times out above 10fps. Figure out why this is.
printf("CAMU_SetFrameRate: 0x%08X\n", (unsigned int) CAMU_SetFrameRate(SELECT_OUT1_OUT2, FRAME_RATE_10));
printf("CAMU_SetNoiseFilter: 0x%08X\n", (unsigned int) CAMU_SetNoiseFilter(SELECT_OUT1_OUT2, true));
printf("CAMU_SetAutoExposure: 0x%08X\n", (unsigned int) CAMU_SetAutoExposure(SELECT_OUT1_OUT2, true));
printf("CAMU_SetAutoWhiteBalance: 0x%08X\n", (unsigned int) CAMU_SetAutoWhiteBalance(SELECT_OUT1_OUT2, true));
// TODO: Figure out how to use the effects properly.
//printf("CAMU_SetEffect: 0x%08X\n", (unsigned int) CAMU_SetEffect(SELECT_OUT1_OUT2, EFFECT_SEPIA, CONTEXT_A));
printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM1, false));
printf("CAMU_SetTrimming: 0x%08X\n", (unsigned int) CAMU_SetTrimming(PORT_CAM2, false));
//printf("CAMU_SetTrimmingParamsCenter: 0x%08X\n", (unsigned int) CAMU_SetTrimmingParamsCenter(PORT_CAM1, 512, 240, 512, 384));
u8 *buf = malloc(BUF_SIZE);
if(!buf) {
hang("Failed to allocate memory!");
}
u32 bufSize;
printf("CAMU_GetMaxBytes: 0x%08X\n", (unsigned int) CAMU_GetMaxBytes(&bufSize, WIDTH, HEIGHT));
printf("CAMU_SetTransferBytes: 0x%08X\n", (unsigned int) CAMU_SetTransferBytes(PORT_BOTH, bufSize, WIDTH, HEIGHT));
printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_OUT1_OUT2));
Handle camReceiveEvent = 0;
Handle camReceiveEvent2 = 0;
printf("CAMU_ClearBuffer: 0x%08X\n", (unsigned int) CAMU_ClearBuffer(PORT_BOTH));
printf("CAMU_SynchronizeVsyncTiming: 0x%08X\n", (unsigned int) CAMU_SynchronizeVsyncTiming(SELECT_OUT1, SELECT_OUT2));
printf("CAMU_StartCapture: 0x%08X\n", (unsigned int) CAMU_StartCapture(PORT_BOTH));
printf("CAMU_PlayShutterSound: 0x%08X\n", (unsigned int) CAMU_PlayShutterSound(SHUTTER_SOUND_TYPE_MOVIE));
gfxFlushBuffers();
gspWaitForVBlank();
gfxSwapBuffers();
printf("\nUse slider to enable/disable 3D\n");
printf("Press Start to exit to Homebrew Launcher\n");
// Main loop
while (aptMainLoop()) {
// Read which buttons are currently pressed or not
hidScanInput();
kDown = hidKeysDown();
// If START button is pressed, break loop and quit
if (kDown & KEY_START) {
break;
}
printf("CAMU_SetReceiving: 0x%08X\n", (unsigned int) CAMU_SetReceiving(&camReceiveEvent, buf, PORT_CAM1, SCREEN_SIZE, (s16) bufSize));
CAMU_SetReceiving(&camReceiveEvent2, buf + SCREEN_SIZE, PORT_CAM2, SCREEN_SIZE, (s16) bufSize);
printf("svcWaitSynchronization: 0x%08X\n", (unsigned int) svcWaitSynchronization(camReceiveEvent, WAIT_TIMEOUT));
svcWaitSynchronization(camReceiveEvent2, WAIT_TIMEOUT);
if(CONFIG_3D_SLIDERSTATE > 0.0f) {
gfxSet3D(true);
writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), buf, 0, 0, WIDTH, HEIGHT);
writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL), buf + SCREEN_SIZE, 0, 0, WIDTH, HEIGHT);
} else {
gfxSet3D(false);
writePictureToFramebufferRGB565(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), buf, 0, 0, WIDTH, HEIGHT);
}
printf("svcCloseHandle: 0x%08X\n", (unsigned int) svcCloseHandle(camReceiveEvent));
svcCloseHandle(camReceiveEvent2);
// Flush and swap framebuffers
gfxFlushBuffers();
gspWaitForVBlank();
gfxSwapBuffers();
}
printf("CAMU_StopCapture: 0x%08X\n", (unsigned int) CAMU_StopCapture(PORT_BOTH));
printf("CAMU_Activate: 0x%08X\n", (unsigned int) CAMU_Activate(SELECT_NONE));
// Exit
free(buf);
cleanup();
// Return to hbmenu
return 0;
}

View File

@ -0,0 +1,3 @@
<targets selectable="false">
<title mediatype="0">0004001000021400</title>
</targets>

View File

@ -0,0 +1,175 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,4 @@
get_system_language
=======
This is an example on how to get the system language on the 3DS.

View File

@ -0,0 +1,46 @@
#include <stdio.h>
#include <string.h>
#include <3ds.h>
int main(int argc, char** argv)
{
// Initialize services
gfxInitDefault();
initCfgu();
u8 language = 0;
Result res;
// Init console for text output
consoleInit(GFX_BOTTOM, NULL);
// Read the language field from the config savegame.
res = CFGU_GetSystemLanguage(&language);
// Print return value and language code
printf(" Result: 0x%x\n", (int)res);
printf("Language code: %d", (int)language);
// Main loop
while (aptMainLoop())
{
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
gspWaitForVBlank();
}
// Exit services
exitCfgu();
gfxExit();
return 0;
}

View File

@ -0,0 +1,7 @@
SUBDIRS:= `ls | egrep -v '^(CVS)$$'`
all:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
clean:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
install:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i install || { exit 1;} fi; done;

View File

@ -0,0 +1,193 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA :=
INCLUDES := include
GRAPHICS := gfx
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(PNGFILES:.png=.bgr.o) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) \
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
IMAGEMAGICK := $(shell which convert)
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
ifeq ($(strip $(IMAGEMAGICK)),)
all:
@echo "Image Magick not found!"
@echo
@echo "Please install Image Magick from http://www.imagemagick.org/ to build this example"
else
all: $(BUILD)
endif
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
.PHONY: all
all : $(OUTPUT).3dsx $(OUTPUT).smdh
endif
$(OUTPUT).3dsx : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.bgr.o: %.bgr
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
%.bgr: %.png
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@convert $< -rotate 90 $@
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,16 @@
24bit Bitmap Example
=======
This example shows on bottom screen an upscaled version of the nds examples Drunken Coders logo that can be found in devkitPro.
If you want to try with your own image follow these steps:
1. Download & install: http://www.imagemagick.org/ (If you get an option to add the application to the path make sure to check it!).
2. convert fileIn.png -channel B -separate fileIn.png -channel G -separate fileIn.png -channel R -separate -channel RGB -combine -rotate 90 fileOut.rgb
3. Rename fileOut.rgb in fileOut.bin
4. Copy fileOut.bin in the data folder of your project
5. Replace any reference of drunkenlogo_bin in main.cpp with fileOut_bin (or however you named it)
6. Re-Build the project
As you can see from the previos steps the image is clockwise rotated by 90 degrees and its B and R channels are swapped. The first operation is done because the 3DS screens are actually portrait screens rotated by 90 degrees (in a counter-clockwise direction), while the second one is done because the 3DS screens' framebuffers have a BGR888 color format, by default.

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View File

@ -0,0 +1,64 @@
/*
Hello World example made by Aurelio Mannara for ctrulib
This code was modified for the last time on: 12/13/2014 01:00 UTC+1
This wouldn't be possible without the amazing work done by:
-Smealum
-fincs
-WinterMute
-yellows8
-plutoo
-mtheall
-Many others who worked on 3DS and I'm surely forgetting about
*/
#include <3ds.h>
#include <stdio.h>
#include <string.h>
//This include a header containing definitions of our image
#include "brew_bgr.h"
int main(int argc, char **argv)
{
gfxInitDefault();
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
consoleInit(GFX_TOP, NULL);
printf("Why so sad Smealum? We can haz 3DS homebrew!");
printf("\x1b[20;15HPress Start to exit.");
//We don't need double buffering in this example. In this way we can draw our image only once on screen.
gfxSetDoubleBuffering(GFX_BOTTOM, false);
//Get the bottom screen's frame buffer
u8* fb = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
//Copy our image in the bottom screen's frame buffer
memcpy(fb, brew_bgr, brew_bgr_size);
// Main loop
while (aptMainLoop())
{
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
}
// Exit services
gfxExit();
return 0;
}

View File

@ -0,0 +1,7 @@
SUBDIRS:= `ls | egrep -v '^(CVS)$$'`
all:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
clean:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
install:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i install || { exit 1;} fi; done;

View File

@ -0,0 +1,177 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pica)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) $(PICAFILES:.pica=.shbin.o) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
# rule for assembling GPU shaders
#---------------------------------------------------------------------------------
%.shbin.o: %.pica
@echo $(notdir $<)
$(eval CURBIN := $(patsubst %.pica,%.shbin,$(notdir $<)))
$(eval CURH := $(patsubst %.pica,%.psh.h,$(notdir $<)))
@picasso -h $(CURH) -o $(CURBIN) $<
@bin2s $(CURBIN) | $(AS) -o $@
@echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h
@echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h
@echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,6 @@
# GPU example
This is a simple GPU example using the `picasso` shader assembler which comes with devkitARM r45 and up.
Users of earlier versions of devkitARM need to install the tool, which can be found in the address below:
https://github.com/fincs/picasso/releases

View File

@ -0,0 +1,172 @@
#include "3dmath.h"
void m4x4_identity(matrix_4x4* out)
{
m4x4_zeros(out);
out->r[0].x = out->r[1].y = out->r[2].z = out->r[3].w = 1.0f;
}
void m4x4_multiply(matrix_4x4* out, const matrix_4x4* a, const matrix_4x4* b)
{
int i, j;
for (i = 0; i < 4; i ++)
for (j = 0; j < 4; j ++)
out->r[j].c[i] = a->r[j].x*b->r[0].c[i] + a->r[j].y*b->r[1].c[i] + a->r[j].z*b->r[2].c[i] + a->r[j].w*b->r[3].c[i];
}
void m4x4_translate(matrix_4x4* mtx, float x, float y, float z)
{
matrix_4x4 tm, om;
m4x4_identity(&tm);
tm.r[0].w = x;
tm.r[1].w = y;
tm.r[2].w = z;
m4x4_multiply(&om, mtx, &tm);
m4x4_copy(mtx, &om);
}
void m4x4_scale(matrix_4x4* mtx, float x, float y, float z)
{
int i;
for (i = 0; i < 4; i ++)
{
mtx->r[i].x *= x;
mtx->r[i].y *= y;
mtx->r[i].z *= z;
}
}
void m4x4_rotate_x(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = 1.0f;
rm.r[1].y = cosAngle;
rm.r[1].z = sinAngle;
rm.r[2].y = -sinAngle;
rm.r[2].z = cosAngle;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_rotate_y(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = cosAngle;
rm.r[0].z = sinAngle;
rm.r[1].y = 1.0f;
rm.r[2].x = -sinAngle;
rm.r[2].z = cosAngle;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_rotate_z(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = cosAngle;
rm.r[0].y = sinAngle;
rm.r[1].x = -sinAngle;
rm.r[1].y = cosAngle;
rm.r[2].z = 1.0f;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_ortho_tilt(matrix_4x4* mtx, float left, float right, float bottom, float top, float near, float far)
{
matrix_4x4 mp;
m4x4_zeros(&mp);
// Build standard orthogonal projection matrix
mp.r[0].x = 2.0f / (right - left);
mp.r[0].w = (left + right) / (left - right);
mp.r[1].y = 2.0f / (top - bottom);
mp.r[1].w = (bottom + top) / (bottom - top);
mp.r[2].z = 2.0f / (near - far);
mp.r[2].w = (far + near) / (far - near);
mp.r[3].w = 1.0f;
// Fix depth range to [-1, 0]
matrix_4x4 mp2, mp3;
m4x4_identity(&mp2);
mp2.r[2].z = 0.5;
mp2.r[2].w = -0.5;
m4x4_multiply(&mp3, &mp2, &mp);
// Fix the 3DS screens' orientation by swapping the X and Y axis
m4x4_identity(&mp2);
mp2.r[0].x = 0.0;
mp2.r[0].y = 1.0;
mp2.r[1].x = -1.0; // flipped
mp2.r[1].y = 0.0;
m4x4_multiply(mtx, &mp2, &mp3);
}
void m4x4_persp_tilt(matrix_4x4* mtx, float fovx, float invaspect, float near, float far)
{
// Notes:
// We are passed "fovy" and the "aspect ratio". However, the 3DS screens are sideways,
// and so are these parameters -- in fact, they are actually the fovx and the inverse
// of the aspect ratio. Therefore the formula for the perspective projection matrix
// had to be modified to be expressed in these terms instead.
// Notes:
// fovx = 2 atan(tan(fovy/2)*w/h)
// fovy = 2 atan(tan(fovx/2)*h/w)
// invaspect = h/w
// a0,0 = h / (w*tan(fovy/2)) =
// = h / (w*tan(2 atan(tan(fovx/2)*h/w) / 2)) =
// = h / (w*tan( atan(tan(fovx/2)*h/w) )) =
// = h / (w * tan(fovx/2)*h/w) =
// = 1 / tan(fovx/2)
// a1,1 = 1 / tan(fovy/2) = (...) = w / (h*tan(fovx/2))
float fovx_tan = tanf(fovx / 2);
matrix_4x4 mp;
m4x4_zeros(&mp);
// Build standard perspective projection matrix
mp.r[0].x = 1.0f / fovx_tan;
mp.r[1].y = 1.0f / (fovx_tan*invaspect);
mp.r[2].z = (near + far) / (near - far);
mp.r[2].w = (2 * near * far) / (near - far);
mp.r[3].z = -1.0f;
// Fix depth range to [-1, 0]
matrix_4x4 mp2;
m4x4_identity(&mp2);
mp2.r[2].z = 0.5;
mp2.r[2].w = -0.5;
m4x4_multiply(mtx, &mp2, &mp);
// Rotate the matrix one quarter of a turn CCW in order to fix the 3DS screens' orientation
m4x4_rotate_z(mtx, M_PI / 2, true);
}

View File

@ -0,0 +1,56 @@
/*
* Bare-bones simplistic 3D math library
* This library is common to all libctru GPU examples
*/
#pragma once
#include <string.h>
#include <stdbool.h>
#include <math.h>
typedef union { struct { float w, z, y, x; }; float c[4]; } vector_4f;
typedef struct { vector_4f r[4]; } matrix_4x4;
static inline float v4f_dp4(const vector_4f* a, const vector_4f* b)
{
return a->x*b->x + a->y*b->y + a->z*b->z + a->w*b->w;
}
static inline float v4f_mod4(const vector_4f* a)
{
return sqrtf(v4f_dp4(a,a));
}
static inline void v4f_norm4(vector_4f* vec)
{
float m = v4f_mod4(vec);
if (m == 0.0) return;
vec->x /= m;
vec->y /= m;
vec->z /= m;
vec->w /= m;
}
static inline void m4x4_zeros(matrix_4x4* out)
{
memset(out, 0, sizeof(*out));
}
static inline void m4x4_copy(matrix_4x4* out, const matrix_4x4* in)
{
memcpy(out, in, sizeof(*out));
}
void m4x4_identity(matrix_4x4* out);
void m4x4_multiply(matrix_4x4* out, const matrix_4x4* a, const matrix_4x4* b);
void m4x4_translate(matrix_4x4* mtx, float x, float y, float z);
void m4x4_scale(matrix_4x4* mtx, float x, float y, float z);
void m4x4_rotate_x(matrix_4x4* mtx, float angle, bool bRightSide);
void m4x4_rotate_y(matrix_4x4* mtx, float angle, bool bRightSide);
void m4x4_rotate_z(matrix_4x4* mtx, float angle, bool bRightSide);
// Special versions of the projection matrices that take the 3DS' screen orientation into account
void m4x4_ortho_tilt(matrix_4x4* mtx, float left, float right, float bottom, float top, float near, float far);
void m4x4_persp_tilt(matrix_4x4* mtx, float fovy, float aspect, float near, float far);

View File

@ -0,0 +1,93 @@
#include "gpu.h"
#define DISPLAY_TRANSFER_FLAGS \
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
static u32 *colorBuf, *depthBuf;
static u32 *cmdBuf;
void gpuInit(void)
{
colorBuf = vramAlloc(400*240*4);
depthBuf = vramAlloc(400*240*4);
cmdBuf = linearAlloc(0x40000*4);
GPU_Init(NULL);
GPU_Reset(NULL, cmdBuf, 0x40000);
}
void gpuExit(void)
{
linearFree(cmdBuf);
vramFree(depthBuf);
vramFree(colorBuf);
}
void gpuClearBuffers(u32 clearColor)
{
GX_SetMemoryFill(NULL,
colorBuf, clearColor, &colorBuf[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH,
depthBuf, 0, &depthBuf[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH);
gspWaitForPSC0(); // Wait for the fill to complete
}
void gpuFrameBegin(void)
{
// Configure the viewport and the depth linear conversion function
GPU_SetViewport(
(u32*)osConvertVirtToPhys((u32)depthBuf),
(u32*)osConvertVirtToPhys((u32)colorBuf),
0, 0, 240, 400); // The top screen is physically 240x400 pixels
GPU_DepthMap(-1.0f, 0.0f); // calculate the depth value from the Z coordinate in the following way: -1.0*z + 0.0
// Configure some boilerplate
GPU_SetFaceCulling(GPU_CULL_BACK_CCW);
GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP);
GPU_SetBlendingColor(0,0,0,0);
GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL);
// This is unknown
GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0);
GPUCMD_AddWrite(GPUREG_0118, 0);
// Configure alpha blending and test
GPU_SetAlphaBlending(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00);
int i;
for (i = 0; i < 6; i ++)
GPU_SetDummyTexEnv(i);
}
void gpuFrameEnd(void)
{
// Finish rendering
GPU_FinishDrawing();
GPUCMD_Finalize();
GPUCMD_FlushAndRun(NULL);
gspWaitForP3D(); // Wait for the rendering to complete
// Transfer the GPU output to the framebuffer
GX_SetDisplayTransfer(NULL, colorBuf, GX_BUFFER_DIM(240, 400),
(u32*)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), GX_BUFFER_DIM(240, 400),
DISPLAY_TRANSFER_FLAGS);
gspWaitForPPF(); // Wait for the transfer to complete
// Reset the command buffer
GPUCMD_SetBufferOffset(0);
};
void GPU_SetDummyTexEnv(int id)
{
GPU_SetTexEnv(id,
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
GPU_TEVOPERANDS(0, 0, 0),
GPU_TEVOPERANDS(0, 0, 0),
GPU_REPLACE,
GPU_REPLACE,
0xFFFFFFFF);
}

View File

@ -0,0 +1,26 @@
/*
* Bare-bones simplistic GPU wrapper
* This library is common to all libctru GPU examples
*/
#pragma once
#include <string.h>
#include <3ds.h>
#include "3dmath.h"
void gpuInit(void);
void gpuExit(void);
void gpuClearBuffers(u32 clearColor);
void gpuFrameBegin(void);
void gpuFrameEnd(void);
// Configures the specified fixed-function fragment shading substage to be a no-operation
void GPU_SetDummyTexEnv(int id);
// Uploads an uniform matrix
static inline void GPU_SetFloatUniformMatrix(GPU_SHADER_TYPE type, int location, matrix_4x4* matrix)
{
GPU_SetFloatUniform(type, location, (u32*)matrix, 4);
}

View File

@ -0,0 +1,91 @@
; Example PICA200 geometry shader
; Uniforms
.fvec projection[4]
; Constants
.constf myconst(0.0, 1.0, -1.0, 0.5)
.alias zeros myconst.xxxx ; Vector full of zeros
.alias ones myconst.yyyy ; Vector full of ones
.alias half myconst.wwww
; Outputs - this time the type *is* used
.out outpos position
.out outclr color
; Inputs: we will receive the following inputs:
; v0-v1: position/color of the first vertex
; v2-v3: position/color of the second vertex
; v4-v5: position/color of the third vertex
.proc main
; Calculate the midpoints of the vertices
mov r4, v0
add r4, v2, r4
mul r4, half, r4
mov r5, v2
add r5, v4, r5
mul r5, half, r5
mov r6, v4
add r6, v0, r6
mul r6, half, r6
; Emit the first triangle
mov r0, v0
mov r1, r4
mov r2, r6
call emit_triangle
; Emit the second triangle
mov r0, r4
mov r1, v2
mov r2, r5
call emit_triangle
; Emit the third triangle
mov r0, r6
mov r1, r5
mov r2, v4
call emit_triangle
; We're finished
end
.end
.proc emit_triangle
; Emit the first vertex
setemit 0
mov r8, r0
mov r9, v1
call process_vertex
emit
; Emit the second vertex
setemit 1
mov r8, r1
mov r9, v3
call process_vertex
emit
; Emit the third vertex and finish the primitive
setemit 2, prim
mov r8, r2
mov r9, v5
call process_vertex
emit
.end
; Subroutine
; Inputs:
; r8: vertex position
; r9: vertex color
.proc process_vertex
; outpos = projectionMatrix * r8
dp4 outpos.x, projection[0], r8
dp4 outpos.y, projection[1], r8
dp4 outpos.z, projection[2], r8
dp4 outpos.w, projection[3], r8
; outclr = r9
mov outclr, r9
.end

View File

@ -0,0 +1,139 @@
/*
* ~~ Simple libctru GPU geometry shader example ~~
* This example demonstrates the basics of using the PICA200 in a 3DS homebrew
* application in order to render a basic scene using a geoshader.
* The example geoshader receives the vertices of a triangle and emits three
* smaller triangles, thus forming a 'triforce' shape.
*/
#include "gpu.h"
#include "vshader_shbin.h"
#include "gshader_shbin.h"
#define CLEAR_COLOR 0x68B0D8FF
typedef struct { float position[3]; float color[4]; } vertex;
static const vertex vertex_list[] =
{
{ {200.0f, 200.0f, 0.5f}, {1.0f, 0.0f, 0.0f, 1.0f} },
{ {100.0f, 40.0f, 0.5f}, {0.0f, 1.0f, 0.0f, 1.0f} },
{ {300.0f, 40.0f, 0.5f}, {0.0f, 0.0f, 1.0f, 1.0f} },
};
#define vertex_list_count (sizeof(vertex_list)/sizeof(vertex_list[0]))
static DVLB_s *vshader_dvlb, *gshader_dvlb;
static shaderProgram_s program;
static int uLoc_projection;
static matrix_4x4 projection;
static void* vbo_data;
static void sceneInit(void)
{
// Load the shaders and create a shader program
// The geoshader stride is set to 6 so that it processes a triangle at a time
vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_size);
gshader_dvlb = DVLB_ParseFile((u32*)gshader_shbin, gshader_shbin_size);
shaderProgramInit(&program);
shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]);
shaderProgramSetGsh(&program, &gshader_dvlb->DVLE[0], 6);
// Get the location of the projection matrix uniform
uLoc_projection = shaderInstanceGetUniformLocation(program.geometryShader, "projection");
// Compute the projection matrix
m4x4_ortho_tilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0);
// Create the VBO (vertex buffer object)
vbo_data = linearAlloc(sizeof(vertex_list));
memcpy(vbo_data, vertex_list, sizeof(vertex_list));
}
static void sceneRender(void)
{
// Bind the shader program
shaderProgramUse(&program);
// Configure the first fragment shading substage to just pass through the vertex color
// See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight
GPU_SetTexEnv(0,
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // RGB channels
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // Alpha
GPU_TEVOPERANDS(0, 0, 0), // RGB
GPU_TEVOPERANDS(0, 0, 0), // Alpha
GPU_REPLACE, GPU_REPLACE, // RGB, Alpha
0xFFFFFFFF);
// Configure the "attribute buffers" (that is, the vertex input buffers)
GPU_SetAttributeBuffers(
2, // Number of inputs per vertex
(u32*)osConvertVirtToPhys((u32)vbo_data), // Location of the VBO
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) |
GPU_ATTRIBFMT(1, 4, GPU_FLOAT), // Format of the inputs (in this case the only input is a 3-element float vector)
0xFFC, // Unused attribute mask, in our case bit 0 is cleared since it is used
0x10, // Attribute permutations (here it is the identity)
1, // Number of buffers
(u32[]) { 0x0 }, // Buffer offsets (placeholders)
(u64[]) { 0x10 }, // Attribute permutations for each buffer (identity again)
(u8[]) { 2 }); // Number of attributes for each buffer
// Upload the projection matrix
GPU_SetFloatUniformMatrix(GPU_GEOMETRY_SHADER, uLoc_projection, &projection);
// Draw the VBO - GPU_UNKPRIM allows the geoshader to control primitive emission
GPU_DrawArray(GPU_UNKPRIM, 0, vertex_list_count);
}
static void sceneExit(void)
{
// Free the VBO
linearFree(vbo_data);
// Free the shader program
shaderProgramFree(&program);
DVLB_Free(vshader_dvlb);
DVLB_Free(gshader_dvlb);
}
int main()
{
// Initialize graphics
gfxInitDefault();
gpuInit();
// Initialize the scene
sceneInit();
gpuClearBuffers(CLEAR_COLOR);
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank(); // Synchronize with the start of VBlank
gfxSwapBuffersGpu(); // Swap the framebuffers so that the frame that we rendered last frame is now visible
hidScanInput(); // Read the user input
// Respond to user input
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
// Render the scene
gpuFrameBegin();
sceneRender();
gpuFrameEnd();
gpuClearBuffers(CLEAR_COLOR);
// Flush the framebuffers out of the data cache (not necessary with pure GPU rendering)
//gfxFlushBuffers();
}
// Deinitialize the scene
sceneExit();
// Deinitialize graphics
gpuExit();
gfxExit();
return 0;
}

View File

@ -0,0 +1,24 @@
; Example PICA200 vertex shader
; Constants
.constf myconst(0.0, 1.0, -1.0, -0.5)
.alias zeros myconst.xxxx ; Vector full of zeros
.alias ones myconst.yyyy ; Vector full of ones
; Outputs - since we are also using a geoshader the output type isn't really used
.out outpos position
.out outclr color
; Inputs (defined as aliases for convenience)
.alias inpos v0
.alias inclr v1
.proc main
; Pass through both inputs to the geoshader
mov outpos.xyz, inpos
mov outpos.w, ones
mov outclr, inclr
; We're finished
end
.end

View File

@ -0,0 +1,177 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pica)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) $(PICAFILES:.pica=.shbin.o) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
# rule for assembling GPU shaders
#---------------------------------------------------------------------------------
%.shbin.o: %.pica
@echo $(notdir $<)
$(eval CURBIN := $(patsubst %.pica,%.shbin,$(notdir $<)))
$(eval CURH := $(patsubst %.pica,%.psh.h,$(notdir $<)))
@picasso -h $(CURH) -o $(CURBIN) $<
@bin2s $(CURBIN) | $(AS) -o $@
@echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h
@echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h
@echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,6 @@
# GPU example
This is a simple GPU example using the `picasso` shader assembler which comes with devkitARM r45 and up.
Users of earlier versions of devkitARM need to install the tool, which can be found in the address below:
https://github.com/fincs/picasso/releases

View File

@ -0,0 +1,172 @@
#include "3dmath.h"
void m4x4_identity(matrix_4x4* out)
{
m4x4_zeros(out);
out->r[0].x = out->r[1].y = out->r[2].z = out->r[3].w = 1.0f;
}
void m4x4_multiply(matrix_4x4* out, const matrix_4x4* a, const matrix_4x4* b)
{
int i, j;
for (i = 0; i < 4; i ++)
for (j = 0; j < 4; j ++)
out->r[j].c[i] = a->r[j].x*b->r[0].c[i] + a->r[j].y*b->r[1].c[i] + a->r[j].z*b->r[2].c[i] + a->r[j].w*b->r[3].c[i];
}
void m4x4_translate(matrix_4x4* mtx, float x, float y, float z)
{
matrix_4x4 tm, om;
m4x4_identity(&tm);
tm.r[0].w = x;
tm.r[1].w = y;
tm.r[2].w = z;
m4x4_multiply(&om, mtx, &tm);
m4x4_copy(mtx, &om);
}
void m4x4_scale(matrix_4x4* mtx, float x, float y, float z)
{
int i;
for (i = 0; i < 4; i ++)
{
mtx->r[i].x *= x;
mtx->r[i].y *= y;
mtx->r[i].z *= z;
}
}
void m4x4_rotate_x(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = 1.0f;
rm.r[1].y = cosAngle;
rm.r[1].z = sinAngle;
rm.r[2].y = -sinAngle;
rm.r[2].z = cosAngle;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_rotate_y(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = cosAngle;
rm.r[0].z = sinAngle;
rm.r[1].y = 1.0f;
rm.r[2].x = -sinAngle;
rm.r[2].z = cosAngle;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_rotate_z(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = cosAngle;
rm.r[0].y = sinAngle;
rm.r[1].x = -sinAngle;
rm.r[1].y = cosAngle;
rm.r[2].z = 1.0f;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_ortho_tilt(matrix_4x4* mtx, float left, float right, float bottom, float top, float near, float far)
{
matrix_4x4 mp;
m4x4_zeros(&mp);
// Build standard orthogonal projection matrix
mp.r[0].x = 2.0f / (right - left);
mp.r[0].w = (left + right) / (left - right);
mp.r[1].y = 2.0f / (top - bottom);
mp.r[1].w = (bottom + top) / (bottom - top);
mp.r[2].z = 2.0f / (near - far);
mp.r[2].w = (far + near) / (far - near);
mp.r[3].w = 1.0f;
// Fix depth range to [-1, 0]
matrix_4x4 mp2, mp3;
m4x4_identity(&mp2);
mp2.r[2].z = 0.5;
mp2.r[2].w = -0.5;
m4x4_multiply(&mp3, &mp2, &mp);
// Fix the 3DS screens' orientation by swapping the X and Y axis
m4x4_identity(&mp2);
mp2.r[0].x = 0.0;
mp2.r[0].y = 1.0;
mp2.r[1].x = -1.0; // flipped
mp2.r[1].y = 0.0;
m4x4_multiply(mtx, &mp2, &mp3);
}
void m4x4_persp_tilt(matrix_4x4* mtx, float fovx, float invaspect, float near, float far)
{
// Notes:
// We are passed "fovy" and the "aspect ratio". However, the 3DS screens are sideways,
// and so are these parameters -- in fact, they are actually the fovx and the inverse
// of the aspect ratio. Therefore the formula for the perspective projection matrix
// had to be modified to be expressed in these terms instead.
// Notes:
// fovx = 2 atan(tan(fovy/2)*w/h)
// fovy = 2 atan(tan(fovx/2)*h/w)
// invaspect = h/w
// a0,0 = h / (w*tan(fovy/2)) =
// = h / (w*tan(2 atan(tan(fovx/2)*h/w) / 2)) =
// = h / (w*tan( atan(tan(fovx/2)*h/w) )) =
// = h / (w * tan(fovx/2)*h/w) =
// = 1 / tan(fovx/2)
// a1,1 = 1 / tan(fovy/2) = (...) = w / (h*tan(fovx/2))
float fovx_tan = tanf(fovx / 2);
matrix_4x4 mp;
m4x4_zeros(&mp);
// Build standard perspective projection matrix
mp.r[0].x = 1.0f / fovx_tan;
mp.r[1].y = 1.0f / (fovx_tan*invaspect);
mp.r[2].z = (near + far) / (near - far);
mp.r[2].w = (2 * near * far) / (near - far);
mp.r[3].z = -1.0f;
// Fix depth range to [-1, 0]
matrix_4x4 mp2;
m4x4_identity(&mp2);
mp2.r[2].z = 0.5;
mp2.r[2].w = -0.5;
m4x4_multiply(mtx, &mp2, &mp);
// Rotate the matrix one quarter of a turn CCW in order to fix the 3DS screens' orientation
m4x4_rotate_z(mtx, M_PI / 2, true);
}

View File

@ -0,0 +1,56 @@
/*
* Bare-bones simplistic 3D math library
* This library is common to all libctru GPU examples
*/
#pragma once
#include <string.h>
#include <stdbool.h>
#include <math.h>
typedef union { struct { float w, z, y, x; }; float c[4]; } vector_4f;
typedef struct { vector_4f r[4]; } matrix_4x4;
static inline float v4f_dp4(const vector_4f* a, const vector_4f* b)
{
return a->x*b->x + a->y*b->y + a->z*b->z + a->w*b->w;
}
static inline float v4f_mod4(const vector_4f* a)
{
return sqrtf(v4f_dp4(a,a));
}
static inline void v4f_norm4(vector_4f* vec)
{
float m = v4f_mod4(vec);
if (m == 0.0) return;
vec->x /= m;
vec->y /= m;
vec->z /= m;
vec->w /= m;
}
static inline void m4x4_zeros(matrix_4x4* out)
{
memset(out, 0, sizeof(*out));
}
static inline void m4x4_copy(matrix_4x4* out, const matrix_4x4* in)
{
memcpy(out, in, sizeof(*out));
}
void m4x4_identity(matrix_4x4* out);
void m4x4_multiply(matrix_4x4* out, const matrix_4x4* a, const matrix_4x4* b);
void m4x4_translate(matrix_4x4* mtx, float x, float y, float z);
void m4x4_scale(matrix_4x4* mtx, float x, float y, float z);
void m4x4_rotate_x(matrix_4x4* mtx, float angle, bool bRightSide);
void m4x4_rotate_y(matrix_4x4* mtx, float angle, bool bRightSide);
void m4x4_rotate_z(matrix_4x4* mtx, float angle, bool bRightSide);
// Special versions of the projection matrices that take the 3DS' screen orientation into account
void m4x4_ortho_tilt(matrix_4x4* mtx, float left, float right, float bottom, float top, float near, float far);
void m4x4_persp_tilt(matrix_4x4* mtx, float fovy, float aspect, float near, float far);

View File

@ -0,0 +1,93 @@
#include "gpu.h"
#define DISPLAY_TRANSFER_FLAGS \
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
static u32 *colorBuf, *depthBuf;
static u32 *cmdBuf;
void gpuInit(void)
{
colorBuf = vramAlloc(400*240*4);
depthBuf = vramAlloc(400*240*4);
cmdBuf = linearAlloc(0x40000*4);
GPU_Init(NULL);
GPU_Reset(NULL, cmdBuf, 0x40000);
}
void gpuExit(void)
{
linearFree(cmdBuf);
vramFree(depthBuf);
vramFree(colorBuf);
}
void gpuClearBuffers(u32 clearColor)
{
GX_SetMemoryFill(NULL,
colorBuf, clearColor, &colorBuf[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH,
depthBuf, 0, &depthBuf[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH);
gspWaitForPSC0(); // Wait for the fill to complete
}
void gpuFrameBegin(void)
{
// Configure the viewport and the depth linear conversion function
GPU_SetViewport(
(u32*)osConvertVirtToPhys((u32)depthBuf),
(u32*)osConvertVirtToPhys((u32)colorBuf),
0, 0, 240, 400); // The top screen is physically 240x400 pixels
GPU_DepthMap(-1.0f, 0.0f); // calculate the depth value from the Z coordinate in the following way: -1.0*z + 0.0
// Configure some boilerplate
GPU_SetFaceCulling(GPU_CULL_BACK_CCW);
GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP);
GPU_SetBlendingColor(0,0,0,0);
GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL);
// This is unknown
GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0);
GPUCMD_AddWrite(GPUREG_0118, 0);
// Configure alpha blending and test
GPU_SetAlphaBlending(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00);
int i;
for (i = 0; i < 6; i ++)
GPU_SetDummyTexEnv(i);
}
void gpuFrameEnd(void)
{
// Finish rendering
GPU_FinishDrawing();
GPUCMD_Finalize();
GPUCMD_FlushAndRun(NULL);
gspWaitForP3D(); // Wait for the rendering to complete
// Transfer the GPU output to the framebuffer
GX_SetDisplayTransfer(NULL, colorBuf, GX_BUFFER_DIM(240, 400),
(u32*)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), GX_BUFFER_DIM(240, 400),
DISPLAY_TRANSFER_FLAGS);
gspWaitForPPF(); // Wait for the transfer to complete
// Reset the command buffer
GPUCMD_SetBufferOffset(0);
};
void GPU_SetDummyTexEnv(int id)
{
GPU_SetTexEnv(id,
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
GPU_TEVOPERANDS(0, 0, 0),
GPU_TEVOPERANDS(0, 0, 0),
GPU_REPLACE,
GPU_REPLACE,
0xFFFFFFFF);
}

View File

@ -0,0 +1,26 @@
/*
* Bare-bones simplistic GPU wrapper
* This library is common to all libctru GPU examples
*/
#pragma once
#include <string.h>
#include <3ds.h>
#include "3dmath.h"
void gpuInit(void);
void gpuExit(void);
void gpuClearBuffers(u32 clearColor);
void gpuFrameBegin(void);
void gpuFrameEnd(void);
// Configures the specified fixed-function fragment shading substage to be a no-operation
void GPU_SetDummyTexEnv(int id);
// Uploads an uniform matrix
static inline void GPU_SetFloatUniformMatrix(GPU_SHADER_TYPE type, int location, matrix_4x4* matrix)
{
GPU_SetFloatUniform(type, location, (u32*)matrix, 4);
}

View File

@ -0,0 +1,131 @@
/*
* ~~ Simple libctru GPU triangle example ~~
* This example demonstrates the basics of using the PICA200 in a 3DS homebrew
* application in order to render a basic scene consisting of a white solid triangle.
*/
#include "gpu.h"
#include "vshader_shbin.h"
#define CLEAR_COLOR 0x68B0D8FF
typedef struct { float x, y, z; } vertex;
static const vertex vertex_list[] =
{
{ 200.0f, 200.0f, 0.5f },
{ 100.0f, 40.0f, 0.5f },
{ 300.0f, 40.0f, 0.5f },
};
#define vertex_list_count (sizeof(vertex_list)/sizeof(vertex_list[0]))
static DVLB_s* vshader_dvlb;
static shaderProgram_s program;
static int uLoc_projection;
static matrix_4x4 projection;
static void* vbo_data;
static void sceneInit(void)
{
// Load the vertex shader and create a shader program
vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_size);
shaderProgramInit(&program);
shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]);
// Get the location of the projection matrix uniform
uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection");
// Compute the projection matrix
m4x4_ortho_tilt(&projection, 0.0, 400.0, 0.0, 240.0, 0.0, 1.0);
// Create the VBO (vertex buffer object)
vbo_data = linearAlloc(sizeof(vertex_list));
memcpy(vbo_data, vertex_list, sizeof(vertex_list));
}
static void sceneRender(void)
{
// Bind the shader program
shaderProgramUse(&program);
// Configure the first fragment shading substage to just pass through the vertex color
// See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight
GPU_SetTexEnv(0,
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // RGB channels
GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // Alpha
GPU_TEVOPERANDS(0, 0, 0), // RGB
GPU_TEVOPERANDS(0, 0, 0), // Alpha
GPU_REPLACE, GPU_REPLACE, // RGB, Alpha
0xFFFFFFFF);
// Configure the "attribute buffers" (that is, the vertex input buffers)
GPU_SetAttributeBuffers(
1, // Number of inputs per vertex
(u32*)osConvertVirtToPhys((u32)vbo_data), // Location of the VBO
GPU_ATTRIBFMT(0, 3, GPU_FLOAT), // Format of the inputs (in this case the only input is a 3-element float vector)
0xFFE, // Unused attribute mask, in our case bit 0 is cleared since it is used
0x0, // Attribute permutations (here it is the identity)
1, // Number of buffers
(u32[]) { 0x0 }, // Buffer offsets (placeholders)
(u64[]) { 0x0 }, // Attribute permutations for each buffer (identity again)
(u8[]) { 1 }); // Number of attributes for each buffer
// Upload the projection matrix
GPU_SetFloatUniformMatrix(GPU_VERTEX_SHADER, uLoc_projection, &projection);
// Draw the VBO
GPU_DrawArray(GPU_TRIANGLES, 0, vertex_list_count);
}
static void sceneExit(void)
{
// Free the VBO
linearFree(vbo_data);
// Free the shader program
shaderProgramFree(&program);
DVLB_Free(vshader_dvlb);
}
int main()
{
// Initialize graphics
gfxInitDefault();
gpuInit();
// Initialize the scene
sceneInit();
gpuClearBuffers(CLEAR_COLOR);
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank(); // Synchronize with the start of VBlank
gfxSwapBuffersGpu(); // Swap the framebuffers so that the frame that we rendered last frame is now visible
hidScanInput(); // Read the user input
// Respond to user input
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
// Render the scene
gpuFrameBegin();
sceneRender();
gpuFrameEnd();
gpuClearBuffers(CLEAR_COLOR);
// Flush the framebuffers out of the data cache (not necessary with pure GPU rendering)
//gfxFlushBuffers();
}
// Deinitialize the scene
sceneExit();
// Deinitialize graphics
gpuExit();
gfxExit();
return 0;
}

View File

@ -0,0 +1,34 @@
; Example PICA200 vertex shader
; Uniforms
.fvec projection[4]
; Constants
.constf myconst(0.0, 1.0, -1.0, -0.5)
.alias zeros myconst.xxxx ; Vector full of zeros
.alias ones myconst.yyyy ; Vector full of ones
; Outputs
.out outpos position
.out outclr color
; Inputs (defined as aliases for convenience)
.alias inpos v0
.proc main
; Force the w component of inpos to be 1.0
mov r0.xyz, inpos
mov r0.w, ones
; outpos = projectionMatrix * inpos
dp4 outpos.x, projection[0], r0
dp4 outpos.y, projection[1], r0
dp4 outpos.z, projection[2], r0
dp4 outpos.w, projection[3], r0
; outclr = solid white color
mov outclr, ones
; We're finished
end
.end

View File

@ -0,0 +1,177 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.pica)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) $(PICAFILES:.pica=.shbin.o) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
#---------------------------------------------------------------------------------
# rule for assembling GPU shaders
#---------------------------------------------------------------------------------
%.shbin.o: %.pica
@echo $(notdir $<)
$(eval CURBIN := $(patsubst %.pica,%.shbin,$(notdir $<)))
$(eval CURH := $(patsubst %.pica,%.psh.h,$(notdir $<)))
@picasso -h $(CURH) -o $(CURBIN) $<
@bin2s $(CURBIN) | $(AS) -o $@
@echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h
@echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h
@echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,6 @@
# GPU example
This is a simple GPU example using the `picasso` shader assembler which comes with devkitARM r45 and up.
Users of earlier versions of devkitARM need to install the tool, which can be found in the address below:
https://github.com/fincs/picasso/releases

Binary file not shown.

View File

@ -0,0 +1,172 @@
#include "3dmath.h"
void m4x4_identity(matrix_4x4* out)
{
m4x4_zeros(out);
out->r[0].x = out->r[1].y = out->r[2].z = out->r[3].w = 1.0f;
}
void m4x4_multiply(matrix_4x4* out, const matrix_4x4* a, const matrix_4x4* b)
{
int i, j;
for (i = 0; i < 4; i ++)
for (j = 0; j < 4; j ++)
out->r[j].c[i] = a->r[j].x*b->r[0].c[i] + a->r[j].y*b->r[1].c[i] + a->r[j].z*b->r[2].c[i] + a->r[j].w*b->r[3].c[i];
}
void m4x4_translate(matrix_4x4* mtx, float x, float y, float z)
{
matrix_4x4 tm, om;
m4x4_identity(&tm);
tm.r[0].w = x;
tm.r[1].w = y;
tm.r[2].w = z;
m4x4_multiply(&om, mtx, &tm);
m4x4_copy(mtx, &om);
}
void m4x4_scale(matrix_4x4* mtx, float x, float y, float z)
{
int i;
for (i = 0; i < 4; i ++)
{
mtx->r[i].x *= x;
mtx->r[i].y *= y;
mtx->r[i].z *= z;
}
}
void m4x4_rotate_x(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = 1.0f;
rm.r[1].y = cosAngle;
rm.r[1].z = sinAngle;
rm.r[2].y = -sinAngle;
rm.r[2].z = cosAngle;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_rotate_y(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = cosAngle;
rm.r[0].z = sinAngle;
rm.r[1].y = 1.0f;
rm.r[2].x = -sinAngle;
rm.r[2].z = cosAngle;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_rotate_z(matrix_4x4* mtx, float angle, bool bRightSide)
{
matrix_4x4 rm, om;
float cosAngle = cosf(angle);
float sinAngle = sinf(angle);
m4x4_zeros(&rm);
rm.r[0].x = cosAngle;
rm.r[0].y = sinAngle;
rm.r[1].x = -sinAngle;
rm.r[1].y = cosAngle;
rm.r[2].z = 1.0f;
rm.r[3].w = 1.0f;
if (bRightSide) m4x4_multiply(&om, mtx, &rm);
else m4x4_multiply(&om, &rm, mtx);
m4x4_copy(mtx, &om);
}
void m4x4_ortho_tilt(matrix_4x4* mtx, float left, float right, float bottom, float top, float near, float far)
{
matrix_4x4 mp;
m4x4_zeros(&mp);
// Build standard orthogonal projection matrix
mp.r[0].x = 2.0f / (right - left);
mp.r[0].w = (left + right) / (left - right);
mp.r[1].y = 2.0f / (top - bottom);
mp.r[1].w = (bottom + top) / (bottom - top);
mp.r[2].z = 2.0f / (near - far);
mp.r[2].w = (far + near) / (far - near);
mp.r[3].w = 1.0f;
// Fix depth range to [-1, 0]
matrix_4x4 mp2, mp3;
m4x4_identity(&mp2);
mp2.r[2].z = 0.5;
mp2.r[2].w = -0.5;
m4x4_multiply(&mp3, &mp2, &mp);
// Fix the 3DS screens' orientation by swapping the X and Y axis
m4x4_identity(&mp2);
mp2.r[0].x = 0.0;
mp2.r[0].y = 1.0;
mp2.r[1].x = -1.0; // flipped
mp2.r[1].y = 0.0;
m4x4_multiply(mtx, &mp2, &mp3);
}
void m4x4_persp_tilt(matrix_4x4* mtx, float fovx, float invaspect, float near, float far)
{
// Notes:
// We are passed "fovy" and the "aspect ratio". However, the 3DS screens are sideways,
// and so are these parameters -- in fact, they are actually the fovx and the inverse
// of the aspect ratio. Therefore the formula for the perspective projection matrix
// had to be modified to be expressed in these terms instead.
// Notes:
// fovx = 2 atan(tan(fovy/2)*w/h)
// fovy = 2 atan(tan(fovx/2)*h/w)
// invaspect = h/w
// a0,0 = h / (w*tan(fovy/2)) =
// = h / (w*tan(2 atan(tan(fovx/2)*h/w) / 2)) =
// = h / (w*tan( atan(tan(fovx/2)*h/w) )) =
// = h / (w * tan(fovx/2)*h/w) =
// = 1 / tan(fovx/2)
// a1,1 = 1 / tan(fovy/2) = (...) = w / (h*tan(fovx/2))
float fovx_tan = tanf(fovx / 2);
matrix_4x4 mp;
m4x4_zeros(&mp);
// Build standard perspective projection matrix
mp.r[0].x = 1.0f / fovx_tan;
mp.r[1].y = 1.0f / (fovx_tan*invaspect);
mp.r[2].z = (near + far) / (near - far);
mp.r[2].w = (2 * near * far) / (near - far);
mp.r[3].z = -1.0f;
// Fix depth range to [-1, 0]
matrix_4x4 mp2;
m4x4_identity(&mp2);
mp2.r[2].z = 0.5;
mp2.r[2].w = -0.5;
m4x4_multiply(mtx, &mp2, &mp);
// Rotate the matrix one quarter of a turn CCW in order to fix the 3DS screens' orientation
m4x4_rotate_z(mtx, M_PI / 2, true);
}

View File

@ -0,0 +1,56 @@
/*
* Bare-bones simplistic 3D math library
* This library is common to all libctru GPU examples
*/
#pragma once
#include <string.h>
#include <stdbool.h>
#include <math.h>
typedef union { struct { float w, z, y, x; }; float c[4]; } vector_4f;
typedef struct { vector_4f r[4]; } matrix_4x4;
static inline float v4f_dp4(const vector_4f* a, const vector_4f* b)
{
return a->x*b->x + a->y*b->y + a->z*b->z + a->w*b->w;
}
static inline float v4f_mod4(const vector_4f* a)
{
return sqrtf(v4f_dp4(a,a));
}
static inline void v4f_norm4(vector_4f* vec)
{
float m = v4f_mod4(vec);
if (m == 0.0) return;
vec->x /= m;
vec->y /= m;
vec->z /= m;
vec->w /= m;
}
static inline void m4x4_zeros(matrix_4x4* out)
{
memset(out, 0, sizeof(*out));
}
static inline void m4x4_copy(matrix_4x4* out, const matrix_4x4* in)
{
memcpy(out, in, sizeof(*out));
}
void m4x4_identity(matrix_4x4* out);
void m4x4_multiply(matrix_4x4* out, const matrix_4x4* a, const matrix_4x4* b);
void m4x4_translate(matrix_4x4* mtx, float x, float y, float z);
void m4x4_scale(matrix_4x4* mtx, float x, float y, float z);
void m4x4_rotate_x(matrix_4x4* mtx, float angle, bool bRightSide);
void m4x4_rotate_y(matrix_4x4* mtx, float angle, bool bRightSide);
void m4x4_rotate_z(matrix_4x4* mtx, float angle, bool bRightSide);
// Special versions of the projection matrices that take the 3DS' screen orientation into account
void m4x4_ortho_tilt(matrix_4x4* mtx, float left, float right, float bottom, float top, float near, float far);
void m4x4_persp_tilt(matrix_4x4* mtx, float fovy, float aspect, float near, float far);

View File

@ -0,0 +1,93 @@
#include "gpu.h"
#define DISPLAY_TRANSFER_FLAGS \
(GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \
GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
static u32 *colorBuf, *depthBuf;
static u32 *cmdBuf;
void gpuInit(void)
{
colorBuf = vramAlloc(400*240*4);
depthBuf = vramAlloc(400*240*4);
cmdBuf = linearAlloc(0x40000*4);
GPU_Init(NULL);
GPU_Reset(NULL, cmdBuf, 0x40000);
}
void gpuExit(void)
{
linearFree(cmdBuf);
vramFree(depthBuf);
vramFree(colorBuf);
}
void gpuClearBuffers(u32 clearColor)
{
GX_SetMemoryFill(NULL,
colorBuf, clearColor, &colorBuf[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH,
depthBuf, 0, &depthBuf[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH);
gspWaitForPSC0(); // Wait for the fill to complete
}
void gpuFrameBegin(void)
{
// Configure the viewport and the depth linear conversion function
GPU_SetViewport(
(u32*)osConvertVirtToPhys((u32)depthBuf),
(u32*)osConvertVirtToPhys((u32)colorBuf),
0, 0, 240, 400); // The top screen is physically 240x400 pixels
GPU_DepthMap(-1.0f, 0.0f); // calculate the depth value from the Z coordinate in the following way: -1.0*z + 0.0
// Configure some boilerplate
GPU_SetFaceCulling(GPU_CULL_BACK_CCW);
GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00);
GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP);
GPU_SetBlendingColor(0,0,0,0);
GPU_SetDepthTestAndWriteMask(true, GPU_GREATER, GPU_WRITE_ALL);
// This is unknown
GPUCMD_AddMaskedWrite(GPUREG_0062, 0x1, 0);
GPUCMD_AddWrite(GPUREG_0118, 0);
// Configure alpha blending and test
GPU_SetAlphaBlending(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA);
GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00);
int i;
for (i = 0; i < 6; i ++)
GPU_SetDummyTexEnv(i);
}
void gpuFrameEnd(void)
{
// Finish rendering
GPU_FinishDrawing();
GPUCMD_Finalize();
GPUCMD_FlushAndRun(NULL);
gspWaitForP3D(); // Wait for the rendering to complete
// Transfer the GPU output to the framebuffer
GX_SetDisplayTransfer(NULL, colorBuf, GX_BUFFER_DIM(240, 400),
(u32*)gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), GX_BUFFER_DIM(240, 400),
DISPLAY_TRANSFER_FLAGS);
gspWaitForPPF(); // Wait for the transfer to complete
// Reset the command buffer
GPUCMD_SetBufferOffset(0);
};
void GPU_SetDummyTexEnv(int id)
{
GPU_SetTexEnv(id,
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0),
GPU_TEVOPERANDS(0, 0, 0),
GPU_TEVOPERANDS(0, 0, 0),
GPU_REPLACE,
GPU_REPLACE,
0xFFFFFFFF);
}

View File

@ -0,0 +1,26 @@
/*
* Bare-bones simplistic GPU wrapper
* This library is common to all libctru GPU examples
*/
#pragma once
#include <string.h>
#include <3ds.h>
#include "3dmath.h"
void gpuInit(void);
void gpuExit(void);
void gpuClearBuffers(u32 clearColor);
void gpuFrameBegin(void);
void gpuFrameEnd(void);
// Configures the specified fixed-function fragment shading substage to be a no-operation
void GPU_SetDummyTexEnv(int id);
// Uploads an uniform matrix
static inline void GPU_SetFloatUniformMatrix(GPU_SHADER_TYPE type, int location, matrix_4x4* matrix)
{
GPU_SetFloatUniform(type, location, (u32*)matrix, 4);
}

View File

@ -0,0 +1,244 @@
/*
* ~~ Simple libctru GPU textured cube example ~~
* This example demonstrates the basics of using the PICA200 in a 3DS homebrew
* application in order to render a basic scene consisting of a rotating
* textured cube which is also shaded using a simple shading algorithm.
* The shading algorithm is explained in the vertex shader source code.
*/
#include "gpu.h"
#include "vshader_shbin.h"
#include "kitten_bin.h"
#define CLEAR_COLOR 0x68B0D8FF
typedef struct { float position[3]; float texcoord[2]; float normal[3]; } vertex;
static const vertex vertex_list[] =
{
// First face (PZ)
// First triangle
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f} },
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 0.0f}, {0.0f, 0.0f, +1.0f} },
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f} },
// Second triangle
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, +1.0f} },
{ {-0.5f, +0.5f, +0.5f}, {0.0f, 1.0f}, {0.0f, 0.0f, +1.0f} },
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, +1.0f} },
// Second face (MZ)
// First triangle
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
{ {-0.5f, +0.5f, -0.5f}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
// Second triangle
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
// Third face (PX)
// First triangle
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} },
{ {+0.5f, +0.5f, -0.5f}, {1.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} },
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} },
// Second triangle
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} },
{ {+0.5f, -0.5f, +0.5f}, {0.0f, 1.0f}, {+1.0f, 0.0f, 0.0f} },
{ {+0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {+1.0f, 0.0f, 0.0f} },
// Fourth face (MX)
// First triangle
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} },
{ {-0.5f, -0.5f, +0.5f}, {1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} },
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} },
// Second triangle
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} },
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f} },
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f} },
// Fifth face (PY)
// First triangle
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f} },
{ {-0.5f, +0.5f, +0.5f}, {1.0f, 0.0f}, {0.0f, +1.0f, 0.0f} },
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f} },
// Second triangle
{ {+0.5f, +0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, +1.0f, 0.0f} },
{ {+0.5f, +0.5f, -0.5f}, {0.0f, 1.0f}, {0.0f, +1.0f, 0.0f} },
{ {-0.5f, +0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, +1.0f, 0.0f} },
// Sixth face (MY)
// First triangle
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} },
{ {+0.5f, -0.5f, -0.5f}, {1.0f, 0.0f}, {0.0f, -1.0f, 0.0f} },
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f} },
// Second triangle
{ {+0.5f, -0.5f, +0.5f}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f} },
{ {-0.5f, -0.5f, +0.5f}, {0.0f, 1.0f}, {0.0f, -1.0f, 0.0f} },
{ {-0.5f, -0.5f, -0.5f}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f} },
};
#define vertex_list_count (sizeof(vertex_list)/sizeof(vertex_list[0]))
static DVLB_s* vshader_dvlb;
static shaderProgram_s program;
static int uLoc_projection, uLoc_modelView;
static int uLoc_lightVec, uLoc_lightHalfVec, uLoc_lightClr, uLoc_material;
static matrix_4x4 projection;
static matrix_4x4 material =
{
{
{ { 0.0f, 0.2f, 0.2f, 0.2f } }, // Ambient
{ { 0.0f, 0.4f, 0.4f, 0.4f } }, // Diffuse
{ { 0.0f, 0.8f, 0.8f, 0.8f } }, // Specular
{ { 1.0f, 0.0f, 0.0f, 0.0f } }, // Emission
}
};
static void* vbo_data;
static void* tex_data;
static float angleX = 0.0, angleY = 0.0;
static void sceneInit(void)
{
// Load the vertex shader and create a shader program
vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_size);
shaderProgramInit(&program);
shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]);
// Get the location of the uniforms
uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection");
uLoc_modelView = shaderInstanceGetUniformLocation(program.vertexShader, "modelView");
uLoc_lightVec = shaderInstanceGetUniformLocation(program.vertexShader, "lightVec");
uLoc_lightHalfVec = shaderInstanceGetUniformLocation(program.vertexShader, "lightHalfVec");
uLoc_lightClr = shaderInstanceGetUniformLocation(program.vertexShader, "lightClr");
uLoc_material = shaderInstanceGetUniformLocation(program.vertexShader, "material");
// Compute the projection matrix
m4x4_persp_tilt(&projection, 80.0f*M_PI/180.0f, 400.0f/240.0f, 0.01f, 1000.0f);
// Create the VBO (vertex buffer object)
vbo_data = linearAlloc(sizeof(vertex_list));
memcpy(vbo_data, vertex_list, sizeof(vertex_list));
// Load the texture
tex_data = linearAlloc(kitten_bin_size);
memcpy(tex_data, kitten_bin, kitten_bin_size);
}
static void sceneRender(void)
{
// Bind the shader program
shaderProgramUse(&program);
// Configure the first fragment shading substage to blend the texture color with
// the vertex color (calculated by the vertex shader using a lighting algorithm)
// See https://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml for more insight
GPU_SetTexEnv(0,
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // RGB channels
GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR), // Alpha
GPU_TEVOPERANDS(0, 0, 0), // RGB
GPU_TEVOPERANDS(0, 0, 0), // Alpha
GPU_MODULATE, GPU_MODULATE, // RGB, Alpha
0xFFFFFFFF);
// Configure the first texture unit
GPU_SetTextureEnable(GPU_TEXUNIT0);
GPU_SetTexture(
GPU_TEXUNIT0,
(u32*)osConvertVirtToPhys((u32)tex_data),
64, // Width
64, // Height
GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT), // Flags
GPU_RGBA8 // Pixel format
);
// Configure the "attribute buffers" (that is, the vertex input buffers)
GPU_SetAttributeBuffers(
3, // Number of inputs per vertex
(u32*)osConvertVirtToPhys((u32)vbo_data), // Location of the VBO
GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | // Format of the inputs
GPU_ATTRIBFMT(1, 2, GPU_FLOAT) |
GPU_ATTRIBFMT(2, 3, GPU_FLOAT),
0xFFC, // Unused attribute mask, in our case bits 0~2 are cleared since they are used
0x210, // Attribute permutations (here it is the identity, passing each attribute in order)
1, // Number of buffers
(u32[]) { 0x0 }, // Buffer offsets (placeholders)
(u64[]) { 0x210 }, // Attribute permutations for each buffer (identity again)
(u8[]) { 3 }); // Number of attributes for each buffer
// Calculate the modelView matrix
matrix_4x4 modelView;
m4x4_identity(&modelView);
m4x4_translate(&modelView, 0.0, 0.0, -2.0 + 0.5*sinf(angleX));
m4x4_rotate_x(&modelView, angleX, true);
m4x4_rotate_y(&modelView, angleY, true);
// Rotate the cube each frame
angleX += M_PI / 180;
angleY += M_PI / 360;
// Upload the uniforms
GPU_SetFloatUniformMatrix(GPU_VERTEX_SHADER, uLoc_projection, &projection);
GPU_SetFloatUniformMatrix(GPU_VERTEX_SHADER, uLoc_modelView, &modelView);
GPU_SetFloatUniformMatrix(GPU_VERTEX_SHADER, uLoc_material, &material);
GPU_SetFloatUniform(GPU_VERTEX_SHADER, uLoc_lightVec, (u32*)(float[]){0.0f, -1.0f, 0.0f, 0.0f}, 1);
GPU_SetFloatUniform(GPU_VERTEX_SHADER, uLoc_lightHalfVec, (u32*)(float[]){0.0f, -1.0f, 0.0f, 0.0f}, 1);
GPU_SetFloatUniform(GPU_VERTEX_SHADER, uLoc_lightClr, (u32*)(float[]){1.0f, 1.0f, 1.0f, 1.0f}, 1);
// Draw the VBO
GPU_DrawArray(GPU_TRIANGLES, 0, vertex_list_count);
}
static void sceneExit(void)
{
// Free the texture
linearFree(tex_data);
// Free the VBO
linearFree(vbo_data);
// Free the shader program
shaderProgramFree(&program);
DVLB_Free(vshader_dvlb);
}
int main()
{
// Initialize graphics
gfxInitDefault();
gpuInit();
// Initialize the scene
sceneInit();
gpuClearBuffers(CLEAR_COLOR);
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank(); // Synchronize with the start of VBlank
gfxSwapBuffersGpu(); // Swap the framebuffers so that the frame that we rendered last frame is now visible
hidScanInput(); // Read the user input
// Respond to user input
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
// Render the scene
gpuFrameBegin();
sceneRender();
gpuFrameEnd();
gpuClearBuffers(CLEAR_COLOR);
// Flush the framebuffers out of the data cache (not necessary with pure GPU rendering)
//gfxFlushBuffers();
}
// Deinitialize the scene
sceneExit();
// Deinitialize graphics
gpuExit();
gfxExit();
return 0;
}

View File

@ -0,0 +1,90 @@
; Example PICA200 vertex shader
; Uniforms
.fvec projection[4], modelView[4]
.fvec lightVec, lightHalfVec, lightClr, material[4]
.alias mat_amb material[0]
.alias mat_dif material[1]
.alias mat_spe material[2]
.alias mat_emi material[3]
; Constants
.constf myconst(0.0, 1.0, -1.0, -0.5)
.alias zeros myconst.xxxx ; Vector full of zeros
.alias ones myconst.yyyy ; Vector full of ones
; Outputs
.out outpos position
.out outtc0 texcoord0
.out outclr color
; Inputs (defined as aliases for convenience)
.alias inpos v0
.alias intex v1
.alias innrm v2
.proc main
; Force the w component of inpos to be 1.0
mov r0.xyz, inpos
mov r0.w, ones
; r1 = modelView * inpos
dp4 r1.x, modelView[0], r0
dp4 r1.y, modelView[1], r0
dp4 r1.z, modelView[2], r0
dp4 r1.w, modelView[3], r0
; outpos = projection * r1
dp4 outpos.x, projection[0], r1
dp4 outpos.y, projection[1], r1
dp4 outpos.z, projection[2], r1
dp4 outpos.w, projection[3], r1
; outtex = intex
mov outtc0, intex
; Transform the normal vector with the modelView matrix
; r1 = normalize(modelView * innrm)
mov r0.xyz, innrm
mov r0.w, zeros
dp4 r1.x, modelView[0], r0
dp4 r1.y, modelView[1], r0
dp4 r1.z, modelView[2], r0
mov r1.w, zeros
dp3 r2, r1, r1 ; r2 = x^2+y^2+z^2 for each component
rsq r2, r2 ; r2 = 1/sqrt(r2) ''
mul r1, r2, r1 ; r1 = r1*r2
; Calculate the diffuse level (r0.x) and the shininess level (r0.y)
; r0.x = max(0, -(lightVec * r1))
; r0.y = max(0, (-lightHalfVec[i]) * r1) ^ 2
dp3 r0.x, lightVec, r1
add r0.x, zeros, -r0
dp3 r0.y, -lightHalfVec, r1
max r0, zeros, r0
mul r0.y, r0, r0
; Accumulate the vertex color in r1, initializing it to the emission color
mov r1, mat_emi
; r1 += specularColor * lightClr * shininessLevel
mul r2, lightClr, r0.yyyy
mul r2, mat_spe, r2
add r1, r2, r1
; r1 += diffuseColor * lightClr * diffuseLevel
mul r2, lightClr, r0.xxxx
mul r2, mat_dif, r2
add r1, r2, r1
; r1 += ambientColor * lightClr
mov r2, lightClr
mul r2, mat_amb, r2
add r1, r2, r1
; outclr = clamp r1 to [0,1]
min outclr, ones, r1
; We're finished
end
.end

View File

@ -0,0 +1,7 @@
SUBDIRS:= `ls | egrep -v '^(CVS)$$'`
all:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
clean:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
install:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i install || { exit 1;} fi; done;

View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,65 @@
/*
Both Screen Text example made by Aurelio Mannara for ctrulib
This code was modified for the last time on: 12/12/2014 23:20 UTC+1
This wouldn't be possible without the amazing work done by:
-Smealum
-fincs
-WinterMute
-yellows8
-plutoo
-mtheall
-Many others who worked on 3DS and I'm surely forgetting about
*/
#include <3ds.h>
#include <stdio.h>
int main(int argc, char **argv)
{
// Initialize services
gfxInitDefault();
//In this example we need one PrintConsole for each screen
PrintConsole topScreen, bottomScreen;
//Initialize console for both screen using the two different PrintConsole we have defined
consoleInit(GFX_TOP, &topScreen);
consoleInit(GFX_BOTTOM, &bottomScreen);
//Before doing any text printing we should select the PrintConsole in which we are willing to write, otherwise the library will print on the last selected/initialized one
//Let's start by printing something on the top screen
consoleSelect(&topScreen);
printf("This is the top screen. We have lot of space here!\n");
//Now write something else on the bottom screen
consoleSelect(&bottomScreen);
printf("This is the bottom screen. We don't have much space...\nStill better than DS screens :D");
consoleSelect(&topScreen);
printf("\x1b[29;15HPress Start to exit.");
// Main loop
while (aptMainLoop())
{
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
}
// Exit services
gfxExit();
return 0;
}

View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,77 @@
/*
Colored Text example made by Aurelio Mannara for ctrulib
This code was modified for the last time on: 12/12/2014 23:00 UTC+1
This wouldn't be possible without the amazing work done by:
-Smealum
-fincs
-WinterMute
-yellows8
-plutoo
-mtheall
-Many others who worked on 3DS and I'm surely forgetting about
*/
#include <3ds.h>
#include <stdio.h>
int main(int argc, char **argv)
{
// Initialize services
gfxInitDefault();
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
consoleInit(GFX_TOP, NULL);
//Move the cursor to row 15 and column 19 and then prints "Hello World!"
//To move the cursor you have tu print "\x1b[r;cH", where r and c are respectively
//the row and column where you want your cursor to move
//The top screen has 30 rows and 50 columns
//The bottom screen has 30 rows and 40 columns
printf("\x1b[15;19HHello World!");
//Move the cursor to the top left corner of the screen
printf("\x1b[0;0H");
//Print a REALLY crappy poeam with colored text
//\x1b[cm set a SGR (Select Graphic Rendition) parameter, where c is the parameter that you want to set
//Please refer to http://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes to see all the possible SGR parameters
//As of now ctrulib support only these parameters:
//Reset (0), Half bright colors (2), Reverse (7), Text color (30-37) and Background color (40-47)
printf("Roses are \x1b[31mred\x1b[0m\n");
printf("Violets are \x1b[34mblue\x1b[0m\n");
printf("Piracy is bad\n");
printf("While homebrews are good\n\n");
//Black text on white background
//In this example we set two parameter in a single escape sequence by separating them by a semicolon
//\x1b[47;30m means that it will set a white background (47) and it will print white characters (30)
//In this we also could have used the
printf("\x1b[47;30mBlack text on white background\x1b[0m");
printf("\x1b[29;15HPress Start to exit.");
// Main loop
while (aptMainLoop())
{
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
}
// Exit services
gfxExit();
return 0;
}

View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,55 @@
/*
Hello World example made by Aurelio Mannara for ctrulib
This code was modified for the last time on: 12/12/2014 21:00 UTC+1
This wouldn't be possible without the amazing work done by:
-Smealum
-fincs
-WinterMute
-yellows8
-plutoo
-mtheall
-Many others who worked on 3DS and I'm surely forgetting about
*/
#include <3ds.h>
#include <stdio.h>
int main(int argc, char **argv)
{
gfxInitDefault();
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
consoleInit(GFX_TOP, NULL);
//Move the cursor to row 15 and column 19 and then prints "Hello World!"
//To move the cursor you have to print "\x1b[r;cH", where r and c are respectively
//the row and column where you want your cursor to move
//The top screen has 30 rows and 50 columns
//The bottom screen has 30 rows and 40 columns
printf("\x1b[15;19HHello World!");
printf("\x1b[29;15HPress Start to exit.");
// Main loop
while (aptMainLoop())
{
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
}
gfxExit();
return 0;
}

View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,74 @@
/*
Multiple Windows Text example made by Aurelio Mannara for ctrulib
This code was modified for the last time on: 12/12/2014 23:50 UTC+1
This wouldn't be possible without the amazing work done by:
-Smealum
-fincs
-WinterMute
-yellows8
-plutoo
-mtheall
-Many others who worked on 3DS and I'm surely forgetting about
*/
#include <3ds.h>
#include <stdio.h>
int main(int argc, char **argv)
{
// Initialize services
gfxInitDefault();
//In this example we need three PrintConsole, one for each window and one for the whole top screen
PrintConsole leftWindow, rightWindow, topScreen;
//Initialize console for each window
consoleInit(GFX_TOP, &leftWindow);
consoleInit(GFX_TOP, &rightWindow);
consoleInit(GFX_TOP, &topScreen);
//Now we specify the window position and dimension for each console window using consoleSetWindow(PrintConsole* console, int x, int y, int width, int height);
//x, y, width and height are in terms of cells, not pixel, where each cell is composed by 8x8 pixels.
consoleSetWindow(&leftWindow, 1, 1, 23, 28);
consoleSetWindow(&rightWindow, 26, 1, 23, 28);
//Before doing any text printing we should select the PrintConsole in which we are willing to write, otherwise the library will print on the last selected/initialized one
//Let's start by printing something on the top screen
consoleSelect(&leftWindow);
printf("This text is in the left window!\n");
printf("3DS rocks!!!\n");
//Now write something else on the bottom screen
consoleSelect(&rightWindow);
printf("This text is in the right window!\n");
printf("This thing works pretty well!\n");
consoleSelect(&topScreen);
printf("\x1b[29;15HPress Start to exit.");
// Main loop
while (aptMainLoop())
{
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
}
// Exit services
gfxExit();
return 0;
}

174
examples/http/Makefile Normal file
View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

4
examples/http/README.md Normal file
View File

@ -0,0 +1,4 @@
# http
This is an example for using HTTPC. This downloads a raw image for displaying on the top-screen. The URL used here is a LAN-only one, hence this URL must be changed before building+running this example.

113
examples/http/source/main.c Normal file
View File

@ -0,0 +1,113 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
#include <3ds.h>
Result http_download(httpcContext *context)//This error handling needs updated with proper text printing once ctrulib itself supports that.
{
Result ret=0;
u8* framebuf_top;
u32 statuscode=0;
u32 size=0, contentsize=0;
u8 *buf;
ret = httpcBeginRequest(context);
if(ret!=0)return ret;
ret = httpcGetResponseStatusCode(context, &statuscode, 0);
if(ret!=0)return ret;
if(statuscode!=200)return -2;
ret=httpcGetDownloadSizeState(context, NULL, &contentsize);
if(ret!=0)return ret;
printf("size: %"PRId32"\n",contentsize);
gfxFlushBuffers();
buf = (u8*)malloc(contentsize);
if(buf==NULL)return -1;
memset(buf, 0, contentsize);
ret = httpcDownloadData(context, buf, contentsize, NULL);
if(ret!=0)
{
free(buf);
return ret;
}
size = contentsize;
if(size>(240*400*3*2))size = 240*400*3*2;
framebuf_top = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
memcpy(framebuf_top, buf, size);
gfxFlushBuffers();
gfxSwapBuffers();
framebuf_top = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
memcpy(framebuf_top, buf, size);
gfxFlushBuffers();
gfxSwapBuffers();
gspWaitForVBlank();
free(buf);
return 0;
}
int main()
{
Result ret=0;
httpcContext context;
gfxInitDefault();
httpcInit();
consoleInit(GFX_BOTTOM,NULL);
//Change this to your own URL.
char *url = "http://devkitpro.org/misc/httpexample_rawimg.rgb";
printf("Downloading %s\n",url);
gfxFlushBuffers();
ret = httpcOpenContext(&context, url, 1);
printf("return from httpcOpenContext: %"PRId32"\n",ret);
gfxFlushBuffers();
if(ret==0)
{
ret=http_download(&context);
printf("return from http_download: %"PRId32"\n",ret);
gfxFlushBuffers();
httpcCloseContext(&context);
}
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank();
hidScanInput();
// Your code goes here
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
}
// Exit services
httpcExit();
gfxExit();
return 0;
}

7
examples/input/Makefile Normal file
View File

@ -0,0 +1,7 @@
SUBDIRS:= `ls | egrep -v '^(CVS)$$'`
all:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
clean:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
install:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i install || { exit 1;} fi; done;

View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,105 @@
/*
Circle Pad example made by Aurelio Mannara for ctrulib
Please refer to https://github.com/smealum/ctrulib/blob/master/libctru/include/3ds/services/hid.h for more information
This code was modified for the last time on: 12/13/2014 2:20 UTC+1
This wouldn't be possible without the amazing work done by:
-Smealum
-fincs
-WinterMute
-yellows8
-plutoo
-mtheall
-Many others who worked on 3DS and I'm surely forgetting about
*/
#include <3ds.h>
#include <stdio.h>
int main(int argc, char **argv)
{
//Matrix containing the name of each key. Useful for printing when a key is pressed
char keysNames[32][32] = {
"KEY_A", "KEY_B", "KEY_SELECT", "KEY_START",
"KEY_DRIGHT", "KEY_DLEFT", "KEY_DUP", "KEY_DDOWN",
"KEY_R", "KEY_L", "KEY_X", "KEY_Y",
"", "", "KEY_ZL", "KEY_ZR",
"", "", "", "",
"KEY_TOUCH", "", "", "",
"KEY_CSTICK_RIGHT", "KEY_CSTICK_LEFT", "KEY_CSTICK_UP", "KEY_CSTICK_DOWN",
"KEY_CPAD_RIGHT", "KEY_CPAD_LEFT", "KEY_CPAD_UP", "KEY_CPAD_DOWN"
};
// Initialize services
gfxInitDefault();
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
consoleInit(GFX_TOP, NULL);
u32 kDownOld = 0, kHeldOld = 0, kUpOld = 0; //In these variables there will be information about keys detected in the previous frame
printf("\x1b[0;0HPress Start to exit.");
printf("\x1b[1;0HCirclePad position:");
// Main loop
while (aptMainLoop())
{
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
//hidKeysHeld returns information about which buttons have are held down in this frame
u32 kHeld = hidKeysHeld();
//hidKeysUp returns information about which buttons have been just released
u32 kUp = hidKeysUp();
if (kDown & KEY_START) break; // break in order to return to hbmenu
//Do the keys printing only if keys have changed
if (kDown != kDownOld || kHeld != kHeldOld || kUp != kUpOld)
{
//Clear console
consoleClear();
//These two lines must be rewritten because we cleared the whole console
printf("\x1b[0;0HPress Start to exit.");
printf("\x1b[1;0HCirclePad position:");
printf("\x1b[3;0H"); //Move the cursor to the fourth row because on the third one we'll write the circle pad position
//Check if some of the keys are down, held or up
int i;
for (i = 0; i < 32; i++)
{
if (kDown & BIT(i)) printf("%s down\n", keysNames[i]);
if (kHeld & BIT(i)) printf("%s held\n", keysNames[i]);
if (kUp & BIT(i)) printf("%s up\n", keysNames[i]);
}
}
//Set keys old values for the next frame
kDownOld = kDown;
kHeldOld = kHeld;
kUpOld = kUp;
circlePosition pos;
//Read the CirclePad position
hidCircleRead(&pos);
//Print the CirclePad position
printf("\x1b[2;0H%04d; %04d", pos.dx, pos.dy);
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
}
// Exit services
gfxExit();
return 0;
}

View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,60 @@
/*
Touch Screen example made by Aurelio Mannara for ctrulib
Please refer to https://github.com/smealum/ctrulib/blob/master/libctru/include/3ds/services/hid.h for more information
This code was modified for the last time on: 12/13/2014 2:30 UTC+1
This wouldn't be possible without the amazing work done by:
-Smealum
-fincs
-WinterMute
-yellows8
-plutoo
-mtheall
-Many others who worked on 3DS and I'm surely forgetting about
*/
#include <3ds.h>
#include <stdio.h>
int main(int argc, char **argv)
{
gfxInitDefault();
//Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
consoleInit(GFX_TOP, NULL);
printf("\x1b[0;0HPress Start to exit.");
printf("\x1b[1;0HTouch Screen position:");
// Main loop
while (aptMainLoop())
{
//Scan all the inputs. This should be done once for each frame
hidScanInput();
//hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
if (kDown & KEY_START) break; // break in order to return to hbmenu
touchPosition touch;
//Read the touch screen coordinates
hidTouchRead(&touch);
//Print the touch screen coordinates
printf("\x1b[2;0H%03d; %03d", touch.px, touch.py);
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
//Wait for VBlank
gspWaitForVBlank();
}
// Exit services
gfxExit();
return 0;
}

View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,7 @@
libapplet_launch
=======
Example for launching library applets. This launches the extrapad library applet(Circle Pad Pro calibration applet) when the B button is pressed.
This is not usable from the homebrew launcher.

View File

@ -0,0 +1,45 @@
#include <3ds.h>
#include <stdio.h>
static bool allowed = false;
// If you define this function, you can monitor/debug APT events
void _aptDebug(int a, int b)
{
if (allowed)
printf("_aptDebug(%d,%x)\n", a, b);
}
int main()
{
gfxInitDefault();
consoleInit(GFX_TOP, NULL);
allowed = true;
printf("Press B to launch applet\n");
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank();
gfxSwapBuffers();
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
gfxFlushBuffers();
// Launch the extrapad library applet when button B is pressed.
if (kDown & KEY_B)
{
Result rc = APT_LaunchLibraryApplet(APPID_EXTRAPAD, 0, NULL, 0);
if (rc) printf("APT_LaunchLibraryApplet: %08lX\n", rc);
}
}
// Exit services
gfxExit();
return 0;
}

174
examples/mvd/Makefile Normal file
View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

1
examples/mvd/README.md Normal file
View File

@ -0,0 +1 @@
This example is for using New3DS MVD, for hardware color-format conversion + video processing(the latter is not supported by ctrulib/this example yet).

View File

@ -0,0 +1,6 @@
#ifndef COSTABLE_H
#define COSTABLE_H
s32 costable[] = {4096, 4095, 4094, 4093, 4091, 4088, 4084, 4080, 4076, 4071, 4065, 4058, 4051, 4044, 4035, 4026, 4017, 4007, 3996, 3985, 3973, 3960, 3947, 3934, 3919, 3904, 3889, 3873, 3856, 3839, 3821, 3803, 3784, 3765, 3744, 3724, 3703, 3681, 3659, 3636, 3612, 3588, 3564, 3539, 3513, 3487, 3461, 3434, 3406, 3378, 3349, 3320, 3290, 3260, 3229, 3198, 3167, 3135, 3102, 3069, 3035, 3002, 2967, 2932, 2897, 2861, 2825, 2788, 2751, 2714, 2676, 2638, 2599, 2560, 2521, 2481, 2441, 2401, 2360, 2318, 2277, 2235, 2193, 2150, 2107, 2064, 2020, 1976, 1932, 1888, 1843, 1798, 1753, 1707, 1662, 1616, 1569, 1523, 1476, 1429, 1382, 1334, 1287, 1239, 1191, 1143, 1095, 1046, 997, 949, 900, 851, 801, 752, 703, 653, 603, 554, 504, 454, 404, 354, 304, 254, 204, 153, 103, 53, 3, -46, -97, -147, -197, -247, -297, -347, -398, -448, -497, -547, -597, -647, -696, -746, -795, -844, -893, -942, -991, -1040, -1088, -1137, -1185, -1233, -1281, -1328, -1376, -1423, -1470, -1517, -1563, -1610, -1656, -1701, -1747, -1792, -1837, -1882, -1927, -1971, -2015, -2058, -2102, -2144, -2187, -2229, -2271, -2313, -2354, -2395, -2436, -2476, -2516, -2555, -2594, -2633, -2671, -2709, -2747, -2784, -2820, -2857, -2892, -2928, -2963, -2997, -3031, -3065, -3098, -3130, -3163, -3194, -3225, -3256, -3286, -3316, -3345, -3374, -3402, -3430, -3457, -3484, -3510, -3536, -3561, -3585, -3609, -3633, -3656, -3678, -3700, -3721, -3742, -3762, -3782, -3801, -3819, -3837, -3854, -3871, -3887, -3902, -3917, -3932, -3946, -3959, -3971, -3983, -3995, -4005, -4016, -4025, -4034, -4042, -4050, -4057, -4064, -4070, -4075, -4080, -4084, -4087, -4090, -4092, -4094, -4095, -4095, -4095, -4094, -4093, -4091, -4088, -4085, -4081, -4076, -4071, -4066, -4059, -4052, -4045, -4036, -4028, -4018, -4008, -3997, -3986, -3974, -3962, -3949, -3935, -3921, -3906, -3891, -3875, -3858, -3841, -3824, -3805, -3787, -3767, -3747, -3727, -3705, -3684, -3662, -3639, -3615, -3592, -3567, -3542, -3517, -3491, -3464, -3437, -3409, -3381, -3353, -3324, -3294, -3264, -3233, -3202, -3171, -3139, -3106, -3073, -3040, -3006, -2972, -2937, -2902, -2866, -2830, -2793, -2756, -2719, -2681, -2643, -2604, -2565, -2526, -2486, -2446, -2406, -2365, -2324, -2282, -2240, -2198, -2156, -2113, -2069, -2026, -1982, -1938, -1894, -1849, -1804, -1759, -1713, -1668, -1622, -1575, -1529, -1482, -1435, -1388, -1341, -1293, -1245, -1197, -1149, -1101, -1052, -1004, -955, -906, -857, -808, -758, -709, -660, -610, -560, -510, -460, -411, -360, -310, -260, -210, -160, -110, -60, -9, 40, 90, 140, 191, 241, 291, 341, 391, 441, 491, 541, 591, 640, 690, 739, 789, 838, 887, 936, 985, 1033, 1082, 1130, 1179, 1227, 1274, 1322, 1370, 1417, 1464, 1511, 1557, 1604, 1650, 1695, 1741, 1786, 1831, 1876, 1921, 1965, 2009, 2053, 2096, 2139, 2182, 2224, 2266, 2308, 2349, 2390, 2431, 2471, 2511, 2550, 2589, 2628, 2666, 2704, 2742, 2779, 2816, 2852, 2888, 2923, 2958, 2993, 3027, 3060, 3093, 3126, 3158, 3190, 3221, 3252, 3282, 3312, 3342, 3370, 3399, 3426, 3454, 3480, 3507, 3532, 3557, 3582, 3606, 3630, 3653, 3675, 3697, 3718, 3739, 3759, 3779, 3798, 3817, 3835, 3852, 3869, 3885, 3900, 3915, 3930, 3944, 3957, 3970, 3982, 3993, 4004, 4014, 4024, 4033, 4041, 4049, 4056, 4063, 4069, 4074, 4079, 4083, 4087, 4090, 4092, 4094, 4095};
#endif

143
examples/mvd/source/main.c Normal file
View File

@ -0,0 +1,143 @@
#include <stdio.h>
#include <string.h>
#include <3ds.h>
#include "costable.h"
u8* inaddr;
u8* outaddr;
char logstring[256];
s32 pcCos(u16 v)
{
return costable[v&0x1FF];
}
void printstring(char *str)//Placeholder until ctrulib itself has proper text drawing.
{
strncat(logstring, str, sizeof(logstring)-1);
}
void draw_startup()
{
Result ret;
FILE *f = NULL;
u8* bufAdr = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
u8* gfxtopadr = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
mvdstdConfig config;
char str[256];
int i, j;
u32 cnt=0;
for(i=0;i<320;i++)
{
for(j=0;j<240;j++)
{
u32 v=(j+i*240)*3;
bufAdr[v]=(pcCos(i+cnt)+4096)/32;
bufAdr[v+1]=(pcCos(j-256+cnt)+4096)/64;
bufAdr[v+2]=(pcCos(i+128-cnt)+4096)/32;
}
}
f = fopen("sdmc:/mvd_indata.bin", "r");
if(f)
{
fread(inaddr, 1, 0x46500, f);
fclose(f);
}
else
{
memcpy(inaddr, bufAdr, 320*240*3);
}
memset(gfxtopadr, 0, 0x46500);
GSPGPU_FlushDataCache(NULL, inaddr, 0x46500);
printstring("mvd example\n");
ret = mvdstdInit(MVDMODE_COLORFORMATCONV, MVDTYPEIN_YUYV422, MVDTYPEOUT_RGB565, 0);
memset(str, 0, 256);
snprintf(str, sizeof(str)-1, "mvdstdInit(): 0x%08x\n", (unsigned int)ret);
printstring(str);
if(ret>=0)
{
mvdstdGenerateDefaultConfig(&config, 320, 240, 320, 240, (u32*)inaddr, (u32*)outaddr, (u32*)&outaddr[0x12c00]);
ret = mvdstdProcessFrame(&config, NULL, 0, 0);
memset(str, 0, 256);
snprintf(str, sizeof(str)-1, "mvdstdProcessFrame(): 0x%08x\n", (unsigned int)ret);
printstring(str);
}
svcSleepThread(1000000000);//Not sure how to determine when frame processing finishes.
GSPGPU_InvalidateDataCache(NULL, outaddr, 0x100000);
f = fopen("sdmc:/mvd_outdata.bin", "w");
if(f)
{
fwrite(outaddr, 1, 0x100000, f);
fclose(f);
}
f = fopen("sdmc:/mvd_log", "w");
if(f)
{
fwrite(logstring, 1, strlen(logstring), f);
fclose(f);
}
memcpy(gfxtopadr, outaddr, 0x46500);
mvdstdShutdown();
gfxFlushBuffers();
gfxSwapBuffers();
gspWaitForVBlank();
}
int main()
{
gfxInitDefault();
//gfxSet3D(true); // uncomment if using stereoscopic 3D
memset(logstring, 0, 256);
inaddr = linearAlloc(0x100000);
outaddr = linearAlloc(0x100000);
if(inaddr && outaddr)
{
memset(inaddr, 0, 0x100000);
memset(outaddr, 0, 0x100000);
draw_startup();
}
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank();
hidScanInput();
// Your code goes here
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
}
if(inaddr)linearFree(inaddr);
if(outaddr)linearFree(outaddr);
gfxExit();
return 0;
}

183
examples/qtm/Makefile Normal file
View File

@ -0,0 +1,183 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
APP_TITLE := Head tracking demo
APP_DESCRIPTION := This is a small demo app for the New 3DS head tracking.
APP_AUTHOR := yellows8
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

6
examples/qtm/README.md Normal file
View File

@ -0,0 +1,6 @@
# qtm
This is an example for using New3DS QTM for head-tracking.
This is currently not usable from the homebrew launcher.

View File

@ -0,0 +1,85 @@
#include <string.h>
#include <stdio.h>
#include <3ds.h>
int main()
{
u32 pos;
u32 x, y;
Result ret;
bool qtm_usable;
qtmHeadtrackingInfo qtminfo;
u32 colors[4] = {0x0000FF, 0x00FF00, 0xFF0000, 0xFFFFFF};
gfxInitDefault();
//gfxSet3D(true); // uncomment if using stereoscopic 3D
qtmInit();
consoleInit(GFX_BOTTOM, NULL);
printf("qtm example\n");
qtm_usable = qtmCheckInitialized();
if(!qtm_usable)printf("QTM is not usable, therefore this example won't do anything with QTM.\n");
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank();
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
if(qtm_usable)
{
u8* fb = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
memset(fb, 0, 400*240*3);
ret = qtmGetHeadtrackingInfo(0, &qtminfo);
if(ret==0)
{
consoleClear();
for(pos=0; pos<5; pos++)
{
printf("flags[%x]=0x%x", (unsigned int)pos, qtminfo.flags[pos]);
if(pos<4)printf(", ");
}
printf("\nfloatdata_x08: %f\n", qtminfo.floatdata_x08);
printf("coords0: ");
for(pos=0; pos<4; pos++)
{
printf("[%x].x=%f, y=%f", (unsigned int)pos, qtminfo.coords0[pos].x, qtminfo.coords0[pos].y);
if(pos<3)printf(", ");
}
printf("\n");
if(qtmCheckHeadFullyDetected(&qtminfo))
{
for(pos=0; pos<4; pos++)
{
ret = qtmConvertCoordToScreen(&qtminfo.coords0[pos], NULL, NULL, &x, &y);
if(ret==0)memcpy(&fb[(x*240 + y) * 3], &colors[pos], 3);
}
}
}
}
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
}
// Exit services
qtmExit();
gfxExit();
return 0;
}

181
examples/romfs/Makefile Normal file
View File

@ -0,0 +1,181 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional)
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
ROMFS := romfs
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
ifneq ($(ROMFS),)
export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,6 @@
Hello, this is the libctru romfs example.
This text is being read off a file in romfs.
>>3DS Homebrew is Cool<<
Signed off, fincs

View File

@ -0,0 +1,2 @@
The path to this file contains UTF-16
characters that fall outside ASCII.

View File

@ -0,0 +1,58 @@
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <3ds.h>
void printfile(const char* path)
{
FILE* f = fopen(path, "r");
if (f)
{
char mystring[100];
while (fgets(mystring, sizeof(mystring), f))
{
int a = strlen(mystring);
if (mystring[a-1] == '\n')
{
mystring[a-1] = 0;
if (mystring[a-2] == '\r')
mystring[a-2] = 0;
}
puts(mystring);
}
printf(">>EOF<<\n");
fclose(f);
}
}
int main()
{
gfxInitDefault();
consoleInit(GFX_TOP, NULL);
Result rc = romfsInit();
if (rc)
printf("romfsInit: %08lX\n", rc);
else
{
printf("romfs Init Successful!\n");
printfile("folder/file.txt");
// Test reading a file with non-ASCII characters in the name
printfile("フォルダ/ファイル.txt");
}
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank();
hidScanInput();
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
}
romfsExit();
gfxExit();
return 0;
}

174
examples/sdmc/Makefile Normal file
View File

@ -0,0 +1,174 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

5
examples/sdmc/README.md Normal file
View File

@ -0,0 +1,5 @@
sdmc
=======
very simple example of how to access SD files with libctru;

View File

@ -0,0 +1,50 @@
#include <3ds/types.h>
s32 costable[] = { 4096, 4095, 4094, 4093, 4091, 4088, 4084, 4080, 4076, 4071, 4065,
4058, 4051, 4044, 4035, 4026, 4017, 4007, 3996, 3985, 3973, 3960,
3947, 3934, 3919, 3904, 3889, 3873, 3856, 3839, 3821, 3803, 3784,
3765, 3744, 3724, 3703, 3681, 3659, 3636, 3612, 3588, 3564, 3539,
3513, 3487, 3461, 3434, 3406, 3378, 3349, 3320, 3290, 3260, 3229,
3198, 3167, 3135, 3102, 3069, 3035, 3002, 2967, 2932, 2897, 2861,
2825, 2788, 2751, 2714, 2676, 2638, 2599, 2560, 2521, 2481, 2441,
2401, 2360, 2318, 2277, 2235, 2193, 2150, 2107, 2064, 2020, 1976,
1932, 1888, 1843, 1798, 1753, 1707, 1662, 1616, 1569, 1523, 1476,
1429, 1382, 1334, 1287, 1239, 1191, 1143, 1095, 1046, 997, 949,
900, 851, 801, 752, 703, 653, 603, 554, 504, 454, 404, 354, 304,
254, 204, 153, 103, 53, 3, -46, -97, -147, -197, -247, -297, -347,
-398, -448, -497, -547, -597, -647, -696, -746, -795, -844, -893,
-942, -991, -1040, -1088, -1137, -1185, -1233, -1281, -1328, -1376,
-1423, -1470, -1517, -1563, -1610, -1656, -1701, -1747, -1792, -1837,
-1882, -1927, -1971, -2015, -2058, -2102, -2144, -2187, -2229, -2271,
-2313, -2354, -2395, -2436, -2476, -2516, -2555, -2594, -2633, -2671,
-2709, -2747, -2784, -2820, -2857, -2892, -2928, -2963, -2997, -3031,
-3065, -3098, -3130, -3163, -3194, -3225, -3256, -3286, -3316, -3345,
-3374, -3402, -3430, -3457, -3484, -3510, -3536, -3561, -3585, -3609,
-3633, -3656, -3678, -3700, -3721, -3742, -3762, -3782, -3801, -3819,
-3837, -3854, -3871, -3887, -3902, -3917, -3932, -3946, -3959, -3971,
-3983, -3995, -4005, -4016, -4025, -4034, -4042, -4050, -4057, -4064,
-4070, -4075, -4080, -4084, -4087, -4090, -4092, -4094, -4095, -4095,
-4095, -4094, -4093, -4091, -4088, -4085, -4081, -4076, -4071, -4066,
-4059, -4052, -4045, -4036, -4028, -4018, -4008, -3997, -3986, -3974,
-3962, -3949, -3935, -3921, -3906, -3891, -3875, -3858, -3841, -3824,
-3805, -3787, -3767, -3747, -3727, -3705, -3684, -3662, -3639, -3615,
-3592, -3567, -3542, -3517, -3491, -3464, -3437, -3409, -3381, -3353,
-3324, -3294, -3264, -3233, -3202, -3171, -3139, -3106, -3073, -3040,
-3006, -2972, -2937, -2902, -2866, -2830, -2793, -2756, -2719, -2681,
-2643, -2604, -2565, -2526, -2486, -2446, -2406, -2365, -2324, -2282,
-2240, -2198, -2156, -2113, -2069, -2026, -1982, -1938, -1894, -1849,
-1804, -1759, -1713, -1668, -1622, -1575, -1529, -1482, -1435, -1388,
-1341, -1293, -1245, -1197, -1149, -1101, -1052, -1004, -955, -906,
-857, -808, -758, -709, -660, -610, -560, -510, -460, -411, -360,
-310, -260, -210, -160, -110, -60, -9, 40, 90, 140, 191, 241, 291,
341, 391, 441, 491, 541, 591, 640, 690, 739, 789, 838, 887, 936,
985, 1033, 1082, 1130, 1179, 1227, 1274, 1322, 1370, 1417, 1464,
1511, 1557, 1604, 1650, 1695, 1741, 1786, 1831, 1876, 1921, 1965,
2009, 2053, 2096, 2139, 2182, 2224, 2266, 2308, 2349, 2390, 2431,
2471, 2511, 2550, 2589, 2628, 2666, 2704, 2742, 2779, 2816, 2852,
2888, 2923, 2958, 2993, 3027, 3060, 3093, 3126, 3158, 3190, 3221,
3252, 3282, 3312, 3342, 3370, 3399, 3426, 3454, 3480, 3507, 3532,
3557, 3582, 3606, 3630, 3653, 3675, 3697, 3718, 3739, 3759, 3779,
3798, 3817, 3835, 3852, 3869, 3885, 3900, 3915, 3930, 3944, 3957,
3970, 3982, 3993, 4004, 4014, 4024, 4033, 4041, 4049, 4056, 4063,
4069, 4074, 4079, 4083, 4087, 4090, 4092, 4094, 4095};

View File

@ -0,0 +1,6 @@
#ifndef COSTABLE_H
#define COSTABLE_H
extern s32 costable[];
#endif

View File

@ -0,0 +1,98 @@
///////////////////////////////////////
// SDMC example //
///////////////////////////////////////
//this example shows you how to load a binary image file from the SD card and display it on the lower screen
//for this to work you should copy test.bin to same folder as your .3dsx
//this file was generated with GIMP by saving a 240x320 image to raw RGB
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <3ds.h>
#include "costable.h"
//this will contain the data read from SDMC
u8* buffer;
//3DS has VFPs so we could just use cos
//but we're old school so LUT4life
s32 pcCos(u16 v)
{
return costable[v&0x1FF];
}
void renderEffect()
{
static int cnt;
u8* bufAdr=gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
int i, j;
for(i=1;i<400;i++)
{
for(j=1;j<240;j++)
{
u32 v=(j+i*240)*3;
bufAdr[v]=(pcCos(i+cnt)+4096)/32;
bufAdr[v+1]=(pcCos(j-256+cnt)+4096)/64;
bufAdr[v+2]=(pcCos(i+128-cnt)+4096)/32;
}
}
cnt++;
}
int main(int argc, char** argv)
{
gfxInitDefault(); //makes displaying to screen easier
FILE *file = fopen("test.bin","rb");
if (file == NULL) goto exit;
// seek to end of file
fseek(file,0,SEEK_END);
// file pointer tells us the size
off_t size = ftell(file);
// seek back to start
fseek(file,0,SEEK_SET);
//allocate a buffer
buffer=malloc(size);
if(!buffer)goto exit;
//read contents !
off_t bytesRead = fread(buffer,1,size,file);
//close the file because we like being nice and tidy
fclose(file);
if(size!=bytesRead)goto exit;
while(aptMainLoop())
{
//exit when user hits B
hidScanInput();
if(keysHeld()&KEY_B)break;
//render rainbow
renderEffect();
//copy buffer to lower screen (don't have to do it every frame)
memcpy(gfxGetFramebuffer(GFX_BOTTOM, GFX_BOTTOM, NULL, NULL), buffer, size);
//wait & swap
gfxSwapBuffersGpu();
gspWaitForEvent(GSPEVENT_VBlank0, false);
}
//cleanup and return
//returning from main() returns to hbmenu when run under ninjhax
exit:
//closing all services even more so
gfxExit();
return 0;
}

1
examples/sdmc/test.bin Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
SUBDIRS:= `ls | egrep -v '^(CVS)$$'`
all:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i || { exit 1;} fi; done;
clean:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i clean || { exit 1;} fi; done;
install:
@for i in $(SUBDIRS); do if test -e $$i/Makefile ; then $(MAKE) -C $$i install || { exit 1;} fi; done;

View File

@ -0,0 +1,175 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.png
# - icon.png
# - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2 -mword-relocations \
-fomit-frame-pointer -ffast-math \
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lctru -lm
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.png)
ifneq (,$(findstring $(TARGET).png,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).png
else
ifneq (,$(findstring icon.png,$(icons)))
export APP_ICON := $(TOPDIR)/icon.png
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
$(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh
else
$(OUTPUT).3dsx : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o : %.vsh
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
@rm ../$(notdir $<).shbin
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,3 @@
# template
This is a template for starting new 3DS libctru projects.

View File

@ -0,0 +1,37 @@
#include <string.h>
#include <3ds.h>
int main()
{
gfxInitDefault();
//gfxSet3D(true); // uncomment if using stereoscopic 3D
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank();
hidScanInput();
// Your code goes here
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
// Example rendering code that displays a white pixel
// Please note that the 3DS screens are sideways (thus 240x400 and 240x320)
u8* fb = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL);
memset(fb, 0, 240*400*3);
fb[3*(10+10*240)] = 0xFF;
fb[3*(10+10*240)+1] = 0xFF;
fb[3*(10+10*240)+2] = 0xFF;
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
}
gfxExit();
return 0;
}

View File

@ -0,0 +1,121 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/3ds_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(shell basename $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard
CFLAGS := -g -Wall -O2\
$(ARCH)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/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)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
lib:
@[ -d $@ ] || mkdir -p $@
$(BUILD): lib
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) lib
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,3 @@
# template
This is a template for starting new 3DS library projects.

View File

@ -0,0 +1,6 @@
#ifndef _templatelib_h_
#define _templatelib_h_
int myLibFunction();
#endif // _templatelib_h_

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