diff --git a/Makefile b/Makefile index fdcf35b7..b783a127 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,8 @@ all: @echo Make WiiFlow Loader @$(MAKE) --no-print-directory -C $(CURDIR_TMP)/resources/extldr \ -f $(CURDIR_TMP)/resources/extldr/Makefile + @mv -u $(CURDIR_TMP)/resources/extldr/extldr.bin \ + $(CURDIR_TMP)/out/bins/ext_loader.bin @echo Make WiiFlow Booter @$(MAKE) --no-print-directory -C $(CURDIR_TMP)/resources/wiiflow_game_booter \ diff --git a/Makefile.main b/Makefile.main index 85f32516..869cffcc 100644 --- a/Makefile.main +++ b/Makefile.main @@ -151,8 +151,8 @@ all: clean: @echo clean ... @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol $(CURDIR)/source/svnrev.h \ - $(CURDIR)/source/loader/alt_ios_gen.h \ - $(CURDIR)/out/bins/ext_booter.bin $(CURDIR)/out/bins/app_booter.bin + $(CURDIR)/source/loader/alt_ios_gen.h $(CURDIR)/out/bins/ext_loader.bin \ + $(CURDIR)/out/bins/ext_booter.bin $(CURDIR)/out/bins/app_booter.bin #--------------------------------------------------------------------------------- else diff --git a/resources/app_booter/Makefile b/resources/app_booter/Makefile index 3e64b1c2..17deab9a 100644 --- a/resources/app_booter/Makefile +++ b/resources/app_booter/Makefile @@ -136,11 +136,11 @@ $(OUTPUT).elf: $(OFILES) # This rule links in binary data with the .jpg extension #--------------------------------------------------------------------------------- %.bin: %.elf - @echo "output ... $@" + @echo "output ... $(TARGET).bin" $(Q)$(OBJCOPY) -O binary $< $@ %.elf: link.ld $(OFILES) - @echo "linking ... $@" + @echo "linking ... $(TARGET).elf" $(Q)$(CC) -n -T $^ $(LDFLAGS) -o $@ %.o: %.c diff --git a/resources/extldr/Makefile b/resources/extldr/Makefile index 88acd2c0..3cf14293 100644 --- a/resources/extldr/Makefile +++ b/resources/extldr/Makefile @@ -10,16 +10,16 @@ OBJCOPY = $(PREFIX)objcopy RANLIB = $(PREFIX)ranlib STRIP = $(PREFIX)strip -MACHDEP = -mcpu=750 -mno-eabi -mhard-float -CFLAGS = $(MACHDEP) -O1 -Werror -Wall -pipe -ffunction-sections -finline-functions-called-once -mno-sdata +MACHDEP = -mcpu=750 -mno-eabi +CFLAGS = $(MACHDEP) -O1 -Werror -Wall -pipe -mno-sdata LDFLAGS = $(MACHDEP) -n -nostartfiles -nostdlib -Wl,-T,link.ld -L. ASFLAGS = -D_LANGUAGE_ASSEMBLY -DHW_RVL TARGET_LINKED = boot.elf -TARGET = ../../data/extldr.bin +TARGET = extldr.bin -CFILES = string.c sync.c main.c -OBJS = crt0.o string.o sync.o main.o +CFILES = string.c sync.c usbgecko.c main.c +OBJS = crt0.o string.o sync.o usbgecko.o main.o DEPDIR = .deps diff --git a/resources/extldr/exi.h b/resources/extldr/exi.h new file mode 100644 index 00000000..a5a4c88b --- /dev/null +++ b/resources/extldr/exi.h @@ -0,0 +1,33 @@ +#ifndef __EXI_H_ +/* Retrieve the I/O register base for a given EXI channel */ +#define EXI_ADDR(channel) (0xCD006800 + (channel) * 0x14) +#define EXI_CSR 0x0000 /* EXI Channel 0 Parameter Register */ +#define EXI_CSR_ROMDIS (1 << 13) /* EXI0: de-scramble logic disabled */ +#define EXI_CSR_EXT (1 << 12) /* Device connected if 1 */ +#define EXI_CSR_EXTINT (1 << 11) /* External Insertion Interrupt Status */ +#define EXI_CSR_EXTINTMASK (1 << 10) /* EXT interrupt mask */ +#define EXI_CSR_CLK_1MHZ (0 << 4) /* Clock: 1MHz */ +#define EXI_CSR_CLK_2MHZ (1 << 4) /* Clock: 2MHz */ +#define EXI_CSR_CLK_4MHZ (2 << 4) /* Clock: 4MHz */ +#define EXI_CSR_CLK_8MHZ (3 << 4) /* Clock: 8MHz */ +#define EXI_CSR_CLK_16MHZ (4 << 4) /* Clock: 16MHz */ +#define EXI_CSR_CLK_32MHZ (5 << 4) /* Clock: 32MHz */ +#define EXI_CSR_CS(x) ((x) << 7) /* Chip select */ +#define EXI_CSR_TCINT (1 << 3) /* Transfer complete interrupt status */ +#define EXI_CSR_TCINTMASK (1 << 2) /* Transfer complete interrupt mask */ +#define EXI_CSR_EXTSTAT (1 << 1) /* Interrupt status */ +#define EXI_CSR_EXTSTATMASK (1 << 0) /* EXI interrupt mask */ +#define EXI_CR 0x0000c /* EXI Channel 0 Control Register */ +#define EXI_CR_TLEN_1 (0 << 4) /* Transfer length: 1 byte */ +#define EXI_CR_TLEN_2 (1 << 4) /* Transfer length: 2 byte */ +#define EXI_CR_TLEN_3 (2 << 4) /* Transfer length: 3 byte */ +#define EXI_CR_TLEN_4 (4 << 4) /* Transfer length: 4 byte */ +#define EXI_CR_RW_R (0 << 2) /* Transfer type: read */ +#define EXI_CR_RW_W (1 << 2) /* Transfer type: write */ +#define EXI_CR_RW_RW (2 << 2) /* Transfer type: read/write */ +#define EXI_CR_DMA (1 << 1) /* DMA transfer mode */ +#define EXI_CR_TSTART (1 << 0) /* Start transfer */ +#define EXI_DATA 0x0010 /* EXI Channel 0 Immediate Data */ + +#endif + diff --git a/resources/extldr/main.c b/resources/extldr/main.c index 21455f46..a9739fdc 100644 --- a/resources/extldr/main.c +++ b/resources/extldr/main.c @@ -2,14 +2,17 @@ #include #include "string.h" #include "sync.h" +#include "usbgecko.h" typedef void (*entrypoint) (void); -unsigned char *cfg = (unsigned char*)0x80A7FFF0; -unsigned char *start = (unsigned char*)0x80A80000; -unsigned char *buffer = (unsigned char*)0x90100000; +static entrypoint exeEntryPoint = (entrypoint)0x80A80000; +static unsigned char *start = (unsigned char*)0x80A80000; +static unsigned char *buffer = (unsigned char*)0x90110000; void _main(void) { - entrypoint exeEntryPoint = (entrypoint)start; - memcpy(cfg, buffer, 0x01000000); //1mb safe copying of cfg and booter - sync_before_exec(cfg, 0x01000000); + usbgecko_init(); + gprintf("Copying External Booter...\n"); + memcpy(start, buffer, 0xF0000); //960kb safe copying of booter + sync_before_exec(start, 0xF0000); + gprintf("Done! Jumping to Entrypoint...\n"); exeEntryPoint(); } \ No newline at end of file diff --git a/resources/extldr/usbgecko.c b/resources/extldr/usbgecko.c new file mode 100644 index 00000000..dfff2e8c --- /dev/null +++ b/resources/extldr/usbgecko.c @@ -0,0 +1,90 @@ +#include "exi.h" +#include "usbgecko.h" + +#define USBGECKO_CMD_IDENTIFY 0x90000000 +#define USBGECKO_IDENTIFY_RESPONSE 0x04700000 +#define USBGECKO_CMD_TX_STATUS 0xc0000000 +#define USBGECKO_TX_FIFO_READY 0x04000000 +#define USBGECKO_CMD_RX_STATUS 0xd0000000 +#define USBGECKO_RX_FIFO_READY 0x04000000 +#define USBGECKO_CMD_RECEIVE 0xa0000000 +#define USBGECKO_CMD_TRANSMIT(ch) (0xb0000000 | ((ch) << 20)) + +/* We're poking registers; so ensure any access is volatile! */ +typedef volatile unsigned int vuint32_t; +typedef unsigned int uint32_t; + +static int usb_gecko_channel = -1; + +static uint32_t +usbgecko_transaction(int ch, uint32_t data) +{ + volatile void* exi_base = (volatile void*)EXI_ADDR(ch); + + /* 5.9.1.2: Selecting a specific EXI device: select the USB Gecko device */ + *(vuint32_t*)(exi_base + EXI_CSR) = EXI_CSR_CLK_32MHZ | EXI_CSR_CS(1); + + /* 5.9.1.4: Perform IMM operation: setup data */ + *(vuint32_t*)(exi_base + EXI_DATA) = data; + + /* 5.9.1.4: Perform IMM operation: schedule read/write; 2 bytes; start now */ + *(vuint32_t*)(exi_base + EXI_CR) = EXI_CR_TLEN_2 | EXI_CR_RW_RW | EXI_CR_TSTART; + + /* 5.9.1.4: Perform IMM operation: Wait until transfer is completed */ + while (1) { + if ((*(vuint32_t*)(exi_base + EXI_CR) & EXI_CR_TSTART) == 0) + break; + /* XXX barrier */ + } + + /* 5.9.1.4: Fetch the data */ + data = *(vuint32_t*)(exi_base + EXI_DATA); + + /* 5.9.1.3: Deselecting EXI devices */ + *(vuint32_t*)(exi_base + EXI_CSR) = 0; + + return data; +} + +static void usbgecko_putch(char ch) +{ + if (usb_gecko_channel < 0) + return; + + int timeout = 16; + while (1) { + if (usbgecko_transaction(usb_gecko_channel, USBGECKO_CMD_TX_STATUS) & USBGECKO_TX_FIFO_READY) + break; + timeout--; + if (timeout < 0) { + break; + } + } + usbgecko_transaction(usb_gecko_channel, USBGECKO_CMD_TRANSMIT(ch)); + /* XXX hack to get newlines right */ + if (ch == '\n') + usbgecko_putch('\r'); +} + +void gprintf(const char* string) +{ + char* temp = (char*)string; + while (*temp != '\x0') + { + usbgecko_putch(*temp); + temp++; + } +} + +void usbgecko_init() +{ + int i; + for (i = 0; i < 2; i++) { + uint32_t d = usbgecko_transaction(i, USBGECKO_CMD_IDENTIFY); + if (d != USBGECKO_IDENTIFY_RESPONSE) + continue; + usb_gecko_channel = i; + } +} + +/* vim:set ts=2 sw=2: */ diff --git a/resources/extldr/usbgecko.h b/resources/extldr/usbgecko.h new file mode 100644 index 00000000..82911f56 --- /dev/null +++ b/resources/extldr/usbgecko.h @@ -0,0 +1,7 @@ +#ifndef __USBGECKO_H__ +#define __USBGECKO_H__ + +void usbgecko_init(); +void gprintf(const char* string); + +#endif diff --git a/resources/wiiflow_game_booter/source/main.cpp b/resources/wiiflow_game_booter/source/main.cpp index e93b327f..29373bef 100644 --- a/resources/wiiflow_game_booter/source/main.cpp +++ b/resources/wiiflow_game_booter/source/main.cpp @@ -33,7 +33,7 @@ #include "wdvd.h" #include "gecko.h" -#define EXT_ADDR_CFG ((vu32*)0x80A7FFF0) +#define EXT_ADDR_CFG ((vu32*)0x90100000) using namespace std; IOS_Info CurrentIOS; diff --git a/source/booter/external_booter.cpp b/source/booter/external_booter.cpp index 257b59da..1380dbac 100644 --- a/source/booter/external_booter.cpp +++ b/source/booter/external_booter.cpp @@ -38,13 +38,13 @@ /* External WiiFlow Game Booter */ the_CFG normalCFG; -#define EXT_ADDR_CFG ((vu32*)0x90100000) //later for 0x80A7FFF0 -#define EXT_ADDR ((u8*)0x90100010) //later for 0x80A80000 +#define EXT_ADDR_CFG ((vu32*)0x90100000) +#define EXT_ADDR ((u8*)0x90110000) //later for 0x80A80000 #define LDR_ADDR ((u8*)0x93300000) #define LDR_ENTRY ((entry)LDR_ADDR) -extern const u8 extldr_bin[]; -extern const u32 extldr_bin_size; +u8 *extldr_ptr = NULL; +size_t extldr_size = 0; extern "C" { u8 configbytes[2]; @@ -101,21 +101,25 @@ void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 pat memcpy(EXT_ADDR, booter_ptr, booter_size); DCFlushRange(EXT_ADDR, booter_size); /* Loader just for the booter */ - memcpy(LDR_ADDR, extldr_bin, extldr_bin_size); - DCFlushRange(LDR_ADDR, extldr_bin_size); + memcpy(LDR_ADDR, extldr_ptr, extldr_size); + DCFlushRange(LDR_ADDR, extldr_size); /* Boot it */ JumpToEntry(LDR_ENTRY); } -bool ExternalBooter_LoadBooter(const char *booter_path) +bool ExternalBooter_LoadBins(const char *binDir) { - fsop_GetFileSizeBytes(booter_path, &booter_size); - if(booter_size > 0) - { - booter_ptr = fsop_ReadFile(booter_path, &booter_size); - if(booter_ptr != NULL) - return true; - } + extldr_ptr = fsop_ReadFile(fmt("%s/ext_loader.bin", binDir), &extldr_size); + if(extldr_size == 0 || extldr_ptr == NULL) + return false; + + booter_ptr = fsop_ReadFile(fmt("%s/ext_booter.bin", binDir), &booter_size); + if(booter_size > 0 && booter_ptr != NULL) + return true; + + free(extldr_ptr); + extldr_ptr = NULL; + extldr_size = 0; return false; } diff --git a/source/booter/external_booter.hpp b/source/booter/external_booter.hpp index f70f92b7..efd08800 100644 --- a/source/booter/external_booter.hpp +++ b/source/booter/external_booter.hpp @@ -30,7 +30,7 @@ extern u32 hooktype; void WiiFlow_ExternalBooter(u8 vidMode, bool vipatch, bool countryString, u8 patchVidMode, int aspectRatio, u32 returnTo, u8 BootType, bool use_led); -bool ExternalBooter_LoadBooter(const char *booter_path); +bool ExternalBooter_LoadBins(const char *binDir); void ExternalBooter_ChannelSetup(u64 title, bool dol); void ExternalBooter_WiiGameSetup(bool wbfs, bool dvd, bool patchregion, const char *ID); void ShutdownBeforeExit(void); diff --git a/source/gui/gcvid.cpp b/source/gui/gcvid.cpp index a77dc6b8..eb91902f 100644 --- a/source/gui/gcvid.cpp +++ b/source/gui/gcvid.cpp @@ -709,9 +709,20 @@ void decodeRealJpeg(const u8* data, int size, VideoFrame& dest, bool fancy) tjhandle _jpegDecompressor = tjInitDecompress(); tjDecompressHeader2(_jpegDecompressor, src, size, &width, &height, &jpegSubsamp); /* decode to buffer */ - dest.resize(width, height); - tjDecompress2(_jpegDecompressor, src, size, dest.data, width, 0, height, - TJPF_RGBA, fancy ? TJFLAG_ACCURATEDCT : (TJFLAG_FASTDCT | TJFLAG_FASTUPSAMPLE)); + if(fancy) + { + width = ALIGN(4, width); + height = ALIGN(4, height); + dest.resize(width, height); + tjDecompress2(_jpegDecompressor, src, size, dest.data, width, 0, height, + TJPF_RGBA, TJFLAG_ACCURATEDCT); + } + else + { + dest.resize(width, height); + tjDecompress2(_jpegDecompressor, src, size, dest.data, width, 0, height, + TJPF_RGBA, TJFLAG_FASTDCT | TJFLAG_FASTUPSAMPLE); + } tjDestroy(_jpegDecompressor); g_isLoading = false; } diff --git a/source/gui/texture.cpp b/source/gui/texture.cpp index b1ac152f..a5aafe8b 100644 --- a/source/gui/texture.cpp +++ b/source/gui/texture.cpp @@ -43,29 +43,31 @@ static inline u32 coordsRGB565(u32 x, u32 y, u32 w) static inline void _convertToRGBA(u8 *dst, const u8 *src, u32 width, u32 height) { - for (u32 y = 0; y < height; ++y) - { - for (u32 x = 0; x < width; ++x) + u32 x,y,i,j; + for (y = 0; y < height; ++y) + for (x = 0; x < width; ++x) { - u32 i = (x + y * width) * 4; - dst[i] = src[coordsRGBA8(x, y, width) + 1]; - dst[i + 1] = src[coordsRGBA8(x, y, width) + 32]; - dst[i + 2] = src[coordsRGBA8(x, y, width) + 33]; - dst[i + 3] = src[coordsRGBA8(x, y, width)]; + i = (x + y * width) * 4; + j = coordsRGBA8(x, y, width); + dst[i] = src[j + 1]; + dst[i + 1] = src[j + 32]; + dst[i + 2] = src[j + 33]; + dst[i + 3] = src[j]; } - } } static inline void _convertToRGBA8(u8 *dst, const u8 *src, u32 width, u32 height) { - for (u32 y = 0; y < height; ++y) - for (u32 x = 0; x < width; ++x) + u32 x,y,i,j; + for (y = 0; y < height; ++y) + for (x = 0; x < width; ++x) { - u32 i = (x + y * width) * 4; - dst[coordsRGBA8(x, y, width) + 1] = src[i]; - dst[coordsRGBA8(x, y, width) + 32] = src[i + 1]; - dst[coordsRGBA8(x, y, width) + 33] = src[i + 2]; - dst[coordsRGBA8(x, y, width)] = src[i + 3]; + i = (x + y * width) * 4; + j = coordsRGBA8(x, y, width); + dst[j + 1] = src[i]; + dst[j + 32] = src[i + 1]; + dst[j + 33] = src[i + 2]; + dst[j] = src[i + 3]; } } diff --git a/source/homebrew/homebrew.cpp b/source/homebrew/homebrew.cpp index 7601ebaa..9db572f8 100644 --- a/source/homebrew/homebrew.cpp +++ b/source/homebrew/homebrew.cpp @@ -11,11 +11,16 @@ #include "fileOps/fileOps.h" #include "gecko/gecko.hpp" -#define EXECUTE_ADDR ((u8 *)0x92000000) -#define BOOTER_ADDR ((u8 *)0x93300000) -#define ARGS_ADDR ((u8 *)0x90100000) -#define BOOTER_ENTRY ((entry)BOOTER_ADDR) +static u8 *EXECUTE_ADDR = (u8*)0x92000000; +static u8 *BOOTER_ADDR = (u8*)0x93300000; +static entry BOOTER_ENTRY = (entry)BOOTER_ADDR; + +static __argv *ARGS_ADDR = (__argv*)0x90100000; +static char *CMD_ADDR = (char*)ARGS_ADDR + sizeof(struct __argv); + +u8 *appbooter_ptr = NULL; +u32 appbooter_size = 0; using namespace std; extern const u8 stub_bin[]; @@ -46,15 +51,10 @@ void AddBootArgument(const char * argv) bool LoadAppBooter(const char *filepath) { - u32 filesize = 0; - fsop_GetFileSizeBytes(filepath, &filesize); - if(filesize > 0) - { - fsop_ReadFileLoc(filepath, filesize, BOOTER_ADDR); - DCFlushRange(BOOTER_ADDR, filesize); - return true; - } - return false; + appbooter_ptr = fsop_ReadFile(filepath, &appbooter_size); + if(appbooter_size == 0 || appbooter_ptr == NULL) + return false; + return true; } bool LoadHomebrew(const char *filepath) @@ -75,40 +75,29 @@ bool LoadHomebrew(const char *filepath) return true; } -int SetupARGV(struct __argv * args) +static int SetupARGV() { - if(!args) - return -1; - + __argv *args = ARGS_ADDR; memset(args, 0, sizeof(struct __argv)); args->argvMagic = ARGV_MAGIC; - u32 argc = 0; u32 position = 0; - u32 stringlength = 1; - /** Append Arguments **/ + /** Count Arguments Size **/ + u32 stringlength = 1; for(u32 i = 0; i < Arguments.size(); i++) stringlength += Arguments[i].size()+1; - args->length = stringlength; - //! Put the argument into mem2 too, to avoid overwriting it - args->commandLine = (char *) ARGS_ADDR + sizeof(struct __argv); /** Append Arguments **/ - for(u32 i = 0; i < Arguments.size(); i++) + args->argc = Arguments.size(); + args->commandLine = CMD_ADDR; + for(int i = 0; i < args->argc; i++) { strcpy(&args->commandLine[position], Arguments[i].c_str()); position += Arguments[i].size() + 1; - argc++; } - - args->argc = argc; - args->commandLine[args->length - 1] = '\0'; - args->argv = &args->commandLine; - args->endARGV = args->argv + 1; - Arguments.clear(); return 0; @@ -134,14 +123,13 @@ void writeStub() void BootHomebrew() { - __argv args; if(!IsDollZ(EXECUTE_ADDR) && !IsSpecialELF(EXECUTE_ADDR)) - SetupARGV(&args); + SetupARGV(); else gprintf("Homebrew Boot Arguments disabled\n"); - memmove(ARGS_ADDR, &args, sizeof(args)); - DCFlushRange(ARGS_ADDR, sizeof(args) + args.length); + memcpy(BOOTER_ADDR, appbooter_ptr, appbooter_size); + DCFlushRange(BOOTER_ADDR, appbooter_size); JumpToEntry(BOOTER_ENTRY); } diff --git a/source/menu/menu_game.cpp b/source/menu/menu_game.cpp index cb67535d..8d118068 100644 --- a/source/menu/menu_game.cpp +++ b/source/menu/menu_game.cpp @@ -406,7 +406,7 @@ bool CMenu::_startVideo() if(fsop_FileExist(THP_Path)) { m_gameSound.FreeMemory(); - MusicPlayer.Stop(); + CheckGameSoundThread(); m_banner.SetShowBanner(false); /* Lets play the movie */ movie.Init(THP_Path); @@ -1257,7 +1257,7 @@ void CMenu::_launchChannel(dir_discHdr *hdr) while(1) usleep(500); } } - if(WII_Launch == false && ExternalBooter_LoadBooter(fmt("%s/ext_booter.bin", m_binsDir.c_str())) == false) + if(WII_Launch == false && ExternalBooter_LoadBins(m_binsDir.c_str()) == false) Sys_Exit(); if(_loadIOS(gameIOS, userIOS, id, !NAND_Emu) == LOAD_IOS_FAILED) Sys_Exit(); @@ -1494,7 +1494,7 @@ void CMenu::_launchGame(dir_discHdr *hdr, bool dvd) gprintf("Check\n"); patchregion = NandHandle.Do_Region_Change(id, true); } - if(ExternalBooter_LoadBooter(fmt("%s/ext_booter.bin", m_binsDir.c_str())) == false) + if(ExternalBooter_LoadBins(m_binsDir.c_str()) == false) Sys_Exit(); if((!dvd || neek2o()) && !Sys_DolphinMode()) {