Merge code to patch Wii Channels' Menu button with bootOpera...
June 25, 2011 01:38AM
If anyone is familiar with the app called bootOpera, it is basically a small app that launches the Opera Wii Channel from a homebrew loader. Its purpose? For people like me who use the Homebrew Channel as an alternative to the Wii Menu. The one thing that this does not do, however, is return back to the Homebrew Channel, which almost makes it pointless.

I have come across one application which can do this with Wii titles. Unfortunately, it is a USB loader (sorry,) but I only began to use it because of this feature. Configurable USB Loader can be configured to patch the Home Button Screen's Menu button to launch the loader or another application, like HBC for instance.

I have only looked a little while for the Loader's code, but if someone could spot out the code needed to patch a Wii title for the Menu button, and merge that with the bootOpera code, no one will ever have to launch the Wii Menu ever again (except for settings, of course.) This would also be great with Gecko, but those guys have already wrapped up that project, so there is no hope in it. Please, someone reach out and help put this together. I know it's possible, the Loader did it.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 25, 2011 03:51AM
I doubt this will happen, cause you have to remember one thing about USB Loaders, and other non discussable items that are detailed while you're creating your post, and that's these arent discussable for the sheer fact that some of these use a bit of Nintendos programming code in some form to accomplish what they do, which primarily would be for loading pirated game images without needing the disc. People will claim back, and forth that they dont, but seriously you're talking to programmers that know what they're looking at when they examine programming code. Especially Wii programming code.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 25, 2011 10:27AM
Are you saying that Loaders steal copy protected source codes from Nintendo to develop their software? Well, that would be illegal then and hopeless for development without breaking the law. If there's the slightest chance someone finds a program that accomplishes this that is made from original open sourced code and not Nintendo's, this would be the place to share it, but I guess that is not probable.

Just out of curiosity, anyone can answer this, do you think source codes from "sketchy" projects like the one we are discussing will go around the web unnoticed and without ethics in a couple years from now? The same can be said about Super Nintendo roms, for example: twenty year old games which no one makes profit from anymore are downloaded every day. Plus, as many of my peers have been saying from time to time, the Wii will be a small-time family toy soon.

I'm really looking forward to retiring my Wii (and actually custom casing and designing it, I have recently decided) as a little all-around family console chucked ready with old classic games, many good and great homebrew games as well as fun and handy apps, an easy to use "app store" (HBB, if it still exists,) movies and videos with DVD support, Shoutcast internet radio and music, Netflix (of course) and Youtube, a built in "Gameshark" (or what we know as Gecko's codes,) with a great selection of Wii games as well as Gamecube games in their cases and a great array of wireless controllers, and all of this running on the Homebrew Channel. I want to hand this down to my kids like I was an NES system once, but it will be loaded full of fun stuff to play with exceeding its original potential for keeping play value, and I want it to be as perfect as possible so anyone can use it. That is only why I wish to have apps like bootOpera and bootNetflix return to the HBC instead of the Wii Menu. If only...
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 25, 2011 11:11PM
I'm sure someone could write a Gecko OS code that does that.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 25, 2011 11:30PM
I reckon this is the function needed:

