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