-removed sd only arg and replaced it with eisteinx2's code to detect sd only. with slight change because mountall() is called in other places.

-fixed font glyph x spacing so letters like W no longer bleed into or look like they connect to the next letter. also fixes letters like j's. thanks to usbloader gx freetypegx code.
-changed some font sizing. but had to make button fonts in bold. if not bold then sometime's the text would fade out and be hard to read. something to do with the wiiflow button images being transparent. has no effect on non transparent buttons like carbonik abz theme.
-fixed wfl so time and date in games is correct. thanks aphirst!
-now unloading theme.ini from mem after all buttons and labels are created. this is possible since coverflow.ini is now seperate from theme.ini.
- other minor code changes and rem's put in for easier code decyphering.
This commit is contained in:
fledge68 2018-07-09 14:53:35 +00:00
parent 4a566375e0
commit 66c17c023c
31 changed files with 614 additions and 430 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -70,7 +70,7 @@ static NandDevice NandDeviceList[] =
void Nand::Init() void Nand::Init()
{ {
MountedDevice = 0; MountedDevice = 0;
EmuDevice = REAL_NAND; EmuDevice = WII_NAND;
Partition = 0; Partition = 0;
FullMode = 0x100; FullMode = 0x100;
memset(NandPath, 0, sizeof(NandPath)); memset(NandPath, 0, sizeof(NandPath));

View File

@ -10,7 +10,7 @@
#include "loader/disc.h" #include "loader/disc.h"
#define REAL_NAND 0 #define WII_NAND 0
#define EMU_SD 1 #define EMU_SD 1
#define EMU_USB 2 #define EMU_USB 2

View File

@ -48,10 +48,16 @@ void DeviceHandler::Init()
OGC_Device.Init();// used for Devolution gamecube iso launcher OGC_Device.Init();// used for Devolution gamecube iso launcher
} }
bool mount_usb = false;
void DeviceHandler::SetMountUSB(bool using_usb)
{
mount_usb = using_usb;
}
void DeviceHandler::MountAll() void DeviceHandler::MountAll()
{ {
MountSD(); MountSD();
if(!Sys_DolphinMode()) if(!Sys_DolphinMode() && mount_usb)
MountAllUSB(); MountAllUSB();
} }

View File

@ -66,6 +66,7 @@ class DeviceHandler
public: public:
void Init(); void Init();
void SetModes(); void SetModes();
void SetMountUSB(bool using_usb);
void MountAll(); void MountAll();
void UnMountAll(); void UnMountAll();
bool Mount(int dev); bool Mount(int dev);

View File

@ -141,7 +141,7 @@ bool fsop_CopyFile(const char *source, const char *target, progress_callback_t s
if(!fs) if(!fs)
return false; return false;
ft = fopen(target, "wt"); ft = fopen(target, "wb");
if(!ft) if(!ft)
{ {
fclose(fs); fclose(fs);
@ -292,6 +292,7 @@ void fsop_deleteFolder(const char *source)
pdir = opendir(source); pdir = opendir(source);
/* first delete all subfolders and files in the folder */
while((pent = readdir(pdir)) != NULL) while((pent = readdir(pdir)) != NULL)
{ {
// Skip it // Skip it
@ -313,8 +314,9 @@ void fsop_deleteFolder(const char *source)
} }
} }
closedir(pdir); closedir(pdir);
/* now actually delete the folder */
gprintf("Deleting directory: %s\n", source); gprintf("Deleting directory: %s\n", source);
unlink(source); unlink(source);// using POSIX unlink to delete the folder
} }
bool fsop_FileExist(const char *fn) bool fsop_FileExist(const char *fn)

View File

@ -1,21 +1,21 @@
// Can put this in defines.h later, but its easier // Can put this in defines.h later, but its easier
//not having to recompile the whole menu for now by doing it this way //not having to recompile the whole menu for now by doing it this way
#define WIIFONT_NAME "WiiNTLG-Regular.ttc" //#define WIIFONT_NAME "WiiNTLG-Regular.ttc"
#define WIIFONT_NAME_KOR "Wii-kr_Round Gothic B.ttf" //#define WIIFONT_NAME_KOR "Wii-kr_Round Gothic B.ttf"
const u8 WIIFONT_HASH[] = {0x32, 0xb3, 0x39, 0xcb, 0xbb, 0x50, 0x7d, 0x50, 0x27, 0x79, 0x25, 0x9a, 0x78, 0x66, 0x99, 0x5d, 0x03, 0x0b, 0x1d, 0x88}; const u8 WIIFONT_HASH[] = {0x32, 0xb3, 0x39, 0xcb, 0xbb, 0x50, 0x7d, 0x50, 0x27, 0x79, 0x25, 0x9a, 0x78, 0x66, 0x99, 0x5d, 0x03, 0x0b, 0x1d, 0x88};
const u8 WIIFONT_HASH_KOR[] = {0xb7, 0x15, 0x6d, 0xf0, 0xf4, 0xae, 0x07, 0x8f, 0xd1, 0x53, 0x58, 0x3e, 0x93, 0x6e, 0x07, 0xc0, 0x98, 0x77, 0x49, 0x0e}; const u8 WIIFONT_HASH_KOR[] = {0xb7, 0x15, 0x6d, 0xf0, 0xf4, 0xae, 0x07, 0x8f, 0xd1, 0x53, 0x58, 0x3e, 0x93, 0x6e, 0x07, 0xc0, 0x98, 0x77, 0x49, 0x0e};
const u8 WFB_HASH[] = { 0x4f, 0xad, 0x97, 0xfd, 0x4a, 0x28, 0x8c, 0x47, 0xe0, 0x58, 0x7f, 0x3b, 0xbd, 0x29, 0x23, 0x79, 0xf8, 0x70, 0x9e, 0xb9 }; const u8 WFB_HASH[] = {0x4f, 0xad, 0x97, 0xfd, 0x4a, 0x28, 0x8c, 0x47, 0xe0, 0x58, 0x7f, 0x3b, 0xbd, 0x29, 0x23, 0x79, 0xf8, 0x70, 0x9e, 0xb9};
#define FONT_BOLD 36u #define FONT_BOLD 32u
#define FONT_NOBOLD 8u #define FONT_NOBOLD 8u
#define TITLEFONT_PT_SZ 30u #define TITLEFONT_PT_SZ 30u
#define BTNFONT_PT_SZ 20u #define BTNFONT_PT_SZ 18u
#define LBLFONT_PT_SZ 20u #define LBLFONT_PT_SZ 20u
#define TEXTFONT_PT_SZ 16u #define TEXTFONT_PT_SZ 18u
#define TITLEFONT TITLEFONT_PT_SZ, TITLEFONT_PT_SZ - 4, FONT_BOLD, 1, "title_font" #define TITLEFONT TITLEFONT_PT_SZ, TITLEFONT_PT_SZ - 4, FONT_NOBOLD, 1, "title_font"
#define BUTTONFONT BTNFONT_PT_SZ, BTNFONT_PT_SZ - 4, FONT_BOLD, 1, "button_font" #define BUTTONFONT BTNFONT_PT_SZ, BTNFONT_PT_SZ - 4, FONT_BOLD, 1, "button_font"
#define LABELFONT LBLFONT_PT_SZ, LBLFONT_PT_SZ + 4, FONT_BOLD, 1, "label_font" #define LABELFONT LBLFONT_PT_SZ, LBLFONT_PT_SZ + 4, FONT_NOBOLD, 1, "label_font"
#define TEXTFONT TEXTFONT_PT_SZ, TEXTFONT_PT_SZ + 6, FONT_BOLD, 1, "text_font" #define TEXTFONT TEXTFONT_PT_SZ, TEXTFONT_PT_SZ + 6, FONT_NOBOLD, 1, "text_font"

View File