//giantpune's magic super patch to return to channels - Added by Dr. Clipper
bool PatchReturnTo(void *Address, int Size, u32 id) {
    if( !id )return 0;
    //new __OSLoadMenu() (SM2.0 and higher)
    u8 SearchPattern[ 12 ] =    { 0x38, 0x80, 0x00, 0x02, 0x38, 0x60, 0x00, 0x01, 0x38, 0xa0, 0x00, 0x00 };

    //old _OSLoadMenu() (used in launch games)
    u8 SearchPatternB[ 12 ] =   { 0x38, 0xC0, 0x00, 0x02, 0x38, 0xA0, 0x00, 0x01, 0x38, 0xE0, 0x00, 0x00 };

    //identifier for the safe place
    u8 SearchPattern2[ 12 ] =   { 0x4D, 0x65, 0x74, 0x72, 0x6F, 0x77, 0x65, 0x72, 0x6B, 0x73, 0x20, 0x54 };


    int found = 0;
    int patched = 0;
    u8 oldSDK = 0;
    u32 ad[ 4 ] = { 0, 0, 0, 0 };

    void *Addr = Address;
    void *Addr_end = Address+Size;

    while (Addr <= Addr_end - 12 ) {
        //find a safe place or the patch to hang out
        if ( ! ad[ 3 ] && memcmp( Addr, SearchPattern2, 12 )==0 ) {
            ad[ 3 ] = (u32)Addr + 0x30;
            debug_printf("found a safe place @ %08x\n", ad[ 3 ]);
            //hexdump( Addr, 0x50 );
        }
        //find __OSLaunchMenu() and remember some addresses in it
        else if ( memcmp( Addr, SearchPattern, 12 )==0 ) {
            ad[ found++ ] = (u32)Addr;
        }
        else if ( ad[ 0 ] && memcmp( Addr, SearchPattern, 8 )==0 ) //after the first match is found, only search the first 8 bytes for the other 2
        {
            if( !ad[ 1 ] ) ad[ found++ ] = (u32)Addr;
            else if( !ad[ 2 ] ) ad[ found++ ] = (u32)Addr;
            if( found >= 3 )break;
        }
        Addr += 4;
    }
    //check for the older-ass version of the SDK
    if( found < 3 && ad[ 3 ] )
    {
        Addr = Address;
        ad[ 0 ] = 0; 
                ad[ 1 ] = 0;
        ad[ 2 ] = 0;
        found = 0;
        oldSDK = 1;

        while (Addr <= Addr_end - 12 ) {
            //find __OSLaunchMenu() and remember some addresses in it
            if ( memcmp( Addr, SearchPatternB, 12 )==0 ) {
                ad[ found++ ] = (u32)Addr;
            }
            else if ( ad[ 0 ] && memcmp( Addr, SearchPatternB, 8 ) == 0 ) //after the first match is found, only search the first 8 bytes for the other 2
            {
                if( !ad[ 1 ] ) ad[ found++ ] = (u32)Addr;
                else if( !ad[ 2 ] ) ad[ found++ ] = (u32)Addr;
                if( found >= 3 )break;
            }
            Addr += 4;
        }
    }

    //if the function is found and if it is not too far into the main.dol
    if( found == 3 && ( ad[ 2 ] - ad[ 3 ] < 0x1000001 ) && ad[ 3 ] )
    {
        debug_printf("patch __OSLaunchMenu( 0x00010001, 0x%08x )\n", id);
        u32 nop = 0x60000000;

        //the magic that writes the TID to the registers
        u8 jump[ 20 ] = { 0x3C, 0x60, 0x00, 0x01, 0x60, 0x63, 0x00, 0x01,
                          0x3C, 0x80, 0x4A, 0x4F, 0x60, 0x84, 0x44, 0x49,
                          0x4E, 0x80, 0x00, 0x20 };
        if( oldSDK )
        {
            jump[ 1 ] = 0xA0; //3CA00001 60A50001
            jump[ 5 ] = 0xA5; //3CC04A4F 60C64449
            jump[ 9 ] = 0xC0;
            jump[ 13 ] = 0xC6;
        }
        //patch the thing to use the new TID
        jump[ 10 ] = (u8)( id >> 24 );
        jump[ 11 ] = (u8)( id >> 16 );
        jump[ 14 ] = (u8)( id >> 8 );
        jump[ 15 ] = (u8)id;

        void* addr = (u32*)ad[ 3 ];

        //write new stuff to memory main.dol in a unused part of the main.dol
        memcpy( addr, jump, sizeof( jump ) );

        //ES_GetTicketViews()
        u32 newval = ( ad[ 3 ] - ad[ 0 ] );
        newval &= 0x03FFFFFC;
        newval |= 0x48000001;
        addr = (u32*)ad[ 0 ];
        memcpy( addr, &newval, sizeof( u32 ) );
        memcpy( addr + 4, &nop, sizeof( u32 ) );
        debug_printf("\t%p -> %08x\n", addr, newval );

        //ES_GetTicketViews() again
        newval = ( ad[ 3 ] - ad[ 1 ] );
        newval &= 0x03FFFFFC;
        newval |= 0x48000001;
        addr = (u32*)ad[ 1 ];
        memcpy( addr, &newval, sizeof( u32 ) );
        memcpy( addr + 4, &nop, sizeof( u32 ) );
        debug_printf("\t%p -> %08x\n", addr, newval );

        //ES_LaunchTitle()
        newval = ( ad[ 3 ] - ad[ 2 ] );
        newval &= 0x03FFFFFC;
        newval |= 0x48000001;
        addr = (u32*)ad[ 2 ];
        memcpy( addr, &newval, sizeof( u32 ) );
        memcpy( addr + 4, &nop, sizeof( u32 ) );
        debug_printf("\t%p -> %08x\n", addr, newval );

        patched = 1;
    }
    else
    {
        debug_printf("not patched\n");
        debug_printf("found %d addresses\n", found);
        int i;
        for( i = 0; i< 4; i++)
            debug_printf("ad[ %d ]: %08x\n", i, ad[ i ] );
        debug_printf("offset : %08x\n", ad[ 2 ] - ad[ 3 ] );

    }
    return patched;
}

