mirror of
https://github.com/Fledge68/WiiFlow_Lite.git
synced 2024-11-30 15:14:18 +01:00
-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:
parent
4a566375e0
commit
66c17c023c
BIN
out/boot.dol
BIN
out/boot.dol
Binary file not shown.
Before Width: | Height: | Size: 3.3 MiB After Width: | Height: | Size: 3.3 MiB |
@ -70,7 +70,7 @@ static NandDevice NandDeviceList[] =
|
||||
void Nand::Init()
|
||||
{
|
||||
MountedDevice = 0;
|
||||
EmuDevice = REAL_NAND;
|
||||
EmuDevice = WII_NAND;
|
||||
Partition = 0;
|
||||
FullMode = 0x100;
|
||||
memset(NandPath, 0, sizeof(NandPath));
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "loader/disc.h"
|
||||
|
||||
#define REAL_NAND 0
|
||||
#define WII_NAND 0
|
||||
#define EMU_SD 1
|
||||
#define EMU_USB 2
|
||||
|
||||
|
@ -48,10 +48,16 @@ void DeviceHandler::Init()
|
||||
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()
|
||||
{
|
||||
MountSD();
|
||||
if(!Sys_DolphinMode())
|
||||
if(!Sys_DolphinMode() && mount_usb)
|
||||
MountAllUSB();
|
||||
}
|
||||
|
||||
|
@ -66,6 +66,7 @@ class DeviceHandler
|
||||
public:
|
||||
void Init();
|
||||
void SetModes();
|
||||
void SetMountUSB(bool using_usb);
|
||||
void MountAll();
|
||||
void UnMountAll();
|
||||
bool Mount(int dev);
|
||||
|
@ -141,7 +141,7 @@ bool fsop_CopyFile(const char *source, const char *target, progress_callback_t s
|
||||
if(!fs)
|
||||
return false;
|
||||
|
||||
ft = fopen(target, "wt");
|
||||
ft = fopen(target, "wb");
|
||||
if(!ft)
|
||||
{
|
||||
fclose(fs);
|
||||
@ -292,6 +292,7 @@ void fsop_deleteFolder(const char *source)
|
||||
|
||||
pdir = opendir(source);
|
||||
|
||||
/* first delete all subfolders and files in the folder */
|
||||
while((pent = readdir(pdir)) != NULL)
|
||||
{
|
||||
// Skip it
|
||||
@ -313,8 +314,9 @@ void fsop_deleteFolder(const char *source)
|
||||
}
|
||||
}
|
||||
closedir(pdir);
|
||||
/* now actually delete the folder */
|
||||
gprintf("Deleting directory: %s\n", source);
|
||||
unlink(source);
|
||||
unlink(source);// using POSIX unlink to delete the folder
|
||||
}
|
||||
|
||||
bool fsop_FileExist(const char *fn)
|
||||
|
@ -1,21 +1,21 @@
|
||||
// Can put this in defines.h later, but its easier
|
||||
//not having to recompile the whole menu for now by doing it this way
|
||||
|
||||
#define WIIFONT_NAME "WiiNTLG-Regular.ttc"
|
||||
#define WIIFONT_NAME_KOR "Wii-kr_Round Gothic B.ttf"
|
||||
//#define WIIFONT_NAME "WiiNTLG-Regular.ttc"
|
||||
//#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_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};
|
||||
|
||||
#define FONT_BOLD 36u
|
||||
#define FONT_BOLD 32u
|
||||
#define FONT_NOBOLD 8u
|
||||
|
||||
#define TITLEFONT_PT_SZ 30u
|
||||
#define BTNFONT_PT_SZ 20u
|
||||
#define BTNFONT_PT_SZ 18u
|
||||
#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 LABELFONT LBLFONT_PT_SZ, LBLFONT_PT_SZ + 4, FONT_BOLD, 1, "label_font"
|
||||
#define TEXTFONT TEXTFONT_PT_SZ, TEXTFONT_PT_SZ + 6, FONT_BOLD, 1, "text_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_NOBOLD, 1, "text_font"
|
@ -18,124 +18,166 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with FreeTypeGX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "FreeTypeGX.h"
|
||||
#include "memory/mem2.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define ALIGN8(x) (((x) + 7) & ~7)
|
||||
|
||||
FreeTypeGX::FreeTypeGX()
|
||||
{
|
||||
FT_Init_FreeType(&this->ftLibrary);
|
||||
FT_Init_FreeType(&ftLibrary);
|
||||
reset();
|
||||
this->ftFace = 0;
|
||||
ftFace = 0;
|
||||
}
|
||||
|
||||
FreeTypeGX::~FreeTypeGX()
|
||||
{
|
||||
this->unloadFont();
|
||||
FT_Done_Face(this->ftFace);
|
||||
FT_Done_FreeType(this->ftLibrary);
|
||||
unloadFont();
|
||||
FT_Done_Face(ftFace);
|
||||
FT_Done_FreeType(ftLibrary);
|
||||
}
|
||||
|
||||
wchar_t* FreeTypeGX::charToWideChar(char* strChar)
|
||||
{
|
||||
wchar_t *strWChar;
|
||||
strWChar = new wchar_t[strlen(strChar) + 1];
|
||||
if (!strChar) return NULL;
|
||||
|
||||
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;
|
||||
while((*tempDest++ = *tempSrc++));
|
||||
while ((*tempDest++ = *strChar++));
|
||||
|
||||
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();
|
||||
this->ftPointSize = pointSize != 0 ? pointSize : this->ftPointSize;
|
||||
this->ftWeight = weight;
|
||||
// lastFace is true for wii system font from buffer
|
||||
unloadFont();
|
||||
//ftPointSize = pointSize != 0 ? pointSize : ftPointSize;
|
||||
ftWeight = weight;
|
||||
|
||||
// Check if the index is valid
|
||||
if (index != 0)
|
||||
int faceIndex = 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);
|
||||
if (index >= (uint32_t) this->ftFace->num_faces)
|
||||
index = this->ftFace->num_faces - 1; // Use the last face
|
||||
FT_New_Memory_Face(this->ftLibrary, (FT_Byte *)fontBuffer, bufferSize, -1, &this->ftFace);
|
||||
faceIndex = this->ftFace->num_faces - 1; // Use the last face
|
||||
FT_Done_Face(this->ftFace);
|
||||
this->ftFace = NULL;
|
||||
}
|
||||
|
||||
FT_New_Memory_Face(this->ftLibrary, fontBuffer, bufferSize, index, &this->ftFace);
|
||||
FT_Set_Pixel_Sizes(this->ftFace, 0, this->ftPointSize);
|
||||
// load font face 0 or the last face available
|
||||
FT_New_Memory_Face(this->ftLibrary, (FT_Byte *) fontBuffer, bufferSize, faceIndex, &this->ftFace);
|
||||
|
||||
this->ftSlot = this->ftFace->glyph;
|
||||
this->ftKerningEnabled = FT_HAS_KERNING(this->ftFace);
|
||||
|
||||
if (cacheAll)
|
||||
return this->cacheGlyphDataComplete();
|
||||
|
||||
return 0;
|
||||
ftKerningEnabled = false;//FT_HAS_KERNING(ftFace);
|
||||
}
|
||||
|
||||
void FreeTypeGX::unloadFont()
|
||||
{
|
||||
if(this->fontData.size() == 0)
|
||||
return;
|
||||
if (this->fontData.size() == 0) return;
|
||||
|
||||
std::map<wchar_t, ftgxCharData>::iterator itr;
|
||||
for(itr = this->fontData.begin(); itr != this->fontData.end(); itr++)
|
||||
MEM2_free(itr->second.glyphDataTexture);
|
||||
this->fontData.clear();
|
||||
map<int16_t, map<wchar_t, ftgxCharData> >::iterator itr;
|
||||
map<wchar_t, ftgxCharData>::iterator itr2;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
ftgxCharData *FreeTypeGX::cacheGlyphData(wchar_t charCode)
|
||||
fontData.clear();
|
||||
ftgxAlign.clear();
|
||||
}
|
||||
|
||||
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;
|
||||
uint16_t textureWidth = 0, textureHeight = 0;
|
||||
|
||||
gIndex = FT_Get_Char_Index( this->ftFace, charCode );
|
||||
if(!FT_Load_Glyph(this->ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER))
|
||||
if (ftPointSize != pixelSize)
|
||||
{
|
||||
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;
|
||||
FT_Bitmap_Embolden(this->ftLibrary, glyphBitmap, this->ftWeight, this->ftWeight);
|
||||
|
||||
textureWidth = glyphBitmap->width % 8 == 0 ? glyphBitmap->width : 8 + glyphBitmap->width - (glyphBitmap->width % 8);
|
||||
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];
|
||||
ftgxAlign[ftPointSize].ascender = (int16_t) ftFace->size->metrics.ascender >> 6;
|
||||
ftgxAlign[ftPointSize].descender = (int16_t) ftFace->size->metrics.descender >> 6;
|
||||
ftgxAlign[ftPointSize].max = 0;
|
||||
ftgxAlign[ftPointSize].min = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
uint16_t FreeTypeGX::cacheGlyphDataComplete()
|
||||
uint16_t FreeTypeGX::cacheGlyphDataComplete(int16_t pixelSize)
|
||||
{
|
||||
uint16_t i = 0;
|
||||
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)
|
||||
{
|
||||
if(this->cacheGlyphData(charCode) != NULL)
|
||||
i++;
|
||||
|
||||
charCode = FT_Get_Next_Char( this->ftFace, charCode, &gIndex );
|
||||
if(cacheGlyphData(charCode, pixelSize) != NULL)
|
||||
++i;
|
||||
charCode = FT_Get_Next_Char(ftFace, charCode, &gIndex);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -176,7 +218,7 @@ void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData)
|
||||
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)
|
||||
return 0;
|
||||
@ -187,137 +229,206 @@ uint16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format)
|
||||
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 )
|
||||
return -offset.max;
|
||||
else if (format & FTGX_ALIGN_MIDDLE )
|
||||
return -(offset.max - offset.min) >> 1;
|
||||
else if (format & FTGX_ALIGN_BOTTOM )
|
||||
return offset.min;
|
||||
map<int16_t, ftgxDataOffset>::iterator itrAlign = ftgxAlign.find(pixelSize);
|
||||
if (itrAlign == ftgxAlign.end()) return 0;
|
||||
|
||||
switch (format & FTGX_ALIGN_MASK)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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_offset = 0, y_offset = 0;
|
||||
GXTexObj glyphTexture;
|
||||
FT_Vector pairDelta;
|
||||
|
||||
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;
|
||||
if( this->fontData.find(text[i]) != this->fontData.end())
|
||||
glyphData = &this->fontData[text[i]];
|
||||
else
|
||||
glyphData = this->cacheGlyphData(text[i]);
|
||||
x_offset = getStyleOffsetWidth(fullTextWidth, textStyle);
|
||||
}
|
||||
if (textStyle & FTGX_ALIGN_MASK)
|
||||
{
|
||||
y_offset = getStyleOffsetHeight(textStyle, pixelSize);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (text[i])
|
||||
{
|
||||
if (widthLimit > 0 && (x_pos - x) > widthLimit) break;
|
||||
|
||||
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
|
||||
|
||||
if (glyphData != NULL)
|
||||
{
|
||||
|
||||
if(this->ftKerningEnabled && i)
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
printed++;
|
||||
++printed;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color);
|
||||
if (format & FTGX_STYLE_UNDERLINE) this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, color);
|
||||
|
||||
if (format & FTGX_STYLE_STRIKE)
|
||||
this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData.max) >> 1), color);
|
||||
if (format & FTGX_STYLE_STRIKE) 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;
|
||||
FT_Vector pairDelta;
|
||||
|
||||
for (uint16_t i = 0; i < strLength; i++)
|
||||
int i = 0;
|
||||
while (text[i])
|
||||
{
|
||||
ftgxCharData* glyphData = NULL;
|
||||
if( this->fontData.find(text[i]) != this->fontData.end())
|
||||
glyphData = &this->fontData[text[i]];
|
||||
else
|
||||
glyphData = this->cacheGlyphData(text[i]);
|
||||
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
|
||||
|
||||
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 += 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;
|
||||
}
|
||||
|
||||
uint16_t FreeTypeGX::getHeight(const wchar_t *text)
|
||||
uint16_t FreeTypeGX::getHeight(const wchar_t *text, int16_t pixelSize)
|
||||
{
|
||||
ftgxDataOffset offset = this->getOffset(text);
|
||||
return offset.max + offset.min;
|
||||
getOffset(text, pixelSize);
|
||||
|
||||
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);
|
||||
uint16_t strMax = 0, strMin = 0;
|
||||
if (ftgxAlign.find(pixelSize) != ftgxAlign.end()) return;
|
||||
|
||||
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( this->fontData.find(text[i]) != this->fontData.end())
|
||||
glyphData = &this->fontData[text[i]];
|
||||
else
|
||||
glyphData = this->cacheGlyphData(text[i]);
|
||||
if (widthLimit > 0 && currWidth >= widthLimit) break;
|
||||
|
||||
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize);
|
||||
|
||||
if (glyphData != NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
f32 f32TexWidth = texWidth, f32TexHeight = texHeight;
|
||||
f32 f32TexWidth = (float)texWidth;
|
||||
f32 f32TexHeight = (float)texHeight;
|
||||
float x = (float)screenX + xPos;
|
||||
float y = (float)screenY + yPos;
|
||||
|
||||
GX_LoadTexObj(texObj, GX_TEXMAP0);
|
||||
|
||||
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||||
|
||||
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)
|
||||
{
|
||||
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_Position3f32(screenX, screenY, 0);
|
||||
GX_Position3f32(x, y, 0);
|
||||
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_Position3f32(f32FeatureWidth + screenX, f32FeatureHeight + screenY, 0);
|
||||
GX_Position3f32(f32FeatureWidth + x, f32FeatureHeight + y, 0);
|
||||
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_End();
|
||||
}
|
@ -33,34 +33,43 @@
|
||||
#include <wchar.h>
|
||||
#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 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 textureHeight; /**< Texture glyph height in pixels/bytes. */
|
||||
|
||||
uint16_t renderOffsetY; /**< Texture Y axis bearing offset. */
|
||||
uint16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */
|
||||
uint16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */
|
||||
int16_t renderOffsetY; /**< Texture Y axis bearing offset. */
|
||||
int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */
|
||||
int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */
|
||||
|
||||
uint8_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */
|
||||
} ftgxCharData;
|
||||
|
||||
typedef struct ftgxDataOffset_ {
|
||||
uint16_t max; /**< Maximum data offset. */
|
||||
uint16_t min; /**< Minimum data offset. */
|
||||
typedef struct ftgxDataOffset_
|
||||
{
|
||||
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;
|
||||
|
||||
#define FTGX_NULL 0x0000
|
||||
#define FTGX_JUSTIFY_LEFT 0x0001
|
||||
#define FTGX_JUSTIFY_CENTER 0x0002
|
||||
#define FTGX_JUSTIFY_RIGHT 0x0004
|
||||
#define FTGX_JUSTIFY_MASK 0x000f
|
||||
#define FTGX_JUSTIFY_LEFT 0x0001 //0001
|
||||
#define FTGX_JUSTIFY_CENTER 0x0002 //0010
|
||||
#define FTGX_JUSTIFY_RIGHT 0x0004 //0100
|
||||
#define FTGX_JUSTIFY_MASK 0x000f //1111
|
||||
|
||||
#define FTGX_ALIGN_TOP 0x0010
|
||||
#define FTGX_ALIGN_MIDDLE 0x0020
|
||||
#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_STYLE_UNDERLINE 0x1000
|
||||
@ -74,28 +83,31 @@ class FreeTypeGX {
|
||||
private:
|
||||
FT_Library ftLibrary; /**< FreeType FT_Library instance. */
|
||||
FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
|
||||
FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */
|
||||
FT_UInt ftPointSize; /**< Requested size of the rendered font. */
|
||||
//FT_GlyphSlot ftSlot; /**< FreeType reusable FT_GlyphSlot glyph container object. */
|
||||
int16_t ftPointSize; /**< Requested size of the rendered font. */
|
||||
FT_Pos ftWeight; /**< Requested weight of the rendered font. */
|
||||
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
|
||||
|
||||
float xScale;
|
||||
float yScale;
|
||||
float xPos;
|
||||
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);
|
||||
static uint16_t getStyleOffsetHeight(ftgxDataOffset offset, uint16_t format);
|
||||
|
||||
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);
|
||||
int16_t getStyleOffsetWidth(uint16_t width, uint16_t format);
|
||||
int16_t getStyleOffsetHeight(int16_t format, uint16_t pixelSize);
|
||||
|
||||
void unloadFont();
|
||||
ftgxCharData *cacheGlyphData(wchar_t charCode);
|
||||
uint16_t cacheGlyphDataComplete();
|
||||
ftgxCharData *cacheGlyphData(wchar_t charCode, int16_t pixelSize);
|
||||
uint16_t cacheGlyphDataComplete(int16_t pixelSize);
|
||||
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:
|
||||
FreeTypeGX();
|
||||
@ -103,13 +115,15 @@ class FreeTypeGX {
|
||||
|
||||
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 getHeight(const wchar_t *text);
|
||||
ftgxDataOffset getOffset(const wchar_t *text);
|
||||
uint16_t getWidth(const wchar_t *text, int16_t pixelSize);
|
||||
uint16_t getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar = 0x0000);
|
||||
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 getYScale(void) const { return yScale; }
|
||||
|
@ -1176,7 +1176,11 @@ void CCoverFlow::_drawTitle(int i, bool mirror, bool rectangle)
|
||||
if (m_covers[i].txtColor == 0) return;
|
||||
|
||||
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_SetNumTevStages(1);
|
||||
|
@ -748,8 +748,8 @@ void CButtonsMgr::_drawBtn(CButtonsMgr::SButton &b, bool selected, bool click)
|
||||
if (!b.font.font) return;
|
||||
b.font.font->reset();
|
||||
//CColor txtColor(b.textColor.r, b.textColor.g, b.textColor.b, (u8)((int)b.textColor.a * (int)alpha / 0xFF));
|
||||
if(m_vid.wide())
|
||||
scaleX *= 0.8f;
|
||||
//if(m_vid.wide())
|
||||
// scaleX *= 0.8f;
|
||||
b.font.font->setXScale(scaleX);
|
||||
b.font.font->setYScale(scaleY);
|
||||
//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.text.setColor(CColor(b.textColor.r, b.textColor.g, b.textColor.b, (u8)((int)b.textColor.a * (int)alpha / 0xFF)));
|
||||
if(m_vid.wide())
|
||||
scaleX *= 0.8f;
|
||||
//if(m_vid.wide())
|
||||
// scaleX *= 0.8f;
|
||||
b.font.font->setXScale(scaleX);
|
||||
b.font.font->setYScale(scaleY);
|
||||
float posX = b.pos.x;
|
||||
|
@ -171,7 +171,7 @@ bool SFont::fromBuffer(const u8 *buffer, const u32 bufferSize, u32 size, u32 lsp
|
||||
fSize = min(max(6ul, size), 1000ul);
|
||||
lineSpacing = min(max(6ul, lspacing), 1000ul);
|
||||
weight = min(w, 32ul);
|
||||
index = idx;
|
||||
index = idx;// currently not used
|
||||
|
||||
if(data != NULL)
|
||||
free(data);
|
||||
@ -184,7 +184,7 @@ bool SFont::fromBuffer(const u8 *buffer, const u32 bufferSize, u32 size, u32 lsp
|
||||
|
||||
memcpy(name, fontname, 127);
|
||||
font = new FreeTypeGX();
|
||||
font->loadFont(data, dataSize, fSize, weight, index, false);
|
||||
font->loadFont(data, dataSize, weight, 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);
|
||||
weight = min(w, 32ul);
|
||||
index = idx = 0;
|
||||
index = idx;// currently not used
|
||||
|
||||
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);
|
||||
font = new FreeTypeGX();
|
||||
font->loadFont(data, dataSize, fSize, weight, index, false);
|
||||
font->loadFont(data, dataSize, weight, false);
|
||||
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)
|
||||
{
|
||||
SWord w;
|
||||
@ -232,18 +232,18 @@ void CText::setText(const SFont &font, const wstringEx &t)
|
||||
wstringEx::size_type j;
|
||||
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)
|
||||
{
|
||||
w.text.assign(l, i, j - i);
|
||||
m_lines.back().push_back(w);
|
||||
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);
|
||||
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;
|
||||
totalHeight = 0;
|
||||
float space = m_font.font->getWidth(L" ");
|
||||
float space = m_font.font->getWidth(L" ", m_font.fSize);//
|
||||
float posX = 0.f;
|
||||
float posY = 0.f;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
words[i].targetPos = Vector3D(posX, posY, 0.f);
|
||||
@ -370,10 +370,11 @@ void CText::setColor(const CColor &c)
|
||||
m_color = c;
|
||||
}
|
||||
|
||||
/* moves each word of each line of text from current pos to targetPos */
|
||||
void CText::tick(void)
|
||||
{
|
||||
for (u32 k = 0; k < m_lines.size(); ++k)
|
||||
for (u32 i = 0; i < m_lines[k].size(); ++i)
|
||||
for (u32 k = 0; k < m_lines.size(); ++k)// lines of text
|
||||
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;
|
||||
}
|
||||
|
||||
@ -387,7 +388,7 @@ void CText::draw(void)
|
||||
{
|
||||
m_font.font->setX(m_lines[k][i].pos.x);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,8 +171,9 @@ void CVideo::init(void)
|
||||
GX_SetDispCopyDst(m_rmode->fbWidth, m_xfbHeight);
|
||||
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_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_ClearVtxDesc();
|
||||
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
@ -251,7 +252,11 @@ void CVideo::_clearScreen()
|
||||
|
||||
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);
|
||||
_setViewPort(0.f, 0.f, (float)m_rmode->fbWidth, (float)m_rmode->efbHeight);
|
||||
GX_SetScissor(0, 0, m_rmode->fbWidth, m_rmode->efbHeight);
|
||||
GX_InvVtxCache();
|
||||
@ -454,11 +459,11 @@ void CVideo::renderAAPass(int aaStep)
|
||||
|
||||
void CVideo::render(void)
|
||||
{
|
||||
GX_DrawDone();
|
||||
GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_TRUE);
|
||||
GX_SetColorUpdate(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);
|
||||
GX_DrawDone();
|
||||
VIDEO_SetNextFramebuffer(m_frameBuf[m_curFB]);
|
||||
VIDEO_Flush();
|
||||
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_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||||
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
|
||||
GX_SetNumTexGens(1);
|
||||
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);
|
||||
@ -783,10 +789,13 @@ void DrawTexturePos(const TexData *tex)
|
||||
GX_SetAlphaUpdate(GX_FALSE);
|
||||
GX_SetCullMode(GX_CULL_NONE);
|
||||
GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_FALSE);
|
||||
|
||||
guMtxIdentity(modelViewMtx);
|
||||
GX_LoadPosMtxImm(modelViewMtx, GX_PNMTX0);
|
||||
|
||||
GX_InitTexObj(&texObj, tex->data, tex->width, tex->height, tex->format, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
||||
GX_LoadTexObj(&texObj, GX_TEXMAP0);
|
||||
|
||||
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
|
||||
GX_Position2f32(currentMoviePos.x1, currentMoviePos.y1);
|
||||
GX_TexCoord2f32(0.f, 0.f);
|
||||
|
@ -88,7 +88,7 @@ void Sys_ExitTo(int option)
|
||||
*Priiloader_CFG1 = 0x4461636F;// Daco
|
||||
*Priiloader_CFG2 = 0x4461636F;
|
||||
}
|
||||
else
|
||||
else // PRIILOADER_DEF
|
||||
{
|
||||
*Priiloader_CFG1 = 0xFFFFFFFF;
|
||||
*Priiloader_CFG2 = 0xFFFFFFFF;
|
||||
@ -99,17 +99,15 @@ void Sys_ExitTo(int option)
|
||||
|
||||
void Sys_Exit(void)
|
||||
{
|
||||
//if(ExitOption == EXIT_TO_DISABLE)
|
||||
// return;
|
||||
|
||||
/* Shutdown Inputs */
|
||||
Close_Inputs();
|
||||
/* Just shutdown console*/
|
||||
if(ExitOption == BUTTON_CALLBACK)
|
||||
SYS_ResetSystem(SYS_POWEROFF_STANDBY, 0, 0);
|
||||
|
||||
/* We wanna to boot sth */
|
||||
/* We wanna to boot something */
|
||||
WII_Initialize();
|
||||
/* if in neek2o mode Launch_nk will just return to neek2o system menu and not launch anything */
|
||||
if(ExitOption == EXIT_TO_WFNK2O)
|
||||
Launch_nk(0x1000157464C41LL, NeekPath, 0);// 57464C41 = WFLA : 44574641 = DWFA
|
||||
else if(ExitOption == EXIT_TO_SMNK2O)
|
||||
@ -126,7 +124,7 @@ void Sys_Exit(void)
|
||||
}
|
||||
else if(ExitOption == EXIT_TO_WIIU)
|
||||
WII_LaunchTitle(WIIU_CHANNEL);
|
||||
/* else Return to Menu */
|
||||
/* else Return to System Menu */
|
||||
SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
|
||||
exit(1);
|
||||
}
|
||||
@ -154,14 +152,18 @@ bool AHBPROT_Patched(void)
|
||||
}
|
||||
|
||||
/* WiiU Check by crediar, thanks */
|
||||
bool WiiUChecked = false;
|
||||
bool WiiUMode = false;
|
||||
bool IsOnWiiU(void)
|
||||
{
|
||||
if(WiiUChecked)
|
||||
return WiiUMode;
|
||||
|
||||
if((*HW_PROCESSOR >> 16) == 0xCAFE)
|
||||
{
|
||||
gprintf("vWii Mode\n");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
WiiUMode = true;
|
||||
|
||||
WiiUChecked = true;
|
||||
return WiiUMode;
|
||||
}
|
||||
|
||||
void Sys_SetNeekPath(const char *Path)
|
||||
@ -205,15 +207,10 @@ bool Sys_DolphinMode(void)
|
||||
|
||||
);
|
||||
if(ofpr1 != 0x56cc62b2)
|
||||
{
|
||||
gprintf("Dolphin-Emu\n");
|
||||
DolphinMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
gprintf("Real Wii\n");
|
||||
DolphinMode = false;
|
||||
}
|
||||
|
||||
ModeChecked = true;
|
||||
return DolphinMode;
|
||||
}
|
||||
@ -225,7 +222,6 @@ bool Sys_HW_Access(void)
|
||||
if(hw_checked == true)
|
||||
return on_hw;
|
||||
|
||||
check_neek2o();
|
||||
on_hw = AHBPROT_Patched() && (!Sys_DolphinMode() && !neek2o());
|
||||
hw_checked = true;
|
||||
return on_hw;
|
||||
|
@ -19,17 +19,16 @@ extern "C" {
|
||||
|
||||
enum
|
||||
{
|
||||
PRIILOADER_DEF = 0,
|
||||
EXIT_TO_MENU,
|
||||
EXIT_TO_MENU = 0,
|
||||
EXIT_TO_HBC,
|
||||
EXIT_TO_WIIU,
|
||||
PRIILOADER_DEF,
|
||||
EXIT_TO_PRIILOADER,
|
||||
//EXIT_TO_DISABLE,
|
||||
EXIT_TO_BOOTMII,
|
||||
EXIT_TO_WFNK2O,
|
||||
EXIT_TO_SMNK2O,
|
||||
BUTTON_CALLBACK,
|
||||
WIIFLOW_DEF,
|
||||
WIIFLOW_DEF,// m_cfg.getInt("GENERAL", "exit_to", 0). (EXIT_TO_MENU, EXIT_TO_HBC, EXIT_TO_WIIU)
|
||||
};
|
||||
|
||||
/* Prototypes */
|
||||
|
@ -25,6 +25,56 @@ bool useMainIOS = false;
|
||||
volatile bool NANDemuView = 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)
|
||||
{
|
||||
MEM_init(); //Inits both mem1lo and mem2
|
||||
@ -36,7 +86,6 @@ int main(int argc, char **argv)
|
||||
bool iosOK = true;
|
||||
char *gameid = NULL;
|
||||
bool showFlashImg = true;
|
||||
bool sd_only = false;
|
||||
bool wait_loop = false;
|
||||
char wait_dir[256];
|
||||
memset(&wait_dir, 0, sizeof(wait_dir));
|
||||
@ -59,8 +108,6 @@ int main(int argc, char **argv)
|
||||
wait_loop = true;
|
||||
else if(strcasestr(argv[i], "noflash") != NULL)
|
||||
showFlashImg = false;
|
||||
else if(strcasestr(argv[i], "sdonly") != NULL)
|
||||
sd_only = true;
|
||||
else if(strlen(argv[i]) == 6)
|
||||
{
|
||||
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 */
|
||||
m_vid.init();
|
||||
if(showFlashImg)
|
||||
@ -98,14 +152,13 @@ int main(int argc, char **argv)
|
||||
else if(useMainIOS && CustomIOS(IOS_GetType(mainIOS))) /* Requested */
|
||||
iosOK = loadIOS(mainIOS, false) && CustomIOS(CurrentIOS.Type);
|
||||
|
||||
/* set reset and power button callbacks and exitTo option */
|
||||
Sys_Init();
|
||||
Sys_ExitTo(EXIT_TO_HBC);
|
||||
/* sys inits */
|
||||
Sys_Init();// set reset and power button callbacks
|
||||
Sys_ExitTo(EXIT_TO_HBC);// set exit to in case of failed launch
|
||||
|
||||
/* mount Devices */
|
||||
DeviceHandle.MountSD();
|
||||
if(!sd_only && !Sys_DolphinMode())
|
||||
DeviceHandle.MountAllUSB();
|
||||
DeviceHandle.SetMountUSB(isUsingUSB());
|
||||
DeviceHandle.MountAll();
|
||||
|
||||
/* init wait images and show wait animation */
|
||||
m_vid.setCustomWaitImgs(wait_dir, wait_loop);
|
||||
|
@ -175,7 +175,7 @@ bool CMenu::init()
|
||||
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
|
||||
{
|
||||
@ -438,12 +438,10 @@ bool CMenu::init()
|
||||
if(m_cfg.getString("GENERAL", "returnto", "WFLA") == "DWFA")
|
||||
m_cfg.setString("GENERAL", "returnto", "WFLA");
|
||||
|
||||
int exit_to = m_cfg.getInt("GENERAL", "exit_to", 0);
|
||||
if(exit_to == EXIT_TO_BOOTMII && (!DeviceHandle.IsInserted(SD) ||
|
||||
stat(fmt("%s:/bootmii/armboot.bin",DeviceName[SD]), &dummy) != 0 ||
|
||||
stat(fmt("%s:/bootmii/ppcboot.elf", DeviceName[SD]), &dummy) != 0))
|
||||
exit_to = EXIT_TO_HBC;
|
||||
Sys_ExitTo(exit_to + 1);
|
||||
/* set WIIFLOW_DEF exit to option */
|
||||
/* 0 thru 2 of exit to enum (EXIT_TO_MENU, EXIT_TO_HBC, EXIT_TO_WIIU) in sys.h */
|
||||
int exit_to = min(max(0, m_cfg.getInt("GENERAL", "exit_to", 0)), (int)ARRAY_SIZE(CMenu::_exitTo) - 1);
|
||||
Sys_ExitTo(exit_to);
|
||||
|
||||
LWP_MutexInit(&m_mutex, 0);
|
||||
|
||||
@ -607,7 +605,7 @@ void CMenu::_Theme_Cleanup(void)
|
||||
theme.texSet.clear();
|
||||
theme.fontSet.clear();
|
||||
theme.soundSet.clear();
|
||||
m_theme.unload();
|
||||
//m_theme.unload();
|
||||
m_coverflow.unload();
|
||||
}
|
||||
|
||||
@ -1302,6 +1300,7 @@ void CMenu::_buildMenus(void)
|
||||
_initPathsMenu();
|
||||
|
||||
_loadCFCfg();
|
||||
m_theme.unload();// done with theme.ini so lets unload it from mem
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
/* get font info from theme.ini or use the default values */
|
||||
string filename;
|
||||
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 }};
|
||||
@ -1325,12 +1325,13 @@ SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSp
|
||||
filename = m_theme.getString("GENERAL", genKey, genKey);
|
||||
bool useDefault = filename == genKey;
|
||||
|
||||
/* get the resources - fontSize, lineSpacing, and weight */
|
||||
for(u32 i = 0; i < 3; i++)
|
||||
{
|
||||
string defValue = genKey;
|
||||
defValue += fonts[i].ext;
|
||||
defValue += fonts[i].ext;// _size, _line_height, _weight
|
||||
string value = key;
|
||||
value += fonts[i].ext;
|
||||
value += fonts[i].ext;// _size, _line_height, _weight
|
||||
|
||||
if(!general)
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
|
||||
// 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;
|
||||
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);
|
||||
return retFont;
|
||||
}
|
||||
|
||||
/* 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()))
|
||||
{
|
||||
@ -1365,7 +1370,9 @@ SFont CMenu::_font(const char *domain, const char *key, u32 fontSize, u32 lineSp
|
||||
theme.fontSet.push_back(retFont);
|
||||
return retFont;
|
||||
}*/
|
||||
|
||||
/* 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()))
|
||||
{
|
||||
// Default font
|
||||
@ -2308,7 +2315,7 @@ bool CMenu::_loadChannelList(void)
|
||||
if(chantypes & CHANNELS_EMU)
|
||||
{
|
||||
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)
|
||||
{
|
||||
currentPartition = emuPartition;
|
||||
@ -2329,8 +2336,6 @@ bool CMenu::_loadPluginList()
|
||||
bool addGamecube = false;
|
||||
bool addWii = false;
|
||||
bool addChannel = false;
|
||||
//u8 addChannel = 0;
|
||||
//u8 addEmuChannel = 0;
|
||||
bool updateCache = m_cfg.getBool(PLUGIN_DOMAIN, "update_cache");
|
||||
|
||||
for(u8 i = 0; m_plugin.PluginExist(i); ++i)
|
||||
@ -2405,11 +2410,6 @@ bool CMenu::_loadPluginList()
|
||||
if(addChannel)
|
||||
_loadChannelList();
|
||||
|
||||
/*if(addChannel || addEmuChannel)
|
||||
{
|
||||
m_cfg.setUInt(CHANNEL_DOMAIN, "channels_type", addChannel | addEmuChannel);
|
||||
_loadChannelList();
|
||||
}*/
|
||||
m_cfg.remove(PLUGIN_DOMAIN, "update_cache");
|
||||
return true;
|
||||
}
|
||||
@ -2477,7 +2477,6 @@ void CMenu::_hideWaitMessage()
|
||||
void CMenu::_showWaitMessage()
|
||||
{
|
||||
m_vid.waitMessage(0.15f);
|
||||
//m_vid.waitMessage(_textures("GENERAL", "waitmessage"), m_theme.getFloat("GENERAL", "waitmessage_delay", 0.f));
|
||||
}
|
||||
|
||||
typedef struct map_entry
|
||||
@ -2645,7 +2644,8 @@ const char *CMenu::getBlankCoverPath(const dir_discHdr *element)
|
||||
default:
|
||||
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)
|
||||
|
@ -1179,8 +1179,8 @@ private:
|
||||
void _stopSounds(void);
|
||||
static void * _NandDumper(void *obj);
|
||||
static void * _NandFlasher(void *obj);
|
||||
int _FindEmuPart(bool searchvalid, bool savesnand);
|
||||
bool _checkSave(string id, bool nand);
|
||||
int _FindEmuPart(bool savesnand, bool searchvalid);
|
||||
bool _checkSave(string id, int nand_type);
|
||||
bool _TestEmuNand(int epart, const char *path, bool indept);
|
||||
void _checkEmuNandSettings(void);
|
||||
void _FullNandCheck(void);
|
||||
|
@ -12,6 +12,7 @@ s16 m_aboutLblUser[4];
|
||||
s16 m_aboutLblIOS;
|
||||
|
||||
bool showHelp;
|
||||
int thanks_h;
|
||||
|
||||
void CMenu::_about(bool help)
|
||||
{
|
||||
@ -19,8 +20,6 @@ void CMenu::_about(bool help)
|
||||
int pixels_to_skip = 10;
|
||||
int amount_of_skips = 0;
|
||||
int xtra_skips = 0;
|
||||
|
||||
int thanks_h = m_theme.getInt("ABOUT/INFO", "height", 300);
|
||||
int thanks_th = 0;
|
||||
|
||||
SetupInput();
|
||||
@ -103,6 +102,7 @@ void CMenu::_initAboutMenu()
|
||||
_setHideAnim(m_aboutLblIOS, "ABOUT/IOS", 0, 0, -2.f, 0.f);
|
||||
|
||||
_hideAbout(true);
|
||||
thanks_h = m_theme.getInt("ABOUT/INFO", "height", 300);
|
||||
}
|
||||
|
||||
void CMenu::_textAbout(void)
|
||||
|
@ -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));
|
||||
m_cfg.setInt("GENERAL", "exit_to", exit_to);
|
||||
Sys_ExitTo(exit_to + 1);
|
||||
Sys_ExitTo(exit_to);
|
||||
_showConfig4();
|
||||
}
|
||||
else if (m_btnMgr.selected(m_config4BtnSaveFavMode))
|
||||
|
@ -168,6 +168,7 @@ void CMenu::_showGameSettings()
|
||||
m_btnMgr.show(m_gameSettingsLblUser[i]);
|
||||
|
||||
wstringEx title(_t("cfgg1", L"Settings"));
|
||||
if(GameHdr->type != TYPE_PLUGIN)
|
||||
title.append(wfmt(L" [%.6s]", id));
|
||||
m_btnMgr.setText(m_gameSettingsLblTitle, title);
|
||||
m_btnMgr.show(m_gameSettingsLblTitle);
|
||||
@ -465,7 +466,7 @@ void CMenu::_showGameSettings()
|
||||
void CMenu::_gameSettings(const dir_discHdr *hdr, bool disc)
|
||||
{
|
||||
m_gcfg2.load(fmt("%s/" GAME_SETTINGS2_FILENAME, m_settingsDir.c_str()));
|
||||
GameHdr = hdr;
|
||||
GameHdr = hdr;//
|
||||
const char *id = GameHdr->id;
|
||||
if(GameHdr->type == TYPE_GC_GAME)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ void CMenu::error(const wstringEx &msg)
|
||||
_hideConfigScreen();
|
||||
_hideConfigSnd();
|
||||
_hideDownload();
|
||||
_hideExitTo();
|
||||
_hideGame();
|
||||
_hideMain();
|
||||
_hideWBFS();
|
||||
|
@ -1801,7 +1801,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd, bool disc_cfg)
|
||||
|
||||
if(emulate_mode && !dvd && !neek2o())
|
||||
{
|
||||
int emuPart = _FindEmuPart( true, true);
|
||||
int emuPart = _FindEmuPart(SAVES_NAND, true);
|
||||
if(emuPart == -1)//if savepartition is unusable
|
||||
{
|
||||
_hideWaitMessage();
|
||||
@ -1809,7 +1809,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd, bool disc_cfg)
|
||||
emulate_mode = 0;
|
||||
_showWaitMessage();
|
||||
}
|
||||
else
|
||||
else // partition is good so now check if save exists on savesnand
|
||||
{
|
||||
bool need_config = 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];
|
||||
|
||||
// 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/meta", 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.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
|
||||
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
|
||||
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 cheat = m_gcfg2.getBool(id, "cheat", false);
|
||||
|
@ -7,6 +7,7 @@ wstringEx gameinfo_Title_w;
|
||||
|
||||
bool tdb_found = false;
|
||||
u8 cnt_controlsreq = 0, cnt_controls = 0;
|
||||
int synopsis_h;
|
||||
|
||||
void CMenu::_gameinfo(void)
|
||||
{
|
||||
@ -14,13 +15,11 @@ void CMenu::_gameinfo(void)
|
||||
int pixels_to_skip = 10;
|
||||
int amount_of_skips = 0;
|
||||
int xtra_skips = 0;
|
||||
int synopsis_th = 0;
|
||||
|
||||
SetupInput();
|
||||
_showGameInfo();
|
||||
|
||||
int synopsis_h = m_theme.getInt("GAMEINFO/SYNOPSIS", "height", 280);
|
||||
int synopsis_th = 0;
|
||||
|
||||
while(!m_exit)
|
||||
{
|
||||
_mainLoopCommon();
|
||||
@ -226,6 +225,7 @@ void CMenu::_initGameInfoMenu()
|
||||
_setHideAnim(m_gameinfoLblWifiplayers, "GAMEINFO/WIFIPLAYERS", 0, -100, 0.f, 0.f);
|
||||
//
|
||||
_hideGameInfo(true);
|
||||
synopsis_h = m_theme.getInt("GAMEINFO/SYNOPSIS", "height", 280);
|
||||
}
|
||||
|
||||
void CMenu::_textGameInfo(void)
|
||||
|
@ -15,6 +15,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
#include "menu.hpp"
|
||||
#include "channel/nand.hpp"
|
||||
#include "loader/cios.h"
|
||||
#include "loader/nk.h"
|
||||
#include "const_str.hpp"
|
||||
@ -65,6 +66,7 @@ bool CMenu::_Home(void)
|
||||
m_btnMgr.down();
|
||||
else if(BTN_1_PRESSED)
|
||||
{
|
||||
m_theme.load(fmt("%s.ini", m_themeDataDir.c_str()));
|
||||
m_theme.save();
|
||||
_hideHome();
|
||||
error(_t("savedtheme", L"Theme config saved!"));
|
||||
@ -179,7 +181,7 @@ bool CMenu::_ExitTo(void)
|
||||
m_btnMgr.up();
|
||||
else if(BTN_DOWN_PRESSED)
|
||||
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))
|
||||
{
|
||||
@ -209,15 +211,28 @@ bool CMenu::_ExitTo(void)
|
||||
if(!Load_Neek2o_Kernel())
|
||||
{
|
||||
error(_fmt("errneek1", L"Cannot launch neek2o. Verify your neek2o setup"));
|
||||
exitHandler(PRIILOADER_DEF);
|
||||
_showExitTo();
|
||||
}
|
||||
else
|
||||
{
|
||||
//bool nkWiiflow = m_cfg.getBool("NEEK2O", "launchwiiflow", true);
|
||||
//if(nkWiiflow)
|
||||
//if(m_cfg.getBool("NEEK2O", "launchwiiflow", true) && !neek2o())
|
||||
// exitHandler(EXIT_TO_WFNK2O);
|
||||
//else
|
||||
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;
|
||||
}
|
||||
|
@ -751,23 +751,10 @@ int CMenu::main(void)
|
||||
ScanInput();
|
||||
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()));
|
||||
_launchHomebrew(fmt("%s/boot.dol", m_appDir.c_str()), arguments);
|
||||
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();
|
||||
//gprintf("Saving configuration files\n");
|
||||
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.
|
||||
{
|
||||
struct stat dummy;
|
||||
if(!DeviceHandle.IsInserted(SD) ||
|
||||
stat("sd:/bootmii/armboot.bin", &dummy) != 0 ||
|
||||
stat("sd:/bootmii/ppcboot.elf", &dummy) != 0)
|
||||
if(!DeviceHandle.IsInserted(SD) || stat("sd:/bootmii/armboot.bin", &dummy) != 0 || stat("sd:/bootmii/ppcboot.elf", &dummy) != 0)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ int curSavesNand = 0;
|
||||
vector<string> emuNands;
|
||||
vector<string> savesNands;
|
||||
bool m_nandext;
|
||||
bool m_fulldump;
|
||||
bool m_nanddump;
|
||||
bool m_sgdump;
|
||||
bool m_saveall;
|
||||
|
||||
@ -78,7 +78,7 @@ void CMenu::_listEmuNands(const char *path, vector<string> &emuNands)
|
||||
DIR *d;
|
||||
struct dirent *dir;
|
||||
emuNands.clear();
|
||||
bool def = true;
|
||||
bool add_def = true;
|
||||
|
||||
d = opendir(path);
|
||||
if(d != 0)
|
||||
@ -90,14 +90,13 @@ void CMenu::_listEmuNands(const char *path, vector<string> &emuNands)
|
||||
if(dir->d_type == DT_DIR)
|
||||
{
|
||||
emuNands.push_back(dir->d_name);
|
||||
string filename = dir->d_name;
|
||||
if(filename == "default")
|
||||
def = false;
|
||||
if(strlen(dir->d_name) == 7 && strcasecmp(dir->d_name, "default") == 0)
|
||||
add_def = false;
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
if(def)
|
||||
if(add_def)
|
||||
emuNands.push_back("default");
|
||||
sort(emuNands.begin(), emuNands.end());
|
||||
}
|
||||
@ -115,7 +114,10 @@ void CMenu::_checkEmuNandSettings(void)
|
||||
for(i = SD; i < MAXDEVICES; i++)// find first usable partition
|
||||
{
|
||||
if(DeviceHandle.PartitionUsableForNandEmu(i))
|
||||
{
|
||||
emuPart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == MAXDEVICES)// if no usable partitions found set to SD for now
|
||||
emuPart = SD;
|
||||
@ -126,7 +128,10 @@ void CMenu::_checkEmuNandSettings(void)
|
||||
for(i = SD; i < MAXDEVICES; i++)
|
||||
{
|
||||
if(DeviceHandle.PartitionUsableForNandEmu(i))
|
||||
{
|
||||
savesPart = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == MAXDEVICES)
|
||||
savesPart = SD;
|
||||
@ -191,13 +196,13 @@ void CMenu::_FullNandCheck(void)
|
||||
for(u8 i = 0; i < 2; i++)
|
||||
{
|
||||
int emulate_mode;
|
||||
if(i == 0)
|
||||
if(i == EMU_NAND)
|
||||
emulate_mode = m_cfg.getInt(CHANNEL_DOMAIN, "emulation", 0);
|
||||
else
|
||||
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)
|
||||
continue;
|
||||
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;
|
||||
char tmpPath[MAX_FAT_PATH];
|
||||
@ -242,7 +247,7 @@ int CMenu::_FindEmuPart(bool skipchecks, bool savesnand)
|
||||
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());
|
||||
}
|
||||
if(!DeviceHandle.PartitionUsableForNandEmu(emuPart))
|
||||
if(!DeviceHandle.PartitionUsableForNandEmu(emuPart))//check if device is mounted and partition is FAT
|
||||
return -1;
|
||||
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];
|
||||
if(nand)
|
||||
if(nand_type == REAL_NAND)
|
||||
{
|
||||
u32 temp = 0;
|
||||
if(ISFS_ReadDir(fmt("/title/00010000/%08x", savePath), NULL, &temp) < 0)
|
||||
if(ISFS_ReadDir(fmt("/title/00010004/%08x", savePath), NULL, &temp) < 0)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
else // SAVES_NAND
|
||||
{
|
||||
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());
|
||||
@ -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)))
|
||||
{
|
||||
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)
|
||||
{
|
||||
_hideNandEmu(true);
|
||||
error(_t("cfgne8", L"No valid FAT partition found for NAND Emulation!"));
|
||||
_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_nandfilePBar);
|
||||
m_btnMgr.show(m_nandemuPBar);
|
||||
@ -611,14 +615,14 @@ int CMenu::_NandEmuCfg(void)
|
||||
m_btnMgr.setText(m_nandemuLblMessage, L"");
|
||||
m_btnMgr.setText(m_nandfileLblMessage, L"");
|
||||
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"));
|
||||
}
|
||||
else
|
||||
else // saves dump
|
||||
{
|
||||
ExtNand = savesNands[curSavesNand];
|
||||
//ExtNand = savesNands[curSavesNand];
|
||||
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne13", L"Game Save Extractor"));
|
||||
}
|
||||
m_thrdStop = false;
|
||||
@ -693,6 +697,7 @@ int CMenu::_NandEmuCfg(void)
|
||||
}
|
||||
_hideNandEmu();
|
||||
_FullNandCheck();
|
||||
/* if changed emunand choice or emunand is the new one extracted */
|
||||
if(emuNand != m_cfg.getString(CHANNEL_DOMAIN, "current_emunand") || emuNand == ExtNand)
|
||||
{
|
||||
m_cfg.setBool(CHANNEL_DOMAIN, "update_cache", true);
|
||||
@ -704,26 +709,18 @@ int CMenu::_NandEmuCfg(void)
|
||||
|
||||
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;
|
||||
|
||||
if(!_checkSave(gameId, false))// if save not on savenand
|
||||
if(!_checkSave(gameId, SAVES_NAND))// if save not on saves emunand
|
||||
return 0;
|
||||
|
||||
lwp_t thread = 0;
|
||||
SetupInput();
|
||||
m_thrdStop = false;
|
||||
m_thrdMessageAdded = false;
|
||||
m_nandext = false;
|
||||
|
||||
m_saveExtGameId = gameId;
|
||||
|
||||
while(!m_exit)
|
||||
{
|
||||
_mainLoopCommon();
|
||||
if(m_forceext)
|
||||
{
|
||||
m_forceext = false;
|
||||
m_btnMgr.show(m_nandemuLblTitle);
|
||||
m_btnMgr.show(m_nandfilePBar);
|
||||
m_btnMgr.show(m_nandemuPBar);
|
||||
@ -735,11 +732,15 @@ int CMenu::_FlashSave(string gameId)
|
||||
m_btnMgr.setText(m_nandfileLblMessage, L"");
|
||||
m_btnMgr.setText(m_nandemuLblDialog, _t("cfgne11", L"Overall Progress:"));
|
||||
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne28", L"Game Save Flasher"));
|
||||
m_thrdStop = false;
|
||||
m_thrdProgress = 0.f;
|
||||
m_thrdWorking = true;
|
||||
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))))
|
||||
break;
|
||||
|
||||
@ -771,19 +772,19 @@ int CMenu::_FlashSave(string gameId)
|
||||
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);
|
||||
if(m_forceext && emuPart == -1)// if game config force extract and savenand partition unusable
|
||||
int emuPart = _FindEmuPart(SAVES_NAND, false);
|
||||
if(emuPart == -1)// if savesnand partition unusable
|
||||
{
|
||||
m_forceext = false;
|
||||
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];
|
||||
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/meta", 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/ticket", 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;
|
||||
|
||||
if(!m_forceext && _checkSave(gameId, false))//if wii game launch and save is already on emunand
|
||||
return 1;
|
||||
|
||||
lwp_t thread = 0;
|
||||
m_thrdStop = false;
|
||||
m_thrdMessageAdded = false;
|
||||
m_nandext = false;
|
||||
m_saveExtGameId = gameId;
|
||||
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_nandfilePBar);
|
||||
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_nandemuLblDialog, _t("cfgne11", L"Overall Progress:"));
|
||||
m_btnMgr.setText(m_nandemuLblTitle, _t("cfgne13", L"Game Save Extractor"));
|
||||
m_thrdStop = false;
|
||||
m_thrdProgress = 0.f;
|
||||
m_thrdWorking = true;
|
||||
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();
|
||||
return 0;
|
||||
}
|
||||
else if(finished && (BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack))))
|
||||
_mainLoopCommon();
|
||||
if(finished && (BTN_HOME_PRESSED || BTN_B_PRESSED || (BTN_A_PRESSED && m_btnMgr.selected(m_nandemuBtnBack))))
|
||||
break;
|
||||
|
||||
if(m_thrdMessageAdded)
|
||||
@ -893,7 +865,7 @@ void * CMenu::_NandFlasher(void *obj)
|
||||
char source[MAX_FAT_PATH];
|
||||
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();
|
||||
int flashID = SaveGameID[0] << 24 | SaveGameID[1] << 16 | SaveGameID[2] << 8 | SaveGameID[3];
|
||||
@ -939,7 +911,7 @@ void * CMenu::_NandDumper(void *obj)
|
||||
|
||||
NandHandle.ResetCounters();
|
||||
|
||||
int emuPartition = m._FindEmuPart(true, !m_fulldump);
|
||||
int emuPartition = m._FindEmuPart(!m_nanddump, true);
|
||||
const char *emuPath = NandHandle.Get_NandPath();
|
||||
char basepath[64];
|
||||
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);
|
||||
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_nandext = true;
|
||||
@ -977,9 +949,9 @@ void * CMenu::_NandDumper(void *obj)
|
||||
{
|
||||
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++;
|
||||
saveList.push_back(id);
|
||||
@ -1000,7 +972,7 @@ void * CMenu::_NandDumper(void *obj)
|
||||
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];
|
||||
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);
|
||||
|
||||
m.m_dumpsize = NandHandle.CalcDumpSpace(source, CMenu::_ShowProgress, obj);
|
||||
@ -1011,7 +983,7 @@ void * CMenu::_NandDumper(void *obj)
|
||||
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];
|
||||
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);
|
||||
|
||||
m_nandext = true;
|
||||
|
@ -444,7 +444,7 @@ void CMenu::_Wad(const char *wad_path)
|
||||
int emuPart = 0;
|
||||
if(!mios)
|
||||
{
|
||||
emuPart = _FindEmuPart(false, false);
|
||||
emuPart = _FindEmuPart(EMU_NAND, false);
|
||||
if(emuPart < 0)
|
||||
{
|
||||
//cfgne8=No valid FAT partition found for NAND Emulation!
|
||||
|
@ -323,7 +323,7 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
||||
}
|
||||
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;
|
||||
break;
|
||||
|
||||
@ -349,6 +349,10 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
||||
}
|
||||
else if(Disc_IsGC() == 0)
|
||||
{
|
||||
error(_t("wbfsoperr6", L"Install game is broken, please use cleanrip."));
|
||||
out = true;
|
||||
break;
|
||||
|
||||
Disc_ReadGCHeader(&gc_hdr);
|
||||
memcpy(GameID, gc_hdr.id, 6);
|
||||
if(_searchGamesByID(GameID))
|
||||
@ -392,14 +396,14 @@ bool CMenu::_wbfsOp(CMenu::WBFS_OP op)
|
||||
if(strcasestr(CF_Hdr->path, "boot.bin") != NULL)
|
||||
{
|
||||
strncpy(GC_Path, CF_Hdr->path, 1023);
|
||||
*strrchr(GC_Path, '/') = '\0'; //boot.bin
|
||||
*strrchr(GC_Path, '/') = '\0'; //sys
|
||||
*strrchr(GC_Path, '/') = '\0'; // remove /boot.bin from path
|
||||
*strrchr(GC_Path, '/') = '\0'; // remove /sys folder from path
|
||||
fsop_deleteFolder(GC_Path);
|
||||
}
|
||||
else
|
||||
{
|
||||
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]);
|
||||
if(strcasecmp(GC_Path, cmp) == 0)
|
||||
fsop_deleteFile(CF_Hdr->path);
|
||||
|
@ -11,6 +11,12 @@ enum {
|
||||
NINTENDONT
|
||||
};
|
||||
|
||||
enum {
|
||||
EMU_NAND = 0,
|
||||
SAVES_NAND,
|
||||
REAL_NAND
|
||||
};
|
||||
|
||||
enum {
|
||||
CHANNELS_REAL = 1,
|
||||
CHANNELS_EMU,
|
||||
|
@ -451,7 +451,7 @@ wbfsoperr2=Disc_Open failed
|
||||
wbfsoperr3=This is not a Wii disc!
|
||||
wbfsoperr4=Game already installed
|
||||
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%%
|
||||
wbfsremdlg=To permanently remove the game : %s, click on Go.
|
||||
wifiplayers= Wifi Players
|
||||
|
Loading…
Reference in New Issue
Block a user