@ -18,124 +18,166 @@
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with FreeTypeGX. If not, see <http://www.gnu.org/licenses/>. * along with FreeTypeGX. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h>
#include "FreeTypeGX.h" #include "FreeTypeGX.h"
#include "memory/mem2.hpp" #include "memory/mem2.hpp"
using namespace std;
#define ALIGN8(x) (((x) + 7) & ~7)
FreeTypeGX::FreeTypeGX() FreeTypeGX::FreeTypeGX()
{ {
FT_Init_FreeType(&this->ftLibrary); FT_Init_FreeType(&ftLibrary);
reset(); reset();
this->ftFace = 0; ftFace = 0;
} }
FreeTypeGX::~FreeTypeGX() FreeTypeGX::~FreeTypeGX()
{ {
this->unloadFont(); unloadFont();
FT_Done_Face(this->ftFace); FT_Done_Face(ftFace);
FT_Done_FreeType(this->ftLibrary); FT_Done_FreeType(ftLibrary);
} }
wchar_t* FreeTypeGX::charToWideChar(char* strChar) wchar_t* FreeTypeGX::charToWideChar(char* strChar)
{ {
wchar_t *strWChar; if (!strChar) return NULL;
strWChar = new wchar_t[strlen(strChar) + 1];
wchar_t *strWChar = new (std::nothrow) wchar_t[strlen(strChar) + 1];
if (!strWChar) return NULL;
int bt = mbstowcs(strWChar, strChar, strlen(strChar));
if (bt > 0)
{
strWChar[bt] = 0;
return strWChar;
}
char *tempSrc = strChar;
wchar_t *tempDest = strWChar; wchar_t *tempDest = strWChar;
while((*tempDest++ = *tempSrc++)); while ((*tempDest++ = *strChar++));
return strWChar; return strWChar;
} }
uint16_t FreeTypeGX::loadFont(FT_Byte *fontBuffer, FT_Long bufferSize, FT_UInt pointSize, FT_Pos weight, uint32_t index, bool cacheAll) void FreeTypeGX::loadFont(const uint8_t* fontBuffer, FT_Long bufferSize, FT_Pos weight, bool lastFace)
{ {
this->unloadFont(); // lastFace is true for wii system font from buffer
this->ftPointSize = pointSize != 0 ? pointSize : this->ftPointSize; unloadFont();
this->ftWeight = weight; //ftPointSize = pointSize != 0 ? pointSize : ftPointSize;
ftWeight = weight;
// Check if the index is valid int faceIndex = 0;
if (index != 0) ftPointSize = 0;
// if we want the last face of the font use this to set faceIndex to the last face. then close ftface to reload it after the if with that faceIndex
if(lastFace)
{ {
FT_New_Memory_Face(this->ftLibrary, fontBuffer, bufferSize, -1, &this->ftFace); FT_New_Memory_Face(this->ftLibrary, (FT_Byte *)fontBuffer, bufferSize, -1, &this->ftFace);
if (index >= (uint32_t) this->ftFace->num_faces) faceIndex = this->ftFace->num_faces - 1; // Use the last face
index = this->ftFace->num_faces - 1; // Use the last face
FT_Done_Face(this->ftFace); FT_Done_Face(this->ftFace);
this->ftFace = NULL; this->ftFace = NULL;
} }
FT_New_Memory_Face(this->ftLibrary, fontBuffer, bufferSize, index, &this->ftFace); // load font face 0 or the last face available
FT_Set_Pixel_Sizes(this->ftFace, 0, this->ftPointSize); FT_New_Memory_Face(this->ftLibrary, (FT_Byte *) fontBuffer, bufferSize, faceIndex, &this->ftFace);
this->ftSlot = this->ftFace->glyph; ftKerningEnabled = false;//FT_HAS_KERNING(ftFace);
this->ftKerningEnabled = FT_HAS_KERNING(this->ftFace);
if (cacheAll)
return this->cacheGlyphDataComplete();
return 0;
} }
void FreeTypeGX::unloadFont() void FreeTypeGX::unloadFont()
{ {
if(this->fontData.size() == 0) if (this->fontData.size() == 0) return;
return;
std::map<wchar_t, ftgxCharData>::iterator itr; map<int16_t, map<wchar_t, ftgxCharData> >::iterator itr;
for(itr = this->fontData.begin(); itr != this->fontData.end(); itr++) map<wchar_t, ftgxCharData>::iterator itr2;
MEM2_free(itr->second.glyphDataTexture);
this->fontData.clear(); for (itr = fontData.begin(); itr != fontData.end(); itr++)
{
for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++)
MEM2_free(itr2->second.glyphDataTexture);
itr->second.clear();
}
fontData.clear();
ftgxAlign.clear();
} }
ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode) ftgxCharData * FreeTypeGX::cacheGlyphData(wchar_t charCode, int16_t pixelSize)
{ {
map<int16_t, map<wchar_t, ftgxCharData> >::iterator itr = fontData.find(pixelSize);
if (itr != fontData.end())
{
map<wchar_t, ftgxCharData>::iterator itr2 = itr->second.find(charCode);
if (itr2 != itr->second.end())
{
return &itr2->second;
}
}
FT_UInt gIndex; FT_UInt gIndex;
uint16_t textureWidth = 0, textureHeight = 0; uint16_t textureWidth = 0, textureHeight = 0;
gIndex = FT_Get_Char_Index( this->ftFace, charCode ); if (ftPointSize != pixelSize)
if(!FT_Load_Glyph(this->ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER))
{ {
if(this->ftSlot->format == FT_GLYPH_FORMAT_BITMAP) ftPointSize = pixelSize;
FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize);
//!Cache ascender and decender as well
map<int16_t, ftgxDataOffset>::iterator itrAlign = ftgxAlign.find(ftPointSize);
if (itrAlign == ftgxAlign.end())
{ {
FT_Bitmap *glyphBitmap = &this->ftSlot->bitmap; ftgxAlign[ftPointSize].ascender = (int16_t) ftFace->size->metrics.ascender >> 6;
FT_Bitmap_Embolden(this->ftLibrary, glyphBitmap, this->ftWeight, this->ftWeight); ftgxAlign[ftPointSize].descender = (int16_t) ftFace->size->metrics.descender >> 6;
ftgxAlign[ftPointSize].max = 0;
textureWidth = glyphBitmap->width % 8 == 0 ? glyphBitmap->width : 8 + glyphBitmap->width - (glyphBitmap->width % 8); ftgxAlign[ftPointSize].min = 0;
textureHeight = glyphBitmap->rows % 8 == 0 ? glyphBitmap->rows : 8 + glyphBitmap->rows - (glyphBitmap->rows % 8);
this->fontData[charCode] = (ftgxCharData)
{
(u16)(this->ftSlot->advance.x >> 6),
(u16)(gIndex),
textureWidth,
textureHeight,
(u16)(this->ftSlot->bitmap_top),
(u16)(this->ftSlot->bitmap_top),
(u16)(textureHeight - this->ftSlot->bitmap_top),
NULL
};
this->loadGlyphData(glyphBitmap, &this->fontData[charCode]);
return &this->fontData[charCode];
} }
} }
gIndex = FT_Get_Char_Index(ftFace, (FT_ULong) charCode);
if (gIndex != 0 && FT_Load_Glyph(ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER) == 0)
{
if (ftFace->glyph->format == FT_GLYPH_FORMAT_BITMAP)
{
FT_Bitmap *glyphBitmap = &ftFace->glyph->bitmap;
FT_Bitmap_Embolden(ftLibrary, glyphBitmap, ftWeight, ftWeight);
textureWidth = ALIGN8(glyphBitmap->width);
textureHeight = ALIGN8(glyphBitmap->rows);
if(textureWidth == 0)
textureWidth = 8;
if(textureHeight == 0)
textureHeight = 8;
fontData[pixelSize][charCode].renderOffsetX = (int16_t) ftFace->glyph->bitmap_left;
fontData[pixelSize][charCode].glyphAdvanceX = (uint16_t) (ftFace->glyph->advance.x >> 6);
fontData[pixelSize][charCode].glyphIndex = (uint32_t) gIndex;
fontData[pixelSize][charCode].textureWidth = (uint16_t) textureWidth;
fontData[pixelSize][charCode].textureHeight = (uint16_t) textureHeight;
fontData[pixelSize][charCode].renderOffsetY = (int16_t) ftFace->glyph->bitmap_top;
fontData[pixelSize][charCode].renderOffsetMax = (int16_t) ftFace->glyph->bitmap_top;
fontData[pixelSize][charCode].renderOffsetMin = (int16_t) glyphBitmap->rows - ftFace->glyph->bitmap_top;
fontData[pixelSize][charCode].glyphDataTexture = NULL;
loadGlyphData(glyphBitmap, &fontData[pixelSize][charCode]);
return &fontData[pixelSize][charCode];
}
}
return NULL; return NULL;
} }
uint16_t FreeTypeGX::cacheGlyphDataComplete() uint16_t FreeTypeGX::cacheGlyphDataComplete(int16_t pixelSize)
{ {
uint16_t i = 0; uint16_t i = 0;
FT_UInt gIndex; FT_UInt gIndex;
FT_ULong charCode = FT_Get_First_Char( this->ftFace, &gIndex ); FT_ULong charCode = FT_Get_First_Char(ftFace, &gIndex);
while( gIndex != 0 ) while(gIndex != 0)
{ {
if(this->cacheGlyphData(charCode) != NULL) if(cacheGlyphData(charCode, pixelSize) != NULL)
i++; ++i;
charCode = FT_Get_Next_Char(ftFace, charCode, &gIndex);
charCode = FT_Get_Next_Char( this->ftFace, charCode, &gIndex );
} }
return i; return i;
} }
@ -176,148 +218,217 @@ void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData)
charData->glyphDataTexture = glyphData; charData->glyphDataTexture = glyphData;
} }
uint16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) int16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format)
{ {
if (format & FTGX_JUSTIFY_LEFT ) if (format & FTGX_JUSTIFY_LEFT)
return 0; return 0;
else if (format & FTGX_JUSTIFY_CENTER ) else if (format & FTGX_JUSTIFY_CENTER)
return width >> 1; return width >> 1;
else if (format & FTGX_JUSTIFY_RIGHT ) else if (format & FTGX_JUSTIFY_RIGHT)
return width; return width;
return 0; return 0;
} }
uint16_t FreeTypeGX::getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format) int16_t FreeTypeGX::getStyleOffsetHeight(int16_t format, uint16_t pixelSize)
{ {
if (format & FTGX_ALIGN_TOP ) map<int16_t, ftgxDataOffset>::iterator itrAlign = ftgxAlign.find(pixelSize);
return -offset.max; if (itrAlign == ftgxAlign.end()) return 0;
else if (format & FTGX_ALIGN_MIDDLE )
return -(offset.max - offset.min) >> 1; switch (format & FTGX_ALIGN_MASK)
else if (format & FTGX_ALIGN_BOTTOM ) {
return offset.min; case FTGX_ALIGN_TOP:
return itrAlign->second.ascender;
case FTGX_ALIGN_MIDDLE:
default:
return (itrAlign->second.ascender + itrAlign->second.descender + 1) >> 1;
case FTGX_ALIGN_BOTTOM:
return itrAlign->second.descender;
case FTGX_ALIGN_BASELINE:
return 0;
case FTGX_ALIGN_GLYPH_TOP:
return itrAlign->second.max;
case FTGX_ALIGN_GLYPH_MIDDLE:
return (itrAlign->second.max + itrAlign->second.min + 1) >> 1;
case FTGX_ALIGN_GLYPH_BOTTOM:
return itrAlign->second.min;
}
return 0; return 0;
} }
uint16_t FreeTypeGX::drawText(uint16_t x, uint16_t y, const wchar_t *text, GXColor color, uint16_t textStyle) uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, const wchar_t *text, int16_t pixelSize, GXColor color,
uint16_t textStyle, uint16_t textWidth, uint16_t widthLimit)
{ {
uint16_t strLength = wcslen(text); if (!text) return 0;
uint16_t fullTextWidth = textWidth > 0 ? textWidth : getWidth(text, pixelSize);
uint16_t x_pos = x, printed = 0; uint16_t x_pos = x, printed = 0;
uint16_t x_offset = 0, y_offset = 0; uint16_t x_offset = 0, y_offset = 0;
GXTexObj glyphTexture; GXTexObj glyphTexture;
FT_Vector pairDelta; FT_Vector pairDelta;
if(textStyle & FTGX_JUSTIFY_MASK) if (textStyle & FTGX_JUSTIFY_MASK)
x_offset = this->getStyleOffsetWidth(this->getWidth(text), textStyle);
if(textStyle & FTGX_ALIGN_MASK)
y_offset = this->getStyleOffsetHeight(this->getOffset(text), textStyle);
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
for (uint16_t i = 0; i < strLength; i++)
{ {
ftgxCharData* glyphData = NULL; x_offset = getStyleOffsetWidth(fullTextWidth, textStyle);
if( this->fontData.find(text[i]) != this->fontData.end()) }
glyphData = &this->fontData[text[i]]; if (textStyle & FTGX_ALIGN_MASK)
else
glyphData = this->cacheGlyphData(text[i]);
if(glyphData != NULL)
{ {
y_offset = getStyleOffsetHeight(textStyle, pixelSize);
}
if(this->ftKerningEnabled && i) int i = 0;
while (text[i])
{ {
FT_Get_Kerning( this->ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); if (widthLimit > 0 && (x_pos - x) > widthLimit) break;
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
if (glyphData != NULL)
{
if (ftKerningEnabled && i > 0)
{
FT_Get_Kerning(ftFace, fontData[pixelSize][text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
x_pos += pairDelta.x >> 6; x_pos += pairDelta.x >> 6;
} }
// renderoffsety is to make sure short letters are not aligned with the top of tall letters.
// renderoffsetx is to properly space wide letters like w or short letters like j.
// x_offset and y_offset are used for justify x and align y the text.
// in wiiflow they are 0. getStyleOffsetWidth and getStyleOffsetHeight above are not called. wiiflow does style prior to calling drawText.
GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE); GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, GX_TF_I4, GX_CLAMP, GX_CLAMP, GX_FALSE);
this->copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos - x_offset, y - glyphData->renderOffsetY - y_offset, color); copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos + glyphData->renderOffsetX - x_offset, y - glyphData->renderOffsetY - y_offset, color);
x_pos += glyphData->glyphAdvanceX; x_pos += glyphData->glyphAdvanceX;
printed++; ++printed;
} }
++i;
} }
if(textStyle & FTGX_STYLE_MASK) if (textStyle & FTGX_STYLE_MASK)
this->drawTextFeature(x - x_offset, y, this->getWidth(text), this->getOffset(text), textStyle, color); {
getOffset(text, pixelSize, widthLimit);
drawTextFeature(x + x_offset, y + y_offset, pixelSize, fullTextWidth, &ftgxAlign[pixelSize], textStyle, color);
}
return printed; return printed;
} }
void FreeTypeGX::drawTextFeature(uint16_t x, uint16_t y, uint16_t width, ftgxDataOffset offsetData, uint16_t format, GXColor color) void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, int16_t pixelSize, uint16_t width,
ftgxDataOffset *offsetData, uint16_t format, GXColor color)
{ {
uint16_t featureHeight = this->ftPointSize >> 4 > 0 ? this->ftPointSize >> 4 : 1; uint16_t featureHeight = pixelSize >> 4 > 0 ? pixelSize >> 4 : 1;
if (format & FTGX_STYLE_UNDERLINE) if (format & FTGX_STYLE_UNDERLINE) this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color);
this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color);
if (format & FTGX_STYLE_STRIKE) if (format & FTGX_STYLE_STRIKE) this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData->max) >> 1), color);
this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max) >> 1), color);
} }
uint16_t FreeTypeGX::getWidth(const wchar_t *text) uint16_t FreeTypeGX::getWidth(const wchar_t *text, int16_t pixelSize)
{ {
uint16_t strLength = wcslen(text); if (!text) return 0;
uint16_t strWidth = 0; uint16_t strWidth = 0;
FT_Vector pairDelta; FT_Vector pairDelta;
for (uint16_t i = 0; i < strLength; i++) int i = 0;
while (text[i])
{ {
ftgxCharData* glyphData = NULL; ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
if( this->fontData.find(text[i]) != this->fontData.end())
glyphData = &this->fontData[text[i]]; if (glyphData != NULL)
else
glyphData = this->cacheGlyphData(text[i]);
if(glyphData != NULL)
{ {
if(this->ftKerningEnabled && (i > 0)) if (ftKerningEnabled && (i > 0))
{ {
FT_Get_Kerning( this->ftFace, this->fontData[text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); FT_Get_Kerning(ftFace, fontData[pixelSize][text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta);
strWidth += pairDelta.x >> 6; strWidth += pairDelta.x >> 6;
} }
strWidth += glyphData->glyphAdvanceX; strWidth += glyphData->glyphAdvanceX;
} }
++i;
}
return strWidth;
}
uint16_t FreeTypeGX::getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar)
{
uint16_t strWidth = 0;
ftgxCharData * glyphData = cacheGlyphData(wChar, pixelSize);
if (glyphData != NULL)
{
if (ftKerningEnabled && prevChar != 0x0000)
{
FT_Vector pairDelta;
FT_Get_Kerning(ftFace, fontData[pixelSize][prevChar].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT,
&pairDelta);
strWidth += pairDelta.x >> 6;
}
strWidth += glyphData->glyphAdvanceX;
} }
return strWidth; return strWidth;
} }
uint16_t FreeTypeGX::getHeight(const wchar_t *text) uint16_t FreeTypeGX::getHeight(const wchar_t *text, int16_t pixelSize)
{ {
ftgxDataOffset offset = this->getOffset(text); getOffset(text, pixelSize);
return offset.max + offset.min;
return ftgxAlign[pixelSize].max - ftgxAlign[pixelSize].min;
} }
ftgxDataOffset FreeTypeGX::getOffset(const wchar_t *text) void FreeTypeGX::getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit)
{ {
uint16_t strLength = wcslen(text); if (ftgxAlign.find(pixelSize) != ftgxAlign.end()) return;
uint16_t strMax = 0, strMin = 0;
for (uint16_t i = 0; i < strLength; i++) int16_t strMax = 0, strMin = 9999;
uint16_t currWidth = 0;
int i = 0;
while (text[i])
{ {
ftgxCharData* glyphData = NULL; if (widthLimit > 0 && currWidth >= widthLimit) break;
if( this->fontData.find(text[i]) != this->fontData.end())
glyphData = &this->fontData[text[i]];
else
glyphData = this->cacheGlyphData(text[i]);
if(glyphData != NULL) ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
if (glyphData != NULL)
{ {
strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax; strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax;
strMin = glyphData->renderOffsetMin > strMin ? glyphData->renderOffsetMin : strMin; strMin = glyphData->renderOffsetMin < strMin ? glyphData->renderOffsetMin : strMin;
currWidth += glyphData->glyphAdvanceX;
} }
++i;
} }
return (ftgxDataOffset){strMax, strMin};
if (ftPointSize != pixelSize)
{
ftPointSize = pixelSize;
FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize);
}
ftgxAlign[pixelSize].ascender = ftFace->size->metrics.ascender >> 6;
ftgxAlign[pixelSize].descender = ftFace->size->metrics.descender >> 6;
ftgxAlign[pixelSize].max = strMax;
ftgxAlign[pixelSize].min = strMin;
} }
void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, uint16_t texWidth, uint16_t texHeight, int16_t screenX, int16_t screenY, GXColor color) void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, uint16_t texWidth, uint16_t texHeight, int16_t screenX, int16_t screenY, GXColor color)
{ {
f32 f32TexWidth = texWidth, f32TexHeight = texHeight; f32 f32TexWidth = (float)texWidth;
f32 f32TexHeight = (float)texHeight;
float x = (float)screenX + xPos; float x = (float)screenX + xPos;
float y = (float)screenY + yPos; float y = (float)screenY + yPos;
GX_LoadTexObj(texObj, GX_TEXMAP0); GX_LoadTexObj(texObj, GX_TEXMAP0);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position3f32(x * xScale, y * yScale, 0); GX_Position3f32(x * xScale, y * yScale, 0);
@ -341,21 +452,22 @@ void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, uint16_t texWidth, u
void FreeTypeGX::copyFeatureToFramebuffer(uint16_t featureWidth, uint16_t featureHeight, int16_t screenX, int16_t screenY, GXColor color) void FreeTypeGX::copyFeatureToFramebuffer(uint16_t featureWidth, uint16_t featureHeight, int16_t screenX, int16_t screenY, GXColor color)
{ {
f32 f32FeatureWidth = featureWidth, f32FeatureHeight = featureHeight; f32 f32FeatureWidth = (float)featureWidth;
f32 f32FeatureHeight = (float)featureHeight;
float x = (float)screenX;// + xPos;
float y = (float)screenY;// + yPos;
GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position3f32(x, y, 0);
GX_Position3f32(screenX, screenY, 0);
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8(color.r, color.g, color.b, color.a);
GX_Position3f32(f32FeatureWidth + screenX, screenY, 0); GX_Position3f32(f32FeatureWidth + x, y, 0);
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8(color.r, color.g, color.b, color.a);
GX_Position3f32(f32FeatureWidth + screenX, f32FeatureHeight + screenY, 0); GX_Position3f32(f32FeatureWidth + x, f32FeatureHeight + y, 0);
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8(color.r, color.g, color.b, color.a);
GX_Position3f32(screenX, f32FeatureHeight + screenY, 0); GX_Position3f32(x, f32FeatureHeight + y, 0);
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8(color.r, color.g, color.b, color.a);
GX_End(); GX_End();
} }

View File

@ -33,34 +33,43 @@
#include <wchar.h> #include <wchar.h>
#include <map> #include <map>
typedef struct ftgxCharData_ { typedef struct ftgxCharData_
{
int16_t renderOffsetX; /**< Texture X axis bearing offset. */
uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */ uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */
uint16_t glyphIndex; /**< Charachter glyph index in the font face. */ uint32_t glyphIndex; /**< Charachter glyph index in the font face. */
uint16_t textureWidth; /**< Texture width in pixels/bytes. */ uint16_t textureWidth; /**< Texture width in pixels/bytes. */
uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */ uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */
uint16_t renderOffsetY; /**< Texture Y axis bearing offset. */ int16_t renderOffsetY; /**< Texture Y axis bearing offset. */
uint16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */ int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */
uint16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */ int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */
uint8_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */ uint8_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */
} ftgxCharData; } ftgxCharData;
typedef struct ftgxDataOffset_ { typedef struct ftgxDataOffset_
uint16_t max; /**< Maximum data offset. */ {
uint16_t min; /**< Minimum data offset. */ int16_t ascender; /**< Maximum data offset. */
int16_t descender; /**< Minimum data offset. */
int16_t max; /**< Maximum data offset. */
int16_t min; /**< Minimum data offset. */
} ftgxDataOffset; } ftgxDataOffset;
#define FTGX_NULL 0x0000 #define FTGX_NULL 0x0000
#define FTGX_JUSTIFY_LEFT 0x0001 #define FTGX_JUSTIFY_LEFT 0x0001 //0001
#define FTGX_JUSTIFY_CENTER 0x0002 #define FTGX_JUSTIFY_CENTER 0x0002 //0010
#define FTGX_JUSTIFY_RIGHT 0x0004 #define FTGX_JUSTIFY_RIGHT 0x0004 //0100
#define FTGX_JUSTIFY_MASK 0x000f #define FTGX_JUSTIFY_MASK 0x000f //1111
#define FTGX_ALIGN_TOP 0x0010 #define FTGX_ALIGN_TOP 0x0010
#define FTGX_ALIGN_MIDDLE 0x0020 #define FTGX_ALIGN_MIDDLE 0x0020
#define FTGX_ALIGN_BOTTOM 0x0040 #define FTGX_ALIGN_BOTTOM 0x0040
#define FTGX_ALIGN_BASELINE 0x0080
#define FTGX_ALIGN_GLYPH_TOP 0x0100
#define FTGX_ALIGN_GLYPH_MIDDLE 0x0200
#define FTGX_ALIGN_GLYPH_BOTTOM 0x0400
#define FTGX_ALIGN_MASK 0x0ff0 #define FTGX_ALIGN_MASK 0x0ff0
#define FTGX_STYLE_UNDERLINE 0x1000 #define FTGX_STYLE_UNDERLINE 0x1000
@ -74,28 +83,31 @@ class FreeTypeGX {
private: private:
FT_Library ftLibrary; /**< FreeType FT_Library instance. */ FT_Library ftLibrary; /**< FreeType FT_Library instance. */
FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */ FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */ //FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */
FT_UInt ftPointSize; /**< Requested size of the rendered font. */ int16_t ftPointSize; /**< Requested size of the rendered font. */
FT_Pos ftWeight; /**< Requested weight of the rendered font. */ FT_Pos ftWeight; /**< Requested weight of the rendered font. */
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */ bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
float xScale; float xScale;
float yScale; float yScale;
float xPos; float xPos;
float yPos; float yPos;
std::map<wchar_t, ftgxCharData> fontData; /**< Map which holds the glyph data structures for the corresponding characters. */ std::map<int16_t, std::map<wchar_t, ftgxCharData> > fontData; /**< Map which holds the glyph data structures for the corresponding characters in one size. */
std::map<int16_t, ftgxDataOffset> ftgxAlign; /**< Map which holds the ascender and decender for different sizes. */
static uint16_t getStyleOffsetWidth(uint16_t width, uint16_t format); int16_t getStyleOffsetWidth(uint16_t width, uint16_t format);
static uint16_t getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format); int16_t getStyleOffsetHeight(int16_t format, uint16_t pixelSize);
void copyTextureToFramebuffer(GXTexObj *texObj, uint16_t texWidth, uint16_t texHeight, int16_t screenX, int16_t screenY, GXColor color);
void copyFeatureToFramebuffer(uint16_t featureWidth, uint16_t featureHeight, int16_t screenX, int16_t screenY, GXColor color);
void unloadFont(); void unloadFont();
ftgxCharData *cacheGlyphData(wchar_t charCode); ftgxCharData *cacheGlyphData(wchar_t charCode, int16_t pixelSize);
uint16_t cacheGlyphDataComplete(); uint16_t cacheGlyphDataComplete(int16_t pixelSize);
void loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData); void loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData);
void drawTextFeature(uint16_t x, uint16_t y, uint16_t width, ftgxDataOffset offsetData, uint16_t format, GXColor color);
void drawTextFeature(int16_t x, int16_t y, int16_t pixelSize, uint16_t width,
ftgxDataOffset *offsetData, uint16_t format, GXColor color);
void copyTextureToFramebuffer(GXTexObj *texObj, uint16_t texWidth, uint16_t texHeight, int16_t screenX, int16_t screenY, GXColor color);
void copyFeatureToFramebuffer(uint16_t featureWidth, uint16_t featureHeight, int16_t screenX, int16_t screenY, GXColor color);
public: public:
FreeTypeGX(); FreeTypeGX();
@ -103,13 +115,15 @@ class FreeTypeGX {
static wchar_t* charToWideChar(char* p); static wchar_t* charToWideChar(char* p);
uint16_t loadFont(FT_Byte *fontBuffer, FT_Long bufferSize, FT_UInt pointSize, FT_Pos weight = 0, uint32_t index = 0, bool cacheAll = false); void loadFont(const uint8_t* fontBuffer, FT_Long bufferSize, FT_Pos weight = 0, bool lastFace = false);
uint16_t drawText(uint16_t x, uint16_t y, const wchar_t *text, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL); uint16_t drawText(int16_t x, int16_t y, const wchar_t *text, int16_t pixelSize, GXColor color = ftgxWhite,
uint16_t textStyling = FTGX_NULL, uint16_t textWidth = 0, uint16_t widthLimit = 0);
uint16_t getWidth(const wchar_t *text); uint16_t getWidth(const wchar_t *text, int16_t pixelSize);
uint16_t getHeight(const wchar_t *text); uint16_t getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar = 0x0000);
ftgxDataOffset getOffset(const wchar_t *text); uint16_t getHeight(const wchar_t *text, int16_t pixelSize);
void getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit = 0);
float getXScale(void) const { return xScale; } float getXScale(void) const { return xScale; }
float getYScale(void) const { return yScale; } float getYScale(void) const { return yScale; }

