int main(int argc, char** argv) { gfxInitDefault(); consoleInit(GFX_TOP, NULL); svcCreateEvent(&threadRequest,0); u32 *threadStack = memalign(32, STACKSIZE); Result ret = svcCreateThread(&threadHandle, threadMain, 0, &threadStack[STACKSIZE/4], 0x3f, 0); printf("thread create returned %x\n", ret); // Main loop while (aptMainLoop()) { gspWaitForVBlank(); hidScanInput(); printf("\x1b[5;0H"); printf("thread counter = %d\n",threadcount); u32 kDown = hidKeysDown(); if (kDown & KEY_START) break; // break in order to return to hbmenu if (kDown & KEY_A) svcSignalEvent(threadRequest); // Flush and swap framebuffers gfxFlushBuffers(); gfxSwapBuffers(); } // tell thread to exit threadExit = true; // signal the thread svcSignalEvent(threadRequest); // give it time to exit svcSleepThread(10000000ULL); // close handles and free allocated stack svcCloseHandle(threadRequest); svcCloseHandle(threadHandle); free(threadStack); gfxExit(); return 0; }
static void titles_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { titles_data* listData = (titles_data*) data; if(hidKeysDown() & KEY_B) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } ui_pop(); task_clear_titles(items); list_destroy(view); free(listData); return; } if(hidKeysDown() & KEY_SELECT) { titles_options_open(listData); return; } if(!listData->populated || (hidKeysDown() & KEY_X)) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } listData->populateData.items = items; Result res = task_populate_titles(&listData->populateData); if(R_FAILED(res)) { error_display_res(NULL, NULL, res, "Failed to initiate title list population."); } listData->populated = true; } if(listData->populateData.finished && R_FAILED(listData->populateData.result)) { error_display_res(NULL, NULL, listData->populateData.result, "Failed to populate title list."); listData->populateData.result = 0; } if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) { titles_action_open(items, selected); return; } }
static void files_repopulate(files_data* listData) { if(listData->cancelEvent != 0) { svcSignalEvent(listData->cancelEvent); while(svcWaitSynchronization(listData->cancelEvent, 0) == 0) { svcSleepThread(1000000); } listData->cancelEvent = 0; } while(!util_is_dir(&listData->archive, listData->currDir.path)) { char parentPath[PATH_MAX]; util_get_parent_path(parentPath, listData->currDir.path, PATH_MAX); strncpy(listData->currDir.path, parentPath, PATH_MAX); util_get_path_file(listData->currDir.name, listData->currDir.path, NAME_MAX); util_get_parent_path(parentPath, listData->currDir.path, PATH_MAX); strncpy(listData->parentDir.path, parentPath, PATH_MAX); util_get_path_file(listData->parentDir.name, listData->parentDir.path, NAME_MAX); } listData->cancelEvent = task_populate_files(listData->items, &listData->count, FILES_MAX, &listData->currDir); listData->populated = true; }
void gspExitEventHandler(void) { // Stop event thread gspRunEvents = false; svcSignalEvent(gspEvent); threadJoin(gspEventThread, U64_MAX); }
static void files_free_data(files_data* data) { if(!data->populateData.finished) { svcSignalEvent(data->populateData.cancelEvent); while(!data->populateData.finished) { svcSleepThread(1000000); } } if(data->dirItem != NULL) { task_free_file(data->dirItem); data->dirItem = NULL; } if(data->archive != 0) { FSUSER_CloseArchive(data->archive); data->archive = 0; } if(data->archivePath.data != NULL) { free((void*) data->archivePath.data); data->archivePath.data = NULL; } free(data); }
static void ndspThreadMain(void* arg) { ndspThreadRun = true; while (ndspThreadRun) { ndspSync(); // Call callbacks here if (ndspMaster.callback) ndspMaster.callback(ndspMaster.callbackData); if (bSleeping || !bDspReady) continue; if (bNeedsSync) ndspSync(); ndspUpdateMaster(); // Call aux user callback here if enabled // Execute DSP effects here ndspiUpdateChn(); ndspSetCounter(ndspBufferCurId, ndspFrameId++); svcSignalEvent(dspSem); ndspBufferCurId = ndspFrameId & 1; frameCount++; bNeedsSync = true; } }
static void action_paste_files_update(ui_view* view, void* data, float* progress, char* text) { paste_files_data* pasteData = (paste_files_data*) data; if(pasteData->pasteInfo.finished) { FSUSER_ControlArchive(pasteData->target->archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); linked_list_sort(pasteData->items, util_compare_file_infos); ui_pop(); info_destroy(view); if(R_SUCCEEDED(pasteData->pasteInfo.result)) { prompt_display("Success", "Contents pasted.", COLOR_TEXT, false, NULL, NULL, NULL); } action_paste_files_free_data(pasteData); return; } if((hidKeysDown() & KEY_B) && !pasteData->pasteInfo.finished) { svcSignalEvent(pasteData->pasteInfo.cancelEvent); } *progress = pasteData->pasteInfo.currTotal != 0 ? (float) ((double) pasteData->pasteInfo.currProcessed / (double) pasteData->pasteInfo.currTotal) : 0; snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu\n%.2f %s / %.2f %s", pasteData->pasteInfo.processed, pasteData->pasteInfo.total, util_get_display_size(pasteData->pasteInfo.currProcessed), util_get_display_size_units(pasteData->pasteInfo.currProcessed), util_get_display_size(pasteData->pasteInfo.currTotal), util_get_display_size_units(pasteData->pasteInfo.currTotal)); }
static void files_repopulate(files_data* listData, linked_list* items) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } if(listData->dirItem != NULL) { task_free_file(listData->dirItem); listData->dirItem = NULL; } Result res = 0; if(R_SUCCEEDED(res = task_create_file_item(&listData->dirItem, listData->archive, listData->currDir))) { listData->populateData.items = items; listData->populateData.base = (file_info*) listData->dirItem->data; res = task_populate_files(&listData->populateData); } if(R_FAILED(res)) { error_display_res(NULL, NULL, NULL, res, "Failed to initiate file list population."); } listData->populated = true; }
static void files_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { files_data* listData = (files_data*) data; if(hidKeysDown() & KEY_B) { if(strcmp(listData->currDir.path, "/") == 0) { if(listData->archive.handle != 0) { FSUSER_CloseArchive(&listData->archive); listData->archive.handle = 0; } if(listData->archivePath != NULL) { free(listData->archivePath); listData->archivePath = NULL; } if(listData->cancelEvent != 0) { svcSignalEvent(listData->cancelEvent); while(svcWaitSynchronization(listData->cancelEvent, 0) == 0) { svcSleepThread(1000000); } listData->cancelEvent = 0; } ui_pop(); list_destroy(view); free(listData); return; } else { files_navigate(listData, listData->parentDir.path); } } if(hidKeysDown() & KEY_Y) { files_action_open(&listData->currDir, &listData->populated); return; } if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) { file_info* fileInfo = (file_info*) selected->data; if(util_is_dir(&listData->archive, fileInfo->path)) { files_navigate(listData, fileInfo->path); } else { files_action_open(fileInfo, &listData->populated); return; } } if(!listData->populated || (hidKeysDown() & KEY_X)) { files_repopulate(listData); } if(*itemCount != &listData->count || *items != listData->items) { *itemCount = &listData->count; *items = listData->items; } }
int main(void) { Handle handles[10] = {0}; //notification handle + service handles MyThread receiverThread = {0}, senderThread = {0}, PXISRV11HandlerThread = {0}; for(u32 i = 0; i < 9; i++) assertSuccess(srvRegisterService(handles + 1 + i, serviceNames[i], 1)); assertSuccess(MyThread_Create(&receiverThread, receiver, receiverStack, THREAD_STACK_SIZE, 0x2D, -2)); assertSuccess(MyThread_Create(&senderThread, sender, senderStack, THREAD_STACK_SIZE, 0x2D, -2)); assertSuccess(MyThread_Create(&PXISRV11HandlerThread, PXISRV11Handler, PXISRV11HandlerStack, THREAD_STACK_SIZE, 0x2D, -2)); assertSuccess(srvEnableNotification(&handles[0])); while(!shouldTerminate) { s32 index = 0; assertSuccess(svcWaitSynchronizationN(&index, handles, 10, false, -1LL)); if(index == 0) { u32 notificationId; assertSuccess(srvReceiveNotification(¬ificationId)); if(notificationId == 0x100) shouldTerminate = true; } else { Handle session = 0; SessionData *data = &sessionManager.sessionData[index - 1]; assertSuccess(svcAcceptSession(&session, handles[index])); RecursiveLock_Lock(&sessionManager.senderLock); if(data->handle != 0) svcBreak(USERBREAK_PANIC); data->handle = session; assertSuccess(svcSignalEvent(sessionManager.sendAllBuffersToArm9Event)); RecursiveLock_Unlock(&sessionManager.senderLock); } } u32 PXIMC_OnPXITerminate = 0x10000; //TODO: see if this is correct sessionManager.sessionData[0].state = STATE_SENT_TO_ARM9; sendPXICmdbuf(NULL, 0, &PXIMC_OnPXITerminate); assertSuccess(MyThread_Join(&receiverThread, -1LL)); assertSuccess(MyThread_Join(&senderThread, -1LL)); assertSuccess(MyThread_Join(&PXISRV11HandlerThread, -1LL)); for(u32 i = 0; i < 10; i++) svcCloseHandle(handles[i]); return 0; }
static void extsavedata_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { extsavedata_data* listData = (extsavedata_data*) data; if(hidKeysDown() & KEY_B) { if(listData->cancelEvent != 0) { svcSignalEvent(listData->cancelEvent); while(svcWaitSynchronization(listData->cancelEvent, 0) == 0) { svcSleepThread(1000000); } listData->cancelEvent = 0; } ui_pop(); list_destroy(view); free(listData); return; } if(!listData->populated || (hidKeysDown() & KEY_X)) { if(listData->cancelEvent != 0) { svcSignalEvent(listData->cancelEvent); while(svcWaitSynchronization(listData->cancelEvent, 0) == 0) { svcSleepThread(1000000); } listData->cancelEvent = 0; } listData->cancelEvent = task_populate_ext_save_data(listData->items, &listData->count, EXTSAVEDATA_MAX); listData->populated = true; } if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) { extsavedata_action_open((ext_save_data_info*) selected->data, &listData->populated); return; } if(*itemCount != &listData->count || *items != listData->items) { *itemCount = &listData->count; *items = listData->items; } }
void LuaBox_PushEvent(int type, int value) { svcWaitSynchronization(LuaBox_EventMutex, U64_MAX); // Attempt to lock event list struct LuaBox_Event * ev = malloc(sizeof(struct LuaBox_Event)); // Allocate event ev->type = type; ev->value = value; ev->next = LuaBox_EventList; LuaBox_EventList = ev; svcReleaseMutex(LuaBox_EventMutex); // release event mutex svcSignalEvent(LuaBox_EventSignal); // Signal Lua thread if it's listening; }
void conn_main() { APP_STATUS status; u32 it = 0; int ret = 0; int first = 1; int exiting = 0; while((status = aptGetStatus()) != APP_EXITING) { hidScanInput(); consoleClear(&bot); print(&bot, "frame: %08x\n", it); print(&bot, "ret: %08x\n", ret); print(&bot, "last_cmd: %02x\n", last_cmd & 0xFF); if(!first) { u32 bytes_read = 0; while(1) { ret = recv(sock, &cmd, sizeof(cmd), 0); if(ret < 0) { if(ret == -EWOULDBLOCK) continue; break; } bytes_read += ret; if(bytes_read == sizeof(cmd)) { svcSignalEvent(new_cmd_event); svcWaitSynchronization(cmd_done_event, U64_MAX); svcClearEvent(cmd_done_event); send(sock, &resp, sizeof(resp), 0); if(last_cmd_result == 0xDEAD) exiting = 1; break; } } } first = 0; it++; if(enable_draw) renderFrame(); u32 keys = hidKeysUp(); if(keys & KEY_A || exiting) break; } }
void aptExit() { if (!aptInitialised) return; if(!aptIsCrippled())aptAppletUtility_Exit_RetToApp(0); // This is only executed when application-termination was triggered via the home-menu power-off screen. if(aptGetStatusPower() == 1) { aptOpenSession(); APT_ReplySleepQuery(NULL, currentAppId, 0x0); aptCloseSession(); } if(!aptIsCrippled()) { bool isReinit = aptIsReinit(); if (aptGetStatus() == APP_EXITING || !isReinit) { aptOpenSession(); APT_PrepareToCloseApplication(NULL, 0x1); aptCloseSession(); aptOpenSession(); APT_CloseApplication(NULL, 0x0, 0x0, 0x0); aptCloseSession(); if (isReinit) { extern void (*__system_retAddr)(void); __system_retAddr = NULL; } } else if (isReinit) { aptOpenSession(); APT_Finalize(NULL, currentAppId); aptCloseSession(); } } svcSignalEvent(aptEvents[2]); svcWaitSynchronization(aptEventHandlerThread, U64_MAX); svcCloseHandle(aptEventHandlerThread); svcCloseHandle(aptEvents[2]); svcCloseHandle(aptSleepSync); svcCloseHandle(aptStatusMutex); svcCloseHandle(aptLockHandle); svcCloseHandle(aptStatusEvent); aptInitialised = false; }
void cmd_thread_func() { while(1) { svcWaitSynchronization(new_cmd_event, U64_MAX); svcClearEvent(new_cmd_event); if(thread_exit) svcExitThread(); last_cmd = cmd.type; last_cmd_result = execute_cmd(sock, &cmd); svcSignalEvent(cmd_done_event); } }
void aptSetStatus(APP_STATUS status) { svcWaitSynchronization(aptStatusMutex, U64_MAX); aptStatus = status; //if(prevstatus != APP_NOTINITIALIZED) //{ if(status == APP_RUNNING || status == APP_EXITING || status == APP_APPLETSTARTED || status == APP_APPLETCLOSED) svcSignalEvent(aptStatusEvent); //} svcReleaseMutex(aptStatusMutex); }
void closeMusic(Music* src){ closeStream = true; svcSignalEvent(updateStream); while (closeStream){} // Wait for thread exiting... svcCloseHandle(updateStream); // Purging everything purgeTable(src->blocks); ndspChnReset(src->ch); ndspChnWaveBufClear(src->ch); linearFree(src->audiobuf); if (src->audiobuf2 != NULL) linearFree(src->audiobuf2); free(src); }
void aptSetStatus(APT_AppStatus status) { LightLock_Lock(&aptStatusMutex); aptStatus = status; //if(prevstatus != APP_NOTINITIALIZED) //{ if(status == APP_RUNNING) __ctru_speedup_config(); if(status == APP_RUNNING || status == APP_EXITING || status == APP_APPLETSTARTED || status == APP_APPLETCLOSED) svcSignalEvent(aptStatusEvent); //} LightLock_Unlock(&aptStatusMutex); }
// startMusic: Plays a song with network streaming feature void startMusic(Socket* sock, Music* src) { closeStream = false; src->streamLoop = false; // TODO: Add looping feature songPointer = 0; netSize = 0; u32 ch = 0x08; u32 ch2 = 0x09; bool non_native_encode = false; ThreadFunc streamFunction = streamWAV; u8 tmp_encode; /*if (src->encoding == CSND_ENCODING_VORBIS){ streamFunction = streamOGG; tmp_encode = src->encoding; src->encoding = CSND_ENCODING_PCM16; non_native_encode = true; }*/ int raw_format; if (src->audiotype == 1) raw_format = NDSP_FORMAT_MONO_PCM16; else raw_format = NDSP_FORMAT_STEREO_PCM16; ndspChnReset(ch); ndspChnWaveBufClear(ch); ndspChnSetInterp(ch, NDSP_INTERP_LINEAR); ndspChnSetRate(ch, float(src->samplerate)); ndspChnSetFormat(ch, raw_format); ndspWaveBuf* waveBuf = (ndspWaveBuf*)calloc(1, sizeof(ndspWaveBuf)); createDspBlock(waveBuf, src->bytepersample, src->mem_size, 0, (u32*)src->audiobuf); src->blocks = NULL; populatePurgeTable(src, waveBuf); ndspChnWaveBufAdd(ch, waveBuf); src->tick = osGetTime(); src->wavebuf = waveBuf; src->ch = ch; src->isPlaying = true; src->lastCheck = ndspChnGetSamplePos(ch); src->streamLoop = false; svcCreateEvent(&updateStream,0); cachePackage* pkg = (cachePackage*)malloc(sizeof(cachePackage)); pkg->client = sock; pkg->song = src; svcSignalEvent(updateStream); threadCreate(streamFunction, pkg, 8192, 0x18, 0, true); src->isPlaying = true; }
static void files_repopulate(files_data* listData, linked_list* items) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } listData->populateData.items = items; listData->populateData.archive = listData->archive; strncpy(listData->populateData.path, listData->currDir, FILE_PATH_MAX); Result res = task_populate_files(&listData->populateData); if(R_FAILED(res)) { error_display_res(NULL, NULL, res, "Failed to initiate file list population."); } listData->populated = true; }
static void files_free_data(files_data* data) { if(!data->populateData.finished) { svcSignalEvent(data->populateData.cancelEvent); while(!data->populateData.finished) { svcSleepThread(1000000); } } if(data->archive != 0) { util_close_archive(data->archive); data->archive = 0; } if(data->archivePath.data != NULL) { free((void*) data->archivePath.data); data->archivePath.data = NULL; } free(data); }
void ndspExit(void) { if (AtomicDecrement(&ndspRefCount)) return; if (!bDspReady) return; ndspThreadRun = false; if (bSleeping) svcSignalEvent(sleepEvent); threadJoin(ndspThread, U64_MAX); svcCloseHandle(sleepEvent); aptUnhook(&aptCookie); if (!bSleeping) ndspFinalize(false); bSleeping = false; bNeedsSync = false; dspExit(); if (componentFree) { free((void*)componentBin); componentBin = NULL; } }
static void ndspAptHook(APT_HookType hook, void* param) { switch (hook) { case APTHOOK_ONRESTORE: case APTHOOK_ONWAKEUP: bSleeping = false; ndspInitialize(true); svcSignalEvent(sleepEvent); break; case APTHOOK_ONSUSPEND: case APTHOOK_ONSLEEP: bSleeping = true; ndspFinalize(true); break; default: break; } }
Result task_populate_titledb(populate_titledb_data* data) { if(data == NULL || data->items == NULL) { return R_APP_INVALID_ARGUMENT; } task_clear_titledb(data->items); data->itemsListed = false; data->finished = false; data->result = 0; data->cancelEvent = 0; Result res = 0; if(R_SUCCEEDED(res = svcCreateEvent(&data->cancelEvent, RESET_STICKY))) { if(R_SUCCEEDED(res = svcCreateEvent(&data->resumeEvent, RESET_STICKY))) { svcSignalEvent(data->resumeEvent); if(threadCreate(task_populate_titledb_thread, data, 0x10000, 0x19, 1, true) == NULL) { res = R_APP_THREAD_CREATE_FAILED; } } } if(R_FAILED(res)) { data->itemsListed = true; data->finished = true; if(data->resumeEvent != 0) { svcCloseHandle(data->resumeEvent); data->resumeEvent = 0; } if(data->cancelEvent != 0) { svcCloseHandle(data->cancelEvent); data->cancelEvent = 0; } } return res; }
static void action_install_tickets_update(ui_view* view, void* data, float* progress, char* text) { install_tickets_data* installData = (install_tickets_data*) data; if(installData->installInfo.finished) { ui_pop(); info_destroy(view); if(!installData->installInfo.premature) { prompt_display("Success", "Install finished.", COLOR_TEXT, false, installData->base, NULL, ui_draw_file_info, NULL); } action_install_tickets_free_data(installData); return; } if(hidKeysDown() & KEY_B) { svcSignalEvent(installData->cancelEvent); } *progress = installData->installInfo.currTotal != 0 ? (float) ((double) installData->installInfo.currProcessed / (double) installData->installInfo.currTotal) : 0; snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu\n%.2f MB / %.2f MB", installData->installInfo.processed, installData->installInfo.total, installData->installInfo.currProcessed / 1024.0 / 1024.0, installData->installInfo.currTotal / 1024.0 / 1024.0); }
static void dumpnand_update(ui_view* view, void* data, float* progress, char* text) { data_op_data* dumpData = (data_op_data*) data; if(dumpData->finished) { ui_pop(); info_destroy(view); if(R_SUCCEEDED(dumpData->result)) { prompt_display("Success", "NAND dumped.", COLOR_TEXT, false, NULL, NULL, NULL, NULL); } free(dumpData); return; } if(hidKeysDown() & KEY_B) { svcSignalEvent(dumpData->cancelEvent); } *progress = dumpData->currTotal != 0 ? (float) ((double) dumpData->currProcessed / (double) dumpData->currTotal) : 0; snprintf(text, PROGRESS_TEXT_MAX, "%.2f MiB / %.2f MiB", dumpData->currProcessed / 1024.0f / 1024.0f, dumpData->currTotal / 1024.0f / 1024.0f); }
static void action_import_twl_save_update(ui_view* view, void* data, float* progress, char* text) { import_twl_save_data* importData = (import_twl_save_data*) data; if(importData->importInfo.finished) { ui_pop(); info_destroy(view); if(R_SUCCEEDED(importData->importInfo.result)) { prompt_display("Success", "Save imported.", COLOR_TEXT, false, importData->title, ui_draw_title_info, NULL); } free(data); return; } if(hidKeysDown() & KEY_B) { svcSignalEvent(importData->importInfo.cancelEvent); } *progress = importData->importInfo.currTotal != 0 ? (float) ((double) importData->importInfo.currProcessed / (double) importData->importInfo.currTotal) : 0; snprintf(text, PROGRESS_TEXT_MAX, "%.2f %s / %.2f %s", util_get_display_size(importData->importInfo.currProcessed), util_get_display_size_units(importData->importInfo.currProcessed), util_get_display_size(importData->importInfo.currTotal), util_get_display_size_units(importData->importInfo.currTotal)); }
static Result ndspInitialize(bool resume) { Result rc; rc = ndspLoadComponent(); if (R_FAILED(rc)) return rc; rc = svcCreateEvent(&irqEvent, 1); if (R_FAILED(rc)) goto _fail1; rc = DSP_RegisterInterruptEvents(irqEvent, 2, 2); if (R_FAILED(rc)) goto _fail2; rc = DSP_GetSemaphoreHandle(&dspSem); if (R_FAILED(rc)) goto _fail3; DSP_SetSemaphoreMask(0x2000); u16 val = resume ? 2 : 0; if (resume) memcpy(ndspVars[5][0], dspVar5Backup, sizeof(dspVar5Backup)); DSP_WriteProcessPipe(2, &val, 4); DSP_SetSemaphore(0x4000); ndspWaitForIrq(); DSP_ReadPipeIfPossible(2, 0, &val, sizeof(val), NULL); u16 vars[16]; DSP_ReadPipeIfPossible(2, 0, vars, val*2, NULL); int i; for (i = 0; i < val; i ++) { DSP_ConvertProcessAddressFromDspDram(vars[i], (u32*)&ndspVars[i][0]); DSP_ConvertProcessAddressFromDspDram(vars[i] | 0x10000, (u32*)&ndspVars[i][1]); } DSP_SetSemaphore(0x4000); ndspFrameId = 4; ndspSetCounter(0, 4); ndspFrameId++; svcSignalEvent(dspSem); ndspBufferCurId = ndspFrameId & 1; ndspBufferId = ndspFrameId & 1; bDspReady = true; ndspDirtyMaster(); ndspUpdateMaster(); if (resume) { ndspiDirtyChn(); ndspiUpdateChn(); // Force update effect params here } return 0; _fail3: DSP_RegisterInterruptEvents(0, 2, 2); _fail2: svcCloseHandle(irqEvent); _fail1: DSP_UnloadComponent(); return rc; }
bool stream_file(const std::string& filename) { if (filename.empty()) { print("No file selected\n"); return true; } VGMSTREAM* vgmstream = init_vgmstream(filename.c_str()); if (!vgmstream) { print("Bad file %s\n", filename.c_str()); return true; } const int channels = vgmstream->channels; u32 buffer_size = max_samples * vgmstream->channels * sizeof(sample); rawSampleBuffer = static_cast<sample*>(linearAlloc(buffer_size)); sample* buffer = static_cast<sample*>(linearAlloc(buffer_size)); sample* buffer2 = static_cast<sample*>(linearAlloc(buffer_size)); playBuffer1.samples = max_samples; playBuffer2.samples = max_samples; for (int i = 0; i < channels; i++) { playBuffer1.channels.push_back(buffer + i * max_samples); playBuffer2.channels.push_back(buffer2 + i * max_samples); } stream_filename strm_file; strm_file.filename = filename; strm_file.stream = vgmstream; runThreads = true; s32 prio = 0; Thread musicThread; Thread produceThread; svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); musicThread = threadCreate(streamMusic, &strm_file, 4 * 1024, prio-1, -2, false); produceThread = threadCreate(decodeThread, &strm_file, 4 * 1024, prio-1, -2, false); bool ret = false; while (aptMainLoop()) { hidScanInput(); u32 kDown = hidKeysDown(); if (kDown & KEY_START || kDown & KEY_B) { ret = kDown & KEY_START; break; } gfxFlushBuffers(); gfxSwapBuffers(); gspWaitForVBlank(); } runThreads = false; svcSignalEvent(bufferReadyProduceRequest); svcSignalEvent(bufferReadyConsumeRequest); threadJoin(musicThread, U64_MAX); threadJoin(produceThread, U64_MAX); threadFree(musicThread); threadFree(produceThread); svcClearEvent(bufferReadyConsumeRequest); svcClearEvent(bufferReadyProduceRequest); linearFree(rawSampleBuffer); linearFree(buffer); linearFree(buffer2); playBuffer1.channels.clear(); playBuffer2.channels.clear(); close_vgmstream(vgmstream); return ret; }
void aptSignalReadyForSleep(void) { svcSignalEvent(aptSleepSync); }