1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_Memory.h
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_DEMO_MEMORY_H_
19 #define NW_DEMO_MEMORY_H_
20 
21 #include <nw/types.h>
22 #include <nw/os/os_Memory.h>
23 #include <nn/dbg.h>
24 #include <nn/fnd.h>
25 
26 namespace nw {
27 namespace demo {
28 
29 class DemoAllocator;
30 
31 // デモではデバイスメモリから全てのメモリを確保するようになっています。
32 
33 // デモで使用するメモリサイズです。
34 const size_t DEMO_MEMORY_SIZE = 0x1000000;
35 
36 // パーティクル用のメモリサイズです。
37 const size_t DEMO_PARTICLE_MEMORY_SIZE = 0x100000;
38 
39 //=====================
40 //! @name メモリアロケーター
41 //@{
42 
43 //! @brief 与えられたデモアロケータを初期化します。
44 //!
45 //! @param[in] allocator 初期化するデモアロケータです。
46 //! @param[in] size アロケータで管理するメモリサイズです。
47 //! @param[in] option 拡張ヒープのオプションです。
48 //!
49 void InitializeDemoAllocator(DemoAllocator* allocator, size_t size, bit32 option = 0 );
50 
51 //! @brief 与えられたデモアロケータを解放します。
52 //!
53 //! @param[in] allocator 解放するデモアロケータです。
54 //!
55 void FinalizeDemoAllocator(DemoAllocator* allocator);
56 
57 //---------------------------------------------------------------------------
58 //! @brief       デモ用にメモリを初期化します。
59 //!
60 //!              明示的に呼ばれなかった場合には、初回のアロケート実行時に実行されます。
61 //---------------------------------------------------------------------------
62 void InitializeDemoMemory();
63 
64 //---------------------------------------------------------------------------
65 //! @brief       アライメントされたメモリを確保したアドレスへ戻します。
66 //!
67 //! @param[in]   memory  アラインされたメモリのポインタです。
68 //!
69 //! @return      アライン前のアドレスを返します。
70 //---------------------------------------------------------------------------
71 void* UnAlignMemory( void* memory );
72 
73 //---------------------------------------------------------------------------
74 //! @brief       メインメモリからメモリ領域を確保します。
75 //!
76 //! @param[in]   size      確保するメモリサイズです。
77 //! @param[in]   alignment 確保するメモリのアライメント値です。
78 //!
79 //! @return      確保したメモリアドレスです。
80 //---------------------------------------------------------------------------
81 void* Alloc(size_t size, u8 alignment = 4);
82 
83 //---------------------------------------------------------------------------
84 //! @brief       ヒープへメモリ領域を解放します。
85 //!
86 //! @param[in]   memory  解放するメモリ領域です。
87 //---------------------------------------------------------------------------
88 void  Free(void* memory);
89 
90 //---------------------------------------------------------------------------
91 //! @brief       メインメモリの状態を表示します。
92 //---------------------------------------------------------------------------
93 void Dump();
94 
95 //@}
96 
97 //---------------------------------------------------------------------------
98 //! @brief   デモ用のメインメモリアロケータです。
99 //!
100 //!          内部で CTR-SDK の拡張ヒープを使用しています。
101 //---------------------------------------------------------------------------
102 class DemoAllocator : public nw::os::IAllocator
103 {
104 public:
105     //! @brief コンストラクタです。
DemoAllocator()106     DemoAllocator()
107     : m_StartAddress(0),
108       m_BreakAllocAddress(NULL),
109       m_BreakAllocSize(0),
110       m_BreakFreeAddress(NULL),
111       m_BreakFreeSize(0)
112     {}
113 
114     //=====================
115     //! @name 作成/破棄
116     //@{
117 
118     //! @brief デモ用のアロケータを初期化します。
119     //!
120     //!        内部で拡張ヒープを初期化します。
121     //!
122     //! @param[in] startAddress 先頭アドレスです。
123     //! @param[in] size アロケートできるサイズです。
124     //! @param[in] option 拡張ヒープのオプションです。
125     //!
126     void Initialize(uptr startAddress, size_t size, bit32 option = 0);
127 
128     //! @brief デモ用のアロケータを破棄します。
129     //!
130     void Finalize();
131 
132     //@}
133 
134 
135     //! @brief 初期化時に指定した先頭アドレスを取得します。
136     //!
137     //! @return 先頭アドレスです。
GetStartAddress()138     uptr GetStartAddress() const { return m_StartAddress; }
139 
140     //=====================
141     //! @name メモリの確保と解放
142     //@{
143 
144     //! @brief メインメモリからメモリを確保します。
145     //!
146     //! @param[in] size      確保するメモリサイズです。
147     //! @param[in] alignment アライメントです。
148     //!
149     //! @return 確保したメモリアドレスを返します。
Alloc(size_t size,u8 alignment)150     virtual void* Alloc(size_t size, u8 alignment)
151     {
152         NW_ASSERT(size != 0);
153 
154         void* memory = m_Heap.Allocate(size, alignment);
155 
156 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
157         if (memory != NULL)
158         {
159             void* unalignMemory = UnAlignMemory(memory);
160             if (unalignMemory == m_BreakAllocAddress &&
161                 (m_BreakAllocSize == 0 || GetMemoryBlockSize(unalignMemory) == m_BreakAllocSize))
162             {
163                 NW_DEV_LOG("Alloc(): Specified memory block allocated\n");
164     #if defined(NW_DEBUG_BREAK_ALLOCATOR)
165                 nn::dbg::Break(nn::dbg::BREAK_REASON_USER);
166     #endif
167             }
168         }
169 #endif
170 
171         return memory;
172     }
173 
174     using nw::os::IAllocator::Alloc;
175 
176     //! @brief メインメモリにメモリを返却します。
177     //!
178     //! @param[in] memory    返却するメモリアドレスです。
Free(void * memory)179     virtual void Free(void* memory)
180     {
181 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
182         void* unalignMemory = UnAlignMemory(memory);
183         if (unalignMemory == m_BreakFreeAddress &&
184             (m_BreakFreeSize == 0 || GetMemoryBlockSize(unalignMemory) == m_BreakFreeSize))
185         {
186             NW_DEV_LOG("Free(): Specified memory block freed\n");
187 #if defined(NW_DEBUG_BREAK_ALLOCATOR)
188             nn::dbg::Break(nn::dbg::BREAK_REASON_USER);
189 #endif
190         }
191 #endif
192 
193         m_Heap.Free(memory);
194     }
195 
196     //@}
197     //=====================
198     //! @name デバッグ
199     //@{
200 
201 
202 
203     //---------------------------------------------------------------------------
204     //! @brief       空きメモリサイズを返します。
205     //!
206     //! @return      空きメモリサイズです。
207     //---------------------------------------------------------------------------
208     size_t GetFreeSize();
209 
210     //---------------------------------------------------------------------------
211     //! @brief       割り当てられたメモリサイズを返します。
212     //!
213     //! @return      割り当てられたメモリサイズです。
214     //---------------------------------------------------------------------------
215     size_t GetTotalSize();
216 
217     //---------------------------------------------------------------------------
218     //! @brief       確保されたメモリブロックのサイズを返します。
219     //!
220     //! @param[in]   address メモリブロックの先頭アドレスを指定します。
221     //!
222     //! @return      指定されたブロックのサイズです。
223     //---------------------------------------------------------------------------
224     size_t GetMemoryBlockSize(void* address);
225 
226 
227     //! @brief  メインメモリの状態を表示します。
228     void Dump();
229 
230     //! @brief  メモリ確保時の停止条件を設定します。
231     //!
232     //!         指定したアドレスとサイズのメモリ確保が行われるときにプログラムを強制的に一時停止するように設定します。
233     //!         NW_DEBUG_TRAP_ALLOCATOR マクロと NW_DEBUG_BREAK_ALLOCATOR マクロを定義することでこの機能は有効になります。
234     //!         NW_DEBUG_TRAP_ALLOCATOR マクロのみを定義した場合はメッセージ出力のみを行います。
235     //!         サイズに 0 を指定するとアドレスのみを条件とします。
236     //!
237     //!         アドレス、サイズともに Dump() で表示される数値(実際に確保されたアドレスとサイズ)を指定します。
238     //!
239     //! @param  address ブレーク条件のアドレスです。
240     //! @param  size ブレーク条件のサイズです。
SetBreakAlloc(int address,size_t size)241     void SetBreakAlloc(int address, size_t size)
242     {
243 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
244         m_BreakAllocAddress = reinterpret_cast<void *>(address);
245         m_BreakAllocSize = size;
246 #else
247         NW_UNUSED_VARIABLE(address);
248         NW_UNUSED_VARIABLE(size);
249 #endif
250     }
251 
252     //! @brief  メモリ解放時の停止条件を設定します。
253     //!
254     //!         指定したアドレスとサイズのメモリが解放されるときにプログラムを強制的に一時停止するように設定します。
255     //!         NW_DEBUG_TRAP_ALLOCATOR マクロと NW_DEBUG_BREAK_ALLOCATOR マクロを定義することでこの機能は有効になります。
256     //!         NW_DEBUG_TRAP_ALLOCATOR マクロのみを定義した場合はメッセージ出力のみを行います。
257     //!         サイズに 0 を指定するとアドレスのみを条件とします。
258     //!
259     //!         アドレス、サイズともに Dump() で表示される数値(実際に確保されたアドレスとサイズ)を指定します。
260     //!
261     //! @param  address ブレーク条件のアドレスです。
262     //! @param  size ブレーク条件のサイズです。
SetBreakFree(int address,size_t size)263     void SetBreakFree(int address, size_t size)
264     {
265 #if defined(NW_DEBUG_TRAP_ALLOCATOR)
266         m_BreakFreeAddress = reinterpret_cast<void *>(address);
267         m_BreakFreeSize = size;
268 #else
269         NW_UNUSED_VARIABLE(address);
270         NW_UNUSED_VARIABLE(size);
271 #endif
272     }
273 
274     //@}
275 
276 
277 
278 private:
279     uptr m_StartAddress;
280 
281     void* m_BreakAllocAddress;
282     size_t m_BreakAllocSize;
283 
284     void* m_BreakFreeAddress;
285     size_t m_BreakFreeSize;
286 
287     nn::fnd::ExpHeap m_Heap;
288 };
289 
290 
291 //---------------------------------------------------------------------------
292 //! @brief        デモ用のフレームヒープアロケータです。
293 //!
294 //!               内部で CTR-SDK のフレームヒープを使用しています。
295 //---------------------------------------------------------------------------
296 class FrameHeapAllocator : public nw::os::IAllocator
297 {
298 public:
299     //! @brief コンストラクタです。
FrameHeapAllocator()300     FrameHeapAllocator()
301     : m_StartAddress(0)
302     {}
303 
304     //! @brief コンストラクタです。
305     //!
306     //!        フレームヒープの初期化も行ないます。
307     //!
308     //! @param[in] startAddress 先頭アドレスです。
309     //! @param[in] size アロケートできるサイズです。
310     //! @param[in] option フレームヒープのオプションです。
311     //!
312     FrameHeapAllocator(uptr startAddress, size_t size, bit32 option = 0)
m_StartAddress(startAddress)313     : m_StartAddress(startAddress)
314     {
315         Initialize(startAddress, size, option);
316     }
317 
318     //=====================
319     //! @name 作成/破棄
320     //@{
321 
322     //! @brief デモ用のフレームヒープアロケータを初期化します。
323     //!
324     //!        内部でフレームヒープを初期化します。
325     //!
326     //! @param[in] startAddress 先頭アドレスです。
327     //! @param[in] size アロケートできるサイズです。
328     //! @param[in] option フレームヒープのオプションです。
329     //!
330     void Initialize(uptr startAddress, size_t size, bit32 option = 0);
331 
332     //! @brief デモ用のフレームヒープアロケータを破棄します。
333     //!
334     void Finalize();
335 
336     //@}
337 
338     //! @brief 初期化時に指定した先頭アドレスを取得します。
339     //!
340     //! @return 先頭アドレスです。
GetStartAddress()341     uptr GetStartAddress() const { return m_StartAddress; }
342 
343     //=====================
344     //! @name メモリの確保と解放
345     //@{
346 
347     //! @brief フレームヒープからメモリを確保します。
348     //!
349     //! @param[in] size      確保するメモリサイズです。
350     //! @param[in] alignment アライメントです。
351     //!
352     //! @return 確保したメモリアドレスを返します。
Alloc(size_t size,u8 alignment)353     virtual void* Alloc(size_t size, u8 alignment)
354     {
355         NW_ASSERT(size != 0);
356 
357         return m_FrameHeap.Allocate(size, alignment);
358     }
359 
360     //! @brief IAllocator の実装としてこの関数が用意されていますが、呼び出しても何も起きません。
Free(void *)361     virtual void Free(void*)
362     {
363         // フレームヒープは全部解放しかできないため、何もしない。
364     }
365 
366     //! @brief 確保されたすべてのメモリを解放します。
FreeAll()367     void FreeAll()
368     {
369         m_FrameHeap.Free();
370     }
371 
372     //@}
373 
374 private:
375     uptr m_StartAddress;
376 
377     nn::fnd::FrameHeap m_FrameHeap;
378 };
379 
380 
381 } // namespace demo
382 } // namespace nw
383 
384 /* NW_DEMO_MEMORY_H_ */
385 #endif
386 
387