View File

@ -1176,7 +1176,11 @@ void CCoverFlow::_drawTitle(int i, bool mirror, bool rectangle)
if (m_covers[i].txtColor == 0) return; if (m_covers[i].txtColor == 0) return;
color.a = mirror ? (u8)((float)m_covers[i].txtColor * m_txtMirrorAlpha) : m_covers[i].txtColor; color.a = mirror ? (u8)((float)m_covers[i].txtColor * m_txtMirrorAlpha) : m_covers[i].txtColor;
if (rectangle && !mirror)// rectangle (mainloop adjusting) is never set true
// rectangle is never used. in menu.cpp _mainLoopCommon() adjusting is never set true
// but if it would be. rectangle is the same as using a frame for the text as when the gui draws a label.
// when using a frame the text style is used. otherwise it is not used.
if (rectangle && !mirror)
{ {
// GX setup // GX setup
GX_SetNumTevStages(1); GX_SetNumTevStages(1);

View File

@ -748,8 +748,8 @@ void CButtonsMgr::_drawBtn(CButtonsMgr::SButton &b, bool selected, bool click)
if (!b.font.font) return; if (!b.font.font) return;
b.font.font->reset(); b.font.font->reset();
//CColor txtColor(b.textColor.r, b.textColor.g, b.textColor.b, (u8)((int)b.textColor.a * (int)alpha / 0xFF)); //CColor txtColor(b.textColor.r, b.textColor.g, b.textColor.b, (u8)((int)b.textColor.a * (int)alpha / 0xFF));
if(m_vid.wide()) //if(m_vid.wide())
scaleX *= 0.8f; // scaleX *= 0.8f;
b.font.font->setXScale(scaleX); b.font.font->setXScale(scaleX);
b.font.font->setYScale(scaleY); b.font.font->setYScale(scaleY);
//b.font.font->drawText(0, 0, b.text.c_str(), txtColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE); //b.font.font->drawText(0, 0, b.text.c_str(), txtColor, FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE);
@ -797,8 +797,8 @@ void CButtonsMgr::_drawLbl(CButtonsMgr::SLabel &b)
b.font.font->reset(); b.font.font->reset();
b.text.setColor(CColor(b.textColor.r, b.textColor.g, b.textColor.b, (u8)((int)b.textColor.a * (int)alpha / 0xFF))); b.text.setColor(CColor(b.textColor.r, b.textColor.g, b.textColor.b, (u8)((int)b.textColor.a * (int)alpha / 0xFF)));
if(m_vid.wide()) //if(m_vid.wide())
scaleX *= 0.8f; // scaleX *= 0.8f;
b.font.font->setXScale(scaleX); b.font.font->setXScale(scaleX);
b.font.font->setYScale(scaleY); b.font.font->setYScale(scaleY);
float posX = b.pos.x; float posX = b.pos.x;

View File

@ -171,7 +171,7 @@ bool SFont::fromBuffer(const u8 *buffer, const u32 bufferSize, u32 size, u32 lsp
fSize = min(max(6ul, size), 1000ul); fSize = min(max(6ul, size), 1000ul);
lineSpacing = min(max(6ul, lspacing), 1000ul); lineSpacing = min(max(6ul, lspacing), 1000ul);
weight = min(w, 32ul); weight = min(w, 32ul);
index = idx; index = idx;// currently not used
if(data != NULL) if(data != NULL)
free(data); free(data);
@ -184,7 +184,7 @@ bool SFont::fromBuffer(const u8 *buffer, const u32 bufferSize, u32 size, u32 lsp
memcpy(name, fontname, 127); memcpy(name, fontname, 127);
font = new FreeTypeGX(); font = new FreeTypeGX();
font->loadFont(data, dataSize, fSize, weight, index, false); font->loadFont(data, dataSize, weight, true);
return true; return true;
} }
@ -192,7 +192,7 @@ bool SFont::fromFile(const char *path, u32 size, u32 lspacing, u32 w, u32 idx, c
{ {
fSize = min(max(6ul, size), 1000ul); fSize = min(max(6ul, size), 1000ul);
weight = min(w, 32ul); weight = min(w, 32ul);
index = idx = 0; index = idx;// currently not used
lineSpacing = min(max(6ul, lspacing), 1000ul); lineSpacing = min(max(6ul, lspacing), 1000ul);
@ -206,11 +206,11 @@ bool SFont::fromFile(const char *path, u32 size, u32 lspacing, u32 w, u32 idx, c
memcpy(name, fontname, 127); memcpy(name, fontname, 127);
font = new FreeTypeGX(); font = new FreeTypeGX();
font->loadFont(data, dataSize, fSize, weight, index, false); font->loadFont(data, dataSize, weight, false);
return true; return true;
} }
static const wchar_t *g_whitespaces = L" \f\n\r\t\v"; static const wchar_t *g_whitespaces = L" \f\n\r\t\v";// notice the first character is a space
void CText::setText(const SFont &font, const wstringEx &t) void CText::setText(const SFont &font, const wstringEx &t)
{ {
SWord w; SWord w;
@ -232,18 +232,18 @@ void CText::setText(const SFont &font, const wstringEx &t)
wstringEx::size_type j; wstringEx::size_type j;
while (i != wstringEx::npos) while (i != wstringEx::npos)
{ {
j = l.find_first_of(g_whitespaces, i); j = l.find_first_of(g_whitespaces, i);// find a space or end of line character
if (j != wstringEx::npos && j > i) if (j != wstringEx::npos && j > i)
{ {
w.text.assign(l, i, j - i); w.text.assign(l, i, j - i);
m_lines.back().push_back(w); m_lines.back().push_back(w);
i = l.find_first_not_of(g_whitespaces, j); i = l.find_first_not_of(g_whitespaces, j);
} }
else if (j == wstringEx::npos) else if (j == wstringEx::npos)// if end of line
{ {
w.text.assign(l, i, l.size() - i); w.text.assign(l, i, l.size() - i);
m_lines.back().push_back(w); m_lines.back().push_back(w);
i = wstringEx::npos; i = wstringEx::npos;// or could just break;
} }
} }
} }
@ -298,7 +298,7 @@ void CText::setFrame(float width, u16 style, bool ignoreNewlines, bool instant)
float shift; float shift;
totalHeight = 0; totalHeight = 0;
float space = m_font.font->getWidth(L" "); float space = m_font.font->getWidth(L" ", m_font.fSize);//
float posX = 0.f; float posX = 0.f;
float posY = 0.f; float posY = 0.f;
u32 lineBeg = 0; u32 lineBeg = 0;
@ -316,7 +316,7 @@ void CText::setFrame(float width, u16 style, bool ignoreNewlines, bool instant)
for (u32 i = 0; i < words.size(); ++i) for (u32 i = 0; i < words.size(); ++i)
{ {
float wordWidth = m_font.font->getWidth(words[i].text.c_str()); float wordWidth = m_font.font->getWidth(words[i].text.c_str(), m_font.fSize);//
if (posX == 0.f || posX + (float)wordWidth + space * 2 <= width) if (posX == 0.f || posX + (float)wordWidth + space * 2 <= width)
{ {
words[i].targetPos = Vector3D(posX, posY, 0.f); words[i].targetPos = Vector3D(posX, posY, 0.f);
@ -370,10 +370,11 @@ void CText::setColor(const CColor &c)
m_color = c; m_color = c;
} }
/* moves each word of each line of text from current pos to targetPos */
void CText::tick(void) void CText::tick(void)
{ {
for (u32 k = 0; k < m_lines.size(); ++k) for (u32 k = 0; k < m_lines.size(); ++k)// lines of text
for (u32 i = 0; i < m_lines[k].size(); ++i) for (u32 i = 0; i < m_lines[k].size(); ++i)// number of words per line[k]
m_lines[k][i].pos += (m_lines[k][i].targetPos - m_lines[k][i].pos) * 0.05f; m_lines[k][i].pos += (m_lines[k][i].targetPos - m_lines[k][i].pos) * 0.05f;
} }
@ -387,7 +388,7 @@ void CText::draw(void)
{ {
m_font.font->setX(m_lines[k][i].pos.x); m_font.font->setX(m_lines[k][i].pos.x);
m_font.font->setY(m_lines[k][i].pos.y); m_font.font->setY(m_lines[k][i].pos.y);
m_font.font->drawText(0, m_font.lineSpacing, m_lines[k][i].text.c_str(), m_color); m_font.font->drawText(0, m_font.lineSpacing, m_lines[k][i].text.c_str(), m_font.fSize, m_color);
} }
} }

View File

@ -171,8 +171,9 @@ void CVideo::init(void)
GX_SetDispCopyDst(m_rmode->fbWidth, m_xfbHeight); GX_SetDispCopyDst(m_rmode->fbWidth, m_xfbHeight);
GX_SetCopyFilter(m_rmode->aa, m_rmode->sample_pattern, GX_TRUE, m_rmode->vfilter); GX_SetCopyFilter(m_rmode->aa, m_rmode->sample_pattern, GX_TRUE, m_rmode->vfilter);
GX_SetFieldMode(m_rmode->field_rendering, ((m_rmode->viHeight == 2 * m_rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); GX_SetFieldMode(m_rmode->field_rendering, ((m_rmode->viHeight == 2 * m_rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
GX_SetCullMode(GX_CULL_NONE); GX_SetCullMode(GX_CULL_NONE);
GX_CopyDisp(m_frameBuf[m_curFB], GX_TRUE); //GX_CopyDisp(m_frameBuf[m_curFB], GX_TRUE);
GX_SetDispCopyGamma(GX_GM_1_0); GX_SetDispCopyGamma(GX_GM_1_0);
GX_ClearVtxDesc(); GX_ClearVtxDesc();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
@ -251,7 +252,11 @@ void CVideo::_clearScreen()
void CVideo::prepare(void) void CVideo::prepare(void)
{ {
if (m_rmode->aa)
GX_SetPixelFmt(GX_PF_RGBA6_Z24, GX_ZC_LINEAR);
else
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
//GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
_setViewPort(0.f, 0.f, (float)m_rmode->fbWidth, (float)m_rmode->efbHeight); _setViewPort(0.f, 0.f, (float)m_rmode->fbWidth, (float)m_rmode->efbHeight);
GX_SetScissor(0, 0, m_rmode->fbWidth, m_rmode->efbHeight); GX_SetScissor(0, 0, m_rmode->fbWidth, m_rmode->efbHeight);
GX_InvVtxCache(); GX_InvVtxCache();
@ -454,11 +459,11 @@ void CVideo::renderAAPass(int aaStep)
void CVideo::render(void) void CVideo::render(void)
{ {
GX_DrawDone();
GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_TRUE); GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_TRUE);
GX_SetColorUpdate(GX_TRUE); GX_SetColorUpdate(GX_TRUE);
GX_CopyDisp(MEM_K1_TO_K0(m_frameBuf[m_curFB]), GX_TRUE); GX_CopyDisp(MEM_K1_TO_K0(m_frameBuf[m_curFB]), GX_TRUE);
DCFlushRange(m_frameBuf[m_curFB], 2 * m_rmode->fbWidth * m_rmode->xfbHeight); DCFlushRange(m_frameBuf[m_curFB], 2 * m_rmode->fbWidth * m_rmode->xfbHeight);
GX_DrawDone();
VIDEO_SetNextFramebuffer(m_frameBuf[m_curFB]); VIDEO_SetNextFramebuffer(m_frameBuf[m_curFB]);
VIDEO_Flush(); VIDEO_Flush();
VIDEO_WaitVSync(); VIDEO_WaitVSync();
@ -774,6 +779,7 @@ void DrawTexturePos(const TexData *tex)
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0);
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
GX_SetNumTexGens(1); GX_SetNumTexGens(1);
GX_SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC); GX_SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
GX_SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GX_SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
@ -783,10 +789,13 @@ void DrawTexturePos(const TexData *tex)
GX_SetAlphaUpdate(GX_FALSE); GX_SetAlphaUpdate(GX_FALSE);
GX_SetCullMode(GX_CULL_NONE); GX_SetCullMode(GX_CULL_NONE);
GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_FALSE); GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_FALSE);
guMtxIdentity(modelViewMtx); guMtxIdentity(modelViewMtx);
GX_LoadPosMtxImm(modelViewMtx, GX_PNMTX0); GX_LoadPosMtxImm(modelViewMtx, GX_PNMTX0);
GX_InitTexObj(&texObj, tex->data, tex->width, tex->height, tex->format, GX_CLAMP, GX_CLAMP, GX_FALSE); GX_InitTexObj(&texObj, tex->data, tex->width, tex->height, tex->format, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_LoadTexObj(&texObj, GX_TEXMAP0); GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position2f32(currentMoviePos.x1, currentMoviePos.y1); GX_Position2f32(currentMoviePos.x1, currentMoviePos.y1);
GX_TexCoord2f32(0.f, 0.f); GX_TexCoord2f32(0.f, 0.f);

View File

@ -88,7 +88,7 @@ void Sys_ExitTo(int option)
*Priiloader_CFG1 = 0x4461636F;// Daco *Priiloader_CFG1 = 0x4461636F;// Daco
*Priiloader_CFG2 = 0x4461636F; *Priiloader_CFG2 = 0x4461636F;
} }
else else // PRIILOADER_DEF
{ {
*Priiloader_CFG1 = 0xFFFFFFFF; *Priiloader_CFG1 = 0xFFFFFFFF;
*Priiloader_CFG2 = 0xFFFFFFFF; *Priiloader_CFG2 = 0xFFFFFFFF;
@ -99,17 +99,15 @@ void Sys_ExitTo(int option)
void Sys_Exit(void) void Sys_Exit(void)
{ {
//if(ExitOption == EXIT_TO_DISABLE)
// return;
/* Shutdown Inputs */ /* Shutdown Inputs */
Close_Inputs(); Close_Inputs();
/* Just shutdown console*/ /* Just shutdown console*/
if(ExitOption == BUTTON_CALLBACK) if(ExitOption == BUTTON_CALLBACK)
SYS_ResetSystem(SYS_POWEROFF_STANDBY, 0, 0); SYS_ResetSystem(SYS_POWEROFF_STANDBY, 0, 0);
/* We wanna to boot sth */ /* We wanna to boot something */
WII_Initialize(); WII_Initialize();
/* if in neek2o mode Launch_nk will just return to neek2o system menu and not launch anything */
if(ExitOption == EXIT_TO_WFNK2O) if(ExitOption == EXIT_TO_WFNK2O)
Launch_nk(0x1000157464C41LL, NeekPath, 0);// 57464C41 = WFLA : 44574641 = DWFA Launch_nk(0x1000157464C41LL, NeekPath, 0);// 57464C41 = WFLA : 44574641 = DWFA
else if(ExitOption == EXIT_TO_SMNK2O) else if(ExitOption == EXIT_TO_SMNK2O)
@ -126,7 +124,7 @@ void Sys_Exit(void)
} }
else if(ExitOption == EXIT_TO_WIIU) else if(ExitOption == EXIT_TO_WIIU)
WII_LaunchTitle(WIIU_CHANNEL); WII_LaunchTitle(WIIU_CHANNEL);
/* else Return to Menu */ /* else Return to System Menu */
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
exit(1); exit(1);
} }
@ -154,14 +152,18 @@ bool AHBPROT_Patched(void)
} }
/* WiiU Check by crediar, thanks */ /* WiiU Check by crediar, thanks */
bool WiiUChecked = false;
bool WiiUMode = false;
bool IsOnWiiU(void) bool IsOnWiiU(void)
{ {
if(WiiUChecked)
return WiiUMode;
if((*HW_PROCESSOR >> 16) == 0xCAFE) if((*HW_PROCESSOR >> 16) == 0xCAFE)
{ WiiUMode = true;
gprintf("vWii Mode\n");
return true; WiiUChecked = true;
} return WiiUMode;
return false;
} }
void Sys_SetNeekPath(const char *Path) void Sys_SetNeekPath(const char *Path)
@ -205,15 +207,10 @@ bool Sys_DolphinMode(void)
); );
if(ofpr1 != 0x56cc62b2) if(ofpr1 != 0x56cc62b2)
{
gprintf("Dolphin-Emu\n");
DolphinMode = true; DolphinMode = true;
}
else else
{
gprintf("Real Wii\n");
DolphinMode = false; DolphinMode = false;
}
ModeChecked = true; ModeChecked = true;
return DolphinMode; return DolphinMode;
} }
@ -225,7 +222,6 @@ bool Sys_HW_Access(void)
if(hw_checked == true) if(hw_checked == true)
return on_hw; return on_hw;
check_neek2o();
on_hw = AHBPROT_Patched() && (!Sys_DolphinMode() && !neek2o()); on_hw = AHBPROT_Patched() && (!Sys_DolphinMode() && !neek2o());
hw_checked = true; hw_checked = true;
return on_hw; return on_hw;

