/*---------------------------------------------------------------------------* Project: Dolphin File: DEMOPuts.c Copyright 1998-2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: DEMOPuts.c,v $ Revision 1.4 2006/08/07 00:08:00 tojo Allocated memory for ROM font by MEM. Revision 1.3 2006/02/20 04:19:58 mitu Changed include path from dolphin/ to revolution/. Revision 1.2 2006/01/07 07:14:44 hirose Deleted obsolete target codes. Revision 1.1.1.1 2005/05/12 02:15:48 yasuh-to transitioned from the Dolphin source tree 22 2004/03/10 17:53 Shiki Added support for UTF code. 21 2003/04/08 21:25 Hirose Fixed a problem with field-rendering mode. 20 2002/08/22 20:33 Shiki Modified DEMORFPuts() to process tab character. 19 2001/12/14 9:46 Shiki Fixed DEMODumpROMFont(). 18 2001/07/12 18:02 Shiki Added DEMOGetROMFontSize() and DEMOGetRFTextHeight(). 17 2001/06/11 4:08p Hirose Fixed text alignment problem again. 16 2001/05/09 10:11p Hirose Renamed some ROM font functions 15 2001/04/28 1:07p John Fixed MAC build errors: Renamed Size to FontSize Renamed DrawChar to DrawFontChar 14 2001/04/25 14:29 Shiki Revised ROM font API interface. Added DEMOGetTextWidth(). 13 2001/04/25 11:32 Shiki Added DEMOSetFontSize(). 12 2001/04/19 13:41 Shiki Added ROM font functions. 11 2000/10/27 3:47p Hirose Fixed build flags 10 2000/07/07 7:09p Dante PC Compatibility 9 2000/06/13 5:17p Shiki Fixed DEMOPrintf(). 8 2000/06/06 8:58p Carl Fixed text alignment problem. 7 2000/05/20 4:57a Hirose fixed TevOrder and NumChans for drawing captions 6 2000/05/17 9:08p Hirose deleted tab codes 5 2000/05/17 8:53p Hirose Fixed pixel processing mode setting defined in DEMOInitCaption 4 2000/03/06 11:54a Alligator Changed GXSetDefaultMtx to GXSetCurrentMtx 3 2000/01/13 5:55p Alligator Integrated with ArtX GX library code 2 1999/12/10 4:48p Carl Fixed Z compare stuff. 21 1999/11/12 4:31p Yasu Add GXSetNumTexGens 20 1999/11/09 7:47p Hirose Added GXSetNumTexGens and GXSetTevOrder 19 1999/10/29 3:45p Hirose Replaced GXSetTevStages(GXTevStageID) by GXSetNumTevStages(u8) 18 1999/10/13 6:38p Yasu Rollback 1 level 16 1999/09/30 10:32p Yasu Renamed and clean up functions and enums. 15 1999/09/29 10:29p Yasu Parameter of GXSetFogRangeAdj was changed 14 1999/09/28 6:56p Yasu Changed calling parameter of DEMOInitCaption 13 1999/09/28 2:46a Yasu Add more initialize works in DEMOInitCaption 12 1999/09/27 11:03p Yasu Z scale was inversed in DEMOSetupScrnSpc 11 1999/09/24 6:47p Yasu Changed the parameter of DEMOsetuoScrnSpc(). 10 1999/09/24 6:34p Yasu Let DEMOSetupScrnSpc() out of DEMOInitCaption() 9 1999/09/21 5:24p Yasu Changed function name cmMtxScreen -> DEMOMtxScreen. 8 1999/09/14 5:12p Yasu Fixed small bug. 7 1999/09/14 4:57p Yasu Moved it into the demo library. Changed APIs to simpler. 6 1999/09/10 6:38a Yasu Added small letters. Added some type cast to avoid warning message 5 1999/09/07 9:52p Yasu Changed file name and prefix 4 1999/09/01 5:45p Ryan 3 1999/08/28 12:08a Yasu Changed enum name GX_MAT_3x4 -> GX_MTX3x4 2 1999/08/26 7:55p Yasu Changed function name. 1 1999/8/25/99 6:21p Yasu Initial version $NoKeywords: $ *---------------------------------------------------------------------------*/ #include #include #include #include #include extern u32 DemoUseMEMHeap; extern MEMAllocator DemoAllocator1; extern MEMAllocator DemoAllocator2; //============================================================================ // Font data //============================================================================ static s32 fontShift = 0; static GXTexObj fontTexObj; //============================================================================ // Functions //============================================================================ /*---------------------------------------------------------------------------* Name: DEMOSetFontType Description: Set font type Arguments: s32 attr: Font attribute id Returns: none *---------------------------------------------------------------------------*/ void DEMOSetFontType( s32 attr ) { // Font type switch ( attr ) { case DM_FT_RVS: // Reverse mode GXSetBlendMode( GX_BM_LOGIC, GX_BL_ZERO, GX_BL_ZERO, GX_LO_INVCOPY ); break; case DM_FT_XLU: // Translucent mode GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_CLEAR ); break; case DM_FT_OPQ: default: // Normal mode GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR ); break; } return; } /*---------------------------------------------------------------------------* Name: DEMOLoadFont Description: Prepare font texture Arguments: DMTexFlt texFlt: DMTF_BILERP/DMTF_POINTSAMPLE GXBool bilerp: if you need bilerp image, set this Returns: none *---------------------------------------------------------------------------*/ void DEMOLoadFont( GXTexMapID texMap, GXTexMtx texMtx, DMTexFlt texFlt ) { Mtx fontTMtx; u16 width = 64; u16 height = (u16)( (0x80-0x20)*8*8 / width ); // Set up and load texture object GXInitTexObj( &fontTexObj, // obj DEMOFontBitmap, // image_ptr width, // weight height, // height GX_TF_I4, // format GX_CLAMP, // wrap_s (don't care) GX_CLAMP, // wrap_t (don't care) GX_FALSE ); // mipmap (don't care) if ( texFlt == DMTF_POINTSAMPLE ) { GXInitTexObjLOD( &fontTexObj, GX_NEAR, // min_filt GX_NEAR, // max_filt 0.0f, // min_lod (don't care) 0.0f, // max_lod (don't care) 0.0f, // lod_bias (don't care) GX_DISABLE, // bias_clamp (don't care) GX_FALSE, // do_edge_lod (don't care) GX_ANISO_1 ); // max_aniso (don't care) fontShift = 0; } else { fontShift = 1; } GXLoadTexObj( &fontTexObj, texMap ); // Set texture matrix to fit texture coordinate to texel (1:1) // Set up texture coord-gen MTXScale( fontTMtx, 1.0f/(float)width, 1.0f/(float)height, 1.0f ); GXLoadTexMtxImm( fontTMtx, texMtx, GX_MTX2x4 ); GXSetNumTexGens( 1 ); GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, texMtx ); return; } /*---------------------------------------------------------------------------* Name: DEMOSetupScrnSpc Description: Set matrices up to screen coordinates system Arguments: Returns: none *---------------------------------------------------------------------------*/ void DEMOSetupScrnSpc( s32 width, s32 height, float depth ) { Mtx44 pMtx; Mtx mMtx; f32 top; if ( DEMOGetRenderModeObj()->field_rendering && !VIGetNextField() ) { top = -0.667F; } else { top = 0.00F; } MTXOrtho( pMtx, top, (float)height, 0.0f, (float)width, 0.0f, -depth ); GXSetProjection( pMtx, GX_ORTHOGRAPHIC ); MTXIdentity( mMtx ); GXLoadPosMtxImm( mMtx, GX_PNMTX0 ); GXSetCurrentMtx( GX_PNMTX0 ); return; } /*---------------------------------------------------------------------------* Name: DEMOInitCaption Description: Set rendering pipe to default caption drawing mode Arguments: Returns: none *---------------------------------------------------------------------------*/ void DEMOInitCaption( s32 font_type, s32 width, s32 height ) { // Set matrices DEMOSetupScrnSpc( width, height, 100.0f ); // Set pixel processing mode GXSetZMode( GX_ENABLE, GX_ALWAYS, GX_ENABLE ); // Set TEV parameters to "REPLACE COLOR" GXSetNumChans( 0 ); GXSetNumTevStages( 1 ); GXSetTevOp( GX_TEVSTAGE0, GX_REPLACE ); GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL ); // Load Font DEMOLoadFont( GX_TEXMAP0, GX_TEXMTX0, DMTF_POINTSAMPLE ); // Set font attr to normal DEMOSetFontType( font_type ); return; } /*---------------------------------------------------------------------------* Name: DEMOPuts Description: output strings until detects NULL code Arguments: s16 x, y, z: coordinate at the origin char *string: output strings Returns: none *---------------------------------------------------------------------------*/ void DEMOPuts( s16 x, s16 y, s16 z, char* string ) { char* str = string; s32 s, t; s32 c, w, len, i; // Set up vertex descriptors GXClearVtxDesc(); GXSetVtxDesc( GX_VA_POS, GX_DIRECT ); GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT ); GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 ); GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 1 ); len = 0; while (1) { // Search visible letters c = *str ++; if ( ' ' <= c && c <= 0x7f ) { len ++; } // Check if end of line else { if ( len > 0 ) { // Put a line GXBegin( GX_QUADS, GX_VTXFMT0, (u16)(len*4) ); for ( i = 0; i < len; i ++ ) { // Draw a letter w = string[i] - ' '; s = ( w % 8 ) * 16 + fontShift; t = ( w / 8 ) * 16 + fontShift; GXPosition3s16( (s16)(i*8+x ), (s16)(y ), z ); GXTexCoord2s16( (s16)(s ), (s16)(t ) ); GXPosition3s16( (s16)(i*8+x+8), (s16)(y ), z ); GXTexCoord2s16( (s16)(s+16 ), (s16)(t ) ); GXPosition3s16( (s16)(i*8+x+8), (s16)(y+8 ), z ); GXTexCoord2s16( (s16)(s+16 ), (s16)(t+16) ); GXPosition3s16( (s16)(i*8+x ), (s16)(y+8 ), z ); GXTexCoord2s16( (s16)(s ), (s16)(t+16) ); } GXEnd( ); len = 0; } string = str; // Continue if CR/LF if ( c == '\n' ) y += 8; // Terminate if else else break; } } return; } /*---------------------------------------------------------------------------* Name: DEMOPrintf Description: output formatted strings Strings must be shorter than 256 words. Arguments: s16 x, y, z: coordinate at the origin. char *fmt: format string ...: any other parameter Returns: none *---------------------------------------------------------------------------*/ void DEMOPrintf( s16 x, s16 y, s16 z, char* fmt, ... ) { va_list vlist; char buf[256]; // Get output string va_start( vlist, fmt ); vsprintf( buf, fmt, vlist ); va_end( vlist ); // Feed to puts DEMOPuts( x, y, z, buf ); return; } //============================================================================ // // ROM Font data and functions // //============================================================================ static OSFontHeader* FontData; static void* LastSheet; static s16 FontSize; // GX_S16, 4 static s16 FontSpace; // GX_S16, 4 /*---------------------------------------------------------------------------* Name: DEMOInitROMFont Description: Allocates font buffer from the heap and initializes ROM font Arguments: None Returns: pointer to font data *---------------------------------------------------------------------------*/ OSFontHeader* DEMOInitROMFont(void) { switch (OSGetFontEncode()) { case OS_FONT_ENCODE_SJIS: if (DemoUseMEMHeap) { FontData = MEMAllocFromAllocator(&DemoAllocator1, OS_FONT_SIZE_SJIS); } else { FontData = OSAlloc(OS_FONT_SIZE_SJIS); } break; case OS_FONT_ENCODE_ANSI: if (DemoUseMEMHeap) { FontData = MEMAllocFromAllocator(&DemoAllocator1, OS_FONT_SIZE_ANSI); } else { FontData = OSAlloc(OS_FONT_SIZE_ANSI); } break; default: if (DemoUseMEMHeap) { FontData = MEMAllocFromAllocator(&DemoAllocator1, OS_FONT_SIZE_UTF); } else { FontData = OSAlloc(OS_FONT_SIZE_UTF); } break; } if (!FontData) { OSHalt("Ins. memory to load ROM font."); } if (!OSInitFont(FontData)) { OSHalt("ROM font is available in boot ROM ver 0.8 or later."); } FontSize = (s16) (FontData->cellWidth * 16); FontSpace = -16; return FontData; } /*---------------------------------------------------------------------------* Name: DEMOSetROMFontSize Description: Specifies the font size Arguments: size: font size space: character space Returns: None *---------------------------------------------------------------------------*/ void DEMOSetROMFontSize(s16 size, s16 space) { FontSize = (s16) (size * 16); FontSpace = (s16) (space * 16); } /*---------------------------------------------------------------------------* Name: DEMOGetROMFontSize Description: Gets the current font size Arguments: size font size space character space Returns: None *---------------------------------------------------------------------------*/ void DEMOGetROMFontSize(s16* size, s16* space) { if (size) { *size = (s16) (FontSize / 16); } if (space) { *space = (s16) (FontSpace / 16); } } static void DrawFontChar(int x, int y, int z, int xChar, int yChar) { s16 posLeft = (s16) x; s16 posRight = (s16) (posLeft + FontSize); s16 posTop = (s16) (y - (FontData->ascent * FontSize / FontData->cellWidth)); s16 posBottom = (s16) (y + (FontData->descent * FontSize / FontData->cellWidth)); s16 texLeft = (s16) xChar; s16 texRight = (s16) (xChar + FontData->cellWidth); s16 texTop = (s16) yChar; s16 texBottom = (s16) (yChar + FontData->cellHeight); GXBegin(GX_QUADS, GX_VTXFMT0, 4); GXPosition3s16(posLeft , posTop , (s16) z); GXTexCoord2s16(texLeft , texTop ); GXPosition3s16(posRight, posTop , (s16) z); GXTexCoord2s16(texRight, texTop ); GXPosition3s16(posRight, posBottom, (s16) z); GXTexCoord2s16(texRight, texBottom ); GXPosition3s16(posLeft , posBottom, (s16) z); GXTexCoord2s16(texLeft , texBottom ); GXEnd(); } static void LoadSheet(void* image, GXTexMapID texMapID) { Mtx mtx; GXTexObj texObj; if (LastSheet == image) { return; } LastSheet = image; // Set up and load texture object GXInitTexObj(&texObj, // obj image, // image_ptr FontData->sheetWidth, // weight FontData->sheetHeight, // height (GXTexFmt) FontData->sheetFormat, // format GX_CLAMP, // wrap_s (don't care) GX_CLAMP, // wrap_t (don't care) GX_FALSE); // mipmap (don't care) GXInitTexObjLOD(&texObj, GX_LINEAR, // min_filt GX_LINEAR, // max_filt 0.0f, // min_lod (don't care) 0.0f, // max_lod (don't care) 0.0f, // lod_bias (don't care) GX_DISABLE, // bias_clamp (don't care) GX_FALSE, // do_edge_lod (don't care) GX_ANISO_1); // max_aniso (don't care) GXLoadTexObj(&texObj, texMapID); MTXScale(mtx, 1.0f / FontData->sheetWidth, 1.0f / FontData->sheetHeight, 1.0f); GXLoadTexMtxImm(mtx, GX_TEXMTX0, GX_MTX2x4); GXSetNumTexGens(1); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0); } /*---------------------------------------------------------------------------* Name: DEMORFPuts Description: Draw the specified string with ROM font Arguments: x: base line horizontal position y: base line vertical position string: output strings Returns: total string width in texels *---------------------------------------------------------------------------*/ int DEMORFPuts(s16 x, s16 y, s16 z, char* string) { s32 cx; void* image; s32 xChar; s32 yChar; s32 width; ASSERT(FontData); LastSheet = 0; // Set up vertex descriptors GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 4); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0); // Convert to GX_S16, 4 format x *= 16; y *= 16; z *= 16; width = 0; while (*string) { if (*string == '\n') { width = 0; y += FontData->leading * FontSize / FontData->cellWidth; ++string; continue; } if (*string == '\t') { width += 8 * (FontSize + FontSpace); width -= width % (8 * (FontSize + FontSpace)); ++string; continue; } string = OSGetFontTexture(string, &image, &xChar, &yChar, &cx); LoadSheet(image, GX_TEXMAP0); DrawFontChar(x + width, y, z, xChar, yChar); width += FontSize * cx / FontData->cellWidth + FontSpace; } return (width + 15) / 16; } int DEMORFPutsEx(s16 x, s16 y, s16 z, char* string, s16 maxWidth, int length) { s32 cx; void* image; s32 xChar; s32 yChar; s32 width; char* end; ASSERT(FontData); LastSheet = 0; // Set up vertex descriptors GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 4); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0); // Convert to GX_S16, 4 format x *= 16; y *= 16; z *= 16; maxWidth *= 16; end = string + length; width = 0; while (*string && string < end) { // Line break if (*string == '\n') { width = 0; y += FontData->leading * FontSize / FontData->cellWidth; ++string; continue; } string = OSGetFontTexture(string, &image, &xChar, &yChar, &cx); // Line break if (maxWidth < width + FontSize * cx / FontData->cellWidth + FontSpace) { width = 0; y += FontData->leading * FontSize / FontData->cellWidth; } LoadSheet(image, GX_TEXMAP0); DrawFontChar(x + width, y, z, xChar, yChar); width += FontSize * cx / FontData->cellWidth + FontSpace; } return (width + 15) / 16; } /*---------------------------------------------------------------------------* Name: DEMORFPrintf Description: output formatted strings with ROM font Strings must be shorter than 256 words. Arguments: s16 x, y, z: coordinate at the origin. char *fmt: format string ...: any other parameter Returns: total string width in texels *---------------------------------------------------------------------------*/ int DEMORFPrintf(s16 x, s16 y, s16 z, char* fmt, ...) { va_list vlist; char buf[256]; // Get output string va_start(vlist, fmt); vsprintf(buf, fmt, vlist); va_end(vlist); // Feed to puts return DEMORFPuts(x, y, z, buf); } /*---------------------------------------------------------------------------* Name: DEMODumpROMFont Description: Dumps the ROM font data to debug output Arguments: string: output strings Returns: pointer to the next character *---------------------------------------------------------------------------*/ char* DEMODumpROMFont(char* string) { u32 image[48/2*48/4]; // 48 x 48 void* temp; int i, j; s32 width; ASSERT(FontData); switch (OSGetFontEncode()) { case OS_FONT_ENCODE_SJIS: temp = (u8*) FontData + OS_FONT_SIZE_SJIS - OS_FONT_ROM_SIZE_SJIS; break; case OS_FONT_ENCODE_ANSI: temp = (u8*) FontData + OS_FONT_SIZE_ANSI - OS_FONT_ROM_SIZE_ANSI; break; default: temp = (u8*) FontData + OS_FONT_SIZE_UTF - OS_FONT_ROM_SIZE_UTF; break; } temp = (void*) OSRoundDown32B(temp); OSLoadFont(FontData, temp); // Clear image buffer by zero since OSGetFontTexel() copies out // font texels using logical OR. memset(image, 0x00, sizeof(image)); // OSGetFontTexel() only works with the compressed font data // read by OSLoadFont(). string = OSGetFontTexel(string, image, 0, 48 / 4, &width); for (i = 0; i < 48; i++) { j = 48 * (i / 8) + (i % 8); OSReport("%08x%08x%08x%08x%08x%08x\n", image[j], image[j + 32/4], image[j + 64/4], image[j + 96/4], image[j + 128/4], image[j + 160/4]); } OSReport("\nwidth %d\n", width); OSInitFont(FontData); // To re-expand compressed data return string; } /*---------------------------------------------------------------------------* Name: DEMOGetRFTextWidth Description: Computes the width of the specified string Arguments: string: point to character string Returns: total string width in texels *---------------------------------------------------------------------------*/ int DEMOGetRFTextWidth(char* string) { s32 cx; s32 width; s32 maxWidth; ASSERT(FontData); maxWidth = width = 0; while (*string) { if (*string == '\n') { if (maxWidth < width) { maxWidth = width; } width = 0; } string = OSGetFontWidth(string, &cx); width += FontSize * cx / FontData->cellWidth + FontSpace; } if (maxWidth < width) { maxWidth = width; } return (maxWidth + 15) / 16; } /*---------------------------------------------------------------------------* Name: DEMOGetRFTextHeight Description: Computes the height of the specified string Arguments: string: point to character string Returns: total string height in texels *---------------------------------------------------------------------------*/ int DEMOGetRFTextHeight(char* string) { s32 height; ASSERT(FontData); height = 1; while (*string) { if (*string == '\n') { ++height; } ++string; } height *= FontData->leading * FontSize / FontData->cellWidth; return (height + 15) / 16; } /*======== End of DEMOPuts.c ========*/