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