Dunno exactly how it works or what the parameters are, but there it is.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 26, 2011 03:53AM
Well, whatdaya know. The thing is though I don't know how to combine this with the other code (and I'm not surprised.) Will someone compile these two and show how they look together?
#include "gccore.h"
#include "wiiuse/wpad.h"
#include "ogc/ios.h"
#include "fat.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"

static void *xfb = NULL;
static GXRModeObj *vmode = NULL;
char * url = "";

void setupVideo() {

  VIDEO_Init();
  vmode = VIDEO_GetPreferredMode(NULL);
  VIDEO_Configure(vmode);
  xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(vmode));
  console_init (xfb, 20, 20, vmode->fbWidth, vmode->xfbHeight, vmode->fbWidth*VI_DISPLAY_PIX_SZ);
  VIDEO_Configure(vmode);
  VIDEO_ClearFrameBuffer(vmode, xfb, COLOR_BLACK);
  VIDEO_SetNextFramebuffer(xfb);
  VIDEO_SetBlack(0);
  VIDEO_Flush();
  VIDEO_WaitVSync(); 
  if (vmode->viTVMode & VI_NON_INTERLACE)
    VIDEO_WaitVSync();

}

s32 launchTitle(u64 TitleID, char * url) {
	WII_Initialize();
	if (url[0] != 0) {
		//Load title with specified URL as an argument
		return WII_LaunchTitleWithArgs(TitleID, 0, url, NULL); 
	} else {
			return WII_LaunchTitle(TitleID); 
	}
}

s32 readCfg(char * path) {
	int c = 0;
	int i = 0;
	FILE *f = fopen(path, "r");
	if (f == NULL)
		return 0;
	fseek(f , 0 , SEEK_END);
	u32 size = ftell(f);
	rewind(f);
	url = (char*) malloc(sizeof(char)*size);
	while (c != EOF) {
		c = fgetc(f);
		if (31 < c && c < 127)
			url[i++] = c;
	}
	url = '\0';
	fclose(f);
	return 1;
}

int main(int argc, char **argv) {
	setupVideo();

	s32 ret;
	if (argc > 0) {
		char path[MAXPATHLEN];
		int len = strlen(argv[0]);
		int i = 0;
        for(i = len; argv[0] != '/'; i--);
        if(i < 1)
			readCfg("sd:/url.cfg");
        else {
			argv[0] = 0;
			sprintf(path, "%s/url.cfg", argv[0]);
			readCfg(path);
		}
	}
	ret = launchTitle(0x0001000148414445LL, url);
	if (ret < 0) {
		ret = launchTitle(0x000100014841444ALL, url);
	}
	if (ret < 0) {
		ret = launchTitle(0x0001000148414450LL, url);
	}
	return ret;
}
This is the bootOpera code which compiles into a working dol.

