/*
 *  Copyright (C) 2008 Nuke (wiinuke@gmail.com)
 *
 *  this file is part of GeckoOS for USB Gecko
 *  http://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
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <gccore.h>
#include <wiiuse/wpad.h>
#include <sys/unistd.h>
#include "kenobiwii.h"
#include "geckomenu.h"
#include "font.h"
#include "geckocard.h"
#include "geckomusic.h"
#include "geckoload.h"
#include "geckodvd.h"
#include "geckousb.h"
#include "geckomem.h"
#include "geckolowlevel.h"
#include "apploader.h"
#include "patchcode.h"
#include "tools.h"
#include "menu_rnc.h"
#include "libcios.h"


#define logogfx_size 563200


u32 *xfb = NULL;
static GXRModeObj *rmode = NULL;
u8 gecko_command = 0;

extern s32 __SYS_LoadMenu();

static void power_cb () {
	STM_ShutdownToStandby();
}

static void reset_cb () {
	STM_RebootSystem();
}

static void __cleanup()
{
	gecko_command = 0;
	sleep(1);			
	clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
	usb_flush(EXI_CHANNEL_1);
	gecko_command = 0;
}

static void __configswitch()
{
		switch(configbytes[0])
				{
					case 0xCD: 
						write_font(185, 178, "Lang: Default");
					break;

					case 0x00: 
						write_font(185, 178, "Lang: Japanese");
					break;

					case 0x01: 
						write_font(185, 178, "Lang: English");
					break;

					case 0x02: 
						write_font(185, 178, "Lang: German");
					break;

					case 0x03: 
						write_font(185, 178, "Lang: French");
					break;

					case 0x04: 
						write_font(185, 178, "Lang: Spanish");
					break;

					case 0x05: 
						write_font(185, 178, "Lang: Italian");
					break;

					case 0x06: 
						write_font(185, 178, "Lang: Dutch");
					break;

					case 0x07: 
						write_font(185, 178, "Lang: S. Chinese");
					break;

					case 0x08: 
						write_font(185, 178, "Lang: T. Chinese");
					break;

					case 0x09: 
						write_font(185, 178, "Lang: Korean");
					break;
				}
}

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

	u8 *gfxbuffer;
	u32 geckoattached = 0;
	s32 di_error_code;

	u8 gamestatus = 0x03;
	u8 versionnumber = 0x80;
//	u8 fail_packet = 0xFF;
	u32 frozenvalue;
	//s32 ret = 0;
	char buffer[64];

	CIOS_Load();

	/* Init Video, Pad, Fonts */
	VIDEO_Init();
	PAD_Init();
	WPAD_Init();
	WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
	init_font();
	SYS_SetPowerCallback (power_cb);
    SYS_SetResetCallback (reset_cb);
	AUDIO_Init (NULL);
    DSP_Init ();
	AUDIO_StopDMA();
	AUDIO_RegisterDMACallback(NULL);
	
	rmode = VIDEO_GetPreferredMode(NULL);
	if (CONF_GetProgressiveScan() > 0 && VIDEO_HaveComponentCable()) {
		progmode = 1;
	}
			
	xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));

	console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);

	VIDEO_Configure(rmode);
	VIDEO_SetNextFramebuffer(xfb);
	VIDEO_SetBlack(FALSE);
	VIDEO_Flush();

	VIDEO_WaitVSync();
	if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
	VIDEO_ClearFrameBuffer(rmode,xfb,0x44B54451);
	
	/* Setup Graphics */
	gfxbuffer = (u8*) memalign (32, logogfx_size);
	if(!gfxbuffer){
		printf("\n\n");
		printf("Failed to allocated graphics memory\n");
		while(1);
	}

	depackrnc1((u8*)menu_rnc,gfxbuffer);
	VIDEO_ClearFrameBuffer(rmode,xfb,*((unsigned long *) &gfxbuffer[logogfx_size - 4]));
	memcpy(xfb, gfxbuffer, logogfx_size);
	
	*(vu32*)0xCD00643C = 0x00000000;	// 32Mhz on Bus

	geckoattached = usb_isgeckoalive(EXI_CHANNEL_1);

	if(!geckoattached){	
		drawicon(xfb, 22, 397, 32/2, 27,0);
		VIDEO_WaitVSync();
	}
	else {
		drawicon(xfb, 22, 397, 32/2, 27,1);
		usb_flush(EXI_CHANNEL_1);
		VIDEO_WaitVSync();
	}

	clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
	
	drawmenu(0);
	drawselected(0);

	snprintf(buffer, sizeof(buffer), "Backup Launcher 0.3 gamma, IOS%d", IOS_GetVersion());
	write_font(80, 400, buffer);
	
	/* Stop Drive */
	di_error_code = dvd_openios();
	di_error_code = dvd_stopdrive();
	dvd_closeios();

	/* Main Loop */
	while(1)
	{	// need if statement here for none usb gecko users
		if(geckoattached){
		usb_recvbuffer(EXI_CHANNEL_1,&gecko_command,1);
		switch(gecko_command)
		{
		
	//		case 0x04:	
	//			write_font(60, 154, "Dumping Mem");
	///			checkmusicloaded();
	//		gecko_readmem();
	//		__cleanup();
			break;

			case 0x14:		
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Loading DOL File");
				checkmusicloaded();
				commands_uploadexe(0);
				__cleanup();
			break;

			
			case 0x15:			
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);	
				write_font(185, 154, "Listing Saves in Slot A");
				checkmusicloaded();
				commands_listcard();
				__cleanup();
			break;

			case 0x16:		
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);	
				write_font(185, 154, "Dumping GC Save");	
				checkmusicloaded();
				commands_dumpsave();
				__cleanup();
			break;
			
			case 0x17:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);	
				write_font(185, 154, "Erasing GC Save");	
				checkmusicloaded();
				commands_erasesave();
				__cleanup();
			break;

			case 0x24:		
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Loading ELF File");
				checkmusicloaded();
				commands_uploadexe(1);
				__cleanup();
			break; 

			case 0x28:
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);	
				write_font(185, 154, "Loading Mod File");
				checkmusicloaded();
				commands_uploadmod();
				__cleanup();
			break;

			case 0x29:			
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);	
				write_font(185, 154, "Loading MP3 File");	
				checkmusicloaded();
				commands_uploadmp3();
				__cleanup();
			break;

			case 0x32:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);	
				write_font(185, 154, "Uploading GC Save");	
				checkmusicloaded();
				commands_uploadsave();
				__cleanup();
			break;
			
			case 0x42:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Launching Game");
				hooktype = 1;
				nowiird = 0;
				memset((void*)0x80001800,0,kenobiwii_size);
				memcpy((void*)0x80001800,kenobiwii,kenobiwii_size); 
				DCFlushRange((void*)0x80001800,kenobiwii_size);
				usb_recvbuffer_safe(EXI_CHANNEL_1,&configbytes,2);	// Get config
				__configswitch();
				checkmusicloaded();
				apploader();
				__cleanup();	// Shouldn't return
			break;

			case 0x43:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Launching Game (Paused)");
				hooktype = 1;
				nowiird = 0;
				memset((void*)0x80001800,0,kenobiwii_size);
				memcpy((void*)0x80001800,kenobiwii,kenobiwii_size); 
				frozenvalue = *(u32*)0x80001808;
				*(u32*)frozenvalue = 1;	
				DCFlushRange((void*)0x80001800,kenobiwii_size);
				usb_recvbuffer_safe(EXI_CHANNEL_1,&configbytes,2);	// Get config
				__configswitch();
				checkmusicloaded();
				apploader();
				__cleanup();	// Shouldn't return
			break;

			case 0x44:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Launching Game");
				hooktype = 2;
				nowiird = 0;
				memset((void*)0x80001800,0,kenobiwii_size);
				memcpy((void*)0x80001800,kenobiwii,kenobiwii_size); 
				DCFlushRange((void*)0x80001800,kenobiwii_size);
				usb_recvbuffer_safe(EXI_CHANNEL_1,&configbytes,2);	// Get config
				__configswitch();
				checkmusicloaded();
				apploader();
				__cleanup();	// Shouldn't return
			break;

			case 0x45:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Launching Game (Paused)");
				hooktype = 2;
				nowiird = 0;
				memset((void*)0x80001800,0,kenobiwii_size);
				memcpy((void*)0x80001800,kenobiwii,kenobiwii_size); 
				frozenvalue = *(u32*)0x80001808;
				*(u32*)frozenvalue = 1;	
				DCFlushRange((void*)0x80001800,kenobiwii_size);
				usb_recvbuffer_safe(EXI_CHANNEL_1,&configbytes,2);	// Get config
				__configswitch();
				checkmusicloaded();
				apploader();
				__cleanup();	// Shouldn't return
			break;

			case 0x46:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Launching Game");
				hooktype = 3;
				nowiird = 0;
				memset((void*)0x80001800,0,kenobiwii_size);
				memcpy((void*)0x80001800,kenobiwii,kenobiwii_size); 
				DCFlushRange((void*)0x80001800,kenobiwii_size);
				usb_recvbuffer_safe(EXI_CHANNEL_1,&configbytes,2);	// Get config
				__configswitch();
				checkmusicloaded();
				apploader();
				__cleanup();	// Shouldn't return
			break;

			case 0x47:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Launching Game (Paused)");
				hooktype = 3;
				nowiird = 0;
				memset((void*)0x80001800,0,kenobiwii_size);
				memcpy((void*)0x80001800,kenobiwii,kenobiwii_size); 
				frozenvalue = *(u32*)0x80001808;
				*(u32*)frozenvalue = 1;	
				DCFlushRange((void*)0x80001800,kenobiwii_size);
				usb_recvbuffer_safe(EXI_CHANNEL_1,&configbytes,2);	// Get config
				__configswitch();
				checkmusicloaded();
				apploader();
				__cleanup();	// Shouldn't return
			break;
/*
			case 0x48:	
				clearscreen(xfb, 20, 80, 278, 315, 0x00800080);
				write_font(185, 154, "Game Log Enabled");
				debugmode = 1;
				nowiird = 0;
				checkmusicloaded();
				apploader();
				__cleanup();	// Shouldn't return
			break;
*/
			case 0x50:		
				usb_sendbuffer_safe(EXI_CHANNEL_1,&gamestatus,1);
			break;

			case 0x99:		
				usb_sendbuffer_safe(EXI_CHANNEL_1,&versionnumber,1); 
			break;
		}
		}	

		processwpad();
	}

	return 0;
}
