-added flash screen image to appear before wiiflow wait animation. i hope the image isn't too big to cause problems with wfl.

-added 'noflash' arg for meta.xml if you don't want the flash screen image to appear. and no i can't make it load a image from a folder. it must be compiled in the code.
-added 'sdonly' arg for meta.xml for those of you that have everything on SD and hate the 20 second wait for wiiflow to search for usb devices. thanks einsteinx2!
-added meta.xml args support. meaning when a homebrew boot.dol or elf is launched the meta.xml (if exist) will be read for arguments and those args sent when the app is launched. this fixes the issue of custom wait images when changing themes.
-added spanish translation file 'spanish.ini'. thanks to ravmn for sending it to me!
-other minor changes, mainly remarks added for myself.
This commit is contained in:
fledge68 2018-06-27 12:47:03 +00:00
parent 1e57a1c9e6
commit 4a566375e0
16 changed files with 685 additions and 463 deletions

BIN
data/images/splash.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@ -42,9 +42,10 @@ DeviceHandler DeviceHandle;
void DeviceHandler::Init()
{
/* PartitionHandle inits */
sd.Init();
usb.Init();
OGC_Device.Init();
OGC_Device.Init();// used for Devolution gamecube iso launcher
}
void DeviceHandler::MountAll()

View File

@ -356,9 +356,16 @@ void CCoverFlow::setRange(u32 rows, u32 columns)
if (m_covers != NULL)
{
stopCoverLoader();
MEM2_free(m_covers);
CCover *tmpCovers = (CCover*)MEM2_alloc(sizeof(CCover) * range);
for(size_t i = 0; i < range; ++i)
tmpCovers[i] = *(new(tmpCovers+i) CCover);
{
// does not allocate memory -- calls: operator new (sizeof(CCover), tmpCovers+i)
// only constructs an object at tmpCovers+i
// delete is not needed
// this is the same as CCover tmpCovers[range] except the objects memory address is specified and won't go out of scope
tmpCovers[i] = *(new (tmpCovers+i) CCover);
}
if (rows >= 3)
for (u32 x = 0; x < columns; ++x)
for (u32 y = 1; y < rows - 1; ++y)
@ -369,7 +376,6 @@ void CCoverFlow::setRange(u32 rows, u32 columns)
m_rows = rows;
m_columns = columns;
m_range = range;
MEM2_free(m_covers);
m_covers = tmpCovers;
_loadAllCovers(m_covers[m_range / 2].index);
_updateAllTargets();
@ -1903,7 +1909,7 @@ bool CCoverFlow::start(const string &m_imgsDir)
m_covers = NULL;
if(m_range > 0)
{
m_covers = (CCover*)MEM2_alloc(sizeof(struct CCover) * m_range);
m_covers = (CCover*)MEM2_alloc(sizeof(CCover) * m_range);
for(size_t i = 0; i < m_range; ++i)
m_covers[i] = *(new(m_covers+i) CCover);
}

View File

@ -748,6 +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;
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);
@ -795,6 +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;
b.font.font->setXScale(scaleX);
b.font.font->setYScale(scaleY);
float posX = b.pos.x;

View File