View File

@ -19,17 +19,16 @@ extern "C" {
enum enum
{ {
PRIILOADER_DEF = 0, EXIT_TO_MENU = 0,
EXIT_TO_MENU,
EXIT_TO_HBC, EXIT_TO_HBC,
EXIT_TO_WIIU, EXIT_TO_WIIU,
PRIILOADER_DEF,
EXIT_TO_PRIILOADER, EXIT_TO_PRIILOADER,
//EXIT_TO_DISABLE,
EXIT_TO_BOOTMII, EXIT_TO_BOOTMII,
EXIT_TO_WFNK2O, EXIT_TO_WFNK2O,
EXIT_TO_SMNK2O, EXIT_TO_SMNK2O,
BUTTON_CALLBACK, BUTTON_CALLBACK,
WIIFLOW_DEF, WIIFLOW_DEF,// m_cfg.getInt("GENERAL", "exit_to", 0). (EXIT_TO_MENU, EXIT_TO_HBC, EXIT_TO_WIIU)
}; };
/* Prototypes */ /* Prototypes */

View File

@ -25,6 +25,56 @@ bool useMainIOS = false;
volatile bool NANDemuView = false; volatile bool NANDemuView = false;
volatile bool networkInit = false; volatile bool networkInit = false;
/* quick check if we will be using a USB device. */
/* if not then we can skip the 20 second cycle trying to connect a USB device. */
/* this is nice for SD only users */
bool isUsingUSB() {
/* First check if the app path exists on the SD card, if not then we're using USB */
struct stat dummy;
string appPath = fmt("%s:/%s", DeviceName[SD], APPS_DIR);
if(DeviceHandle.IsInserted(SD) && DeviceHandle.GetFSType(SD) != PART_FS_WBFS && stat(appPath.c_str(), &dummy) != 0)
{
// No app path exists on SD card, so assuming we're using USB.
return true;
}
/* Check that the config file exists, or we can't do the following checks */
string configPath = fmt("%s/" CFG_FILENAME, appPath.c_str());
if(stat(configPath.c_str(), &dummy) != 0)
{
// The app path is on SD but no config file exists, so assuming we might need USB.
return true;
}
/* Load the config file */
Config m_cfg;// = new Config();
if(!m_cfg.load(configPath.c_str()))
{
// The app path is on SD and a config file exists, but we can't load it, so assuming we might need USB.
return true;
}
/* If we have the WiiFlow data on USB, then we're using USB */
if(m_cfg.getBool("general", "data_on_usb", false))
{
// data_on_usb is true, so assuming we're using USB.
return true;
}
/* If any of the sections have partition set > 0, we're on USB */
const char *domains[] = {WII_DOMAIN, GC_DOMAIN, CHANNEL_DOMAIN, PLUGIN_DOMAIN, HOMEBREW_DOMAIN};
for(int i = 0; i < 5; i++)
{
if(!m_cfg.getBool(domains[i], "disable", false) && m_cfg.getInt(domains[i], "partition", SD) != SD)
{
// a domain is enabled and partition is not SD, so assuming we're using USB.
return true;
}
}
gprintf("using SD only, no need for USB mounting.\n");
return false;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
MEM_init(); //Inits both mem1lo and mem2 MEM_init(); //Inits both mem1lo and mem2
@ -36,7 +86,6 @@ int main(int argc, char **argv)
bool iosOK = true; bool iosOK = true;
char *gameid = NULL; char *gameid = NULL;
bool showFlashImg = true; bool showFlashImg = true;
bool sd_only = false;
bool wait_loop = false; bool wait_loop = false;
char wait_dir[256]; char wait_dir[256];
memset(&wait_dir, 0, sizeof(wait_dir)); memset(&wait_dir, 0, sizeof(wait_dir));
@ -59,8 +108,6 @@ int main(int argc, char **argv)
wait_loop = true; wait_loop = true;
else if(strcasestr(argv[i], "noflash") != NULL) else if(strcasestr(argv[i], "noflash") != NULL)
showFlashImg = false; showFlashImg = false;
else if(strcasestr(argv[i], "sdonly") != NULL)
sd_only = true;
else if(strlen(argv[i]) == 6) else if(strlen(argv[i]) == 6)
{ {
gameid = argv[i]; gameid = argv[i];
@ -72,6 +119,13 @@ int main(int argc, char **argv)
} }
} }
if(Sys_DolphinMode())
gprintf("Dolphin-Emu\n");
else if(IsOnWiiU())
gprintf("vWii Mode\n");
else
gprintf("Real Wii\n");
/* Init video */ /* Init video */
m_vid.init(); m_vid.init();
if(showFlashImg) if(showFlashImg)
@ -98,14 +152,13 @@ int main(int argc, char **argv)
else if(useMainIOS && CustomIOS(IOS_GetType(mainIOS))) /* Requested */ else if(useMainIOS && CustomIOS(IOS_GetType(mainIOS))) /* Requested */
iosOK = loadIOS(mainIOS, false) && CustomIOS(CurrentIOS.Type); iosOK = loadIOS(mainIOS, false) && CustomIOS(CurrentIOS.Type);
/* set reset and power button callbacks and exitTo option */ /* sys inits */
Sys_Init(); Sys_Init();// set reset and power button callbacks
Sys_ExitTo(EXIT_TO_HBC); Sys_ExitTo(EXIT_TO_HBC);// set exit to in case of failed launch
/* mount Devices */ /* mount Devices */
DeviceHandle.MountSD(); DeviceHandle.SetMountUSB(isUsingUSB());
if(!sd_only && !Sys_DolphinMode()) DeviceHandle.MountAll();
DeviceHandle.MountAllUSB();
/* init wait images and show wait animation */ /* init wait images and show wait animation */
m_vid.setCustomWaitImgs(wait_dir, wait_loop); m_vid.setCustomWaitImgs(wait_dir, wait_loop);

