この章では、アプリケーションから扱うことのできるメモリ領域と、カードアプリが記録されるニンテンドー3DS 専用ゲームカードについて説明します。
3.1. メモリ
3.1.1. メモリマップ
アプリケーションから見たメモリマップを以下に示します。下図のメモリマップは製品版のものです。
アプリケーションからメモリへのアクセスは、仮想アドレスで行われます。
セキュリティ上の理由から、プログラムがロードされた領域以外のメモリ(ヒープメモリやデバイスメモリなど)にロードされたデータ列を実行することはできません。
0x4000_0000 以降は予約領域です。
3.1.2. デバイスメモリ
デバイスメモリとは、GPU などの周辺デバイスからのアクセスの際に OS がアドレスの整合性を保証しているメモリ領域のことです。グラフィックスで利用している GPU や、サウンドで利用している DSP などがアクセスするバッファには、このデバイスメモリに確保されていなければならないものもあります。逆に、デバイスメモリに確保してはいけないバッファもあり、基本的にアライメントが 4096 Byte、サイズが 4096 Byte の倍数でなければならないバッファがこれに該当します。
デバイスメモリとして確保するメモリ領域のサイズは nn::os::SetDeviceMemorySize()
で指定することができます。指定の際は、nn::os::DEVICE_MEMORY_UNITSIZE
( 4096 Byte ) の倍数単位で設定してください。CTR の場合はメインプログラムとヒープメモリ、デバイスメモリの合計が 64 MByte(開発機は 96 MByte)に収まる範囲で、SNAKE の場合はメインプログラムとヒープメモリ、デバイスメモリの合計が 124 MByte(開発機は 178 MByte)に収まる範囲でそれぞれ確保することができます。再度呼び出して、確保するメモリ領域のサイズを変更することも可能ですが、その場合は変更前後のサイズが 1 MByte(1048576 Byte)の倍数でなければなりません。この時、サイズ 0 へ変更する場合は変更前のサイズが 1 MByte の倍数でなくても問題ありません。サイズ 0 から変更する場合も同様に変更後のサイズは 1 MByte の倍数でなくても問題ありません。ただし、4096 Byte の倍数にする必要はあります。
確保される領域のアドレスが毎回同じである保証はありませんので、サイズを指定したあとに nn::os::GetDeviceMemoryAddress()
で先頭アドレスを取得してからデバイスメモリにアクセスしてください。現在確保中のメモリ領域のサイズは nn::os::GetDeviceMemorySize()
で取得することができます。
デバイス |
バッファの種類 |
アライメント |
備考 |
---|---|---|---|
GPU |
テクスチャイメージ |
128 Byte |
|
頂点バッファ |
1 ~ 4 Byte |
頂点属性によって変化します。 |
|
ディスプレイバッファ |
16 Byte |
|
|
DSP |
音源データ |
32 Byte |
音源データを格納する領域全体のサイズは 32 Byte の倍数でなければなりません。 |
CAMERA |
受信用バッファ |
64 Byte(推奨) |
デバイスメモリ以外に確保したバッファを使用すると Panic で停止します。 |
Y2R |
画像データ転送元 / 転送先バッファ |
64 Byte(推奨) |
デバイスメモリ以外に確保したバッファを使用すると Panic で停止します。 |
GPU がアクセスするバッファは VRAM 上に確保することもできます。
バッファ |
備考 |
---|---|
マイクのサンプリング結果を格納するバッファ |
アライメントは 4096 Byte、サイズは 4096 Byte の倍数でなければなりません。 |
UDS ライブラリの受信バッファ |
アライメントは 4096 Byte、サイズは 4096 Byte の倍数でなければなりません。 |
Socket ライブラリの受信バッファ |
アライメントは 4096 Byte、サイズは 4096 Byte の倍数でなければなりません。 |
HTTP ライブラリの作業バッファ |
アライメントは 4096 Byte、サイズは 4096 Byte の倍数でなければなりません。 |
DLP ライブラリの作業バッファ |
アライメントは 4096 Byte、サイズは 4096 Byte の倍数でなければなりません。 |
ACT ライブラリの通信用バッファ |
アライメントは 4096 Byte、サイズは 4096 Byte の倍数でなければなりません。 |
3.1.3. VRAM
VRAM-A と VRAM-B の 2 チャンネルで構成され、それぞれが 3 MByte の合計 6 MByte 搭載されています。
カラーバッファの確保など、GX(グラフィックス)ライブラリが使用するメモリ領域の管理はアプリケーションで行わなければなりませんが、CPU で VRAM 上のメモリ領域を読み込んだときに取得する内容が正確であるかどうかは保証されていません。VRAM 上のメモリ領域を確保する際には、nngxGetVramStartAddr()
、nngxGetVramEndAddr()
、nngxGetVramSize()
で VRAM の開始アドレス、終了アドレス、サイズを取得し、要求されたメモリ領域の配置をアプリケーションで管理してください。
GX ライブラリやライブラリが使用するメモリ領域の管理方法については「5.5. GX ライブラリの初期化」や「3DS プログラミングマニュアル - グラフィックス基本編」を参照してください。
3.1.4. ヒープメモリ
ファイルの読み込みバッファなど、アプリケーションが自由に使うことのできるメモリ領域です。ヒープメモリの確保は nn::os::SetHeapSize()
でサイズを指定することで行います。サイズは nn::os::HEAP_UNITSIZE
( 4096 ) の倍数のバイト数である必要があります。CTR の場合はメインプログラムとヒープメモリ、デバイスメモリとの合計が 64 MByte(開発機は 96 MByte)に収まる範囲で確保することができます。SNAKE の場合はヒープメモリの最大が 96 MByte かつ、メインプログラム、ヒープメモリ、デバイスメモリの合計が 124 MByte(開発機は 178 MByte)に収まる範囲で確保することができます。再度呼び出して、確保するメモリ領域のサイズを変更することも可能です。
利用状況に応じてヒープメモリ領域のサイズを拡大・縮小し、それに合わせてデバイスメモリ領域のリサイズを行う場合、ヒープメモリ領域の取り扱いは次の点に注意してください。
- ヒープメモリ領域は、拡大したのち、縮小するときは拡大したときの増加分と同じサイズ分を減少してください。
- ヒープメモリ領域は複数回に分けて拡大することが可能です。その場合は、縮小するときも拡大する前のサイズに戻していくように、段階的に実行してください。
上記に違反すると未割当の領域をデバイスメモリとして確保できない場合があります。
図 3-2 の例のように、ヒープメモリ領域を Step 1 、 Step 2、 Step 3 と段階的に拡大していた状態から、ヒープメモリ領域を減らしてデバイスメモリ領域を拡大する場合は、ヒープメモリ領域を拡大する前のサイズに戻すように、まず Step 3 での増加分と同じサイズ分を減少し(Step 4)、次にStep 2 での増加分と同じサイズ分を減少させます(Step 5)。
ヒープメモリ領域は可能な限り一括で必要なサイズを確保し、リサイズせずに使用することを推奨します。どうしてもリサイズが必要な場合のみ上述のように段階的に行ってください。ただし、細かい単位でリサイズを行うとメモリアクセスの著しいパフォーマンス低下を招く原因になります。
確保される領域のアドレスが毎回同じである保証はありませんので、ヒープメモリへのアクセスは、サイズを指定したあとに nn::os::GetHeapAddr()
で先頭アドレスを取得してから行ってください。現在確保中のヒープメモリのサイズは nn::os::GetHeapSize()
で取得することができます。
3.2. ニンテンドー3DS 専用ゲームカード
ニンテンドー3DS 専用ゲームカード(3DS カード)には、"CARD1" と "CARD2" の 2 種類があり、タイトルの仕様に応じた適切なものが使用可能です。
原則として、バックアップメモリの容量が 512 KByte 以下のタイトルは CARD1 を、1 MByte 以上のタイトルは CARD2 を、それぞれ使用してください。
3.2.1. CARD1
CARD1 は、ROM(Read Only Memory)とバックアップメモリ(書き換え可能な不揮発性メモリ)の 2 つのデバイスを搭載しているカードです。
3.2.1.1. ROM
CARD1 の ROM の転送速度は使用する SDK のバージョンやデータサイズによって異なります。また、デバイスの個体差により若干のばらつきがありますので、転送速度に依存するようなアプリケーションの実装はしないでください。
ROM の容量は、現時点で 128 MByte ~ 4 GByte の 6 種類を用意しています。
ROM の容量 |
転送 |
仕向け先による使用可能領域のサイズ |
||
---|---|---|---|---|
日本/北米/韓国向け |
欧州向け |
中国/台湾向け |
||
128 MByte |
※ |
93.5 MByte |
91.5 MByte |
61.5 MByte |
256 MByte |
219.0 MByte |
217.0 MByte |
187.0 MByte |
|
512 MByte |
470.0 MByte (492,830,720 byte) |
468.0 MByte |
438.0 MByte |
|
1 GByte |
921.5 MByte |
919.5 MByte |
889.5 MByte |
|
2 GByte |
1875.5 MByte |
1873.5 MByte |
1843.5 MByte |
|
4 GByte |
3783.0 MByte |
3781.0 MByte |
3751.0 MByte |
※ 使用する SDK のバージョンやデータサイズによって異なります。詳しくは「3DS パフォーマンス TIPS」を参照してください。
3.2.1.2. バックアップメモリ
CARD1 のバックアップメモリの転送速度は、使用する SDK のバージョンやデータサイズによって異なります。また、デバイスの個体差により若干のばらつきがありますので、転送速度に依存するようなアプリケーションの実装はしないでください。また、書き換え回数についてはガイドラインを参照し、その規定に従ってください。
バックアップメモリの容量は、128 KByte と 512 KByte の 2 種類を用意しています。バックアップメモリに 1 MByte 以上の容量が必要な場合は、CARD2 を使用してください。
バックアップメモリの工場出荷時の内容は、全領域が 0xFF で埋められていることが保証されています。デバッグ時に、工場出荷状態をエミュレートする場合は全領域を 0xFF で埋めてください。
バックアップメモリに保存されるセーブデータは、ライブラリによるバックアップ領域の二重化を有効にすることができます。ただし、二重化を有効にした場合、実際にファイルの保存に使用することのできる容量は全容量の 40 % 程度になります。
バックアップメモリの容量 |
転送速度 |
二重化有効時の使用可能領域のサイズ |
---|---|---|
128 KByte |
※ |
50 KByte 以下 |
512 KByte |
239 KByte 以下 |
※ 使用する SDK のバージョンやデータサイズによって異なります。詳しくは「3DS パフォーマンス TIPS」を参照してください。
3.2.2. CARD2
CARD2 は、ROM とバックアップメモリの両方の機能を持つ Writable メモリを搭載しているカードです。
3.2.2.1. Writable メモリ
CARD2 の Writable メモリの転送速度は、使用する SDK のバージョンやデータサイズによって異なります。デバイスの個体差により若干のばらつきがありますので、転送速度に依存するようなアプリケーションの実装はしないでください。また、書き換え回数についてはガイドラインを参照し、その規定に従ってください。
Writable メモリは、ROM 領域(書き換え不可)とバックアップ領域(書き換え可能)の 2 つの領域の境界を 1 MByte 単位で変更することができます。
バックアップ領域は、CARD1 のバックアップメモリと同様に、ライブラリによる二重化を選択することができます。ファイルの保存に使用することのできる容量についても、同様の計算で求めることができます。バックアップ領域として指定可能なサイズの上限は Writable メモリの容量の半分です。Writable メモリの容量は、512 MByte ~ 2 GByte の 3 種類を用意しています。
Writable メモリの容量 |
転送 |
仕向け先による使用可能領域のサイズ |
||
---|---|---|---|---|
日本/北米/韓国向け |
欧州向け |
中国/台湾向け |
||
512 MByte |
※ |
412.5 MByte |
410.5 MByte |
412.5 MByte |
1 GByte |
889.5 MByte |
887.5 MByte |
889.5 MByte |
|
2 GByte |
1843.5 MByte |
1841.5 MByte |
1843.5 MByte |
※ 使用する SDK のバージョンやデータサイズによって異なります。詳しくは「3DS パフォーマンス TIPS」を参照してください。