1 /*---------------------------------------------------------------------------*
2 Project: KPAD sample program
3 File: kfont.c
4 Programmer: Keizo Ohta
5 Haruki Tojo
6
7 Copyright 2005-2009 Nintendo. All rights reserved.
8
9 These coded instructions, statements, and computer programs contain
10 proprietary information of Nintendo of America Inc. and/or Nintendo
11 Company Ltd., and are protected by Federal copyright law. They may
12 not be disclosed to third parties or copied or duplicated in any form,
13 in whole or in part, without the prior written consent of Nintendo.
14 *---------------------------------------------------------------------------*/
15
16 #include <revolution.h>
17 #include <math.h>
18
19 #include "kfont.h"
20
21
22 /***************************************************************
23 Definitions
24 ***************************************************************/
25 #define KFONT_MAX (10+26+2) // "0~9" "A~Z" "," "." "-" "+" ":"
26 #define KFONT_WD 24 // SDK fixed
27 #define KFONT_HT 24 // SDK fixed
28 #define KFONT_SHEET_WD (KFONT_WD * KFONT_MAX) // Support up to 1024.
29 #define KFONT_SHEET_HT KFONT_HT
30 #define KFONT_TEX_SIZE (KFONT_SHEET_WD * KFONT_SHEET_HT * 4 / 8)
31
32
33 /***************************************************************
34 Variables
35 ***************************************************************/
36 static f32 canvas_wd,canvas_ht ; // Virtual canvas size
37 static f32 cursor_wd,cursor_ht ; // Cursor size
38 static s32 cursor_nx,cursor_ny ; // Number of cursors arranged on canvas
39 static f32 cursor_x1,cursor_y1 ; // Coordinate of upper leftmost cursor
40 static f32 letter_ox,letter_oy ; // Offset from the cursor position to the character position
41 static f32 letter_wd,letter_ht ; // Character size
42
43 static char *kfont_str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ,.-+:" ;
44 static void *kfont_tex ;
45 static GXTexObj kfont_tobj ;
46
47 static f32 s1_ofs ; // Adjust the display of fonts that differ between the Japanese and US versions of the console
48 static f32 s2_ofs ; //
49 static f32 t1_ofs ; //
50
51
52 /*******************************************************************************
53 Prepare a texture from a built-in font
54 *******************************************************************************/
init_kfont_texture(void)55 void init_kfont_texture( void )
56 {
57 OSFontHeader *font ;
58 void *tmp ;
59 void *tex_p ;
60 char *str_p ;
61 u32 *ptr ;
62 s32 wd, ofs ;
63
64
65 //----- Allocate texture buffer
66 kfont_tex = OSAlloc( KFONT_TEX_SIZE ) ;
67
68 //----- Clear texture buffer
69 ptr = (u32*)( (u32)kfont_tex + KFONT_TEX_SIZE ) - 1 ;
70 do {
71 *ptr = 0x00000000 ;
72 } while ( --ptr != (u32*)kfont_tex ) ;
73
74 //----- Load font data
75 if ( OSGetFontEncode() == OS_FONT_ENCODE_SJIS ) {
76 font = (OSFontHeader*)OSAlloc( OS_FONT_DATA_SIZE_SJIS ) ;
77 tmp = OSAlloc( OS_FONT_ROM_SIZE_SJIS ) ;
78
79 s1_ofs = 0.15f * (f32)KFONT_WD / (f32)KFONT_SHEET_WD ;
80 s2_ofs = -0.30f * (f32)KFONT_WD / (f32)KFONT_SHEET_WD ;
81 t1_ofs = 0.00f ;
82 } else {
83 font = (OSFontHeader*)OSAlloc( OS_FONT_DATA_SIZE_ANSI ) ;
84 tmp = OSAlloc( OS_FONT_ROM_SIZE_ANSI ) ;
85
86 s1_ofs = 0.05f * (f32)KFONT_WD / (f32)KFONT_SHEET_WD ;
87 s2_ofs = -0.10f * (f32)KFONT_WD / (f32)KFONT_SHEET_WD ;
88 t1_ofs = 0.13f ;
89 }
90 (void)OSLoadFont( font, tmp ) ;
91
92 //----- Convert font data to a texture
93 tex_p = kfont_tex ;
94 str_p = kfont_str ;
95 do {
96 (void)OSGetFontWidth( str_p, &wd ) ;
97 ofs = ( KFONT_WD - wd ) / 2 ;
98 (void)OSGetFontTexel( str_p, tex_p, ofs+1, KFONT_SHEET_WD/4, &wd ) ;
99 str_p = OSGetFontTexel( str_p, tex_p, ofs, KFONT_SHEET_WD/4, &wd ) ;
100 tex_p = (void*)( (u32)tex_p + KFONT_WD / 8 * 32 ) ;
101 } while ( *str_p != '\0' ) ;
102
103 DCStoreRange( kfont_tex, KFONT_TEX_SIZE ) ;
104 GXInitTexObj( &kfont_tobj, kfont_tex, KFONT_SHEET_WD,KFONT_SHEET_HT, GX_TF_I4, GX_CLAMP,GX_CLAMP, GX_FALSE ) ;
105 GXInitTexObjLOD( &kfont_tobj, GX_LINEAR,GX_LINEAR, 0.0f,0.0f, 0.0f, GX_DISABLE, GX_FALSE, GX_ANISO_1 ) ;
106
107 //----- Free font data
108 OSFree( font ) ;
109 OSFree( tmp ) ;
110 }
111
112
113 /*******************************************************************************
114 Initialize drawing of simple graphics
115 fb_width :Horizontal resolution of frame buffer
116 fb_height :Vertical resolution of frame buffer
117 lt_width :Letter width (line from center to center)
118 lt_height :Letter height (line from center to center)
119 ******************************************************************************/
init_draw_kfont(u16 fb_width,u16 fb_height,f32 lt_width,f32 lt_height)120 void init_draw_kfont( u16 fb_width, u16 fb_height, f32 lt_width, f32 lt_height )
121 {
122 Mtx44 proj_mtx ;
123 Mtx view_mtx ;
124
125
126 //----- Calculate variables
127 canvas_wd = fb_width * 0.91346f ;
128 canvas_ht = (f32)(fb_height) ;
129 letter_wd = lt_width ;
130 letter_ht = lt_height ;
131 cursor_wd = letter_wd * 0.90f ; // Reduce the space between letters a bit
132 cursor_ht = letter_ht * 1.05f ; // Make a little extra room in the vertical direction
133 letter_ox = ( cursor_wd - letter_wd ) * 0.5f ;
134 letter_oy = ( cursor_ht - letter_ht ) * 0.5f ;
135 cursor_nx = (s32)( canvas_wd / cursor_wd ) ;
136 cursor_ny = (s32)( canvas_ht / cursor_ht ) ;
137 cursor_x1 = (f32)cursor_nx * cursor_wd * -0.5f ;
138 cursor_y1 = (f32)cursor_ny * cursor_ht * -0.5f ;
139
140 //----- MTX
141 MTXOrtho( proj_mtx, canvas_ht * -0.5f,canvas_ht * 0.5f, canvas_wd * -0.5f,canvas_wd * 0.5f, -10.0f,10.0f ) ;
142 GXSetProjection( proj_mtx, GX_ORTHOGRAPHIC ) ;
143
144 MTXIdentity( view_mtx ) ;
145 GXLoadPosMtxImm( view_mtx, GX_PNMTX0 ) ;
146 GXSetCurrentMtx( GX_PNMTX0 ) ;
147
148 //----- VERTEX
149 GXClearVtxDesc() ;
150 GXSetVtxDesc( GX_VA_POS , GX_DIRECT ) ;
151 GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT ) ;
152 GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS , GX_POS_XY, GX_F32, 0 ) ;
153 GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 ) ;
154
155 //----- CHANNEL
156 GXSetNumChans( 0 ) ;
157 GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ;
158 GXSetChanCtrl( GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE ) ;
159
160 //----- TEXTURE
161 GXSetNumTexGens( 1 ) ;
162 GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY ) ;
163 GXLoadTexObj( &kfont_tobj, GX_TEXMAP0 ) ;
164
165 //----- TEV
166 GXSetNumTevStages( 1 ) ;
167 GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL ) ;
168 GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C0, GX_CC_TEXC, GX_CC_ZERO ) ;
169 GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ;
170 GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO ) ;
171 GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_ENABLE, GX_TEVPREV ) ;
172 GXSetAlphaCompare( GX_ALWAYS,0, GX_AOP_OR, GX_ALWAYS,0 ) ;
173
174 //----- SCREEN
175 GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP ) ;
176 GXSetAlphaUpdate( GX_DISABLE ) ;
177
178 GXSetZMode( GX_DISABLE, GX_ALWAYS, GX_DISABLE ) ;
179 GXSetCullMode( GX_CULL_BACK ) ;
180 }
181
182
183 /*******************************************************************************
184 Draw font character
185 *******************************************************************************/
draw_kfont_one(f32 cx,f32 cy,char c)186 static void draw_kfont_one( f32 cx, f32 cy, char c )
187 {
188 f32 x1,x2, y1,y2, s1,s2 ;
189 s32 i ;
190
191
192 if ( c >= 'A' && c <= 'Z' ) {
193 i = c - 'A' + 10 ;
194 } else if ( c >= '0' && c <= '9' ) {
195 i = c - '0' ;
196 } else if ( c == ',' ) {
197 i = 10 + 26 ;
198 } else if ( c == '.' ) {
199 i = 10 + 26 + 1;
200 } else if ( c == '-' ) {
201 i = 10 + 26 + 2 ;
202 } else if ( c == '+' ) {
203 i = 10 + 26 + 3 ;
204 } else if ( c == ':' ) {
205 i = 10 + 26 + 4 ;
206 } else {
207 return ;
208 }
209
210 s1 = (f32)( i * KFONT_WD ) / (f32)KFONT_SHEET_WD + s1_ofs ;
211 s2 = s1 + (f32)KFONT_WD / (f32)KFONT_SHEET_WD + s2_ofs ;
212
213 x1 = cx * cursor_wd + cursor_x1 + letter_ox ;
214 x2 = x1 + letter_wd ;
215
216 y1 = cy * cursor_ht + cursor_y1 + letter_oy ;
217 y2 = y1 + letter_ht ;
218
219 GXBegin( GX_QUADS, GX_VTXFMT0, 4 ) ;
220 GXPosition2f32( x1,y1 ) ; GXTexCoord2f32( s1,t1_ofs ) ;
221 GXPosition2f32( x2,y1 ) ; GXTexCoord2f32( s2,t1_ofs ) ;
222 GXPosition2f32( x2,y2 ) ; GXTexCoord2f32( s2,1.0f ) ;
223 GXPosition2f32( x1,y2 ) ; GXTexCoord2f32( s1,1.0f ) ;
224 GXEnd() ;
225 }
226
227
228 /*******************************************************************************
229 Draw integer (return the number of characters that were drawn)
230 *******************************************************************************/
draw_kfont_s32(f32 cx,f32 cy,GXColor clr,s32 val)231 s32 draw_kfont_s32( f32 cx, f32 cy, GXColor clr, s32 val )
232 {
233 s32 v,a, rt = 0 ;
234 f32 x ;
235
236
237 GXSetTevColor( GX_TEVREG0, clr ) ;
238
239 //----- Prepare positive number
240 if ( val < 0 ) {
241 v = -val ;
242 } else {
243 v = val ;
244 }
245
246 //----- Draw number beginning from the lowest digit
247 x = cx ;
248 do {
249 a = v % 10 ;
250 draw_kfont_one( x, cy, (char)('0'+ a ) ) ;
251 x -= 1.0f ;
252 ++ rt ;
253 v -= a ;
254 v /= 10 ;
255 } while ( v != 0 ) ;
256
257 //----- Draw sign
258 if ( val < 0 ) {
259 draw_kfont_one( x, cy, '-' ) ;
260 ++ rt ;
261 }
262
263 return ( rt ) ;
264 }
265
266
267 /*******************************************************************************
268 Draw floating point (also specify the number of digits following the decimal point)
269 *******************************************************************************/
draw_kfont_f32(f32 cx,f32 cy,GXColor clr,f32 val,s32 keta)270 s32 draw_kfont_f32( f32 cx, f32 cy, GXColor clr, f32 val, s32 keta )
271 {
272 s32 v,a, k,n, rt ;
273 f32 x, vf ;
274
275
276 GXSetTevColor( GX_TEVREG0, clr ) ;
277
278 //----- Prepare positive number
279 if ( val < 0.0f ) {
280 vf = -val ;
281 } else {
282 vf = val ;
283 }
284
285 //----- Calculate the number of displayed digits that follow the decimal point
286 k = (s32)keta ;
287 if ( k < 1 ) k = 1 ;
288
289 //----- Shift digits so that the portion to be displayed following the decimal point is a positive number
290 n = k ;
291 do {
292 vf *= 10.0f ;
293 } while ( --n != 0 ) ;
294
295 //----- Draw the number following the decimal point
296 v = (s32)( vf + 0.5f ) ;
297 x = cx + 1.0f + (f32)k ;
298 n = k ;
299 do {
300 a = v % 10 ;
301 draw_kfont_one( x, cy, (char)('0'+ a ) ) ;
302 x -= 1.0f ;
303 v -= a ;
304 v /= 10 ;
305 } while ( --n != 0 ) ;
306
307 //----- Draw decimal point
308 draw_kfont_one( x, cy, '.' ) ;
309 x -= 1.0f ;
310 rt = 1 + k ;
311
312 //----- Draw the integer part of the number as an integer
313 a = draw_kfont_s32( cx, cy, clr, v ) ;
314 rt += a ;
315 if ( val < 0.0f ) {
316 draw_kfont_one( cx - a, cy, '-' ) ;
317 ++ rt ;
318 }
319
320 return ( rt ) ;
321 }
322
323
324 /*******************************************************************************
325 Draw binary number (also specify the number of bits to be displayed)
326 *******************************************************************************/
draw_kfont_bit(f32 cx,f32 cy,GXColor clr,u32 val,s32 keta)327 void draw_kfont_bit( f32 cx, f32 cy, GXColor clr, u32 val, s32 keta )
328 {
329 u32 bit = 1 ;
330 s32 n = keta ;
331 f32 x = cx ;
332
333
334 GXSetTevColor( GX_TEVREG0, clr ) ;
335
336 do {
337 if ( (bit & 0x01010100) != 0 ) {
338 draw_kfont_one( x, cy, '-' ) ;
339 x -= 1.0f ;
340 }
341 if ( (val & bit) != 0 ) {
342 draw_kfont_one( x, cy, '1' ) ;
343 } else {
344 draw_kfont_one( x, cy, '0' ) ;
345 }
346 x -= 1.0f ;
347 bit <<= 1 ;
348 } while ( --n != 0 ) ;
349 }
350
351
352 /*******************************************************************************
353 Draw character string
354 *******************************************************************************/
draw_kfont_letter(f32 cx,f32 cy,GXColor clr,char * str)355 void draw_kfont_letter( f32 cx, f32 cy, GXColor clr, char *str )
356 {
357 f32 x = cx ;
358 char *cp = str ;
359
360
361 GXSetTevColor( GX_TEVREG0, clr ) ;
362
363 do {
364 draw_kfont_one( x, cy, *cp ) ;
365 x += 1.0f ;
366 } while ( *++cp != '\0' ) ;
367 }
368
369
370 /*******************************************************************************
371 Calculate the rectangular coordinate of the character under current canvas settings: Upper left (x1, y1), Lower right (x2, y2)
372 *******************************************************************************/
calc_kfont_x1(f32 cx)373 f32 calc_kfont_x1( f32 cx )
374 {
375 return ( cx * cursor_wd + cursor_x1 + letter_ox ) ;
376 }
377
calc_kfont_y1(f32 cy)378 f32 calc_kfont_y1( f32 cy )
379 {
380 return ( cy * cursor_ht + cursor_y1 + letter_oy ) ;
381 }
382
calc_kfont_x2(f32 cx)383 f32 calc_kfont_x2( f32 cx )
384 {
385 return ( cx * cursor_wd + cursor_x1 + letter_ox + letter_wd ) ;
386 }
387
calc_kfont_y2(f32 cy)388 f32 calc_kfont_y2( f32 cy )
389 {
390 return ( cy * cursor_ht + cursor_y1 + letter_oy + letter_ht ) ;
391 }
392