View File

@ -175,7 +175,7 @@ bool CMenu::init()
m_cfg.setBool("GENERAL", "data_on_usb", true); m_cfg.setBool("GENERAL", "data_on_usb", true);
} }
} }
else // onUSB = true if(onUSB)
{ {
for(u8 i = USB1; i <= USB8; i++) //Look for first partition with a wiiflow folder in root for(u8 i = USB1; i <= USB8; i++) //Look for first partition with a wiiflow folder in root
{ {
@ -438,12 +438,10 @@ bool CMenu::init()
if(m_cfg.getString("GENERAL", "returnto", "WFLA") == "DWFA") if(m_cfg.getString("GENERAL", "returnto", "WFLA") == "DWFA")
m_cfg.setString("GENERAL", "returnto", "WFLA"); m_cfg.setString("GENERAL", "returnto", "WFLA");
int exit_to = m_cfg.getInt("GENERAL", "exit_to", 0); /* set WIIFLOW_DEF exit to option */
if(exit_to == EXIT_TO_BOOTMII && (!DeviceHandle.IsInserted(SD) || /* 0 thru 2 of exit to enum (EXIT_TO_MENU, EXIT_TO_HBC, EXIT_TO_WIIU) in sys.h */
stat(fmt("%s:/bootmii/armboot.bin",DeviceName[SD]), &dummy) != 0 || int exit_to = min(max(0, m_cfg.getInt("GENERAL", "exit_to", 0)), (int)ARRAY_SIZE(CMenu::_exitTo) - 1);
stat(fmt("%s:/bootmii/ppcboot.elf", DeviceName[SD]), &dummy) != 0)) Sys_ExitTo(exit_to);
exit_to = EXIT_TO_HBC;
Sys_ExitTo(exit_to + 1);
LWP_MutexInit(&m_mutex, 0); LWP_MutexInit(&m_mutex, 0);
@ -607,7 +605,7 @@ void CMenu::_Theme_Cleanup(void)
theme.texSet.clear(); theme.texSet.clear();
theme.fontSet.clear(); theme.fontSet.clear();
theme.soundSet.clear(); theme.soundSet.clear();
m_theme.unload(); //m_theme.unload();
m_coverflow.unload(); m_coverflow.unload();
} }
@ -1302,6 +1300,7 @@ void CMenu::_buildMenus(void)
_initPathsMenu(); _initPathsMenu();
_loadCFCfg(); _loadCFCfg();
m_theme.unload();// done with theme.ini so lets unload it from mem
} }
typedef struct typedef struct
@ -1315,6 +1314,7 @@ typedef struct
SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSpacing, u32 weight, u32 index, const char *genKey) SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSpacing, u32 weight, u32 index, const char *genKey)
{ {
/* get font info from theme.ini or use the default values */
string filename; string filename;
bool general = strncmp(domain, "GENERAL", 7) == 0; bool general = strncmp(domain, "GENERAL", 7) == 0;
FontHolder fonts[3] = {{ "_size", 6u, 300u, fontSize, 0 }, { "_line_height", 6u, 300u, lineSpacing, 0 }, { "_weight", 1u, 32u, weight, 0 }}; FontHolder fonts[3] = {{ "_size", 6u, 300u, fontSize, 0 }, { "_line_height", 6u, 300u, lineSpacing, 0 }, { "_weight", 1u, 32u, weight, 0 }};
@ -1325,12 +1325,13 @@ SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSp
filename = m_theme.getString("GENERAL", genKey, genKey); filename = m_theme.getString("GENERAL", genKey, genKey);
bool useDefault = filename == genKey; bool useDefault = filename == genKey;
/* get the resources - fontSize, lineSpacing, and weight */
for(u32 i = 0; i < 3; i++) for(u32 i = 0; i < 3; i++)
{ {
string defValue = genKey; string defValue = genKey;
defValue += fonts[i].ext; defValue += fonts[i].ext;// _size, _line_height, _weight
string value = key; string value = key;
value += fonts[i].ext; value += fonts[i].ext;// _size, _line_height, _weight
if(!general) if(!general)
fonts[i].res = (u32)m_theme.getInt(domain, value); fonts[i].res = (u32)m_theme.getInt(domain, value);
@ -1340,7 +1341,9 @@ SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSp
fonts[i].res = min(max(fonts[i].min, fonts[i].res <= 0 ? fonts[i].def : fonts[i].res), fonts[i].max); fonts[i].res = min(max(fonts[i].min, fonts[i].res <= 0 ? fonts[i].def : fonts[i].res), fonts[i].max);
} }
/* ONLY return the font if spacing and weight are the same */ /* check if font is already in memory */
/* and the filename, size, spacing, and weight are the same */
/* if so return this font */
std::vector<SFont>::iterator font_itr; std::vector<SFont>::iterator font_itr;
for(font_itr = theme.fontSet.begin(); font_itr != theme.fontSet.end(); ++font_itr) for(font_itr = theme.fontSet.begin(); font_itr != theme.fontSet.end(); ++font_itr)
{ {
@ -1350,7 +1353,8 @@ SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSp
} }
if (font_itr != theme.fontSet.end()) return *font_itr; if (font_itr != theme.fontSet.end()) return *font_itr;
// TTF not found in memory, load it to create a new font /* font not found in memory, load it to create a new font */
/* unless useDefault font is specified */
SFont retFont; SFont retFont;
if(!useDefault && retFont.fromFile(fmt("%s/%s", m_themeDataDir.c_str(), filename.c_str()), fonts[0].res, fonts[1].res, fonts[2].res, index, filename.c_str())) if(!useDefault && retFont.fromFile(fmt("%s/%s", m_themeDataDir.c_str(), filename.c_str()), fonts[0].res, fonts[1].res, fonts[2].res, index, filename.c_str()))
{ {
@ -1358,6 +1362,7 @@ SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSp
theme.fontSet.push_back(retFont); theme.fontSet.push_back(retFont);
return retFont; return retFont;
} }
/* try default font in imgs folder /* try default font in imgs folder
if(retFont.fromFile(fmt("%s/font.ttf", m_imgsDir.c_str()), fonts[0].res, fonts[1].res, fonts[2].res, index, filename.c_str())) if(retFont.fromFile(fmt("%s/font.ttf", m_imgsDir.c_str()), fonts[0].res, fonts[1].res, fonts[2].res, index, filename.c_str()))
{ {
@ -1365,7 +1370,9 @@ SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSp
theme.fontSet.push_back(retFont); theme.fontSet.push_back(retFont);
return retFont; return retFont;
}*/ }*/
/* Fallback to default font */ /* Fallback to default font */
/* default font is the wii's system font */
if(retFont.fromBuffer(m_base_font, m_base_font_size, fonts[0].res, fonts[1].res, fonts[2].res, index, filename.c_str())) if(retFont.fromBuffer(m_base_font, m_base_font_size, fonts[0].res, fonts[1].res, fonts[2].res, index, filename.c_str()))
{ {
// Default font // Default font
@ -2308,7 +2315,7 @@ bool CMenu::_loadChannelList(void)
if(chantypes & CHANNELS_EMU) if(chantypes & CHANNELS_EMU)
{ {
NANDemuView = true; NANDemuView = true;
int emuPartition = _FindEmuPart(false, false);// check if emunand folder exist and on FAT int emuPartition = _FindEmuPart(EMU_NAND, false);// check if emunand folder exist and on FAT
if(emuPartition >= 0) if(emuPartition >= 0)
{ {
currentPartition = emuPartition; currentPartition = emuPartition;
@ -2329,8 +2336,6 @@ bool CMenu::_loadPluginList()
bool addGamecube = false; bool addGamecube = false;
bool addWii = false; bool addWii = false;
bool addChannel = false; bool addChannel = false;
//u8 addChannel = 0;
//u8 addEmuChannel = 0;
bool updateCache = m_cfg.getBool(PLUGIN_DOMAIN, "update_cache"); bool updateCache = m_cfg.getBool(PLUGIN_DOMAIN, "update_cache");
for(u8 i = 0; m_plugin.PluginExist(i); ++i) for(u8 i = 0; m_plugin.PluginExist(i); ++i)
@ -2405,11 +2410,6 @@ bool CMenu::_loadPluginList()
if(addChannel) if(addChannel)
_loadChannelList(); _loadChannelList();
/*if(addChannel || addEmuChannel)
{
m_cfg.setUInt(CHANNEL_DOMAIN, "channels_type", addChannel | addEmuChannel);
_loadChannelList();
}*/
m_cfg.remove(PLUGIN_DOMAIN, "update_cache"); m_cfg.remove(PLUGIN_DOMAIN, "update_cache");
return true; return true;
} }
@ -2477,7 +2477,6 @@ void CMenu::_hideWaitMessage()
void CMenu::_showWaitMessage() void CMenu::_showWaitMessage()
{ {
m_vid.waitMessage(0.15f); m_vid.waitMessage(0.15f);
//m_vid.waitMessage(_textures("GENERAL", "waitmessage"), m_theme.getFloat("GENERAL", "waitmessage_delay", 0.f));
} }
typedef struct map_entry typedef struct map_entry
@ -2645,7 +2644,8 @@ const char *CMenu::getBlankCoverPath(const dir_discHdr *element)
default: default:
blankCoverKey = "wii"; blankCoverKey = "wii";
} }
return fmt("%s/%s", m_boxPicDir.c_str(), m_theme.getString("BLANK_COVERS", blankCoverKey, fmt("%s.jpg", blankCoverKey)).c_str()); //return fmt("%s/%s", m_boxPicDir.c_str(), m_theme.getString("BLANK_COVERS", blankCoverKey, fmt("%s.jpg", blankCoverKey)).c_str());
return fmt("%s/%s.jpg", m_boxPicDir.c_str(), blankCoverKey);
} }
const char *CMenu::getBoxPath(const dir_discHdr *element) const char *CMenu::getBoxPath(const dir_discHdr *element)

View File

@ -1179,8 +1179,8 @@ private:
void _stopSounds(void); void _stopSounds(void);
static void * _NandDumper(void *obj); static void * _NandDumper(void *obj);
static void * _NandFlasher(void *obj); static void * _NandFlasher(void *obj);
int _FindEmuPart(bool searchvalid, bool savesnand); int _FindEmuPart(bool savesnand, bool searchvalid);
bool _checkSave(string id, bool nand); bool _checkSave(string id, int nand_type);
bool _TestEmuNand(int epart, const char *path, bool indept); bool _TestEmuNand(int epart, const char *path, bool indept);
void _checkEmuNandSettings(void); void _checkEmuNandSettings(void);
void _FullNandCheck(void); void _FullNandCheck(void);

View File

@ -12,6 +12,7 @@ s16 m_aboutLblUser[4];
s16 m_aboutLblIOS; s16 m_aboutLblIOS;
bool showHelp; bool showHelp;
int thanks_h;
void CMenu::_about(bool help) void CMenu::_about(bool help)
{ {
@ -19,8 +20,6 @@ void CMenu::_about(bool help)
int pixels_to_skip = 10; int pixels_to_skip = 10;
int amount_of_skips = 0; int amount_of_skips = 0;
int xtra_skips = 0; int xtra_skips = 0;
int thanks_h = m_theme.getInt("ABOUT/INFO", "height", 300);
int thanks_th = 0; int thanks_th = 0;
SetupInput(); SetupInput();
@ -103,6 +102,7 @@ void CMenu::_initAboutMenu()
_setHideAnim(m_aboutLblIOS, "ABOUT/IOS", 0, 0, -2.f, 0.f); _setHideAnim(m_aboutLblIOS, "ABOUT/IOS", 0, 0, -2.f, 0.f);
_hideAbout(true); _hideAbout(true);
thanks_h = m_theme.getInt("ABOUT/INFO", "height", 300);
} }
void CMenu::_textAbout(void) void CMenu::_textAbout(void)

View File

@ -100,7 +100,7 @@ int CMenu::_config4(void)
{ {
int exit_to = (int)loopNum(m_cfg.getUInt("GENERAL", "exit_to", 0) + 1, ARRAY_SIZE(CMenu::_exitTo)); int exit_to = (int)loopNum(m_cfg.getUInt("GENERAL", "exit_to", 0) + 1, ARRAY_SIZE(CMenu::_exitTo));
m_cfg.setInt("GENERAL", "exit_to", exit_to); m_cfg.setInt("GENERAL", "exit_to", exit_to);
Sys_ExitTo(exit_to + 1); Sys_ExitTo(exit_to);
_showConfig4(); _showConfig4();
} }
else if (m_btnMgr.selected(m_config4BtnSaveFavMode)) else if (m_btnMgr.selected(m_config4BtnSaveFavMode))

View File

@ -168,6 +168,7 @@ void CMenu::_showGameSettings()
m_btnMgr.show(m_gameSettingsLblUser[i]); m_btnMgr.show(m_gameSettingsLblUser[i]);
wstringEx title(_t("cfgg1", L"Settings")); wstringEx title(_t("cfgg1", L"Settings"));
if(GameHdr->type != TYPE_PLUGIN)
title.append(wfmt(L" [%.6s]", id)); title.append(wfmt(L" [%.6s]", id));
m_btnMgr.setText(m_gameSettingsLblTitle, title); m_btnMgr.setText(m_gameSettingsLblTitle, title);
m_btnMgr.show(m_gameSettingsLblTitle); m_btnMgr.show(m_gameSettingsLblTitle);
@ -465,7 +466,7 @@ void CMenu::_showGameSettings()
void CMenu::_gameSettings(const dir_discHdr *hdr, bool disc) void CMenu::_gameSettings(const dir_discHdr *hdr, bool disc)
{ {
m_gcfg2.load(fmt("%s/" GAME_SETTINGS2_FILENAME, m_settingsDir.c_str())); m_gcfg2.load(fmt("%s/" GAME_SETTINGS2_FILENAME, m_settingsDir.c_str()));
GameHdr = hdr; GameHdr = hdr;//
const char *id = GameHdr->id; const char *id = GameHdr->id;
if(GameHdr->type == TYPE_GC_GAME) if(GameHdr->type == TYPE_GC_GAME)
{ {

View File

@ -17,6 +17,7 @@ void CMenu::error(const wstringEx &msg)
_hideConfigScreen(); _hideConfigScreen();
_hideConfigSnd(); _hideConfigSnd();
_hideDownload(); _hideDownload();
_hideExitTo();
_hideGame(); _hideGame();
_hideMain(); _hideMain();
_hideWBFS(); _hideWBFS();

View File

@ -1801,7 +1801,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd, bool disc_cfg)
if(emulate_mode && !dvd && !neek2o()) if(emulate_mode && !dvd && !neek2o())
{ {
int emuPart = _FindEmuPart( true, true); int emuPart = _FindEmuPart(SAVES_NAND, true);
if(emuPart == -1)//if savepartition is unusable if(emuPart == -1)//if savepartition is unusable
{ {
_hideWaitMessage(); _hideWaitMessage();
@ -1809,7 +1809,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd, bool disc_cfg)
emulate_mode = 0; emulate_mode = 0;
_showWaitMessage(); _showWaitMessage();
} }
else else // partition is good so now check if save exists on savesnand
{ {
bool need_config = false; bool need_config = false;
bool need_miis = false; bool need_miis = false;
@ -1821,8 +1821,10 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd, bool disc_cfg)
char testpath[strlen(basepath) + 42]; char testpath[strlen(basepath) + 42];
// does not check to see if actual tmd exist just if the folder exist // does not check to see if actual tmd exist just if the folder exist
if(!_checkSave(id, false))//if save is not on emunand if(!_checkSave(id, SAVES_NAND))//if save is not on saves emunand
{ {
/* still use savesnand to create a new save on the savesnand */
/* make savesnand folders in case they don't already exist */
NandHandle.CreatePath("%s/import", basepath); NandHandle.CreatePath("%s/import", basepath);
NandHandle.CreatePath("%s/meta", basepath); NandHandle.CreatePath("%s/meta", basepath);
NandHandle.CreatePath("%s/shared1", basepath); NandHandle.CreatePath("%s/shared1", basepath);
@ -1833,7 +1835,8 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd, bool disc_cfg)
NandHandle.CreatePath("%s/tmp", basepath); NandHandle.CreatePath("%s/tmp", basepath);
NandHandle.CreateTitleTMD(hdr);//setup emunand for wii gamesave NandHandle.CreateTitleTMD(hdr);//setup emunand for wii gamesave
} }
if(gameEmuMode == 3)//full per game setting - in case global is not full /* check if saves emulation is set to full per this game in case the global defualt is not full */
if(gameEmuMode == 3)// if is then we need to make sure the savesnand contains mii's and config files
{ {
//check config files //check config files
snprintf(testpath, sizeof(testpath), "%s/shared2/sys/SYSCONF", basepath); snprintf(testpath, sizeof(testpath), "%s/shared2/sys/SYSCONF", basepath);
@ -1852,7 +1855,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd, bool disc_cfg)
} }
} }
else else
emulate_mode = 0;//sets to off we are using neek2o or launching a DVD game emulate_mode = 0;//sets to off if we are using neek2o or launching a DVD game
bool use_led = m_gcfg2.getBool(id, "led", false); bool use_led = m_gcfg2.getBool(id, "led", false);
bool cheat = m_gcfg2.getBool(id, "cheat", false); bool cheat = m_gcfg2.getBool(id, "cheat", false);

View File

@ -7,6 +7,7 @@ wstringEx gameinfo_Title_w;
bool tdb_found = false; bool tdb_found = false;
u8 cnt_controlsreq = 0, cnt_controls = 0; u8 cnt_controlsreq = 0, cnt_controls = 0;
int synopsis_h;
void CMenu::_gameinfo(void) void CMenu::_gameinfo(void)
{ {
@ -14,13 +15,11 @@ void CMenu::_gameinfo(void)
int pixels_to_skip = 10; int pixels_to_skip = 10;
int amount_of_skips = 0; int amount_of_skips = 0;
int xtra_skips = 0; int xtra_skips = 0;
int synopsis_th = 0;
SetupInput(); SetupInput();
_showGameInfo(); _showGameInfo();
int synopsis_h = m_theme.getInt("GAMEINFO/SYNOPSIS", "height", 280);
int synopsis_th = 0;
while(!m_exit) while(!m_exit)
{ {
_mainLoopCommon(); _mainLoopCommon();
@ -226,6 +225,7 @@ void CMenu::_initGameInfoMenu()
_setHideAnim(m_gameinfoLblWifiplayers, "GAMEINFO/WIFIPLAYERS", 0, -100, 0.f, 0.f); _setHideAnim(m_gameinfoLblWifiplayers, "GAMEINFO/WIFIPLAYERS", 0, -100, 0.f, 0.f);
// //
_hideGameInfo(true); _hideGameInfo(true);
synopsis_h = m_theme.getInt("GAMEINFO/SYNOPSIS", "height", 280);
} }
void CMenu::_textGameInfo(void) void CMenu::_textGameInfo(void)

View File

@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/ ****************************************************************************/
#include "menu.hpp" #include "menu.hpp"
#include "channel/nand.hpp"
#include "loader/cios.h" #include "loader/cios.h"
#include "loader/nk.h" #include "loader/nk.h"
#include "const_str.hpp" #include "const_str.hpp"
@ -65,6 +66,7 @@ bool CMenu::_Home(void)
m_btnMgr.down(); m_btnMgr.down();
else if(BTN_1_PRESSED) else if(BTN_1_PRESSED)
{ {
m_theme.load(fmt("%s.ini", m_themeDataDir.c_str()));
m_theme.save(); m_theme.save();
_hideHome(); _hideHome();
error(_t("savedtheme", L"Theme config saved!")); error(_t("savedtheme", L"Theme config saved!"));
@ -179,7 +181,7 @@ bool CMenu::_ExitTo(void)
m_btnMgr.up(); m_btnMgr.up();
else if(BTN_DOWN_PRESSED) else if(BTN_DOWN_PRESSED)
m_btnMgr.down(); m_btnMgr.down();
else if(BTN_A_PRESSED) else if(BTN_A_PRESSED)// note exitHandler sets m_exit = true
{ {
if(m_btnMgr.selected(m_homeBtnExitToHBC)) if(m_btnMgr.selected(m_homeBtnExitToHBC))
{ {
@ -209,15 +211,28 @@ bool CMenu::_ExitTo(void)
if(!Load_Neek2o_Kernel()) if(!Load_Neek2o_Kernel())
{ {
error(_fmt("errneek1", L"Cannot launch neek2o. Verify your neek2o setup")); error(_fmt("errneek1", L"Cannot launch neek2o. Verify your neek2o setup"));
exitHandler(PRIILOADER_DEF); _showExitTo();
} }
else else
{ {
//bool nkWiiflow = m_cfg.getBool("NEEK2O", "launchwiiflow", true); //if(m_cfg.getBool("NEEK2O", "launchwiiflow", true) && !neek2o())
//if(nkWiiflow)
// exitHandler(EXIT_TO_WFNK2O); // exitHandler(EXIT_TO_WFNK2O);
//else //else
exitHandler(EXIT_TO_SMNK2O); exitHandler(EXIT_TO_SMNK2O);
/* if exiting to Neek2o we must set the EmuNand Path for sys_exit() in sys.c */
const char *EmuNandPath = NULL;
/* but only if we are not already in neek2o mode */
if(!neek2o())
{
if(_FindEmuPart(EMU_NAND, false) >= 0)// make sure emunand exists
EmuNandPath = NandHandle.Get_NandPath();
else
{
error(_fmt("errneek1", L"Cannot launch neek2o. Verify your neek2o setup"));
_showExitTo();
}
}
Sys_SetNeekPath(EmuNandPath);
} }
break; break;
} }

View File

@ -751,23 +751,10 @@ int CMenu::main(void)
ScanInput(); ScanInput();
if(m_reload || BTN_B_HELD)// rebooting wiiflow if(m_reload || BTN_B_HELD)// rebooting wiiflow
{ {
CoverFlow.clear();
_showWaitMessage();
exitHandler(PRIILOADER_DEF); //Making wiiflow ready to boot something
vector<string> arguments = _getMetaXML(fmt("%s/boot.dol", m_appDir.c_str())); vector<string> arguments = _getMetaXML(fmt("%s/boot.dol", m_appDir.c_str()));
_launchHomebrew(fmt("%s/boot.dol", m_appDir.c_str()), arguments); _launchHomebrew(fmt("%s/boot.dol", m_appDir.c_str()), arguments);
return 0; return 0;
} }
else if(Sys_GetExitTo() == EXIT_TO_SMNK2O || Sys_GetExitTo() == EXIT_TO_WFNK2O)
{
const char *ReturnPath = NULL;
if(!m_cfg.getBool(CHANNEL_DOMAIN, "neek_return_default", false))
{
if(_FindEmuPart(false, false) >= 0)// make sure emunand folder exists
ReturnPath = NandHandle.Get_NandPath();
}
Sys_SetNeekPath(ReturnPath);
}
cleanup(); cleanup();
//gprintf("Saving configuration files\n"); //gprintf("Saving configuration files\n");
m_gcfg1.save(true);// save configs on power off or exit wiiflow m_gcfg1.save(true);// save configs on power off or exit wiiflow
@ -1035,12 +1022,10 @@ void CMenu::exitHandler(int ExitTo)
if(ExitTo == EXIT_TO_BOOTMII) //Bootmii, check that the files are there, or ios will hang. if(ExitTo == EXIT_TO_BOOTMII) //Bootmii, check that the files are there, or ios will hang.
{ {
struct stat dummy; struct stat dummy;
if(!DeviceHandle.IsInserted(SD) || if(!DeviceHandle.IsInserted(SD) || stat("sd:/bootmii/armboot.bin", &dummy) != 0 || stat("sd:/bootmii/ppcboot.elf", &dummy) != 0)
stat("sd:/bootmii/armboot.bin", &dummy) != 0 ||
stat("sd:/bootmii/ppcboot.elf", &dummy) != 0)
ExitTo = EXIT_TO_HBC; ExitTo = EXIT_TO_HBC;
} }
if(ExitTo != WIIFLOW_DEF) if(ExitTo != WIIFLOW_DEF)// if not using wiiflows exit option then go ahead and set the exit to
Sys_ExitTo(ExitTo); Sys_ExitTo(ExitTo);
} }

View File

@ -64,7 +64,7 @@ int curSavesNand = 0;
vector<string> emuNands; vector<string> emuNands;
vector<string> savesNands; vector<string> savesNands;
bool m_nandext; bool m_nandext;
bool m_fulldump; bool m_nanddump;
bool m_sgdump; bool m_sgdump;
bool m_saveall; bool m_saveall;
@ -78,7 +78,7 @@ void CMenu::_listEmuNands(const char *path, vector<string> &emuNands)
DIR *d; DIR *d;
struct dirent *dir; struct dirent *dir;
emuNands.clear(); emuNands.clear();
bool def = true; bool add_def = true;
d = opendir(path); d = opendir(path);
if(d != 0) if(d != 0)
@ -90,14 +90,13 @@ void CMenu::_listEmuNands(const char *path, vector<string> &emuNands)
if(dir->d_type == DT_DIR) if(dir->d_type == DT_DIR)
{ {
emuNands.push_back(dir->d_name); emuNands.push_back(dir->d_name);
string filename = dir->d_name; if(strlen(dir->d_name) == 7 && strcasecmp(dir->d_name, "default") == 0)
if(filename == "default") add_def = false;
def = false;
} }
} }
closedir(d); closedir(d);
} }
if(def) if(add_def)
emuNands.push_back("default"); emuNands.push_back("default");
sort(emuNands.begin(), emuNands.end()); sort(emuNands.begin(), emuNands.end());
} }
@ -115,7 +114,10 @@ void CMenu::_checkEmuNandSettings(void)
for(i = SD; i < MAXDEVICES; i++)// find first usable partition for(i = SD; i < MAXDEVICES; i++)// find first usable partition
{ {
if(DeviceHandle.PartitionUsableForNandEmu(i)) if(DeviceHandle.PartitionUsableForNandEmu(i))
{
emuPart = i; emuPart = i;
break;
}
} }
if(i == MAXDEVICES)// if no usable partitions found set to SD for now if(i == MAXDEVICES)// if no usable partitions found set to SD for now
emuPart = SD; emuPart = SD;
@ -126,7 +128,10 @@ void CMenu::_checkEmuNandSettings(void)
for(i = SD; i < MAXDEVICES; i++) for(i = SD; i < MAXDEVICES; i++)
{ {
if(DeviceHandle.PartitionUsableForNandEmu(i)) if(DeviceHandle.PartitionUsableForNandEmu(i))
{
savesPart = i; savesPart = i;
break;
}
} }
if(i == MAXDEVICES) if(i == MAXDEVICES)
savesPart = SD; savesPart = SD;
@ -191,13 +196,13 @@ void CMenu::_FullNandCheck(void)
for(u8 i = 0; i < 2; i++) for(u8 i = 0; i < 2; i++)
{ {
int emulate_mode; int emulate_mode;
if(i == 0) if(i == EMU_NAND)
emulate_mode = m_cfg.getInt(CHANNEL_DOMAIN, "emulation", 0); emulate_mode = m_cfg.getInt(CHANNEL_DOMAIN, "emulation", 0);
else else
emulate_mode = m_cfg.getInt(WII_DOMAIN, "save_emulation", 0); emulate_mode = m_cfg.getInt(WII_DOMAIN, "save_emulation", 0);
if((i == 0 && emulate_mode == 1) || (i == 1 && emulate_mode == 2))//full if((i == EMU_NAND && emulate_mode == 1) || (i == SAVES_NAND && emulate_mode == 2))//full
{ {
int emuPart = _FindEmuPart( true, i); int emuPart = _FindEmuPart(i, true);
if(emuPart < 0) if(emuPart < 0)
continue; continue;
bool need_config = false; bool need_config = false;
@ -228,7 +233,7 @@ void CMenu::_FullNandCheck(void)
} }
} }
int CMenu::_FindEmuPart(bool skipchecks, bool savesnand) int CMenu::_FindEmuPart(bool savesnand, bool skipchecks)
{ {
int emuPart; int emuPart;
char tmpPath[MAX_FAT_PATH]; char tmpPath[MAX_FAT_PATH];
@ -242,7 +247,7 @@ int CMenu::_FindEmuPart(bool skipchecks, bool savesnand)
emuPart = m_cfg.getInt(CHANNEL_DOMAIN, "partition"); emuPart = m_cfg.getInt(CHANNEL_DOMAIN, "partition");
snprintf(tmpPath, sizeof(tmpPath), "/%s/%s", emu_nands_dir, m_cfg.getString(CHANNEL_DOMAIN, "current_emunand").c_str()); snprintf(tmpPath, sizeof(tmpPath), "/%s/%s", emu_nands_dir, m_cfg.getString(CHANNEL_DOMAIN, "current_emunand").c_str());
} }
if(!DeviceHandle.PartitionUsableForNandEmu(emuPart)) if(!DeviceHandle.PartitionUsableForNandEmu(emuPart))//check if device is mounted and partition is FAT
return -1; return -1;
else if((skipchecks || _TestEmuNand(emuPart, tmpPath, false)))//check if emunand folder exist else if((skipchecks || _TestEmuNand(emuPart, tmpPath, false)))//check if emunand folder exist
{ {
@ -294,17 +299,17 @@ static bool _saveExists(const char *path)
} }
} }
bool CMenu::_checkSave(string id, bool nand) bool CMenu::_checkSave(string id, int nand_type)
{ {
int savePath = id.c_str()[0] << 24 | id.c_str()[1] << 16 | id.c_str()[2] << 8 | id.c_str()[3]; int savePath = id.c_str()[0] << 24 | id.c_str()[1] << 16 | id.c_str()[2] << 8 | id.c_str()[3];
if(nand) if(nand_type == REAL_NAND)
{ {
u32 temp = 0; u32 temp = 0;
if(ISFS_ReadDir(fmt("/title/00010000/%08x", savePath), NULL, &temp) < 0) if(ISFS_ReadDir(fmt("/title/00010000/%08x", savePath), NULL, &temp) < 0)
if(ISFS_ReadDir(fmt("/title/00010004/%08x", savePath), NULL, &temp) < 0) if(ISFS_ReadDir(fmt("/title/00010004/%08x", savePath), NULL, &temp) < 0)
return false; return false;
} }
else else // SAVES_NAND
{ {
int emuPartition = m_cfg.getInt(WII_DOMAIN, "savepartition"); int emuPartition = m_cfg.getInt(WII_DOMAIN, "savepartition");
const char *emuPath = fmt("/%s/%s", emu_nands_dir, m_cfg.getString(WII_DOMAIN, "current_save_emunand").c_str()); const char *emuPath = fmt("/%s/%s", emu_nands_dir, m_cfg.getString(WII_DOMAIN, "current_save_emunand").c_str());
@ -587,20 +592,19 @@ int CMenu::_NandEmuCfg(void)
} }
else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnNandDump) || m_btnMgr.selected(m_nandemuBtnAll) || m_btnMgr.selected(m_nandemuBtnMissing))) else if(BTN_A_PRESSED && (m_btnMgr.selected(m_nandemuBtnNandDump) || m_btnMgr.selected(m_nandemuBtnAll) || m_btnMgr.selected(m_nandemuBtnMissing)))
{ {
int emuPart = _FindEmuPart(true, !m_fulldump); m_nanddump = m_btnMgr.selected(m_nandemuBtnNandDump) ? true : false;
m_saveall = m_btnMgr.selected(m_nandemuBtnAll) ? true : false;
m_btnMgr.hide(m_nandemuBtnBack);
_hideNandEmu(true);
int emuPart = _FindEmuPart(!m_nanddump, true);
if(emuPart < 0) if(emuPart < 0)
{ {
_hideNandEmu(true);
error(_t("cfgne8", L"No valid FAT partition found for NAND Emulation!")); error(_t("cfgne8", L"No valid FAT partition found for NAND Emulation!"));
_showNandEmu(); _showNandEmu();
} }
else // partition usable else
{ {
m_fulldump = m_btnMgr.selected(m_nandemuBtnNandDump) ? true : false;
m_saveall = m_btnMgr.selected(m_nandemuBtnAll) ? true : false;
m_btnMgr.hide(m_nandemuBtnBack);
_hideNandEmu(true);
m_btnMgr.show(m_nandemuLblTitle); m_btnMgr.show(m_nandemuLblTitle);
m_btnMgr.show(m_nandfilePBar); m_btnMgr.show(m_nandfilePBar);
m_btnMgr.show(m_nandemuPBar); m_btnMgr.show(m_nandemuPBar);
@ -611,14 +615,14 @@ int CMenu::_NandEmuCfg(void)
m_btnMgr.setText(m_nandemuLblMessage, L""); m_btnMgr.setText(m_nandemuLblMessage, L"");
m_btnMgr.setText(m_nandfileLblMessage, L""); m_btnMgr.setText(m_nandfileLblMessage, L"");
m_btnMgr.setText(m_nandemuLblDialog, _t("cfgne11", L"Overall Progress:")); m_btnMgr.setText(m_nandemuLblDialog, _t("cfgne11", L"Overall Progress:"));
if(m_fulldump) if(m_nanddump)
{ {
ExtNand = emuNands[curEmuNand]; ExtNand = emuNands[curEmuNand];// set for later to refresh game list
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne12", L"NAND Extractor")); m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne12", L"NAND Extractor"));
} }
else else // saves dump
{ {
ExtNand = savesNands[curSavesNand]; //ExtNand = savesNands[curSavesNand];
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne13", L"Game Save Extractor")); m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne13", L"Game Save Extractor"));
} }
m_thrdStop = false; m_thrdStop = false;
@ -693,6 +697,7 @@ int CMenu::_NandEmuCfg(void)
} }
_hideNandEmu(); _hideNandEmu();
_FullNandCheck(); _FullNandCheck();
/* if changed emunand choice or emunand is the new one extracted */
if(emuNand != m_cfg.getString(CHANNEL_DOMAIN, "current_emunand") || emuNand == ExtNand) if(emuNand != m_cfg.getString(CHANNEL_DOMAIN, "current_emunand") || emuNand == ExtNand)
{ {
m_cfg.setBool(CHANNEL_DOMAIN, "update_cache", true); m_cfg.setBool(CHANNEL_DOMAIN, "update_cache", true);
@ -704,26 +709,18 @@ int CMenu::_NandEmuCfg(void)
int CMenu::_FlashSave(string gameId) int CMenu::_FlashSave(string gameId)
{ {
if(_FindEmuPart(false, true) < 0)// if savenand not found if(_FindEmuPart(SAVES_NAND, false) < 0)// if savesnand folder not found
return 0; return 0;
if(!_checkSave(gameId, false))// if save not on savenand if(!_checkSave(gameId, SAVES_NAND))// if save not on saves emunand
return 0; return 0;
lwp_t thread = 0; lwp_t thread = 0;
SetupInput();
m_thrdStop = false; m_thrdStop = false;
m_thrdMessageAdded = false; m_thrdMessageAdded = false;
m_nandext = false; m_nandext = false;
m_saveExtGameId = gameId; m_saveExtGameId = gameId;
while(!m_exit)
{
_mainLoopCommon();
if(m_forceext)
{
m_forceext = false;
m_btnMgr.show(m_nandemuLblTitle); m_btnMgr.show(m_nandemuLblTitle);
m_btnMgr.show(m_nandfilePBar); m_btnMgr.show(m_nandfilePBar);
m_btnMgr.show(m_nandemuPBar); m_btnMgr.show(m_nandemuPBar);
@ -735,11 +732,15 @@ int CMenu::_FlashSave(string gameId)
m_btnMgr.setText(m_nandfileLblMessage, L""); m_btnMgr.setText(m_nandfileLblMessage, L"");
m_btnMgr.setText(m_nandemuLblDialog, _t("cfgne11", L"Overall Progress:")); m_btnMgr.setText(m_nandemuLblDialog, _t("cfgne11", L"Overall Progress:"));
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne28", L"Game Save Flasher")); m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne28", L"Game Save Flasher"));
m_thrdStop = false;
m_thrdProgress = 0.f; m_thrdProgress = 0.f;
m_thrdWorking = true; m_thrdWorking = true;
LWP_CreateThread(&thread, _NandFlasher, this, 0, 32768, 40); LWP_CreateThread(&thread, _NandFlasher, this, 0, 32768, 40);
}
SetupInput();
while(!m_exit)
{
_mainLoopCommon();
if(!m_thrdWorking && (BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack)))) if(!m_thrdWorking && (BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack))))
break; break;
@ -771,19 +772,19 @@ int CMenu::_FlashSave(string gameId)
return 1; return 1;
} }
int CMenu::_AutoExtractSave(string gameId)// called from wii game config menu or launching wii game int CMenu::_AutoExtractSave(string gameId)// called from game settings menu to extract a gamesave from real nand to savesnand
{ {
int emuPart = _FindEmuPart(false, true); int emuPart = _FindEmuPart(SAVES_NAND, false);
if(m_forceext && emuPart == -1)// if game config force extract and savenand partition unusable if(emuPart == -1)// if savesnand partition unusable
{ {
m_forceext = false;
return 0; return 0;
} }
/*else if(emuPart == -2)// emunand folder not found so make it else if(emuPart == -2)// emunand folder not found so make it
{ {
emuPart = _FindEmuPart(true, true); emuPart = _FindEmuPart(SAVES_NAND, true);
const char *emuPath = NandHandle.Get_NandPath();
char basepath[MAX_FAT_PATH]; char basepath[MAX_FAT_PATH];
snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPart], emuPath.c_str()); snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPart], emuPath);
NandHandle.CreatePath("%s/import", basepath); NandHandle.CreatePath("%s/import", basepath);
NandHandle.CreatePath("%s/meta", basepath); NandHandle.CreatePath("%s/meta", basepath);
NandHandle.CreatePath("%s/shared1", basepath); NandHandle.CreatePath("%s/shared1", basepath);
@ -792,47 +793,19 @@ int CMenu::_AutoExtractSave(string gameId)// called from wii game config menu or
NandHandle.CreatePath("%s/title", basepath); NandHandle.CreatePath("%s/title", basepath);
NandHandle.CreatePath("%s/ticket", basepath); NandHandle.CreatePath("%s/ticket", basepath);
NandHandle.CreatePath("%s/tmp", basepath); NandHandle.CreatePath("%s/tmp", basepath);
}*/ }
if(!_checkSave(gameId, true))//if save not on real nand if(!_checkSave(gameId, REAL_NAND))//if save not on real nand
return 0; return 0;
if(!m_forceext && _checkSave(gameId, false))//if wii game launch and save is already on emunand
return 1;
lwp_t thread = 0; lwp_t thread = 0;
m_thrdStop = false; m_thrdStop = false;
m_thrdMessageAdded = false; m_thrdMessageAdded = false;
m_nandext = false; m_nandext = false;
m_saveExtGameId = gameId; m_saveExtGameId = gameId;
bool finished = false; bool finished = false;
m_nanddump = false;
SetupInput();
if(!m_forceext)// if wii game launch show this prompt menu
{
m_btnMgr.setText(m_nandemuBtnExtract, _t("cfgne24", L"Extract save"));
m_btnMgr.setText(m_nandemuBtnDisable, _t("cfgne25", L"Create new save"));
m_btnMgr.setText(m_nandemuLblInit, _t("cfgne26", L"A save file for this game was created on real NAND. Extract existing save file from real NAND or create new file for NAND Emulation?"));
m_btnMgr.show(m_nandemuBtnExtract);
m_btnMgr.show(m_nandemuBtnDisable);
m_btnMgr.show(m_nandemuLblInit);
}
while(!m_exit)
{
_mainLoopCommon();
if(BTN_UP_PRESSED && !m_thrdWorking)
m_btnMgr.up();
else if(BTN_DOWN_PRESSED && !m_thrdWorking)
m_btnMgr.down();
else if((BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnExtract)) || m_forceext)
{
m_forceext = false;
m_fulldump = false;
m_btnMgr.hide(m_nandemuBtnExtract);
m_btnMgr.hide(m_nandemuBtnDisable);
m_btnMgr.hide(m_nandemuLblInit);
m_btnMgr.show(m_nandemuLblTitle); m_btnMgr.show(m_nandemuLblTitle);
m_btnMgr.show(m_nandfilePBar); m_btnMgr.show(m_nandfilePBar);
m_btnMgr.show(m_nandemuPBar); m_btnMgr.show(m_nandemuPBar);
@ -844,17 +817,16 @@ int CMenu::_AutoExtractSave(string gameId)// called from wii game config menu or
m_btnMgr.setText(m_nandfileLblMessage, L""); m_btnMgr.setText(m_nandfileLblMessage, L"");
m_btnMgr.setText(m_nandemuLblDialog, _t("cfgne11", L"Overall Progress:")); m_btnMgr.setText(m_nandemuLblDialog, _t("cfgne11", L"Overall Progress:"));
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne13", L"Game Save Extractor")); m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne13", L"Game Save Extractor"));
m_thrdStop = false;
m_thrdProgress = 0.f; m_thrdProgress = 0.f;
m_thrdWorking = true; m_thrdWorking = true;
LWP_CreateThread(&thread, _NandDumper, this, 0, 32768, 40); LWP_CreateThread(&thread, _NandDumper, this, 0, 32768, 40);
}
else if(BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnDisable))//create new save SetupInput();
while(!m_exit)
{ {
_hideNandEmu(); _mainLoopCommon();
return 0; if(finished && (BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack))))
}
else if(finished && (BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack))))
break; break;
if(m_thrdMessageAdded) if(m_thrdMessageAdded)
@ -893,7 +865,7 @@ void * CMenu::_NandFlasher(void *obj)
char source[MAX_FAT_PATH]; char source[MAX_FAT_PATH];
char dest[ISFS_MAXPATH]; char dest[ISFS_MAXPATH];
int emuPartition = m._FindEmuPart(true, true); int emuPartition = m._FindEmuPart(SAVES_NAND, true);
const char *SaveGameID = m.m_saveExtGameId.c_str(); const char *SaveGameID = m.m_saveExtGameId.c_str();
int flashID = SaveGameID[0] << 24 | SaveGameID[1] << 16 | SaveGameID[2] << 8 | SaveGameID[3]; int flashID = SaveGameID[0] << 24 | SaveGameID[1] << 16 | SaveGameID[2] << 8 | SaveGameID[3];
@ -939,7 +911,7 @@ void * CMenu::_NandDumper(void *obj)
NandHandle.ResetCounters(); NandHandle.ResetCounters();
int emuPartition = m._FindEmuPart(true, !m_fulldump); int emuPartition = m._FindEmuPart(!m_nanddump, true);
const char *emuPath = NandHandle.Get_NandPath(); const char *emuPath = NandHandle.Get_NandPath();
char basepath[64]; char basepath[64];
snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPartition], emuPath); snprintf(basepath, sizeof(basepath), "%s:%s", DeviceName[emuPartition], emuPath);
@ -950,7 +922,7 @@ void * CMenu::_NandDumper(void *obj)
m._setDumpMsg(m._t("cfgne27", L"Calculating space needed for extraction..."), 0.f, 0.f); m._setDumpMsg(m._t("cfgne27", L"Calculating space needed for extraction..."), 0.f, 0.f);
LWP_MutexUnlock(m.m_mutex); LWP_MutexUnlock(m.m_mutex);
if(m_fulldump)/* full nand dump */ if(m_nanddump)/* full nand dump */
{ {
m.m_dumpsize = NandHandle.CalcDumpSpace("/", CMenu::_ShowProgress, obj); m.m_dumpsize = NandHandle.CalcDumpSpace("/", CMenu::_ShowProgress, obj);
m_nandext = true; m_nandext = true;
@ -977,9 +949,9 @@ void * CMenu::_NandDumper(void *obj)
{ {
string id((const char *)m.m_gameList[i].id, 4); string id((const char *)m.m_gameList[i].id, 4);
if(!missingOnly || !m._checkSave(id, false))// if all or gamesave not already on emunand if(!missingOnly || !m._checkSave(id, SAVES_NAND))// if all or the gamesave is not already on saves emunand
{ {
if(m._checkSave(id, true))// if save on real nand if(m._checkSave(id, REAL_NAND))// if save on real nand
{ {
m.m_nandexentry++; m.m_nandexentry++;
saveList.push_back(id); saveList.push_back(id);
@ -1000,7 +972,7 @@ void * CMenu::_NandDumper(void *obj)
char source[ISFS_MAXPATH]; char source[ISFS_MAXPATH];
int savePath = saveList[i].c_str()[0] << 24 | saveList[i].c_str()[1] << 16 | saveList[i].c_str()[2] << 8 | saveList[i].c_str()[3]; int savePath = saveList[i].c_str()[0] << 24 | saveList[i].c_str()[1] << 16 | saveList[i].c_str()[2] << 8 | saveList[i].c_str()[3];
snprintf(source, sizeof(source), "/title/00010000/%08x", savePath); snprintf(source, sizeof(source), "/title/00010000/%08x", savePath);
if(!m._checkSave(saveList[i], true)) if(!m._checkSave(saveList[i], REAL_NAND))
snprintf(source, sizeof(source), "/title/00010004/%08x", savePath); snprintf(source, sizeof(source), "/title/00010004/%08x", savePath);
m.m_dumpsize = NandHandle.CalcDumpSpace(source, CMenu::_ShowProgress, obj); m.m_dumpsize = NandHandle.CalcDumpSpace(source, CMenu::_ShowProgress, obj);
@ -1011,7 +983,7 @@ void * CMenu::_NandDumper(void *obj)
char source[ISFS_MAXPATH]; char source[ISFS_MAXPATH];
int savePath = saveList[i].c_str()[0] << 24 | saveList[i].c_str()[1] << 16 | saveList[i].c_str()[2] << 8 | saveList[i].c_str()[3]; int savePath = saveList[i].c_str()[0] << 24 | saveList[i].c_str()[1] << 16 | saveList[i].c_str()[2] << 8 | saveList[i].c_str()[3];
snprintf(source, sizeof(source), "/title/00010000/%08x", savePath); snprintf(source, sizeof(source), "/title/00010000/%08x", savePath);
if(!m._checkSave(saveList[i], true)) if(!m._checkSave(saveList[i], REAL_NAND))
snprintf(source, sizeof(source), "/title/00010004/%08x", savePath); snprintf(source, sizeof(source), "/title/00010004/%08x", savePath);
m_nandext = true; m_nandext = true;

View File

@ -444,7 +444,7 @@ void CMenu::_Wad(const char *wad_path)
int emuPart = 0; int emuPart = 0;
if(!mios) if(!mios)
{ {
emuPart = _FindEmuPart(false, false); emuPart = _FindEmuPart(EMU_NAND, false);
if(emuPart < 0) if(emuPart < 0)
{ {
//cfgne8=No valid FAT partition found for NAND Emulation! //cfgne8=No valid FAT partition found for NAND Emulation!

View File

@ -323,7 +323,7 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
} }
if (Disc_IsWii() == 0) if (Disc_IsWii() == 0)
{ {
error(_t("wbfsoperr6", L"Install Wii game is broken, please use cleanrip.")); error(_t("wbfsoperr6", L"Install game is broken, please use cleanrip."));
out = true; out = true;
break; break;
@ -349,6 +349,10 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
} }
else if(Disc_IsGC() == 0) else if(Disc_IsGC() == 0)
{ {
error(_t("wbfsoperr6", L"Install game is broken, please use cleanrip."));
out = true;
break;
Disc_ReadGCHeader(&gc_hdr); Disc_ReadGCHeader(&gc_hdr);
memcpy(GameID, gc_hdr.id, 6); memcpy(GameID, gc_hdr.id, 6);
if(_searchGamesByID(GameID)) if(_searchGamesByID(GameID))
@ -392,14 +396,14 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
if(strcasestr(CF_Hdr->path, "boot.bin") != NULL) if(strcasestr(CF_Hdr->path, "boot.bin") != NULL)
{ {
strncpy(GC_Path, CF_Hdr->path, 1023); strncpy(GC_Path, CF_Hdr->path, 1023);
*strrchr(GC_Path, '/') = '\0'; //boot.bin *strrchr(GC_Path, '/') = '\0'; // remove /boot.bin from path
*strrchr(GC_Path, '/') = '\0'; //sys *strrchr(GC_Path, '/') = '\0'; // remove /sys folder from path
fsop_deleteFolder(GC_Path); fsop_deleteFolder(GC_Path);
} }
else else
{ {
strncpy(GC_Path, CF_Hdr->path, 1023); strncpy(GC_Path, CF_Hdr->path, 1023);
*strrchr(GC_Path, '/') = '\0'; //iso path *strrchr(GC_Path, '/') = '\0'; // remove /game.iso from path
const char *cmp = fmt(gc_games_dir, DeviceName[currentPartition]); const char *cmp = fmt(gc_games_dir, DeviceName[currentPartition]);
if(strcasecmp(GC_Path, cmp) == 0) if(strcasecmp(GC_Path, cmp) == 0)
fsop_deleteFile(CF_Hdr->path); fsop_deleteFile(CF_Hdr->path);

View File

@ -11,6 +11,12 @@ enum {
NINTENDONT NINTENDONT
}; };
enum {
EMU_NAND = 0,
SAVES_NAND,
REAL_NAND
};
enum { enum {
CHANNELS_REAL = 1, CHANNELS_REAL = 1,
CHANNELS_EMU, CHANNELS_EMU,

View File

@ -451,7 +451,7 @@ wbfsoperr2=Disc_Open failed
wbfsoperr3=This is not a Wii disc! wbfsoperr3=This is not a Wii disc!
wbfsoperr4=Game already installed wbfsoperr4=Game already installed
wbfsoperr5=Deleting this Channel is not allowed! wbfsoperr5=Deleting this Channel is not allowed!
wbfsoperr6=Install Wii game is broken, please use cleanrip. wbfsoperr6=Install game is broken, please use cleanrip.
wbfsprogress=%i%% wbfsprogress=%i%%
wbfsremdlg=To permanently remove the game : %s, click on Go. wbfsremdlg=To permanently remove the game : %s, click on Go.
wifiplayers= Wifi Players wifiplayers= Wifi Players