/*
 *  Copyright (C) 2008 Nuke (wiinuke@gmail.com)
 *
 *  this file is part of GeckoOS for USB Gecko
 *  [www.usbgecko.com]
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __PATCHCODE_H__
#define __PATCHCODE_H__

// Globals
u32 hooktype;
int patched;
u8 configbytes[2];
u32 regionfree;

// Function prototypes
void dogamehooks(void *addr, u32 len);
void langpatcher(void *addr, u32 len);
void vidolpatcher(void *addr, u32 len);
void patchdebug(void *addr, u32 len);


#endif // __PATCHCODE_H__
#ifndef _APPLOADER_H_
#define _APPLOADER_H_

/* Entry point */
typedef void (*entry_point)(void);

/* Prototypes */
s32 Apploader_Run(entry_point *); 

bool disable_return_to_patch;

#endif


#ifndef _GECKO_H_
#define _GECKO_H_

#ifdef __cplusplus
extern "C" {
#endif

#ifndef NO_DEBUG
        //use this just like printf();
        void gprintf(const char *str, ...);
        void gsenddata(const u8 *data, int length, const char *filename);
        void ghexdump(void *d, int len);
        bool InitGecko();
#else
        #define gprintf(...)
        #define gsenddata(...)
        #define InitGecko()      false
#endif /* NO_DEBUG */



#ifdef __cplusplus
}
#endif

#endif
I believe these are the extra parameters to include when making the patch compile.
BTW, would "sys/unistd.h" be different from just "unistd.h?" If so, that also needs to be included.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 26, 2011 07:13AM
this patch wont work with that method to boot a channel. there are 3 ways ive seen channels be loaded.
1) having IOS launch it <- system menu and the code you posted above does it this way
2) booting the nandloader from the PPC app <- geckoOS does it this way
3) copying the executable into memory directly and running it

this patch only works with the 3rd method.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 28, 2011 12:57AM
I understand why that is. So, the thing is that this code is written for a loader to, after launching a Wii game, modify the Wii Menu files as they being copied into the memory, right? This won't work with a channel because of two things. First of all, this code would need to be modified anyway because it is written to await the input of "launching the game" and is directed to the "disk," which has a different code than a particular channel. Secondly, Wii games are easily modifiable since they are broken up into file trees. Channels, on the other hand, are simply one wad file, aren't they? Well, I only see two possibilities then, and they may not be even possible:
1. If there were a way to block the process of copying the Wii Menu Button code into the memory from the Wii title, then a complete version of a modified one could be copied instead. In other words, a code to tell the Wii when launching a title not to copy the files from the Channel, but instead to copy from another location, ie. the SD card. Unfortunately, I can only imagine that this is too difficult for someone to do for this small purpose. =(
2. IDK if a wad file can be taken apart, edited, and put back together. If it can, that is an option to permanently modify the Channels's Wii Menu Button to have it return to the HBC. Honestly, I wouldn't mind this either.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 28, 2011 11:09AM
Um, no.

The reason this method won't work is as follows:

In that particular loader (and I think most USB Loaders), when loading a game, it's executable (the DOL) is loaded into memory first, then patched to run properly (and in this case, return to a channel), then loaded. It is this DOL that gets patched. NOT System Menu files.
When loading a channel, there is a function in IOS for launching a title. This can be used, and that is how it is done in bootOpera. This means IOS handles everything, and does it all automatically. There is no point in the process where there is access to the DOL loading into memory.
Channels are NOT WAD files. A WAD is simply a container file (think ZIP or RAR, but without the compression I think) holding other files. WADs are how pirates distribute WiiWare and Virtual Console games illegally. When a channel is installed, it is not a WAD. It is a number of "contents", one of which is a DOL.
You can load this DOL into memory, patch it and then load it. And this would make the patch work. But I don't know of any existing code to do this, so it'd have to be written from scratch.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 28, 2011 11:33PM
I thought WADs were for forwarders too, but, yeah.
Makes sense. The code to do that for a channel would be similar, but have different parameters, definitions, etc. Well, I feel much better now knowing that it should be possible.
Re: Merge code to patch Wii Channels' Menu button with bootOpera...
June 28, 2011 11:52PM
Judging by one of your posts above, I'm fairly sure you don't know what parameters are...

But anyway, yes it is possible, however it is probably unlikely anyone will bother.
Sorry, only registered users may post in this forum.

Click here to login