diff --git a/360/file_browser.c b/360/file_browser.c index 716a9c4c47..baae8e60ba 100644 --- a/360/file_browser.c +++ b/360/file_browser.c @@ -30,6 +30,16 @@ static const char * filebrowser_get_extension(const char * filename) return ""; } +static void filebrowser_clear_current_entries(filebrowser_t * filebrowser) +{ + for(uint32_t i = 0; i < MAX_FILE_LIMIT; i++) + { + filebrowser->cur[filebrowser->file_count].d_type = 0; + filebrowser->cur[filebrowser->file_count].d_namlen = 0; + strcpy(filebrowser->cur[filebrowser->file_count].d_name, "\0"); + } +} + void filebrowser_parse_directory(filebrowser_t * filebrowser, const char * path, const char *extensions) { int error = FALSE; @@ -60,6 +70,7 @@ void filebrowser_parse_directory(filebrowser_t * filebrowser, const char * path, do { + strcpy(filebrowser->dir[filebrowser->directory_stack_size], path); bool found_dir = false; if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { @@ -100,4 +111,22 @@ error: SSNES_ERR("Failed to open directory: \"%s\"\n", path); } FindClose(hFind); +} + +void filebrowser_new(filebrowser_t * filebrowser, const char * start_dir, const char * extensions) +{ + filebrowser_clear_current_entries(filebrowser); + filebrowser->directory_stack_size = 0; + strcpy(filebrowser->extensions, extensions); + + filebrowser_parse_directory(filebrowser, start_dir, filebrowser->extensions); +} + +void filebrowser_push_directory(filebrowser_t * filebrowser, const char * path, bool with_extension) +{ + filebrowser->directory_stack_size++; + if(with_extension) + filebrowser_parse_directory(filebrowser, path, filebrowser->extensions); + else + filebrowser_parse_directory(filebrowser, path, "empty"); } \ No newline at end of file diff --git a/360/file_browser.h b/360/file_browser.h index 70f251c5e3..6d3afcd6d2 100644 --- a/360/file_browser.h +++ b/360/file_browser.h @@ -16,18 +16,28 @@ * If not, see . */ +#include + #define FATX_MAX_FILE_LIMIT 4096 +#define MAX_FILE_LIMIT FATX_MAX_FILE_LIMIT typedef struct { unsigned d_type; + unsigned d_namlen; CHAR d_name[MAX_PATH]; } DirectoryEntry; typedef struct { unsigned file_count; // amount of files in current directory unsigned currently_selected; // currently selected browser entry - DirectoryEntry cur[FATX_MAX_FILE_LIMIT]; // current file listing + uint32_t directory_stack_size; + char dir[128][2048]; /* info on the current directory */ + DirectoryEntry cur[MAX_FILE_LIMIT]; // current file listing char extensions[512]; // allowed file extensions } filebrowser_t; -void filebrowser_parse_directory(filebrowser_t * filebrowser, const char * path, const char *extensions); \ No newline at end of file +void filebrowser_new(filebrowser_t * filebrowser, const char * start_dir, const char * extensions); +void filebrowser_parse_directory(filebrowser_t * filebrowser, const char * path, const char *extensions); +void filebrowser_push_directory(filebrowser_t * filebrowser, const char * path, bool with_extension); + +#define FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(filebrowser) (filebrowser.dir[filebrowser.directory_stack_size]) \ No newline at end of file diff --git a/360/xdk360_video_debugfonts.cpp b/360/fonts.cpp similarity index 56% rename from 360/xdk360_video_debugfonts.cpp rename to 360/fonts.cpp index e9e02e1f0d..d307894534 100644 --- a/360/xdk360_video_debugfonts.cpp +++ b/360/fonts.cpp @@ -17,11 +17,229 @@ */ #include -#include +#include #include "xdk360_video.h" -#include "xdk360_video_debugfonts.h" +#include "fonts.h" #include "../general.h" +static video_console_t video_console; +static xdk360_video_font_t m_Font; + +void xdk360_console_draw(void) +{ + xdk360_video_t *vid = (xdk360_video_t*)g_d3d; + D3DDevice *m_pd3dDevice = vid->xdk360_render_device; + + // The top line + unsigned int nTextLine = ( video_console.m_nCurLine - + video_console.m_cScreenHeight + video_console.m_cScreenHeightVirtual - + video_console.m_nScrollOffset + 1 ) + % video_console.m_cScreenHeightVirtual; + + xdk360_video_font_begin(&m_Font); + + for( unsigned int nScreenLine = 0; nScreenLine < video_console.m_cScreenHeight; nScreenLine++ ) + { + xdk360_video_font_draw_text(&m_Font, (float)( video_console.m_cxSafeAreaOffset ), + (float)( video_console.m_cySafeAreaOffset + + video_console.m_fLineHeight * nScreenLine ), + video_console.m_colTextColor, + video_console.m_Lines[nTextLine], 0.0f ); + + nTextLine = ( nTextLine + 1 ) % video_console.m_cScreenHeightVirtual; + } + + xdk360_video_font_end(&m_Font); +} + +HRESULT xdk360_console_init( LPCSTR strFontFileName, unsigned long colBackColor, + unsigned long colTextColor) +{ + xdk360_video_t *vid = (xdk360_video_t*)g_d3d; + D3DDevice *m_pd3dDevice = vid->xdk360_render_device; + + video_console.first_message = true; + video_console.m_Buffer = NULL; + video_console.m_Lines = NULL; + video_console.m_nScrollOffset = 0; + + // Calculate the safe area + unsigned int uiSafeAreaPct = vid->video_mode.fIsHiDef ? SAFE_AREA_PCT_HDTV + : SAFE_AREA_PCT_4x3; + + video_console.m_cxSafeArea = ( vid->d3dpp.BackBufferWidth * uiSafeAreaPct ) / 100; + video_console.m_cySafeArea = ( vid->d3dpp.BackBufferHeight * uiSafeAreaPct ) / 100; + + video_console.m_cxSafeAreaOffset = ( vid->d3dpp.BackBufferWidth - video_console.m_cxSafeArea ) / 2; + video_console.m_cySafeAreaOffset = ( vid->d3dpp.BackBufferHeight - video_console.m_cySafeArea ) / 2; + + // Create the font + HRESULT hr = xdk360_video_font_init(&m_Font, strFontFileName ); + if( FAILED( hr ) ) + { + SSNES_ERR( "Could not create font.\n" ); + return -1; + } + + // Save the colors + video_console.m_colBackColor = colBackColor; + video_console.m_colTextColor = colTextColor; + + // Calculate the number of lines on the screen + float fCharWidth, fCharHeight; + xdk360_video_font_get_text_width(&m_Font, L"i", &fCharWidth, &fCharHeight, FALSE); + + video_console.m_cScreenHeight = (unsigned int)( video_console.m_cySafeArea / fCharHeight ); + video_console.m_cScreenWidth = (unsigned int)( video_console.m_cxSafeArea / fCharWidth ); + + video_console.m_cScreenHeightVirtual = video_console.m_cScreenHeight; + + video_console.m_fLineHeight = fCharHeight; + + // Allocate memory to hold the lines + video_console.m_Buffer = new wchar_t[ video_console.m_cScreenHeightVirtual * ( video_console.m_cScreenWidth + 1 ) ]; + video_console.m_Lines = new wchar_t *[ video_console.m_cScreenHeightVirtual ]; + + // Set the line pointers as indexes into the buffer + for( unsigned int i = 0; i < video_console.m_cScreenHeightVirtual; i++ ) + video_console.m_Lines[ i ] = video_console.m_Buffer + ( video_console.m_cScreenWidth + 1 ) * i; + + video_console.m_nCurLine = 0; + video_console.m_cCurLineLength = 0; + memset( video_console.m_Buffer, 0, video_console.m_cScreenHeightVirtual * ( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); + xdk360_console_draw(); + + return hr; +} + +void xdk360_console_deinit() +{ + // Delete the memory we've allocated + if(video_console.m_Lines) + { + delete[] video_console.m_Lines; + video_console.m_Lines = NULL; + } + + if(video_console.m_Buffer) + { + delete[] video_console.m_Buffer; + video_console.m_Buffer = NULL; + } + + // Destroy the font + xdk360_video_font_deinit(&m_Font); +} + +void xdk360_console_add( wchar_t wch ) +{ + // If this is a newline, just increment lines and move on + if( wch == L'\n' ) + { + video_console.m_nCurLine = ( video_console.m_nCurLine + 1 ) + % video_console.m_cScreenHeightVirtual; + video_console.m_cCurLineLength = 0; + memset(video_console.m_Lines[video_console.m_nCurLine], 0, + ( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); + return; + } + + int bIncrementLine = FALSE; // Whether to wrap to the next line + + if( video_console.m_cCurLineLength == video_console.m_cScreenWidth ) + bIncrementLine = TRUE; + else + { + // Try to append the character to the line + video_console.m_Lines[ video_console.m_nCurLine ] + [ video_console.m_cCurLineLength ] = wch; + + float fTextWidth, fTextHeight; + xdk360_video_font_get_text_width(&m_Font, video_console.m_Lines[ video_console.m_nCurLine ], &fTextWidth, &fTextHeight, 0); + if( fTextHeight > video_console.m_cxSafeArea ) + { + // The line is too long, we need to wrap the character to the next line + video_console.m_Lines[video_console.m_nCurLine] + [ video_console.m_cCurLineLength ] = L'\0'; + bIncrementLine = TRUE; + } + } + + // If we need to skip to the next line, do so + if( bIncrementLine ) + { + video_console.m_nCurLine = ( video_console.m_nCurLine + 1 ) + % video_console.m_cScreenHeightVirtual; + video_console.m_cCurLineLength = 0; + memset( video_console.m_Lines[video_console.m_nCurLine], + 0, ( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); + video_console.m_Lines[video_console.m_nCurLine ][0] = wch; + } + + video_console.m_cCurLineLength++; +} + +void xdk360_console_format(_In_z_ _Printf_format_string_ LPCSTR strFormat, ... ) +{ + video_console.m_nCurLine = 0; + video_console.m_cCurLineLength = 0; + memset( video_console.m_Buffer, 0, + video_console.m_cScreenHeightVirtual * + ( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); + + va_list pArgList; + va_start( pArgList, strFormat ); + + // Count the required length of the string + unsigned long dwStrLen = _vscprintf( strFormat, pArgList ) + 1; + // +1 = null terminator + char * strMessage = ( char * )_malloca( dwStrLen ); + vsprintf_s( strMessage, dwStrLen, strFormat, pArgList ); + + // Output the string to the console + unsigned long uStringLength = strlen( strMessage ); + for( unsigned long i = 0; i < uStringLength; i++ ) + { + wchar_t wch; + int ret = MultiByteToWideChar( CP_ACP, // ANSI code page + 0, // No flags + &strMessage[i], // Character to convert + 1, // Convert one byte + &wch, // Target wide character buffer + 1 ); // One wide character + xdk360_console_add( wch ); + } + + _freea( strMessage ); + + va_end( pArgList ); +} + +void xdk360_console_format_w(_In_z_ _Printf_format_string_ LPCWSTR wstrFormat, ... ) +{ + video_console.m_nCurLine = 0; + video_console.m_cCurLineLength = 0; + memset( video_console.m_Buffer, 0, video_console.m_cScreenHeightVirtual + * ( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); + + va_list pArgList; + va_start( pArgList, wstrFormat ); + + // Count the required length of the string + unsigned long dwStrLen = _vscwprintf( wstrFormat, pArgList ) + 1; // +1 = null terminator + wchar_t * strMessage = ( wchar_t * )_malloca( dwStrLen * sizeof( wchar_t ) ); + vswprintf_s( strMessage, dwStrLen, wstrFormat, pArgList ); + + // Output the string to the console + unsigned long uStringLength = wcslen( strMessage ); + for( unsigned long i = 0; i < uStringLength; i++ ) + xdk360_console_add( strMessage[i] ); + + _freea( strMessage ); + + va_end( pArgList ); +} + #define CALCFONTFILEHEADERSIZE(x) ( sizeof(unsigned long) + (sizeof(float)* 4) + sizeof(unsigned short) + (sizeof(wchar_t)*(x)) ) #define FONTFILEVERSION 5 @@ -44,11 +262,8 @@ typedef struct FontFileStrikesImage_t { GLYPH_ATTR m_Glyphs[1]; // Array of font strike uv's etc... NOTE: It's m_dwNumGlyphs in size } FontFileStrikesImage_t; -//-------------------------------------------------------------------------------------- -// Vertex and pixel shaders for font rendering -// Please note the removal of comment or dead lines... -// They are commented out because the shader compiler has no use for them. -//-------------------------------------------------------------------------------------- +static PackedResource m_xprResource; + static const char g_strFontShader[] = "struct VS_IN\n" "{\n" @@ -56,7 +271,6 @@ static const char g_strFontShader[] = "float2 Tex : TEXCOORD0;\n" "float4 ChannelSelector : TEXCOORD1;\n" "};\n" -// "\n" "struct VS_OUT\n" "{\n" "float4 Position : POSITION;\n" @@ -64,12 +278,9 @@ static const char g_strFontShader[] = "float2 TexCoord0 : TEXCOORD0;\n" "float4 ChannelSelector : TEXCOORD1;\n" "};\n" -// "\n" "uniform float4 Color : register(c1);\n" "uniform float2 TexScale : register(c2);\n" -// "\n" "sampler FontTexture : register(s0);\n" -// "\n" "VS_OUT FontVertexShader( VS_IN In )\n" "{\n" "VS_OUT Out;\n" @@ -83,36 +294,15 @@ static const char g_strFontShader[] = "Out.ChannelSelector = In.ChannelSelector;\n" "return Out;\n" "}\n" - // "\n" "float4 FontPixelShader( VS_OUT In ) : COLOR0\n" "{\n" -// "// Fetch a texel from the font texture\n" "float4 FontTexel = tex2D( FontTexture, In.TexCoord0 );\n" -// "\n" "if( dot( In.ChannelSelector, float4(1,1,1,1) ) )\n" "{\n" -// "// Select the color from the channel\n" "float value = dot( FontTexel, In.ChannelSelector );\n" -// "\n" -// "// For white pixels, the high bit is 1 and the low\n" -// "// bits are luminance, so r0.a will be > 0.5. For the\n" -// "// RGB channel, we want to lop off the msb and shift\n" -// "// the lower bits up one bit. This is simple to do\n" -// "// with the _bx2 modifier. Since these pixels are\n" -// "// opaque, we emit a 1 for the alpha channel (which\n" -// "// is 0.5 x2 ).\n" -// "\n" -// "// For black pixels, the high bit is 0 and the low\n" -// "// bits are alpha, so r0.a will be < 0.5. For the RGB\n" -// "// channel, we emit zero. For the alpha channel, we\n" -// "// just use the x2 modifier to scale up the low bits\n" -// "// of the alpha.\n" "float4 Color;\n" "Color.rgb = ( value > 0.5f ? 2*value-1 : 0.0f );\n" "Color.a = 2 * ( value > 0.5f ? 1.0f : value );\n" -// "\n" -// "// Return the texture color modulated with the vertex\n" -// "// color\n" "return Color * In.Diffuse;\n" "}\n" "else\n" @@ -130,12 +320,7 @@ typedef struct AtgFont_Locals_t { // All elements are defaulted to NULL static AtgFont_Locals_t s_AtgFontLocals; // Global static instance -//-------------------------------------------------------------------------------------- -// Name: CreateFontShaders() -// Desc: Creates the global font shaders -//-------------------------------------------------------------------------------------- - -HRESULT XdkFont::CreateFontShaders() +static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font) { // // There are only two states the globals could be in, @@ -232,53 +417,26 @@ HRESULT XdkFont::CreateFontShaders() return hr; // Return the error code if any } -//-------------------------------------------------------------------------------------- -// Name: Font() -// Desc: Constructor -//-------------------------------------------------------------------------------------- -XdkFont::XdkFont() +void xdk360_video_font_set_size(xdk360_video_font_t * font, float x, float y) { - m_pFontTexture = NULL; - - m_dwNumGlyphs = 0L; - m_Glyphs = NULL; - - m_fCursorX = 0.0f; - m_fCursorY = 0.0f; - - m_fXScaleFactor = 2.0f; - m_fYScaleFactor = 2.0f; - - m_cMaxGlyph = 0; - m_TranslatorTable = NULL; - - m_dwNestedBeginCount = 0L; + font->m_fXScaleFactor = x; + font->m_fYScaleFactor = y; } - -//-------------------------------------------------------------------------------------- -// Name: ~Font() -// Desc: Destructor -//-------------------------------------------------------------------------------------- -XdkFont::~XdkFont() +HRESULT xdk360_video_font_init(xdk360_video_font_t * font, const char * strFontFileName) { - Destroy(); -} - -void XdkFont::SetFontSize(float x, float y) -{ - m_fXScaleFactor = x; - m_fYScaleFactor = y; -} - -//-------------------------------------------------------------------------------------- -// Name: Create() -// Desc: Create the font's internal objects (texture and array of glyph info) -// using the XPR packed resource file -//-------------------------------------------------------------------------------------- -HRESULT XdkFont::Create( const char * strFontFileName ) -{ - // Create the font + font->m_pFontTexture = NULL; + font->m_dwNumGlyphs = 0L; + font->m_Glyphs = NULL; + font->m_fCursorX = 0.0f; + font->m_fCursorY = 0.0f; + font->m_fXScaleFactor = 2.0f; + font->m_fYScaleFactor = 2.0f; + font->m_cMaxGlyph = 0; + font->m_TranslatorTable = NULL; + font->m_dwNestedBeginCount = 0L; + + // Create the font if( FAILED( m_xprResource.Create( strFontFileName ) ) ) return E_FAIL; @@ -286,7 +444,7 @@ HRESULT XdkFont::Create( const char * strFontFileName ) const void * pFontData = m_xprResource.GetData( "FontData"); // Save a copy of the texture - m_pFontTexture = pFontTexture; + font->m_pFontTexture = pFontTexture; // Check version of file (to make sure it matches up with the FontMaker tool) const unsigned char * pData = static_cast(pFontData); @@ -294,21 +452,21 @@ HRESULT XdkFont::Create( const char * strFontFileName ) if( dwFileVersion == FONTFILEVERSION ) { - m_fFontHeight = reinterpret_cast(pData)->m_fFontHeight; - m_fFontTopPadding = reinterpret_cast(pData)->m_fFontTopPadding; - m_fFontBottomPadding = reinterpret_cast(pData)->m_fFontBottomPadding; - m_fFontYAdvance = reinterpret_cast(pData)->m_fFontYAdvance; + font->m_fFontHeight = reinterpret_cast(pData)->m_fFontHeight; + font->m_fFontTopPadding = reinterpret_cast(pData)->m_fFontTopPadding; + font->m_fFontBottomPadding = reinterpret_cast(pData)->m_fFontBottomPadding; + font->m_fFontYAdvance = reinterpret_cast(pData)->m_fFontYAdvance; // Point to the translator string which immediately follows the 4 floats - m_cMaxGlyph = reinterpret_cast(pData)->m_cMaxGlyph; + font->m_cMaxGlyph = reinterpret_cast(pData)->m_cMaxGlyph; - m_TranslatorTable = const_cast(reinterpret_cast(pData))->m_TranslatorTable; + font->m_TranslatorTable = const_cast(reinterpret_cast(pData))->m_TranslatorTable; - pData += CALCFONTFILEHEADERSIZE( m_cMaxGlyph + 1 ); + pData += CALCFONTFILEHEADERSIZE( font->m_cMaxGlyph + 1 ); // Read the glyph attributes from the file - m_dwNumGlyphs = reinterpret_cast(pData)->m_dwNumGlyphs; - m_Glyphs = reinterpret_cast(pData)->m_Glyphs; // Pointer + font->m_dwNumGlyphs = reinterpret_cast(pData)->m_dwNumGlyphs; + font->m_Glyphs = reinterpret_cast(pData)->m_Glyphs; // Pointer } else { @@ -317,7 +475,7 @@ HRESULT XdkFont::Create( const char * strFontFileName ) } // Create the vertex and pixel shaders for rendering the font - if( FAILED( CreateFontShaders() ) ) + if( FAILED( xdk360_video_font_create_shaders(font) ) ) { SSNES_ERR( "Could not create font shaders.\n" ); return E_FAIL; @@ -329,29 +487,25 @@ HRESULT XdkFont::Create( const char * strFontFileName ) // Initialize the window D3DDISPLAYMODE DisplayMode; pd3dDevice->GetDisplayMode( 0, &DisplayMode ); - m_rcWindow.x1 = 0; - m_rcWindow.y1 = 0; - m_rcWindow.x2 = DisplayMode.Width; - m_rcWindow.y2 = DisplayMode.Height; + font->m_rcWindow.x1 = 0; + font->m_rcWindow.y1 = 0; + font->m_rcWindow.x2 = DisplayMode.Width; + font->m_rcWindow.y2 = DisplayMode.Height; // Determine whether we should save/restore state - m_bSaveState = TRUE; + font->m_bSaveState = TRUE; return S_OK; } -//-------------------------------------------------------------------------------------- -// Name: Destroy() -// Desc: Destroy the font object -//-------------------------------------------------------------------------------------- -void XdkFont::Destroy() +void xdk360_video_font_deinit(xdk360_video_font_t * font) { - m_pFontTexture = NULL; - m_dwNumGlyphs = 0L; - m_Glyphs = NULL; - m_cMaxGlyph = 0; - m_TranslatorTable = NULL; - m_dwNestedBeginCount = 0L; + font->m_pFontTexture = NULL; + font->m_dwNumGlyphs = 0L; + font->m_Glyphs = NULL; + font->m_cMaxGlyph = 0; + font->m_TranslatorTable = NULL; + font->m_dwNestedBeginCount = 0L; // Safely release shaders // NOTE: They are released in reverse order of creation @@ -368,25 +522,15 @@ void XdkFont::Destroy() m_xprResource.Destroy(); } -//-------------------------------------------------------------------------------------- -// Name: SetCursorPosition() -// Desc: Sets the cursor position for drawing text -//-------------------------------------------------------------------------------------- -void XdkFont::SetCursorPosition( float fCursorX, float fCursorY ) +void xdk360_video_font_set_cursor_position(xdk360_video_font_t *font, float fCursorX, float fCursorY ) { - m_fCursorX = floorf( fCursorX ); - m_fCursorY = floorf( fCursorY ); + font->m_fCursorX = floorf( fCursorX ); + font->m_fCursorY = floorf( fCursorY ); } -//-------------------------------------------------------------------------------------- -// Name: GetTextExtent() -// Desc: Get the dimensions of a text string -//-------------------------------------------------------------------------------------- - -void XdkFont::GetTextExtent( const wchar_t * strText, float * pWidth, - float * pHeight, int bFirstLineOnly ) const +void xdk360_video_font_get_text_width(xdk360_video_font_t * font, const wchar_t * strText, float * pWidth, float * pHeight, int bFirstLineOnly) { - // Set default text extent in output parameters + // Set default text extent in output parameters int iWidth = 0; float fHeight = 0.0f; @@ -394,7 +538,7 @@ void XdkFont::GetTextExtent( const wchar_t * strText, float * pWidth, { // Initialize counters that keep track of text extent int ix = 0; - float fy = m_fFontHeight; // One character high to start + float fy = font->m_fFontHeight; // One character high to start if( fy > fHeight ) fHeight = fy; @@ -410,7 +554,7 @@ void XdkFont::GetTextExtent( const wchar_t * strText, float * pWidth, if( bFirstLineOnly ) break; ix = 0; - fy += m_fFontYAdvance; + fy += font->m_fFontYAdvance; // since the height has changed, test against the height extent if( fy > fHeight ) fHeight = fy; @@ -424,12 +568,12 @@ void XdkFont::GetTextExtent( const wchar_t * strText, float * pWidth, // Translate unprintable characters const GLYPH_ATTR* pGlyph; - if( letter > m_cMaxGlyph ) + if( letter > font->m_cMaxGlyph ) letter = 0; // Out of bounds? else - letter = m_TranslatorTable[letter]; // Remap ASCII to glyph + letter = font->m_TranslatorTable[letter]; // Remap ASCII to glyph - pGlyph = &m_Glyphs[letter]; // Get the requested glyph + pGlyph = &font->m_Glyphs[letter]; // Get the requested glyph // Get text extent for this character's glyph ix += pGlyph->wOffset; @@ -445,72 +589,54 @@ void XdkFont::GetTextExtent( const wchar_t * strText, float * pWidth, // Convert the width to a float here, load/hit/store. :( float fWidth = static_cast(iWidth); // Delay the use if fWidth to reduce LHS pain // Apply the scale factor to the result - fHeight *= m_fYScaleFactor; + fHeight *= font->m_fYScaleFactor; // Store the final results *pHeight = fHeight; - fWidth *= m_fXScaleFactor; + fWidth *= font->m_fXScaleFactor; *pWidth = fWidth; } -//-------------------------------------------------------------------------------------- -// Name: GetTextWidth() -// Desc: Returns the width in pixels of a text string -//-------------------------------------------------------------------------------------- -float XdkFont::GetTextWidth( const wchar_t * strText ) const +void xdk360_video_font_begin (xdk360_video_font_t * font) { - float fTextWidth, fTextHeight; - GetTextExtent( strText, &fTextWidth, &fTextHeight ); - return fTextWidth; -} - - -//-------------------------------------------------------------------------------------- -// Name: Begin() -// Desc: Prepares the font vertex buffers for rendering. -//-------------------------------------------------------------------------------------- -VOID XdkFont::Begin() -{ - PIXBeginNamedEvent( 0, "Text Rendering" ); - // Set state on the first call - if( m_dwNestedBeginCount == 0 ) + if( font->m_dwNestedBeginCount == 0 ) { // Cache the global pointer into a register xdk360_video_t *vid = (xdk360_video_t*)g_d3d; D3DDevice *pD3dDevice = vid->xdk360_render_device; // Save state - if( m_bSaveState ) + if( font->m_bSaveState ) { // Note, we are not saving the texture, vertex, or pixel shader, // since it's not worth the performance. We're more interested // in saving state that would cause hard to find problems. pD3dDevice->GetRenderState( D3DRS_ALPHABLENDENABLE, - &m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHABLENDENABLE ] ); - pD3dDevice->GetRenderState( D3DRS_SRCBLEND, &m_dwSavedState[ SAVEDSTATE_D3DRS_SRCBLEND ] ); - pD3dDevice->GetRenderState( D3DRS_DESTBLEND, &m_dwSavedState[ SAVEDSTATE_D3DRS_DESTBLEND ] ); - pD3dDevice->GetRenderState( D3DRS_BLENDOP, &m_dwSavedState[ SAVEDSTATE_D3DRS_BLENDOP ] ); - pD3dDevice->GetRenderState( D3DRS_ALPHATESTENABLE, &m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHATESTENABLE ] ); - pD3dDevice->GetRenderState( D3DRS_ALPHAREF, &m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAREF ] ); - pD3dDevice->GetRenderState( D3DRS_ALPHAFUNC, &m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAFUNC ] ); - pD3dDevice->GetRenderState( D3DRS_FILLMODE, &m_dwSavedState[ SAVEDSTATE_D3DRS_FILLMODE ] ); - pD3dDevice->GetRenderState( D3DRS_CULLMODE, &m_dwSavedState[ SAVEDSTATE_D3DRS_CULLMODE ] ); - pD3dDevice->GetRenderState( D3DRS_ZENABLE, &m_dwSavedState[ SAVEDSTATE_D3DRS_ZENABLE ] ); - pD3dDevice->GetRenderState( D3DRS_STENCILENABLE, &m_dwSavedState[ SAVEDSTATE_D3DRS_STENCILENABLE ] ); - pD3dDevice->GetRenderState( D3DRS_VIEWPORTENABLE, &m_dwSavedState[ SAVEDSTATE_D3DRS_VIEWPORTENABLE ] ); - pD3dDevice->GetSamplerState( 0, D3DSAMP_MINFILTER, &m_dwSavedState[ SAVEDSTATE_D3DSAMP_MINFILTER ] ); - pD3dDevice->GetSamplerState( 0, D3DSAMP_MAGFILTER, &m_dwSavedState[ SAVEDSTATE_D3DSAMP_MAGFILTER ] ); - pD3dDevice->GetSamplerState( 0, D3DSAMP_ADDRESSU, &m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSU ] ); - pD3dDevice->GetSamplerState( 0, D3DSAMP_ADDRESSV, &m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSV ] ); + &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHABLENDENABLE ] ); + pD3dDevice->GetRenderState( D3DRS_SRCBLEND, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_SRCBLEND ] ); + pD3dDevice->GetRenderState( D3DRS_DESTBLEND, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_DESTBLEND ] ); + pD3dDevice->GetRenderState( D3DRS_BLENDOP, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_BLENDOP ] ); + pD3dDevice->GetRenderState( D3DRS_ALPHATESTENABLE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHATESTENABLE ] ); + pD3dDevice->GetRenderState( D3DRS_ALPHAREF, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAREF ] ); + pD3dDevice->GetRenderState( D3DRS_ALPHAFUNC, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAFUNC ] ); + pD3dDevice->GetRenderState( D3DRS_FILLMODE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_FILLMODE ] ); + pD3dDevice->GetRenderState( D3DRS_CULLMODE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_CULLMODE ] ); + pD3dDevice->GetRenderState( D3DRS_ZENABLE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ZENABLE ] ); + pD3dDevice->GetRenderState( D3DRS_STENCILENABLE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_STENCILENABLE ] ); + pD3dDevice->GetRenderState( D3DRS_VIEWPORTENABLE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_VIEWPORTENABLE ] ); + pD3dDevice->GetSamplerState( 0, D3DSAMP_MINFILTER, &font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_MINFILTER ] ); + pD3dDevice->GetSamplerState( 0, D3DSAMP_MAGFILTER, &font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_MAGFILTER ] ); + pD3dDevice->GetSamplerState( 0, D3DSAMP_ADDRESSU, &font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSU ] ); + pD3dDevice->GetSamplerState( 0, D3DSAMP_ADDRESSV, &font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSV ] ); } // Set the texture scaling factor as a vertex shader constant D3DSURFACE_DESC TextureDesc; - m_pFontTexture->GetLevelDesc( 0, &TextureDesc ); // Get the description + font->m_pFontTexture->GetLevelDesc( 0, &TextureDesc ); // Get the description // Set render state - pD3dDevice->SetTexture( 0, m_pFontTexture ); + pD3dDevice->SetTexture( 0, font->m_pFontTexture ); // Read the TextureDesc here to ensure no load/hit/store from GetLevelDesc() float vTexScale[4]; @@ -546,42 +672,52 @@ VOID XdkFont::Begin() } // Keep track of the nested begin/end calls. - m_dwNestedBeginCount++; + font->m_dwNestedBeginCount++; } - -//-------------------------------------------------------------------------------------- -// Name: DrawText() -// Desc: Draws text as textured polygons -//-------------------------------------------------------------------------------------- -VOID XdkFont::DrawText( unsigned long dwColor, const wchar_t * strText, - unsigned long dwFlags, float fMaxPixelWidth ) +void xdk360_video_font_end(xdk360_video_font_t * font) { - DrawText( m_fCursorX, m_fCursorY, dwColor, strText, dwFlags, fMaxPixelWidth ); + if( --font->m_dwNestedBeginCount > 0 ) + return; + + // Restore state + if( font->m_bSaveState ) + { + // Cache the global pointer into a register + xdk360_video_t *vid = (xdk360_video_t*)g_d3d; + D3DDevice *pD3dDevice = vid->xdk360_render_device; + + pD3dDevice->SetTexture( 0, NULL ); + pD3dDevice->SetVertexDeclaration( NULL ); + pD3dDevice->SetVertexShader( NULL ); + pD3dDevice->SetPixelShader( NULL ); + pD3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHABLENDENABLE ] ); + pD3dDevice->SetRenderState( D3DRS_SRCBLEND, font->m_dwSavedState[ SAVEDSTATE_D3DRS_SRCBLEND ] ); + pD3dDevice->SetRenderState( D3DRS_DESTBLEND, font->m_dwSavedState[ SAVEDSTATE_D3DRS_DESTBLEND ] ); + pD3dDevice->SetRenderState( D3DRS_BLENDOP, font->m_dwSavedState[ SAVEDSTATE_D3DRS_BLENDOP ] ); + pD3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHATESTENABLE ] ); + pD3dDevice->SetRenderState( D3DRS_ALPHAREF, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAREF ] ); + pD3dDevice->SetRenderState( D3DRS_ALPHAFUNC, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAFUNC ] ); + pD3dDevice->SetRenderState( D3DRS_FILLMODE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_FILLMODE ] ); + pD3dDevice->SetRenderState( D3DRS_CULLMODE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_CULLMODE ] ); + pD3dDevice->SetRenderState( D3DRS_ZENABLE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ZENABLE ] ); + pD3dDevice->SetRenderState( D3DRS_STENCILENABLE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_STENCILENABLE ] ); + pD3dDevice->SetRenderState( D3DRS_VIEWPORTENABLE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_VIEWPORTENABLE ] ); + pD3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_MINFILTER ] ); + pD3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_MAGFILTER ] ); + pD3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSU ] ); + pD3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSV ] ); + } } - -//-------------------------------------------------------------------------------------- -// Name: DrawText() -// Desc: Draws text as textured polygons -// TODO: This function should use the Begin/SetVertexData/End() API when it -// becomes available. -//-------------------------------------------------------------------------------------- -VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, - const wchar_t * strText, unsigned long dwFlags, float fMaxPixelWidth ) +void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, float fOriginY, unsigned long dwColor, + const wchar_t * strText, float fMaxPixelWidth ) { - if( strText == NULL ) - return; - if( L'\0' == strText[0] ) + if( strText == NULL || strText[0] == L'\0') return; xdk360_video_t *vid = (xdk360_video_t*)g_d3d; D3DDevice *pd3dDevice = vid->xdk360_render_device; - - // Create a PIX user-defined event that encapsulates all of the text draw calls. - // This makes DrawText calls easier to recognize in PIX captures, and it makes - // them take up fewer entries in the event list. - PIXBeginNamedEvent( dwColor, "DrawText: %S", strText ); // Set the color as a vertex shader constant float vColor[4]; @@ -591,7 +727,7 @@ VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, vColor[3] = ( ( dwColor & 0xff000000 ) >> 24L ) / 255.0F; // Set up stuff to prepare for drawing text - Begin(); + xdk360_video_font_begin(font); // Perform the actual storing of the color constant here to prevent // a load-hit-store by inserting work between the store and the use of @@ -599,56 +735,24 @@ VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, pd3dDevice->SetVertexShaderConstantF( 1, vColor, 1 ); // Set the starting screen position - if( ( fOriginX < 0.0f ) || ( ( dwFlags & FONT_RIGHT ) && ( fOriginX <= 0.0f ) ) ) - fOriginX += ( m_rcWindow.x2 - m_rcWindow.x1 ); + if((fOriginX < 0.0f)) + fOriginX += font->m_rcWindow.x2; if( fOriginY < 0.0f ) - fOriginY += ( m_rcWindow.y2 - m_rcWindow.y1 ); + fOriginY += font->m_rcWindow.y2; - m_fCursorX = floorf( fOriginX ); - m_fCursorY = floorf( fOriginY ); + font->m_fCursorX = floorf( fOriginX ); + font->m_fCursorY = floorf( fOriginY ); // Adjust for padding - fOriginY -= m_fFontTopPadding; - - float fEllipsesPixelWidth = m_fXScaleFactor * 3.0f * ( m_Glyphs[m_TranslatorTable[L'.']].wOffset + - m_Glyphs[m_TranslatorTable[L'.']].wAdvance ); - - if( dwFlags & FONT_TRUNCATED ) - { - // Check if we will really need to truncate the string - if( fMaxPixelWidth <= 0.0f ) - dwFlags &= ( ~FONT_TRUNCATED ); - else - { - float w, h; - GetTextExtent( strText, &w, &h, TRUE ); - - // If not, then clear the flag - if( w <= fMaxPixelWidth ) - dwFlags &= ( ~FONT_TRUNCATED ); - } - } - - // If vertically centered, offset the starting m_fCursorY value - if( dwFlags & FONT_CENTER_Y ) - { - float w, h; - GetTextExtent( strText, &w, &h ); - m_fCursorY = floorf( m_fCursorY - (h * 0.5f) ); - } + fOriginY -= font->m_fFontTopPadding; // Add window offsets - float Winx = static_cast(m_rcWindow.x1); - float Winy = static_cast(m_rcWindow.y1); + float Winx = 0.0f; + float Winy = 0.0f; fOriginX += Winx; fOriginY += Winy; - m_fCursorX += Winx; - m_fCursorY += Winy; - - // Set a flag so we can determine initial justification effects - BOOL bStartingNewLine = TRUE; - - unsigned long dwNumEllipsesToDraw = 0; + font->m_fCursorX += Winx; + font->m_fCursorY += Winy; // Begin drawing the vertices @@ -658,7 +762,7 @@ VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, volatile float * pVertex; - unsigned long dwNumChars = wcslen( strText ) + ( dwFlags & FONT_TRUNCATED ? 3 : 0 ); + unsigned long dwNumChars = wcslen(strText); HRESULT hr = pd3dDevice->BeginVertices( D3DPT_QUADLIST, 4 * dwNumChars, sizeof( XMFLOAT4 ) , ( VOID** )&pVertex ); // The ring buffer may run out of space when tiling, doing z-prepasses, @@ -666,87 +770,42 @@ VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, if( FAILED( hr ) ) SSNES_ERR( "Ring buffer out of memory.\n" ); - bStartingNewLine = TRUE; - // Draw four vertices for each glyph while( *strText ) { wchar_t letter; - if( dwNumEllipsesToDraw ) - letter = L'.'; - else + // Get the current letter in the string + letter = *strText++; + + // Handle the newline character + if( letter == L'\n' ) { - // If starting text on a new line, determine justification effects - if( bStartingNewLine ) - { - if( dwFlags & ( FONT_RIGHT | FONT_CENTER_X ) ) - { - // Get the extent of this line - float w, h; - GetTextExtent( strText, &w, &h, TRUE ); - - // Offset this line's starting m_fCursorX value - if( dwFlags & FONT_RIGHT ) - m_fCursorX = floorf( fOriginX - w ); - if( dwFlags & FONT_CENTER_X ) - m_fCursorX = floorf( fOriginX - w * 0.5f ); - } - bStartingNewLine = FALSE; - } - - // Get the current letter in the string - letter = *strText++; - - // Handle the newline character - if( letter == L'\n' ) - { - m_fCursorX = fOriginX; - m_fCursorY += m_fFontYAdvance * m_fYScaleFactor; - bStartingNewLine = TRUE; - continue; - } - - // Handle carriage return characters by ignoring them. This helps when - // displaying text from a file. - if( letter == L'\r' ) - continue; + font->m_fCursorX = fOriginX; + font->m_fCursorY += font->m_fFontYAdvance * font->m_fYScaleFactor; + continue; } // Translate unprintable characters - const GLYPH_ATTR * pGlyph = &m_Glyphs[ ( letter <= m_cMaxGlyph ) ? m_TranslatorTable[letter] : 0 ]; + const GLYPH_ATTR * pGlyph = &font->m_Glyphs[ ( letter <= font->m_cMaxGlyph ) ? font->m_TranslatorTable[letter] : 0 ]; - float fOffset = m_fXScaleFactor * (float)pGlyph->wOffset; - float fAdvance = m_fXScaleFactor * (float)pGlyph->wAdvance; - float fWidth = m_fXScaleFactor * (float)pGlyph->wWidth; - float fHeight = m_fYScaleFactor * m_fFontHeight; - - if( 0 == dwNumEllipsesToDraw ) - { - if( dwFlags & FONT_TRUNCATED ) - { - // Check if we will be exceeded the max allowed width - if( m_fCursorX + fOffset + fWidth + fEllipsesPixelWidth > fOriginX + fMaxPixelWidth ) - { - // Yup, draw the three ellipses dots instead - dwNumEllipsesToDraw = 3; - continue; - } - } - } + float fOffset = font->m_fXScaleFactor * (float)pGlyph->wOffset; + float fAdvance = font->m_fXScaleFactor * (float)pGlyph->wAdvance; + float fWidth = font->m_fXScaleFactor * (float)pGlyph->wWidth; + float fHeight = font->m_fYScaleFactor * font->m_fFontHeight; // Setup the screen coordinates - m_fCursorX += fOffset; - float X4 = m_fCursorX; + font->m_fCursorX += fOffset; + float X4 = font->m_fCursorX; float X1 = X4; float X3 = X4 + fWidth; float X2 = X1 + fWidth; - float Y1 = m_fCursorY; + float Y1 = font->m_fCursorY; float Y3 = Y1 + fHeight; float Y2 = Y1; float Y4 = Y3; - m_fCursorX += fAdvance; + font->m_fCursorX += fAdvance; // Select the RGBA channel that the compressed glyph is stored in // Takes a 4 bit per pixel ARGB value and expand it to an 8 bit per pixel ARGB value @@ -795,13 +854,6 @@ VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, reinterpret_cast(pVertex)[15] = dwChannelSelector; pVertex+=16; - // If drawing ellipses, exit when they're all drawn - if( dwNumEllipsesToDraw ) - { - if( --dwNumEllipsesToDraw == 0 ) - break; - } - dwNumChars--; } @@ -833,57 +885,9 @@ VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, pd3dDevice->EndVertices(); // Undo window offsets - m_fCursorX -= Winx; - m_fCursorY -= Winy; + font->m_fCursorX -= Winx; + font->m_fCursorY -= Winy; // Call End() to complete the begin/end pair for drawing text - End(); - - // Close off the user-defined event opened with PIXBeginNamedEvent. - PIXEndNamedEvent(); -} - - -//-------------------------------------------------------------------------------------- -// Name: End() -// Desc: Paired call that restores state set in the Begin() call. -//-------------------------------------------------------------------------------------- -VOID XdkFont::End() -{ - if( --m_dwNestedBeginCount > 0 ) - { - PIXEndNamedEvent(); - return; - } - - // Restore state - if( m_bSaveState ) - { - // Cache the global pointer into a register - xdk360_video_t *vid = (xdk360_video_t*)g_d3d; - D3DDevice *pD3dDevice = vid->xdk360_render_device; - - pD3dDevice->SetTexture( 0, NULL ); - pD3dDevice->SetVertexDeclaration( NULL ); - pD3dDevice->SetVertexShader( NULL ); - pD3dDevice->SetPixelShader( NULL ); - pD3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHABLENDENABLE ] ); - pD3dDevice->SetRenderState( D3DRS_SRCBLEND, m_dwSavedState[ SAVEDSTATE_D3DRS_SRCBLEND ] ); - pD3dDevice->SetRenderState( D3DRS_DESTBLEND, m_dwSavedState[ SAVEDSTATE_D3DRS_DESTBLEND ] ); - pD3dDevice->SetRenderState( D3DRS_BLENDOP, m_dwSavedState[ SAVEDSTATE_D3DRS_BLENDOP ] ); - pD3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHATESTENABLE ] ); - pD3dDevice->SetRenderState( D3DRS_ALPHAREF, m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAREF ] ); - pD3dDevice->SetRenderState( D3DRS_ALPHAFUNC, m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAFUNC ] ); - pD3dDevice->SetRenderState( D3DRS_FILLMODE, m_dwSavedState[ SAVEDSTATE_D3DRS_FILLMODE ] ); - pD3dDevice->SetRenderState( D3DRS_CULLMODE, m_dwSavedState[ SAVEDSTATE_D3DRS_CULLMODE ] ); - pD3dDevice->SetRenderState( D3DRS_ZENABLE, m_dwSavedState[ SAVEDSTATE_D3DRS_ZENABLE ] ); - pD3dDevice->SetRenderState( D3DRS_STENCILENABLE, m_dwSavedState[ SAVEDSTATE_D3DRS_STENCILENABLE ] ); - pD3dDevice->SetRenderState( D3DRS_VIEWPORTENABLE, m_dwSavedState[ SAVEDSTATE_D3DRS_VIEWPORTENABLE ] ); - pD3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, m_dwSavedState[ SAVEDSTATE_D3DSAMP_MINFILTER ] ); - pD3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, m_dwSavedState[ SAVEDSTATE_D3DSAMP_MAGFILTER ] ); - pD3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSU ] ); - pD3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSV ] ); - } - - PIXEndNamedEvent(); + xdk360_video_font_end(font); } \ No newline at end of file diff --git a/360/fonts.h b/360/fonts.h new file mode 100644 index 0000000000..c4f1e7b780 --- /dev/null +++ b/360/fonts.h @@ -0,0 +1,121 @@ +/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * Copyright (C) 2011-2012 - Daniel De Matteis + * + * Some code herein may be based on code found in BSNES. + * + * SSNES is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with SSNES. + * If not, see . + */ + +#ifndef SSNES_360_FONTS_H +#define SSNES_360_FONTS_H + +#include "xdk360_video_resources.h" + +#define PAGE_UP (255) +#define PAGE_DOWN (-255) + +#define SCREEN_SIZE_X_DEFAULT 640 +#define SCREEN_SIZE_Y_DEFAULT 480 + +#define SAFE_AREA_PCT_4x3 85 +#define SAFE_AREA_PCT_HDTV 90 + +typedef struct +{ + float m_fLineHeight; // height of a single line in pixels + unsigned int m_nScrollOffset; // offset to display text (in lines) + unsigned int first_message; + unsigned int m_cxSafeArea; + unsigned int m_cySafeArea; + unsigned int m_cxSafeAreaOffset; + unsigned int m_cySafeAreaOffset; + unsigned int m_nCurLine; // index of current line being written to + unsigned int m_cCurLineLength; // length of the current line + unsigned long m_colBackColor; + unsigned long m_colTextColor; + unsigned int m_cScreenHeight; // height in lines of screen area + unsigned int m_cScreenHeightVirtual; // height in lines of text storage buffer + unsigned int m_cScreenWidth; // width in characters + wchar_t * m_Buffer; // buffer big enough to hold a full screen + wchar_t ** m_Lines; // pointers to individual lines +} video_console_t; + +typedef struct GLYPH_ATTR +{ + unsigned short tu1, tv1, tu2, tv2; // Texture coordinates for the image + short wOffset; // Pixel offset for glyph start + short wWidth; // Pixel width of the glyph + short wAdvance; // Pixels to advance after the glyph + unsigned short wMask; // Channel mask +} GLYPH_ATTR; + +enum SavedStates +{ + SAVEDSTATE_D3DRS_ALPHABLENDENABLE, + SAVEDSTATE_D3DRS_SRCBLEND, + SAVEDSTATE_D3DRS_DESTBLEND, + SAVEDSTATE_D3DRS_BLENDOP, + SAVEDSTATE_D3DRS_ALPHATESTENABLE, + SAVEDSTATE_D3DRS_ALPHAREF, + SAVEDSTATE_D3DRS_ALPHAFUNC, + SAVEDSTATE_D3DRS_FILLMODE, + SAVEDSTATE_D3DRS_CULLMODE, + SAVEDSTATE_D3DRS_ZENABLE, + SAVEDSTATE_D3DRS_STENCILENABLE, + SAVEDSTATE_D3DRS_VIEWPORTENABLE, + SAVEDSTATE_D3DSAMP_MINFILTER, + SAVEDSTATE_D3DSAMP_MAGFILTER, + SAVEDSTATE_D3DSAMP_ADDRESSU, + SAVEDSTATE_D3DSAMP_ADDRESSV, + + SAVEDSTATE_COUNT +}; + +typedef struct +{ + unsigned int m_bSaveState; + unsigned long m_dwSavedState[ SAVEDSTATE_COUNT ]; + unsigned long m_dwNestedBeginCount; + unsigned long m_cMaxGlyph; // Number of entries in the translator table + unsigned long m_dwNumGlyphs; // Number of valid glyphs + float m_fFontHeight; // Height of the font strike in pixels + float m_fFontTopPadding; // Padding above the strike zone + float m_fFontBottomPadding; // Padding below the strike zone + float m_fFontYAdvance; // Number of pixels to move the cursor for a line feed + float m_fXScaleFactor; // Scaling constants + float m_fYScaleFactor; + float m_fCursorX; // Current text cursor + float m_fCursorY; + D3DRECT m_rcWindow; // Bounds rect of the text window, modify via accessors only! + wchar_t * m_TranslatorTable; // ASCII to glyph lookup table + D3DTexture* m_pFontTexture; + const GLYPH_ATTR* m_Glyphs; // Array of glyphs +} xdk360_video_font_t; + +HRESULT xdk360_console_init ( LPCSTR strFontFileName, D3DCOLOR colBackColor, D3DCOLOR colTextColor); +void xdk360_console_deinit (void); +void xdk360_console_format (_In_z_ _Printf_format_string_ LPCSTR strFormat, ... ); +void xdk360_console_format_w (_In_z_ _Printf_format_string_ LPCWSTR wstrFormat, ... ); +void xdk360_console_draw (void); + +HRESULT xdk360_video_font_init(xdk360_video_font_t * font, const char * strFontFileName); +void xdk360_video_font_get_text_width(xdk360_video_font_t * font, const wchar_t * strText, float * pWidth, float * pHeight, int bFirstLineOnly); +void xdk360_video_font_deinit(xdk360_video_font_t * font); +void xdk360_video_font_set_cursor_position(xdk360_video_font_t *font, float fCursorX, float fCursorY ); +void xdk360_video_font_begin (xdk360_video_font_t * font); +void xdk360_video_font_end (xdk360_video_font_t * font); +void xdk360_video_font_set_size(float x, float y); +void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, float fOriginY, unsigned long dwColor, + const wchar_t * strText, float fMaxPixelWidth ); + +#endif diff --git a/360/menu.cpp b/360/menu.cpp index 023d588932..7fdde89560 100644 --- a/360/menu.cpp +++ b/360/menu.cpp @@ -69,7 +69,7 @@ HRESULT CSSNES::UnregisterXuiClasses (void) static void filebrowser_fetch_directory_entries(const char *path, CXuiList * romlist, CXuiTextElement * rompath_title) { - filebrowser_parse_directory(&browser, path, ssnes_console_get_rom_ext()); + filebrowser_push_directory(&browser, path, true); unsigned long dwNum_rompath = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0); wchar_t * rompath_name = new wchar_t[dwNum_rompath]; @@ -232,6 +232,8 @@ HRESULT CSSNESMain::OnInit(XUIMessageInit * pInitData, BOOL& bHandled) HRESULT CSSNESFileBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandled ) { + char path[MAX_PATH_LENGTH]; + if(hObjPressed == m_romlist) { int index = m_romlist.GetCurSel(); @@ -240,7 +242,7 @@ HRESULT CSSNESFileBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandled ) memset(strbuffer, 0, sizeof(strbuffer)); wcstombs(strbuffer, (const wchar_t *)m_romlist.GetText(index), sizeof(strbuffer)); memset(g_console.rom_path, 0, sizeof(g_console.rom_path)); - sprintf(g_console.rom_path, "%s%s", g_console.default_rom_startup_dir, strbuffer); + sprintf(g_console.rom_path, "%s%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser), strbuffer); return_to_game(); g_console.initialize_ssnes_enable = 1; @@ -249,9 +251,8 @@ HRESULT CSSNESFileBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandled ) { memset(strbuffer, 0, sizeof(strbuffer)); wcstombs(strbuffer, (const wchar_t *)m_romlist.GetText(index), sizeof(strbuffer)); - char strbuf[512]; - snprintf(strbuf, sizeof(strbuf), "%s%s", g_console.default_rom_startup_dir, strbuffer); - filebrowser_fetch_directory_entries(strbuf, &m_romlist, &m_rompathtitle); + snprintf(path, sizeof(path), "%s%s\\", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser), strbuffer); + filebrowser_fetch_directory_entries(path, &m_romlist, &m_rompathtitle); } } else if(hObjPressed == m_back) @@ -358,6 +359,8 @@ int menu_init (void) XuiSceneNavigateFirst(app.GetRootObj(), app.hMainScene, XUSER_INDEX_FOCUS); + filebrowser_new(&browser, g_console.default_rom_startup_dir, ssnes_console_get_rom_ext()); + return 0; } diff --git a/360/xdk360_video.cpp b/360/xdk360_video.cpp index c10776607f..048ccd6e6b 100644 --- a/360/xdk360_video.cpp +++ b/360/xdk360_video.cpp @@ -22,6 +22,7 @@ #include "xdk360_video.h" #include "../general.h" +#include "../message.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -71,7 +72,6 @@ static bool g_quitting; static bool g_first_msg; unsigned g_frame_count; void *g_d3d; -Console g_screen_console; static void xdk360_gfx_free(void * data) { @@ -283,12 +283,12 @@ static bool xdk360_gfx_frame(void *data, const void *frame, { if(IS_TIMER_EXPIRED() || g_first_msg) { - g_screen_console.Format(true, msg); + xdk360_console_format(msg); g_first_msg = 0; - SET_TIMER_EXPIRATION(60); + SET_TIMER_EXPIRATION(30); } - g_screen_console.Render(); + xdk360_console_draw(); } if(!vid->block_swap) @@ -363,7 +363,7 @@ void xdk360_video_init(void) g_first_msg = true; - HRESULT hr = g_screen_console.Create("game:\\media\\Arial_12.xpr", + HRESULT hr = xdk360_console_init("game:\\media\\Arial_12.xpr", 0xff000000, 0xffffffff ); if(FAILED(hr)) { @@ -375,6 +375,7 @@ void xdk360_video_deinit(void) { void *data = g_d3d; g_d3d = NULL; + xdk360_console_deinit(); xdk360_gfx_free(data); } diff --git a/360/xdk360_video.h b/360/xdk360_video.h index 8e0fec84b1..89af5bb764 100644 --- a/360/xdk360_video.h +++ b/360/xdk360_video.h @@ -19,7 +19,7 @@ #ifndef _XDK360_VIDEO_H #define _XDK360_VIDEO_H -#include "xdk360_video_console.h" +#include "fonts.h" typedef struct { float x; @@ -58,7 +58,6 @@ void xdk360_video_init(void); void xdk360_video_deinit(void); void xdk360_video_set_vsync(bool vsync); -extern Console g_screen_console; extern unsigned g_frame_count; extern void *g_d3d; diff --git a/360/xdk360_video_console.cpp b/360/xdk360_video_console.cpp deleted file mode 100644 index ee075f0877..0000000000 --- a/360/xdk360_video_console.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes. - * Copyright (C) 2010-2012 - Hans-Kristian Arntzen - * Copyright (C) 2011-2012 - Daniel De Matteis - * - * Some code herein may be based on code found in BSNES. - * - * SSNES is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with SSNES. - * If not, see . - */ - -#include -#include -#include "xdk360_video.h" -#include "xdk360_video_console.h" -#include "xdk360_video_debugfonts.h" -#include "../general.h" - -Console::Console() -{ - first_message = true; - m_Buffer = NULL; - m_Lines = NULL; - m_nScrollOffset = 0; -} - -Console::~Console() -{ - Destroy(); -} - -HRESULT Console::Create( LPCSTR strFontFileName, unsigned long colBackColor, - unsigned long colTextColor, unsigned int nLines ) -{ - xdk360_video_t *vid = (xdk360_video_t*)g_d3d; - D3DDevice *m_pd3dDevice = vid->xdk360_render_device; - - // Calculate the safe area - unsigned int uiSafeAreaPct = vid->video_mode.fIsHiDef ? SAFE_AREA_PCT_HDTV - : SAFE_AREA_PCT_4x3; - - m_cxSafeArea = ( vid->d3dpp.BackBufferWidth * uiSafeAreaPct ) / 100; - m_cySafeArea = ( vid->d3dpp.BackBufferHeight * uiSafeAreaPct ) / 100; - - m_cxSafeAreaOffset = ( vid->d3dpp.BackBufferWidth - m_cxSafeArea ) / 2; - m_cySafeAreaOffset = ( vid->d3dpp.BackBufferHeight - m_cySafeArea ) / 2; - - // Create the font - HRESULT hr = m_Font.Create( strFontFileName ); - if( FAILED( hr ) ) - { - SSNES_ERR( "Could not create font.\n" ); - return -1; - } - - // Save the colors - m_colBackColor = colBackColor; - m_colTextColor = colTextColor; - - // Calculate the number of lines on the screen - float fCharWidth, fCharHeight; - m_Font.GetTextExtent( L"i", &fCharWidth, &fCharHeight, FALSE ); - - m_cScreenHeight = (unsigned int)( m_cySafeArea / fCharHeight ); - m_cScreenWidth = (unsigned int)( m_cxSafeArea / fCharWidth ); - - m_cScreenHeightVirtual = max( m_cScreenHeight, nLines ); - - m_fLineHeight = fCharHeight; - - // Allocate memory to hold the lines - m_Buffer = new wchar_t[ m_cScreenHeightVirtual * ( m_cScreenWidth + 1 ) ]; - m_Lines = new wchar_t *[ m_cScreenHeightVirtual ]; - - // Set the line pointers as indexes into the buffer - for( unsigned int i = 0; i < m_cScreenHeightVirtual; i++ ) - m_Lines[ i ] = m_Buffer + ( m_cScreenWidth + 1 ) * i; - - m_nCurLine = 0; - m_cCurLineLength = 0; - memset( m_Buffer, 0, m_cScreenHeightVirtual * ( m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); - Render(); - - return hr; -} - -//-------------------------------------------------------------------------------------- -// Name: Destroy() -// Desc: Tear everything down -//-------------------------------------------------------------------------------------- -void Console::Destroy() -{ - // Delete the memory we've allocated - if( m_Lines ) - { - delete[] m_Lines; - m_Lines = NULL; - } - - if( m_Buffer ) - { - delete[] m_Buffer; - m_Buffer = NULL; - } - - // Destroy the font - m_Font.Destroy(); -} - - -//-------------------------------------------------------------------------------------- -// Name: Render() -// Desc: Render the console to the screen -//-------------------------------------------------------------------------------------- -void Console::Render() -{ - xdk360_video_t *vid = (xdk360_video_t*)g_d3d; - D3DDevice *m_pd3dDevice = vid->xdk360_render_device; - - // The top line - unsigned int nTextLine = ( m_nCurLine - m_cScreenHeight + m_cScreenHeightVirtual - m_nScrollOffset + 1 ) - % m_cScreenHeightVirtual; - - m_Font.Begin(); - - for( unsigned int nScreenLine = 0; nScreenLine < m_cScreenHeight; nScreenLine++ ) - { - m_Font.DrawText( (float)( m_cxSafeAreaOffset ), - (float)( m_cySafeAreaOffset + m_fLineHeight * nScreenLine ), - m_colTextColor, m_Lines[nTextLine] ); - - nTextLine = ( nTextLine + 1 ) % m_cScreenHeightVirtual; - } - - m_Font.End(); -} - - -//-------------------------------------------------------------------------------------- -// Name: Add( CHAR ) -// Desc: Convert ANSI to WCHAR and add to the current line -//-------------------------------------------------------------------------------------- -void Console::Add( char ch ) -{ - wchar_t wch; - - int ret = MultiByteToWideChar( CP_ACP, // ANSI code page - 0, // No flags - &ch, // Character to convert - 1, // Convert one byte - &wch, // Target wide character buffer - 1 ); // One wide character - - Add( wch ); -} - - - -//-------------------------------------------------------------------------------------- -// Name: Add( WCHAR ) -// Desc: Add a wide character to the current line -//-------------------------------------------------------------------------------------- -void Console::Add( wchar_t wch ) -{ - // If this is a newline, just increment lines and move on - if( wch == L'\n' ) - { - m_nCurLine = ( m_nCurLine + 1 ) % m_cScreenHeightVirtual; - m_cCurLineLength = 0; - memset( m_Lines[m_nCurLine], 0, ( m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); - return; - } - - int bIncrementLine = FALSE; // Whether to wrap to the next line - - if( m_cCurLineLength == m_cScreenWidth ) - bIncrementLine = TRUE; - else - { - // Try to append the character to the line - m_Lines[ m_nCurLine ][ m_cCurLineLength ] = wch; - - if( m_Font.GetTextWidth( m_Lines[ m_nCurLine ] ) > m_cxSafeArea ) - { - // The line is too long, we need to wrap the character to the next line - m_Lines[ m_nCurLine][ m_cCurLineLength ] = L'\0'; - bIncrementLine = TRUE; - } - } - - // If we need to skip to the next line, do so - if( bIncrementLine ) - { - m_nCurLine = ( m_nCurLine + 1 ) % m_cScreenHeightVirtual; - m_cCurLineLength = 0; - memset( m_Lines[m_nCurLine], 0, ( m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); - m_Lines[ m_nCurLine ][0] = wch; - } - - if(IS_TIMER_EXPIRED()) - m_cCurLineLength++; -} - - -//-------------------------------------------------------------------------------------- -// Name: Format() -// Desc: Output a variable argument list using a format string -//-------------------------------------------------------------------------------------- -void Console::Format(int clear_screen, _In_z_ _Printf_format_string_ LPCSTR strFormat, ... ) -{ - if(clear_screen) - { - m_nCurLine = 0; - m_cCurLineLength = 0; - memset( m_Buffer, 0, m_cScreenHeightVirtual * ( m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); - } - - va_list pArgList; - va_start( pArgList, strFormat ); - FormatV( strFormat, pArgList ); - va_end( pArgList ); - - // Render the output - Render(); -} - -void Console::Format(int clear_screen, _In_z_ _Printf_format_string_ LPCWSTR wstrFormat, ... ) -{ - if(clear_screen) - { - m_nCurLine = 0; - m_cCurLineLength = 0; - memset( m_Buffer, 0, m_cScreenHeightVirtual * ( m_cScreenWidth + 1 ) * sizeof( wchar_t ) ); - } - - va_list pArgList; - va_start( pArgList, wstrFormat ); - FormatV( wstrFormat, pArgList ); - va_end( pArgList ); - - // Render the output - Render(); -} - - -//-------------------------------------------------------------------------------------- -// Name: FormatV() -// Desc: Output a va_list using a format string -//-------------------------------------------------------------------------------------- -void Console::FormatV( _In_z_ _Printf_format_string_ LPCSTR strFormat, va_list pArgList ) -{ - // Count the required length of the string - unsigned long dwStrLen = _vscprintf( strFormat, pArgList ) + 1; // +1 = null terminator - char * strMessage = ( char * )_malloca( dwStrLen ); - vsprintf_s( strMessage, dwStrLen, strFormat, pArgList ); - - // Output the string to the console - unsigned long uStringLength = strlen( strMessage ); - for( unsigned long i = 0; i < uStringLength; i++ ) - Add( strMessage[i] ); - - _freea( strMessage ); -} - -void Console::FormatV( _In_z_ _Printf_format_string_ LPCWSTR wstrFormat, va_list pArgList ) -{ - // Count the required length of the string - unsigned long dwStrLen = _vscwprintf( wstrFormat, pArgList ) + 1; // +1 = null terminator - wchar_t * strMessage = ( wchar_t * )_malloca( dwStrLen * sizeof( wchar_t ) ); - vswprintf_s( strMessage, dwStrLen, wstrFormat, pArgList ); - - // Output the string to the console - unsigned long uStringLength = wcslen( strMessage ); - for( unsigned long i = 0; i < uStringLength; i++ ) - Add( strMessage[i] ); - - _freea( strMessage ); -} diff --git a/360/xdk360_video_console.h b/360/xdk360_video_console.h deleted file mode 100644 index a436b23677..0000000000 --- a/360/xdk360_video_console.h +++ /dev/null @@ -1,93 +0,0 @@ -/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes. - * Copyright (C) 2010-2012 - Hans-Kristian Arntzen - * Copyright (C) 2011-2012 - Daniel De Matteis - * - * Some code herein may be based on code found in BSNES. - * - * SSNES is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with SSNES. - * If not, see . - */ - -#pragma once -#ifndef SSNES360_CONSOLE_H -#define SSNES360_CONSOLE_H - -#include -#include "xdk360_video_debugfonts.h" - -#define PAGE_UP (255) -#define PAGE_DOWN (-255) - -#define SCREEN_SIZE_X_DEFAULT 640 -#define SCREEN_SIZE_Y_DEFAULT 480 - -#define SAFE_AREA_PCT_4x3 85 -#define SAFE_AREA_PCT_HDTV 90 - -//-------------------------------------------------------------------------------------- -// Name: class Console -// Desc: Class to implement the console. -//-------------------------------------------------------------------------------------- -class Console -{ -public: - Console(); - ~Console(); - - // Initialization - HRESULT Create( LPCSTR strFontFileName, - D3DCOLOR colBackColor, - D3DCOLOR colTextColor, - unsigned int nLines = 0 ); - - void Destroy(); - - // Console output - void Format(int clear_screen, _In_z_ _Printf_format_string_ LPCSTR strFormat, ... ); - void Format(int clear_screen, _In_z_ _Printf_format_string_ LPCWSTR wstrFormat, ... ); - void FormatV( _In_z_ _Printf_format_string_ LPCSTR strFormat, va_list pArgList ); - void FormatV( _In_z_ _Printf_format_string_ LPCWSTR wstrFormat, va_list pArgList ); - - // method for rendering the console - void Render(); - // Font for rendering text - XdkFont m_Font; -private: - int first_message; - // Safe area dimensions - unsigned int m_cxSafeArea; - unsigned int m_cySafeArea; - - unsigned int m_cxSafeAreaOffset; - unsigned int m_cySafeAreaOffset; - - // Colors - unsigned long m_colBackColor; - unsigned long m_colTextColor; - - // Text Buffers - unsigned int m_cScreenHeight; // height in lines of screen area - unsigned int m_cScreenHeightVirtual; // height in lines of text storage buffer - unsigned int m_cScreenWidth; // width in characters - float m_fLineHeight; // height of a single line in pixels - - wchar_t * m_Buffer; // buffer big enough to hold a full screen - wchar_t ** m_Lines; // pointers to individual lines - unsigned int m_nCurLine; // index of current line being written to - unsigned int m_cCurLineLength; // length of the current line - int m_nScrollOffset; // offset to display text (in lines) - - // Add a character to the current line - void Add( char ch ); - void Add( wchar_t wch ); -}; - -#endif diff --git a/360/xdk360_video_debugfonts.h b/360/xdk360_video_debugfonts.h deleted file mode 100644 index df0370e9e5..0000000000 --- a/360/xdk360_video_debugfonts.h +++ /dev/null @@ -1,124 +0,0 @@ -/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes. - * Copyright (C) 2010-2012 - Hans-Kristian Arntzen - * Copyright (C) 2011-2012 - Daniel De Matteis - * - * Some code herein may be based on code found in BSNES. - * - * SSNES is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with SSNES. - * If not, see . - */ - -#ifndef _SSNES360_DEBUG_FONTS_H -#define _SSNES360_DEBUG_FONTS_H - -#include "xdk360_video_resources.h" - -typedef struct GLYPH_ATTR -{ - unsigned short tu1, tv1, tu2, tv2; // Texture coordinates for the image - short wOffset; // Pixel offset for glyph start - short wWidth; // Pixel width of the glyph - short wAdvance; // Pixels to advance after the glyph - unsigned short wMask; // Channel mask -} GLYPH_ATTR; - -#define FONT_LEFT 0x00000000 -#define FONT_RIGHT 0x00000001 -#define FONT_CENTER_X 0x00000002 -#define FONT_CENTER_Y 0x00000004 -#define FONT_TRUNCATED 0x00000008 - -enum SavedStates -{ - SAVEDSTATE_D3DRS_ALPHABLENDENABLE, - SAVEDSTATE_D3DRS_SRCBLEND, - SAVEDSTATE_D3DRS_DESTBLEND, - SAVEDSTATE_D3DRS_BLENDOP, - SAVEDSTATE_D3DRS_ALPHATESTENABLE, - SAVEDSTATE_D3DRS_ALPHAREF, - SAVEDSTATE_D3DRS_ALPHAFUNC, - SAVEDSTATE_D3DRS_FILLMODE, - SAVEDSTATE_D3DRS_CULLMODE, - SAVEDSTATE_D3DRS_ZENABLE, - SAVEDSTATE_D3DRS_STENCILENABLE, - SAVEDSTATE_D3DRS_VIEWPORTENABLE, - SAVEDSTATE_D3DSAMP_MINFILTER, - SAVEDSTATE_D3DSAMP_MAGFILTER, - SAVEDSTATE_D3DSAMP_ADDRESSU, - SAVEDSTATE_D3DSAMP_ADDRESSV, - - SAVEDSTATE_COUNT -}; - -class XdkFont -{ -public: - PackedResource m_xprResource; - - // Font vertical dimensions taken from the font file - float m_fFontHeight; // Height of the font strike in pixels - float m_fFontTopPadding; // Padding above the strike zone - float m_fFontBottomPadding; // Padding below the strike zone - float m_fFontYAdvance; // Number of pixels to move the cursor for a line feed - - float m_fXScaleFactor; // Scaling constants - float m_fYScaleFactor; - - D3DRECT m_rcWindow; // Bounds rect if the text window, modify via accessors only! - float m_fCursorX; // Current text cursor - float m_fCursorY; - - // Translator table for supporting unicode ranges - unsigned long m_cMaxGlyph; // Number of entries in the translator table - wchar_t * m_TranslatorTable; // ASCII to glyph lookup table - - // Glyph data for the font - unsigned long m_dwNumGlyphs; // Number of valid glyphs - const GLYPH_ATTR* m_Glyphs; // Array of glyphs - - // D3D rendering objects - D3DTexture* m_pFontTexture; - - // Saved state for rendering (if not using a pure device) - unsigned long m_dwSavedState[ SAVEDSTATE_COUNT ]; - unsigned long m_dwNestedBeginCount; - int m_bSaveState; -public: - XdkFont(); - ~XdkFont(); - - // Functions to create and destroy the internal objects - HRESULT Create( const char * strFontFileName ); - void Destroy(); - - // Returns the dimensions of a text string - void GetTextExtent( const wchar_t * strText, float * pWidth, - float * pHeight, int bFirstLineOnly=FALSE ) const; - float GetTextWidth( const wchar_t * strText ) const; - void SetCursorPosition( float fCursorX, float fCursorY ); - void SetFontSize(float x, float y); - - // Public calls to render text. Callers can simply call DrawText(), but for - // performance, they should batch multiple calls together, bracketed by calls to - // Begin() and End(). - void Begin(); - void DrawText( unsigned long dwColor, const wchar_t * strText, unsigned long dwFlags=0L, - float fMaxPixelWidth = 0.0f ); - void DrawText( float sx, float sy, unsigned long dwColor, const wchar_t * strText, - unsigned long dwFlags=0L, float fMaxPixelWidth = 0.0f ); - void End(); - -private: - // Internal helper functions - HRESULT CreateFontShaders(); -}; - -#endif \ No newline at end of file diff --git a/360/xdk360_video_resources.cpp b/360/xdk360_video_resources.cpp index 104058f575..e518caab08 100644 --- a/360/xdk360_video_resources.cpp +++ b/360/xdk360_video_resources.cpp @@ -33,7 +33,6 @@ struct XPR_HEADER }; #define XPR2_MAGIC_VALUE (0x58505232) -#define eXALLOCAllocatorId_AtgResource eXALLOCAllocatorId_GameMax //-------------------------------------------------------------------------------------- // Name: PackedResource @@ -120,7 +119,7 @@ HRESULT PackedResource::Create( const char * strFilename ) m_dwSysMemDataSize = 0; return E_FAIL; } - m_pVidMemData = ( BYTE* )XMemAlloc( m_dwVidMemDataSize, MAKE_XALLOC_ATTRIBUTES( 0, 0, 0, 0, eXALLOCAllocatorId_AtgResource, + m_pVidMemData = ( BYTE* )XMemAlloc( m_dwVidMemDataSize, MAKE_XALLOC_ATTRIBUTES( 0, 0, 0, 0, eXALLOCAllocatorId_GameMax, XALLOC_PHYSICAL_ALIGNMENT_4K, XALLOC_MEMPROTECT_WRITECOMBINE, 0, XALLOC_MEMTYPE_PHYSICAL ) ); if( m_pVidMemData == NULL ) @@ -160,9 +159,6 @@ HRESULT PackedResource::Create( const char * strFilename ) D3DTexture* pTexture = ( D3DTexture* )&m_pSysMemData[m_pResourceTags[i].dwOffset]; // Adjust Base address according to where memory was allocated XGOffsetBaseTextureAddress( pTexture, m_pVidMemData, m_pVidMemData ); - - // Let PIX know the name of the texture - PIXSetTextureName(pTexture, m_pResourceTags[i].strName); } } @@ -182,7 +178,7 @@ void PackedResource::Destroy() m_dwSysMemDataSize = 0L; if( m_pVidMemData != NULL ) - XMemFree( m_pVidMemData, MAKE_XALLOC_ATTRIBUTES( 0, 0, 0, 0, eXALLOCAllocatorId_AtgResource, + XMemFree( m_pVidMemData, MAKE_XALLOC_ATTRIBUTES( 0, 0, 0, 0, eXALLOCAllocatorId_GameMax, 0, 0, 0, XALLOC_MEMTYPE_PHYSICAL ) ); m_pVidMemData = NULL; diff --git a/file.c b/file.c index 95f9533c19..12ce830781 100644 --- a/file.c +++ b/file.c @@ -550,23 +550,17 @@ void save_ram_file(const char *path, int type) } } -#ifdef HAVE_XML static char *load_xml_map(const char *path) { char *xml_buf = NULL; if (*path) { - if (!read_file_string(path, &xml_buf)) - SSNES_LOG("Did not find XML memory map in \"%s\"\n", path); - else + if (read_file_string(path, &xml_buf)) SSNES_LOG("Found XML memory map in \"%s\"\n", path); } return xml_buf; } -#else -#define load_xml_map(xml_name) (NULL) -#endif static bool load_sgb_rom(void) { diff --git a/input/sdl_input.c b/input/sdl_input.c index 3ce051f393..3cb38b828e 100644 --- a/input/sdl_input.c +++ b/input/sdl_input.c @@ -150,23 +150,28 @@ static void *sdl_input_init(void) if (g_settings.input.joypad_map[i] < 0) continue; - if (sdl->num_joysticks > (unsigned)g_settings.input.joypad_map[i]) - { - sdl->joysticks[i] = SDL_JoystickOpen(g_settings.input.joypad_map[i]); - if (!sdl->joysticks[i]) - { - SSNES_ERR("Couldn't open SDL joystick #%u on SNES port %u\n", g_settings.input.joypad_map[i], i + 1); - free(sdl); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - return NULL; - } + unsigned port = g_settings.input.joypad_map[i]; - SSNES_LOG("Opened Joystick: %s #%u on port %u\n", - SDL_JoystickName(g_settings.input.joypad_map[i]), g_settings.input.joypad_map[i], i + 1); - sdl->num_axes[i] = SDL_JoystickNumAxes(sdl->joysticks[i]); - sdl->num_buttons[i] = SDL_JoystickNumButtons(sdl->joysticks[i]); - sdl->num_hats[i] = SDL_JoystickNumHats(sdl->joysticks[i]); + if (sdl->num_joysticks <= port) + continue; + + sdl->joysticks[i] = SDL_JoystickOpen(port); + if (!sdl->joysticks[i]) + { + SSNES_ERR("Couldn't open SDL joystick #%u on SNES port %u\n", port, i + 1); + free(sdl); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + return NULL; } + + SSNES_LOG("Opened Joystick: %s (#%u) on port %u\n", + SDL_JoystickName(port), port, i + 1); + + sdl->num_axes[i] = SDL_JoystickNumAxes(sdl->joysticks[i]); + sdl->num_buttons[i] = SDL_JoystickNumButtons(sdl->joysticks[i]); + sdl->num_hats[i] = SDL_JoystickNumHats(sdl->joysticks[i]); + SSNES_LOG("Joypad has: %u axes, %u buttons, %u hats.\n", + sdl->num_axes[i], sdl->num_buttons[i], sdl->num_hats[i]); } #endif @@ -188,39 +193,32 @@ static bool sdl_joykey_pressed(sdl_input_t *sdl, int port_num, uint16_t joykey) // Check hat. if (GET_HAT_DIR(joykey)) { - int hat = GET_HAT(joykey); - if (hat < (int)sdl->num_hats[port_num]) + uint16_t hat = GET_HAT(joykey); + if (hat >= sdl->num_hats[port_num]) + return false; + + Uint8 dir = SDL_JoystickGetHat(sdl->joysticks[port_num], hat); + switch (GET_HAT_DIR(joykey)) { - Uint8 dir = SDL_JoystickGetHat(sdl->joysticks[port_num], hat); - switch (GET_HAT_DIR(joykey)) - { - case HAT_UP_MASK: - if (dir & SDL_HAT_UP) - return true; - break; - case HAT_DOWN_MASK: - if (dir & SDL_HAT_DOWN) - return true; - break; - case HAT_LEFT_MASK: - if (dir & SDL_HAT_LEFT) - return true; - break; - case HAT_RIGHT_MASK: - if (dir & SDL_HAT_RIGHT) - return true; - break; - default: - break; - } + case HAT_UP_MASK: + return dir & SDL_HAT_UP; + case HAT_DOWN_MASK: + return dir & SDL_HAT_DOWN; + case HAT_LEFT_MASK: + return dir & SDL_HAT_LEFT; + case HAT_RIGHT_MASK: + return dir & SDL_HAT_RIGHT; + default: + return false; } } else // Check the button { if (joykey < sdl->num_buttons[port_num] && SDL_JoystickGetButton(sdl->joysticks[port_num], joykey)) return true; + + return false; } - return false; } static bool sdl_axis_pressed(sdl_input_t *sdl, int port_num, uint32_t joyaxis) diff --git a/msvc-360/SSNES-360/SSNES-360.vcxproj b/msvc-360/SSNES-360/SSNES-360.vcxproj index 7e325822d7..d78cfd81a6 100644 --- a/msvc-360/SSNES-360/SSNES-360.vcxproj +++ b/msvc-360/SSNES-360/SSNES-360.vcxproj @@ -283,13 +283,12 @@ + - - diff --git a/msvc-360/SSNES-360/SSNES-360.vcxproj.filters b/msvc-360/SSNES-360/SSNES-360.vcxproj.filters index 3ac3d35f3b..16aa724cae 100644 --- a/msvc-360/SSNES-360/SSNES-360.vcxproj.filters +++ b/msvc-360/SSNES-360/SSNES-360.vcxproj.filters @@ -131,13 +131,10 @@ Source Files\console - - Source Files\360 - Source Files\360 - + Source Files\360 diff --git a/settings.c b/settings.c index 5980071922..fc39b0c408 100644 --- a/settings.c +++ b/settings.c @@ -418,7 +418,7 @@ bool config_load_file(const char *path) for (unsigned i = 0; i < MAX_PLAYERS; i++) { char buf[64]; - snprintf(buf, sizeof(buf), "input_player%u_joypad_index", i); + snprintf(buf, sizeof(buf), "input_player%u_joypad_index", i + 1); CONFIG_GET_INT(input.joypad_map[i], buf); } @@ -697,27 +697,30 @@ static void read_keybinds_keyboard(config_file_t *conf, unsigned player, unsigne static void parse_hat(struct snes_keybind *bind, const char *str) { - if (isdigit(*str)) + if (!isdigit(*str)) + return; + + char *dir = NULL; + uint16_t hat = strtoul(str, &dir, 0); + uint16_t hat_dir = 0; + + if (!dir) { - char *dir = NULL; - int hat = strtol(str, &dir, 0); - int hat_dir = 0; - - if (dir) - { - if (strcasecmp(str, "up") == 0) - hat_dir = HAT_UP_MASK; - else if (strcasecmp(str, "down") == 0) - hat_dir = HAT_DOWN_MASK; - else if (strcasecmp(str, "left") == 0) - hat_dir = HAT_LEFT_MASK; - else if (strcasecmp(str, "right") == 0) - hat_dir = HAT_RIGHT_MASK; - - if (hat_dir) - bind->joykey = HAT_MAP(hat, hat_dir); - } + SSNES_WARN("Found invalid hat in config!\n"); + return; } + + if (strcasecmp(dir, "up") == 0) + hat_dir = HAT_UP_MASK; + else if (strcasecmp(dir, "down") == 0) + hat_dir = HAT_DOWN_MASK; + else if (strcasecmp(dir, "left") == 0) + hat_dir = HAT_LEFT_MASK; + else if (strcasecmp(dir, "right") == 0) + hat_dir = HAT_RIGHT_MASK; + + if (hat_dir) + bind->joykey = HAT_MAP(hat, hat_dir); } static void read_keybinds_button(config_file_t *conf, unsigned player, unsigned index, struct snes_keybind *bind) diff --git a/ssnes.c b/ssnes.c index cbf22d6acf..389e767512 100644 --- a/ssnes.c +++ b/ssnes.c @@ -419,9 +419,7 @@ static void print_features(void) _PSUPP(al, "OpenAL", "audio driver"); _PSUPP(dylib, "External", "External filter and driver support"); _PSUPP(cg, "Cg", "Cg pixel shaders"); -#ifdef HAVE_XML _PSUPP(xml, "XML", "bSNES XML pixel shaders"); -#endif _PSUPP(sdl_image, "SDL_image", "SDL_image image loading"); _PSUPP(fbo, "FBO", "OpenGL render-to-texture (multi-pass shaders)"); _PSUPP(dynamic, "Dynamic", "Dynamic run-time loading of libsnes library"); @@ -512,9 +510,7 @@ static void print_help(void) puts("\t-v/--verbose: Verbose logging."); puts("\t-U/--ups: Specifies path for UPS patch that will be applied to ROM."); puts("\t--bps: Specifies path for BPS patch that will be applied to ROM."); -#ifdef HAVE_XML puts("\t-X/--xml: Specifies path to XML memory map."); -#endif puts("\t-D/--detach: Detach SSNES from the running console. Not relevant for all platforms.\n"); } @@ -661,9 +657,7 @@ static void parse_input(int argc, char *argv[]) #endif { "ups", 1, NULL, 'U' }, { "bps", 1, &val, 'B' }, -#ifdef HAVE_XML { "xml", 1, NULL, 'X' }, -#endif { "detach", 0, NULL, 'D' }, { "features", 0, &val, 'f' }, { NULL, 0, NULL, 0 } @@ -856,11 +850,10 @@ static void parse_input(int argc, char *argv[]) strlcpy(g_extern.ups_name, optarg, sizeof(g_extern.ups_name)); g_extern.ups_pref = true; break; -#ifdef HAVE_XML + case 'X': strlcpy(g_extern.xml_name, optarg, sizeof(g_extern.xml_name)); break; -#endif case 'D': #if defined(_WIN32) && !defined(_XBOX) @@ -1492,10 +1485,8 @@ static void fill_pathnames(void) if (!(*g_extern.bps_name)) fill_pathname_noext(g_extern.bps_name, g_extern.basename, ".bps", sizeof(g_extern.bps_name)); -#ifdef HAVE_XML if (!(*g_extern.xml_name)) fill_pathname_noext(g_extern.xml_name, g_extern.basename, ".xml", sizeof(g_extern.xml_name)); -#endif if (!(*g_settings.screenshot_directory)) {