> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ダウンロード可能なコンテンツ (DLC) の管理とライセンス供与

> 耐久型製品をタイトルのダウンロード可能なコンテンツ (DLC) として使用します — パートナー センターのセットアップ、ライセンス チェック、インストール管理、およびランタイム エンタイトルメント コード。

ダウンロード可能なコンテンツ (DLC) は、購入するとユーザーにダウンロード可能なパッケージが提供される製品で構成されます。DLC は、その内容にアクセスする前に、独立してライセンス供与およびマウントする必要があります。

DLC パッケージは、[ゲームの製品共有モデル](/publishing/xstore-commerce/xstore-product-sharing)で説明されているとおり、各デバイスのコンテンツ共有の動作に応じてライセンス供与できます。

パートナー センターでは、パッケージのない耐久型製品もサポートしています。パッケージのない耐久型は、ライセンスのみの製品に適しており、ベース ゲームと共に既にインストールされているコンテンツを有効化できます。この種のライセンスのみの製品では、ユーザーがダウンロードする必要があった空のパッケージを作成する手順を省略できます。詳細については、[パッケージのない耐久型の使用方法](/publishing/xstore-commerce/xstore-dwob)を参照してください。

## DLC の開発ワークフロー

MicrosoftGame.config を通じてベース ゲームとの関連付けを行う方法など、DLC コンテンツの構成方法の詳細については、Downloadable content (DLC) packages のドキュメントを参照してください。

DLC のインストールには次の 3 つの方法があります。

