1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin
3   File:     DEMOPuts.c
4 
5   Copyright 1998-2006 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: DEMOPuts.c,v $
14   Revision 1.9  2008/07/29 07:26:38  nakano_yoshinobu
15   Added comments for ASSERT.
16 
17   Revision 1.8  2008/07/29 07:19:07  nakano_yoshinobu
18   Changed vsprintf of DEMORFPrintf to vsnprintf for the buffer overflow measures.
19 
20   Revision 1.7  2008/07/23 06:01:47  nakano_yoshinobu
21   Changed vsprintf of DEMOPrintf to vsnprintf for the buffer overflow measures.
22 
23   Revision 1.6  2008/05/23 07:34:32  nakano_yoshinobu
24   Fixed ASSERT in DEMOPrintf.
25 
26   Revision 1.5  2008/05/22 08:29:35  nakano_yoshinobu
27   Added ASSERT in DEMOPrintf.
28 
29   Revision 1.4  2006/08/07 00:08:00  tojo
30   Allocated memory for ROM font by MEM.
31 
32   Revision 1.3  2006/02/20 04:19:58  mitu
33   Changed include path from dolphin/ to revolution/.
34 
35   Revision 1.2  2006/01/07 07:14:44  hirose
36   Deleted obsolete target codes.
37 
38   Revision 1.1.1.1  2005/05/12 02:15:48  yasuh-to
39   Ported from dolphin source tree.
40 
41     22     2004/03/10 17:53 Shiki
42     Added support for UTF code.
43 
44     21    2003/04/08 21:25 Hirose
45     Fixed a problem with field-rendering mode.
46 
47     20    2002/08/22 20:33 Shiki
48     Modified DEMORFPuts() to process tab character.
49 
50     19    2001/12/14 9:46 Shiki
51     Fixed DEMODumpROMFont().
52 
53     18    2001/07/12 18:02 Shiki
54     Added DEMOGetROMFontSize() and DEMOGetRFTextHeight().
55 
56     17    2001/06/11 4:08p Hirose
57     Fixed text alignment problem again.
58 
59     16    2001/05/09 10:11p Hirose
60     Renamed some ROM font functions
61 
62     15    2001/04/28 1:07p John
63     Fixed MAC build errors:
64     Renamed Size to FontSize
65     Renamed DrawChar to DrawFontChar
66 
67     14    2001/04/25 14:29 Shiki
68     Revised ROM font API interface. Added DEMOGetTextWidth().
69 
70     13    2001/04/25 11:32 Shiki
71     Added DEMOSetFontSize().
72 
73     12    2001/04/19 13:41 Shiki
74     Added ROM font functions.
75 
76     11    2000/10/27 3:47p Hirose
77     Fixed build flags
78 
79     10    2000/07/07 7:09p Dante
80     PC Compatibility
81 
82     9     2000/06/13 5:17p Shiki
83     Fixed DEMOPrintf().
84 
85     8     2000/06/06 8:58p Carl
86     Fixed text alignment problem.
87 
88     7     2000/05/20 4:57a Hirose
89     Fixed TevOrder and NumChans for drawing captions
90 
91     6     2000/05/17 9:08p Hirose
92     Deleted tab codes
93 
94     5     2000/05/17 8:53p Hirose
95     Fixed pixel processing mode setting defined in DEMOInitCaption
96 
97     4     2000/03/06 11:54a Alligator
98     Changed GXSetDefaultMtx to GXSetCurrentMtx
99 
100     3     2000/01/13 5:55p Alligator
101     Integrated with ArtX GX library code
102 
103     2     1999/12/10 4:48p Carl
104     Fixed Z compare stuff.
105 
106     21    1999/11/12 4:31p Yasu
107     Added GXSetNumTexGens
108 
109     20    1999/11/09 7:47p Hirose
110     Added GXSetNumTexGens and GXSetTevOrder
111 
112     19    1999/10/29 3:45p Hirose
113     Replaced GXSetTevStages(GXTevStageID) by GXSetNumTevStages(u8)
114 
115     18    1999/10/13 6:38p Yasu
116     Rollback 1 level
117 
118     16    1999/09/30 10:32p Yasu
119     Renamed and clean up functions and enums.
120 
121     15    1999/09/29 10:29p Yasu
122     Parameter of GXSetFogRangeAdj was changed
123 
124     14    1999/09/28 6:56p Yasu
125     Changed calling parameter of DEMOInitCaption
126 
127     13    1999/09/28 2:46a Yasu
128     Added more initialize works in DEMOInitCaption
129 
130     12    1999/09/27 11:03p Yasu
131     Z scale was inversed in DEMOSetupScrnSpc
132 
133     11    1999/09/24 6:47p Yasu
134     Changed the parameter of DEMOsetuoScrnSpc().
135 
136     10    1999/09/24 6:34p Yasu
137     Let DEMOSetupScrnSpc() out of DEMOInitCaption()
138 
139     9     1999/09/21 5:24p Yasu
140     Changed function name cmMtxScreen -> DEMOMtxScreen.
141 
142     8     1999/09/14 5:12p Yasu
143     Fixed small bug.
144 
145     7     1999/09/14 4:57p Yasu
146     Moved it into the demo library.
147     Changed APIs to simpler.
148 
149     6     1999/09/10 6:38a Yasu
150     Added small letters.
151     Added some type cast to avoid warning message
152 
153     5     1999/09/07 9:52p Yasu
154     Changed file name and prefix
155 
156     4     1999/09/01 5:45p Ryan
157 
158     3     1999/08/28 12:08a Yasu
159     Changed enum name GX_MAT_3x4 -> GX_MTX3x4
160 
161     2     1999/08/26 7:55p Yasu
162     Changed function name.
163 
164     1     1999/08/25 6:21p Yasu
165     Initial version
166   $NoKeywords: $
167  *---------------------------------------------------------------------------*/
168 #include        <revolution.h>
169 #include        <stdio.h>
170 #include        <stdarg.h>
171 #include        <string.h>
172 #include        <demo.h>
173 
174 extern u32		DemoUseMEMHeap;
175 
176 extern MEMAllocator	DemoAllocator1;
177 extern MEMAllocator	DemoAllocator2;
178 
179 
180 //============================================================================
181 //  Font data
182 //============================================================================
183 static  s32             fontShift = 0;
184 static  GXTexObj        fontTexObj;
185 
186 //============================================================================
187 //  Functions
188 //============================================================================
189 
190 /*---------------------------------------------------------------------------*
191     Name:           DEMOSetFontType
192     Description:    Set font type
193     Arguments:      s32 attr: Font attribute id
194     Returns:        None.
195  *---------------------------------------------------------------------------*/
DEMOSetFontType(s32 attr)196 void    DEMOSetFontType( s32 attr )
197 {
198     // Font type
199     switch ( attr )
200     {
201       case  DM_FT_RVS:
202         // Reverse mode
203         GXSetBlendMode( GX_BM_LOGIC, GX_BL_ZERO, GX_BL_ZERO, GX_LO_INVCOPY );
204         break;
205 
206       case  DM_FT_XLU:
207         // Translucent mode
208         GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR );
209         break;
210 
211       case  DM_FT_OPQ:
212       default:
213         // Normal mode
214         GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR );
215         break;
216     }
217     return;
218 }
219 
220 /*---------------------------------------------------------------------------*
221     Name:           DEMOLoadFont
222     Description:    Prepare font texture
223     Arguments:      DMTexFlt   texFlt: DMTF_BILERP/DMTF_POINTSAMPLE
224                     GXBool bilerp: if you need bilerp image, set this
225     Returns:        None.
226  *---------------------------------------------------------------------------*/
DEMOLoadFont(GXTexMapID texMap,GXTexMtx texMtx,DMTexFlt texFlt)227 void    DEMOLoadFont( GXTexMapID texMap, GXTexMtx texMtx, DMTexFlt texFlt )
228 {
229     Mtx         fontTMtx;
230     u16         width  = 64;
231     u16         height = (u16)( (0x80-0x20)*8*8 / width );
232 
233     // Set up and load texture object
234     GXInitTexObj( &fontTexObj,          // obj
235                   DEMOFontBitmap,       // image_ptr
236                   width,                // weight
237                   height,               // height
238                   GX_TF_I4,             // format
239                   GX_CLAMP,             // wrap_s (don't care)
240                   GX_CLAMP,             // wrap_t (don't care)
241                   GX_FALSE );           // mipmap (don't care)
242 
243     if ( texFlt == DMTF_POINTSAMPLE )
244     {
245         GXInitTexObjLOD( &fontTexObj,
246                          GX_NEAR,       // min_filt
247                          GX_NEAR,       // max_filt
248                          0.0f,          // min_lod     (don't care)
249                          0.0f,          // max_lod     (don't care)
250                          0.0f,          // lod_bias    (don't care)
251                          GX_DISABLE,    // bias_clamp  (don't care)
252                          GX_FALSE,      // do_edge_lod (don't care)
253                          GX_ANISO_1 );  // max_aniso   (don't care)
254         fontShift = 0;
255     }
256     else
257     {
258         fontShift = 1;
259     }
260 
261     GXLoadTexObj( &fontTexObj, texMap );
262 
263     // Set texture matrix to fit texture coordinate to texel (1:1)
264     // Set up texture coord-gen
265     MTXScale( fontTMtx, 1.0f/(float)width, 1.0f/(float)height, 1.0f );
266 
267     GXLoadTexMtxImm( fontTMtx, texMtx, GX_MTX2x4 );
268     GXSetNumTexGens( 1 );
269     GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, texMtx );
270 
271     return;
272 }
273 
274 /*---------------------------------------------------------------------------*
275     Name:           DEMOSetupScrnSpc
276     Description:    Set matrices up to screen coordinates system
277     Arguments:
278 
279     Returns:        None.
280  *---------------------------------------------------------------------------*/
DEMOSetupScrnSpc(s32 width,s32 height,float depth)281 void    DEMOSetupScrnSpc( s32 width, s32 height, float depth )
282 {
283     Mtx44  pMtx;
284     Mtx    mMtx;
285     f32   top;
286 
287     if ( DEMOGetRenderModeObj()->field_rendering && !VIGetNextField() )
288     {
289         top = -0.667F;
290     }
291     else
292     {
293         top = 0.00F;
294     }
295 
296     MTXOrtho( pMtx, top, (float)height, 0.0f, (float)width, 0.0f, -depth );
297     GXSetProjection( pMtx, GX_ORTHOGRAPHIC );
298     MTXIdentity( mMtx );
299     GXLoadPosMtxImm( mMtx, GX_PNMTX0 );
300     GXSetCurrentMtx( GX_PNMTX0 );
301 
302     return;
303 }
304 
305 /*---------------------------------------------------------------------------*
306     Name:           DEMOInitCaption
307     Description:    Set rendering pipe to default caption drawing mode
308     Arguments:
309 
310     Returns:        None.
311  *---------------------------------------------------------------------------*/
DEMOInitCaption(s32 font_type,s32 width,s32 height)312 void    DEMOInitCaption( s32 font_type, s32 width, s32 height )
313 {
314     // Set matrices
315     DEMOSetupScrnSpc( width, height, 100.0f );
316 
317     // Set pixel processing mode
318     GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE );
319 
320     // Set TEV parameters to "REPLACE COLOR"
321     GXSetNumChans( 0 );
322     GXSetNumTevStages( 1 );
323     GXSetTevOp( GX_TEVSTAGE0, GX_REPLACE );
324     GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL );
325 
326     // Load Font
327     DEMOLoadFont( GX_TEXMAP0, GX_TEXMTX0, DMTF_POINTSAMPLE );
328 
329     // Set font attr to normal
330     DEMOSetFontType( font_type );
331 
332     return;
333 }
334 
335 /*---------------------------------------------------------------------------*
336     Name:           DEMOPuts
337     Description:    Output strings until detects NULL code
338     Arguments:      s16  x, y, z: Coordinate at the origin
339                     char *string: Output strings
340     Returns:        None.
341  *---------------------------------------------------------------------------*/
DEMOPuts(s16 x,s16 y,s16 z,char * string)342 void    DEMOPuts( s16 x, s16 y, s16 z, char* string )
343 {
344     char* str = string;
345     s32   s, t;
346     s32   c, w, len, i;
347 
348     // Set up vertex descriptors
349     GXClearVtxDesc();
350     GXSetVtxDesc( GX_VA_POS,  GX_DIRECT );
351     GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );
352     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS,  GX_POS_XYZ, GX_S16, 0 );
353     GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST,  GX_S16, 1 );
354 
355     len = 0;
356     while (1)
357     {
358         // Search visible letters
359         c = *str ++;
360         if ( ' ' <= c && c <= 0x7f )
361         {
362             len ++;
363         }
364         // Check if end of line
365         else
366         {
367             if ( len > 0 )
368             {
369                 // Put a line
370                 GXBegin( GX_QUADS, GX_VTXFMT0, (u16)(len*4) );
371                 for ( i = 0; i < len; i ++ )
372                 {
373                     // Draw a letter
374                     w = string[i] - ' ';
375                     s = ( w % 8 ) * 16 + fontShift;
376                     t = ( w / 8 ) * 16 + fontShift;
377                     GXPosition3s16( (s16)(i*8+x  ), (s16)(y   ), z );
378                     GXTexCoord2s16( (s16)(s      ), (s16)(t   )    );
379                     GXPosition3s16( (s16)(i*8+x+8), (s16)(y   ), z );
380                     GXTexCoord2s16( (s16)(s+16   ), (s16)(t   )    );
381                     GXPosition3s16( (s16)(i*8+x+8), (s16)(y+8 ), z );
382                     GXTexCoord2s16( (s16)(s+16   ), (s16)(t+16)    );
383                     GXPosition3s16( (s16)(i*8+x  ), (s16)(y+8 ), z );
384                     GXTexCoord2s16( (s16)(s      ), (s16)(t+16)    );
385                 }
386                 GXEnd( );
387                 len = 0;
388             }
389             string = str;
390             // Continue if CR/LF
391             if ( c == '\n' ) y += 8;
392             // Terminate if else
393             else break;
394         }
395     }
396     return;
397 }
398 
399 /*---------------------------------------------------------------------------*
400     Name:           DEMOPrintf
401     Description:    Output formatted strings
402                     Strings must be shorter than 256 words.
403     Arguments:      s16 x, y, z: Coordinate at the origin.
404                     char *fmt:   Format string
405                     ...:         Any other parameter
406     Returns:        None.
407  *---------------------------------------------------------------------------*/
DEMOPrintf(s16 x,s16 y,s16 z,char * fmt,...)408 void    DEMOPrintf( s16 x, s16 y, s16 z, char* fmt, ... )
409 {
410     va_list  vlist;
411     char     buf[256];
412     int      stringSize;
413 
414     // Get output string
415     va_start( vlist, fmt );
416     stringSize = vsnprintf( buf, 256, fmt, vlist );
417     // Assert for over string size
418     ASSERT( stringSize < 256 );
419     va_end( vlist );
420 
421     // Feed to puts
422     DEMOPuts( x, y, z, buf );
423 
424     return;
425 }
426 
427 //============================================================================
428 //
429 //  ROM Font data and functions
430 //
431 //============================================================================
432 
433 static OSFontHeader* FontData;
434 static void*         LastSheet;
435 static s16           FontSize;      // GX_S16, 4
436 static s16           FontSpace;     // GX_S16, 4
437 
438 /*---------------------------------------------------------------------------*
439     Name:           DEMOInitROMFont
440 
441     Description:    Allocates font buffer from the heap and initializes ROM
442                     font
443 
444     Arguments:      None
445 
446     Returns:        Pointer to font data
447  *---------------------------------------------------------------------------*/
DEMOInitROMFont(void)448 OSFontHeader* DEMOInitROMFont(void)
449 {
450     switch (OSGetFontEncode())
451     {
452       case OS_FONT_ENCODE_SJIS:
453         if (DemoUseMEMHeap)
454         {
455             FontData = MEMAllocFromAllocator(&DemoAllocator1, OS_FONT_SIZE_SJIS);
456         }
457         else
458         {
459             FontData = OSAlloc(OS_FONT_SIZE_SJIS);
460         }
461         break;
462       case OS_FONT_ENCODE_ANSI:
463         if (DemoUseMEMHeap)
464         {
465             FontData = MEMAllocFromAllocator(&DemoAllocator1, OS_FONT_SIZE_ANSI);
466         }
467         else
468         {
469             FontData = OSAlloc(OS_FONT_SIZE_ANSI);
470         }
471         break;
472       default:
473         if (DemoUseMEMHeap)
474         {
475             FontData = MEMAllocFromAllocator(&DemoAllocator1, OS_FONT_SIZE_UTF);
476         }
477         else
478         {
479             FontData = OSAlloc(OS_FONT_SIZE_UTF);
480         }
481         break;
482     }
483     if (!FontData)
484     {
485         OSHalt("Ins. memory to load ROM font.");
486     }
487     if (!OSInitFont(FontData))
488     {
489         OSHalt("ROM font is available in boot ROM ver 0.8 or later.");
490     }
491 
492     FontSize  = (s16) (FontData->cellWidth * 16);
493     FontSpace = -16;
494 
495     return FontData;
496 }
497 
498 /*---------------------------------------------------------------------------*
499     Name:           DEMOSetROMFontSize
500 
501     Description:    Specifies the font size
502 
503     Arguments:      size        Font size
504                     space       Character space
505 
506     Returns:        None
507  *---------------------------------------------------------------------------*/
DEMOSetROMFontSize(s16 size,s16 space)508 void DEMOSetROMFontSize(s16 size, s16 space)
509 {
510     FontSize  = (s16) (size  * 16);
511     FontSpace = (s16) (space * 16);
512 }
513 
514 /*---------------------------------------------------------------------------*
515     Name:           DEMOGetROMFontSize
516 
517     Description:    Gets the current font size
518 
519     Arguments:      size        Font size
520                     space       Character space
521 
522     Returns:        None
523  *---------------------------------------------------------------------------*/
DEMOGetROMFontSize(s16 * size,s16 * space)524 void DEMOGetROMFontSize(s16* size, s16* space)
525 {
526     if (size)
527     {
528         *size  = (s16) (FontSize  / 16);
529     }
530     if (space)
531     {
532         *space = (s16) (FontSpace / 16);
533     }
534 }
535 
DrawFontChar(int x,int y,int z,int xChar,int yChar)536 static void DrawFontChar(int x, int y, int z, int xChar, int yChar)
537 {
538     s16 posLeft   = (s16) x;
539     s16 posRight  = (s16) (posLeft + FontSize);
540     s16 posTop    = (s16) (y - (FontData->ascent  * FontSize / FontData->cellWidth));
541     s16 posBottom = (s16) (y + (FontData->descent * FontSize / FontData->cellWidth));
542 
543     s16 texLeft   = (s16) xChar;
544     s16 texRight  = (s16) (xChar + FontData->cellWidth);
545     s16 texTop    = (s16) yChar;
546     s16 texBottom = (s16) (yChar + FontData->cellHeight);
547 
548     GXBegin(GX_QUADS, GX_VTXFMT0, 4);
549         GXPosition3s16(posLeft , posTop   , (s16) z);
550         GXTexCoord2s16(texLeft , texTop      );
551 
552         GXPosition3s16(posRight, posTop   , (s16) z);
553         GXTexCoord2s16(texRight, texTop      );
554 
555         GXPosition3s16(posRight, posBottom, (s16) z);
556         GXTexCoord2s16(texRight, texBottom   );
557 
558         GXPosition3s16(posLeft , posBottom, (s16) z);
559         GXTexCoord2s16(texLeft , texBottom   );
560     GXEnd();
561 }
562 
LoadSheet(void * image,GXTexMapID texMapID)563 static void LoadSheet(void* image, GXTexMapID texMapID)
564 {
565     Mtx          mtx;
566     GXTexObj     texObj;
567 
568     if (LastSheet == image)
569     {
570         return;
571     }
572     LastSheet = image;
573 
574     // Set up and load texture object
575     GXInitTexObj(&texObj,                           // obj
576                  image,                             // image_ptr
577                  FontData->sheetWidth,              // weight
578                  FontData->sheetHeight,             // height
579                  (GXTexFmt) FontData->sheetFormat,  // format
580                  GX_CLAMP,                          // wrap_s (don't care)
581                  GX_CLAMP,                          // wrap_t (don't care)
582                  GX_FALSE);                         // mipmap (don't care)
583 
584     GXInitTexObjLOD(&texObj,
585                     GX_LINEAR,     // min_filt
586                     GX_LINEAR,     // max_filt
587                     0.0f,          // min_lod     (don't care)
588                     0.0f,          // max_lod     (don't care)
589                     0.0f,          // lod_bias    (don't care)
590                     GX_DISABLE,    // bias_clamp  (don't care)
591                     GX_FALSE,      // do_edge_lod (don't care)
592                     GX_ANISO_1);   // max_aniso   (don't care)
593 
594     GXLoadTexObj(&texObj, texMapID);
595     MTXScale(mtx, 1.0f / FontData->sheetWidth,
596                   1.0f / FontData->sheetHeight,
597                   1.0f);
598     GXLoadTexMtxImm(mtx, GX_TEXMTX0, GX_MTX2x4);
599     GXSetNumTexGens(1);
600     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
601 }
602 
603 /*---------------------------------------------------------------------------*
604     Name:           DEMORFPuts
605 
606     Description:    Draw the specified string with ROM font
607 
608     Arguments:      x       Baseline horizontal position
609                     y       Baseline vertical position
610                     string  Output strings
611 
612     Returns:        Total string width in texels
613  *---------------------------------------------------------------------------*/
DEMORFPuts(s16 x,s16 y,s16 z,char * string)614 int DEMORFPuts(s16 x, s16 y, s16 z, char* string)
615 {
616     s32   cx;
617     void* image;
618     s32   xChar;
619     s32   yChar;
620     s32   width;
621 
622     ASSERT(FontData);
623 
624     LastSheet = 0;
625 
626     // Set up vertex descriptors
627     GXClearVtxDesc();
628     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
629     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
630     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS,  GX_POS_XYZ, GX_S16, 4);
631     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST,  GX_S16, 0);
632 
633     // Convert to GX_S16, 4 format
634     x *= 16;
635     y *= 16;
636     z *= 16;
637 
638     width = 0;
639     while (*string)
640     {
641         if (*string == '\n')
642         {
643             width = 0;
644             y += FontData->leading * FontSize / FontData->cellWidth;
645             ++string;
646             continue;
647         }
648 
649         if (*string == '\t')
650         {
651             width += 8 * (FontSize + FontSpace);
652             width -= width % (8 * (FontSize + FontSpace));
653             ++string;
654             continue;
655         }
656 
657         string = OSGetFontTexture(string, &image, &xChar, &yChar, &cx);
658 
659         LoadSheet(image, GX_TEXMAP0);
660         DrawFontChar(x + width, y, z, xChar, yChar);
661         width += FontSize * cx / FontData->cellWidth + FontSpace;
662     }
663     return (width + 15) / 16;
664 }
665 
DEMORFPutsEx(s16 x,s16 y,s16 z,char * string,s16 maxWidth,int length)666 int DEMORFPutsEx(s16 x, s16 y, s16 z, char* string, s16 maxWidth, int length)
667 {
668     s32   cx;
669     void* image;
670     s32   xChar;
671     s32   yChar;
672     s32   width;
673     char* end;
674 
675     ASSERT(FontData);
676 
677     LastSheet = 0;
678 
679     // Set up vertex descriptors
680     GXClearVtxDesc();
681     GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
682     GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
683     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS,  GX_POS_XYZ, GX_S16, 4);
684     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST,  GX_S16, 0);
685 
686     // Convert to GX_S16, 4 format
687     x *= 16;
688     y *= 16;
689     z *= 16;
690     maxWidth *= 16;
691 
692     end = string + length;
693     width = 0;
694     while (*string && string < end)
695     {
696         // Line break
697         if (*string == '\n')
698         {
699             width = 0;
700             y += FontData->leading * FontSize / FontData->cellWidth;
701             ++string;
702             continue;
703         }
704 
705         string = OSGetFontTexture(string, &image, &xChar, &yChar, &cx);
706 
707         // Line break
708         if (maxWidth < width + FontSize * cx / FontData->cellWidth + FontSpace)
709         {
710             width = 0;
711             y += FontData->leading * FontSize / FontData->cellWidth;
712         }
713 
714         LoadSheet(image, GX_TEXMAP0);
715         DrawFontChar(x + width, y, z, xChar, yChar);
716         width += FontSize * cx / FontData->cellWidth + FontSpace;
717     }
718     return (width + 15) / 16;
719 }
720 
721 /*---------------------------------------------------------------------------*
722     Name:           DEMORFPrintf
723 
724     Description:    Output formatted strings with ROM font
725                     Strings must be shorter than 256 words.
726 
727     Arguments:      s16 x, y, z: Coordinate at the origin.
728                     char *fmt:   Format string
729                     ...:         Any other parameter
730 
731     Returns:        Total string width in texels
732  *---------------------------------------------------------------------------*/
DEMORFPrintf(s16 x,s16 y,s16 z,char * fmt,...)733 int DEMORFPrintf(s16 x, s16 y, s16 z, char* fmt, ...)
734 {
735     va_list  vlist;
736     char     buf[256];
737     int      stringSize;
738 
739     // Get output string
740     va_start( vlist, fmt );
741     stringSize = vsnprintf( buf, 256, fmt, vlist );
742     // Assert for over string size
743     ASSERT( stringSize < 256 );
744     va_end( vlist );
745 
746     // Feed to puts
747     return DEMORFPuts(x, y, z, buf);
748 }
749 
750 /*---------------------------------------------------------------------------*
751   Name:         DEMODumpROMFont
752 
753   Description:  Dumps the ROM font data to debug output
754 
755   Arguments:    string  Output strings
756 
757   Returns:      Pointer to the next character
758  *---------------------------------------------------------------------------*/
DEMODumpROMFont(char * string)759 char* DEMODumpROMFont(char* string)
760 {
761     u32   image[48/2*48/4];   // 48 x 48
762     void* temp;
763     int   i, j;
764     s32   width;
765 
766     ASSERT(FontData);
767 
768     switch (OSGetFontEncode())
769     {
770       case OS_FONT_ENCODE_SJIS:
771         temp = (u8*) FontData + OS_FONT_SIZE_SJIS - OS_FONT_ROM_SIZE_SJIS;
772         break;
773       case OS_FONT_ENCODE_ANSI:
774         temp = (u8*) FontData + OS_FONT_SIZE_ANSI - OS_FONT_ROM_SIZE_ANSI;
775         break;
776       default:
777         temp = (u8*) FontData + OS_FONT_SIZE_UTF - OS_FONT_ROM_SIZE_UTF;
778         break;
779     }
780     temp = (void*) OSRoundDown32B(temp);
781     OSLoadFont(FontData, temp);
782 
783     // Clear image buffer by zero since OSGetFontTexel() copies out
784     // font texels using logical OR.
785     memset(image, 0x00, sizeof(image));
786 
787     // OSGetFontTexel() only works with the compressed font data
788     // read by OSLoadFont().
789     string = OSGetFontTexel(string, image, 0, 48 / 4, &width);
790 
791     for (i = 0; i < 48; i++)
792     {
793         j = 48 * (i / 8) + (i % 8);
794         OSReport("%08x%08x%08x%08x%08x%08x\n",
795                  image[j],        image[j + 32/4],  image[j + 64/4],
796                  image[j + 96/4], image[j + 128/4], image[j + 160/4]);
797     }
798 
799     OSReport("\nwidth %d\n", width);
800 
801     OSInitFont(FontData);   // To re-expand compressed data
802 
803     return string;
804 }
805 
806 /*---------------------------------------------------------------------------*
807     Name:           DEMOGetRFTextWidth
808 
809     Description:    Computes the width of the specified string
810 
811     Arguments:      string  Point to character string
812 
813     Returns:        Total string width in texels
814  *---------------------------------------------------------------------------*/
DEMOGetRFTextWidth(char * string)815 int DEMOGetRFTextWidth(char* string)
816 {
817     s32   cx;
818     s32   width;
819     s32   maxWidth;
820 
821     ASSERT(FontData);
822 
823     maxWidth = width = 0;
824     while (*string)
825     {
826         if (*string == '\n')
827         {
828             if (maxWidth < width)
829             {
830                 maxWidth = width;
831             }
832             width = 0;
833         }
834         string = OSGetFontWidth(string, &cx);
835         width += FontSize * cx / FontData->cellWidth + FontSpace;
836     }
837     if (maxWidth < width)
838     {
839         maxWidth = width;
840     }
841     return (maxWidth + 15) / 16;
842 }
843 
844 /*---------------------------------------------------------------------------*
845     Name:           DEMOGetRFTextHeight
846 
847     Description:    Computes the height of the specified string
848 
849     Arguments:      string  Point to character string
850 
851     Returns:        Total string height in texels
852  *---------------------------------------------------------------------------*/
DEMOGetRFTextHeight(char * string)853 int DEMOGetRFTextHeight(char* string)
854 {
855     s32 height;
856 
857     ASSERT(FontData);
858 
859     height = 1;
860     while (*string)
861     {
862         if (*string == '\n')
863         {
864             ++height;
865         }
866         ++string;
867     }
868     height *= FontData->leading * FontSize / FontData->cellWidth;
869     return (height + 15) / 16;
870 }
871 
872 /*======== End of DEMOPuts.c ========*/
873