/*---------------------------------------------------------------------------*
  Project:	NITRO-System - tests - gfd - VramManager - FramePlttVramMan
  File:     main.c

  Copyright 2004,2005 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.

  $Log: main.c,v $
  Revision 1.6  08/17/2005 08:10:08  kitani_toshikazu
  Added a function for debug display

  Revision 1.5  02/25/2005 08:21:47  kitani_toshikazu
  Support for compiler warnings when NITRO_WARNING_STRICT option is used

  Revision 1.4  01/31/2005 00:09:27  nishida
  Corrected the year of the copyright date.

  Revision 1.3  01/28/2005 05:40:06  kitani_toshikazu
  Added the check item for rounding up the size that is smaller than the minimum size.

  Revision 1.2  12/07/2004 04:18:04  kitani_toshikazu
  Commented out part describing verification of failure to secure

  Revision 1.1  11/17/2004 01:03:39  kitani_toshikazu
  Registration of the initial version

  $NoKeywords: $
 *---------------------------------------------------------------------------*/
//
// This sample uses the frame VRAM manager (texture palette).
// It allocates regions using a variety of patterns.
// 
#include <nitro.h>
#include <nnsys/gfd.h>


//   Variables used inside the program
static NNSGfdFrmPlttVramState           state_;
static NNSGfdPlttKey                    mem;
static int                              vramLowerPtr,vramHigherPtr;

//  Match the VRAM higher and lower pointers with the manager pointers.
static BOOL checkVramPtr() {
     NNS_GfdGetFrmPlttVramState(&state_);
	return ((state_.address[0] == vramLowerPtr) && (state_.address[1] == vramHigherPtr));
}


/*---------------------------------------------------------------------------*
  Name:         NitroMain

  Description:  The Main function of the sample
                
  Arguments:    None
                
  Returns:      None
  
 *---------------------------------------------------------------------------*/
