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 2f25a01f82..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,70 +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 -{ - float fTextWidth, fTextHeight; - GetTextExtent( strText, &fTextWidth, &fTextHeight ); - return fTextWidth; -} - - -//-------------------------------------------------------------------------------------- -// Name: Begin() -// Desc: Prepares the font vertex buffers for rendering. -//-------------------------------------------------------------------------------------- -VOID XdkFont::Begin() +void xdk360_video_font_begin (xdk360_video_font_t * font) { // 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]; @@ -544,28 +672,45 @@ 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, - float fMaxPixelWidth ) +void xdk360_video_font_end(xdk360_video_font_t * font) { - DrawText( m_fCursorX, m_fCursorY, dwColor, strText, 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, +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 || strText[0] == L'\0') @@ -582,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 @@ -591,23 +736,23 @@ VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, // Set the starting screen position if((fOriginX < 0.0f)) - fOriginX += m_rcWindow.x2; + fOriginX += font->m_rcWindow.x2; if( fOriginY < 0.0f ) - fOriginY += m_rcWindow.y2; + 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; + fOriginY -= font->m_fFontTopPadding; // Add window offsets float Winx = 0.0f; float Winy = 0.0f; fOriginX += Winx; fOriginY += Winy; - m_fCursorX += Winx; - m_fCursorY += Winy; + font->m_fCursorX += Winx; + font->m_fCursorY += Winy; // Begin drawing the vertices @@ -636,31 +781,31 @@ VOID XdkFont::DrawText( float fOriginX, float fOriginY, unsigned long dwColor, // Handle the newline character if( letter == L'\n' ) { - m_fCursorX = fOriginX; - m_fCursorY += m_fFontYAdvance * m_fYScaleFactor; + 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; + 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 @@ -740,49 +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(); -} - - -//-------------------------------------------------------------------------------------- -// Name: End() -// Desc: Paired call that restores state set in the Begin() call. -//-------------------------------------------------------------------------------------- -VOID XdkFont::End() -{ - if( --m_dwNestedBeginCount > 0 ) - 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 ] ); - } + 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.h b/360/xdk360_video.h index af4857f809..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; diff --git a/360/xdk360_video_console.cpp b/360/xdk360_video_console.cpp deleted file mode 100644 index 46c636fc5b..0000000000 --- a/360/xdk360_video_console.cpp +++ /dev/null @@ -1,241 +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" - -static video_console_t video_console; -static XdkFont 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; - - m_Font.Begin(); - - for( unsigned int nScreenLine = 0; nScreenLine < video_console.m_cScreenHeight; nScreenLine++ ) - { - m_Font.DrawText( (float)( video_console.m_cxSafeAreaOffset ), - (float)( video_console.m_cySafeAreaOffset + - video_console.m_fLineHeight * nScreenLine ), - video_console.m_colTextColor, - video_console.m_Lines[nTextLine] ); - - nTextLine = ( nTextLine + 1 ) % video_console.m_cScreenHeightVirtual; - } - - m_Font.End(); -} - -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 = m_Font.Create( 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; - m_Font.GetTextExtent( 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 - m_Font.Destroy(); -} - -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; - - if( m_Font.GetTextWidth( video_console.m_Lines - [ video_console.m_nCurLine ] ) > 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 ); -} \ No newline at end of file diff --git a/360/xdk360_video_console.h b/360/xdk360_video_console.h deleted file mode 100644 index d3173f740b..0000000000 --- a/360/xdk360_video_console.h +++ /dev/null @@ -1,61 +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 - -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; - -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); - -#endif diff --git a/360/xdk360_video_debugfonts.h b/360/xdk360_video_debugfonts.h deleted file mode 100644 index 2aeeab4743..0000000000 --- a/360/xdk360_video_debugfonts.h +++ /dev/null @@ -1,118 +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; - -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 of 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, - float fMaxPixelWidth = 0.0f ); - void DrawText( float sx, float sy, unsigned long dwColor, - const wchar_t * strText, 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 e65b098ab9..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 ) @@ -179,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/input/sdl_input.c b/input/sdl_input.c index 3ce051f393..abfd407608 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 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 55cf817650..e34317c5f5 100644 --- a/settings.c +++ b/settings.c @@ -420,7 +420,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); }