| 434 | } |
| 435 | |
| 436 | Result Installer::WriteContents(OnStartWriteFunction on_start_write_fn, OnContentWriteFunction on_content_write_fn) { |
| 437 | auto nand_sys_explorer = fs::GetNANDSystemExplorer(); |
| 438 | u64 total_size = 0; |
| 439 | u64 total_written_size = 0; |
| 440 | std::vector<u32> content_file_idxs; |
| 441 | std::vector<NcmPlaceHolderId> content_placehld_ids; |
| 442 | std::vector<u32> content_write_idxs; |
| 443 | for(const auto &cnt: this->contents) { |
| 444 | const auto content_file_name = util::FormatContentId(cnt.content_id) + ((cnt.content_type == NcmContentType_Meta) ? ".cnmt" : "") + ".nca"; |
| 445 | const auto content_file_idx = this->pfs0_file.GetFileIndexByName(content_file_name); |
| 446 | GLEAF_RC_UNLESS(fs::PFS0::IsValidFileIndex(content_file_idx), rc::goldleaf::ResultInvalidNsp); |
| 447 | total_size += pfs0_file.GetFileSize(content_file_idx); |
| 448 | content_file_idxs.push_back(content_file_idx); |
| 449 | } |
| 450 | |
| 451 | ContentWriteContext write_ctx(on_content_write_fn, this->cnt_storage); |
| 452 | for(u32 i = 0; i < this->contents.size(); i++) { |
| 453 | const auto &cnt = this->contents.at(i); |
| 454 | const auto content_file_idx = content_file_idxs.at(i); |
| 455 | const auto content_file_size = this->pfs0_file.GetFileSize(content_file_idx); |
| 456 | |
| 457 | NcmPlaceHolderId placehld_id = {}; |
| 458 | memcpy(placehld_id.uuid.uuid, cnt.content_id.c, sizeof(placehld_id.uuid.uuid)); |
| 459 | content_placehld_ids.push_back(placehld_id); |
| 460 | const auto cnt_id = write_ctx.RegisterContent(static_cast<NcmContentType>(cnt.content_type), placehld_id, content_file_size); |
| 461 | content_write_idxs.push_back(cnt_id); |
| 462 | ncmContentStorageDeletePlaceHolder(&this->cnt_storage, &placehld_id); |
| 463 | GLEAF_RC_TRY(ncmContentStorageCreatePlaceHolder(&this->cnt_storage, &cnt.content_id, &placehld_id, content_file_size)); |
| 464 | } |
| 465 | |
| 466 | write_ctx.NotifyStart(on_start_write_fn); |
| 467 | |
| 468 | Thread cnt_write_thread; |
| 469 | GLEAF_RC_TRY(threadCreate(&cnt_write_thread, ContentWriteMain, reinterpret_cast<void*>(&write_ctx), nullptr, 1_MB, 0x1F, -2)); |
| 470 | GLEAF_RC_TRY(threadStart(&cnt_write_thread)); |
| 471 | |
| 472 | for(u32 i = 0; i < this->contents.size(); i++) { |
| 473 | const auto &cnt = this->contents.at(i); |
| 474 | const auto content_file_idx = content_file_idxs.at(i); |
| 475 | const auto content_file_name = this->pfs0_file.GetFile(content_file_idx); |
| 476 | const auto content_file_size = this->pfs0_file.GetFileSize(content_file_idx); |
| 477 | const auto content_write_id = content_write_idxs.at(i); |
| 478 | |
| 479 | u64 cur_written_size = 0; |
| 480 | auto rem_size = content_file_size; |
| 481 | const auto content_path = GLEAF_PATH_NAND_INSTALL_TEMP_DIR "/" + content_file_name; |
| 482 | switch(cnt.content_type) { |
| 483 | case NcmContentType_Meta: |
| 484 | case NcmContentType_Control: { |
| 485 | nand_sys_explorer->StartFile(content_path, fs::FileMode::Read); |
| 486 | break; |
| 487 | } |
| 488 | default: { |
| 489 | pfs0_file.GetExplorer()->StartFile(pfs0_file.GetPath(), fs::FileMode::Read); |
| 490 | break; |
| 491 | } |
| 492 | } |
| 493 |
no test coverage detected