Compare commits
No commits in common. "master" and "v1.0.0" have entirely different histories.
21
.github/workflows/build.yaml
vendored
21
.github/workflows/build.yaml
vendored
@ -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
|
40
.github/workflows/doxygen.yaml
vendored
40
.github/workflows/doxygen.yaml
vendored
@ -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
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,5 @@ Thumbs.db
|
||||
build/
|
||||
lib/
|
||||
docs/
|
||||
examples/
|
||||
internal_docs
|
||||
build.sh
|
||||
|
47
.travis.yml
Normal file
47
.travis.yml
Normal file
@ -0,0 +1,47 @@
|
||||
language: c
|
||||
|
||||
sudo: false
|
||||
|
||||
#Cache devkitArm and doxygen
|
||||
cache:
|
||||
directories:
|
||||
- /home/travis/devkitPro
|
||||
- /home/travis/doxygen/doxygen-1.8.10/bin
|
||||
|
||||
before_install:
|
||||
# Travis has an OLD doxygen build, so we fetch a recent one
|
||||
- export DOXY_BINPATH=/home/travis/doxygen/doxygen-1.8.10/bin
|
||||
- if [ ! -e "$DOXY_BINPATH/doxygen" ]; then mkdir -p ~/doxygen && cd ~/doxygen; fi
|
||||
- if [ ! -e "$DOXY_BINPATH/doxygen" ]; then wget http://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.10.linux.bin.tar.gz; fi
|
||||
- if [ ! -e "$DOXY_BINPATH/doxygen" ]; then tar xzf doxygen-1.8.10.linux.bin.tar.gz; fi
|
||||
- export PATH=$PATH:$DOXY_BINPATH
|
||||
# Prepare devkitArm update
|
||||
- export DEVKITPRO=/home/travis/devkitPro
|
||||
- export DEVKITARM=${DEVKITPRO}/devkitARM
|
||||
- mkdir -p $DEVKITPRO
|
||||
- cd $DEVKITPRO
|
||||
- wget -N http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl
|
||||
-
|
||||
|
||||
install:
|
||||
- cd $DEVKITPRO
|
||||
# Install or update devkitArm if it's cached
|
||||
- perl devkitARMupdate.pl
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "BkEGbVRearmBLntY9WSuFkaiO2qAMMN43qocbkCL18dGbIDJA7vlUXXCKkahdsS5TU9j7xdcybCokmPBuvMCNRvQcDVwDcYbuh+ASmqG8Br1hphUScWPZNkcVSgTcHqNHh2k+05NP6d3vm3utOLgGZt/V5p+XcdGHti86KMeY34="
|
||||
|
||||
script:
|
||||
- cd $TRAVIS_BUILD_DIR/libctru
|
||||
- make
|
||||
|
||||
|
||||
after_success:
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- #Build the doxygen files and upload to GH pages
|
||||
- git config --global user.email "travis@travis-ci.org"
|
||||
- git config --global user.name "TravisCI-DocBuilder"
|
||||
# Build the doxygen documentation and push it to gh-pages if current branch is great-refactor
|
||||
- sh exportdoc.sh
|
429
Changelog.md
429
Changelog.md
@ -1,434 +1,5 @@
|
||||
# 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:
|
||||
|
10
README.md
10
README.md
@ -1,26 +1,18 @@
|
||||
# libctru - CTR User Library
|
||||
|
||||