@ -3,6 +3,7 @@
#include <unistd.h>
#include <malloc.h>
#include <ogc/machine/processor.h>
#include <algorithm>
#include "memory/mem2.hpp"
#include "video.hpp"
#include "pngu.h"
@ -17,25 +18,6 @@
#define DEFAULT_FIFO_SIZE (256 * 1024)
extern const u8 wait_01_jpg[];
extern const u32 wait_01_jpg_size;
extern const u8 wait_02_jpg[];
extern const u32 wait_02_jpg_size;
extern const u8 wait_03_jpg[];
extern const u32 wait_03_jpg_size;
extern const u8 wait_04_jpg[];
extern const u32 wait_04_jpg_size;
extern const u8 wait_05_jpg[];
extern const u32 wait_05_jpg_size;
extern const u8 wait_06_jpg[];
extern const u32 wait_06_jpg_size;
extern const u8 wait_07_jpg[];
extern const u32 wait_07_jpg_size;
extern const u8 wait_08_jpg[];
extern const u32 wait_08_jpg_size;
vector<TexData> m_defaultWaitMessages;
const float CVideo::_jitter2[2][2] = {
{ 0.246490f, 0.249999f },
{ -0.246490f, -0.249999f }
@ -115,20 +97,10 @@ GXRModeObj TVPal574IntDfScale =
}
};
struct movieP normalMoviePos = { 410, 31, 610, 181 };
struct movieP zoomedMoviePos = { 0, 0, 640, 480 };
struct movieP currentMoviePos = zoomedMoviePos;
const int CVideo::_stencilWidth = 128;
const int CVideo::_stencilHeight = 128;
static lwp_t waitThread = LWP_THREAD_NULL;
vector<TexData> m_defaultWaitMessages;
CVideo m_vid;
u8 CVideo::waitMessageStack[2048] ATTRIBUTE_ALIGN(32);
const u32 CVideo::waitMessageStackSize = 2048;
CVideo::CVideo(void) :
m_rmode(NULL), m_frameBuf(), m_curFB(0), m_fifo(NULL),
m_yScale(0.0f), m_xfbHeight(0), m_wide(false),
@ -139,35 +111,6 @@ CVideo::CVideo(void) :
memset(m_frameBuf, 0, sizeof m_frameBuf);
}
void CColor::blend(const CColor &src)
{
if (src.a == 0) return;
r = (u8)(((int)src.r * (int)src.a + (int)r * (0xFF - (int)src.a)) / 0xFF);
g = (u8)(((int)src.g * (int)src.a + (int)g * (0xFF - (int)src.a)) / 0xFF);
b = (u8)(((int)src.b * (int)src.a + (int)b * (0xFF - (int)src.a)) / 0xFF);
}
CColor CColor::interpolate(const CColor &c1, const CColor &c2, u8 n)
{
CColor c;
c.r = (u8)(((int)c2.r * (int)n + (int)c1.r * (0xFF - (int)n)) / 0xFF);
c.g = (u8)(((int)c2.g * (int)n + (int)c1.g * (0xFF - (int)n)) / 0xFF);
c.b = (u8)(((int)c2.b * (int)n + (int)c1.b * (0xFF - (int)n)) / 0xFF);
c.a = (u8)(((int)c2.a * (int)n + (int)c1.a * (0xFF - (int)n)) / 0xFF);
return c;
}
void CVideo::setAA(u8 aa, bool alpha, int width, int height)
{
if (aa <= 8 && aa != 7 && width <= m_rmode->fbWidth && height <= m_rmode->efbHeight && ((width | height) & 3) == 0)
{
m_aa = aa;
m_aaAlpha = alpha;
m_aaWidth = width;
m_aaHeight = height;
}
}
void CVideo::init(void)
{
/* General Video Init */
@ -212,11 +155,15 @@ void CVideo::init(void)
m_frameBuf[0] = MEM_K0_TO_K1(MEM1_memalign(32, VIDEO_GetFrameBufferSize(m_rmode)));
m_frameBuf[1] = MEM_K0_TO_K1(MEM1_memalign(32, VIDEO_GetFrameBufferSize(m_rmode)));
m_curFB = 0;
m_fifo = MEM1_memalign(32, DEFAULT_FIFO_SIZE);
memset(m_fifo, 0, DEFAULT_FIFO_SIZE);
GX_Init(m_fifo, DEFAULT_FIFO_SIZE);
GX_SetCopyClear(CColor(0), 0x00FFFFFF);
_setViewPort(0, 0, m_rmode->fbWidth, m_rmode->efbHeight);
m_yScale = GX_GetYScaleFactor(m_rmode->efbHeight, m_rmode->xfbHeight);
m_xfbHeight = GX_SetDispCopyYScale(m_yScale);
GX_SetScissor(0, 0, m_rmode->fbWidth, m_rmode->efbHeight);
@ -237,11 +184,14 @@ void CVideo::init(void)
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORDNULL, GX_TEXMAP_NULL, GX_COLOR0A0);
GX_SetNumChans(0);
GX_SetZCompLoc(GX_ENABLE);
setup2DProjection();
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
for(u32 i = 0; i < 8; i++)
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0+i, GX_TEX_ST, GX_F32, 0);
m_stencil = MEM1_memalign(32, CVideo::_stencilWidth * CVideo::_stencilHeight);
memset(m_stencil, 0, CVideo::_stencilWidth * CVideo::_stencilHeight);
@ -255,65 +205,6 @@ void CVideo::init(void)
VIDEO_WaitVSync();
}
void CVideo::_clearScreen()
{
VIDEO_ClearFrameBuffer(m_rmode, m_frameBuf[0], COLOR_BLACK);
VIDEO_ClearFrameBuffer(m_rmode, m_frameBuf[1], COLOR_BLACK);
render();
render();
}
void CVideo::set2DViewport(u32 w, u32 h, int x, int y)
{
m_width2D = std::min(std::max(512ul, w), 800ul);
m_height2D = std::min(std::max(384ul, h), 600ul);
m_x2D = std::min(std::max(-50, x), 50);
m_y2D = std::min(std::max(-50, y), 50);
}
void CVideo::setup2DProjection(bool setViewPort, bool noScale)
{
Mtx44 projMtx;
float width2D = noScale ? 640.f : (float)m_width2D;
float height2D = noScale ? 480.f : (float)m_height2D;
float x = noScale ? 0.f : (float)(640 - width2D) * 0.5f + (float)m_x2D;
float y = noScale ? 0.f : (float)(480 - height2D) * 0.5f + (float)m_y2D;
if (setViewPort)
_setViewPort(0, 0, m_rmode->fbWidth, m_rmode->efbHeight);
guOrtho(projMtx, y, height2D + y, x, width2D + x, 0.f, 1000.0f);
GX_LoadProjectionMtx(projMtx, GX_ORTHOGRAPHIC);
}
void CVideo::renderToTexture(TexData &tex, bool clear)
{
if(tex.data == NULL)
{
tex.dataSize = GX_GetTexBufferSize(tex.width, tex.height, tex.format, GX_FALSE, 0);
tex.data = (u8*)MEM2_alloc(tex.dataSize);
if(tex.data == NULL)
return;
}
GX_DrawDone();
GX_SetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
GX_SetTexCopySrc(0, 0, tex.width, tex.height);
GX_SetTexCopyDst(tex.width, tex.height, tex.format, GX_FALSE);
GX_CopyTex(tex.data, clear ? GX_TRUE : GX_FALSE);
GX_PixModeSync();
GX_SetCopyFilter(m_rmode->aa, m_rmode->sample_pattern, GX_TRUE, m_rmode->vfilter);
DCFlushRange(tex.data, tex.dataSize);
GX_SetScissor(0, 0, m_rmode->fbWidth, m_rmode->efbHeight);
}
void CVideo::prepare(void)
{
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();
GX_InvalidateTexAll();
}
void CVideo::cleanup(void)
{
//gprintf("Cleaning up video...\n");
@ -350,6 +241,79 @@ void CVideo::cleanup(void)
m_fifo = NULL;
}
void CVideo::_clearScreen()
{
VIDEO_ClearFrameBuffer(m_rmode, m_frameBuf[0], COLOR_BLACK);
VIDEO_ClearFrameBuffer(m_rmode, m_frameBuf[1], COLOR_BLACK);
render();
render();
}
void CVideo::prepare(void)
{
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();
GX_InvalidateTexAll();
}
void CVideo::setup2DProjection(bool setViewPort, bool noScale)
{
Mtx44 projMtx;
float width2D = noScale ? 640.f : (float)m_width2D;
float height2D = noScale ? 480.f : (float)m_height2D;
float x = noScale ? 0.f : (float)(640 - width2D) * 0.5f + (float)m_x2D;
float y = noScale ? 0.f : (float)(480 - height2D) * 0.5f + (float)m_y2D;
if (setViewPort)
_setViewPort(0, 0, m_rmode->fbWidth, m_rmode->efbHeight);
guOrtho(projMtx, y, height2D + y, x, width2D + x, 0.f, 1000.0f);
GX_LoadProjectionMtx(projMtx, GX_ORTHOGRAPHIC);
}
void CVideo::_setViewPort(float x, float y, float w, float h)
{
m_vpX = x;
m_vpY = y;
m_vpW = w;
m_vpH = h;
GX_SetViewport(x, y, w, h, 0.f, 1.f);
}
void CVideo::shiftViewPort(float x, float y)
{
GX_SetViewport(m_vpX + x, m_vpY + y, m_vpW, m_vpH, 0.f, 1.f);
}
void CVideo::set2DViewport(u32 w, u32 h, int x, int y)
{
m_width2D = std::min(std::max(512ul, w), 800ul);
m_height2D = std::min(std::max(384ul, h), 600ul);
m_x2D = std::min(std::max(-50, x), 50);
m_y2D = std::min(std::max(-50, y), 50);
}
void CVideo::renderToTexture(TexData &tex, bool clear)
{
if(tex.data == NULL)
{
tex.dataSize = GX_GetTexBufferSize(tex.width, tex.height, tex.format, GX_FALSE, 0);
tex.data = (u8*)MEM2_alloc(tex.dataSize);
if(tex.data == NULL)
return;
}
GX_DrawDone();
GX_SetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
GX_SetTexCopySrc(0, 0, tex.width, tex.height);
GX_SetTexCopyDst(tex.width, tex.height, tex.format, GX_FALSE);
GX_CopyTex(tex.data, clear ? GX_TRUE : GX_FALSE);
GX_PixModeSync();
GX_SetCopyFilter(m_rmode->aa, m_rmode->sample_pattern, GX_TRUE, m_rmode->vfilter);
DCFlushRange(tex.data, tex.dataSize);
GX_SetScissor(0, 0, m_rmode->fbWidth, m_rmode->efbHeight);
}
void CVideo::prepareAAPass(int aaStep)
{
float x = 0.f;
@ -390,31 +354,6 @@ void CVideo::prepareAAPass(int aaStep)
GX_InvalidateTexAll();
}
void CVideo::renderAAPass(int aaStep)
{
u8 texFmt = GX_TF_RGBA8;
u32 w = m_aaWidth <= 0 ? m_rmode->fbWidth : (u32)m_aaWidth;
u32 h = m_aaHeight <= 0 ? m_rmode->efbHeight: (u32)m_aaHeight;
u32 bufLen = GX_GetTexBufferSize(w, h, texFmt, GX_FALSE, 0);
if (!m_aaBuffer[aaStep] || m_aaBufferSize[aaStep] < bufLen)
{
m_aaBuffer[aaStep] = (u8*)MEM2_alloc(bufLen);
if (m_aaBuffer[aaStep] != NULL)
m_aaBufferSize[aaStep] = bufLen;
}
if (!m_aaBuffer[aaStep] || m_aaBufferSize[aaStep] < bufLen)
return;
GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_TRUE);
GX_DrawDone();
GX_SetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
GX_SetTexCopySrc(0, 0, w, h);
GX_SetTexCopyDst(w, h, texFmt, GX_FALSE);
GX_CopyTex(m_aaBuffer[aaStep], GX_TRUE);
GX_PixModeSync();
GX_SetCopyFilter(m_rmode->aa, m_rmode->sample_pattern, GX_TRUE, m_rmode->vfilter);
}
void CVideo::drawAAScene(bool fs)
{
GXTexObj texObj[8];
@ -488,57 +427,28 @@ void CVideo::drawAAScene(bool fs)
GX_SetNumTevStages(1);
}
void CVideo::_setViewPort(float x, float y, float w, float h)
void CVideo::renderAAPass(int aaStep)
{
m_vpX = x;
m_vpY = y;
m_vpW = w;
m_vpH = h;
GX_SetViewport(x, y, w, h, 0.f, 1.f);
}
u8 texFmt = GX_TF_RGBA8;
u32 w = m_aaWidth <= 0 ? m_rmode->fbWidth : (u32)m_aaWidth;
u32 h = m_aaHeight <= 0 ? m_rmode->efbHeight: (u32)m_aaHeight;
u32 bufLen = GX_GetTexBufferSize(w, h, texFmt, GX_FALSE, 0);
void CVideo::shiftViewPort(float x, float y)
{
GX_SetViewport(m_vpX + x, m_vpY + y, m_vpW, m_vpH, 0.f, 1.f);
}
static inline u32 coordsI8(u32 x, u32 y, u32 w)
{
return (((y >> 2) * (w >> 3) + (x >> 3)) << 5) + ((y & 3) << 3) + (x & 7);
}
int CVideo::stencilVal(int x, int y)
{
if ((u32)x >= m_rmode->fbWidth || (u32)y >= m_rmode->efbHeight)
return 0;
x = x * CVideo::_stencilWidth / 640;
y = y * CVideo::_stencilHeight / 480;
u32 i = coordsI8(x, y, (u32)CVideo::_stencilWidth);
if (i >= (u32)(CVideo::_stencilWidth * CVideo::_stencilHeight))
return 0;
return ((u8*)m_stencil)[i];
}
void CVideo::prepareStencil(void)
{
GX_SetPixelFmt(GX_PF_Y8, GX_ZC_LINEAR);
_setViewPort(0.f, 0.f, (float)CVideo::_stencilWidth, (float)CVideo::_stencilHeight);
GX_SetScissor(0, 0, CVideo::_stencilWidth, CVideo::_stencilHeight);
GX_InvVtxCache();
GX_InvalidateTexAll();
}
void CVideo::renderStencil(void)
{
GX_DrawDone();
if (!m_aaBuffer[aaStep] || m_aaBufferSize[aaStep] < bufLen)
{
m_aaBuffer[aaStep] = (u8*)MEM2_alloc(bufLen);
if (m_aaBuffer[aaStep] != NULL)
m_aaBufferSize[aaStep] = bufLen;
}
if (!m_aaBuffer[aaStep] || m_aaBufferSize[aaStep] < bufLen)
return;
GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_TRUE);
GX_SetColorUpdate(GX_TRUE);
GX_DrawDone();
GX_SetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
GX_SetTexCopySrc(0, 0, CVideo::_stencilWidth, CVideo::_stencilHeight);
GX_SetTexCopyDst(CVideo::_stencilWidth, CVideo::_stencilHeight, GX_CTF_R8, GX_FALSE);
GX_CopyTex(m_stencil, GX_TRUE);
GX_SetTexCopySrc(0, 0, w, h);
GX_SetTexCopyDst(w, h, texFmt, GX_FALSE);
GX_CopyTex(m_aaBuffer[aaStep], GX_TRUE);
GX_PixModeSync();
DCFlushRange(m_stencil, CVideo::_stencilWidth * CVideo::_stencilHeight);
GX_SetCopyFilter(m_rmode->aa, m_rmode->sample_pattern, GX_TRUE, m_rmode->vfilter);
}
@ -556,12 +466,38 @@ void CVideo::render(void)
GX_InvalidateTexAll();
}
/* wait animation control */
extern const u8 splash_jpg[];
extern const u32 splash_jpg_size;
extern const u8 wait_01_jpg[];
extern const u32 wait_01_jpg_size;
extern const u8 wait_02_jpg[];
extern const u32 wait_02_jpg_size;
extern const u8 wait_03_jpg[];
extern const u32 wait_03_jpg_size;
extern const u8 wait_04_jpg[];
extern const u32 wait_04_jpg_size;
extern const u8 wait_05_jpg[];
extern const u32 wait_05_jpg_size;
extern const u8 wait_06_jpg[];
extern const u32 wait_06_jpg_size;
extern const u8 wait_07_jpg[];
extern const u32 wait_07_jpg_size;
extern const u8 wait_08_jpg[];
extern const u32 wait_08_jpg_size;
static lwp_t waitThread = LWP_THREAD_NULL;
u8 CVideo::waitMessageStack[2048] ATTRIBUTE_ALIGN(32);
const u32 CVideo::waitMessageStackSize = 2048;
bool custom = false;
bool waitLoop = false;
static vector<string> waitImgs;
static void GrabWaitFiles(char *FullPath)
{
//Just push back
waitImgs.push_back(FullPath);
}
@ -573,13 +509,14 @@ void CVideo::setCustomWaitImgs(const char *path, bool wait_loop)
GetFiles(path, stringToVector(".png|.jpg", '|'), GrabWaitFiles, false, 1);
if(waitImgs.size() > 0)
{
sort(waitImgs.begin(), waitImgs.end());
custom = true;
waitLoop = wait_loop;
}
}
}
void CVideo::waitMessage(float delay)// called from main.cpp to show wait animation on wf boot
void CVideo::waitMessage(float delay)// set wait images from custom or internal
{
if(m_defaultWaitMessages.size() == 0)
{
@ -613,7 +550,7 @@ void CVideo::waitMessage(float delay)// called from main.cpp to show wait animat
waitMessage(m_defaultWaitMessages, delay);
}
void CVideo::waitMessage(const vector<TexData> &tex, float delay)// start wait images and wii slot light threads or draw
void CVideo::waitMessage(const vector<TexData> &tex, float delay)// start wait images and wii slot light threads
{
hideWaitMessage();
@ -698,7 +635,7 @@ void * CVideo::_showWaitMessages(void *obj)// wait images thread
return NULL;
}
void CVideo::hideWaitMessage()// stop wait images and wii disc slot light threads
void CVideo::hideWaitMessage()// stop wait images thread and wii disc slot light thread
{
m_showWaitMessage = false;
if(waitThread != LWP_THREAD_NULL)
@ -716,7 +653,9 @@ void CVideo::hideWaitMessage()// stop wait images and wii disc slot light thread
waitThread = LWP_THREAD_NULL;
}
void CVideo::waitMessage(const TexData &tex)//draw frame image
/* draws wait animation image centered on screen */
/* can be used to draw any texture centered on screen */
void CVideo::waitMessage(const TexData &tex)
{
Mtx modelViewMtx;
GXTexObj texObj;
@ -743,7 +682,7 @@ void CVideo::waitMessage(const TexData &tex)//draw frame image
GX_LoadTexObj(&texObj, GX_TEXMAP0);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
u32 texWidth = m_wide ? tex.width * .75 : tex.width;
GX_Position3f32((float)((640 - texWidth) / 2), (float)((480 - tex.height) / 2), 0.f);// widescreen = tex.width * .80
GX_Position3f32((float)((640 - texWidth) / 2), (float)((480 - tex.height) / 2), 0.f);
GX_TexCoord2f32(0.f, 0.f);
GX_Position3f32((float)((640 + texWidth) / 2), (float)((480 - tex.height) / 2), 0.f);
GX_TexCoord2f32(1.f, 0.f);
@ -754,6 +693,17 @@ void CVideo::waitMessage(const TexData &tex)//draw frame image
GX_End();
}
/* draw and render startup splash screen */
void CVideo::startImage(void)
{
TexData splashTex;
TexHandle.fromJPG(splashTex, splash_jpg, splash_jpg_size);
waitMessage(splashTex);
render();
TexHandle.Cleanup(splashTex);
}
/* save screenshot */
s32 CVideo::TakeScreenshot(const char *path)
{
IMGCTX ctx = PNGU_SelectImageFromDevice(path);
@ -762,7 +712,9 @@ s32 CVideo::TakeScreenshot(const char *path)
return ret;
}
void DrawTexture(TexData * &tex)// used by coverflow to draw cover texture. use in mainloopcommon() in menu.cpp
/* used by coverflow to draw cover texture. used in mainloopcommon() in menu.cpp */
/* this draws a texture in the upper left at 0,0 */
void DrawTexture(TexData * &tex)
{
if(tex == NULL)
return;
@ -805,35 +757,14 @@ void DrawTexture(TexData * &tex)// used by coverflow to draw cover texture. use
GX_End();
}
void DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color)// used by banner window and screen saver below
{
Mtx modelViewMtx;
guMtxIdentity(modelViewMtx);
GX_LoadPosMtxImm(modelViewMtx, GX_PNMTX0);
/* draws movie frame texture when playing movie in menu_game.cpp */
struct movieP normalMoviePos = { 410, 31, 610, 181 };
struct movieP zoomedMoviePos = { 0, 0, 640, 480 };
struct movieP currentMoviePos = zoomedMoviePos;
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
GX_ClearVtxDesc();
GX_InvVtxCache();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
int i;
f32 x2 = x + width;
f32 y2 = y + height;
guVector v[] = { { x, y, 0.0f }, { x2, y, 0.0f }, { x2, y2, 0.0f }, { x, y2, 0.0f }, { x, y, 0.0f } };
GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, 4);
for(i = 0; i < 4; i++)
{
GX_Position3f32(v[i].x, v[i].y, v[i].z);
GX_Color4u8(color.r, color.g, color.b, color.a);
}
GX_End();
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
}
void DrawTexturePos(const TexData *tex)// draws movie frame texture when playing movie in menu_game.cpp
/* draws a texture/image at a position and width and height specified by struct movieP currentMoviePos */
/* set currentMoviePos before calling this. example - {x, y, x+w, y+h} */
void DrawTexturePos(const TexData *tex)
{
Mtx modelViewMtx;
GXTexObj texObj;
@ -868,17 +799,122 @@ void DrawTexturePos(const TexData *tex)// draws movie frame texture when playing
GX_End();
}
/* screen saver and full banner frame */
void DrawRectangle(f32 x, f32 y, f32 width, f32 height, GXColor color)
{
Mtx modelViewMtx;
guMtxIdentity(modelViewMtx);
GX_LoadPosMtxImm(modelViewMtx, GX_PNMTX0);
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
GX_ClearVtxDesc();
GX_InvVtxCache();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT);
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE);
int i;
f32 x2 = x + width;
f32 y2 = y + height;
guVector v[] = { { x, y, 0.0f }, { x2, y, 0.0f }, { x2, y2, 0.0f }, { x, y2, 0.0f }, { x, y, 0.0f } };
GX_Begin(GX_TRIANGLEFAN, GX_VTXFMT0, 4);
for(i = 0; i < 4; i++)
{
GX_Position3f32(v[i].x, v[i].y, v[i].z);
GX_Color4u8(color.r, color.g, color.b, color.a);
}
GX_End();
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
}
void CVideo::screensaver(u32 no_input, u32 max_no_input)
{
if(no_input == 0)
if(no_input == 0)// no idle time so reset alpha to 0 for next time and don't draw the rectangle on this pass
{
m_screensaver_alpha = 0;
return;
}
if(no_input > max_no_input)
if(no_input > max_no_input)// if idle time > max idle draw rectangle full screen increasing alpha each time
{
DrawRectangle(0, 0, 640, 480, (GXColor){0,0,0,m_screensaver_alpha});
if(m_screensaver_alpha < 150)
m_screensaver_alpha+=2;
}
}
/* misc settings */
void CColor::blend(const CColor &src)
{
if (src.a == 0) return;
r = (u8)(((int)src.r * (int)src.a + (int)r * (0xFF - (int)src.a)) / 0xFF);
g = (u8)(((int)src.g * (int)src.a + (int)g * (0xFF - (int)src.a)) / 0xFF);
b = (u8)(((int)src.b * (int)src.a + (int)b * (0xFF - (int)src.a)) / 0xFF);
}
CColor CColor::interpolate(const CColor &c1, const CColor &c2, u8 n)
{
CColor c;
c.r = (u8)(((int)c2.r * (int)n + (int)c1.r * (0xFF - (int)n)) / 0xFF);
c.g = (u8)(((int)c2.g * (int)n + (int)c1.g * (0xFF - (int)n)) / 0xFF);
c.b = (u8)(((int)c2.b * (int)n + (int)c1.b * (0xFF - (int)n)) / 0xFF);
c.a = (u8)(((int)c2.a * (int)n + (int)c1.a * (0xFF - (int)n)) / 0xFF);
return c;
}
void CVideo::setAA(u8 aa, bool alpha, int width, int height)
{
if (aa <= 8 && aa != 7 && width <= m_rmode->fbWidth && height <= m_rmode->efbHeight && ((width | height) & 3) == 0)
{
m_aa = aa;
m_aaAlpha = alpha;
m_aaWidth = width;
m_aaHeight = height;
}
}
/* stencil used by coverflow */
const int CVideo::_stencilWidth = 128;
const int CVideo::_stencilHeight = 128;
static inline u32 coordsI8(u32 x, u32 y, u32 w)// used by stencilval below
{
return (((y >> 2) * (w >> 3) + (x >> 3)) << 5) + ((y & 3) << 3) + (x & 7);
}
int CVideo::stencilVal(int x, int y)
{
if ((u32)x >= m_rmode->fbWidth || (u32)y >= m_rmode->efbHeight)
return 0;
x = x * CVideo::_stencilWidth / 640;
y = y * CVideo::_stencilHeight / 480;
u32 i = coordsI8(x, y, (u32)CVideo::_stencilWidth);
if (i >= (u32)(CVideo::_stencilWidth * CVideo::_stencilHeight))
return 0;
return ((u8*)m_stencil)[i];
}
void CVideo::prepareStencil(void)
{
GX_SetPixelFmt(GX_PF_Y8, GX_ZC_LINEAR);
_setViewPort(0.f, 0.f, (float)CVideo::_stencilWidth, (float)CVideo::_stencilHeight);
GX_SetScissor(0, 0, CVideo::_stencilWidth, CVideo::_stencilHeight);
GX_InvVtxCache();
GX_InvalidateTexAll();
}
void CVideo::renderStencil(void)
{
GX_DrawDone();
GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_TRUE);
GX_SetColorUpdate(GX_TRUE);
GX_SetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
GX_SetTexCopySrc(0, 0, CVideo::_stencilWidth, CVideo::_stencilHeight);
GX_SetTexCopyDst(CVideo::_stencilWidth, CVideo::_stencilHeight, GX_CTF_R8, GX_FALSE);
GX_CopyTex(m_stencil, GX_TRUE);
GX_PixModeSync();
DCFlushRange(m_stencil, CVideo::_stencilWidth * CVideo::_stencilHeight);
GX_SetCopyFilter(m_rmode->aa, m_rmode->sample_pattern, GX_TRUE, m_rmode->vfilter);
}