1. [Loose DLC 配置](#1-loose-dlc-deployment)
2. [DLC パッケージのローカル インストール](#2-locally-install-dlc-package)
3. [Store から DLC パッケージをインストール](#3-install-dlc-package-from-store)

### 1. Loose DLC 配置

Loose DLC の MicrosoftGame.config とアセット ファイルを指すディレクトリをインストールします。

**XBOX:**

```cmd theme={null}
> xbapp deploy <DLC directory>

Package Full Name: 41336MicrosoftATG.DLC1_2020.10.14.0_neutral__dspnxghe87tn0
The operation completed successfully.
```

**PC:**

```cmd theme={null}
> wdapp register <DLC directory>  

Registered 41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0
Copied temporary generated AppXManifest.xml file to C:\Users\<ntuser>\AppData\Local\Temp\41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0_AppXManifest.xml
The operation completed successfully.
```

### 2. DLC パッケージのローカル インストール

makepkg で作成された .xvc/.msixvc をインストールします。

**XBOX:**

```cmd theme={null}
> xbapp install <xvc package>  

12:16:21.800 Registered for streaming: 41336MicrosoftATG.DLC1_2020.10.14.0_neutral__dspnxghe87tn0_xs.xvc
12:16:22.645 Launch   0.00% Package   0.00%
12:16:32.650 Launch 100.00% Package 100.00%
12:16:32.651 Streaming install finished

The operation completed successfully.
```

**PC:**

```cmd theme={null}
> wdapp install <.msixvc package>  

Starting installation. See the Microsoft Store app for further details.
Launch   100% Package   100%
Installed 100%.
Installed 41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0
```

### 3. Store から DLC パッケージをインストール

開発サンドボックスにサインインしたテスト アカウントで、Store アプリで DLC 製品ページを検索するかダイレクト リンクを開いてインストールします。

## DLC インストールの検証

**XBOX:**

```cmd theme={null}
> xbapp listdlc

Registered DLC by Package Full Name:

   41336MicrosoftATG.DLC1_2020.10.14.0_neutral__dspnxghe87tn0

The operation completed successfully.
```

**PC:**

```cmd theme={null}
> wdapp listdlc

Registered DLC packages by Package Full Name:

41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0

The operation completed successfully.
```

PC では、PowerShell で `get-appxpackage` を使用して、特定のタイトル用にインストールされた DLC を確認することもできます。**Dependencies** セクションに注目してください。

```cmd theme={null}
> get-appxpackage 41336MicrosoftATG.DownloadableContent

Name              : 41336MicrosoftATG.DownloadableContent
Publisher         : CN=A4954634-DF4B-47C7-AB70-D3215D246AF1
Architecture      : X64
ResourceId        :
Version           : 2020.10.14.0
PackageFullName   : 41336MicrosoftATG.DownloadableContent_2020.10.14.0_x64__dspnxghe87tn0
InstallLocation   : E:\Repos\ATG\gx_dev\Samples\Live\DownloadableContent\Gaming.Desktop.x64\Debug
IsFramework       : False
PackageFamilyName : 41336MicrosoftATG.DownloadableContent_dspnxghe87tn0
PublisherId       : dspnxghe87tn0
IsResourcePackage : False
IsBundle          : False
IsDevelopmentMode : True
NonRemovable      : False
Dependencies      : {41336MicrosoftATG.DLC1_2020.10.14.0_x64__dspnxghe87tn0}
IsPartiallyStaged : False
SignatureKind     : None
Status            : Ok
```

**SignatureKind** はインストールされているパッケージの種類を示します。ローカルでビルドしインストールされたパッケージは *None*、Store からインストールされたパッケージは *Store* です。

## DLC の購入とインストール

カタログの列挙方法とアドオン購入の提供方法を理解するには、[基本的な Store 操作](/publishing/xstore-commerce/xstore-basic-operations)を参照してください。アドオン製品は、`[XStoreProduct](/reference/system/xstore/xstore_members).hasDigitalDownload` を確認することで DLC かどうかを判定できます。

Store から DLC が購入されると、DLC はダウンロードのためにキューに入れられます。

[XStoreShowPurchaseUiAsync](/reference/system/xstore/xstore_members) を使用して DLC を購入した場合、DLC はダウンロードのためにキューに入れられません。代わりに、ゲームは以下のコードに従って手動でダウンロードを要求する必要があります。オプションとして、進行状況を追跡するモニターを作成できます。

**パッケージ識別子**は特定のパッケージを識別する不透明な文字列です。識別子はパッケージごとに一意ですが、ゲームの起動インスタンスごとに異なります。したがって、現在のセッション以外で識別子を保存または再利用しないでください。

シナリオに応じて、次の方法でパッケージの識別子を取得できます。

* [XStoreDownloadAndInstallPackagesAsync](/reference/system/xstore/xstore_members) を呼び出してパッケージをダウンロードおよびインストールした後、[XStoreDownloadAndInstallPackagesResult](/reference/system/xstore/xstore_members) を呼び出してそれらのパッケージのパッケージ識別子を取得できます。
* [XPackageEnumeratePackages](/reference/system/xstore/xstore_members) を呼び出し、列挙された各パッケージについて [XPackageEnumerationCallback](/reference/system/xstore/xstore_members) コールバック関数に渡される [XPackageDetails](/reference/system/xstore/xstore_members) 構造体からパッケージ識別子を取得することで、既にダウンロードおよびインストールされているパッケージのパッケージ識別子を取得できます。
* [XPackageGetCurrentProcessPackageIdentifier](/reference/system/xstore/xstore_members) を呼び出すことで、現在のゲームのパッケージ識別子を取得できます。

```cpp theme={null}
void StartDownload()
{
    auto async = new XAsyncBlock{};
    async->queue = m_asyncQueue;
    async->context = this;
    async->callback = [](XAsyncBlock* asyncBlockInner)
    {
        uint32_t count = 0;
        HRESULT hr = XStoreDownloadAndInstallPackagesResultCount(asyncBlockInner, &count);

        std::vector<char[XPACKAGE_IDENTIFIER_MAX_LENGTH]> packageIds(count);

        XStoreDownloadAndInstallPackagesResult(asyncBlockInner, count, packageIds.data());

        for(auto packageId : packageIds)
        {
            hr = XPackageCreateInstallationMonitor(
                packageId,  
                0,  
                nullptr,  
                1000,  
                m_asyncQueue,
                &m_pimHandle);

            if(SUCCEEDED(hr))
            {
                XTaskQueueRegistrationToken callbackToken;

                XPackageRegisterInstallationProgressChanged(
                    m_pimHandle,
                    this,
                    [](void* context, XPackageInstallationMonitorHandle pimHandle)
                    {
                        XPackageInstallationProgress progress;
                        XPackageGetInstallationProgress(pimHandle, &progress);

                        if(!progress.completed)
                        {
                            printf("%llu%% installed\n", static_cast<double>(progress.installedBytes) / static_cast<double>(progress.totalBytes);
                        }
                        else
                        {
                            XPackageCloseInstallationMonitorHandle(pimHandle);
                        }
                    }, &callbackToken);

                // Persist callbackToken to unregister upon completion
            }
        }

        delete asyncBlockInner;
    }

    const char* storeIds[] =  
    {
        "9PLNMXRKNM4C",  
        "9PLNMXRKNM5D"
    };

    HRESULT hr = XStoreDownloadAndInstallPackagesAsync(storeContext, storeIds, ARRAYSIZE(storeIds), async);

    if (FAILED(hr))
    {
        delete async;
        return;
    }
}
```

## DLC パッケージの列挙

DLC のインストール方法に関係なく、使用する前にゲームでインストールされている DLC を列挙する必要があります。インストールされている DLC を列挙するときにパッケージ識別子が取得されます。

```cpp theme={null}
bool CALLBACK DlcCallback(void* context, const XPackageDetails* details)
{
    printf("DLC found: name: %s packageId: %s\n", details->displayName, details->packageIdentifier);

    return true;
}

void RefreshInstalledPackages()
{
    HRESULT hr = XPackageEnumeratePackages(
        XPackageKind::Content,  
        XPackageEnumerationScope::ThisAndRelated,  
        this,  
        DlcCallback);
}
```

## DLC パッケージがインストールされたことの検出

```cpp theme={null}
void RegisterPackageInstalledEvent()
{
    XPackageRegisterPackageInstalled(
        m_asyncQueue,
        this,  
        [](void *context, const XPackageDetails *package)
        {
            printf("Package Installed event received: %s\n", package->displayName);
        },  
        &m_packageInstallToken);
}
```

コード例に到達しない場合は、[トラブルシューティング](/publishing/xstore-commerce/xstore-troubleshooting)セクションを参照してください。イベントは、DLC パッケージのインストール方法に関係なくトリガーされる必要があります。

## DLC のライセンス取得

開発中は、[開発中の DLC ライセンス供与のテスト](#testing-dlc-licensing-in-development)のメモを参照してください。

ベース ゲームは、ユーザーに DLC のコンテンツへのアクセスを許可すべきかを判断するために、DLC のライセンスを取得する必要があります。

ゲームは通常、制限的ライセンスを使用します。ゲームがパッケージのライセンスを取得すると、パッケージへのアクセスはそのデバイスと製品のインスタンスにロックされます。別のインスタンスまたはデバイスがアクセス権とライセンスを取得する前に、ゲームはライセンスを解放する必要があります。ゲームが制限的ライセンスを使用するように構成されていることを確認するには、Microsoft アカウント担当者にお問い合わせください (パートナー センターでは構成できません)。詳細については、[オープン ライセンスと制限的ライセンス](/publishing/xstore-commerce/xstore-open-restrictive-licensing)を参照してください。

ゲームはライセンスを解放する必要があるため、取得したすべての DLC ライセンスを追跡し、不要になったときや終了時にそれらを解放する責任があります。ゲームがライセンスの解放に失敗した場合、タイムアウト期間の後にライセンスは自動的に解放されます。

```cpp theme={null}
void CALLBACK AcquireLicenseForPackageCallback(XAsyncBlock* async)
{
    XStoreLicenseHandle licenseHandle = nullptr;

    HRESULT hr = XStoreAcquireLicenseForPackageResult(
        async,
        &licenseHandle);

    if (FAILED(hr))
    {
        printf("Failed retrieve the license handle: 0x%x\n", hr);
        return;
    }

    bool isValid = XStoreIsLicenseValid(licenseHandle);

    printf("isValid: %s\n", isValid ? "true" : "false");

    hr = XStoreRegisterPackageLicenseLost(licenseHandle, m_asyncQueue, context,
       [](void *context)  
       {
           // Check if the license lost corresponded to any mounted DLC
           // If so, it is up to the game to determine an appropriate time
           // to unmount the DLC, e.g. after the current match is completed
       });

    delete async;
}

void AcquireLicenseForPackage(const char* packageIdentifier)
{
    auto async = new XAsyncBlock{};
    async->context = this;
    async->queue = m_asyncQueue;
    async->callback = AcquireLicenseForPackageCallback;

    HRESULT hr = XStoreAcquireLicenseForPackageAsync(
        m_storeContext,
        packageIdentifier,
        async);

    if (FAILED(hr))
    {
        delete async;
        return;
    }
}
```

## DLC のライセンス ソースを判定する

識別子の種類に応じて [XStoreCanAcquireLicenseForPackageAsync](/reference/system/xstore/xstore_members) または [XStoreCanAcquireLicenseForStoreIdAsync](/reference/system/xstore/xstore_members) を使用すると、DLC の次の状況を判定できます。

1. ライセンス供与可能かどうか。可能でなければ購入オプションを提示できます
2. ディスクによるライセンス供与か、デジタル ライセンスによるライセンス供与か

```cpp theme={null}
void PreviewLicense(const char* storeId)
{
    auto async = new XAsyncBlock{};
    async->queue = m_asyncQueue;
    async->callback = [](XAsyncBlock* async)
    {
        XStoreCanAcquireLicenseResult result;

        HRESULT hr = XStoreCanAcquireLicenseForStoreIdResult(
            async,
            &result);

        if (FAILED(hr))
        {
            printf("Error calling XStoreCanAcquireLicenseForStoreIdResult: 0x%x\n", hr);
        }
        else
        {
            // Status = 1 Licensable and
            // a. licensableSku = "DISC" if disc licensed
            // b. licensableSku = "0010" or similar if digital licensed
            printf("Status: %u LicensableSku: %s\n", result.status, result.licensableSku);
        }

        delete async;
    };

    HRESULT hr = XStoreCanAcquireLicenseForStoreIdAsync(
        m_xStoreContext,
        storeId,
        async);

    if (FAILED(hr))
    {
        delete async;

        printf("Error calling XStoreCanAcquireLicenseForStoreIdAsync: 0x%x", hr);
        return;
    }
}
```

## DLC のマウントとアンマウント

DLC ライセンスが正常に取得されると、DLC コンテンツをマウントしてアクセスできます。

```cpp theme={null}

void CALLBACK MountPackageCallback(XAsyncBlock* async)
{
    XPackageMountHandle mountHandle = {};

    HRESULT hr = XPackageMountWithUiResult(async, &mountHandle);

    if (SUCCEEDED(hr))
    {
        // Access DLC goodness
    }
    else
    {
        XStoreCloseLicenseHandle(license);
        printf("Error mounting package: 0x%x\n", hr);
    }

    delete async;
};

void MountPackage(const char* packageIdentifier)
{
    auto async = new XAsyncBlock{};
    async->queue = m_asyncQueue;
    async->context = context;
    async->callback = MountPackageCallback;

    HRESULT hr = XPackageMountWithUiAsync(packageIdentifier, async);

    if (FAILED(hr))
    {
        printf("XPackageMountWithUiAsync failed : 0x%x\n", hr);
        delete async;
    }
}
```

アンマウント時は、すべてのトークンとハンドルを解放してください。

```cpp theme={null}
void UnmountPackage(XPackageMountHandle mountHandle, XStoreLicenseHandle license, XTaskQueueRegistrationToken licenseLostToken)
{
    XStoreUnregisterPackageLicenseLost(license, licenseLostToken, false);

    XPackageCloseMountHandle(mountHandle);

    XStoreCloseLicenseHandle(license);
}
```

## DLC のアンインストール

DLC パッケージをアンインストールするには [XPackageUninstallPackage](/reference/system/xstore/xstore_members) を使用します。パッケージは最初にアンマウントする必要があります。

## Smart Delivery と DLC

XBOX Series X/S タイトルは、XBOX One タイトル向けに作成された DLC をライセンス供与およびマウントできます。通常、このシナリオは DLC パッケージがゲームで使用されるデータを含まない場合に発生します。確認する唯一の方法は、ERA DLC の package.appxmanifest 内の `AllowedProduct` ID (GUID) が、パートナー センターで製品に割り当てられているレガシー XBOX 製品 ID と一致するかどうかを確認することです。

一致しない場合、そのタイトルはおそらく廃止された XBOX Developer Portal (XDP) から移行されたものであり、XBOX Series X/S 版が XBOX One の製品 ID に割り当てられているため、Store からダウンロードしたパッケージでのみ機能します。開発目的の場合、[トラブルシューティング](/publishing/xstore-commerce/xstore-troubleshooting)セクションのメモを参照してください。

## 異なる製品の DLC

別の製品の DLC を列挙して使用することが可能です。異なる製品の DLC を使用したいタイトルの場合、パートナー センターの **\[製品関係のセットアップ]** セクションで、その DLC 製品に「販売および使用可能」の関係を割り当てます。選択できる製品は、発行元アカウントに限られます。

## 開発中の DLC ライセンス供与のテスト

詳細については、[ライセンス テストの有効化](/publishing/xstore-commerce/xstore-licensing-setup)を参照してください。

ローカル DLC パッケージは /contentid パラメーターを使用して作成する必要があります。

各 DLC パッケージは、既定値から EKBID をオーバーライドする必要があります。

## リファレンス API ドキュメント

* [XStore (API の内容)](/reference/system/xstore/xstore_members)
  * 関数
    * [XStoreShowPurchaseUiAsync](/reference/system/xstore/xstore_members)
    * [XStoreDownloadAndInstallPackagesAsync](/reference/system/xstore/xstore_members)
    * [XStoreDownloadAndInstallPackagesResult](/reference/system/xstore/xstore_members)
    * [XStoreCanAcquireLicenseForPackageAsync](/reference/system/xstore/xstore_members)
    * [XStoreCanAcquireLicenseForStoreIdAsync](/reference/system/xstore/xstore_members)
  * 構造体
    * [xstoreproduct](/reference/system/xstore/xstore_members)
* [XPackage (API の内容)](/reference/system/xstore/xstore_members)
  * 関数
    * [XPackageEnumeratePackages](/reference/system/xstore/xstore_members)
    * [XPackageEnumerationCallback](/reference/system/xstore/xstore_members)
    * [XPackageGetCurrentProcessPackageIdentifier](/reference/system/xstore/xstore_members)
    * [XPackageUninstallPackage](/reference/system/xstore/xstore_members)
  * 構造体
    * [XPackageDetails](/reference/system/xstore/xstore_members)

## 関連項目

[コマースの概要](/publishing/xstore-commerce/xstore-commerce-overview)

[ライセンス テストの有効化](/publishing/xstore-commerce/xstore-licensing-setup)

[パッケージのない耐久型の使用方法](/publishing/xstore-commerce/xstore-dwob)

[XStore API リファレンス](/reference/system/xstore/xstore_members)


## Related topics

- [パッケージのない耐久型の使用方法](/ja-jp/publishing/xstore-commerce/xstore-dwob.md)
- [ライセンス供与テストの有効化](/ja-jp/publishing/xstore-commerce/xstore-licensing-setup.md)
- [適切な製品タイプを選択する](/ja-jp/publishing/xstore-commerce/xstore-choosing-product-type.md)
- [プレイヤーにアドオン コンテンツへのアクセスを付与する](/ja-jp/publishing/xstore-commerce/xstore-granting-access.md)
- [GDK コマース システムの概要](/ja-jp/publishing/xstore-commerce/xstore-overview.md)