void NitroMain()
{
    OS_Init();
    
    {
        const char* vramName[6] 
            = {"VRAM-F","VRAM-G","VRAM-F,G","VRAM-E","VRAM-E,F","VRAM-E,F,G"};
        const GXVRamTexPltt vramEnum[6] 
            = {GX_VRAM_TEXPLTT_0_F,GX_VRAM_TEXPLTT_0_G,GX_VRAM_TEXPLTT_01_FG,
               GX_VRAM_TEXPLTT_0123_E,GX_VRAM_TEXPLTT_01234_EF,GX_VRAM_TEXPLTT_012345_EFG};
        const int vramSize[6] 
            = {16 * 1024,16 * 1024,(16 + 16) * 1024,64 * 1024,(64 + 16) * 1024,(64 + 16 + 16) * 1024};
       
       
       
        //  Allocate all VRAM combination patterns to texture palettes and test them
        int i;
        for(i = 0;i < 6;i ++) 
        {
            //  Initial pointer settings
            vramLowerPtr = 0;
            vramHigherPtr = vramSize[i];
            
            OS_Printf("%s  checking\n",vramName[i]);
            GX_SetBankForTexPltt(vramEnum[i]);
            
            //
            // Initializes manager.
            //
            NNS_GfdInitFrmPlttVramManager( (u32)vramSize[i], TRUE );
            
            //   Allocate area not for 4-color palette from the lower address
            mem = NNS_GfdAllocPlttVram(0x100,FALSE,TRUE);
            vramLowerPtr += 0x100;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramLowerPtr - 0x100);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x100);
            
            //  Allocate area not for 4-color palette from the higher address
            mem = NNS_GfdAllocPlttVram(0x100,FALSE,FALSE);
            vramHigherPtr -= 0x100;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramHigherPtr);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x100);
            
            //  Allocate area not for 4-color palette from the lower address.
            mem = NNS_GfdAllocPlttVram(0x8,TRUE,TRUE);
            vramLowerPtr += 0x8;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramLowerPtr - 0x8);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x8);
            //   Only 4-color palettes are 0x8 aligned, so check if they are correct
            mem = NNS_GfdAllocPlttVram(0x10,TRUE,TRUE);
            vramLowerPtr += 0x10;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramLowerPtr - 0x10);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x10);
            mem = NNS_GfdAllocPlttVram(0x8,TRUE,TRUE);
            vramLowerPtr += 0x8;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramLowerPtr - 0x8);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x8);
            mem = NNS_GfdAllocPlttVram(0x8,TRUE,TRUE);
            vramLowerPtr += 0x8;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramLowerPtr - 0x8);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x8);
            
            // Manager status is output for debugging
            NNS_GfdDumpFrmPlttVramManager();
            
            //  Address is 0x****8, so allocate a texture area not for 4-color palette here
            //  Allocate from current address+0x8
            mem = NNS_GfdAllocPlttVram(0x10,FALSE,TRUE);
            vramLowerPtr += 0x10 + 0x8;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramLowerPtr - 0x10);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x10);
            
            //  If VRAM of a size that exceeds 0x10000 has been allocated,
            //  and not all of the memory above 0x10000 has been allocated yet,
            //  it's impossible to allocate 4-color palette texture memory from the high order side.
            if(vramSize[i] > 0x10000) {
                //
                // If you want to confirm failure of operation to secure memory,  try executing the comment portion
                //
                //   Cannot allocate this
                //mem = NNS_GfdAllocPlttVram(0x8,TRUE,FALSE);
                //NNS_GFD_ASSERT(mem == NNS_GFD_ALLOC_ERROR_PLTTKEY);
                
                //   Allocate all the area over 0x10000
                mem = NNS_GfdAllocPlttVram((u32)(vramSize[i] - 0x10000),FALSE,FALSE);
                vramHigherPtr -= vramSize[i] - 0x10000;
                NNS_GFD_ASSERT(checkVramPtr());
                NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramHigherPtr);
                NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == vramSize[i] - 0x10000);
            }
            
            //   Even if unable to allocate in the above if statement, it can be allocated here
            mem = NNS_GfdAllocPlttVram(0x8,TRUE,FALSE);
            vramHigherPtr -= 0x8;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramHigherPtr);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x8);
            
            //   Same as with lower address
            //   Only 4-color palettes are 0x8 aligned, so check if they are correct
            mem = NNS_GfdAllocPlttVram(0x10,TRUE,FALSE);
            vramHigherPtr -= 0x10;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramHigherPtr);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x10);
            mem = NNS_GfdAllocPlttVram(0x8,TRUE,FALSE);
            vramHigherPtr -= 0x8;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramHigherPtr);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x8);
            mem = NNS_GfdAllocPlttVram(0x8,TRUE,FALSE);
            vramHigherPtr -= 0x8;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramHigherPtr);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x8);
            //  Address is 0x****8, so allocate a texture area not for 4-color palette here
            //  Allocate from current address-0x8
            mem = NNS_GfdAllocPlttVram(0x10,FALSE,FALSE);
            vramHigherPtr -= 0x10 + 0x8;
            NNS_GFD_ASSERT(checkVramPtr());
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeyAddr(mem) == vramHigherPtr);
            NNS_GFD_ASSERT(NNS_GfdGetPlttKeySize(mem) == 0x10);
            
            //
            // If you want to confirm failure of operation to secure memory,  try executing the comment portion
            //
            //  An area larger than available capacity is requested, and the request is denied
            //mem = NNS_GfdAllocPlttVram(vramSize[i],TRUE,FALSE);
            //NNS_GFD_ASSERT(mem == NNS_GFD_ALLOC_ERROR_PLTTKEY);
            //mem = NNS_GfdAllocPlttVram(vramSize[i],FALSE,FALSE);
            //NNS_GFD_ASSERT(mem == NNS_GFD_ALLOC_ERROR_PLTTKEY);
            //mem = NNS_GfdAllocPlttVram(vramSize[i],TRUE,TRUE);
            //NNS_GFD_ASSERT(mem == NNS_GFD_ALLOC_ERROR_PLTTKEY);
            //mem = NNS_GfdAllocPlttVram(vramSize[i],FALSE,TRUE);
            //NNS_GFD_ASSERT(mem == NNS_GFD_ALLOC_ERROR_PLTTKEY);
            
            //  Save current state in state_
            NNS_GfdGetFrmPlttVramState(&state_);
            
            //  Allocate proper area for higher and lower sides
            mem = NNS_GfdAllocPlttVram(0x10,FALSE,FALSE);
            mem = NNS_GfdAllocPlttVram(0x18,TRUE,FALSE);
            mem = NNS_GfdAllocPlttVram(0x10,FALSE,TRUE);
            mem = NNS_GfdAllocPlttVram(0x18,TRUE,TRUE);
            
            //  Return the state stored in state_ to the manager
            NNS_GfdSetFrmPlttVramState(&state_);
            NNS_GFD_ASSERT(checkVramPtr());
            
            
            {
                // Size zero
                mem = NNS_GfdAllocPlttVram(0x0,TRUE,FALSE);
                NNS_GFD_ASSERT( NNS_GfdGetPlttKeySize(mem) == NNS_GFD_PLTTSIZE_MIN );
                NNS_GfdSetFrmPlttVramState(&state_);
                // Smaller than NNS_GFD_PLTTSIZE_MIN
                mem = NNS_GfdAllocPlttVram(0x1,TRUE,FALSE);
                NNS_GFD_ASSERT( NNS_GfdGetPlttKeySize(mem) == NNS_GFD_PLTTSIZE_MIN );
                NNS_GfdSetFrmPlttVramState(&state_);
                // Exactly NNS_GFD_PLTTSIZE_MIN
                mem = NNS_GfdAllocPlttVram(NNS_GFD_PLTTSIZE_MIN,TRUE,FALSE);
                NNS_GFD_ASSERT( NNS_GfdGetPlttKeySize(mem) == NNS_GFD_PLTTSIZE_MIN );
                NNS_GfdSetFrmPlttVramState(&state_);
                // Slightly larger than NNS_GFD_PLTTSIZE_MIN
                mem = NNS_GfdAllocPlttVram(NNS_GFD_PLTTSIZE_MIN+1,TRUE,FALSE);
                NNS_GFD_ASSERT( NNS_GfdGetPlttKeySize(mem) == NNS_GFD_PLTTSIZE_MIN * 2);
                NNS_GfdSetFrmPlttVramState(&state_);
            }
            
            (void)GX_DisableBankForTex();
            
            OS_Printf("%s  OK\n",vramName[i]);
        }
    }
    
    while(1) {}
}


