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