bool appIsInstalled(App app) { if(!serviceRequire("am")) { return false; } u32 titleCount; Result titleCountResult = AM_GetTitleCount(appMediatypeToByte(app.mediaType), &titleCount); if(titleCountResult != 0) { platformSetError(serviceParseError((u32) titleCountResult)); return false; } u64 titleIds[titleCount]; Result titleIdsResult = AM_GetTitleIdList(appMediatypeToByte(app.mediaType), titleCount, titleIds); if(titleIdsResult != 0) { platformSetError(serviceParseError((u32) titleIdsResult)); return false; } for(u32 i = 0; i < titleCount; i++) { if(titleIds[i] == app.titleId) { return true; } } return false; }
AppResult appDelete(App app) { if(!serviceRequire("am")) { return APP_AM_INIT_FAILED; } Result res = AM_DeleteTitle(appMediatypeToByte(app.mediaType), app.titleId); if(res != 0) { platformSetError(serviceParseError((u32) res)); return APP_DELETE_FAILED; } return APP_SUCCESS; }
std::vector<App> appList(MediaType mediaType) { std::vector<App> titles; if(!serviceRequire("am")) { return titles; } u32 titleCount; Result titleCountResult = AM_GetTitleCount(appMediatypeToByte(mediaType), &titleCount); if(titleCountResult != 0) { platformSetError(serviceParseError((u32) titleCountResult)); return titles; } u64 titleIds[titleCount]; Result titleIdsResult = AM_GetTitleIdList(appMediatypeToByte(mediaType), titleCount, titleIds); if(titleIdsResult != 0) { platformSetError(serviceParseError((u32) titleIdsResult)); return titles; } TitleList titleList[titleCount]; Result titleListResult = AM_ListTitles(appMediatypeToByte(mediaType), titleCount, titleIds, titleList); if(titleListResult != 0) { platformSetError(serviceParseError((u32) titleListResult)); return titles; } for(u32 i = 0; i < titleCount; i++) { u64 titleId = titleList[i].titleID; App app; app.titleId = titleId; app.uniqueId = ((u32*) &titleId)[0]; AM_GetTitleProductCode(appMediatypeToByte(mediaType), titleId, app.productCode); if(strcmp(app.productCode, "") == 0) { strcpy(app.productCode, "<N/A>"); } app.mediaType = mediaType; app.platform = appPlatformFromId(((u16*) &titleId)[3]); app.category = appCategoryFromId(((u16*) &titleId)[2]); app.version = titleList[i].titleVersion; app.size = titleList[i].size; titles.push_back(app); } return titles; }
AppResult appInstallFile(MediaType mediaType, const std::string path, std::function<bool(u64 pos, u64 totalSize)> onProgress) { if(!serviceRequire("am")) { return APP_AM_INIT_FAILED; } FILE* fd = fopen(path.c_str(), "r"); if(!fd) { return APP_OPEN_FILE_FAILED; } struct stat st; stat(path.c_str(), &st); u64 size = (u64) (u32) st.st_size; AppResult ret = appInstall(mediaType, fd, size, onProgress); fclose(fd); return ret; }
App appGetCiaInfo(const std::string file, MediaType mediaType) { if(!serviceRequire("am")) { return {}; } FS_archive archive = (FS_archive) {ARCH_SDMC, (FS_path) {PATH_EMPTY, 1, (u8*) ""}}; Result archiveResult = FSUSER_OpenArchive(NULL, &archive); if(archiveResult != 0) { platformSetError(serviceParseError((u32) archiveResult)); return {}; } Handle handle = 0; Result openResult = FSUSER_OpenFile(NULL, &handle, archive, FS_makePath(PATH_CHAR, file.c_str()), FS_OPEN_READ, FS_ATTRIBUTE_NONE); if(openResult != 0) { platformSetError(serviceParseError((u32) openResult)); return {}; } TitleList titleInfo; Result infoResult = AM_GetCiaFileInfo(appMediatypeToByte(mediaType), &titleInfo, handle); if(infoResult != 0) { platformSetError(serviceParseError((u32) infoResult)); return {}; } FSFILE_Close(handle); FSUSER_CloseArchive(NULL, &archive); App app; app.titleId = titleInfo.titleID; app.uniqueId = ((u32*) &titleInfo.titleID)[0]; strcpy(app.productCode, "<N/A>"); app.mediaType = mediaType; app.platform = appPlatformFromId(((u16*) &titleInfo.titleID)[3]); app.category = appCategoryFromId(((u16*) &titleInfo.titleID)[2]); app.version = titleInfo.titleVersion; app.size = titleInfo.size; return app; }
AppResult appInstall(MediaType mediaType, FILE* fd, u64 size, std::function<bool(u64 pos, u64 totalSize)> onProgress) { if(!serviceRequire("am")) { return APP_AM_INIT_FAILED; } if(onProgress != NULL) { onProgress(0, size); } Handle ciaHandle; Result startResult = AM_StartCiaInstall(appMediatypeToByte(mediaType), &ciaHandle); if(startResult != 0) { platformSetError(serviceParseError((u32) startResult)); return APP_BEGIN_INSTALL_FAILED; } u32 bufSize = 1024 * 128; // 128KB void* buf = malloc(bufSize); bool cancelled = false; u64 pos = 0; while(platformIsRunning()) { if(onProgress != NULL && !onProgress(pos, size)) { cancelled = true; break; } size_t bytesRead = fread(buf, 1, bufSize, fd); if(bytesRead > 0) { Result writeResult = FSFILE_Write(ciaHandle, NULL, pos, buf, (u32) bytesRead, FS_WRITE_NOFLUSH); if(writeResult != 0) { AM_CancelCIAInstall(&ciaHandle); platformSetError(serviceParseError((u32) writeResult)); return APP_INSTALL_ERROR; } pos += bytesRead; } if((ferror(fd) && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS) || (size != 0 && pos == size)) { break; } } free(buf); if(cancelled) { AM_CancelCIAInstall(&ciaHandle); return APP_OPERATION_CANCELLED; } if(!platformIsRunning()) { AM_CancelCIAInstall(&ciaHandle); return APP_PROCESS_CLOSING; } if(size != 0 && pos != size) { AM_CancelCIAInstall(&ciaHandle); return APP_IO_ERROR; } if(onProgress != NULL) { onProgress(size, size); } Result finishResult = AM_FinishCiaInstall(appMediatypeToByte(mediaType), &ciaHandle); if(finishResult != 0) { platformSetError(serviceParseError((u32) finishResult)); return APP_FINALIZE_INSTALL_FAILED; } return APP_SUCCESS; }
bool gpuInit() { if(!serviceRequire("gfx")) { return false; } dirtyState = 0xFFFFFFFF; dirtyTexEnvs = 0xFFFFFFFF; dirtyTextures = 0xFFFFFFFF; clearColor = 0; clearDepth = 0; viewportScreen = TOP_SCREEN; viewportX = 0; viewportY = 0; viewportWidth = 240; viewportHeight = 400; scissorMode = SCISSOR_DISABLE; scissorX = 0; scissorY = 0; scissorWidth = 240; scissorHeight = 400; depthNear = 0; depthFar = 1; cullMode = CULL_NONE; stencilEnable = false; stencilFunc = TEST_ALWAYS; stencilRef = 0; stencilMask = 0xFF; stencilReplace = 0; stencilFail = OP_KEEP; stencilZFail = OP_KEEP; stencilZPass = OP_KEEP; blendRed = 0; blendGreen = 0; blendBlue = 0; blendAlpha = 0; blendColorEquation = BLEND_ADD; blendAlphaEquation = BLEND_ADD; blendColorSrc = FACTOR_SRC_ALPHA; blendColorDst = FACTOR_ONE_MINUS_SRC_ALPHA; blendAlphaSrc = FACTOR_SRC_ALPHA; blendAlphaDst = FACTOR_ONE_MINUS_SRC_ALPHA; alphaEnable = false; alphaFunc = TEST_ALWAYS; alphaRef = 0; depthEnable = false; depthFunc = TEST_GREATER; componentMask = GPU_WRITE_ALL; activeShader = NULL; texEnv[0].rgbSources = TEXENV_SOURCES(SOURCE_TEXTURE0, SOURCE_PRIMARY_COLOR, SOURCE_PRIMARY_COLOR); texEnv[0].alphaSources = TEXENV_SOURCES(SOURCE_TEXTURE0, SOURCE_PRIMARY_COLOR, SOURCE_PRIMARY_COLOR); texEnv[0].rgbOperands = TEXENV_OPERANDS(0, 0, 0); texEnv[0].alphaOperands = TEXENV_OPERANDS(0, 0, 0); texEnv[0].rgbCombine = COMBINE_MODULATE; texEnv[0].alphaCombine = COMBINE_MODULATE; texEnv[0].constantColor = 0xFFFFFFFF; for(u8 env = 1; env < TEX_ENV_COUNT; env++) { texEnv[env].rgbSources = TEXENV_SOURCES(SOURCE_PREVIOUS, SOURCE_PRIMARY_COLOR, SOURCE_PRIMARY_COLOR); texEnv[env].alphaSources = TEXENV_SOURCES(SOURCE_PREVIOUS, SOURCE_PRIMARY_COLOR, SOURCE_PRIMARY_COLOR); texEnv[env].rgbOperands = TEXENV_OPERANDS(0, 0, 0); texEnv[env].alphaOperands = TEXENV_OPERANDS(0, 0, 0); texEnv[env].rgbCombine = COMBINE_REPLACE; texEnv[env].alphaCombine = COMBINE_REPLACE; texEnv[env].constantColor = 0xFFFFFFFF; } for(u8 unit = 0; unit < TEX_UNIT_COUNT; unit++) { activeTextures[unit] = NULL; } enabledTextures = 0; u32 gpuCmdSize = 0x40000; u32* gpuCmd = (u32*) linearAlloc(gpuCmdSize * 4); GPU_Init(NULL); GPU_Reset(NULL, gpuCmd, gpuCmdSize); GPUCMD_SetBufferOffset(0); return true; }