/*---------------------------------------------------------------------------*
  Project:   NITRO-System - build - demos - g2d - Text - OBJ1D
  File:     main.c

  Copyright 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.2  05/25/2005 08:09:59  hatamoto_minoru
  Changed the formatting of the fonts. Added 1 element to the character width information.

  Revision 1.1  05/20/2005 04:34:35  hatamoto_minoru
  Registered in NitroSystem.

  Revision 1.4  03/18/2005 09:19:46  hatamoto_minoru
  Added support for the changes to the API.

  Revision 1.3  03/10/2005 09:06:12  hatamoto_minoru
  Revised where the parameters were test values.

  Revision 1.2  03/10/2005 08:43:40  hatamoto_minoru
  Changed the order of the arguments.

  Revision 1.1  03/10/2005 08:13:41  hatamoto_minoru
  Registered the initial version.

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

// ============================================================================
//  Explanation of the demo:
//      This can display a character string, depending on the size of the character string to be displayed.
//      Builds the smallest CharCanvas and performs rendering.
//
//  Operation Method
//      No operations.
// ============================================================================


#include <nnsys/g2d/g2d_TextCanvas.h>
#include <nnsys/g2d/g2d_CharCanvas.h>
#include "g2d_textdemolib.h"



#define CHARACTER_WIDTH     8       // Width of character in pixels
#define CHARACTER_HEIGHT    8       // Height of character in pixels
#define SCREEN_WIDTH        256     // Screen width
#define SCREEN_HEIGHT       192     // screen height

#define TEXT_HSPACE         1       // Amount of space between characters when rendering character strings (in pixel units)
#define TEXT_VSPACE         1       // Amount of space between lines when rendering character strings   (in pixel units)

#define CHARACTER_OFFSET    1       // Starting number of the character string to be used

#define MAX_OBJ_NUM         128     // Maximum number of OBJ
#define MAX_CHARA_NAME      1024    // Maximum character name value


//------------------------------------------------------------------------------
// Global Variables

NNSG2dFont              gFont;          // font

const static NNSG2dChar* sampleText[] =
{
    NNS_G2D_TRANSCODE("This sample program make temporary minimum\n"
                      "CharCanvas to draw a text and draw the\n"
                      "text to it."),
    NNS_G2D_TRANSCODE("sample text"),
    NNS_G2D_TRANSCODE("line 1\n" "line 2\n" "line 3\n" "line 4\n"),
    NNS_G2D_TRANSCODE("A"),
};

//****************************************************************************
// Initialize etc.
//****************************************************************************

/*---------------------------------------------------------------------------*
  Name:         InitScreen

  Description:  Initializes the OBJ display.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
static void InitScreen(void)
{
    // Mapping mode configuration  1D 64 KB
    GX_SetOBJVRamModeChar(GX_OBJVRAMMODE_CHAR_1D_64K);

    // Make the OBJ visible
    CMN_SetPlaneVisible( GX_PLANEMASK_OBJ );

    // Configure color palette
    GX_LoadOBJPltt(TXTColorPalette, 0, sizeof(TXTColorPalette));
}



/*---------------------------------------------------------------------------*
  Name:         AllocCharacters

  Description:  This is a simple character manager.
                It allocates a designated amount of characters, and returns the
                top character name of that allocated character string.

  Arguments:    num:    The number of characters to allocate.

  Returns:      Returns the top character name of the allocated character string
                top character name of that allocated character string.
                Returns a -1 if failed.
 *---------------------------------------------------------------------------*/
static int AllocCharacters(int num)
{
    static int usingCharas = 0;
    int ret;

    if( usingCharas + num > MAX_CHARA_NAME )
    {
        return -1;
    }

    ret = usingCharas;
    usingCharas += ROUNDUP_DIV(num, 2);
        // 1 character name in 1D 64K mode corresponds to 2 characters, so
        // this is divided by 2 and rounded up.

    return ret;
}



/*---------------------------------------------------------------------------*
  Name:         AllocOAM

  Description:  This is a simple OAM manager.
                It allocates a designated number of OAMs, and returns
                a pointer to the top of that allocated OAM string.

  Arguments:    num:    The number of OAMs to allocate.

  Returns:      Returns the top character name of the allocated character string
                if allocation was a success.
                Returns a NULL if failed.
 *---------------------------------------------------------------------------*/
static GXOamAttr* AllocOAM(int num)
{
    static int usingOam = 0;
    GXOamAttr* const pObjBase = (GXOamAttr*)HW_OAM;
    GXOamAttr* ret;

    if( usingOam + num > MAX_OBJ_NUM )
    {
        return NULL;
    }

    ret = pObjBase + usingOam;
    usingOam += num;

    return ret;
}



