/*---------------------------------------------------------------------------*
  Project:  TwlSDK - OS - demos - heap-1
  File:     main.c

  Copyright 2003-2008 Nintendo.  All rights reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Date:: 2008-10-03#$
  $Rev: 8857 $
  $Author: yada $
 *---------------------------------------------------------------------------*/
#include <nitro.h>

//----------------------------------------------------------------
#define   MAIN_HEAP_SIZE1   0x10000
#define   MAIN_HEAP_SIZE2   0x20000
#define   MAIN_HEAP_SIZE3   0x8000

#define   ALLOC_SIZE1       0x10
#define   ALLOC_SIZE2       0x100
#define   ALLOC_SIZE3       0x1000
#define   ALLOC_SIZE4       0x2000
#define   ALLOC_SIZE5       0x10

#define   HEAP_NUM          2
#define   DISPLAY_HEAP1     (1<<0)
#define   DISPLAY_HEAP2     (1<<1)

OSHeapHandle handle1;
OSHeapHandle handle2;

void DisplayHeap(u32 heap);

//================================================================================
//        ヒープの総合的なサンプル
//        メインメモリのアリーナに対し ヒープを作成して、
//        領域確保・領域解放を行ってみる。
/*---------------------------------------------------------------------------*
  Name:         NitroMain

  Description:  main

  Arguments:    None

  Returns:      None
 *---------------------------------------------------------------------------*/
void NitroMain(void)
{
    void   *heapArea1;
    void   *heapArea2;
    void   *heapArea3;
    void   *nstart;
    void   *area1;
    void   *area2;
    void   *area3;
    void   *area4;

    OS_Init();
    //OS_InitArena(); /*called in OS_Init()*/


    OS_Printf("================================ after OS_Init() ================\n", OS_GetMainArenaLo());
    OS_Printf("arena lo = %x\n", OS_GetMainArenaLo());
    OS_Printf("arena hi = %x\n", OS_GetMainArenaHi());

    //---- MainRAM アリーナに対してメモリ割り当てシステム初期化
    nstart = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), HEAP_NUM);
    OS_SetMainArenaLo(nstart);


    //---- アリーナからヒープ用領域を確保してヒープ作成
    OS_Printf("\n================================ create heap ================\n" );
    heapArea1 = OS_AllocFromMainArenaLo(MAIN_HEAP_SIZE1, 32);
    heapArea2 = OS_AllocFromMainArenaLo(MAIN_HEAP_SIZE2, 32);
    handle1 = OS_CreateHeap(OS_ARENA_MAIN, heapArea1, (void *)((u32)heapArea1 + MAIN_HEAP_SIZE1));
    handle2 = OS_CreateHeap(OS_ARENA_MAIN, heapArea2, (void *)((u32)heapArea2 + MAIN_HEAP_SIZE2));

    OS_Printf("heap1 handle=%d area1 = %x-%x\n", handle1, heapArea1, (u32)heapArea1 + MAIN_HEAP_SIZE1);
    OS_Printf("heap2 handle=%d area2 = %x-%x\n", handle2, heapArea2, (u32)heapArea2 + MAIN_HEAP_SIZE2);

    //---- カレントヒープ設定
    (void)OS_SetCurrentHeap(OS_ARENA_MAIN, handle1);

    DisplayHeap( DISPLAY_HEAP1 | DISPLAY_HEAP2 );

    //---- 領域を確保する
    OS_Printf("\n================================ allocate ================\n" );
    area1 = OS_Alloc(ALLOC_SIZE1);
    area2 = OS_Alloc(ALLOC_SIZE2);
    area3 = OS_AllocFromHeap(OS_ARENA_MAIN, handle1, ALLOC_SIZE3);
    area4 = OS_AllocFromHeap(OS_ARENA_MAIN, handle2, ALLOC_SIZE4);

    OS_Printf("area1: heap1  size=%5x  addr=%x\n", ALLOC_SIZE1, area1);
    OS_Printf("area2: heap1  size=%5x  addr=%x\n", ALLOC_SIZE2, area2);
    OS_Printf("area3: heap1  size=%5x  addr=%x\n", ALLOC_SIZE3, area3);
    OS_Printf("area4: heap2  size=%5x  addr=%x\n", ALLOC_SIZE4, area4);

    DisplayHeap( DISPLAY_HEAP1 | DISPLAY_HEAP2 );


    //---- 領域を解放する
    OS_Printf("\n================================ Free ================\n" );
    OS_Free(area2);
    OS_Printf("free area2.\n");

    OS_FreeToHeap(OS_ARENA_MAIN, handle2, area4);
    OS_Printf("free area4.\n");

    DisplayHeap( DISPLAY_HEAP1 | DISPLAY_HEAP2 );


	//---- ヒープ領域を拡張する
    OS_Printf("\n================================ expand heap1 ================\n" );
    heapArea3 = OS_AllocFromMainArenaLo(MAIN_HEAP_SIZE3, 32);
    OS_Printf("expand area %x-%x\n", heapArea3, (u32)heapArea3 + MAIN_HEAP_SIZE3);

    OS_AddToHeap(OS_ARENA_MAIN, handle1, heapArea3, (void *)((u32)heapArea3 + MAIN_HEAP_SIZE3));

    DisplayHeap( DISPLAY_HEAP1 | DISPLAY_HEAP2 );


	//---- ヒープを破壊する
    OS_Printf("\n================================ destroy heap2 ================\n" );
    OS_DestroyHeap(OS_ARENA_MAIN, handle2);


    OS_Printf("\n");
    OS_Printf("==== Finish sample.\n");
    OS_Terminate();
}

//----------------------------------------------------------------
//  DisplayHeap
//
void DisplayHeap( u32 heap )
{
	if ( heap & DISPLAY_HEAP1 )
	{
		OS_Printf( "+-------------------HEAP 1-------------------+\n" );
		OS_Printf( "|                                            |\n" );
		OS_DumpHeap(OS_ARENA_MAIN, handle1);
		OS_Printf( "|                                            |\n" );
		OS_Printf( "+--------------------------------------------+\n" );
	}

	if ( heap & DISPLAY_HEAP2 )
	{
		OS_Printf( "+-------------------HEAP 2-------------------+\n" );
		OS_Printf( "|                                            |\n" );
		OS_DumpHeap(OS_ARENA_MAIN, handle2);
		OS_Printf( "|                                            |\n" );
		OS_Printf( "+--------------------------------------------+\n" );
	}
}

/*====== End of main.c ======*/