View File

@ -70,6 +70,7 @@ public:
int stencilVal(int x, int y);
void setCustomWaitImgs(const char *path, bool loop);
void hideWaitMessage();
void startImage(void);
void waitMessage(float delay);
void waitMessage(const vector<TexData> &tex, float delay);
void waitMessage(const TexData &tex);

View File

@ -33,12 +33,10 @@ int main(int argc, char **argv)
Gecko_Init(); //USB Gecko and SD/WiFi buffer
gprintf(" \nWelcome to %s!\nThis is the debug output.\n", VERSION_STRING.c_str());
m_vid.init(); // Init video
DeviceHandle.Init();
NandHandle.Init();
char *gameid = NULL;
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));
@ -52,6 +50,17 @@ int main(int argc, char **argv)
if(atoi(argv[i]) < 254 && atoi(argv[i]) > 0)
mainIOS = atoi(argv[i]);
}
else if(strcasestr(argv[i], "waitdir=") != NULL)
{
char *ptr = strcasestr(argv[i], "waitdir=");
strncpy(wait_dir, ptr+strlen("waitdir="), sizeof(wait_dir));
}
else if(strcasestr(argv[i], "Waitloop") != NULL)
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];
@ -61,40 +70,51 @@ int main(int argc, char **argv)
gameid = NULL;
}
}
else if(strcasestr(argv[i], "waitdir=") != NULL)
{
char *ptr = strcasestr(argv[i], "waitdir=");
strncpy(wait_dir, ptr+strlen("waitdir="), sizeof(wait_dir));
}
else if(strcasestr(argv[i], "Waitloop") != NULL)
{
wait_loop = true;
}
}
/* Init video */
m_vid.init();
if(showFlashImg)
m_vid.startImage();
/* Init device partition handlers */
DeviceHandle.Init();
/* Init NAND handlers */
NandHandle.Init();
check_neek2o();
/* Init ISFS */
if(neek2o() || Sys_DolphinMode())
NandHandle.Init_ISFS();
else
NandHandle.LoadDefaultIOS(); /* safe reload to preferred IOS */
/* Maybe new IOS and Port settings */
/* load and check wiiflow save for possible new IOS and Port settings */
if(InternalSave.CheckSave())
InternalSave.LoadSettings();
/* Handle (c)IOS Loading */
if(neek2o() || Sys_DolphinMode()) /* wont reload anythin */
iosOK = loadIOS(IOS_GetVersion(), false);
else if(useMainIOS && CustomIOS(IOS_GetType(mainIOS))) /* Requested */
iosOK = loadIOS(mainIOS, false) && CustomIOS(CurrentIOS.Type);
// Init
/* set reset and power button callbacks and exitTo option */
Sys_Init();
Sys_ExitTo(EXIT_TO_HBC);
DeviceHandle.MountAll();
/* mount Devices */
DeviceHandle.MountSD();
if(!sd_only && !Sys_DolphinMode())
DeviceHandle.MountAllUSB();
/* init wait images and show wait animation */
m_vid.setCustomWaitImgs(wait_dir, wait_loop);
m_vid.waitMessage(0.15f);
/* init controllers for input */
Open_Inputs();
/* init configs, folders, coverflow, gui and more */
if(mainMenu.init())
{
if(CurrentIOS.Version != mainIOS && !neek2o() && !Sys_DolphinMode())
@ -114,14 +134,13 @@ int main(int argc, char **argv)
mainMenu.terror("errboot2", L"Could not find a device to save configuration files on!");
else if(WDVD_Init() < 0)
mainMenu.terror("errboot3", L"Could not initialize the DIP module!");
else
else // alls good lets start wiiflow
{
writeStub();
if(gameid != NULL && strlen(gameid) == 6)
writeStub();// copy return stub to memory
if(gameid != NULL && strlen(gameid) == 6)// if argv game ID then launch it
mainMenu.directlaunch(gameid);
else
mainMenu.main();
//if mainMenu.init set exit=true then mainMenu.main while loop does nothing and returns to here to exit wiiflow
mainMenu.main();// start wiiflow with main menu displayed
}
//Exit WiiFlow, no game booted...
mainMenu.cleanup();// removes all sounds, fonts, images, coverflow, plugin stuff, source menu and clear memory

View File

@ -138,7 +138,6 @@ bool CMenu::init()
if(drive == check) // Should not happen
{
/* Could not find a device to save configuration files on! */
//m_exit = true;
return false;
}
@ -166,7 +165,17 @@ bool CMenu::init()
bool onUSB = m_cfg.getBool("GENERAL", "data_on_usb", strncmp(drive, "usb", 3) == 0);
drive = check; //reset the drive variable for the check
//check for wiiflow data directory on USB or SD based on data_on_usb
if(onUSB)
if(!onUSB)
{
if(DeviceHandle.IsInserted(SD))// no need to find sd:/wiiflow, it will be made if not exist
drive = DeviceName[SD];
else
{
onUSB = true;
m_cfg.setBool("GENERAL", "data_on_usb", true);
}
}
else // onUSB = true
{
for(u8 i = USB1; i <= USB8; i++) //Look for first partition with a wiiflow folder in root
{
@ -176,12 +185,7 @@ bool CMenu::init()
break;
}
}
}
if(!onUSB && DeviceHandle.IsInserted(SD) && stat(fmt("%s:/%s", DeviceName[SD], APP_DATA_DIR), &dummy) == 0)
drive = DeviceName[SD];
if(drive == check)//if wiiflow data directory not found then check just for a USB partition or SD card
{
if(onUSB)
if(drive == check)// if wiiflow data directory not found just find a valid USB partition
{
for(u8 i = USB1; i <= USB8; i++)
{
@ -191,21 +195,16 @@ bool CMenu::init()
break;
}
}
if(drive == check && DeviceHandle.IsInserted(SD))//if no available USB partition then force SD
drive = DeviceName[SD];
else if(drive == check)
{
/* No available usb partitions for data and no SD inserted! */
//m_exit = true;
return false;
}
}
else
if(drive == check && DeviceHandle.IsInserted(SD))//if no valid USB partition then force SD if inserted
{
if(DeviceHandle.IsInserted(SD))
drive = DeviceName[SD];
else
drive = DeviceName[USB1];//if no SD insterted then force USB. may set this to the wf boot.dol partition
drive = DeviceName[SD];
// show error msg later after building menus
}
if(drive == check)// should not happen
{
/* No available usb partitions for data and no SD inserted! */
return false;
}
}
m_dataDir = fmt("%s:/%s", drive, APP_DATA_DIR);
@ -427,7 +426,10 @@ bool CMenu::init()
/* Init Button Manager and build the menus */
_buildMenus();
if(drive == DeviceName[SD] && onUSB)
{
error(_fmt("errboot5", L"data_on_usb=yes and No available usb partitions for data!\nUsing SD."));
m_cfg.setBool("GENERAL", "data_on_usb", false);
}
/* Check if locked, set return to, set exit to, and init multi threading */
m_locked = m_cfg.getString("GENERAL", "parent_code", "").size() >= 4;
@ -1662,12 +1664,17 @@ void CMenu::_mainLoopCommon(bool withCF, bool adjusting)
m_vid.render();
return;
}*/
/* ticks - for moving and scaling covers and gui buttons and text */
if(withCF)
CoverFlow.tick();
m_btnMgr.tick();
/* video setup */
m_vid.prepare();
m_vid.setup2DProjection(false, true);
/* background and coverflow drawing */
_updateBg();
if(CoverFlow.getRenderTex())
CoverFlow.RenderTex();
@ -1704,6 +1711,8 @@ void CMenu::_mainLoopCommon(bool withCF, bool adjusting)
CoverFlow.drawText(adjusting);
}
}
/* game video or banner drawing */
if(m_gameSelected)
{
if(m_video_playing)
@ -1717,18 +1726,24 @@ void CMenu::_mainLoopCommon(bool withCF, bool adjusting)
else if(m_banner.GetSelectedGame() && (!m_banner.GetInGameSettings() || (m_banner.GetInGameSettings() && m_bnr_settings)))
m_banner.Draw();
}
/* gui buttons and text drawing */
m_btnMgr.draw();
/* reading controller inputs and drawing cursor pointers*/
ScanInput();
// check if we need to start screensaver
if(!m_vid.showingWaitMessage())
{
if(!m_cfg.getBool("GENERAL", "screensaver_disabled", true))
m_vid.screensaver(NoInputTime(), m_cfg.getInt("GENERAL", "screensaver_idle_seconds", 60));
m_vid.render();
}
/* check if we want screensaver and if its idle long enuff, if so draw full screen black square with mild alpha */
if(!m_cfg.getBool("GENERAL", "screensaver_disabled", true))
m_vid.screensaver(NoInputTime(), m_cfg.getInt("GENERAL", "screensaver_idle_seconds", 60));
/* render everything on screen */
m_vid.render();
// check if power button is pressed and exit wiiflow
if(Sys_Exiting())
exitHandler(BUTTON_CALLBACK);
// check if we need to start playing the game/banner sound
// m_gameSelected means we are on the game selected menu
// m_gamesound_changed means a new game sound is loaded and ready to play
@ -1743,15 +1758,16 @@ void CMenu::_mainLoopCommon(bool withCF, bool adjusting)
// stop game/banner sound from playing if we exited game selected menu or if we move to new game
else if((withCF && m_gameSelected && m_gamesound_changed && m_gameSound.IsPlaying()) || (!m_gameSelected && m_gameSound.IsPlaying()))
m_gameSound.Stop();
/* decrease music volume to zero if any of these are true:
trailer video playing or
game/banner sound is being loaded because we are switching to a new game or
game/banner sound is loaded and ready to play or
trailer video playing or||
game/banner sound is being loaded because we are switching to a new game or||
game/banner sound is loaded and ready to play or||
gamesound hasn't finished - when finishes music volume back to normal - some gamesounds don't loop continuously
also this switches to next song if current song is done */
MusicPlayer.Tick((withCF && (m_video_playing || (m_gameSelected && m_soundThrdBusy) ||
(m_gameSelected && m_gamesound_changed))) ||
m_gameSound.IsPlaying());
(m_gameSelected && m_gamesound_changed))) || m_gameSound.IsPlaying());
// set song title and display it if music info is allowed
if(MusicPlayer.SongChanged() && m_music_info)
{

View File

@ -81,7 +81,7 @@ private:
Config m_titles;
Config m_version;
vector<string> m_homebrewArgs;
//vector<string> m_homebrewArgs;
u8 *m_base_font;
u32 m_base_font_size;
u8 *m_wbf1_font;
@ -1088,6 +1088,7 @@ private:
void _launchGame(dir_discHdr *hdr, bool dvd, bool disc_cfg = false);
void _launchChannel(dir_discHdr *hdr);
void _launchHomebrew(const char *filepath, vector<string> arguments);
vector<string> _getMetaXML(const char *bootpath);
void _launchGC(dir_discHdr *hdr, bool disc);
void _launchShutdown();
void _setCurrentItem(const dir_discHdr *hdr);

View File

@ -218,6 +218,7 @@ void CMenu::_showCFTheme(u32 curParam, int version, bool wide)
}
break;
case CMenu::SCFParamDesc::PDT_FLOAT:
// should we use wstringEx(sfmt())
m_btnMgr.setText(m_cfThemeLblVal[k], sfmt("%.2f", m_coverflow.getFloat(domain, key)));
for (int j = 1; j < 4; ++j)
{

View File

@ -244,7 +244,8 @@ void CMenu::_Explorer(void)
else if(strcasestr(file, ".dol") != NULL || strcasestr(file, ".elf") != NULL)
{
_hideExplorer();
_launchHomebrew(file, m_homebrewArgs);
vector<string> arguments = _getMetaXML(file);
_launchHomebrew(file, arguments);
_showExplorer();
}
else if(strcasestr(file, ".txt") != NULL || strcasestr(file, ".nfo") != NULL

View File

@ -5,6 +5,9 @@
#include <time.h>
#include <network.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "menu.hpp"
#include "types.h"
@ -1065,21 +1068,136 @@ void CMenu::_launch(const dir_discHdr *hdr)
}
else if(launchHdr.type == TYPE_HOMEBREW)
{
const char *gamepath = fmt("%s/boot.dol", launchHdr.path);
if(!fsop_FileExist(gamepath))
gamepath = fmt("%s/boot.elf", launchHdr.path);
if(fsop_FileExist(gamepath))
const char *bootpath = fmt("%s/boot.dol", launchHdr.path);
if(!fsop_FileExist(bootpath))
bootpath = fmt("%s/boot.elf", launchHdr.path);
if(fsop_FileExist(bootpath))
{
m_cfg.setString(HOMEBREW_DOMAIN, "current_item", strrchr(launchHdr.path, '/') + 1);
_launchHomebrew(gamepath, m_homebrewArgs);
/*m_homebrewArgs is basically an empty vector string not needed for homebrew
but used by plugins when _launchHomebrew is called */
vector<string> arguments = _getMetaXML(bootpath);
_launchHomebrew(bootpath, arguments);
}
}
ShutdownBeforeExit();
Sys_Exit();
}
void CMenu::_launchHomebrew(const char *filepath, vector<string> arguments)
{
/* clear coverflow, start wiiflow wait animation, set exit handler */
_launchShutdown();
m_gcfg1.save(true);
m_gcfg2.save(true);
m_cat.save(true);
m_cfg.save(true);
Playlog_Delete();
bool ret = (LoadHomebrew(filepath) && LoadAppBooter(fmt("%s/app_booter.bin", m_binsDir.c_str())));
if(ret == false)
{
error(_t("errgame14", L"app_booter.bin not found!"));
_exitWiiflow();
}
/* no more error msgs - remove btns and sounds */
cleanup();
AddBootArgument(filepath);
for(u32 i = 0; i < arguments.size(); ++i)
{
gprintf("Argument: %s\n", arguments[i].c_str());
AddBootArgument(arguments[i].c_str());
}
ShutdownBeforeExit();// wifi and sd gecko doesnt work anymore after
loadIOS(58, false);
BootHomebrew();
Sys_Exit();
}
vector<string> CMenu::_getMetaXML(const char *bootpath)
{
char *meta_buf = NULL;
vector<string> args;
char meta_path[200];
char *p;
char *e, *end;
struct stat st;
/* load meta.xml */
p = strrchr(bootpath, '/');
snprintf(meta_path, sizeof(meta_path), "%.*smeta.xml", p ? p-bootpath+1 : 0, bootpath);
if (stat(meta_path, &st) != 0)
return args;
if (st.st_size > 64*1024)
return args;
meta_buf = (char *) calloc(st.st_size + 1, 1);// +1 so that the buf is 0 terminated
if (!meta_buf)
return args;
int fd = open(meta_path, O_RDONLY);
if (fd < 0)
{
free(meta_buf);
meta_buf = NULL;
return args;
}
read(fd, meta_buf, st.st_size);
close(fd);
/* strip comments */
p = meta_buf;
int len;
while (p && *p)
{
p = strstr(p, "<!--");
if (!p)
break;
e = strstr(p, "-->");
if (!e)
{
*p = 0; // terminate
break;
}
e += 3;
len = strlen(e);
memmove(p, e, len + 1); // +1 for 0 termination
}
/* parse meta */
if (strstr(meta_buf, "<app") && strstr(meta_buf, "</app>") && strstr(meta_buf, "<arguments>") && strstr(meta_buf, "</arguments>"))
{
p = strstr(meta_buf, "<arguments>");
end = strstr(meta_buf, "</arguments>");
do
{
p = strstr(p, "<arg>");
if (!p)
break;
p += 5; //strlen("<arg>");
e = strstr(p, "</arg>");
if (!e)
break;
string arg(p, e-p);
args.push_back(arg);
p = e + 6;
}
while (p < end);
}
free(meta_buf);
meta_buf = NULL;
return args;
}
void CMenu::_launchGC(dir_discHdr *hdr, bool disc)
{
/* note for a disc boot hdr->id is set to the disc id before _launchGC is called */
@ -1343,39 +1461,6 @@ void CMenu::_launchGC(dir_discHdr *hdr, bool disc)
Sys_Exit();
}
void CMenu::_launchHomebrew(const char *filepath, vector<string> arguments)
{
/* clear coverflow, start wiiflow wait animation, set exit handler */
_launchShutdown();
m_gcfg1.save(true);
m_gcfg2.save(true);
m_cat.save(true);
m_cfg.save(true);
Playlog_Delete();
bool ret = (LoadHomebrew(filepath) && LoadAppBooter(fmt("%s/app_booter.bin", m_binsDir.c_str())));
if(ret == false)
{
error(_t("errgame14", L"app_booter.bin not found!"));
_exitWiiflow();
}
/* no more error msgs - remove btns and sounds */
cleanup();
AddBootArgument(filepath);
for(u32 i = 0; i < arguments.size(); ++i)
{
gprintf("Argument: %s\n", arguments[i].c_str());
AddBootArgument(arguments[i].c_str());
}
ShutdownBeforeExit();// wifi and sd gecko doesnt work anymore after
loadIOS(58, false);
BootHomebrew();
Sys_Exit();
}
/* dont confuse loadIOS with _loadIOS */
int CMenu::_loadIOS(u8 gameIOS, int userIOS, string id, bool RealNAND_Channels)
{

View File

@ -754,7 +754,8 @@ int CMenu::main(void)
CoverFlow.clear();
_showWaitMessage();
exitHandler(PRIILOADER_DEF); //Making wiiflow ready to boot something
_launchHomebrew(fmt("%s/boot.dol", m_appDir.c_str()), m_homebrewArgs);
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)