|
||||
|
||||
Library for writing user mode ARM11 code for the 3DS (CTR)
|
||||
|
||||
This library aims to provide the foundations necessary to write 3DS Homebrew, and straightforwardly access the different functionalities provided by the 3DS operating system.
|
||||
It is not meant to provide higher level functions; to put things in perspective, the purpose of libctru would be to sit between the OS and a possible port of SDL rather than replace it.
|
||||
|
||||
*(Originally located at github.com/smealum/ctrulib)*
|
||||
|
||||
# Setup
|
||||
|
||||
libctru is just a library and needs a toolchain to function. devkitARM (created by [devkitPro](http://devkitpro.org)) is the officially supported ARM cross compiling toolchain, which provides the framework necessary to supply a usable POSIX-like environment, with working C and C++ standard libraries; as well as the tools required to compile homebrew in the 3DSX format, and assemble GPU shaders. The use of other ARM toolchains is severely discouraged.
|
||||
|
||||
The most recent version of devkitARM 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.
|
||||
The most recent version of devkitARM (r45 at the time of writing) is always recommended. The installers/setup scripts supplied by devkitPro install a prebuilt copy of the latest stable version of libctru, which is recommended for general use. Please note that devkitPro has a policy of keeping legacy code to a minimum, so a library upgrade may result in older code failing to compile or behave properly. Developers are encouraged to keep their code working with the latest versions of the tools and libraries.
|
||||
|
||||
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
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
|
3
examples/.gitignore
vendored
Normal file
3
examples/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
build/
|
||||
*.3dsx
|
||||
*.elf
|
26
examples/Makefile
Normal file
26
examples/Makefile
Normal 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 *
|
196
examples/app_launch/Makefile
Normal file
196
examples/app_launch/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
9
examples/app_launch/README.md
Normal file
9
examples/app_launch/README.md
Normal 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.
|
||||
|
49
examples/app_launch/source/main.c
Normal file
49
examples/app_launch/source/main.c
Normal 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(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(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;
|
||||
}
|
196
examples/audio/mic/Makefile
Normal file
196
examples/audio/mic/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
5
examples/audio/mic/README.md
Normal file
5
examples/audio/mic/README.md
Normal 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.
|
||||
|
102
examples/audio/mic/source/main.c
Normal file
102
examples/audio/mic/source/main.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <3ds.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
|
||||
bool initialized = true;
|
||||
|
||||
u32 micbuf_size = 0x30000;
|
||||
u32 micbuf_pos = 0;
|
||||
u8* micbuf = memalign(0x1000, micbuf_size);
|
||||
|
||||
printf("Initializing CSND...\n");
|
||||
if(R_FAILED(csndInit()))
|
||||
{
|
||||
initialized = false;
|
||||
printf("Could not initialize CSND.\n");
|
||||
} else printf("CSND initialized.\n");
|
||||
|
||||
printf("Initializing MIC...\n");
|
||||
if(R_FAILED(micInit(micbuf, micbuf_size)))
|
||||
{
|
||||
initialized = false;
|
||||
printf("Could not initialize MIC.\n");
|
||||
} else printf("MIC initialized.\n");
|
||||
|
||||
u32 micbuf_datasize = micGetSampleDataSize();
|
||||
|
||||
u32 audiobuf_size = 0x100000;
|
||||
u32 audiobuf_pos = 0;
|
||||
u8* audiobuf = linearAlloc(audiobuf_size);
|
||||
|
||||
if(initialized) printf("Hold A to record, release to play.\n");
|
||||
printf("Press START to exit.\n");
|
||||
|
||||
while(aptMainLoop())
|
||||
{
|
||||
hidScanInput();
|
||||
gspWaitForVBlank();
|
||||
|
||||
u32 kDown = hidKeysDown();
|
||||
if (kDown & KEY_START)
|
||||
break; // break in order to return to hbmenu
|
||||
|
||||
if(initialized)
|
||||
{
|
||||
if(kDown & KEY_A)
|
||||
{
|
||||
audiobuf_pos = 0;
|
||||
micbuf_pos = 0;
|
||||
|
||||
printf("Stopping audio playback...\n");
|
||||
CSND_SetPlayState(0x8, 0);
|
||||
if(R_FAILED(CSND_UpdateInfo(0))) printf("Failed to stop audio playback.\n");
|
||||
|
||||
printf("Starting sampling...\n");
|
||||
if(R_SUCCEEDED(MICU_StartSampling(MICU_ENCODING_PCM16_SIGNED, MICU_SAMPLE_RATE_16360, 0, micbuf_datasize, true))) printf("Now recording.\n");
|
||||
else printf("Failed to start sampling.\n");
|
||||
}
|
||||
|
||||
if((hidKeysHeld() & KEY_A) && audiobuf_pos < audiobuf_size)
|
||||
{
|
||||
u32 micbuf_readpos = micbuf_pos;
|
||||
micbuf_pos = micGetLastSampleOffset();
|
||||
while(audiobuf_pos < audiobuf_size && micbuf_readpos != micbuf_pos)
|
||||
{
|
||||
audiobuf[audiobuf_pos] = micbuf[micbuf_readpos];
|
||||
audiobuf_pos++;
|
||||
micbuf_readpos = (micbuf_readpos + 1) % micbuf_datasize;
|
||||
}
|
||||
}
|
||||
|
||||
if(hidKeysUp() & KEY_A)
|
||||
{
|
||||
printf("Stoping sampling...\n");
|
||||
if(R_FAILED(MICU_StopSampling())) printf("Failed to stop sampling.\n");
|
||||
|
||||
printf("Starting audio playback...\n");
|
||||
if(R_SUCCEEDED(GSPGPU_FlushDataCache(audiobuf, audiobuf_pos)) && R_SUCCEEDED(csndPlaySound(0x8, SOUND_ONE_SHOT | SOUND_FORMAT_16BIT, 16360, 1.0, 0.0, (u32*)audiobuf, NULL, audiobuf_pos))) printf("Now playing.\n");
|
||||
else printf("Failed to start playback.\n");
|
||||
}
|
||||
}
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
|
||||
linearFree(audiobuf);
|
||||
|
||||
micExit();
|
||||
free(micbuf);
|
||||
|
||||
csndExit();
|
||||
gfxExit();
|
||||
return 0;
|
||||
}
|
||||
|
196
examples/camera/image/Makefile
Normal file
196
examples/camera/image/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
7
examples/camera/image/README.md
Normal file
7
examples/camera/image/README.md
Normal 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.
|
||||
|
3
examples/camera/image/image.xml
Normal file
3
examples/camera/image/image.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<targets selectable="false">
|
||||
<title mediatype="0">0004001000021400</title>
|
||||
</targets>
|
190
examples/camera/image/src/main.c
Normal file
190
examples/camera/image/src/main.c
Normal 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;
|
||||
}
|
196
examples/camera/video/Makefile
Normal file
196
examples/camera/video/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
7
examples/camera/video/README.md
Normal file
7
examples/camera/video/README.md
Normal 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.
|
||||
|
206
examples/camera/video/src/main.c
Normal file
206
examples/camera/video/src/main.c
Normal 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;
|
||||
}
|
3
examples/camera/video/video.xml
Normal file
3
examples/camera/video/video.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<targets selectable="false">
|
||||
<title mediatype="0">0004001000021400</title>
|
||||
</targets>
|
196
examples/get_system_language/Makefile
Normal file
196
examples/get_system_language/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
4
examples/get_system_language/README.md
Normal file
4
examples/get_system_language/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
get_system_language
|
||||
=======
|
||||
|
||||
This is an example on how to get the system language on the 3DS.
|
46
examples/get_system_language/source/main.c
Normal file
46
examples/get_system_language/source/main.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <3ds.h>
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Initialize services
|
||||
gfxInitDefault();
|
||||
cfguInit();
|
||||
|
||||
|
||||
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
|
||||
cfguExit();
|
||||
gfxExit();
|
||||
return 0;
|
||||
}
|
7
examples/graphics/Makefile
Normal file
7
examples/graphics/Makefile
Normal 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;
|
193
examples/graphics/bitmap/24bit-color/Makefile
Normal file
193
examples/graphics/bitmap/24bit-color/Makefile
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
16
examples/graphics/bitmap/24bit-color/README.md
Normal file
16
examples/graphics/bitmap/24bit-color/README.md
Normal 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.
|
BIN
examples/graphics/bitmap/24bit-color/gfx/brew.png
Normal file
BIN
examples/graphics/bitmap/24bit-color/gfx/brew.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 138 KiB |
64
examples/graphics/bitmap/24bit-color/source/main.c
Normal file
64
examples/graphics/bitmap/24bit-color/source/main.c
Normal 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;
|
||||
}
|
7
examples/graphics/gpu/Makefile
Normal file
7
examples/graphics/gpu/Makefile
Normal 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;
|
177
examples/graphics/gpu/geoshader/Makefile
Normal file
177
examples/graphics/gpu/geoshader/Makefile
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
6
examples/graphics/gpu/geoshader/README.md
Normal file
6
examples/graphics/gpu/geoshader/README.md
Normal 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
|
172
examples/graphics/gpu/geoshader/source/3dmath.c
Normal file
172
examples/graphics/gpu/geoshader/source/3dmath.c
Normal 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);
|
||||
}
|
56
examples/graphics/gpu/geoshader/source/3dmath.h
Normal file
56
examples/graphics/gpu/geoshader/source/3dmath.h
Normal 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);
|
94
examples/graphics/gpu/geoshader/source/gpu.c
Normal file
94
examples/graphics/gpu/geoshader/source/gpu.c
Normal file
@ -0,0 +1,94 @@
|
||||
#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_MemoryFill(
|
||||
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(depthBuf),
|
||||
(u32*)osConvertVirtToPhys(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();
|
||||
gspWaitForP3D(); // Wait for the rendering to complete
|
||||
|
||||
// Transfer the GPU output to the framebuffer
|
||||
GX_DisplayTransfer(
|
||||
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);
|
||||
}
|
26
examples/graphics/gpu/geoshader/source/gpu.h
Normal file
26
examples/graphics/gpu/geoshader/source/gpu.h
Normal 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);
|
||||
}
|
91
examples/graphics/gpu/geoshader/source/gshader.pica
Normal file
91
examples/graphics/gpu/geoshader/source/gshader.pica
Normal 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
|
139
examples/graphics/gpu/geoshader/source/main.c
Normal file
139
examples/graphics/gpu/geoshader/source/main.c
Normal 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(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_GEOMETRY_PRIM allows the geoshader to control primitive emission
|
||||
GPU_DrawArray(GPU_GEOMETRY_PRIM, 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;
|
||||
}
|
24
examples/graphics/gpu/geoshader/source/vshader.pica
Normal file
24
examples/graphics/gpu/geoshader/source/vshader.pica
Normal 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
|
177
examples/graphics/gpu/simple_tri/Makefile
Normal file
177
examples/graphics/gpu/simple_tri/Makefile
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
6
examples/graphics/gpu/simple_tri/README.md
Normal file
6
examples/graphics/gpu/simple_tri/README.md
Normal 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
|
172
examples/graphics/gpu/simple_tri/source/3dmath.c
Normal file
172
examples/graphics/gpu/simple_tri/source/3dmath.c
Normal 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);
|
||||
}
|
56
examples/graphics/gpu/simple_tri/source/3dmath.h
Normal file
56
examples/graphics/gpu/simple_tri/source/3dmath.h
Normal 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);
|
94
examples/graphics/gpu/simple_tri/source/gpu.c
Normal file
94
examples/graphics/gpu/simple_tri/source/gpu.c
Normal file
@ -0,0 +1,94 @@
|
||||
#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_MemoryFill(
|
||||
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(depthBuf),
|
||||
(u32*)osConvertVirtToPhys(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();
|
||||
gspWaitForP3D(); // Wait for the rendering to complete
|
||||
|
||||
// Transfer the GPU output to the framebuffer
|
||||
GX_DisplayTransfer(
|
||||
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);
|
||||
}
|
26
examples/graphics/gpu/simple_tri/source/gpu.h
Normal file
26
examples/graphics/gpu/simple_tri/source/gpu.h
Normal 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);
|
||||
}
|
131
examples/graphics/gpu/simple_tri/source/main.c
Normal file
131
examples/graphics/gpu/simple_tri/source/main.c
Normal 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;
|
||||
}
|
34
examples/graphics/gpu/simple_tri/source/vshader.pica
Normal file
34
examples/graphics/gpu/simple_tri/source/vshader.pica
Normal 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
|
177
examples/graphics/gpu/textured_cube/Makefile
Normal file
177
examples/graphics/gpu/textured_cube/Makefile
Normal 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
|
||||
#---------------------------------------------------------------------------------------
|
6
examples/graphics/gpu/textured_cube/README.md
Normal file
6
examples/graphics/gpu/textured_cube/README.md
Normal 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
|
BIN
examples/graphics/gpu/textured_cube/data/kitten.bin
Normal file
BIN
examples/graphics/gpu/textured_cube/data/kitten.bin
Normal file
Binary file not shown.
172
examples/graphics/gpu/textured_cube/source/3dmath.c
Normal file
172
examples/graphics/gpu/textured_cube/source/3dmath.c
Normal 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);
|
||||
}
|
56
examples/graphics/gpu/textured_cube/source/3dmath.h
Normal file
56
examples/graphics/gpu/textured_cube/source/3dmath.h
Normal 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);
|
94
examples/graphics/gpu/textured_cube/source/gpu.c
Normal file
94
examples/graphics/gpu/textured_cube/source/gpu.c
Normal file
@ -0,0 +1,94 @@
|
||||
#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_MemoryFill(
|
||||
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(depthBuf),
|
||||
(u32*)osConvertVirtToPhys(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();
|
||||
gspWaitForP3D(); // Wait for the rendering to complete
|
||||
|
||||
// Transfer the GPU output to the framebuffer
|
||||
GX_DisplayTransfer(
|
||||
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);
|
||||
}
|
26
examples/graphics/gpu/textured_cube/source/gpu.h
Normal file
26
examples/graphics/gpu/textured_cube/source/gpu.h
Normal 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);
|
||||
}
|
244
examples/graphics/gpu/textured_cube/source/main.c
Normal file
244
examples/graphics/gpu/textured_cube/source/main.c
Normal 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(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(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;
|
||||
}
|
90
examples/graphics/gpu/textured_cube/source/vshader.pica
Normal file
90
examples/graphics/gpu/textured_cube/source/vshader.pica
Normal 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
|
7
examples/graphics/printing/Makefile
Normal file
7
examples/graphics/printing/Makefile
Normal 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;
|
196
examples/graphics/printing/both-screen-text/Makefile
Normal file
196
examples/graphics/printing/both-screen-text/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
57
examples/graphics/printing/both-screen-text/source/main.c
Normal file
57
examples/graphics/printing/both-screen-text/source/main.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
196
examples/graphics/printing/colored-text/Makefile
Normal file
196
examples/graphics/printing/colored-text/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
69
examples/graphics/printing/colored-text/source/main.c
Normal file
69
examples/graphics/printing/colored-text/source/main.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
196
examples/graphics/printing/hello-world/Makefile
Normal file
196
examples/graphics/printing/hello-world/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
46
examples/graphics/printing/hello-world/source/main.c
Normal file
46
examples/graphics/printing/hello-world/source/main.c
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
196
examples/graphics/printing/multiple-windows-text/Makefile
Normal file
196
examples/graphics/printing/multiple-windows-text/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
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
|
||||
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
196
examples/http/Makefile
Normal file
196
examples/http/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
4
examples/http/README.md
Normal file
4
examples/http/README.md
Normal 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
113
examples/http/source/main.c
Normal 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
7
examples/input/Makefile
Normal 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;
|
196
examples/input/read-controls/Makefile
Normal file
196
examples/input/read-controls/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
105
examples/input/read-controls/source/main.c
Normal file
105
examples/input/read-controls/source/main.c
Normal 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;
|
||||
}
|
196
examples/input/touch-screen/Makefile
Normal file
196
examples/input/touch-screen/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
60
examples/input/touch-screen/source/main.c
Normal file
60
examples/input/touch-screen/source/main.c
Normal 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;
|
||||
}
|
196
examples/libapplet_launch/Makefile
Normal file
196
examples/libapplet_launch/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
7
examples/libapplet_launch/README.md
Normal file
7
examples/libapplet_launch/README.md
Normal 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.
|
||||
|
45
examples/libapplet_launch/source/main.c
Normal file
45
examples/libapplet_launch/source/main.c
Normal 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;
|
||||
}
|
196
examples/mvd/Makefile
Normal file
196
examples/mvd/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
1
examples/mvd/README.md
Normal file
1
examples/mvd/README.md
Normal 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).
|
6
examples/mvd/source/costable.h
Normal file
6
examples/mvd/source/costable.h
Normal 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
143
examples/mvd/source/main.c
Normal 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);
|
||||
|
||||
MVDSTD_Config 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(inaddr, 0x46500);
|
||||
|
||||
printstring("mvd example\n");
|
||||
|
||||
ret = mvdstdInit(MVDMODE_COLORFORMATCONV, MVD_INPUT_YUYV422, MVD_OUTPUT_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(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);
|
||||
|
||||
mvdstdExit();
|
||||
|
||||
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;
|
||||
}
|
||||
|
196
examples/qtm/Makefile
Normal file
196
examples/qtm/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
6
examples/qtm/README.md
Normal file
6
examples/qtm/README.md
Normal 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.
|
||||
|
85
examples/qtm/source/main.c
Normal file
85
examples/qtm/source/main.c
Normal 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;
|
||||
QTM_HeadTrackingInfo 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 = QTM_GetHeadTrackingInfo(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;
|
||||
}
|
||||
|
196
examples/romfs/Makefile
Normal file
196
examples/romfs/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
6
examples/romfs/romfs/folder/file.txt
Normal file
6
examples/romfs/romfs/folder/file.txt
Normal 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
|
2
examples/romfs/romfs/フォルダ/ファイル.txt
Normal file
2
examples/romfs/romfs/フォルダ/ファイル.txt
Normal file
@ -0,0 +1,2 @@
|
||||
The path to this file contains UTF-16
|
||||
characters that fall outside ASCII.
|
58
examples/romfs/source/main.c
Normal file
58
examples/romfs/source/main.c
Normal 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;
|
||||
}
|
196
examples/sdmc/Makefile
Normal file
196
examples/sdmc/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
5
examples/sdmc/README.md
Normal file
5
examples/sdmc/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
sdmc
|
||||
=======
|
||||
|
||||
very simple example of how to access SD files with libctru;
|
||||
|
50
examples/sdmc/source/costable.c
Normal file
50
examples/sdmc/source/costable.c
Normal 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};
|
6
examples/sdmc/source/costable.h
Normal file
6
examples/sdmc/source/costable.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef COSTABLE_H
|
||||
#define COSTABLE_H
|
||||
|
||||
extern s32 costable[];
|
||||
|
||||
#endif
|
98
examples/sdmc/source/main.c
Normal file
98
examples/sdmc/source/main.c
Normal 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(GSPGPU_EVENT_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
1
examples/sdmc/test.bin
Normal file
File diff suppressed because one or more lines are too long
7
examples/templates/Makefile
Normal file
7
examples/templates/Makefile
Normal 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;
|
196
examples/templates/application/Makefile
Normal file
196
examples/templates/application/Makefile
Normal file
@ -0,0 +1,196 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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)/*.v.pica)))
|
||||
SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist)))
|
||||
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:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.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
|
||||
|
||||
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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# rules for assembling GPU shaders
|
||||
#---------------------------------------------------------------------------------
|
||||
define shader-as
|
||||
$(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@)))
|
||||
picasso -o $(CURBIN) $1
|
||||
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
|
||||
endef
|
||||
|
||||
%.shbin.o : %.v.pica %.g.pica
|
||||
@echo $(notdir $^)
|
||||
@$(call shader-as,$^)
|
||||
|
||||
%.shbin.o : %.v.pica
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$<)
|
||||
|
||||
%.shbin.o : %.shlist
|
||||
@echo $(notdir $<)
|
||||
@$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
3
examples/templates/application/README.md
Normal file
3
examples/templates/application/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# template
|
||||
|
||||
This is a template for starting new 3DS libctru projects.
|
37
examples/templates/application/source/main.c
Normal file
37
examples/templates/application/source/main.c
Normal 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;
|
||||
}
|
122
examples/templates/library/Makefile
Normal file
122
examples/templates/library/Makefile
Normal file
@ -0,0 +1,122 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.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 -mtp=soft
|
||||
|
||||
CFLAGS := -g -Wall -O2 -mword-relocations \
|
||||
-fomit-frame-pointer -ffunction-sections \
|
||||
$(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
|
||||
#---------------------------------------------------------------------------------------
|
3
examples/templates/library/README.md
Normal file
3
examples/templates/library/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# template
|
||||
|
||||
This is a template for starting new 3DS library projects.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user