summaryrefslogtreecommitdiffstats
path: root/source/main.c
blob: 6040e7176547b649a52ea18f0ac1b63b2bca3ac9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gccore.h>
#include <network.h>
#include <fat.h>
#include <wiiuse/wpad.h>
#include <unistd.h> //for sleep()
#include <stdbool.h>

#include "main.h"
#include "gecko.h"

void boot_elf(void *payload, size_t size);

static void* xfb = NULL;

void* initialise();
static GXRModeObj* rmode = NULL;

const int min_row = 0;
int max_row;

int cursorrow;

enum direction
	{
	UP,DOWN
	};

void move_cursor(enum direction d)
	{
	if (d == UP)
		{
		if(cursorrow > min_row)
			{
			//move cursor back one space
			printf("\033[1D");
			//print space overwriting '>'
			printf(" ");
			--cursorrow;
			//move up a line
			printf("\033[1A");
			//back 1
			printf("\033[1D");
			//overwrite space
			printf(">");
			}
		}
	else if (d == DOWN)
		{

		if(cursorrow < max_row)
			{
			printf("\033[1D");//move cursor back 1 space
			printf(" ");//overwrite '>'
			++cursorrow;
			printf("\033[1B");//move down a line
			printf("\033[1D");//back 1
			printf(">");//overwrite space
			}
		}
	}