View File

@ -150,7 +150,7 @@ void Musicplayer::LoadFile(const char *name, bool display_change)
}
else if(FileNames.size() == 1 && strcmp(name, PLUGIN_DOMAIN) == 0)
{
MusicFile.FreeMemory();
MusicFile.FreeMemory();// GuiSound is MusicFile in gui_sound.cpp
MusicStopped = true;
return;
}

View File

@ -1,6 +1,6 @@

[SPANISH]
about1=Loader original por:\n%s
about1=Cargador original por:\n%s
about2=Interfaz original por:\n%s
about4=Gracias a:\n%s
about6=Desarrolladores actuales:\n%s
@ -8,32 +8,33 @@ about7=Desarrolladores anteriores:\n%s
about8=Parte del código obtenido desde:\n%s
about9=Sitios que apoyan el proyecto:\n%s
about10=Guía de ayuda
alphabetically=Alfabéticamente
alphabetically=alfabéticamente
appname=%s v%s
aspect169=Forzar 16:9
aspect43=Forzar 4:3
aspectDef=Por Defecto
aspectDef=Por defecto
bootmii=BootMii
bycontrollers=Núm. de mandos
byesrb=Clasificación ESRB
bygameid=ID del juego
bylastplayed=Últimos jugados
byplaycount=Más jugados
byplayers=Núm. jugadores
bywifiplayers=Núm. jugadores WiFi
cat1=Seleccionar Categorías
cat2=Borrar
cd1=Atrás
bycontrollers=Por controles
byesrb=Por ESRB
bygameid=Por ID del juego
bylastplayed=Por última jugada
byplaycount=Por veces jugado
byplayers=Por jugadores
bywifiplayers=Por jugadores Wifi
cat1=Elegir categorías
cat2=Limpiar
cd1=Volver
cd2=Eliminar
cd3=Bloqueo de edad
cd3=Bloqueo por edad
cfg1=Configuración
cfg10=Atrás
cfg11=Emulación de partidas en USB
cfg12=Emulación NAND
cfg13=Configuración de emulación NAND
cfg14=Establecer
cfg15=Extras
cfg10=Volver
cfg11=Emulación de archivos en USB
cfg12=Emulación de NAND
cfg13=Ajustes de emulación de NAND
cfg14=Ajustar
cfg15=Complementos
cfg16=Elegir
cfg17=Particiones del juego
cfg3=Descargar carátulas y títulos
cfg4=Descargar
cfg5=Control parental
@ -44,86 +45,109 @@ cfga3=Instalar
cfga6=Idioma
cfga7=Tema
cfgb1=Ocarina
cfgb3=Modo de video
cfgb2=Cargador de GC predefinido
cfgb4=Idioma del juego
cfgb5=DML Modo de video
cfgb6=DML Idioma del juego
cfgb2=Cargador de GC por defecto
cfgb3=Modo de video por defecto
cfgb4=Idioma del juego por defecto
cfgb5=Modo de video GC por defecto
cfgb6=Idioma del juego GC por defecto
cfgb7=Tipo de canales
cfgb8=Ajustes de GameCube
cfgb9=Ajustes de GameCube por defecto
cfgbnr1=Descargar carátula
cfgbnr2=Borrar carátula
cfgbnr3=Descargar Banner personalizado
cfgbnr4=Borrar Banner
cfgbnr3=Descargar banner personalizado
cfgbnr4=Borrar banner
cfgbnr5=Descargar
cfgbnr6=Borrar
cfgbt1=Configuración de inicio
cfgbt1=Ajustes de inicio
cfgbt2=Forzar carga de cIOS
cfgbt3=Forzar revisión de cIOS
cfgbt4=Puerto USB
cfgbt5=Mostrar menú de fuentes al iniciar
cfgbt6=Activar funciones de varias fuentes
cfgbt6=Activar funciones multifuente
cfgbt7=Iniciar servidor FTP al inicio
cfgc1=Salir a
cfgc2=Ajustar ancho
cfgc3=Ajustar altura
cfgc2=Ajustar ancho TV
cfgc3=Ajustar altura TV
cfgc4=Ajustar Coverflow
cfgc5=Ajustar
cfgc6=Ajuste horizontal
cfgc7=Ajuste vertical
cfgc8=Configuración de inicio
cfgc9=Manejar idiomas
cfgd4=Manejador de parches
cfgc9=Idiomas de WiiFlow
cfgd4=Gestor de ubicación
cfgd5=Guardar el modo favorito
cfgd7=Mostrar categorías al iniciar
cfgg1=Configuración
cfgg1=Ajustes
cfgg10=IOS
cfgg12=Descargar carátula
cfgg13=Descargar
cfgg14=Parchar video
cfgg15=Trucos
cfgg11=
cfgg12=
cfgg13=
cfgg14=Parchar modos de video
cfgg15=Códigos de trampa
cfgg16=Elegir
cfgg17=Elegir categorías
cfgg18=Tipo de enganche
cfgg17=Categorías
cfgg18=Tipo de gancho
cfgg19=
cfgg2=Modo de video
cfgg20=
cfgg21=Volver al canal
cfgg22=Depurador
cfgg23=Descargando trucos....
cfgg24=Emulación NAND
cfgg23=Descargando archivo de trampas....
cfgg24=Emulación de NAND
cfgg25=Contraseña incorrecta
cfgg26=Desactivar bloque de recarga de IOS
cfgg26=
cfgg27=Relación de aspecto
cfgg28=NMM
cfgg29=No parche DVD
cfgg28=
cfgg29=
cfgg3=Idioma
cfgg30=Extraer partida de NAND
cfgg31=Extraer
cfgg32=Copiar partida a NAND
cfgg33=Copiar
cfgg34=Emulador de memoria de Devolution
cfgg34=
cfgg35=Cargador de GameCube
cfgg36=Parche pantalla ancha
cfgg37=Cargar Apploader
cfgg37=Apploader de inicio
cfgg38=LED de actividad
cfgg39=Captura de pantalla DM
cfgg40=Manejar Carátula y Banner
cfgg41=Manejar
cfgg4=Parchar frases de país
cfgg39=
cfgg40=Gestionar carátula y banner
cfgg41=Gestionar
cfgg42=Control USB-HID
cfgg43=Control nativo
cfgg44=Antiparpadeo de video
cfgg45=Servidor privado
cfgg46=Pantalla ancha en WiiU
cfgg47=Memoria emulada
cfgg48=Modo arcade Triforce
cfgg50=¡No hay partida a extraer!
cfgg51=¡No hay partida a meter en la NAND!
cfgg52=Vibración de GC en Wiimote
cfgg53=Saltar BIOS IPL
cfgg54=Ancho del video
cfgg55=Posición del video
cfgg56=Parchar PAL50
cfgg57=¡No permitido para discos!
cfgg4=Parchar cadenas de país
cfgg5=Ocarina
cfgg6=
cfgg7=Vipatch
cfgg8=Volver
cfglng1=Manejar idiomas
cfgg9=
cfglng1=Gestionar idiomas
cfglng2=Obtener idiomas
cfglng3=Seleccionar archivo
cfglng4=Descargar archivo seleccionado
cfglng3=Elegir archivo
cfglng4=Descargar archivo elegido
cfgne1=Emulación de NAND
cfgne2=Extraer partidas
cfgne3=Todas
cfgne4=Faltantes
cfgne5=Extraer NAND
cfgne6=Empezar
cfgne7=Atrás
cfgne7=Volver
cfgne8=¡No se encontró partición FAT válida para emulación de NAND!
cfgne9=Archivo actual: %s
cfgne10=Opciones para emulación de NAND
cfgne10=Ajustes de emulación de NAND
cfgne11=Progreso total:
cfgne12=Extractor de NAND
cfgne13=Extractor de partidas
@ -132,70 +156,76 @@ cfgne15=Extraídos: %d archivos / %d carpetas
cfgne16=Tamaño total: %uMB (%d bloques)
cfgne17=Tamaño total: %uKB (%d bloques)
cfgne18=Listando partidas a extraer...
cfgne19=¡La extracción termino!
cfgne20=¡La extracción falló!
cfgne22=Desactivar emulación de NAND
cfgne23=Bienvenido a WiiFlow. No encontré una NAND válida para emulación de NAND. Pulse Extraer para extraer su NAND, o pulse desactivar para desactivar la emulación de NAND.
cfgne24=Extraer partida guardada
cfgne19=¡Extracción terminada!
cfgne20=¡Extracción fallida!
cfgne21=
cfgne22=
cfgne23=
cfgne24=Extraer partida
cfgne25=Crear nueva partida
cfgne26=Una nueva partida se ha creado para este juego en la NAND real. ¿Extraer partida guardada existente de la NAND real o crear un nuevo archivo para emulación de NAND?
cfgne27=Calculando espacio necesario para extracción...
cfgne28=Importar partida guardada
cfgne29=Importados: %d partidas / %d archivos / %d directorios
cfgne30=¡Importación de archivos finalizada!
cfgne31=Seleccionar partición
cfgne32=Cambiar Nand
cfgne32=Cambiar Nand de guardado
cfgne26=Un archivo de guardado fue creado para este juego en la NAND real. ¿Extraer partida existente en la NAND real o crear una nueva para la emulación de NAND?
cfgne27=Calculando espacio necesario para la extracción...
cfgne28=Grabador de partidas
cfgne29=Grabados: %d partidas / %d archivos / %d directorios
cfgne30=¡Grabado de partidas finalizado!
cfgne31=
cfgne32=Elegir NAND de partidas
cfgne32=Emulación de NAND de partidas
cfgne34=Ajustar
cfgne35=Atrás
cfgne35=Volver
cfgne36=Ubicación =
cfgne37=Escoger NAND predefinida
cfgne37=Elegir NAND por defecto
cfgne38=Vacío
cfgp1=Partición de juegos
cfgp1=Partición de NAND de partidas
cfgp2=Carátulas planas
cfgp3=Conectar a la red al inicio
cfgp3=Conectar red al inicio
cfgp4=Caché de banners
cfgp5=Juegos de Wii
cfgp6=Juegos de GC
cfgp7=Música
cfgp8=Carátulas de cajas
cfgp9=Banners personalizados
cfgpl1=Seleccionar extras
cfgpl1=Elegir complementos
cfgs1=Volumen de la música
cfgs2=Volumen de la interfaz
cfgs3=Volumen de Coverflow
cfgs3=Volumen del coverflow
cfgs4=Volumen del juego
cfgsm1=Ajustes del menú de fuentes
cfgsm2=Activar B para menú de fuentes
cfgsm3=Activar Sourceflow
cfgsm4=Cajas chicas para Sourceflow
cfgsm5=Limpiar caché de Sourceflow
cfgsm6=B en modo para fuente
cfgsm7=Manejar menú de fuentes
cfghb1=Ajustes de Homebrew
cfghb2=Cajas chicas para Coverflow
cfghb3=Partición de Homebrew
cfghb4=Modo de caja
cfghb5=Descargar carátulas
ChanReal=NAND real
ChanEmu=NAND emulada
ChanBoth=Ambas
cheat1=Volver
cheat2=Aplicar
cheat3=Archivo de trucos para el juego no encontrado
cheat3=Archivo de trampas para el juego no encontrado.
cheat4=Descarga no encontrada.
commodore=Commodore 64
custom=Personalizado
def=Por Defecto
def=Por defecto
disabled=Desactivado
dl1=Cancelar
dl10=Por favor dona\na GameTDB.com
dl12=GameTDB
dl13=Orden de descarga
dl14=Elija regiones donde buscar carátulas:
dl14=Elige las regiones para buscar carátulas:
dl15=Configuración de descarga
dl16=Establecer
dl16=Ajustar
dl17=Configuración de descarga
dl18=Atrás
dl18=Volver
dl19=Solo original
dl2=Atrás
dl2=Volver
dl20=Original/Original
dl21=Original/Personal
dl22=Personal/Original
dl23=Personal/Personal
dl24=Solo personal
dl21=Original/Personalizada
dl22=Personalizada/Original
dl23=Personalizada/Personalizada
dl24=Solo personalizada
dl25=Todas
dl3=Todas
dl4=Faltantes
@ -211,9 +241,9 @@ dlmsg14=Terminado.
dlmsg15=¡Falló el guardando!
dlmsg16=No se pudo leer el archivo
dlmsg17=¡No hay actualizaciones!
dlmsg18=boot.dol no encontrado en la carpeta predeterminada
dlmsg18=boot.dol no encontrado en la ubicación predeterminada
dlmsg19=¡Actualización disponible!
dlmsg2=No se pudo inicializar la red
dlmsg2=No se pudo conectar a la red
dlmsg20=No se ha encontrado información sobre la versión
dlmsg21=WiiFlow se cerrará para que los cambios tengan efecto.
dlmsg22=Actualizando directorio de la aplicación...
@ -221,7 +251,7 @@ dlmsg23=Actualizando directorio de datos
dlmsg24=Extrayendo...
dlmsg25=¡La extracción ha fallado! Renombrando la copia de seguridad a boot.dol
dlmsg26=Actualizando caché...
dlmsg27=¡Falta memoria!
dlmsg27=¡No hay suficiente memoria!
dlmsg28=Ejecutando servidor FTP en %s:%u
dlmsg29=El servidor FTP se encuentra detenido.
dlmsg3=Descargando desde %s
@ -238,10 +268,10 @@ DMLpal=PAL 576i
DMLpal60=PAL 480i
DMLprog=NTSC 480p
DMLprogP=PAL 480p
errboot1=¡No se encontró cIOS!\ncIOS d2x 249 base 56 y 250 base 57 son suficientes para todos sus juegos.
errboot1=¡No se encontró cIOS!\ncIOS d2x 249 base 56 y 250 base 57 son suficientes para todos tus juegos.
errboot2=¡No se encontró un dispositivo donde guardar los archivos de configuración!
errboot3=¡No se pudo iniciar el módulo DIP!
errboot4=¡No se encontraron particiones disponibles!
errboot4=¡No se encontró el directorio apps/wiiflow!
errboot5=data_on_usb=yes, ¡pero no hay particiones USB disponibles para datos!\nUsando SD.
errboot6=¡No hay particiones USB disponibles para datos ni tarjeta SD insertada!\nSaliendo.
errgame1=No se encontró un juego con el ID: %s
@ -250,17 +280,26 @@ errgame4=No se pudo cargar el IOS %i
errgame5=¡Falló la activación del emu!
errgame6=¡Falló la activación del emu luego de recargar!
errgame7=¡Falló WDVDGetCoverStatus!
errgame8=Por favor, inserte un dico de juego.
errgame8=Por favor, inserta un dico de juego.
errgame9=Esto no es un disco de Wii o GC
errgame10=Falló ajuste de USB: %d
errneek1=No se pudo iniciar neek2o. Verifique sus ajustes de neek2o
errgame11=¡Cargador de GameCube no encontrado! No se puede lanzar el juego.
errgame12=¡Nintendont no encontrado! No se puede lanzar el disco de GC.
errgame13=¡EmuNAND para la partida no encontrado! Usando NAND real.
errgame14=¡app_booter.bin no encontrado!
errgame15=¡WiiFlow bloqueado! Desbloquea WiiFlow para usar esta función.
errgame16=¡No disponible para juegos de complementos!
errgame17=¡No se pueden eliminar canales de la NAND real!
errgame18=¡No hay info del juego!
errneek1=No se pudo iniciar neek2o. Verifica tu instalación de neek2o
errsource1=¡Homebrew bloqueado!
errsource2=¡Homebrew y multifuente no permitidos!
exit_to=Salir a
ftp1=Iniciar
ftp2=Detener
gameinfo1=Desarrollador: %s
gameinfo2=Distribuidor: %s
gameinfo3=Región: %s
gameinfo4=Fecha de lanzamiento: %i.%i.%i
gameinfo4=Lanzamiento: %i.%i.%i
gameinfo5=Género: %s
gameinfo6=Sin información del juego
gametdb_code=ES
@ -270,7 +309,7 @@ GC_Devo=Devolution
GC_Auto=Auto
genesis=Sega Genesis
gm1=Jugar
gm2=Atrás
gm2=Volver
hbc=HBC
homebrew=Homebrew
home1=Ajustes
@ -304,43 +343,51 @@ lngspa=Español
lngsys=Sistema
lngtch=Chino T.
main1=Instalar Juego
main2=Bienvenido a WiiFlow. No encontré ningún juego. Pulse Instalar para instalar un juego o Seleccionar partición para seleccionar su tipo de partición.
main3=Seleccionar partición
main4=Bienvenido a WiiFlow. No encontré ningún juego Pulse Seleccionar partición para elegir su tipo de partición.
main5=Bienvenido a WiiFlow. No encontré ningún complemento. Pulse Seleccionar partición para elegir su tipo de partición.
main2=No se encontraron juegos en
main3=No se encontraron títulos en
main4=No se encontraron apps en
main5=No se encontraron roms/elementos.
main6=No hay complementos elegidos.
main7=Total de juegos: %u
mastersystem=Sega Master System
menu=Menú del sistema
NANDfull=Completa
NANDoff=Desactivado
NANDoff=Desactivada
NANDpart=Parcial
neek1=Lanzar título con neek2o
neek2o=neek2o
neogeo=Neo-Geo
nes=Nintendo
nintendo64=Nintendo64
NMMdebug=Depurar
NMMDef=Por defecto
NMMOff=Desactivado
NMMon=Activado
NMMdebug=Depurar
NoDVDDef=Por defecto
NoDVDOff=Desactivado
NoDVDon=Activado
off=Desactivado
on=Activado
players=Jugadores
part1=Partición de Wii
part2=Partición de GameCube
part3=Partición de Emu NANDs
part4=Partición de complementos
part5=Ajustes de particiones
players= jugadores
prii=Priiloader
real=Nand real
SaveDef=Por defecto
SaveFull=Completa
SaveFullG=Completa
SaveOff=Desactivado
SaveOffG=Desactivado
SaveOff=Desactivada
SaveOffG=Desactivada
SavePart=Partida guardada
SavePartG=Partida guardada
SaveReg=Cambio de región
SaveRegG=Cambio de región
savedtheme=¡Configuración del tema guardada!
snes=Super Nintendo
stup1=Seleccione fuente
stup1=Elegir fuente
stup2=** DESACTIVADO **
sys1=Actualizar WiiFlow
sys2=Versión de WiiFlow:
@ -363,46 +410,49 @@ vmpmore=Más
vmpnone=Ninguno
vmpnormal=Normal
wad1=Instalar WAD
wad2=Comenzar
wad3=Seleccionado %s, después de la instalación usted regresará al explorador.
wad4=Instalando WAD, por favor espere...
wad2=Empezar
wad3=
wad4=Instalando WAD, por favor espera...
wad5=Error de instalación %i!
wad6=Instalación finalizada con %i errores de hash.
wbfsadddlg=Por favor inserte el disco que quiera copiar, y pulse Ir.
wbfscpydlg=Si quiere copiar este juego a la tarjeta SD, pulse Ir
wbfsop1=Instalar Juego
wad7=Listo para instalar %s\nElige emuNAND y aprieta en Empezar.
wbfsadddlg=Por favor, inserta el disco que quieres copiar, y aprieta Empezar.
wbfscpydlg=Si quieres copiar este juego a la tarjeta SD, aprieta Empezar
wbfsop1=Instalar juego
wbfsop10=Copiando [%s] %s...
wbfsop11=Copiar juego
wbfsop12=Error en DVD(%d)
wbfsop12=DVDError(%d)
wbfsop13=Juego instalado, pero el disco tiene errores (%d)
wbfsop14=Juego copiado, pulse volver para iniciar el juego.
wbfsop14=Juego copiado, presiona Volver para iniciar el juego.
wbfsop15=Calculando espacio necesario para %s
wbfsop16=Instalando %s
wbfsop17=Instalando %s disco %d/2
wbfsop18=¡Esto es un juego de Wii!
wbfsop19=¡Esto no es un juego de Gamecube!
wbfsop19=¡Esto no es un juego de GameCube!
wbfsop2=Borrar juego
wbfsop20=¡Ha insertado otra vez el disco %d!
wbfsop20=¡Has insertado otra vez el disco %d!
wbfsop21=¡¡Este es un disco de otro juego!!
wbfsop22=Instalando %s...\n Por favor, inserte el disco 2 para continuar
wbfsop23=Calculando espacio necesario para %s...\n Por favor, inserte el disco %d para continuar
wbfsop24=No hay espacio suficiente: %d bloques necesarios, %d disponible
wbfsop25=¡Error leyendo disco! Pruebe limpiar el disco
wbfsop26=¡¡Disco extraído!! Por favor, inserte el disco
wbfsop4=Atrás
wbfsop5=Ir
wbfsop22=Instalando %s...\n Por favor, inserta el disco 2 para continuar
wbfsop23=Calculando espacio necesario para %s...\n Por favor, inserta el disco %d para continuar
wbfsop24=No hay espacio suficiente: %d bloques necesarios, %d disponibles
wbfsop25=¡Error leyendo el disco! Prueba a limpiar el disco
wbfsop26=¡¡Disco extraído!! Por favor, inserta el disco
wbfsop4=Volver
wbfsop5=Empezar
wbfsop6=Instalando [%s] %s...
wbfsop7=Juego eliminado
wbfsop7=Juego borrado
wbfsop8=Juego instalado, presiona B para salir.
wbfsop9=Ha ocurrido un error
wbfsoperr1=Disc_Wait falló
wbfsoperr2=Disc_Open falló
wbfsoperr3=¡Esto no es un disco de Wii!
wbfsoperr4=El juego ya esta instalado
wbfsoperr5=¡No se permite eliminar este canal!
wbfsoperr4=El juego ya está instalado
wbfsoperr5=¡Eliminar este canal no está permitido!
wbfsoperr6=El instalador de juegos de Wii esta malo, por favor usa cleanrip.
wbfsprogress=%i%%
wbfsremdlg=Para eliminar el juego permanentemente : %s, presione Ir.
wbfsremdlg=Para eliminar permanentemente el juego: %s, presiona Empezar.
wifiplayers= jugadores WiFi
wii=Wii
wiichannels=Canales de Wii
wiichannels=Canales de Wii oficiales
wiiware=WiiWare
wiiu=Menú de Wii U