/*---------------------------------------------------------------------------* Project: KPAD sample program File: kfont.c Programmer: Keizo Ohta 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. *---------------------------------------------------------------------------*/ #include #include #include "kfont.h" /*************************************************************** Definitions ***************************************************************/ #define KFONT_MAX (10+26+2) // 「0〜9」「A〜Z」「.」「-」 #define KFONT_WD 24 // SDK fixed #define KFONT_HT 24 // SDK fixed #define KFONT_SHEET_WD (KFONT_WD * KFONT_MAX) // Support up to 1024. #define KFONT_SHEET_HT KFONT_HT #define KFONT_TEX_SIZE (KFONT_SHEET_WD * KFONT_SHEET_HT * 4 / 8) /*************************************************************** Variables ***************************************************************/ static f32 canvas_wd,canvas_ht ; // Virtual canvas size static f32 cursor_wd,cursor_ht ; // Cursor size static s32 cursor_nx,cursor_ny ; // Number of cursors arranged on canvas static f32 cursor_x1,cursor_y1 ; // Coordinate of upper leftmost cursor static f32 letter_ox,letter_oy ; // Offset from the cursor position to the character position static f32 letter_wd,letter_ht ; // Character size static char *kfont_str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.-" ; static void *kfont_tex ; static GXTexObj kfont_tobj ; static f32 s1_ofs ; // Depending on whether the main unit is the Japanese or USA version: static f32 s2_ofs ; // Adjustments are made to display different fonts static f32 t1_ofs ; // 表示調整を行う /******************************************************************************* Prepare a texture from a built-in font *******************************************************************************/ void init_kfont_texture( void ) { OSFontHeader *font ; void *tmp ; void *tex_p ; char *str_p ; u32 *ptr ; s32 wd, ofs ; //----- Allocate texture buffer kfont_tex = OSAlloc( KFONT_TEX_SIZE ) ; //----- Clear texture buffer ptr = (u32*)( (u32)kfont_tex + KFONT_TEX_SIZE ) - 1 ; do { *ptr = 0x00000000 ; } while ( --ptr != (u32*)kfont_tex ) ; //----- Load font data if ( OSGetFontEncode() == OS_FONT_ENCODE_SJIS ) { font = (OSFontHeader*)OSAlloc( OS_FONT_DATA_SIZE_SJIS ) ; tmp = OSAlloc( OS_FONT_ROM_SIZE_SJIS ) ; s1_ofs = 0.15f * (f32)KFONT_WD / (f32)KFONT_SHEET_WD ; s2_ofs = -0.30f * (f32)KFONT_WD / (f32)KFONT_SHEET_WD ; t1_ofs = 0.00f ; } else { font = (OSFontHeader*)OSAlloc( OS_FONT_DATA_SIZE_ANSI ) ; tmp = OSAlloc( OS_FONT_ROM_SIZE_ANSI ) ; s1_ofs = 0.05f * (f32)KFONT_WD / (f32)KFONT_SHEET_WD ; s2_ofs = -0.10f * (f32)KFONT_WD / (f32)KFONT_SHEET_WD ; t1_ofs = 0.13f ; } (void)OSLoadFont( font, tmp ) ; //----- Convert font data to a texture tex_p = kfont_tex ; str_p = kfont_str ; do { (void)OSGetFontWidth( str_p, &wd ) ; ofs = ( KFONT_WD - wd ) / 2 ; (void)OSGetFontTexel( str_p, tex_p, ofs+1, KFONT_SHEET_WD/4, &wd ) ; str_p = OSGetFontTexel( str_p, tex_p, ofs, KFONT_SHEET_WD/4, &wd ) ; tex_p = (void*)( (u32)tex_p + KFONT_WD / 8 * 32 ) ; } while ( *str_p != '\0' ) ; DCStoreRange( kfont_tex, KFONT_TEX_SIZE ) ; GXInitTexObj( &kfont_tobj, kfont_tex, KFONT_SHEET_WD,KFONT_SHEET_HT, GX_TF_I4, GX_CLAMP,GX_CLAMP, GX_FALSE ) ; GXInitTexObjLOD( &kfont_tobj, GX_LINEAR,GX_LINEAR, 0.0f,0.0f, 0.0f, GX_DISABLE, GX_FALSE, GX_ANISO_1 ) ; //----- Free font data OSFree( font ) ; OSFree( tmp ) ; } /******************************************************************************* Initialize drawing of simple graphics fb_width : Horizontal resolution of frame buffer fb_height : Vertical resolution of frame buffer lt_width : Letter width (line from center to center) lt_width : Letter width (line from center to center) ******************************************************************************/ void init_draw_kfont( u16 fb_width, u16 fb_height, f32 lt_width, f32 lt_height ) { Mtx44 proj_mtx ; Mtx view_mtx ; //----- Calculate variables canvas_wd = fb_width * 0.91346f ; canvas_ht = fb_height ; letter_wd = lt_width ; letter_ht = lt_height ; cursor_wd = letter_wd * 0.90f ; // Reduce separation between letters a bit cursor_ht = letter_ht * 1.05f ; // Make a little extra room in the vertical direction letter_ox = ( cursor_wd - letter_wd ) * 0.5f ; letter_oy = ( cursor_ht - letter_ht ) * 0.5f ; cursor_nx = (s32)( canvas_wd / cursor_wd ) ; cursor_ny = (s32)( canvas_ht / cursor_ht ) ; cursor_x1 = (f32)cursor_nx * cursor_wd * -0.5f ; cursor_y1 = (f32)cursor_ny * cursor_ht * -0.5f ; //----- MTX MTXOrtho( proj_mtx, canvas_ht * -0.5f,canvas_ht * 0.5f, canvas_wd * -0.5f,canvas_wd * 0.5f, -10.0f,10.0f ) ; GXSetProjection( proj_mtx, GX_ORTHOGRAPHIC ) ; MTXIdentity( view_mtx ) ; GXLoadPosMtxImm( view_mtx, GX_PNMTX0 ) ; GXSetCurrentMtx( GX_PNMTX0 ) ; //----- VERTEX GXClearVtxDesc() ; GXSetVtxDesc( GX_VA_POS , GX_DIRECT ) ; GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT ) ; GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS , GX_POS_XY, GX_F32, 0 ) ; GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 ) ; //----- CHANNEL GXSetNumChans( 0 ) ; GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ; GXSetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ; //----- TEXTURE GXSetNumTexGens( 1 ) ; GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY ) ; GXLoadTexObj( &kfont_tobj, GX_TEXMAP0 ) ; //----- TEV GXSetNumTevStages( 1 ) ; GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL ) ; GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO ) ; GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ; GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO ) ; GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ; GXSetAlphaCompare( GX_ALWAYS,0, GX_AOP_OR, GX_ALWAYS,0 ) ; //----- SCREEN GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP ) ; GXSetAlphaUpdate( GX_DISABLE ) ; GXSetZMode( GX_DISABLE, GX_ALWAYS, GX_DISABLE ) ; GXSetCullMode( GX_CULL_BACK ) ; } /******************************************************************************* Draw font character *******************************************************************************/ static void draw_kfont_one( f32 cx, f32 cy, char c ) { f32 x1,x2, y1,y2, s1,s2 ; s32 i ; if ( c >= 'A' && c <= 'Z' ) { i = c - 'A' + 10 ; } else if ( c >= '0' && c <= '9' ) { i = c - '0' ; } else if ( c == '.' ) { i = 10 + 26 ; } else if ( c == '-' ) { i = 10 + 26 + 1 ; } else { return ; } s1 = (f32)( i * KFONT_WD ) / (f32)KFONT_SHEET_WD + s1_ofs ; s2 = s1 + (f32)KFONT_WD / (f32)KFONT_SHEET_WD + s2_ofs ; x1 = cx * cursor_wd + cursor_x1 + letter_ox ; x2 = x1 + letter_wd ; y1 = cy * cursor_ht + cursor_y1 + letter_oy ; y2 = y1 + letter_ht ; GXBegin( GX_QUADS, GX_VTXFMT0, 4 ) ; GXPosition2f32( x1,y1 ) ; GXTexCoord2f32( s1,t1_ofs ) ; GXPosition2f32( x2,y1 ) ; GXTexCoord2f32( s2,t1_ofs ) ; GXPosition2f32( x2,y2 ) ; GXTexCoord2f32( s2,1.0f ) ; GXPosition2f32( x1,y2 ) ; GXTexCoord2f32( s1,1.0f ) ; GXEnd() ; } /******************************************************************************* Draw integer (return the number of characters that were drawn) *******************************************************************************/ s32 draw_kfont_s32( f32 cx, f32 cy, GXColor clr, s32 val ) { s32 v,a, rt = 0 ; f32 x ; GXSetTevColor( GX_TEVREG0, clr ) ; //----- Prepare positive number if ( val < 0 ) { v = -val ; } else { v = val ; } //----- Draw number beginning from the lowest digit x = cx ; do { a = v % 10 ; draw_kfont_one( x, cy, (char)('0'+ a ) ) ; x -= 1.0f ; ++ rt ; v -= a ; v /= 10 ; } while ( v != 0 ) ; //----- Draw sign if ( val < 0 ) { draw_kfont_one( x, cy, '-' ) ; ++ rt ; } return ( rt ) ; } /******************************************************************************* Draw floating point (also specify the number of digits following the decimal point) *******************************************************************************/ s32 draw_kfont_f32( f32 cx, f32 cy, GXColor clr, f32 val, s32 keta ) { s32 v,a, k,n, rt ; f32 x, vf ; GXSetTevColor( GX_TEVREG0, clr ) ; //----- Prepare positive number if ( val < 0.0f ) { vf = -val ; } else { vf = val ; } //----- Calculate number of digits following the decimal point that are to be displayed k = (s32)keta ; if ( k < 1 ) k = 1 ; //----- Shift digits so that the portion to be displayed following the decimal point is a positive number n = k ; do { vf *= 10.0f ; } while ( --n != 0 ) ; //----- Draw the number following the decimal point v = (s32)( vf + 0.5f ) ; x = cx + 1.0f + (f32)k ; n = k ; do { a = v % 10 ; draw_kfont_one( x, cy, (char)('0'+ a ) ) ; x -= 1.0f ; v -= a ; v /= 10 ; } while ( --n != 0 ) ; //----- Draw decimal point draw_kfont_one( x, cy, '.' ) ; x -= 1.0f ; rt = 1 + k ; //----- Draw the integer part of the number as an integer if ( val < 0.0f ) { v = -v ; } rt += draw_kfont_s32( cx, cy, clr, v ) ; return ( rt ) ; } /******************************************************************************* Draw binary number (also specify the number of bits to be displayed) *******************************************************************************/ void draw_kfont_bit( f32 cx, f32 cy, GXColor clr, u32 val, s32 keta ) { u32 bit = 1 ; s32 n = keta ; f32 x = cx ; GXSetTevColor( GX_TEVREG0, clr ) ; do { if ( (bit & 0x01010100) != 0 ) { draw_kfont_one( x, cy, '-' ) ; x -= 1.0f ; } if ( (val & bit) != 0 ) { draw_kfont_one( x, cy, '1' ) ; } else { draw_kfont_one( x, cy, '0' ) ; } x -= 1.0f ; bit <<= 1 ; } while ( --n != 0 ) ; } /******************************************************************************* Draw character string *******************************************************************************/ void draw_kfont_letter( f32 cx, f32 cy, GXColor clr, char *str ) { f32 x = cx ; char *cp = str ; GXSetTevColor( GX_TEVREG0, clr ) ; do { draw_kfont_one( x, cy, *cp ) ; x += 1.0f ; } while ( *++cp != '\0' ) ; } /******************************************************************************* Calculate the rectangular coordinate of the character under current canvas settings: Upper left (x1, y1), Lower right (x2, y2) *******************************************************************************/ f32 calc_kfont_x1( f32 cx ) { return ( cx * cursor_wd + cursor_x1 + letter_ox ) ; } f32 calc_kfont_y1( f32 cy ) { return ( cy * cursor_ht + cursor_y1 + letter_oy ) ; } f32 calc_kfont_x2( f32 cx ) { return ( cx * cursor_wd + cursor_x1 + letter_ox + letter_wd ) ; } f32 calc_kfont_y2( f32 cy ) { return ( cy * cursor_ht + cursor_y1 + letter_oy + letter_ht ) ; }