Compare commits

..

17 Commits

Author SHA1 Message Date
Kripesh Adhikari
bf9df10259
audio/hwopus-decoder: fix glitchy playback (#110)
* audio/hwopus-decoder: fix offset for pointer to wavebuf start
* audio/hwopus-decoder: change to 4 wavebufs and reduce size of wavebufs
2024-10-26 15:36:59 +01:00
Dave Murphy
5e36dc2902
time: display local time 2024-10-18 19:30:12 +01:00
Dave Murphy
399aa26c6e
templates/sysmodule: add force_debug_prod. Closes #109 2024-10-18 18:46:00 +01:00
Vicki Pfau
b41c4957e7
vibration: Improve vibration example usability (#107)
This update moves the frequency controls to D-Pad and lets you turn the values
down, as well as displaying the current values on screen.
2024-10-16 19:57:56 +01:00
Vicki Pfau
d1b2175d58
power: Update charger enum (#108) 2024-10-16 19:57:38 +01:00
Dave Murphy
4f6e700642
sdl2-demo: use acceleration 2024-01-20 02:21:36 +00:00
Narr the Reg
455ad6732c nfc: Update example 2023-07-04 23:17:34 +02:00
yellows8
fbbe90507d
app-playstats: Updated for latest libnx, etc. 2023-03-08 16:36:36 -05:00
yellows8
454610b266
Updated hdls example for passing workmem. 2023-02-23 10:09:09 -05:00
TurtleP
713404797b
Delete various copy constructors and assignment operators (#102)
Prevents common C++ programming mistakes
2023-01-04 21:30:48 +01:00
yellows8
73960d720c
app-playstats: Updated for 15.0.0. 2022-10-16 12:56:12 -04:00
scturtle
0947425fc5 graphics/deko3d: fix and simplify rbtree code 2022-09-14 19:16:35 +02:00
Jeremy S. Postelnek
b55cb17676
account: add code to satisfy multiple accounts (#97)
* add code to satisfy multiple accounts
2022-04-09 16:17:54 -04:00
yellows8
950e99a1ab
Updated hdls example for 13.0.0. 2021-09-17 12:42:06 -04:00
yellows8
f03b9864ce
Improved IMAGE_DISPLAY handling in simplegfx. 2021-09-13 13:25:26 -04:00
Ben Kallus
5980937bdf ChargerType -> PsmChargerType 2021-07-08 23:01:23 +02:00
yellows8
e423a0ab0e
audio/playtone: KEY -> HidNpadButton, which were missed previously. 2021-02-15 12:29:32 -05:00
19 changed files with 188 additions and 82 deletions

View File

@ -37,7 +37,17 @@ int main(int argc, char **argv)
rc = accountGetPreselectedUser(&userID);
if (R_FAILED(rc)) {
printf("accountGetPreselectedUser() failed: 0x%x\n", rc);
printf("accountGetPreselectedUser() failed: 0x%x, using pselShowUserSelector..\n", rc);
/* Create player selection UI settings */
PselUserSelectionSettings settings;
memset(&settings, 0, sizeof(settings));
rc = pselShowUserSelector(&userID, &settings);
if (R_FAILED(rc)) {
printf("pselShowUserSelector() failed: 0x%x\n", rc);
}
}
if (R_SUCCEEDED(rc)) {

View File

@ -86,7 +86,7 @@ int main(int argc, char* argv[])
printf("total_out: %d\n", total_out);
for (i=0; i<total_out; i++) {
printf("%d: ", i);
printf("application_id = 0x%08lX, totalPlayTime = %lu (%llu seconds), totalLaunches = %lu\n", stats[i].application_id, stats[i].totalPlayTime, stats[i].totalPlayTime / 1000000000ULL, stats[i].totalLaunches);
printf("application_id = 0x%08lX, playtime = %lu (%lu seconds), total_launches = %lu\n", stats[i].application_id, stats[i].playtime, stats[i].playtime / 1000000000UL, stats[i].total_launches);
}
}
}
@ -101,10 +101,10 @@ int main(int argc, char* argv[])
if (R_SUCCEEDED(rc)) {
printf("total_out: %d\n", total_out);
for (i=0; i<total_out; i++) {
time_t tmptime = pdmPlayTimestampToPosix(events[i].timestampUser);
time_t tmptime = events[i].timestamp_user;
printf("%d: ", i);
printf("program_id = 0x%08lX, entry_index = 0x%x, timestampUser = %u, timestampNetwork = %u, eventType = %u, timestampUser = %s\n", events[i].program_id, events[i].entry_index, events[i].timestampUser, events[i].timestampNetwork, events[i].eventType, ctime(&tmptime));
printf("program_id = 0x%08lX, entry_index = 0x%x, timestamp_user = %lu, timestamp_network = %lu, event_type = %u, timestamp_user = %s\n", events[i].program_id, events[i].entry_index, events[i].timestamp_user, events[i].timestamp_network, events[i].event_type, ctime(&tmptime));
}
}
@ -112,12 +112,12 @@ int main(int argc, char* argv[])
PdmPlayStatistics playstats[1]={0};
rc = pdmqryQueryPlayStatisticsByApplicationId(application_ids[0], false, &playstats[0]);
printf("pdmqryQueryPlayStatisticsByApplicationId(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) printf("application_id = 0x%08lX, playtimeMinutes = %u, totalLaunches = %u\n", playstats[0].application_id, playstats[0].playtimeMinutes, playstats[0].totalLaunches);
if (R_SUCCEEDED(rc)) printf("program_id = 0x%016lX, playtime = %lu (%lu seconds), total_launches = %u\n", playstats[0].program_id, playstats[0].playtime, playstats[0].playtime / 1000000000UL, playstats[0].total_launches);
// Get PdmPlayStatistics for the specified ApplicationId and user.
rc = pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(application_ids[0], preselected_uid, false, &playstats[0]);
printf("pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) printf("application_id = 0x%08lX, playtimeMinutes = %u, totalLaunches = %u\n", playstats[0].application_id, playstats[0].playtimeMinutes, playstats[0].totalLaunches);
if (R_SUCCEEDED(rc)) printf("program_id = 0x%016lX, playtime = %lu (%lu seconds), total_launches = %u\n", playstats[0].program_id, playstats[0].playtime, playstats[0].playtime / 1000000000UL, playstats[0].total_launches);
// Get a listing of PdmLastPlayTime for the specified applications.
PdmLastPlayTime playtimes[1]={0};
@ -125,7 +125,7 @@ int main(int argc, char* argv[])
printf("pdmqryQueryLastPlayTime(): 0x%x, %d\n", rc, total_out);
if (R_SUCCEEDED(rc)) {
for (i=0; i<total_out; i++)
printf("%d: timestampUser = %lu\n", i, pdmPlayTimestampToPosix(playtimes[i].timestampUser));
printf("%d: timestamp_user = %lu\n", i, pdmPlayTimestampToPosix(playtimes[i].timestamp_user));
}
// Get the available range for reading events, see pdm.h.
@ -133,12 +133,17 @@ int main(int argc, char* argv[])
rc = pdmqryGetAvailablePlayEventRange(&total_entries, &start_entryindex, &end_entryindex);
printf("pdmqryGetAvailablePlayEventRange(): 0x%x, 0x%x, 0x%x, 0x%x\n", rc, total_entries, start_entryindex, end_entryindex);
// Get a listing of applications recently played by the specified user.
rc = pdmqryQueryRecentlyPlayedApplication(preselected_uid, false, application_ids, 1, &total_out);
printf("pdmqryQueryRecentlyPlayedApplication(): 0x%x, %d\n", rc, total_out);
// Get account events.
PdmAccountEvent accevents[5]={};
rc = pdmqryQueryAccountEvent(0, accevents, 5, &total_out);
printf("pdmqryQueryAccountEvent(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) {
for (i=0; i<total_out; i++)
printf("%d: application_id = 0x%08lX\n", i, application_ids[i]);
printf("total_out: %d\n", total_out);
for (i=0; i<total_out; i++) {
time_t tmptime = accevents[i].timestamp_user;
printf("%d: ", i);
printf("uid = 0x%lx 0x%lx, program_id = 0x%016lX, entry_index = 0x%x, timestamp_user = %lu, timestamp_network = %lu, event_type = %u, timestamp_user = %s\n", accevents[i].uid.uid[0], accevents[i].uid.uid[1], accevents[i].program_id, accevents[i].entry_index, accevents[i].timestamp_user, accevents[i].timestamp_network, accevents[i].type, ctime(&tmptime));
}
}
// For more cmds, see pdm.h.

View File

@ -74,15 +74,15 @@ int main(void)
size_t num_channels = 1;
size_t samplerate = 48000;
size_t max_samples = samplerate;
size_t max_samples = samplerate/20;//each wavebuf can hold upto 1sec/20 = 50ms of audio data
size_t max_samples_datasize = max_samples*num_channels*sizeof(opus_int16);
size_t mempool_size = (max_samples_datasize*2 + 0xFFF) &~ 0xFFF;//*2 for 2 wavebufs.
size_t mempool_size = (max_samples_datasize*4 + 0xFFF) &~ 0xFFF;//*4 for 4 wavebufs.
void* mempool_ptr = memalign(0x1000, mempool_size);
void* tmpdata_ptr = malloc(max_samples_datasize);
opuspkt_tmpbuf = (u8*)malloc(opuspkt_tmpbuf_size);
opus_int16* curbuf = NULL;
AudioDriverWaveBuf wavebuf[2] = {0};
AudioDriverWaveBuf wavebuf[4] = {0};
int i, wavei;
HwopusDecoder hwdecoder = {0};
@ -151,9 +151,9 @@ int main(void)
}
audrvVoiceStart(&drv, 0);
for(i=0; i<2; i++) {
for(i=0; i<4; i++) {
wavebuf[i].data_raw = mempool_ptr;
wavebuf[i].size = max_samples_datasize*2;//*2 for 2 wavebufs.
wavebuf[i].size = max_samples_datasize*4;//*4 for 4 wavebufs.
wavebuf[i].start_sample_offset = i * max_samples;
wavebuf[i].end_sample_offset = wavebuf[i].start_sample_offset + max_samples;
}
@ -198,7 +198,7 @@ int main(void)
if (audio_playing) {
wavei = -1;
for(i=0; i<2; i++) {
for(i=0; i<4; i++) {
if (wavebuf[i].state == AudioDriverWaveBufState_Free || wavebuf[i].state == AudioDriverWaveBufState_Done) {
wavei = i;
break;
@ -206,7 +206,7 @@ int main(void)
}
if (wavei >= 0) {
curbuf = (opus_int16*)(mempool_ptr + wavebuf[wavei].start_sample_offset);
curbuf = (opus_int16*)(mempool_ptr + wavebuf[wavei].start_sample_offset * sizeof(opus_int16));
opret = op_read(of, tmpdata_ptr, max_samples * num_channels, NULL);//The buffer used here has to be seperate from mempool_ptr.
if (opret < 0)

View File

@ -145,13 +145,13 @@ int main(int argc, char **argv)
play_tone = true;
}
if (kDown & KEY_L)
if (kDown & HidNpadButton_L)
{
fill_audio_buffer(out_buf_data, 0, data_size, notefreq[8]);
play_tone = true;
}
if (kDown & KEY_R)
if (kDown & HidNpadButton_R)
{
fill_audio_buffer(out_buf_data, 0, data_size, notefreq[9]);
play_tone = true;

View File

@ -15,6 +15,11 @@ class CCmdMemRing
dk::Fence m_fences[NumSlices];
public:
CCmdMemRing() : m_mem{}, m_curSlice{}, m_fences{} { }
CCmdMemRing(const CCmdMemRing&) = delete;
CCmdMemRing& operator=(const CCmdMemRing&) = delete;
~CCmdMemRing()
{
m_mem.destroy();

View File

@ -18,7 +18,12 @@ class CDescriptorSet
CMemPool::Handle m_mem;
public:
CDescriptorSet() : m_mem{} { }
~CDescriptorSet()
CDescriptorSet(const CDescriptorSet&) = delete;
CDescriptorSet& operator=(const CDescriptorSet&) = delete;
~CDescriptorSet()
{
m_mem.destroy();
}

View File

@ -13,6 +13,11 @@ class CExternalImage
CMemPool::Handle m_mem;
public:
CExternalImage() : m_image{}, m_descriptor{}, m_mem{} { }
CExternalImage(const CExternalImage&) = delete;
CExternalImage& operator=(const CExternalImage&) = delete;
~CExternalImage()
{
m_mem.destroy();

View File

@ -192,7 +192,7 @@ void CIntrusiveTreeBase::remove(N* node)
}
else
{
child = node->left() ? node->right() : node->left();
child = node->left() ? node->left() : node->right();
parent = node->getParent();
color = node->getColor();

View File

@ -173,7 +173,7 @@ public:
T* first() const { return toType(minmax(N::Left)); }
T* last() const { return toType(minmax(N::Right)); }
bool empty() const { return m_root != nullptr; }
bool empty() const { return m_root == nullptr; }
void clear() { m_root = nullptr; }
T* prev(T* node) const { return toType(walk(toNode(node), N::Left)); }
@ -194,31 +194,11 @@ public:
mode != UpperBound ? N::Left : N::Right,
[&lambda](N* curnode) { return lambda(toType(curnode)); });
switch (mode)
{
default:
case Exact:
break;
case LowerBound:
if (!node && parent)
{
if (&parent->left() == &point)
node = parent;
else
node = walk(parent, N::Right);
}
break;
case UpperBound:
if (node)
node = walk(node, N::Right);
else if (parent)
{
if (&parent->right() == &point)
node = walk(parent, N::Right);
else
node = parent;
}
break;
if (mode != Exact) {
if (mode == UpperBound && node)
node = walk(node, N::Right);
else if (!node && parent)
node = &parent->left() == &point ? parent : walk(parent, N::Right);
}
return toType(node);
}

View File

@ -20,6 +20,10 @@ class CMemPool
void* m_cpuAddr;
DkGpuAddr m_gpuAddr;
Block(const Block&) = delete;
Block& operator=(const Block&) = delete;
constexpr void* cpuOffset(uint32_t offset) const
{
return m_cpuAddr ? ((u8*)m_cpuAddr + offset) : nullptr;
@ -42,6 +46,10 @@ class CMemPool
uint32_t m_start;
uint32_t m_end;
Slice(const Slice&) = delete;
Slice& operator=(const Slice&) = delete;
constexpr uint32_t getSize() const { return m_end - m_start; }
constexpr bool canCoalesce(Slice const& rhs) const { return m_pool == rhs.m_pool && m_block == rhs.m_block && m_end == rhs.m_start; }
@ -109,9 +117,14 @@ public:
CMemPool(dk::Device dev, uint32_t flags = DkMemBlockFlags_CpuUncached | DkMemBlockFlags_GpuCached, uint32_t blockSize = DefaultBlockSize) :
m_dev{dev}, m_flags{flags}, m_blockSize{blockSize}, m_blocks{}, m_memMap{}, m_sliceHeap{}, m_freeList{} { }
~CMemPool();
Handle allocate(uint32_t size, uint32_t alignment = DK_CMDMEM_ALIGNMENT);
CMemPool(const CMemPool&) = delete;
CMemPool& operator=(const CMemPool&) = delete;
};
constexpr bool operator<(uint32_t lhs, CMemPool::Slice const& rhs)

View File

@ -12,6 +12,11 @@ class CShader
CMemPool::Handle m_codemem;
public:
CShader() : m_shader{}, m_codemem{} { }
CShader(const CShader&) = delete;
CShader& operator=(const CShader&) = delete;
~CShader()
{
m_codemem.destroy();

View File

@ -100,7 +100,7 @@ int main(int argc, char** argv) {
TTF_Init();
SDL_Window* window = SDL_CreateWindow("sdl2+mixer+image+ttf demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_W, SCREEN_H, SDL_WINDOW_SHOWN);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
// load logos from file
SDL_Surface *sdllogo = IMG_Load("data/sdl.png");

View File

@ -33,6 +33,8 @@ int main(int argc, char* argv[])
#ifdef DISPLAY_IMAGE
u8* imageptr = (u8*)image_bin;
const u32 image_width = 1280;
const u32 image_height = 720;
#endif
// Configure our supported input layout: a single player with standard controller styles
@ -73,7 +75,9 @@ int main(int argc, char* argv[])
{
u32 pos = y * stride / sizeof(u32) + x;
#ifdef DISPLAY_IMAGE
framebuf[pos] = RGBA8_MAXALPHA(imageptr[pos*3+0]+(cnt*4), imageptr[pos*3+1], imageptr[pos*3+2]);
if (y >= image_height || x >= image_width) continue;
u32 imagepos = y * image_width + x;
framebuf[pos] = RGBA8_MAXALPHA(imageptr[imagepos*3+0]+(cnt*4), imageptr[imagepos*3+1], imageptr[imagepos*3+2]);
#else
framebuf[pos] = 0x01010101 * cnt * 4;//Set framebuf to different shades of grey.
#endif

View File

@ -28,6 +28,8 @@ int main(int argc, char* argv[])
Result rc=0, rc2=0;
bool initflag=0;
u8 *workmem = NULL;
size_t workmem_size = 0x1000;
printf("hdls example\n");
@ -36,9 +38,12 @@ int main(int argc, char* argv[])
printf("hiddbgInitialize(): 0x%x\n", rc);
}
else {
initflag = 1;
workmem = aligned_alloc(0x1000, workmem_size);
if (workmem) initflag = 1;
else printf("workmem alloc failed\n");
}
HiddbgHdlsSessionId session_id={0};
HiddbgHdlsHandle HdlsHandle={0};
HiddbgHdlsDeviceInfo device = {0};
HiddbgHdlsState state={0};
@ -60,7 +65,7 @@ int main(int argc, char* argv[])
state.analog_stick_r.y = -0x5678;
if (initflag) {
rc = hiddbgAttachHdlsWorkBuffer();
rc = hiddbgAttachHdlsWorkBuffer(&session_id, workmem, workmem_size);
printf("hiddbgAttachHdlsWorkBuffer(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) {
@ -128,10 +133,11 @@ int main(int argc, char* argv[])
printf("hiddbgDetachHdlsVirtualDevice(): 0x%x\n", rc);
}
rc = hiddbgReleaseHdlsWorkBuffer();
rc = hiddbgReleaseHdlsWorkBuffer(session_id);
printf("hiddbgReleaseHdlsWorkBuffer(): 0x%x\n", rc);
hiddbgExit();
free(workmem);
}
// Deinitialize and clean up resources used by the console (important!)

View File

@ -28,17 +28,12 @@ int main(int argc, char* argv[])
PadState pad;
padInitializeDefault(&pad);
printf("Press PLUS to exit.\n");
// Two VibrationDeviceHandles are returned: first one for left-joycon, second one for right-joycon.
// Change the total_handles param to 1, and update the hidSendVibrationValues calls, if you only want 1 VibrationDeviceHandle.
rc = hidInitializeVibrationDevices(VibrationDeviceHandles[0], 2, HidNpadIdType_Handheld, HidNpadStyleTag_NpadHandheld);
// Setup VibrationDeviceHandles for HidNpadIdType_No1 too, since we want to support both HidNpadIdType_Handheld and HidNpadIdType_No1.
if (R_SUCCEEDED(rc)) rc = hidInitializeVibrationDevices(VibrationDeviceHandles[1], 2, HidNpadIdType_No1, HidNpadStyleTag_NpadJoyDual);
printf("hidInitializeVibrationDevices() returned: 0x%x\n", rc);
if (R_SUCCEEDED(rc)) printf("Hold R to vibrate, and press A/B/X/Y while holding R to adjust values.\n");
VibrationValue.amp_low = 0.2f;
VibrationValue.freq_low = 10.0f;
@ -55,6 +50,14 @@ int main(int argc, char* argv[])
// Main loop
while(appletMainLoop())
{
consoleClear();
printf("Press PLUS to exit.\n");
printf("Hold R to vibrate.\n");
printf("Press D-Pad (frequency) and face buttons (amplitude) to adjust values.\n");
printf("High frequency %.0f, amplitude %.1f\n", VibrationValue.freq_high, VibrationValue.amp_high);
printf("Low frequency %.0f, amplitude %.1f\n", VibrationValue.freq_low, VibrationValue.amp_low);
// Scan the gamepad. This should be done once for each frame
padUpdate(&pad);
@ -67,6 +70,18 @@ int main(int argc, char* argv[])
//Select which devices to vibrate.
target_device = padIsHandheld(&pad) ? 0 : 1;
if (kDown & HidNpadButton_A) VibrationValue.amp_low += 0.1f;
if (kDown & HidNpadButton_Y) VibrationValue.amp_low -= 0.1f;
if (kDown & HidNpadButton_X) VibrationValue.amp_high += 0.1f;
if (kDown & HidNpadButton_B) VibrationValue.amp_high -= 0.1f;
if (kDown & HidNpadButton_Right) VibrationValue.freq_low += 5.0f;
if (kDown & HidNpadButton_Left) VibrationValue.freq_low -= 5.0f;
if (kDown & HidNpadButton_Up) VibrationValue.freq_high += 12.0f;
if (kDown & HidNpadButton_Down) VibrationValue.freq_high -= 12.0f;
if (R_SUCCEEDED(rc) && (kHeld & HidNpadButton_R))
{
//Calling hidSendVibrationValue/hidSendVibrationValues is really only needed when sending new VibrationValue(s).
@ -77,11 +92,6 @@ int main(int argc, char* argv[])
rc2 = hidSendVibrationValues(VibrationDeviceHandles[target_device], VibrationValues, 2);
if (R_FAILED(rc2)) printf("hidSendVibrationValues() returned: 0x%x\n", rc2);
if (kDown & HidNpadButton_A) VibrationValue.amp_low += 0.1f;
if (kDown & HidNpadButton_B) VibrationValue.freq_low += 5.0f;
if (kDown & HidNpadButton_X) VibrationValue.amp_high += 0.1f;
if (kDown & HidNpadButton_Y) VibrationValue.freq_high += 12.0f;
}
else if(kUp & HidNpadButton_R)//Stop vibration for all devices.
{

View File

@ -33,7 +33,7 @@ void print_hex(void *buf, size_t size) {
consoleUpdate(NULL);
}
Result process_amiibo(u32 app_id) {
Result process_amiibo() {
Result rc = 0;
// Get the handle of the first controller with NFC capabilities.
@ -94,15 +94,34 @@ Result process_amiibo(u32 app_id) {
rc = eventWaitLoop(&activate_event);
if (R_SUCCEEDED(rc)) {
printf("A tag was detected, please do not remove it from the NFC spot.\n");
printf("A tag was detected, please do not remove it from the NFC spot.\n\n");
consoleUpdate(NULL);
}
}
// Retrieve the tag info data, which contains the protocol, type and uuid.
if (R_SUCCEEDED(rc)) {
NfpTagInfo tag_info = {0};
rc = nfpGetTagInfo(&handle, &tag_info);
if (R_SUCCEEDED(rc)) {
printf("Tag protocol: 0x%02x, type: 0x%02x, UUID: ", tag_info.protocol, tag_info.tag_type);
print_hex(tag_info.uuid, tag_info.uuid_length);
printf("\n");
}
}
// If a tag was successfully detected, load it into memory.
if (R_SUCCEEDED(rc))
if (R_SUCCEEDED(rc)) {
rc = nfpMount(&handle, NfpDeviceType_Amiibo, NfpMountTarget_All);
if (rc == 0x11073) // 2115-0136
printf("This tag is corrupted and has a backup in system.\n");
if (rc == 0x12073) // 2115-0144
printf("This tag is corrupted.\n");
}
// Retrieve the model info data, which contains the amiibo id.
if (R_SUCCEEDED(rc)) {
NfpModelInfo model_info = {0};
@ -111,6 +130,7 @@ Result process_amiibo(u32 app_id) {
if (R_SUCCEEDED(rc)) {
printf("Amiibo ID: ");
print_hex(model_info.amiibo_id, 8);
printf("\n");
}
}
@ -120,8 +140,43 @@ Result process_amiibo(u32 app_id) {
NfpCommonInfo common_info = {0};
rc = nfpGetCommonInfo(&handle, &common_info);
if (R_SUCCEEDED(rc))
if (R_SUCCEEDED(rc)) {
app_area_size = common_info.application_area_size;
printf("Write counter: %d, last write date %d/%d/%d\n\n", common_info.write_counter, common_info.last_write_day, common_info.last_write_month, common_info.last_write_year);
}
}
u32 app_id=0;
// Retrieve the admin info data, which contains the app id.
if (R_SUCCEEDED(rc)) {
NfpAdminInfo admin_info = {0};
rc = nfpGetAdminInfo(&handle, &admin_info);
if (R_SUCCEEDED(rc)) {
app_id = admin_info.application_area_id;
printf("App area: 0x%x, game ID: 0x%lx, console: ", app_id, admin_info.application_id);
switch (admin_info.application_area_version) {
case NfpApplicationAreaVersion_3DS:
printf("Old 3ds");
break;
case NfpApplicationAreaVersion_WiiU:
printf("Wii U");
break;
case NfpApplicationAreaVersion_3DSv2:
printf("New 3ds");
break;
case NfpApplicationAreaVersion_Switch:
printf("Switch");
break;
case NfpApplicationAreaVersion_NotSet:
printf("Not set");
break;
default:
printf("0x%x", admin_info.application_area_version);
break;
}
printf("\n");
}
}
if (R_SUCCEEDED(rc)) {
@ -134,13 +189,15 @@ Result process_amiibo(u32 app_id) {
}
u8 app_area[0xd8] = {0}; // Maximum size of the application area.
u32 app_area_read_size = 0; // Actual number of bytes set by nfpGetApplicationArea.
if (app_area_size > sizeof(app_area)) app_area_size = sizeof(app_area);
if (R_SUCCEEDED(rc)) {
rc = nfpGetApplicationArea(&handle, app_area, app_area_size);
rc = nfpGetApplicationArea(&handle, app_area, app_area_size, &app_area_read_size);
if (R_SUCCEEDED(rc)) {
printf("App area:\n");
print_hex(app_area, app_area_size);
printf("App data:\n");
print_hex(app_area, app_area_read_size);
printf("\n");
}
}
@ -171,11 +228,7 @@ fail_0:
int main(int argc, char* argv[])
{
Result rc = 0;
// Hardcoded for Super Smash Bros. Ultimate.
// See also: https://switchbrew.org/wiki/NFC_services#Application_IDs
u32 app_id = 0x34f80200;
// This example uses a text console, as a simple way to output text to the screen.
// If you want to write a software-rendered graphics application,
// take a look at the graphics/simplegfx example, which uses the libnx Framebuffer API instead.
@ -194,7 +247,9 @@ int main(int argc, char* argv[])
consoleUpdate(NULL);
// Initialize the nfp:* service.
rc = nfpInitialize(NfpServiceType_User);
// Use the NfpServiceType as required by your app, only use Debug if actually needed.
// This example uses nfpGetAdminInfo which is only available on the debug interface.
rc = nfpInitialize(NfpServiceType_Debug);
// Check if NFC is enabled. If not, wait until it is.
// Note that various official games don't use nfc*().
@ -237,7 +292,7 @@ int main(int argc, char* argv[])
// padGetButtonsDown returns the set of buttons that have been
// newly pressed in this frame compared to the previous one
if (padGetButtonsDown(&pad) & HidNpadButton_A) {
rc = process_amiibo(app_id);
rc = process_amiibo();
// If an error happened, print it.
if (R_FAILED(rc))

View File

@ -4,7 +4,7 @@
#include <switch.h>
const char* const chargers[3] = {"None", "Official", "Generic"};
const char* const chargers[4] = {"None", "Full Power", "Low Power", "Unsupported"};
int main(int argc, char **argv)
{
@ -38,7 +38,7 @@ int main(int argc, char **argv)
double rawCharge;
double age;
bool isEnoughPower;
ChargerType type;
PsmChargerType type;
printf("\x1b[1;1H\x1b[K");
rc = psmGetBatteryChargePercentage(&charge);

View File

@ -166,7 +166,8 @@
"type": "debug_flags",
"value": {
"allow_debug": false,
"force_debug": true
"force_debug": true,
"force_debug_prod": false
}
}]
}

View File

@ -1,5 +1,6 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <switch.h>
@ -20,6 +21,7 @@ int main(int argc, char **argv)
padInitializeDefault(&pad);
printf("\x1b[16;16HPress PLUS to exit.");
printf("\x1b[17;16HTZ=%s\n", getenv("TZ"));
// Main loop
while(appletMainLoop())
@ -34,7 +36,7 @@ int main(int argc, char **argv)
//Print current time
time_t unixTime = time(NULL);
struct tm* timeStruct = gmtime((const time_t *)&unixTime);//Gets UTC time. If you want local-time use localtime().
struct tm* timeStruct = localtime((const time_t *)&unixTime); // Gets local time. If you want UTC use gmtime().
int hours = timeStruct->tm_hour;
int minutes = timeStruct->tm_min;