/*---------------------------------------------------------------------------*
  Project:  NITRO-System - build - demos - fnd - archive
  File:     nns_util.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: nns_util.c,v $
  Revision 1.7  03/02/2005 00:37:51  takano_makoto
  Warning measures for signed<->unsigned casts

  Revision 1.6  01/21/2005 05:08:06  kitamurs
  Changed year

  Revision 1.5  11/05/2004 09:47:54  nishida
  Revised Project in the file header

  Revision 1.4  11/04/2004 09:39:25  nishida
  Fixed spelling error in the file header

  Revision 1.3  10/21/2004 05:27:57  nishida
  Fixed so that DC_FlushRange is called after file is loaded.

  Revision 1.2  07/23/2004 05:43:18  nishida
  Fixed bugs and added comments.

  Revision 1.1  05/26/2004 09:29:50  nishida
  Registered the initial version.

  $NoKeywords: $
 *---------------------------------------------------------------------------*/

#include "nns_util.h"

#define SYSTEM_HEAP_SIZE        64*1024

GamePad          gGamePad;      // Game Pad
NNSFndHeapHandle gSysHeap;      // System heap    (Use extended heap)
NNSFndHeapHandle gAppHeap;      // Application heap (use for expanded heap)


/*---------------------------------------------------------------------------*
  Name:         InitMemory

  Description:  Creates system heap and application heap. Both heaps
                use the NITRO-System extended heap.
                
                An area the size of SYSTEM_HEAP_SIZE is allocated from the main arena
                as system heap and allocates the remainder of the main memory arena
                as application heap.
                
                We assume the system heap is being used by system programs of the game system and so on.
                 Use the application heap to load data used by the game.
                 

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
InitMemory(void)
{
    void* sysHeapMemory = OS_AllocFromMainArenaLo(SYSTEM_HEAP_SIZE, 16);

    u32   arenaLow      = ROUND_UP  (OS_GetMainArenaLo(), 16);
    u32   arenaHigh     = ROUND_DOWN(OS_GetMainArenaHi(), 16);
    u32   appHeapSize   = arenaHigh - arenaLow;
    void* appHeapMemory = OS_AllocFromMainArenaLo(appHeapSize, 16);

    gSysHeap = NNS_FndCreateExpHeap(sysHeapMemory, SYSTEM_HEAP_SIZE);
    gAppHeap = NNS_FndCreateExpHeap(appHeapMemory, appHeapSize     );
}

/*---------------------------------------------------------------------------*
  Name:         LoadArchive

  Description:  Load the archive designated with the path name into memory,
                then mount it in the file system. Under this implementation of this function, the function DC_FlushRange can be called to ensure that the loaded archive resides in main memory.
                 
                 

                The memory used to load the archive and the memory used for the NNSFndArchive structure,
                required in order to mount the archive, are allocated from the application heap.
                 

  Arguments:    name:   The name used to identify the archive on the file system
                path:   Path name of the archive.

  Returns:      If archive load is successful, returns a pointer to a NNSFndArchive structure. 
                 If unsuccessful, returns NULL.
 *---------------------------------------------------------------------------*/
NNSFndArchive*
LoadArchive(const char* name, const char* path)
{
    FSFile          file;
    NNSFndArchive*  archive = NULL;

    FS_InitFile(&file);
    if (FS_OpenFile(&file, path))
    {
        u32 binarySize = FS_GetLength(&file);
        u32 memorySize = ROUND_UP(sizeof(NNSFndArchive), 16) + ROUND_UP(binarySize, 16);

        u8* memory     = (u8*)NNS_FndAllocFromExpHeapEx(gAppHeap, memorySize, 16);

        if (memory != NULL)
        {
            u8* binary = memory + ROUND_UP(sizeof(NNSFndArchive), 16);

            if (FS_ReadFile(&file, binary, (s32)binarySize) == binarySize)
            {
                DC_FlushRange(binary, binarySize);

                if (NNS_FndMountArchive((NNSFndArchive*)memory, name, binary))
                {
                    archive = (NNSFndArchive*)memory;
                }
                else
                {
                    NNS_FndFreeToExpHeap(gAppHeap, memory);
                }
            }
        }
        (void)FS_CloseFile(&file);
    }
    return archive;
}

/*---------------------------------------------------------------------------*
  Name:         RemoveArchive

  Description:  Deletes a designated archive from memory.
  
                This unmounts a designated archive from the file system,
                and deallocates the memory into which the archive was loaded.
                
  Arguments:    archive:    A pointer to the NNS archive structure.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
RemoveArchive(NNSFndArchive* archive)
{
    (void)NNS_FndUnmountArchive(archive);
    NNS_FndFreeToExpHeap(gAppHeap, archive);
}

/*---------------------------------------------------------------------------*
  Name:         ReadGamePad

  Description:  Reads key, and requests trigger and release-trigger.
                
  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void ReadGamePad(void)
{
    u16 status = PAD_Read();

    gGamePad.trigger = (u16)(status          & (status ^ gGamePad.button));
    gGamePad.release = (u16)(gGamePad.button & (status ^ gGamePad.button));
    gGamePad.button  = status;
}