/*---------------------------------------------------------------------------*
  Name:         PutText

  Description:

  Arguments:    x:

  Returns:
 *---------------------------------------------------------------------------*/
static void PutText(int x, int y, u8 color, const NNSG2dChar* txt)
{
    GXCharFmt16* const pCharBase = (GXCharFmt16*)G2_GetOBJCharPtr();
    const NNSG2dOBJVramMode vramMode = NNS_G2D_OBJVRAMMODE_64K;
    NNSG2dCharCanvas cc;
    NNSG2dTextCanvas tc;
    NNSG2dTextRect textRect;
    int areaWidth, areaHeight;
    GXOamAttr* pOam;
    int numOBJ;
    int charNo;

    // Finds the size of the text region
    textRect = NNS_G2dFontGetTextRect(&gFont, TEXT_HSPACE, TEXT_VSPACE, txt);
    areaWidth = ROUNDUP_DIV( textRect.width, CHARACTER_WIDTH );
    areaHeight = ROUNDUP_DIV( textRect.height, CHARACTER_HEIGHT );

    // Allocates the OAM and character
    numOBJ = NNS_G2dCalcRequiredOBJ1D( areaWidth, areaHeight );
    charNo = AllocCharacters( areaWidth * areaHeight );
    pOam = AllocOAM( numOBJ );
    NNS_G2D_ASSERT( charNo >= 0 );
    NNS_G2D_POINTER_ASSERT( pOam );

    // Initializes the CharCanvas for the 1D OBJ at the text region size
    NNS_G2dCharCanvasInitForOBJ1D(
        &cc,
        pCharBase + (charNo << vramMode),
        areaWidth,
        areaHeight,
        NNS_G2D_CHARA_COLORMODE_16
    );

    // Place the OBJ for the CharCanvas
    (void)NNS_G2dArrangeOBJ1D(
        pOam,
        areaWidth,
        areaHeight,
        x, y,
        GX_OAM_COLORMODE_16,
        charNo,
        vramMode
    );

    // Build the TextCanvas
    NNS_G2dTextCanvasInit(
        &tc,
        &cc,
        &gFont,
        TEXT_HSPACE,
        TEXT_VSPACE
    );

    // Clear the canvas and render the character string
    NNS_G2dCharCanvasClear(
        &cc,
        TXT_COLOR_WHITE
    );
    NNS_G2dTextCanvasDrawText(
        &tc,
        0, 0,
        color,
        TXT_DRAWTEXT_FLAG_DEFAULT,
        txt
    );


    DTX_PrintLine("%3dx%3d  %2dx%2d    %4d  %3d",
        textRect.width, textRect.height,
        areaWidth, areaHeight,
        areaWidth * areaHeight, numOBJ
    );
}



/*---------------------------------------------------------------------------*
  Name:         PrintSampleInfo

  Description:  Outputs to the screen which did the sample information.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
static void PrintSampleInfo(void)
{
    DTX_PrintLine(
        "Text size dependents Canvas Sample\n"
        "operation\n"
        "  none\n"
        "\n"
        "Size              Using\n"
        "text     canvas   char  OBJ"
    );
}



/*---------------------------------------------------------------------------*
  Name:         SampleMain

  Description:  This is the main process of the sample.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
static void SampleMain(void)
{
    int i;

    InitScreen();

    PrintSampleInfo();

    // load the font
    TXT_LoadFont( &gFont, TXT_FONTRESOURCE_NAME );

    for( i = 0; i < ARY_SIZEOF(sampleText); ++i )
    {
        int x = (int)(SCREEN_WIDTH / ARY_SIZEOF(sampleText)) * i;
        int y = (int)(SCREEN_HEIGHT / ARY_SIZEOF(sampleText)) * i;
        u8 color = (u8)(TXT_COLOR_RED + i);

        PutText(x, y, color, sampleText[i]);
    }
}





//****************************************************************************
// Main
//****************************************************************************


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

  Description:  This is the main function.

  Arguments:    None.

  Returns:      None.
 *---------------------------------------------------------------------------*/
void NitroMain(void)
{
    // Initilizing App.
    {
        // Initialization of SDK and demo library
        OS_Init();
        TXT_Init();

        // Configure the background
        TXT_SetupBackground();

        // Main process of sample
        SampleMain();
    }

    // start display
    {
        CMN_WaitVBlankIntr();
        GX_DispOn();
        GXS_DispOn();
    }

    // Main loop
    while( TRUE )
    {
        CMN_ReadGamePad();

        CMN_WaitVBlankIntr();

        // Display the information output
        DTX_Reflect();
    }
}