int main(int argc, char** argv)
	{
	checkForGecko();
	gprintf("Welcome to Yet Another Mod Fetcher");

	xfb = initialise();
	reset: cursorrow = 0;//reset cursor position to 0 every loop
	printf("\n\n\nYet Another Mod Fetcher\n");
	printf("Use Dpad to select a mod\n");
	printf("Press A to install\n");
	printf("Installed mods are coloured green\n");
	printf("Press + or x to boot mod (will hang if elf is too large)\n");
	printf("Press home or start to quit\n");

	if(!fatInitDefault()){printf("Initializing filesystem failed!\n"); exit(1);}//attempt to initalize filesystem
	download_file("files/wii/root.txt","root.txt",0);//download the root file and save it as "sd:/root.txt"
	max_row = parse_root_txt("sd:/root.txt");//max row = number of mods

	//move cursor back to first row and print '>'
	//up max_row+1 lines to be at the first line
	printf("\033[%dA", max_row+1);
	printf(">");

	while(1)
		{
		VIDEO_WaitVSync();
		WPAD_ScanPads();
		PAD_ScanPads();
		//get the button value for wii and gamecube remotes
		int buttonsDown = WPAD_ButtonsDown(0);
		int gcbuttonsDown = PAD_ButtonsDown(0);
		if((buttonsDown & WPAD_BUTTON_HOME) || (gcbuttonsDown & PAD_BUTTON_START))
			{
			remove("sd:/root.txt");
			printf("\033[2J");
			printf("\n\nBye bye\n");
			gprintf("Exiting");
			exit(0);
			}
		else if((buttonsDown & WPAD_BUTTON_A)||(gcbuttonsDown & PAD_BUTTON_A))
			{
			break;//install selected mod
			}
		else if((buttonsDown & WPAD_BUTTON_UP)||(gcbuttonsDown & PAD_BUTTON_UP))
			{
			move_cursor(UP);
			}
		else if((buttonsDown & WPAD_BUTTON_DOWN)||(gcbuttonsDown & PAD_BUTTON_DOWN))
			{
			move_cursor(DOWN);
			}
		else if((buttonsDown & WPAD_BUTTON_PLUS)||(gcbuttonsDown & PAD_BUTTON_X))
			{
			FILE *fp = fopen("sd:/root.txt", "r");
			fseek(fp, 0L, SEEK_END);//seek to the end of the file
			int size = ftell(fp);//store lenght of file
			rewind(fp);//seek back to start of file

			char buff[size];
			buff[size] = '\0';//add null char to end of buff

			char *colon = buff;//discarded
			char *secondColon = buff;//location of second colon
			char *newLine = buff; //location of newline

			int count = 0; //current line

			while(1)
			       	{
			        if (fgets(buff, size, fp) == NULL)
					{
					printf("Somethings wrong with root.txt\n");
					gprintf("Somethings wrong with root.txt");
					exit(1);
					}//get a single line from fp to buff

				if (cursorrow == count)//only parse root.txt if the correct line is reached
					{
					fclose(fp);
					colon = strstr(buff,":");//find colon in buff
					if (!colon)
						{
						printf("root.txt malformed!\n");
						gprintf("root.txt malformed!");
						exit(1);
						}

					secondColon = strstr(colon+1,":");//find second colon in buff
					if (!secondColon)
						{
						printf("root.txt malformed!\n");
						gprintf("root.txt malformed!");
						exit(1);
						}

					newLine = strstr(secondColon+1,"\n");//find newline in buff
					if (!newLine)
						{
						printf("root.txt malformed!\n");
						gprintf("root.txt malformed!");
						exit(1);
						}
					*newLine = '\0'; //replace newline with null char

					printf("\033[2J");//clear screen

					if (!strstr(secondColon+1,".elf"))
						{
						printf("\n\n\nNot an elf.\n");
						printf("Falling back to sd:/boot.elf.\n");
						gprintf("Not an elf.");
						gprintf("Falling back to sd:/boot.elf.\n");
						memcpy(secondColon+1,"sd:/boot.elf",13);//replace original file with sd:/boot.elf
						sleep(1);
						}

					FILE *elf = fopen(secondColon+1, "r");
					if (!elf)
						{
						printf("\n\n\nCould not open %s.\n", secondColon+1);
						printf("Falling back to sd:/boot.elf.\n");

						gprintf("Could not open %s.", secondColon+1);
						gprintf("Falling back to sd:/boot.elf.\n");
						sleep(1);
						elf = fopen("sd:/boot.elf", "r");
						if (!elf){printf("sd:/boot.elf does not exist"); printf("\033[2J"); goto reset;}
						}

					fseek(elf, 0L, SEEK_END);//seek to the end of the file
					int size = ftell(elf);//store lenght of file
					rewind(elf);//seek back to start of file

					char *payload_elf = malloc(size*sizeof(char));
					if (!payload_elf)
						{
						printf("Malloc failed!\n");
						gprintf("Malloc failed!");
						exit(1);
						}

					(void)fread(payload_elf, 1, size, elf);//if this fread fails here, we were going to crash anyway
					fclose(elf);

					boot_elf(payload_elf, size);
					printf("You should not be here\n");
					}
				++count;
				}

/*

					printf("\033[2J");//clear screen
					FILE *elf = fopen("sd:/boot.elf", "r");
					if (!elf){printf("Could not open root.txt\n"); gprintf("Could not open root.txt"); exit(1);}

					fseek(elf, 0L, SEEK_END);//seek to the end of the file
					int size = ftell(elf);//store lenght of file
					rewind(elf);//seek back to start of file


					//malloc is used since it seems to move the elf away from where is overwritten
					char *payload_elf = malloc(size*sizeof(char));

					(void)fread(payload_elf, 1, size, elf);//if this fread fails here, we were going to crash anyway
					boot_elf(payload_elf, size);
					printf("You should not be here\n");
					*/

			}
		}

	//clear screen
	printf("\033[2J");

	//install selected mod
	install_mod("sd:/root.txt", cursorrow);

	int removed = remove("sd:/root.zip");
	if (removed == -1){printf("Could not cleanup root.zip\n"); gprintf("Could not cleanup root.zip");}
	gprintf("Install Done"); printf("Install Done\n");
	sleep(1);

	printf("\033[2J");//clear screen
	goto reset;//reset so you can install another mod or something...

	return 0;
	}

//needs to be below main if you don't want a DSI
void* initialise()
	{
	void *framebuffer;

	VIDEO_Init();
	WPAD_Init();
	PAD_Init();
	rmode = VIDEO_GetPreferredMode(NULL);
	framebuffer = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
	console_init(framebuffer,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);

	VIDEO_Configure(rmode);
	VIDEO_SetNextFramebuffer(framebuffer);
	VIDEO_SetBlack(FALSE);
	VIDEO_Flush();
	VIDEO_WaitVSync();
	if(rmode->viTVMode&VI_NON_INTERLACE){VIDEO_WaitVSync(); return framebuffer;}
	return NULL;
	}