Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

WAD Manager v1.7

- Directory browsing support added.
- USB 2.0 Mass Storage Device support fixed.
- Autofix bad common key (with fakesigning).
- GUI modified (bigger console and new background).
- Background music added (OGG player).
- Miscellaneous fixes and improvements.
commit 8b9b91726fdcad505d8fd0642409b20884ef7a55 1 parent 09679a2
@waninkoko authored
View
2  Makefile
@@ -36,7 +36,7 @@ LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
-LIBS := -lpng -lfat -lwiiuse -lbte -logc -lm -lz
+LIBS := -lasnd -lvorbisidec -lpng -lfat -lwiiuse -lbte -logc -lm -lz
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
View
21 README.es.txt
@@ -1,5 +1,5 @@
+----------------------------+
-| WAD Manager v1.6 |
+| WAD Manager v1.7 |
| developed by Waninkoko |
+----------------------------+
| www.teknoconsolas.es |
@@ -15,24 +15,29 @@
[ DESCRIPCION ]:
-- WAD Manager es una aplicacion que te permite (des)instalar paquetes WAD.
+- WAD Manager es una aplicacion que permite la (des)instalacion de paquetes
+ en formato WAD (paquetes caseros y oficiales).
- La aplicacion muestra todos los paquetes WAD disponibles en un
- dispositivo de almacenamiento para poder elegir cual (des)instalar.
+ La aplicacion permite navegar al usuario por los contenidos de un dispositivo
+ de almacenamiento para poder trabajar con los paquetes WAD disponibles.
[ DISPOSITIVOS SOPORTADOS ]:
- SDGecko.
- Puerto SD interno (con soporte SDHC).
-- Dispositivo USB (1.1 y 2.0).
+- Dispositivo de almacenamiento USB (1.1 y 2.0).
[ COMO USARLO ]:
-1. Crea un directorio llamado "wad" en la raiz del dispositivo de almacenamiento.
-2. Copia todos los paquetes WAD en el directorio creado en el paso 1.
-3. Ejecuta la aplicacion con cualquier metodo para cargar homebrew.
+1. Copia los paquetes WAD en el dispositivo de almacenamiento.
+2. Inserta el dispositivo de almacenamiento en la Wii.
+3. Ejecuta la aplicacion utilizando cualquier metodo para cargar homebrew.
+4. Selecciona la version de IOS a utilizar. IOS249 recomendado (si esta disponible).
+5. Selecciona el dispositivo de almacenamiento a utilizar.
+6. Navega por los contenidos del dispositivo de almacenamiento y selecciona
+ el paquete WAD a (des)instalar.
[ NOTAS ]:
View
20 README.txt
@@ -1,5 +1,5 @@
+----------------------------+
-| WAD Manager v1.6 |
+| WAD Manager v1.7 |
| developed by Waninkoko |
+----------------------------+
| www.teknoconsolas.es |
@@ -15,11 +15,11 @@
[ DESCRIPTION ]:
-- WAD Manager is an application that allows you to (un)install
- WAD packages.
+- WAD Manager is an application that allows the (un)installation of
+ packages in WAD format (homebrew and official packages).
- It lists all the available WAD packages in a storage device
- so you can select which one to (un)install.
+ It allows the browsing of a storage device to work with the
+ available WAD files in it.
[ SUPPORTED DEVICES ]:
@@ -31,9 +31,13 @@
[ HOW TO USE ]:
-1. Create a folder called "wad" in the root of the storage device.
-2. Copy all the WAD packages in the folder created in the step 1.
-3. Run the application with any method to load homebrew.
+1. Copy all the WAD packages in the storage device.
+2. Insert the storage device in the Wii.
+3. Run the application using any method to load homebrew.
+4. Select the IOS version to use. IOS249 recommended (if available).
+5. Select the storage device to use.
+6. Browse the storage device contents and select the WAD package
+ to (un)install.
[ NOTES ]:
View
BIN  data/background
Binary file not shown
View
16 source/fat.c
@@ -1,5 +1,6 @@
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include <ogcsys.h>
#include "fat.h"
@@ -7,7 +8,8 @@
s32 Fat_Mount(fatDevice *dev)
{
- s32 ret;
+ char dirpath[256];
+ s32 ret;
/* Initialize interface */
ret = dev->interface->startup();
@@ -17,7 +19,11 @@ s32 Fat_Mount(fatDevice *dev)
/* Mount device */
ret = fatMountSimple(dev->mount, dev->interface);
if (!ret)
- return -1;
+ return -2;
+
+ /* Set root directory */
+ sprintf(dirpath, "%s:/", dev->mount);
+ chdir(dirpath);
return 0;
}
@@ -55,3 +61,9 @@ char *Fat_ToFilename(const char *filename)
return buffer;
}
+
+void Fat_ChangeDir(const char *dirname)
+{
+ /* Change directory */
+ chdir(dirname);
+}
View
1  source/fat.h
@@ -36,6 +36,7 @@ typedef struct {
s32 Fat_Mount(fatDevice *);
void Fat_Unmount(fatDevice *);
char *Fat_ToFilename(const char *);
+void Fat_ChangeDir(const char *);
#endif
View
6 source/gui.c
@@ -5,10 +5,10 @@
#include "video.h"
/* Constants */
-#define CONSOLE_XCOORD 48
+#define CONSOLE_XCOORD 52
#define CONSOLE_YCOORD 118
-#define CONSOLE_WIDTH 544
-#define CONSOLE_HEIGHT 236
+#define CONSOLE_WIDTH 540
+#define CONSOLE_HEIGHT 280
s32 __Gui_DrawPng(void *img, u32 x, u32 y)
View
111 source/menu.c
@@ -42,9 +42,7 @@ static nandDevice *ndev = NULL;
/* Constants */
#define CIOS_VERSION 249
-#define ENTRIES_PER_PAGE 8
-
-#define WAD_DIRECTORY "/wad"
+#define ENTRIES_PER_PAGE 10
s32 __Menu_IsGreater(const void *p1, const void *p2)
@@ -64,7 +62,14 @@ s32 __Menu_EntryCmp(const void *p1, const void *p2)
fatFile *f1 = (fatFile *)p1;
fatFile *f2 = (fatFile *)p2;
- /* Compare entries */
+ s32 ret;
+
+ /* Compare attributes */
+ ret = (f1->filestat.st_mode - f2->filestat.st_mode);
+ if (ret)
+ return ret;
+
+ /* Compare names */
return strcmp(f1->filename, f2->filename);
}
@@ -75,22 +80,16 @@ s32 __Menu_RetrieveList(fatFile **outbuf, u32 *outlen)
struct stat filestat;
- char dirpath[256], filename[768];
+ char filename[768];
u32 cnt;
- /* Generate dirpath */
- sprintf(dirpath, "%s:" WAD_DIRECTORY, fdev->mount);
-
/* Open directory */
- dir = diropen(dirpath);
+ dir = diropen(".");
if (!dir)
return -1;
/* Count entries */
- for (cnt = 0; !dirnext(dir, filename, &filestat);) {
- if (!(filestat.st_mode & S_IFDIR))
- cnt++;
- }
+ for(cnt = 0; !dirnext(dir, filename, &filestat); cnt++);
if (cnt > 0) {
/* Allocate memory */
@@ -105,15 +104,13 @@ s32 __Menu_RetrieveList(fatFile **outbuf, u32 *outlen)
/* Get entries */
for (cnt = 0; !dirnext(dir, filename, &filestat);) {
- if (!(filestat.st_mode & S_IFDIR)) {
- fatFile *file = &buffer[cnt++];
+ fatFile *file = &buffer[cnt++];
- /* File name */
- strcpy(file->filename, filename);
+ /* File name */
+ strcpy(file->filename, filename);
- /* File stats */
- file->filestat = filestat;
- }
+ /* File stats */
+ file->filestat = filestat;
}
/* Sort list */
@@ -130,6 +127,19 @@ s32 __Menu_RetrieveList(fatFile **outbuf, u32 *outlen)
return 0;
}
+s32 __Menu_ChangeDir(fatFile *file, fatFile **outbuf, u32 *outlen)
+{
+ /* Change directory */
+ Fat_ChangeDir(file->filename);
+
+ /* Free memory */
+ if (*outbuf)
+ free(*outbuf);
+
+ /* Retrieve list */
+ return __Menu_RetrieveList(outbuf, outlen);
+}
+
void Menu_SelectIOS(void)
{
@@ -215,7 +225,8 @@ void Menu_SelectIOS(void)
void Menu_FatDevice(void)
{
- s32 ret, selected = 0;
+ s32 selected = 0;
+ s32 ret;
/* Unmount FAT device */
if (fdev)
@@ -282,7 +293,8 @@ void Menu_FatDevice(void)
void Menu_NandDevice(void)
{
- s32 ret, selected = 0;
+ s32 selected = 0;
+ s32 ret;
/* Disable NAND emulator */
if (ndev) {
@@ -364,10 +376,8 @@ void Menu_WadManage(fatFile *file)
{
FILE *fp = NULL;
- char filepath[128];
- f32 filesize;
-
- u32 mode = 0;
+ f32 filesize;
+ u32 mode = 0;
/* File size in megabytes */
filesize = (file->filestat.st_size / MB_SIZE);
@@ -408,11 +418,8 @@ void Menu_WadManage(fatFile *file)
printf("[+] Opening \"%s\", please wait...", file->filename);
fflush(stdout);
- /* Generate filepath */
- sprintf(filepath, "%s:" WAD_DIRECTORY "/%s", fdev->mount, file->filename);
-
/* Open WAD */
- fp = fopen(filepath, "rb");
+ fp = fopen(file->filename, "rb");
if (!fp) {
printf(" ERROR!\n");
goto out;
@@ -444,7 +451,8 @@ void Menu_WadList(void)
fatFile *fileList = NULL;
u32 fileCnt;
- s32 ret, selected = 0, start = 0;
+ s32 selected = 0, start = 0;
+ s32 ret;
printf("[+] Retrieving file list...");
fflush(stdout);
@@ -458,7 +466,7 @@ void Menu_WadList(void)
/* No files */
if (!fileCnt) {
- printf(" No files found!\n");
+ printf(" No files/directories found!\n");
goto err;
}
@@ -470,30 +478,36 @@ void Menu_WadList(void)
Con_Clear();
/** Print entries **/
- printf("[+] Available WAD files on the device:\n\n");
+ printf("[++] Filebrowser:\n\n");
/* Print entries */
for (cnt = start; cnt < fileCnt; cnt++) {
- fatFile *file = &fileList[cnt];
- f32 filesize = file->filestat.st_size / MB_SIZE;
+ fatFile *file = &fileList[cnt];
+ f32 fsize = (file->filestat.st_size / MB_SIZE);
/* Entries per page limit */
if ((cnt - start) >= ENTRIES_PER_PAGE)
break;
/* Print filename */
- printf("\t%2s %s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", file->filename, filesize);
+ printf("\t%2s %-42s", (cnt == selected) ? ">>" : " ", file->filename);
+
+ /* Print stats */
+ if (file->filestat.st_mode & S_IFDIR)
+ printf(" (DIR)\n");
+ else
+ printf(" (%.2f MB)\n", fsize);
}
printf("\n");
- printf("[+] Press A button to (un)install a WAD file.\n");
+ printf(" Press A button to open a directory or a WAD file.\n");
printf(" Press B button to select the storage device.\n");
/** Controls **/
u32 buttons = Wpad_WaitButtons();
- /* DPAD buttons */
+ /* D-PAD buttons */
if (buttons & (WPAD_BUTTON_UP | WPAD_BUTTON_LEFT)) {
selected -= (buttons & WPAD_BUTTON_LEFT) ? ENTRIES_PER_PAGE : 1;
@@ -512,8 +526,25 @@ void Menu_WadList(void)
Restart();
/* A button */
- if (buttons & WPAD_BUTTON_A)
- Menu_WadManage(&fileList[selected]);
+ if (buttons & WPAD_BUTTON_A) {
+ fatFile *file = &fileList[selected];
+
+ /* Manage entry */
+ if (file->filestat.st_mode & S_IFDIR) {
+ /* Change directory */
+ ret = __Menu_ChangeDir(file, &fileList, &fileCnt);
+ if (ret < 0) {
+ printf("\n");
+ printf("[+] ERROR: Could not change the directory! (ret = %d)\n", ret);
+
+ break;
+ }
+
+ /* Reset cursor */
+ selected = 0;
+ } else
+ Menu_WadManage(file);
+ }
/* B button */
if (buttons & WPAD_BUTTON_B)
View
546 source/oggplayer.c
@@ -0,0 +1,546 @@
+/*
+ Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net>
+ All rights reserved.
+
+ Proper (standard) vorbis usage by Tantric, 2009
+ Threading modifications/corrections by Tantric, 2009
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - The names of the contributors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NO_SOUND
+
+#include <asndlib.h>
+#include <tremor/ivorbiscodec.h>
+#include <tremor/ivorbisfile.h>
+#include <gccore.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "oggplayer.h"
+
+/* functions to read the Ogg file from memory */
+
+static struct
+{
+ char *mem;
+ int size;
+ int pos;
+} file[4];
+
+static int f_read(void * punt, int bytes, int blocks, int *f)
+{
+ int b;
+ int c = 0;
+ int d;
+
+ if (bytes * blocks <= 0)
+ return 0;
+
+ blocks *= bytes;
+
+ while (blocks > 0)
+ {
+ b = blocks;
+ if (b > 4096)
+ b = 4096;
+
+ d = (*f) - 0x666;
+ if((unsigned)(d) <= (0x669 - 0x666))
+ {
+ if (file[d].size == 0)
+ return -1;
+ if ((file[d].pos + b) > file[d].size)
+ b = file[d].size - file[d].pos;
+ if (b > 0)
+ {
+ memcpy(punt, file[d].mem + file[d].pos, b);
+ file[d].pos += b;
+ }
+ }
+ else
+ b = read(*f, ((char *) punt) + c, b);
+
+ if (b <= 0)
+ {
+ return c / bytes;
+ }
+ c += b;
+ blocks -= b;
+ }
+ return c / bytes;
+}
+
+static int f_seek(int *f, ogg_int64_t offset, int mode)
+{
+ if(f==NULL) return(-1);
+
+ int k;
+ mode &= 3;
+
+ int d = (*f) - 0x666;
+ if((unsigned)(d) <= (0x669 - 0x666))
+ {
+ k = 0;
+
+ if (file[d].size == 0)
+ return -1;
+
+ if (mode == 0)
+ {
+ if ((offset) >= file[d].size)
+ {
+ file[d].pos = file[d].size;
+ k = -1;
+ }
+ else if ((offset) < 0)
+ {
+ file[d].pos = 0;
+ k = -1;
+ }
+ else
+ file[d].pos = offset;
+ }
+ else if (mode == 1)
+ {
+ if ((file[d].pos + offset) >= file[d].size)
+ {
+ file[d].pos = file[d].size;
+ k = -1;
+ }
+ else if ((file[d].pos + offset) < 0)
+ {
+ file[d].pos = 0;
+ k = -1;
+ }
+ else
+ file[d].pos += offset;
+ }
+ else if (mode == 2)
+ {
+
+ if ((file[d].size + offset) >= file[d].size)
+ {
+ file[d].pos = file[d].size;
+ k = -1;
+ }
+ else if ((file[d].size + offset) < 0)
+ {
+ file[d].pos = 0;
+ k = -1;
+ }
+ else
+ file[d].pos = file[d].size + offset;
+ }
+
+ }
+ else
+ k = lseek(*f, (int) offset, mode);
+
+ if (k < 0)
+ k = -1;
+ else
+ k = 0;
+ return k;
+}
+
+static int f_close(int *f)
+{
+ int d = (*f) - 0x666;
+ if((unsigned)(d) <= (0x669 - 0x666))
+ {
+ file[d].size = 0;
+ file[d].pos = 0;
+ if (file[d].mem)
+ {
+ file[d].mem = (void *) 0;
+ }
+ return 0;
+ }
+ else
+ return close(*f);
+ return 0;
+}
+
+static long f_tell(int *f)
+{
+ int k;
+
+ int d = (*f) - 0x666;
+ if((unsigned)(d) <= (0x669 - 0x666))
+ {
+ k = file[d].pos;
+ }
+ else
+ k = lseek(*f, 0, 1);
+
+ return (long) k;
+}
+
+static int mem_open(char * ogg, int size)
+{
+ static int one = 1;
+ int n;
+ if (one)
+ {
+ one = 0;
+
+ file[0].size = 0;
+ file[1].size = 0;
+ file[2].size = 0;
+ file[3].size = 0;
+ file[0].mem = ogg;
+ file[0].size = size;
+ file[0].pos = 0;
+ return (0x666);
+ }
+
+ for (n = 0; n < 4; n++)
+ {
+ if (file[n].size == 0)
+ {
+ file[n].mem = ogg;
+ file[n].size = size;
+ file[n].pos = 0;
+ return (0x666 + n);
+ }
+ }
+ return -1;
+}
+
+static int mem_close(int fd)
+{
+ if((unsigned)((fd) - 0x666) <= (0x669 - 0x666)) // it is a memory file descriptor?
+ {
+ fd -= 0x666;
+ file[fd].size = 0;
+ return 0;
+ }
+ else
+ return f_close(&fd);
+}
+
+static ov_callbacks callbacks = {
+ (size_t (*)(void *, size_t, size_t, void *)) f_read,
+ (int (*)(void *, ogg_int64_t, int)) f_seek,
+ (int (*)(void *)) f_close,
+ (long (*)(void *)) f_tell
+};
+
+/* OGG control */
+
+#define READ_SAMPLES 4096 // samples that it must read before to send
+#define MAX_PCMOUT 4096 // minimum size to read ogg samples
+typedef struct
+{
+ OggVorbis_File vf;
+ vorbis_info *vi;
+ int current_section;
+
+ // OGG file operation
+ int fd;
+ int mode;
+ int eof;
+ int flag;
+ int volume;
+ int seek_time;
+
+ /* OGG buffer control */
+ short pcmout[2][READ_SAMPLES + MAX_PCMOUT * 2]; /* take 4k out of the data segment, not the stack */
+ int pcmout_pos;
+ int pcm_indx;
+
+} private_data_ogg;
+
+static private_data_ogg private_ogg;
+
+// OGG thread control
+
+#define STACKSIZE 8192
+
+static u8 oggplayer_stack[STACKSIZE];
+static lwpq_t oggplayer_queue = LWP_TQUEUE_NULL;
+static lwp_t h_oggplayer = LWP_THREAD_NULL;
+static int ogg_thread_running = 0;
+
+static void ogg_add_callback(int voice)
+{
+ if (!ogg_thread_running)
+ {
+ ASND_StopVoice(0);
+ return;
+ }
+
+ if (private_ogg.flag & 128)
+ return; // Ogg is paused
+
+ if (private_ogg.pcm_indx >= READ_SAMPLES)
+ {
+ if (ASND_AddVoice(0,
+ (void *) private_ogg.pcmout[private_ogg.pcmout_pos],
+ private_ogg.pcm_indx << 1) == 0)
+ {
+ private_ogg.pcmout_pos ^= 1;
+ private_ogg.pcm_indx = 0;
+ private_ogg.flag = 0;
+ LWP_ThreadSignal(oggplayer_queue);
+ }
+ }
+ else
+ {
+ if (private_ogg.flag & 64)
+ {
+ private_ogg.flag &= ~64;
+ LWP_ThreadSignal(oggplayer_queue);
+ }
+ }
+}
+
+static void * ogg_player_thread(private_data_ogg * priv)
+{
+ int first_time = 1;
+ long ret;
+
+ //init
+ LWP_InitQueue(&oggplayer_queue);
+
+ priv[0].vi = ov_info(&priv[0].vf, -1);
+
+ ASND_Pause(0);
+
+ priv[0].pcm_indx = 0;
+ priv[0].pcmout_pos = 0;
+ priv[0].eof = 0;
+ priv[0].flag = 0;
+ priv[0].current_section = 0;
+
+ ogg_thread_running = 1;
+
+ while (!priv[0].eof && ogg_thread_running)
+ {
+ if (priv[0].flag)
+ LWP_ThreadSleep(oggplayer_queue); // wait only when i have samples to send
+
+ if (priv[0].flag == 0) // wait to all samples are sent
+ {
+ if (ASND_TestPointer(0, priv[0].pcmout[priv[0].pcmout_pos])
+ && ASND_StatusVoice(0) != SND_UNUSED)
+ {
+ priv[0].flag |= 64;
+ continue;
+ }
+ if (priv[0].pcm_indx < READ_SAMPLES)
+ {
+ priv[0].flag = 3;
+
+ if (priv[0].seek_time >= 0)
+ {
+ ov_time_seek(&priv[0].vf, priv[0].seek_time);
+ priv[0].seek_time = -1;
+ }
+
+ ret = ov_read(
+ &priv[0].vf,
+ (void *) &priv[0].pcmout[priv[0].pcmout_pos][priv[0].pcm_indx],
+ MAX_PCMOUT,/*0,2,1,*/&priv[0].current_section);
+ priv[0].flag &= 192;
+ if (ret == 0)
+ {
+ /* EOF */
+ if (priv[0].mode & 1)
+ ov_time_seek(&priv[0].vf, 0); // repeat
+ else
+ priv[0].eof = 1; // stops
+ }
+ else if (ret < 0)
+ {
+ /* error in the stream. Not a problem, just reporting it in
+ case we (the app) cares. In this case, we don't. */
+ if (ret != OV_HOLE)
+ {
+ if (priv[0].mode & 1)
+ ov_time_seek(&priv[0].vf, 0); // repeat
+ else
+ priv[0].eof = 1; // stops
+ }
+ }
+ else
+ {
+ /* we don't bother dealing with sample rate changes, etc, but
+ you'll have to*/
+ priv[0].pcm_indx += ret >> 1; //get 16 bits samples
+ }
+ }
+ else
+ priv[0].flag = 1;
+ }
+
+ if (priv[0].flag == 1)
+ {
+ if (ASND_StatusVoice(0) == SND_UNUSED || first_time)
+ {
+ first_time = 0;
+ if (priv[0].vi->channels == 2)
+ {
+ ASND_SetVoice(0, VOICE_STEREO_16BIT, priv[0].vi->rate, 0,
+ (void *) priv[0].pcmout[priv[0].pcmout_pos],
+ priv[0].pcm_indx << 1, priv[0].volume,
+ priv[0].volume, ogg_add_callback);
+ priv[0].pcmout_pos ^= 1;
+ priv[0].pcm_indx = 0;
+ priv[0].flag = 0;
+ }
+ else
+ {
+ ASND_SetVoice(0, VOICE_MONO_16BIT, priv[0].vi->rate, 0,
+ (void *) priv[0].pcmout[priv[0].pcmout_pos],
+ priv[0].pcm_indx << 1, priv[0].volume,
+ priv[0].volume, ogg_add_callback);
+ priv[0].pcmout_pos ^= 1;
+ priv[0].pcm_indx = 0;
+ priv[0].flag = 0;
+ }
+ }
+ }
+ usleep(100);
+ }
+ ov_clear(&priv[0].vf);
+ priv[0].fd = -1;
+ priv[0].pcm_indx = 0;
+
+ return 0;
+}
+
+void StopOgg()
+{
+ ASND_StopVoice(0);
+ ogg_thread_running = 0;
+
+ if(h_oggplayer != LWP_THREAD_NULL)
+ {
+ if(oggplayer_queue != LWP_TQUEUE_NULL)
+ LWP_ThreadSignal(oggplayer_queue);
+ LWP_JoinThread(h_oggplayer, NULL);
+ h_oggplayer = LWP_THREAD_NULL;
+ }
+ if(oggplayer_queue != LWP_TQUEUE_NULL)
+ {
+ LWP_CloseQueue(oggplayer_queue);
+ oggplayer_queue = LWP_TQUEUE_NULL;
+ }
+}
+
+int PlayOgg(const void *buffer, s32 len, int time_pos, int mode)
+{
+ StopOgg();
+
+ private_ogg.fd = mem_open((char *)buffer, len);
+
+ if (private_ogg.fd < 0)
+ {
+ private_ogg.fd = -1;
+ return -1;
+ }
+
+ private_ogg.mode = mode;
+ private_ogg.eof = 0;
+ private_ogg.volume = 127;
+ private_ogg.flag = 0;
+ private_ogg.seek_time = -1;
+
+ if (time_pos > 0)
+ private_ogg.seek_time = time_pos;
+
+ if (ov_open_callbacks((void *) &private_ogg.fd, &private_ogg.vf, NULL, 0, callbacks) < 0)
+ {
+ mem_close(private_ogg.fd); // mem_close() can too close files from devices
+ private_ogg.fd = -1;
+ ogg_thread_running = 0;
+ return -1;
+ }
+
+ if (LWP_CreateThread(&h_oggplayer, (void *) ogg_player_thread,
+ &private_ogg, oggplayer_stack, STACKSIZE, 80) == -1)
+ {
+ ogg_thread_running = 0;
+ ov_clear(&private_ogg.vf);
+ private_ogg.fd = -1;
+ return -1;
+ }
+ return 0;
+}
+
+void PauseOgg(int pause)
+{
+ if (pause)
+ {
+ private_ogg.flag |= 128;
+ }
+ else
+ {
+ if (private_ogg.flag & 128)
+ {
+ private_ogg.flag |= 64;
+ private_ogg.flag &= ~128;
+ if (ogg_thread_running > 0)
+ {
+ LWP_ThreadSignal(oggplayer_queue);
+ }
+ }
+ }
+}
+
+int StatusOgg()
+{
+ if (ogg_thread_running == 0)
+ return -1; // Error
+ else if (private_ogg.eof)
+ return 255; // EOF
+ else if (private_ogg.flag & 128)
+ return 2; // paused
+ return 1; // running
+}
+
+void SetVolumeOgg(int volume)
+{
+ private_ogg.volume = volume;
+ ASND_ChangeVolumeVoice(0, volume, volume);
+}
+
+s32 GetTimeOgg()
+{
+ int ret;
+ if (ogg_thread_running == 0 || private_ogg.fd < 0)
+ return -1;
+ ret = ((s32) ov_time_tell(&private_ogg.vf));
+
+ return ret;
+}
+
+void SetTimeOgg(s32 time_pos)
+{
+ if (time_pos >= 0)
+ private_ogg.seek_time = time_pos;
+}
+
+#endif
View
113 source/oggplayer.h
@@ -0,0 +1,113 @@
+/*
+ Copyright (c) 2008 Francisco Muñoz 'Hermes' <www.elotrolado.net>
+ All rights reserved.
+
+ Proper (standard) vorbis usage by Tantric, 2009
+ Threading modifications/corrections by Tantric, 2009
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - The names of the contributors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OGGPLAYER_H__
+#define __OGGPLAYER_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define OGG_ONE_TIME 0
+#define OGG_INFINITE_TIME 1
+
+#define OGG_STATUS_RUNNING 1
+#define OGG_STATUS_ERR -1
+#define OGG_STATUS_PAUSED 2
+#define OGG_STATUS_EOF 255
+
+/****************************************************************************
+ * PlayOgg
+ *
+ * Creates a thread that starts playing from the specific Ogg buffer
+ * buffer - pointer to the start of the Ogg data
+ * len - length of Ogg file
+ * time_pos - initial time position at which to start playback
+ * mode - playback mode (OGG_ONE_TIME or OGG_INFINITE_TIME)
+ * returns: -1 on error, 0 on success
+ ***************************************************************************/
+int PlayOgg(const void *buffer, s32 len, int time_pos, int mode);
+
+/****************************************************************************
+ * StopOgg
+ *
+ * Stops playback. The player thread is shut down.
+ ***************************************************************************/
+void StopOgg();
+
+/****************************************************************************
+ * PauseOgg
+ *
+ * Pauses playback. 0 -> continue, 1-> pause
+ ***************************************************************************/
+void PauseOgg(int pause);
+
+/****************************************************************************
+ * StatusOgg
+ *
+ * Returns the Ogg player's status
+ * returns:
+ * OGG_STATUS_RUNNING
+ * OGG_STATUS_ERR -> not initialized
+ * OGG_STATUS_PAUSED
+ * OGG_STATUS_EOF -> player stopped by End Of File
+ ***************************************************************************/
+int StatusOgg();
+
+/****************************************************************************
+ * SetVolumeOgg
+ *
+ * Sets the Ogg playback volume (0 to 255 (max))
+ ***************************************************************************/
+void SetVolumeOgg(int volume);
+
+/****************************************************************************
+ * GetTimeOgg
+ *
+ * Gets current Ogg position
+ * returns -1 on error, or the time in milliseconds from the start
+ ***************************************************************************/
+s32 GetTimeOgg();
+
+/****************************************************************************
+ * SetTimeOgg
+ *
+ * Sets the time position
+ * time_pos: time position (in milliseconds) to advance
+ ***************************************************************************/
+void SetTimeOgg(s32 time_pos);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
View
177 source/sha1.c
@@ -0,0 +1,177 @@
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd if true. */
+#define SHA1HANDSOFF
+
+#include <stdio.h>
+#include <string.h>
+#include "sha1.h"
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+typedef struct {
+ unsigned long state[5];
+ unsigned long count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
+{
+unsigned long a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ unsigned long l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
+{
+unsigned int i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned long i, j;
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = j = 0;
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
+
+void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) {
+ SHA1_CTX ctx;
+
+ SHA1Init(&ctx);
+ SHA1Update(&ctx, ptr, size);
+ SHA1Final(outbuf, &ctx);
+}
View
6 source/sha1.h
@@ -0,0 +1,6 @@
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+void SHA1(unsigned char *, unsigned int, unsigned char *);
+
+#endif
View
35 source/sound.c
@@ -0,0 +1,35 @@
+#include <ogcsys.h>
+#include <asndlib.h>
+
+#include "oggplayer.h"
+#include "sound.h"
+
+/* Externs */
+extern u8 bgMusic[];
+extern u32 bgMusic_Len;
+
+
+void Sound_Init(void)
+{
+ /* Init ASND */
+ ASND_Init();
+}
+
+s32 Sound_Play(void)
+{
+ /* Play background music */
+ return PlayOgg(bgMusic, bgMusic_Len, 0, OGG_INFINITE_TIME);
+}
+
+void Sound_Stop(void)
+{
+ /* Stop background music */
+ if (Sound_IsPlaying())
+ StopOgg();
+}
+
+s32 Sound_IsPlaying(void)
+{
+ /* Check if background music is playing */
+ return (StatusOgg() == OGG_STATUS_RUNNING);
+}
View
11 source/sound.h
@@ -0,0 +1,11 @@
+#ifndef _SOUND_H_
+#define _SOUND_H_
+
+/* Prototypes */
+void Sound_Init(void);
+s32 Sound_Play(void);
+void Sound_Stop(void);
+s32 Sound_IsPlaying(void);
+
+#endif
+
View
15 source/stub.S
@@ -1,6 +1,17 @@
.rodata
- .globl bgData
- .balign 32
+ .align 4
+ .global bgData
bgData:
.incbin "../data/background"
+
+
+ .align 4
+ .global bgMusic
+bgMusic:
+ .incbin "../data/bgmusic"
+bgMusic_End:
+
+ .global bgMusic_Len
+bgMusic_Len:
+ .long bgMusic_End - bgMusic
View
68 source/title.c
@@ -1,12 +1,80 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <malloc.h>
#include <ogcsys.h>
+#include "sha1.h"
#include "utils.h"
+s32 Title_ZeroSignature(signed_blob *p_sig)
+{
+ u8 *ptr = (u8 *)p_sig;
+
+ /* Fill signature with zeroes */
+ memset(ptr + 4, 0, SIGNATURE_SIZE(p_sig) - 4);
+
+ return 0;
+}
+
+s32 Title_FakesignTik(signed_blob *p_tik)
+{
+ tik *tik_data = NULL;
+ u16 fill;
+
+ /* Zero signature */
+ Title_ZeroSignature(p_tik);
+
+ /* Ticket data */
+ tik_data = (tik *)SIGNATURE_PAYLOAD(p_tik);
+
+ for (fill = 0; fill < USHRT_MAX; fill++) {
+ sha1 hash;
+
+ /* Modify ticket padding field */
+ tik_data->padding = fill;
+
+ /* Calculate hash */
+ SHA1((u8 *)tik_data, sizeof(tik), hash);
+
+ /* Found valid hash */
+ if (!hash[0])
+ return 0;
+ }
+
+ return -1;
+}
+
+s32 Title_FakesignTMD(signed_blob *p_tmd)
+{
+ tmd *tmd_data = NULL;
+ u16 fill;
+
+ /* Zero signature */
+ Title_ZeroSignature(p_tmd);
+
+ /* TMD data */
+ tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
+
+ for (fill = 0; fill < USHRT_MAX; fill++) {
+ sha1 hash;
+
+ /* Modify TMD fill field */
+ tmd_data->fill3 = fill;
+
+ /* Calculate hash */
+ SHA1((u8 *)tmd_data, TMD_SIZE(tmd_data), hash);
+
+ /* Found valid hash */
+ if (!hash[0])
+ return 0;
+ }
+
+ return -1;
+}
+
s32 Title_GetList(u64 **outbuf, u32 *outlen)
{
u64 *titles = NULL;
View
3  source/title.h
@@ -5,6 +5,9 @@
#define BLOCK_SIZE 1024
/* Prototypes */
+s32 Title_ZeroSignature(signed_blob *);
+s32 Title_FakesignTik(signed_blob *);
+s32 Title_FakesignTMD(signed_blob *);
s32 Title_GetList(u64 **, u32 *);
s32 Title_GetTicketViews(u64, tikview **, u32 *);
s32 Title_GetTMD(u64, signed_blob **, u32 *);
View
62 source/usbstorage.c
@@ -40,8 +40,6 @@ distribution.
#define USB_IOCTL_UMS_READ_STRESS (UMS_BASE+0x5)
#define USB_IOCTL_UMS_SET_VERBOSE (UMS_BASE+0x6)
-#define UMS_HEAPSIZE 0x8000
-
/* Variables */
static s32 hid = -1;
static s32 fd = -1;
@@ -77,16 +75,9 @@ bool USBStorage_Init(void)
{
s32 ret;
- /* Already open */
+ /* Already inited */
if (fd >= 0)
- return 0;
-
- /* Create heap */
- if (hid < 0) {
- hid = iosCreateHeap(UMS_HEAPSIZE);
- if (hid < 0)
- return false;
- }
+ return true;
/* Open USB module */
fd = IOS_Open("/dev/usb2", 0);
@@ -133,70 +124,31 @@ bool USBStorage_Deinit(void)
bool USBStorage_IsInserted(void)
{
/* Check if device is inserted */
- return !!USBStorage_GetCapacity(NULL);
+ return (USBStorage_GetCapacity(NULL) > 0);
}
bool USBStorage_ReadSectors(u32 sector, u32 numSectors, void *buffer)
{
- void *buf = (void *)buffer;
- u32 len = (sector_size * numSectors);
-
- s32 ret;
+ u32 len = (sector_size * numSectors);
/* Device not opened */
if (fd < 0)
return false;
- /* MEM1 buffer */
- if (!__USBStorage_isMEM2Buffer(buffer)) {
- /* Allocate memory */
- buf = iosAlloc(hid, len);
- if (!buf)
- return false;
- }
-
/* Read data */
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buf, len);
-
- /* Copy data */
- if (buf != buffer) {
- memcpy(buffer, buf, len);
- iosFree(hid, buf);
- }
-
- return true;
+ return IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, numSectors, buffer, len);
}
bool USBStorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer)
{
- void *buf = (void *)buffer;
- u32 len = (sector_size * numSectors);
-
- s32 ret;
+ u32 len = (sector_size * numSectors);
/* Device not opened */
if (fd < 0)
return false;
- /* MEM1 buffer */
- if (!__USBStorage_isMEM2Buffer(buffer)) {
- /* Allocate memory */
- buf = iosAlloc(hid, len);
- if (!buf)
- return false;
-
- /* Copy data */
- memcpy(buf, buffer, len);
- }
-
/* Write data */
- ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buf, len);
-
- /* Free memory */
- if (buf != buffer)
- iosFree(hid, buf);
-
- return true;
+ return IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, numSectors, buffer, len);
}
bool USBStorage_ClearStatus(void)
View
7 source/wad-manager.c
@@ -6,6 +6,7 @@
#include "gui.h"
#include "menu.h"
#include "restart.h"
+#include "sound.h"
#include "sys.h"
#include "video.h"
#include "wpad.h"
@@ -52,6 +53,12 @@ int main(int argc, char **argv)
/* Draw background */
Gui_DrawBackground();
+ /* Initialize sound */
+ Sound_Init();
+
+ /* Play sound */
+ Sound_Play();
+
/* Initialize Wiimote */
Wpad_Init();
View
8 source/wad.c
@@ -107,9 +107,13 @@ void __Wad_FixTicket(signed_blob *p_tik)
u8 *data = (u8 *)p_tik;
u8 *ckey = data + 0x1F1;
- /* Check common key */
- if (*ckey > 1)
+ if (*ckey > 1) {
+ /* Set common key */
*ckey = 0;
+
+ /* Fakesign ticket */
+ Title_FakesignTik(p_tik);
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.