### Initialize and Use Socket Networking with libctru Source: https://context7.com/devkitpro/libctru/llms.txt Initializes the SOC service with a provided buffer and size, enabling BSD-style socket networking. Demonstrates getting local IP info, performing DNS lookups, and establishing a basic TCP connection. ```c #include <3ds.h> #include #include #include #include #include #include #include #define SOC_ALIGN 0x1000 #define SOC_BUFFERSIZE 0x100000 static u32* socBuffer; int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // Allocate buffer for SOC service socBuffer = (u32*)memalign(SOC_ALIGN, SOC_BUFFERSIZE); if (!socBuffer) { printf("Failed to allocate SOC buffer\n"); return 1; } Result res = socInit(socBuffer, SOC_BUFFERSIZE); if (R_FAILED(res)) { printf("socInit failed: %08lX\n", res); free(socBuffer); return 1; } // Get local IP info struct in_addr ip, netmask, broadcast; SOCU_GetIPInfo(&ip, &netmask, &broadcast); printf("IP: %s\n", inet_ntoa(ip)); printf("Netmask: %s\n", inet_ntoa(netmask)); // DNS lookup example struct hostent* host = gethostbyname("example.com"); if (host) { printf("\nexample.com resolves to:\n"); for (int i = 0; host->h_addr_list[i]; i++) { struct in_addr addr; memcpy(&addr, host->h_addr_list[i], sizeof(addr)); printf(" %s\n", inet_ntoa(addr)); } } // Simple TCP connection example int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock >= 0) { struct sockaddr_in server; server.sin_family = AF_INET; server.sin_port = htons(80); server.sin_addr = *(struct in_addr*)host->h_addr_list[0]; if (connect(sock, (struct sockaddr*)&server, sizeof(server)) == 0) { const char* request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n"; send(sock, request, strlen(request), 0); char buffer[1024]; int received = recv(sock, buffer, sizeof(buffer) - 1, 0); if (received > 0) { buffer[received] = '\0'; printf("\nResponse (first %d bytes):\n%.200s...\n", received, buffer); } } close(sock); } printf("\nPress START to exit\n"); while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } socExit(); free(socBuffer); gfxExit(); return 0; } ``` -------------------------------- ### Perform HTTP GET Request with libctru Source: https://context7.com/devkitpro/libctru/llms.txt Initializes the HTTP client service and performs a GET request to a specified URL. Handles response status, downloads content, and frees allocated memory. Requires httpcInit before use and httpcExit upon completion. ```c #include <3ds.h> #include #include #include Result httpGet(const char* url, u8** outData, u32* outSize) { httpcContext context; Result res; res = httpcOpenContext(&context, HTTPC_METHOD_GET, url, 0); if (R_FAILED(res)) return res; // Add headers httpcAddRequestHeaderField(&context, "User-Agent", "3DS-Homebrew/1.0"); httpcAddRequestHeaderField(&context, "Connection", "close"); // Start request res = httpcBeginRequest(&context); if (R_FAILED(res)) { httpcCloseContext(&context); return res; } // Get response code u32 statusCode; res = httpcGetResponseStatusCode(&context, &statusCode); if (R_FAILED(res) || statusCode != 200) { httpcCloseContext(&context); return res; } // Get content size u32 contentSize; res = httpcGetDownloadSizeState(&context, NULL, &contentSize); // Download data u8* buffer = (u8*)malloc(contentSize + 1); u32 downloadedSize; res = httpcDownloadData(&context, buffer, contentSize, &downloadedSize); buffer[downloadedSize] = '\0'; *outData = buffer; *outSize = downloadedSize; httpcCloseContext(&context); return res; } int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // Initialize services Result res = httpcInit(0); if (R_FAILED(res)) { printf("httpcInit failed: %08lX\n", res); return 1; } printf("Fetching data...\n"); u8* data; u32 size; res = httpGet("http://example.com/", &data, &size); if (R_SUCCEEDED(res)) { printf("Downloaded %lu bytes:\n\n", size); // Print first 500 chars printf("%.500s...\n", (char*)data); free(data); } else { printf("Request failed: %08lX\n", res); } printf("\nPress START to exit\n"); while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } httpcExit(); gfxExit(); return 0; } ``` -------------------------------- ### IPC Header Parsing Example Output Source: https://github.com/devkitpro/libctru/wiki/IPC-command-headers This is an example output from the IPCParseHeader tool, demonstrating how a raw hexadecimal IPC header value is translated into its constituent parts: command ID, normal parameters, and translate parameters, along with the corresponding IPC_MakeHeader function call. ```text $>IPCParseHeader 0x080b0102 0x80B0102 => id: 0x80B normal: 4 translate: 2 IPC_MakeHeader(0x80B,4,2); // 0x80B0102 ``` -------------------------------- ### Initialize Graphics Subsystem (gfxInit) Source: https://context7.com/devkitpro/libctru/llms.txt Initializes the graphics subsystem for both screens with default or custom settings. Use this to set up framebuffers, enable stereoscopic 3D, and manage display modes. Requires including <3ds.h>. ```c #include <3ds.h> int main(int argc, char* argv[]) { // Initialize with default settings (BGR8 format, double buffering) gfxInitDefault(); // Alternative: Custom initialization with specific formats // gfxInit(GSP_RGBA8_OES, GSP_BGR8_OES, false); // Enable stereoscopic 3D on the top screen gfxSet3D(true); // Enable 800px wide mode (New 3DS only, non-square pixels) // gfxSetWide(true); // Main loop while (aptMainLoop()) { hidScanInput(); u32 kDown = hidKeysDown(); if (kDown & KEY_START) break; // Get framebuffer for rendering u16 width, height; u8* fb = gfxGetFramebuffer(GFX_TOP, GFX_LEFT, &width, &height); // Clear to black (framebuffer is in portrait orientation) memset(fb, 0, width * height * 3); // Flush and swap buffers gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } gfxExit(); return 0; } ``` -------------------------------- ### Initialize and use sockets in libctru Source: https://github.com/devkitpro/libctru/wiki/Networking Demonstrates the lifecycle of the SOC service, including memory allocation for the buffer and socket cleanup. ```c #include #include #include #include #include #include #include <3ds.h> int main() { // Initialize graphics and console gfxInitDefault(); gfxSet3D(false); consoleInit(GFX_BOTTOM, NULL); // Initialize SOC SOC_Initialize((u32*)memalign(0x1000, 0x128000), 0x128000); // Do networking stuff int sockfd = socket(AF_INET, SOCK_STREAM, 0); // ... close(sockfd); // Cleanup SOC SOC_Shutdown(); return 0 } ``` -------------------------------- ### Initialize Console Text Output (consoleInit) Source: https://context7.com/devkitpro/libctru/llms.txt Initializes a console for stdio-like text output on a specified screen, supporting ANSI color codes and cursor positioning. Requires including <3ds.h> and . ```c #include <3ds.h> #include int main(int argc, char* argv[]) { gfxInitDefault(); // Initialize console on bottom screen PrintConsole* console = consoleInit(GFX_BOTTOM, NULL); // Use ANSI color codes printf(CONSOLE_RED "Red text\n" CONSOLE_RESET); printf(CONSOLE_GREEN "Green text\n" CONSOLE_RESET); printf(CONSOLE_CYAN "Cyan text\n" CONSOLE_RESET); // Position cursor at row 10, column 5 printf("\x1b[10;5HPositioned text"); // Clear screen // consoleClear(); // Create a custom window region consoleSetWindow(console, 2, 2, 36, 20); printf("Text inside window region\n"); // Enable debug output to console consoleDebugInit(debugDevice_CONSOLE); fprintf(stderr, "Debug message\n"); while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } gfxExit(); return 0; } ``` -------------------------------- ### Initialize and Use Software Keyboard for Text Input Source: https://context7.com/devkitpro/libctru/llms.txt Initializes the software keyboard for normal text input, sets hint text and buttons, and captures user input. Handles both successful input and cancellation. ```c #include <3ds.h> #include #include int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); char inputBuffer[256]; // Basic text input SwkbdState swkbd; swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, 255); swkbdSetHintText(&swkbd, "Enter your name"); swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, "Cancel", false); swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, "OK", true); swkbdSetFeatures(&swkbd, SWKBD_PREDICTIVE_INPUT | SWKBD_DARKEN_TOP_SCREEN); SwkbdButton button = swkbdInputText(&swkbd, inputBuffer, sizeof(inputBuffer)); if (button == SWKBD_BUTTON_RIGHT) { printf("You entered: %s\n\n", inputBuffer); } else { printf("Input cancelled\n\n"); } // Numpad input SwkbdState numpad; swkbdInit(&numpad, SWKBD_TYPE_NUMPAD, 1, 4); swkbdSetHintText(&numpad, "Enter PIN"); swkbdSetPasswordMode(&numpad, SWKBD_PASSWORD_HIDE_DELAY); swkbdSetValidation(&numpad, SWKBD_FIXEDLEN, 0, 0); swkbdSetNumpadKeys(&numpad, '-', '.'); button = swkbdInputText(&numpad, inputBuffer, sizeof(inputBuffer)); if (button != SWKBD_BUTTON_NONE) { printf("PIN entered: %s\n\n", inputBuffer); } // Input with validation callback SwkbdState validated; swkbdInit(&validated, SWKBD_TYPE_QWERTY, 2, 32); swkbdSetHintText(&validated, "Enter email"); swkbdSetValidation(&validated, SWKBD_NOTEMPTY_NOTBLANK, SWKBD_FILTER_AT, 0); // Disallow @ (just for demo) button = swkbdInputText(&validated, inputBuffer, sizeof(inputBuffer)); SwkbdResult result = swkbdGetResult(&validated); if (result == SWKBD_BANNED_INPUT) { printf("Input was filtered!\n"); } else if (button != SWKBD_BUTTON_NONE) { printf("Email: %s\n", inputBuffer); } printf("\nPress START to exit\n"); while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } gfxExit(); return 0; } ``` -------------------------------- ### Create and Manage Threads with threadCreate Source: https://context7.com/devkitpro/libctru/llms.txt Demonstrates spawning worker threads, using LightLock for thread-safe data access, and cleaning up resources with threadJoin and threadFree. ```c #include <3ds.h> #include volatile bool threadRunning = true; volatile int counter = 0; LightLock counterLock; void workerThread(void* arg) { int threadId = (int)(intptr_t)arg; while (threadRunning) { LightLock_Lock(&counterLock); counter++; int localCounter = counter; LightLock_Unlock(&counterLock); // Simulate work svcSleepThread(100000000LL); // 100ms } threadExit(threadId); // Exit with thread ID as return code } int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); LightLock_Init(&counterLock); // Create worker thread // Priority 0x30 is standard, lower = higher priority // Core -2 = default core from exheader Thread thread1 = threadCreate(workerThread, (void*)1, 4 * 1024, 0x30, -2, false); Thread thread2 = threadCreate(workerThread, (void*)2, 4 * 1024, 0x30, -2, false); if (!thread1 || !thread2) { printf("Failed to create threads\n"); return 1; } printf("Threads created\n"); printf("Press START to stop\n\n"); while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; LightLock_Lock(&counterLock); printf("\x1b[5;1HCounter: %d ", counter); LightLock_Unlock(&counterLock); gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } // Signal threads to stop threadRunning = false; // Wait for threads to finish threadJoin(thread1, U64_MAX); threadJoin(thread2, U64_MAX); // Get exit codes printf("\nThread 1 exit code: %d\n", threadGetExitCode(thread1)); printf("Thread 2 exit code: %d\n", threadGetExitCode(thread2)); // Clean up threadFree(thread1); threadFree(thread2); gfxExit(); return 0; } ``` -------------------------------- ### Filesystem Operations with libctru Source: https://context7.com/devkitpro/libctru/llms.txt Demonstrates file operations using both standard C I/O (sdmc:/) and low-level FSUSER APIs. Ensure the filesystem service is initialized or auto-initialized. ```c #include <3ds.h> #include #include int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // FS is auto-initialized, but can be explicit // fsInit(); // Method 1: Using standard C file I/O (sdmc:/ device) FILE* file = fopen("sdmc:/test.txt", "w"); if (file) { fprintf(file, "Hello from 3DS!\n"); fclose(file); printf("File written successfully\n"); } // Method 2: Using low-level FS API FS_Archive sdmcArchive; Result res = FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")); if (R_SUCCEEDED(res)) { Handle fileHandle; FS_Path filePath = fsMakePath(PATH_ASCII, "/data.bin"); // Create and write file res = FSUSER_OpenFile(&fileHandle, sdmcArchive, filePath, FS_OPEN_CREATE | FS_OPEN_WRITE, 0); if (R_SUCCEEDED(res)) { const char* data = "Binary data"; u32 bytesWritten; FSFILE_Write(fileHandle, &bytesWritten, 0, data, strlen(data), FS_WRITE_FLUSH); FSFILE_Close(fileHandle); printf("Wrote %lu bytes\n", bytesWritten); } // Read file res = FSUSER_OpenFile(&fileHandle, sdmcArchive, filePath, FS_OPEN_READ, 0); if (R_SUCCEEDED(res)) { char buffer[256]; u32 bytesRead; FSFILE_Read(fileHandle, &bytesRead, 0, buffer, sizeof(buffer)); FSFILE_Close(fileHandle); buffer[bytesRead] = '\0'; printf("Read: %s\n", buffer); } // Get SD card free space u64 freeBytes; FSUSER_GetFreeBytes(&freeBytes, sdmcArchive); printf("Free space: %llu MB\n", freeBytes / (1024 * 1024)); FSUSER_CloseArchive(sdmcArchive); } while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } gfxExit(); return 0; } ``` -------------------------------- ### Implement Synchronization with Lightweight Primitives Source: https://context7.com/devkitpro/libctru/llms.txt Shows usage of LightLock, CondVar, LightEvent, and LightSemaphore to coordinate threads without consuming kernel handles. ```c #include <3ds.h> #include LightLock mutex; RecursiveLock recursiveMutex; CondVar condVar; LightEvent event; LightSemaphore semaphore; void producerThread(void* arg) { for (int i = 0; i < 5; i++) { svcSleepThread(500000000LL); // 500ms LightLock_Lock(&mutex); printf("Producer: item %d ready\n", i); CondVar_Signal(&condVar); LightLock_Unlock(&mutex); } // Signal completion LightEvent_Signal(&event); threadExit(0); } void consumerThread(void* arg) { for (int i = 0; i < 5; i++) { LightLock_Lock(&mutex); CondVar_Wait(&condVar, &mutex); printf("Consumer: got item %d\n", i); LightLock_Unlock(&mutex); } threadExit(0); } int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // Initialize synchronization primitives LightLock_Init(&mutex); RecursiveLock_Init(&recursiveMutex); CondVar_Init(&condVar); LightEvent_Init(&event, RESET_ONESHOT); LightSemaphore_Init(&semaphore, 3, 3); // 3 permits // Demonstrate semaphore printf("Semaphore demo:\n"); LightSemaphore_Acquire(&semaphore, 1); printf("Acquired 1 permit\n"); LightSemaphore_Acquire(&semaphore, 2); printf("Acquired 2 permits\n"); if (LightSemaphore_TryAcquire(&semaphore, 1) != 0) { printf("Cannot acquire more (expected)\n"); } LightSemaphore_Release(&semaphore, 3); printf("Released all permits\n\n"); // Producer-consumer demo printf("Producer-Consumer demo:\n"); Thread producer = threadCreate(producerThread, NULL, 4 * 1024, 0x30, -2, false); Thread consumer = threadCreate(consumerThread, NULL, 4 * 1024, 0x30, -2, false); // Wait for producer to signal completion LightEvent_Wait(&event); printf("\nProduction complete!\n"); threadJoin(producer, U64_MAX); threadJoin(consumer, U64_MAX); threadFree(producer); threadFree(consumer); printf("\nPress START to exit\n"); while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } gfxExit(); return 0; } ``` -------------------------------- ### Mount and Access RomFS Files Source: https://context7.com/devkitpro/libctru/llms.txt Initializes RomFS, mounts the application's RomFS, reads a file, and lists directory contents. Ensure RomFS is properly embedded in your application. ```c #include <3ds.h> #include #include int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // Mount the application's RomFS as "romfs:/" Result res = romfsInit(); if (R_FAILED(res)) { printf("romfsInit failed: %08lX\n", res); } else { printf("RomFS mounted successfully\n\n"); // Read a file from RomFS FILE* file = fopen("romfs:/data/config.txt", "r"); if (file) { char buffer[256]; while (fgets(buffer, sizeof(buffer), file)) { printf("%s", buffer); } fclose(file); } // List directory contents DIR* dir = opendir("romfs:/"); if (dir) { printf("\nRomFS contents:\n"); struct dirent* entry; while ((entry = readdir(dir)) != NULL) { printf(" %s%s\n", entry->d_name, entry->d_type == DT_DIR ? "/" : ""); } closedir(dir); } // Mount RomFS from another title // romfsMountFromTitle(0x0004000000001234ULL, MEDIATYPE_SD, "other"); // FILE* f = fopen("other:/file.txt", "r"); romfsExit(); } while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } gfxExit(); return 0; } ``` -------------------------------- ### Play a 440Hz Tone with NDSP Source: https://context7.com/devkitpro/libctru/llms.txt Initializes NDSP, configures audio channels, and plays a continuous 440Hz sine wave tone. Requires linear memory allocation for audio buffers. ```c #include <3ds.h> #include #include #define SAMPLE_RATE 22050 #define SAMPLES_PER_BUF (SAMPLE_RATE / 30) s16* audioBuffer; ndspWaveBuf waveBuf[2]; int fillBlock = 0; void fillAudioBuffer(s16* buffer, size_t samples) { static float phase = 0; float freq = 440.0f; // A4 note for (size_t i = 0; i < samples; i++) { buffer[i] = (s16)(sinf(phase) * 0x7000); phase += 2.0f * M_PI * freq / SAMPLE_RATE; if (phase > 2.0f * M_PI) phase -= 2.0f * M_PI; } DSP_FlushDataCache(buffer, samples * sizeof(s16)); } int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // Initialize NDSP Result res = ndspInit(); if (R_FAILED(res)) { printf("ndspInit failed: %08lX\n", res); return 1; } // Allocate audio buffer in linear memory audioBuffer = (s16*)linearAlloc(SAMPLES_PER_BUF * sizeof(s16) * 2); // Configure NDSP ndspSetOutputMode(NDSP_OUTPUT_STEREO); ndspSetMasterVol(1.0f); // Configure channel 0 ndspChnReset(0); ndspChnSetInterp(0, NDSP_INTERP_LINEAR); ndspChnSetRate(0, SAMPLE_RATE); ndspChnSetFormat(0, NDSP_FORMAT_MONO_PCM16); // Set channel volume (left, right, etc.) float mix[12] = {1.0f, 1.0f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ndspChnSetMix(0, mix); // Initialize wave buffers memset(waveBuf, 0, sizeof(waveBuf)); waveBuf[0].data_vaddr = audioBuffer; waveBuf[0].nsamples = SAMPLES_PER_BUF; waveBuf[1].data_vaddr = audioBuffer + SAMPLES_PER_BUF; waveBuf[1].nsamples = SAMPLES_PER_BUF; // Fill initial buffers fillAudioBuffer(audioBuffer, SAMPLES_PER_BUF); fillAudioBuffer(audioBuffer + SAMPLES_PER_BUF, SAMPLES_PER_BUF); // Queue both buffers ndspChnWaveBufAdd(0, &waveBuf[0]); ndspChnWaveBufAdd(0, &waveBuf[1]); printf("Playing 440Hz tone\n"); printf("Press START to exit\n"); while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; // Refill completed buffers if (waveBuf[fillBlock].status == NDSP_WBUF_DONE) { fillAudioBuffer((s16*)waveBuf[fillBlock].data_vaddr, SAMPLES_PER_BUF); ndspChnWaveBufAdd(0, &waveBuf[fillBlock]); fillBlock = !fillBlock; } gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } ndspChnWaveBufClear(0); linearFree(audioBuffer); ndspExit(); gfxExit(); return 0; } ``` -------------------------------- ### Register APT Hook for System Events Source: https://context7.com/devkitpro/libctru/llms.txt Registers a callback function to handle APT events like suspend, restore, sleep, and wake-up. Ensures the hook is unregistered before exiting. ```c #include <3ds.h> #include // Hook callback for APT events void aptHookCallback(APT_HookType hookType, void* param) { switch (hookType) { case APTHOOK_ONSUSPEND: printf("App suspended\n"); break; case APTHOOK_ONRESTORE: printf("App restored\n"); break; case APTHOOK_ONSLEEP: printf("System sleeping\n"); break; case APTHOOK_ONWAKEUP: printf("System woke up\n"); break; case APTHOOK_ONEXIT: printf("App exiting\n"); break; default: break; } } int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // Register APT hook aptHookCookie cookie; aptHook(&cookie, aptHookCallback, NULL); // Configure sleep behavior aptSetSleepAllowed(true); // Allow HOME button (can be disabled for critical operations) aptSetHomeAllowed(true); // Check if running on New 3DS bool isNew3DS = false; APT_CheckNew3DS(&isNew3DS); printf("Running on %s 3DS\n", isNew3DS ? "New" : "Old"); // Set CPU time limit (for using system core) // APT_SetAppCpuTimeLimit(30); // 30% of system core printf("\nAPT demo - Press START to exit\n"); printf("Try pressing HOME button\n"); while (aptMainLoop()) { hidScanInput(); u32 kDown = hidKeysDown(); if (kDown & KEY_START) break; // Check various APT states if (aptCheckHomePressRejected()) { printf("HOME press was blocked\n"); } // Active state check printf("\x1b[8;1HApp active: %s ", aptIsActive() ? "yes" : "no"); gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } // Unhook before exit aptUnhook(&cookie); gfxExit(); return 0; } ``` -------------------------------- ### Allocate and manage hardware-accessible memory in C Source: https://context7.com/devkitpro/libctru/llms.txt Demonstrates the usage of linearAlloc, vramAlloc, and mappableAlloc for hardware-specific memory requirements. Always flush the data cache before GPU access when using linear memory. ```c #include <3ds.h> #include #include int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // Allocate linear memory (for GPU textures, audio buffers, etc.) size_t size = 256 * 256 * 4; // RGBA texture void* linearBuffer = linearAlloc(size); if (linearBuffer) { printf("Linear buffer allocated: %p\n", linearBuffer); printf("Size: %zu bytes\n", linearGetSize(linearBuffer)); // Get physical address (needed for GPU commands) u32 physAddr = osConvertVirtToPhys(linearBuffer); printf("Physical address: %08lX\n", physAddr); // Use the memory memset(linearBuffer, 0xFF, size); // Flush data cache before GPU access GSPGPU_FlushDataCache(linearBuffer, size); linearFree(linearBuffer); printf("Linear buffer freed\n\n"); } // Allocate VRAM (video memory for framebuffers/textures) void* vramBuffer = vramAlloc(64 * 64 * 2); // RGB565 texture if (vramBuffer) { printf("VRAM buffer allocated: %p\n", vramBuffer); printf("VRAM size: %zu bytes\n", vramGetSize(vramBuffer)); vramFree(vramBuffer); printf("VRAM buffer freed\n\n"); } // Allocate mappable memory (for shared memory with services) void* mappableBuffer = mappableAlloc(0x1000); if (mappableBuffer) { printf("Mappable buffer allocated: %p\n", mappableBuffer); mappableFree(mappableBuffer); printf("Mappable buffer freed\n"); } printf("\nPress START to exit\n"); while (aptMainLoop()) { hidScanInput(); if (hidKeysDown() & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } gfxExit(); return 0; } ``` -------------------------------- ### Parse and Create IPC Command Headers (C) Source: https://github.com/devkitpro/libctru/wiki/IPC-command-headers This C code defines the IPC_MakeHeader function for creating IPC command headers and includes a main function that parses a raw header value from command-line arguments, displays its components, and reconstructs it using IPC_MakeHeader. It also asserts that the parsed components correctly reconstruct the original header. ```c #include #include #include #include typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; /** * @brief Command header to be used for IPC * @param normal_params Size of the normal parameters in words. Up to 63. * @param translate_params Size of the translate parameters in words. Up to 63. * * Normal parameters are sent directly to the process while the translate parameters might go through modifications and checks by the kernel. * The translate parameters are described by headers generated with the IPC_Desc_* functions. * * @note While #normal_params is equivalent to the number of normal parameters, #translate_params includes the size occupied by the translate parameters headers. */ static inline u32 IPC_MakeHeader(u16 command_id, unsigned normal_params, unsigned translate_params) { return ((u32) command_id << 16) | (((u32) normal_params & 0x3F) << 6) | (((u32) translate_params & 0x3F) << 0); } int main(int argc, char* argv[]) { assert(argc == 2); unsigned header = (unsigned)strtol(argv[1], NULL, 0); unsigned id = header>>16; unsigned normal =header >> 6 & 0x3F; unsigned translate = header&0x3F; printf("0x%X =>\n" "\tid: 0x%X\n" "\tnormal: %d\n" "\ttranslate: %d\n" ,header,id,normal,translate ); printf("IPC_MakeHeader(0x%X,%d,%d); // 0x%X\n" ,id,normal,translate,header); assert(header == IPC_MakeHeader(id,normal,translate)); return 0; } ``` -------------------------------- ### Scan and Read Input with libctru Source: https://context7.com/devkitpro/libctru/llms.txt Scans and reads various input states including buttons, Circle Pad, touchscreen, accelerometer, and gyroscope. Ensure HID services are enabled and configured before use. ```c #include <3ds.h> #include int main(int argc, char* argv[]) { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); // Enable accelerometer and gyroscope HIDUSER_EnableAccelerometer(); HIDUSER_EnableGyroscope(); // Configure key repeat for menu navigation hidSetRepeatParameters(25, 5); while (aptMainLoop()) { hidScanInput(); // Get button states u32 kDown = hidKeysDown(); // Just pressed this frame u32 kHeld = hidKeysHeld(); // Currently held u32 kUp = hidKeysUp(); // Just released u32 kRepeat = hidKeysDownRepeat(); // With key repeat if (kDown & KEY_START) break; // Read Circle Pad position (-156 to +156 range) circlePosition circlePos; hidCircleRead(&circlePos); // Read touchscreen touchPosition touchPos; if (kHeld & KEY_TOUCH) { hidTouchRead(&touchPos); printf("\x1b[5;1HTouch: X=%3d Y=%3d ", touchPos.px, touchPos.py); } // Read accelerometer accelVector accel; hidAccelRead(&accel); // Read gyroscope angularRate gyro; hidGyroRead(&gyro); consoleClear(); printf("Circle Pad: X=%4d Y=%4d\n", circlePos.dx, circlePos.dy); printf("Accel: X=%4d Y=%4d Z=%4d\n", accel.x, accel.y, accel.z); printf("Gyro: X=%4d Y=%4d Z=%4d\n", gyro.x, gyro.y, gyro.z); printf("\nButtons: %08lX\n", kHeld); if (kDown & KEY_A) printf("A pressed!\n"); if (kDown & KEY_B) printf("B pressed!\n"); if (kDown & KEY_X) printf("X pressed!\n"); if (kDown & KEY_Y) printf("Y pressed!\n"); gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } HIDUSER_DisableAccelerometer(); HIDUSER_DisableGyroscope(); gfxExit(); return 0; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.