/*---------------------------------------------------------------------------*
  Project:  NitroSystem - build - demos - g3d - demolib
  File:     system.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: system.c,v $
  Revision 1.7  06/29/2005 04:43:58  hatamoto_minoru
  Fixed typos: NitroSyetem -> NitroSystem

  Revision 1.6  02/25/2005 03:08:20  takano_makoto
  Warning measures for signed<->unsigned casts

  Revision 1.5  11/12/2004 05:40:32  nishida
  Revised project name of file header.

  Revision 1.4  09/08/2004 04:05:44  nishida
  Made changes so that it reads a game pad as dummy once a upon initialization.

  Revision 1.3  08/17/2004 06:00:27  nishida
  Supported NITRO-SDK 2.0.0 pr4.

  Revision 1.2  07/23/2004 02:52:02  kitamurs
  Fixed bugs in command of file read function.

  Revision 1.1  07/13/2004 11:13:06  nishida
  Registered the initial version.

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

#include "g3d_demolib/system.h"

#define DEFAULT_DMA_NUMBER      MI_DMA_MAX_NUM
#define SYSTEM_HEAP_SIZE        64*1024


G3DDemoGamePad   G3DDemo_GamePad;       // Game Pad
NNSFndHeapHandle G3DDemo_SysHeap;       // System heap    (Use extended heap)
NNSFndHeapHandle G3DDemo_AppHeap;       // Application heap (use for expanded heap)


/*---------------------------------------------------------------------------*
  Name:         G3DDemo_VBlankIntr

  Description:  V blank callback routine.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
G3DDemo_VBlankIntr(void)
{
    OS_SetIrqCheckFlag(OS_IE_V_BLANK);
}

/*---------------------------------------------------------------------------*
  Name:         G3DDemo_InitSystem

  Description:  Performs the initialization of NITRO.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
G3DDemo_InitSystem(void)
{
    OS_Init();
    FX_Init();
    GX_SetPower(GX_POWER_ALL);
    GX_Init();
    OS_InitTick();

    GX_DispOff();
    GXS_DispOff();

    OS_SetIrqFunction(OS_IE_V_BLANK, G3DDemo_VBlankIntr);

    (void)OS_EnableIrqMask(OS_IE_V_BLANK);
    (void)OS_EnableIrqMask(OS_IE_FIFO_RECV);
    (void)OS_EnableIrq();

    FS_Init(DEFAULT_DMA_NUMBER);

    (void)GX_VBlankIntr(TRUE);         // to generate VBlank interrupt request

    // Dummy read of game pad.
    G3DDemo_ReadGamePad();
}

#define SYSTEM_HEAP_SIZE        64*1024

/*---------------------------------------------------------------------------*
  Name:         G3DDemo_InitVRAM

  Description:  Performs the initialization of VRAM.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void
G3DDemo_InitVRAM(void)
{
    // Allocate all banks to LCDC
    GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);

    // Clear all LCDC space
    MI_CpuClearFast( (void*)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE );
    
    // Disable banks allocated to LCDC
    (void)GX_DisableBankForLCDC();

    MI_CpuFillFast ((void*)HW_OAM    , 192, HW_OAM_SIZE   );  // Clear OAM
    MI_CpuFillFast ((void*)HW_DB_OAM , 192, HW_DB_OAM_SIZE);  // clear OAM

    MI_CpuClearFast((void*)HW_PLTT   , HW_PLTT_SIZE   );      // Clear palette
    MI_CpuClearFast((void*)HW_DB_PLTT, HW_DB_PLTT_SIZE);      // Clear the standard palette
}

/*---------------------------------------------------------------------------*
  Name:         G3DDemo_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 will be used by system programs of the game system.
                 Use the application heap to load data used by the game.
                 

  Arguments:    None.

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

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

    G3DDemo_SysHeap = NNS_FndCreateExpHeap(sysHeapMemory, SYSTEM_HEAP_SIZE);
    G3DDemo_AppHeap = NNS_FndCreateExpHeap(appHeapMemory, appHeapSize      );
}

/*---------------------------------------------------------------------------*
  Name:         G3DDemo_LoadFile

  Description:  Read the file
  
  Arguments:    path        Path to file

  Returns:      Address where file should be loaded
 *---------------------------------------------------------------------------*/
void* G3DDemo_LoadFile(const char *path)
{
    FSFile file;
    void*  memory;

    FS_InitFile(&file);
    if (FS_OpenFile(&file, path))
    {
        u32 fileSize = FS_GetLength(&file);

        memory = NNS_FndAllocFromExpHeapEx(G3DDemo_AppHeap, fileSize, 16);
        if (memory == NULL)
        {
            OS_Printf("no enough memory.\n");
        }
        else
        {
            if (FS_ReadFile(&file, memory, (s32)fileSize) != fileSize)   // If file is too big to be loaded
            {
                NNS_FndFreeToExpHeap(G3DDemo_AppHeap, memory);
                memory = NULL;
                OS_Printf("file reading failed.\n");
            }
        }
        (void)FS_CloseFile(&file);
    }
    return memory;
}

/*---------------------------------------------------------------------------*
  Name:         G3DDemo_ReadGamePad

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

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

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

