| 68 | } |
| 69 | |
| 70 | class CtrScriptHost : public ScriptHost { |
| 71 | public: |
| 72 | int titleCount(void) override { return TitleCatalog::get().getTitleCount(BackupKind::Save); } |
| 73 | |
| 74 | bool titleAt(int idx, HostTitle& out) override |
| 75 | { |
| 76 | if (idx < 0 || idx >= titleCount()) { |
| 77 | return false; |
| 78 | } |
| 79 | Title title; |
| 80 | TitleCatalog::get().getTitle(title, idx, BackupKind::Save); |
| 81 | out.id = title.id(); |
| 82 | out.name = title.longDescription(); |
| 83 | out.productCode = title.productCode; |
| 84 | out.isCart = title.mediaType() == MEDIATYPE_GAME_CARD; |
| 85 | out.hasSave = title.accessibleSave(); |
| 86 | out.hasExtdata = title.accessibleExtdata(); |
| 87 | return true; |
| 88 | } |
| 89 | |
| 90 | int titleIndexOf(uint64_t id) override { return TitleCatalog::get().indexById((u64)id, BackupKind::Save); } |
| 91 | |
| 92 | std::string titleBackupPath(int idx, int kind) override |
| 93 | { |
| 94 | if (idx < 0 || idx >= titleCount()) { |
| 95 | return ""; |
| 96 | } |
| 97 | Title title; |
| 98 | TitleCatalog::get().getTitle(title, idx, BackupKind::Save); |
| 99 | BackupTarget target = title.backup(kind == 0 ? BackupKind::Save : BackupKind::Extdata); |
| 100 | return StringUtils::UTF16toUTF8(target.rootPath()); |
| 101 | } |
| 102 | |
| 103 | int savOpen(int titleIdx, int kind) override |
| 104 | { |
| 105 | if (titleIdx < 0 || titleIdx >= titleCount()) { |
| 106 | return -1; |
| 107 | } |
| 108 | const int slot = freeSlot(); |
| 109 | if (slot < 0) { |
| 110 | return -2; |
| 111 | } |
| 112 | |
| 113 | Title title; |
| 114 | TitleCatalog::get().getTitle(title, titleIdx, BackupKind::Save); |
| 115 | |
| 116 | // Only regular CTR saves and extdata are file-level archives; GBA VC |
| 117 | // (FSPXI raw), DSiWare (TWL FAT) and SPI cart saves are not reachable here. |
| 118 | if (kind == 0) { |
| 119 | const bool spiCart = title.mediaType() == MEDIATYPE_GAME_CARD && title.cardType() != CARD_CTR; |
| 120 | if (!title.accessibleSave() || title.isGBAVC() || title.isDSiWare() || spiCart) { |
| 121 | return -1; |
| 122 | } |
| 123 | } |
| 124 | else if (!title.accessibleExtdata()) { |
| 125 | return -1; |
| 126 | } |
| 127 |
nothing calls this directly
no outgoing calls
no test coverage detected