// Emacs style mode select   -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
//	Main program, simply calls D_DoomMain high level loop.
//
//-----------------------------------------------------------------------------

#include <pspkernel.h>
#include <pspctrl.h>
#include <pspdebug.h>
#include <pspmoduleinfo.h>
#include <psputility.h>
#include <psputility_osk.h>
#include <pspaudio.h>
#include <pspaudiolib.h>
#include <psppower.h>
#include <pspdisplay.h>
#include <pspgu.h>
#include <kubridge.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define printf pspDebugScreenPrintf

#define VERS	 1
#define REVS	 0


#include "doomdef.h"

#include "m_argv.h"
#include "d_main.h"
#include "i_system.h"
#include "m_fixed.h"


int pspDveMgrCheckVideoOut();
int pspDveMgrSetVideoOut(int, int, int, int, int, int, int);


int VERSION = 110;

char psp_home[256];

extern int quit_requested;

PSP_MODULE_INFO("DOOM", 0, VERS, REVS);
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);
PSP_HEAP_SIZE_MAX();
//PSP_HEAP_SIZE_KB(12000);

/* Exit callback */
int exit_callback(int arg1, int arg2, void *common) {
	quit_requested = 1;
	return 0;
}

/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
	int cbid;

	cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
	sceKernelRegisterExitCallback(cbid);
	sceKernelSleepThreadCB();
	return 0;
}

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
	int thid = 0;

	thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0);
	if(thid >= 0) {
		sceKernelStartThread(thid, 0, 0);
	}

	return thid;
}

/*
 * OSK support code
 *
 */

#define BUF_WIDTH (512)
#define SCR_WIDTH (480)
#define SCR_HEIGHT (272)
#define PIXEL_SIZE (4) /* change this if you change to another screenmode */
#define FRAME_SIZE (BUF_WIDTH * SCR_HEIGHT * PIXEL_SIZE)
#define ZBUF_SIZE (BUF_WIDTH SCR_HEIGHT * 2) /* zbuffer seems to be 16-bit? */

static unsigned int __attribute__((aligned(16))) list[262144];

static void SetupGu()
{
	sceGuInit();

	sceGuStart(GU_DIRECT,list);
	sceGuDrawBuffer(GU_PSM_8888,(void*)0,BUF_WIDTH);
	sceGuDispBuffer(SCR_WIDTH,SCR_HEIGHT,(void*)0x88000,BUF_WIDTH);
	sceGuDepthBuffer((void*)0x110000,BUF_WIDTH);
	sceGuOffset(2048 - (SCR_WIDTH/2),2048 - (SCR_HEIGHT/2));
	sceGuViewport(2048,2048,SCR_WIDTH,SCR_HEIGHT);
	sceGuDepthRange(0xc350,0x2710);
	sceGuScissor(0,0,SCR_WIDTH,SCR_HEIGHT);
	sceGuEnable(GU_SCISSOR_TEST);
	sceGuDepthFunc(GU_GEQUAL);
	sceGuEnable(GU_DEPTH_TEST);
	sceGuFrontFace(GU_CW);
	sceGuShadeModel(GU_SMOOTH);
	sceGuEnable(GU_CULL_FACE);
	sceGuEnable(GU_CLIP_PLANES);
	sceGuFinish();
	sceGuSync(0,0);

	sceDisplayWaitVblankStart();
	sceGuDisplay(GU_TRUE);
}

int get_text_osk(char *input, unsigned short *intext, unsigned short *desc)
{
	int done=0;
	unsigned short outtext[128] = { 0 }; // text after input

	SceUtilityOskData data;
	memset(&data, 0, sizeof(data));
	data.language = 2;			// key glyphs: 0-1=hiragana, 2+=western/whatever the other field says
	data.lines = 1;				// just one line
	data.unk_24 = 1;			// set to 1
	data.desc = desc;
	data.intext = intext;
	data.outtextlength = 128;	// sizeof(outtext) / sizeof(unsigned short)
	data.outtextlimit = 50;		// just allow 50 chars
	data.outtext = (unsigned short*)outtext;

	SceUtilityOskParams osk;
	memset(&osk, 0, sizeof(osk));
	osk.base.size = sizeof(osk);
	// dialog language: 0=Japanese, 1=English, 2=French, 3=Spanish, 4=German,
	// 5=Italian, 6=Dutch, 7=Portuguese, 8=Russian, 9=Korean, 10-11=Chinese, 12+=default
	osk.base.language = 1;
	osk.base.buttonSwap = 1;		// X button: 1
	osk.base.graphicsThread = 17;	// gfx thread pri
	osk.base.unknown = 19;			// unknown thread pri (?)
	osk.base.fontThread = 18;
	osk.base.soundThread = 16;
	osk.unk_48 = 1;
	osk.data = &data;

	int rc = sceUtilityOskInitStart(&osk);
	if (rc) return 0;

	while(!done) {
		int i,j=0;

		sceGuStart(GU_DIRECT,list);

		// clear screen
		sceGuClearColor(0xff554433);
		sceGuClearDepth(0);
		sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);

		sceGuFinish();
		sceGuSync(0,0);

		switch(sceUtilityOskGetStatus())
		{
			case PSP_UTILITY_DIALOG_INIT :
			break;
			case PSP_UTILITY_DIALOG_VISIBLE :
			sceUtilityOskUpdate(2); // 2 is taken from ps2dev.org recommendation
			break;
			case PSP_UTILITY_DIALOG_QUIT :
			sceUtilityOskShutdownStart();
			break;
			case PSP_UTILITY_DIALOG_FINISHED :
			done = 1;
			break;
			case PSP_UTILITY_DIALOG_NONE :
			default :
			break;
		}

		for(i = 0; data.outtext[i]; i++)
			if (data.outtext[i]!='\0' && data.outtext[i]!='\n' && data.outtext[i]!='\r')
			{
				input[j] = data.outtext[i];
				j++;
			}
		input[j] = 0;

		sceDisplayWaitVblankStart();
		sceGuSwapBuffers();
	}
	return 1;
}

/*
 * GUI support code
 *
 */

extern char *RequestFile (char *initialPath);

struct gui_menu {
	char *text;
	unsigned int flags;
	void *field1;
	void *field2;
	unsigned int enable;
};

struct gui_list {
	char *text;
	int index;
};

// gui_menu.flags
#define GUI_DIVIDER   0
#define GUI_TEXT      1
#define GUI_MENU      2
#define GUI_FUNCTION  3
#define GUI_SELECT    4
#define GUI_TOGGLE    5
#define GUI_INTEGER   6
#define GUI_FILE      7

#define GUI_CENTER 0x10000000
#define GUI_LEFT   0x20000000
#define GUI_RIGHT  0x30000000

// gui_menu.enable
#define GUI_DISABLED 0
#define GUI_ENABLED  1
#define GUI_SET_ME   0xFFFFFFFF

// misc
#define GUI_END_OF_MENU 0xFFFFFFFF
#define GUI_END_OF_LIST 0xFFFFFFFF

int psp_cpu_speed = 0;

int psp_use_tv = 0;

int psp_lcd_res = 0;
int psp_lcd_sync = 0;
int psp_lcd_detail = 0;

int psp_tv_cable = -1;
int psp_tv_res = 0;
int psp_tv_sync = 0;
int psp_tv_laced = 1;
int psp_tv_aspect = 0;
int psp_tv_detail = 0;
int psp_tv_cx = 0;
int psp_tv_cy = 0;

int psp_snd_upd = 0;
int psp_sfx_enabled = 1;
int psp_music_enabled = 1;

char *psp_iwad_file = 0;
char *psp_pwad_file1 = 0;
char *psp_pwad_file2 = 0;
char *psp_pwad_file3 = 0;
char *psp_pwad_file4 = 0;
char *psp_deh_file1 = 0;
char *psp_deh_file2 = 0;
char *psp_deh_file3 = 0;
char *psp_deh_file4 = 0;
int psp_game_nomonsters = 0;
int psp_game_respawn = 0;
int psp_game_fast = 0;
int psp_game_turbo = 0;
int psp_game_maponhu = 0;
int psp_game_rotatemap = 0;
int psp_game_deathmatch = 0;
int psp_game_altdeath = 0;
int psp_game_record = 0;
int psp_game_playdemo = 0;
int psp_game_forcedemo = 0;
int psp_game_timedemo = 0;
int psp_game_timer = 0;
int psp_game_avg = 0;
int psp_game_statcopy = 0;
int psp_game_version = 110;

int gui_menu_len(struct gui_menu *menu)
{
	int c = 0;
	while (menu[c].flags != GUI_END_OF_MENU)
		c++;
	return c;
}

int gui_list_len(struct gui_list *list)
{
	int c = 0;
	while (list[c].index != GUI_END_OF_LIST)
		c++;
	return c;
}

void do_gui(struct gui_menu *menu, char *exit_msg)
{
	SceCtrlData pad;
	int msy, mlen;
	int i, j, k;
	int csel = 0;

	pspDebugScreenClear();
	mlen = gui_menu_len(menu);
	msy = 17 - mlen;

	sceCtrlReadBufferPositive(&pad, 1);
	while (!(pad.Buttons & PSP_CTRL_CIRCLE))
	{
		if (pad.Buttons & PSP_CTRL_CROSS)
		{
			if (menu[csel].enable == GUI_ENABLED)
				switch (menu[csel].flags & 0x0FFFFFFF)
				{
					void (*fnptr)(void *);
					char temp[256];
					char *req;

					case GUI_MENU:
					while (pad.Buttons & PSP_CTRL_CROSS)
						sceCtrlReadBufferPositive(&pad, 1);
					do_gui((struct gui_menu *)menu[csel].field1, "Return to Prev Menu");
					pspDebugScreenClear();
					break;
					case GUI_FUNCTION:
					while (pad.Buttons & PSP_CTRL_CROSS)
						sceCtrlReadBufferPositive(&pad, 1);
					fnptr = menu[csel].field1;
					(*fnptr)(menu[csel].field2);
					pspDebugScreenClear();
					break;
					case GUI_TOGGLE:
					while (pad.Buttons & PSP_CTRL_CROSS)
						sceCtrlReadBufferPositive(&pad, 1);
					*(int *)menu[csel].field1 ^= 1;
					break;
					case GUI_SELECT:
					if (pad.Buttons & (PSP_CTRL_RIGHT | PSP_CTRL_DOWN))
					{
						// next selection
						while (pad.Buttons & (PSP_CTRL_RIGHT | PSP_CTRL_DOWN))
							sceCtrlReadBufferPositive(&pad, 1);
						j = gui_list_len((struct gui_list *)menu[csel].field1);
						k = *(int *)menu[csel].field2;
						k = (k == (j - 1)) ? 0 : k + 1;
						*(int *)menu[csel].field2 = k;
					}
					if (pad.Buttons & (PSP_CTRL_LEFT | PSP_CTRL_UP))
					{
						// previous selection
						while (pad.Buttons & (PSP_CTRL_LEFT | PSP_CTRL_UP))
							sceCtrlReadBufferPositive(&pad, 1);
						j = gui_list_len((struct gui_list *)menu[csel].field1);
						k = *(int *)menu[csel].field2;
						k = (k == 0) ? j - 1 : k - 1;
						*(int *)menu[csel].field2 = k;
					}
					break;
					case GUI_FILE:
					while (pad.Buttons & PSP_CTRL_CROSS)
						sceCtrlReadBufferPositive(&pad, 1);
					if (*(int *)menu[csel].field1)
						free(*(char **)menu[csel].field1);
					strcpy(temp, psp_home);
					strcat(temp, (char *)menu[csel].field2);
					strcat(temp, "/");
					req = RequestFile(temp);
					*(char **)menu[csel].field1 = req ? strdup(req) : 0;
					pspDebugScreenClear();
					break;
					case GUI_INTEGER:
					if (pad.Buttons & PSP_CTRL_RIGHT)
					{
						// +1
						while (pad.Buttons & PSP_CTRL_RIGHT)
							sceCtrlReadBufferPositive(&pad, 1);
						*(int *)menu[csel].field1 += 1;
					}
					if (pad.Buttons & PSP_CTRL_LEFT)
					{
						// -1
						while (pad.Buttons & PSP_CTRL_LEFT)
							sceCtrlReadBufferPositive(&pad, 1);
						*(int *)menu[csel].field1 -= 1;
					}
					if (pad.Buttons & PSP_CTRL_DOWN)
					{
						// +10
						while (pad.Buttons & PSP_CTRL_DOWN)
							sceCtrlReadBufferPositive(&pad, 1);
						*(int *)menu[csel].field1 += 10;
					}
					if (pad.Buttons & PSP_CTRL_UP)
					{
						// -10
						while (pad.Buttons & PSP_CTRL_UP)
							sceCtrlReadBufferPositive(&pad, 1);
						*(int *)menu[csel].field1 -= 10;
					}
					break;
				}
		}
		else
		{
			if (pad.Buttons & PSP_CTRL_UP)
			{
				while (pad.Buttons & PSP_CTRL_UP)
					sceCtrlReadBufferPositive(&pad, 1);
				csel = (csel == 0) ? mlen - 1 : csel - 1;
			}
			if (pad.Buttons & PSP_CTRL_DOWN)
			{
				while (pad.Buttons & PSP_CTRL_DOWN)
					sceCtrlReadBufferPositive(&pad, 1);
				csel = (csel == (mlen - 1)) ? 0 : csel + 1;
			}
		}

		pspDebugScreenSetTextColor(0xFFFFFF);
		sceDisplayWaitVblankStart();
		pspDebugScreenSetXY(0, 33);
		printf("                                                                    ");
		pspDebugScreenSetXY(2, 33);
		printf("X = ");
		switch (menu[csel].flags & 0x0FFFFFFF)
		{
			case GUI_MENU:
			printf("Enter Sub-Menu");
			break;
			case GUI_FUNCTION:
			printf("Do Function");
			break;
			case GUI_SELECT:
			printf("Hold to change Selection with D-Pad");
			break;
			case GUI_TOGGLE:
			printf("Toggle Flag");
			break;
			case GUI_INTEGER:
			printf("Hold to change Integer with D-Pad");
			break;
			case GUI_FILE:
			printf("Select File");
			break;
		}
		pspDebugScreenSetXY(62 - strlen(exit_msg), 33);
		printf("O = %s", exit_msg);

		for (i=0; i<mlen; i++)
		{
			char line[69];
			char temp[10];

			pspDebugScreenSetXY(0, msy + i * 2);
			printf("                                                                    ");
			if ((menu[i].flags & 0x0FFFFFFF) == GUI_DIVIDER)
				continue;
			if (menu[i].enable == GUI_ENABLED)
				pspDebugScreenSetTextColor((i==csel) ? 0xFFFFFF : 0xCCCCCC);
			else
				pspDebugScreenSetTextColor(0xAAAAAA);

			strcpy(line, menu[i].text);
			switch (menu[i].flags & 0x0FFFFFFF)
			{
				case GUI_SELECT:
				strcat(line, " : ");
				strcat(line, ((struct gui_list *)menu[i].field1)[*(int *)menu[i].field2].text);
				break;
				case GUI_TOGGLE:
				strcat(line, " : ");
				strcat(line, *(int *)menu[i].field1 ? "on" : "off");
				break;
				case GUI_INTEGER:
				strcat(line, " : ");
				sprintf(temp, "%d", *(int *)menu[i].field1);
				strcat(line, temp);
				break;
				case GUI_FILE:
				strcat(line, " : ");
				strcat(line, *(int *)menu[i].field1 ? *(char **)menu[i].field1 : "");
				break;
				case GUI_TEXT:
				if ((int)menu[i].field1)
					pspDebugScreenSetTextColor((int)menu[i].field1);
				if ((int)menu[i].field2)
					pspDebugScreenSetBackColor((int)menu[i].field2);
				break;
			}
			switch (menu[i].flags & 0xF0000000)
			{
				case GUI_CENTER:
				pspDebugScreenSetXY(34 - strlen(line) / 2, msy + i * 2);
				break;
				case GUI_LEFT:
				pspDebugScreenSetXY(1, msy + i * 2);
				break;
				case GUI_RIGHT:
				pspDebugScreenSetXY(67 - strlen(line), msy + i * 2);
				break;
			}
			printf("%s", line);
			pspDebugScreenSetBackColor(0x000000);
		}

		sceKernelDelayThread(20*1000);
		sceCtrlReadBufferPositive(&pad, 1);
		if (quit_requested)
		{
			sceKernelDelayThread(5*1000*1000);
			sceKernelExitGame();
		}
	}
	while (pad.Buttons & PSP_CTRL_CIRCLE)
		sceCtrlReadBufferPositive(&pad, 1);

	pspDebugScreenSetTextColor(0xFFFFFF);
}

void set_myargv(void);
void get_myargv(void);

void psp_load_defaults()
{
	int i;
	FILE *handle;
	char temp[256];

	strcpy(temp, psp_home);
	strcat(temp, "doom.set");
	handle = fopen (temp, "r");
	if (handle == NULL)
		return;

	for (i = 0 ; i < MAXARGVS; i++)
	{
		temp[0] = 0;
		fgets(temp, 255, handle);
		printf(" %d : %s", i, temp);
		if (temp[0] == 0)
			break;
		temp[strlen(temp) - 1] = 0;
		myargv[i] = strdup(temp);
	}
	myargc = i;

	fclose (handle);

	get_myargv();
}

void psp_load_settings(void *arg)
{
	int i;
	char *req;

	req = RequestFile(psp_home);

	pspDebugScreenClear();

	// free old argv entries
	if (myargc)
		for (i = 0 ; i < myargc; i++)
		{
			free(myargv[i]);
			myargv[i] = 0;
		}
	myargc = 0;

	if (req)
	{
		FILE *handle;
		char temp[256];

		printf("Attempting to load settings from %s\n\n", req);

		handle = fopen (req, "r");
		if (handle == NULL)
		{
			printf("Error! Couldn't open file %s\n\n", req);
			sceKernelDelayThread(2*1000*1000);
			return;
		}

		for (i = 0 ; i < MAXARGVS; i++)
		{
			temp[0] = 0;
			fgets(temp, 255, handle);
			printf(" %d : %s", i, temp);
			if (temp[0] == 0)
				break;
			temp[strlen(temp) - 1] = 0;
			myargv[i] = strdup(temp);
		}
		myargc = i;

		fclose (handle);

		get_myargv();

		printf("\nSettings loaded\n\n");
		sceKernelDelayThread(3*1000*1000);
	}
	else
	{
		printf("You need to enter a filename to load!\n\n");
		sceKernelDelayThread(2*1000*1000);
	}
}

void psp_save_settings(void *arg)
{
	int ok, i;
	char filename[64];
	unsigned short intext[128]  = { 'd', 'o', 'o', 'm', '.', 's', 'e', 't', 0 }; // text already in the edit box on start
	unsigned short desc[128]	= { 'E', 'n', 't', 'e', 'r', ' ', 'F', 'i', 'l', 'e', ' ', 'N', 'a', 'm', 'e', 0 }; // description

	SetupGu();

	ok = get_text_osk(filename, intext, desc);

	pspDebugScreenInit();
	pspDebugScreenSetBackColor(0x000000);
	pspDebugScreenSetTextColor(0xffffff);
	pspDebugScreenClear();

	if (ok)
	{
		FILE *handle;
		char temp[256];

		printf("Attempting to save settings to %s%s\n\n", psp_home, filename);

		strcpy(temp, psp_home);
		strcat(temp, filename);
		handle = fopen (temp, "wb");
		if (handle == NULL)
		{
			printf("Error! Couldn't open file %s\n\n", temp);
			sceKernelDelayThread(2*1000*1000);
			return;
		}

		set_myargv();
		for (i = 0 ; i < myargc; i++)
		{
			fwrite (myargv[i], 1, strlen(myargv[i]), handle);
			fwrite ("\n", 1, 1, handle);
		}

		fclose (handle);

		printf("Settings saved to %s\n\n", temp);
		sceKernelDelayThread(2*1000*1000);
	}
	else
	{
		printf("You need to enter a filename to save!\n\n");
		sceKernelDelayThread(2*1000*1000);
	}
}

static void drawLine(int inX0, int inY0, int inX1, int inY1, u32 inColor, u32* inDestination, int inWidth)
{
     int tempDY = inY1 - inY0;
     int tempDX = inX1 - inX0;
     int tempStepX, tempStepY;
     int inZ;

     if(tempDY < 0) {
          tempDY = -tempDY;  tempStepY = -inWidth;
     } else {
          tempStepY = inWidth;
     }

     if(tempDX < 0) {
          tempDX = -tempDX;  tempStepX = -1;
     } else {
          tempStepX = 1;
     }

     tempDY <<= 1;
     tempDX <<= 1;

     inY0 *= inWidth;
     inY1 *= inWidth;
     inDestination[inX0 + inY0] = inColor;
     if(tempDX > tempDY) {
          int tempFraction = tempDY - (tempDX >> 1);
          while(inX0 != inX1) {
               if(tempFraction >= 0) {
                    inY0 += tempStepY;
                    tempFraction -= tempDX;
               }
               inX0 += tempStepX;
               tempFraction += tempDY;
               if (!psp_tv_laced)
                    inDestination[inX0 + inY0] = inColor;
               else {
                    inZ = inY0 / inWidth;
                    if (inZ & 1)
                         inDestination[inX0 + (inZ>>1) * inWidth] = inColor;
                    else
                         inDestination[inX0 + ((inZ>>1) + 262) * inWidth] = inColor;
               }
          }
     } else {
          int tempFraction = tempDX - (tempDY >> 1);
          while(inY0 != inY1) {
               if(tempFraction >= 0) {
                    inX0 += tempStepX;
                    tempFraction -= tempDY;
               }
               inY0 += tempStepY;
               tempFraction += tempDX;
               if (!psp_tv_laced)
                    inDestination[inX0 + inY0] = inColor;
               else {
                    inZ = inY0 / inWidth;
                    if (inZ & 1)
                         inDestination[inX0 + (inZ>>1) * inWidth] = inColor;
                    else
                         inDestination[inX0 + ((inZ>>1) + 262) * inWidth] = inColor;
               }
          }
     }
}

void psp_tv_center(void *arg)
{
	SceCtrlData pad;
	int cx, cy, mx, my, h, w;

	if (psp_tv_cable > 0)
	{
		if (psp_tv_cable == 1)
			pspDveMgrSetVideoOut(2, 0x1d1, 720, 503, 1, 15, 0); // composite
		else
			if (psp_tv_laced)
				pspDveMgrSetVideoOut(0, 0x1d1, 720, 503, 1, 15, 0); // component interlaced
			else
				pspDveMgrSetVideoOut(0, 0x1d2, 720, 480, 1, 15, 0); // component progressive

		sceDisplaySetFrameBuf((void *)0x44000000, 768, PSP_DISPLAY_PIXEL_FORMAT_8888, 1);

		switch (psp_tv_res)
		{
			case 1:
			w = 704;
			h = 448;
			mx = 720 - w;
			my = 480 - h;
			break;
			case 2:
			w = 640;
			h = 400;
			mx = 720 - w;
			my = 480 - h;
			break;
			case 0:
			default:
			w = 720;
			h = 480;
			mx = 720 - w;
			my = 480 - h;
			break;
		}
		cx = psp_tv_cx > mx ? mx : psp_tv_cx;
		cy = psp_tv_cy > my ? my : psp_tv_cy;


		sceCtrlReadBufferPositive(&pad, 1);
		while (!(pad.Buttons & (PSP_CTRL_CIRCLE | PSP_CTRL_CROSS)))
		{
			if (pad.Buttons & PSP_CTRL_UP)
				cy = cy > 0 ? cy-1 : 0;
			if (pad.Buttons & PSP_CTRL_DOWN)
				cy = cy < my ? cy+1 : my;
			if (pad.Buttons & PSP_CTRL_LEFT)
				cx = cx > 0 ? cx-1 : 0;
			if (pad.Buttons & PSP_CTRL_RIGHT)
				cx = cx < mx ? cx+1 : mx;

			sceDisplayWaitVblankStart();
			memset((void *)0x44000000, 0, 503*768*4); // clear screen

			drawLine(cx, cy, cx+w-1, cy, 0xFFFFFF, (u32 *)0x44000000, 768);
			drawLine(cx+w-1, cy, cx+w-1, cy+h-1, 0xFFFFFF, (u32 *)0x44000000, 768);
			drawLine(cx+w-1, cy+h-1, cx, cy+h-1, 0xFFFFFF, (u32 *)0x44000000, 768);
			drawLine(cx, cy+h-1, cx, cy, 0xFFFFFF, (u32 *)0x44000000, 768);
			drawLine(cx, cy, cx+w-1, cy+h-1, 0xFFFFFF, (u32 *)0x44000000, 768);
			drawLine(cx, cy+h-1, cx+w-1, cy, 0xFFFFFF, (u32 *)0x44000000, 768);

			sceKernelDelayThread(100*1000);
			sceCtrlReadBufferPositive(&pad, 1);
		}
		while (pad.Buttons & (PSP_CTRL_CIRCLE | PSP_CTRL_CROSS))
			sceCtrlReadBufferPositive(&pad, 1);

		psp_tv_cx = cx;
		psp_tv_cy = cy;

		pspDebugScreenInit();
		pspDebugScreenSetBackColor(0x000000);
		pspDebugScreenSetTextColor(0xffffff);
	}
}

void psp_gui(void)
{
	struct gui_menu AboutLevel[] = {
		{ "Doom for the PSP", GUI_CENTER | GUI_TEXT, (void *)0xFFFFFF, (void *)0x1020FF, GUI_DISABLED },
		{ "by Chilly Willy", GUI_CENTER | GUI_TEXT, (void *)0xFFFFFF, (void *)0x1020FF, GUI_DISABLED },
		{ "", GUI_CENTER | GUI_DIVIDER, 0, 0, GUI_DISABLED },
		{ "based on ADoomPPC v1.7 by Jarmo Laakkonen", GUI_CENTER | GUI_TEXT, (void *)0x88FF88, 0, GUI_DISABLED },
		{ "based on ADoomPPC v1.3 by Joseph Fenton", GUI_CENTER | GUI_TEXT, (void *)0x88FF88, 0, GUI_DISABLED },
		{ "based on ADoom v1.2 by Peter McGavin", GUI_CENTER | GUI_TEXT, (void *)0x88FF88, 0, GUI_DISABLED },
		{ "", GUI_CENTER | GUI_DIVIDER, 0, 0, GUI_DISABLED },
		{ "Alternate MIDI Instruments by Zer0-X/o'Moses", GUI_CENTER | GUI_TEXT, (void *)0x8888FF, 0, GUI_DISABLED },
		{ "based on samples from Christian Buchner's GMPlay V1.3", GUI_CENTER | GUI_TEXT, (void *)0x8888FF, 0, GUI_DISABLED },
		{ "and the original MIDI Instruments by Joseph Fenton", GUI_CENTER | GUI_TEXT, (void *)0x8888FF, 0, GUI_DISABLED },
		{ "", GUI_CENTER | GUI_DIVIDER, 0, 0, GUI_DISABLED },
		{ "TV-out support lib thanks to Dark_AleX", GUI_CENTER | GUI_TEXT, (void *)0x010101, (void *)0xFFFFFF, GUI_DISABLED },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	struct gui_menu AdvLevel[] = {
		{ "Force Demo", GUI_CENTER | GUI_TOGGLE, &psp_game_forcedemo, 0, GUI_ENABLED },
		{ "Record", GUI_CENTER | GUI_INTEGER, &psp_game_record, 0, GUI_ENABLED },
		{ "Play Demo", GUI_CENTER | GUI_INTEGER, &psp_game_playdemo, 0, GUI_ENABLED },
		{ "Time Demo", GUI_CENTER | GUI_INTEGER, &psp_game_timedemo, 0, GUI_ENABLED },
		{ "Timed Game", GUI_CENTER | GUI_INTEGER, &psp_game_timer, 0, GUI_ENABLED },
		{ "A.V.G.", GUI_CENTER | GUI_TOGGLE, &psp_game_avg, 0, GUI_ENABLED },
		{ "Copy Stats", GUI_CENTER | GUI_TOGGLE, &psp_game_statcopy, 0, GUI_ENABLED },
		{ "Force Version", GUI_CENTER | GUI_INTEGER, &psp_game_version, 0, GUI_ENABLED },
		{ "Fast", GUI_CENTER | GUI_TOGGLE, &psp_game_fast, 0, GUI_ENABLED },
		{ "Turbo", GUI_CENTER | GUI_TOGGLE, &psp_game_turbo, 0, GUI_ENABLED },
		//{ "Warp to Level", GUI_CENTER | GUI_SELECT, &game_warp_list, &psp_game_warp, GUI_ENABLED },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	struct gui_menu GameLevel[] = {
		{ "No Monsters", GUI_CENTER | GUI_TOGGLE, &psp_game_nomonsters, 0, GUI_ENABLED },
		{ "Respawn", GUI_CENTER | GUI_TOGGLE, &psp_game_respawn, 0, GUI_ENABLED },
		{ "Map on HU", GUI_CENTER | GUI_TOGGLE, &psp_game_maponhu, 0, GUI_ENABLED },
		{ "Rotate Map", GUI_CENTER | GUI_TOGGLE, &psp_game_rotatemap, 0, GUI_ENABLED },
		{ "Deathmatch", GUI_CENTER | GUI_TOGGLE, &psp_game_deathmatch, 0, GUI_ENABLED },
		{ "Alt Deathmatch", GUI_CENTER | GUI_TOGGLE, &psp_game_altdeath, 0, GUI_ENABLED },
		{ "Main WAD", GUI_LEFT | GUI_FILE, &psp_iwad_file, "iwad", GUI_ENABLED },
		{ "Patch WAD", GUI_LEFT | GUI_FILE, &psp_pwad_file1, "pwad", GUI_ENABLED },
		{ "Patch WAD", GUI_LEFT | GUI_FILE, &psp_pwad_file2, "pwad", GUI_ENABLED },
		{ "Patch WAD", GUI_LEFT | GUI_FILE, &psp_pwad_file3, "pwad", GUI_ENABLED },
		{ "Patch WAD", GUI_LEFT | GUI_FILE, &psp_pwad_file4, "pwad", GUI_ENABLED },
		{ "DEH File", GUI_LEFT | GUI_FILE, &psp_deh_file1, "deh", GUI_ENABLED },
		{ "DEH File", GUI_LEFT | GUI_FILE, &psp_deh_file2, "deh", GUI_ENABLED },
		{ "DEH File", GUI_LEFT | GUI_FILE, &psp_deh_file3, "deh", GUI_ENABLED },
		{ "DEH File", GUI_LEFT | GUI_FILE, &psp_deh_file4, "deh", GUI_ENABLED },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	struct gui_list snd_upd_list[] = {
		{ "140 Hz", 0 },
		{ "70 Hz", 1 },
		{ "35 Hz", 2 },
		{ 0, GUI_END_OF_LIST }
	};

	struct gui_menu SoundLevel[] = {
		{ "Update Frequency", GUI_CENTER | GUI_SELECT, &snd_upd_list, &psp_snd_upd, GUI_ENABLED },
		{ "Sound Effects", GUI_CENTER | GUI_TOGGLE, &psp_sfx_enabled, 0, GUI_ENABLED },
		{ "Music", GUI_CENTER | GUI_TOGGLE, &psp_music_enabled, 0, GUI_SET_ME },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	struct gui_list tv_res_list[] = {
		{ "720x480", 0 },
		{ "704x448", 1 },
		{ "640x400", 2 },
		{ 0, GUI_END_OF_LIST }
	};

	struct gui_list tv_cable_list[] = {
		{ "None found", 0 },
		{ "Composite", 1 },
		{ "Component", 2 },
		{ 0, GUI_END_OF_LIST }
	};

	struct gui_list psp_detail_list[] = {
		{ "High", 0 },
		{ "Low", 1 },
		{ 0, GUI_END_OF_LIST }
	};

	struct gui_list psp_aspect_list[] = {
		{ "4:3", 0 },
		{ "16:9", 1 },
		{ 0, GUI_END_OF_LIST }
	};

	struct gui_menu TvLevel[] = {
		{ "Cable", GUI_CENTER | GUI_SELECT, &tv_cable_list, &psp_tv_cable, GUI_DISABLED },
		{ "Resolution", GUI_CENTER | GUI_SELECT, &tv_res_list, &psp_tv_res, GUI_ENABLED },
		{ "Sync to VBlank", GUI_CENTER | GUI_TOGGLE, &psp_tv_sync, 0, GUI_ENABLED },
		{ "Detail", GUI_CENTER | GUI_SELECT, &psp_detail_list, &psp_tv_detail, GUI_ENABLED },
		{ "Interlaced", GUI_CENTER | GUI_TOGGLE, &psp_tv_laced, 0, GUI_SET_ME },
		{ "Aspect Ratio", GUI_CENTER | GUI_SELECT, &psp_aspect_list, &psp_tv_aspect, GUI_ENABLED },
		{ "Center Screen", GUI_CENTER | GUI_FUNCTION, &psp_tv_center, 0, GUI_ENABLED },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	struct gui_list lcd_res_list[] = {
		{ "480x272", 0 },
		{ "368x272", 1 },
		{ "320x240", 2 },
		{ 0, GUI_END_OF_LIST }
	};

	struct gui_menu LcdLevel[] = {
		{ "Resolution", GUI_CENTER | GUI_SELECT, &lcd_res_list, &psp_lcd_res, GUI_ENABLED },
		{ "Sync to VBlank", GUI_CENTER | GUI_TOGGLE, &psp_lcd_sync, 0, GUI_ENABLED },
		{ "Detail", GUI_CENTER | GUI_SELECT, &psp_detail_list, &psp_lcd_detail, GUI_ENABLED },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	struct gui_list psp_display_list[] = {
		{ "Use LCD", 0 },
		{ "Use TV", 1 },
		{ 0, GUI_END_OF_LIST }
	};

	struct gui_menu VideoLevel[] = {
		{ "LCD Settings", GUI_CENTER | GUI_MENU, LcdLevel, 0, GUI_ENABLED },
		{ "TV Settings", GUI_CENTER | GUI_MENU, TvLevel, 0, GUI_SET_ME },
		{ "Display", GUI_CENTER | GUI_SELECT, &psp_display_list, &psp_use_tv, GUI_SET_ME },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	struct gui_list cpu_speed_list[] = {
		{ "Default", 0 },
		{ "133/66 MHz", 1 },
		{ "222/111 MHz", 2 },
		{ "266/133 MHz", 3 },
		{ "300/150 MHz", 4 },
		{ "333/166 MHz", 5 },
		{ 0, GUI_END_OF_LIST }
	};
	struct gui_menu CpuLevel[] = {
		{ "CPU Clock Frequency", GUI_CENTER | GUI_SELECT, &cpu_speed_list, &psp_cpu_speed, GUI_ENABLED },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	struct gui_menu TopLevel[] = {
		{ "Load Settings", GUI_CENTER | GUI_FUNCTION, &psp_load_settings, 0, GUI_ENABLED },
		{ "Save Settings", GUI_CENTER | GUI_FUNCTION, &psp_save_settings, 0, GUI_ENABLED },
		{ "CPU Settings", GUI_CENTER |GUI_MENU, CpuLevel, 0, GUI_ENABLED },
		{ "Video Settings", GUI_CENTER | GUI_MENU, VideoLevel, 0, GUI_ENABLED },
		{ "Sound Settings", GUI_CENTER | GUI_MENU, SoundLevel, 0, GUI_ENABLED },
		{ "Game Settings", GUI_CENTER | GUI_MENU, GameLevel, 0, GUI_ENABLED },
		{ "Advanced Settings", GUI_CENTER | GUI_MENU, AdvLevel, 0, GUI_ENABLED },
		{ "About", GUI_CENTER | GUI_MENU, AboutLevel, 0, GUI_ENABLED },
		{ 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu
	};

	FILE *temp;
	char str[256];

	// start by setting some of the enables that depend on certain variables
	VideoLevel[1].enable = (psp_tv_cable > 0) ? GUI_ENABLED : GUI_DISABLED;
	VideoLevel[2].enable = (psp_tv_cable > 0) ? GUI_ENABLED : GUI_DISABLED;
	TvLevel[4].enable = (psp_tv_cable == 2) ? GUI_ENABLED : GUI_DISABLED;
	psp_tv_laced = (psp_tv_cable == 1) ? 1 : 0; // force laced if composite cable
	sprintf(str,"%s%s",psp_home,"MIDI_Instruments");
	temp = fopen(str, "rb");
	psp_music_enabled = temp ? 1 : 0;
	SoundLevel[2].enable = temp ? GUI_ENABLED : GUI_DISABLED;
	fclose(temp);

	do_gui(TopLevel, "Start DOOM");
	set_myargv();
}

int main (int argc, char **argv)
{
    int i, p;

	pspDebugScreenInit();
	pspDebugScreenSetBackColor(0x000000);
	pspDebugScreenSetTextColor(0xffffff);
	sceCtrlSetSamplingCycle(0);
	sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);

	SetupCallbacks();

	// get launch directory name for our home
	strncpy(psp_home,argv[0],sizeof(psp_home)-1);
	psp_home[sizeof(psp_home)-1] = 0;
	char *str_ptr=strrchr(psp_home,'/');
	if (str_ptr){
		str_ptr++;
		*str_ptr = 0;
	}

	if (sceKernelDevkitVersion() >= 0x03070110)
		if (kuKernelGetModel() == PSP_MODEL_SLIM_AND_LITE)
		{
			char str[256];
			sprintf(str,"%s%s",psp_home,"dvemgr.prx");
			if (pspSdkLoadStartModule(str, PSP_MEMORY_PARTITION_KERNEL) >= 0)
				psp_tv_cable = pspDveMgrCheckVideoOut();
		}

	if ((myargv = malloc(sizeof(char *) * MAXARGVS)) == NULL)
	{
		printf("malloc(%d) failed", sizeof(char *) * MAXARGVS);
		sceKernelDelayThread(5*1000*1000);
		sceKernelExitGame();
	}
	memset (myargv, 0, sizeof(char *)*MAXARGVS);
	myargc = 0;

	psp_load_defaults();
	psp_gui();

	pspDebugScreenClear();
	printf ("DOOM v%d.%d for the PSP\n\n", VERS, REVS);
	printf ("Args passed to D_DoomMain() are:\n");
	for (i = 1 ; i < myargc; i++)
		printf (" %s", myargv[i]);
	printf ("\n\n");

/* The original fixed point code is faster on GCC */
#if !defined(__GNUC__)
	//SetFPMode ();  /* set FPU rounding mode to "trunc towards -infinity" */
#endif

	p = M_CheckParm ("-cpuMHz");
	if (p && p < myargc - 1)
	{
		i = atoi (myargv[p+1]);
		scePowerSetClockFrequency(i, i, i>>1);
	}
	i = scePowerGetCpuClockFrequency();
	printf("The current CPU speed is %d MHz\n\n", i);
	sceKernelDelayThread(1*1000*1000);

	p = M_CheckParm ("-forceversion");
	if (p && p < myargc - 1)
		VERSION = atoi (myargv[p+1]);

	D_DoomMain ();

	sceKernelDelayThread(5*1000*1000);
	sceKernelExitGame();
	return 0;
}


#ifndef __SASC
void main_cleanup(void)
{
}
#endif


void set_myargv(void)
{
	char temp[256];
	int i;

	// free old argv entries
	if (myargc)
		for (i = 0 ; i < myargc; i++)
		{
			free(myargv[i]);
			myargv[i] = 0;
		}

	myargv[0] = strdup("Doom");
	myargc = 1;

	if (psp_use_tv)
	{
		myargv[myargc] = strdup("-tv");
		myargc++;

		switch (psp_tv_res)
		{
			case 0:
			myargv[myargc] = strdup("-width");
			myargc++;
			myargv[myargc] = strdup("720");
			myargc++;
			myargv[myargc] = strdup("-height");
			myargc++;
			myargv[myargc] = strdup("480");
			myargc++;
			break;
			case 1:
			myargv[myargc] = strdup("-width");
			myargc++;
			myargv[myargc] = strdup("704");
			myargc++;
			myargv[myargc] = strdup("-height");
			myargc++;
			myargv[myargc] = strdup("448");
			myargc++;
			break;
			case 2:
			myargv[myargc] = strdup("-width");
			myargc++;
			myargv[myargc] = strdup("640");
			myargc++;
			myargv[myargc] = strdup("-height");
			myargc++;
			myargv[myargc] = strdup("400");
			myargc++;
			break;
		}

		if (psp_tv_sync)
		{
			myargv[myargc] = strdup("-vsync");
			myargc++;
		}

		if (psp_tv_laced)
		{
			myargv[myargc] = strdup("-laced");
			myargc++;
		}

		if (psp_tv_aspect)
		{
			myargv[myargc] = strdup("-16:9");
			myargc++;
		}

		if (psp_tv_detail)
		{
			myargv[myargc] = strdup("-lowdetail");
			myargc++;
		}

		myargv[myargc] = strdup("-tvcx");
		myargc++;
		sprintf(temp, "%d", psp_tv_cx);
		myargv[myargc] = strdup(temp);
		myargc++;
		myargv[myargc] = strdup("-tvcy");
		myargc++;
		sprintf(temp, "%d", psp_tv_cy);
		myargv[myargc] = strdup(temp);
		myargc++;
	}
	else
	{
		switch (psp_lcd_res)
		{
			case 0:
			myargv[myargc] = strdup("-width");
			myargc++;
			myargv[myargc] = strdup("480");
			myargc++;
			myargv[myargc] = strdup("-height");
			myargc++;
			myargv[myargc] = strdup("272");
			myargc++;
			break;
			case 1:
			myargv[myargc] = strdup("-width");
			myargc++;
			myargv[myargc] = strdup("368");
			myargc++;
			myargv[myargc] = strdup("-height");
			myargc++;
			myargv[myargc] = strdup("272");
			myargc++;
			break;
			case 2:
			myargv[myargc] = strdup("-width");
			myargc++;
			myargv[myargc] = strdup("320");
			myargc++;
			myargv[myargc] = strdup("-height");
			myargc++;
			myargv[myargc] = strdup("240");
			myargc++;
			break;
		}

		if (psp_lcd_sync)
		{
			myargv[myargc] = strdup("-vsync");
			myargc++;
		}

		if (psp_lcd_detail)
		{
			myargv[myargc] = strdup("-lowdetail");
			myargc++;
		}
	}

	if (!psp_sfx_enabled)
	{
		myargv[myargc] = strdup("-nosfx");
		myargc++;
	}

	if (psp_music_enabled)
	{
		myargv[myargc] = strdup("-music");
		myargc++;
	}

	switch (psp_snd_upd)
	{
		case 0:
		myargv[myargc] = strdup("-140Hz");
		myargc++;
		break;
		case 1:
		myargv[myargc] = strdup("-70Hz");
		myargc++;
		break;
	}

	if (psp_iwad_file)
	{
		myargv[myargc] = strdup("-iwad");
		myargc++;
		myargv[myargc] = strdup(psp_iwad_file);
		myargc++;
	}

	if (psp_pwad_file1 || psp_pwad_file2 || psp_pwad_file3 || psp_pwad_file4)
	{
		myargv[myargc] = strdup("-file");
		myargc++;
		if (psp_pwad_file1)
		{
			myargv[myargc] = strdup(psp_pwad_file1);
			myargc++;
		}
		if (psp_pwad_file2)
		{
			myargv[myargc] = strdup(psp_pwad_file2);
			myargc++;
		}
		if (psp_pwad_file3)
		{
			myargv[myargc] = strdup(psp_pwad_file3);
			myargc++;
		}
		if (psp_pwad_file4)
		{
			myargv[myargc] = strdup(psp_pwad_file4);
			myargc++;
		}
	}

	if (psp_deh_file1 || psp_deh_file2 || psp_deh_file3 || psp_deh_file4)
	{
		myargv[myargc] = strdup("-deh");
		myargc++;
		if (psp_deh_file1)
		{
			myargv[myargc] = strdup(psp_deh_file1);
			myargc++;
		}
		if (psp_deh_file2)
		{
			myargv[myargc] = strdup(psp_deh_file2);
			myargc++;
		}
		if (psp_deh_file3)
		{
			myargv[myargc] = strdup(psp_deh_file3);
			myargc++;
		}
		if (psp_deh_file4)
		{
			myargv[myargc] = strdup(psp_deh_file4);
			myargc++;
		}
	}

	if (psp_game_nomonsters)
	{
		myargv[myargc] = strdup("-nomonsters");
		myargc++;
	}

	if (psp_game_respawn)
	{
		myargv[myargc] = strdup("-respawn");
		myargc++;
	}

	if (psp_game_fast)
	{
		myargv[myargc] = strdup("-fast");
		myargc++;
	}

	if (psp_game_turbo)
	{
		myargv[myargc] = strdup("-turbo");
		myargc++;
	}

	if (psp_game_maponhu)
	{
		myargv[myargc] = strdup("-maponhu");
		myargc++;
	}

	if (psp_game_rotatemap)
	{
		myargv[myargc] = strdup("-rotatemap");
		myargc++;
	}

	if (psp_game_deathmatch)
	{
		myargv[myargc] = strdup("-deathmatch");
		myargc++;
	}

	if (psp_game_altdeath)
	{
		myargv[myargc] = strdup("-altdeath");
		myargc++;
	}

	if (psp_game_record)
	{
		myargv[myargc] = strdup("-record");
		myargc++;
		sprintf(temp, "demo%1d", psp_game_record);
		myargv[myargc] = strdup(temp);
		myargc++;
	}

	if (psp_game_playdemo)
	{
		myargv[myargc] = strdup("-playdemo");
		myargc++;
		sprintf(temp, "demo%1d", psp_game_playdemo);
		myargv[myargc] = strdup(temp);
		myargc++;
	}

	if (psp_game_forcedemo)
	{
		myargv[myargc] = strdup("-forcedemo");
		myargc++;
	}

	if (psp_game_timedemo)
	{
		myargv[myargc] = strdup("-timedemo");
		myargc++;
		sprintf(temp, "demo%1d", psp_game_timedemo);
		myargv[myargc] = strdup(temp);
		myargc++;
	}

	if (psp_game_timer)
	{
		myargv[myargc] = strdup("-timer");
		myargc++;
		sprintf(temp, "%2d", psp_game_timer);
		myargv[myargc] = strdup(temp);
		myargc++;
	}

	if (psp_game_avg)
	{
		myargv[myargc] = strdup("-avg");
		myargc++;
	}

	if (psp_game_statcopy)
	{
		myargv[myargc] = strdup("-statcopy");
		myargc++;
	}

	if (psp_game_version != 110)
	{
		myargv[myargc] = strdup("-forceversion");
		myargc++;
		sprintf(temp, "%3d", psp_game_version);
		myargv[myargc] = strdup(temp);
		myargc++;
	}

	if (psp_cpu_speed != 0)
	{
		myargv[myargc] = strdup("-cpuMHz");
		myargc++;
		switch (psp_cpu_speed)
		{
			case 1:
			myargv[myargc] = strdup("133");
			myargc++;
			break;
			case 2:
			myargv[myargc] = strdup("222");
			myargc++;
			break;
			case 3:
			myargv[myargc] = strdup("266");
			myargc++;
			break;
			case 4:
			myargv[myargc] = strdup("300");
			myargc++;
			break;
			case 5:
			myargv[myargc] = strdup("333");
			myargc++;
			break;
		}
	}
}

int first_argv(char *check)
{
    int		i;

    for (i=1; i<myargc; i++)
		if ( !strcasecmp(check, myargv[i]) )
		    return i;

    return 0;
}

void get_myargv(void)
{
	int i, j;

	psp_use_tv = 0;
	if (first_argv("-tv"))
	{
		psp_use_tv = 1;

		psp_tv_res = 0;
		i = first_argv("-width");
		if (i)
		{
			sscanf(myargv[i+1], "%d", &j);
			switch (j)
			{
				case 720:
				psp_tv_res = 0;
				break;
				case 704:
				psp_tv_res = 1;
				break;
				case 640:
				psp_tv_res = 2;
				break;
			}
		}

		psp_tv_sync = 0;
		if (first_argv("-vsync"))
			psp_tv_sync = 1;

		psp_tv_laced = 0;
		if (first_argv("-laced"))
			psp_tv_laced = 1;

		psp_tv_aspect = 0;
		if (first_argv("-16:9"))
			psp_tv_aspect = 1;

		psp_tv_detail = 0;
		if (first_argv("-lowdetail"))
			psp_tv_detail = 1;

		psp_tv_cx = 0;
		i = first_argv("-tvcx");
		if (i)
			sscanf(myargv[i+1], "%d", &psp_tv_cx);

		psp_tv_cy = 0;
		i = first_argv("-tvcy");
		if (i)
			sscanf(myargv[i+1], "%d", &psp_tv_cy);
	}
	else
	{
		psp_lcd_res = 0;
		i = first_argv("-width");
		if (i)
		{
			sscanf(myargv[i+1], "%d", &j);
			switch (j)
			{
				case 480:
				psp_lcd_res = 0;
				break;
				case 368:
				psp_lcd_res = 1;
				break;
				case 320:
				psp_lcd_res = 2;
				break;
			}
		}

		psp_lcd_sync = 0;
		if (first_argv("-vsync"))
			psp_lcd_sync = 1;

		psp_lcd_detail = 0;
		if (first_argv("-lowdetail"))
			psp_lcd_detail = 1;
	}

	psp_sfx_enabled = 1;
	if (first_argv("-nosfx"))
		psp_sfx_enabled = 0;

	psp_music_enabled = 0;
	if (first_argv("-music"))
		psp_music_enabled = 1;

	psp_snd_upd = 2;
	if (first_argv("-140Hz"))
		psp_snd_upd = 0;
	if (first_argv("-70Hz"))
		psp_snd_upd = 1;

	i = first_argv("-iwad");
	if (i)
		psp_iwad_file = strdup(myargv[i+1]);

	i = first_argv("-file");
	if (i)
	{
		psp_pwad_file1 = strdup(myargv[i+1]);
		if ((i+2 < myargc) && myargv[i+2][0] != '-')
		{
			psp_pwad_file2 = strdup(myargv[i+2]);
			if ((i+3 < myargc) && myargv[i+3][0] != '-')
			{
				psp_pwad_file3 = strdup(myargv[i+3]);
				if ((i+4 < myargc) && myargv[i+4][0] != '-')
					psp_pwad_file4 = strdup(myargv[i+4]);
			}
		}
	}

	i = first_argv("-deh");
	if (i)
	{
		psp_deh_file1 = strdup(myargv[i+1]);
		if ((i+2 < myargc) && myargv[i+2][0] != '-')
		{
			psp_deh_file2 = strdup(myargv[i+2]);
			if ((i+3 < myargc) && myargv[i+3][0] != '-')
			{
				psp_deh_file3 = strdup(myargv[i+3]);
				if ((i+4 < myargc) && myargv[i+4][0] != '-')
					psp_deh_file4 = strdup(myargv[i+1]);
			}
		}
	}

	psp_game_nomonsters = 0;
	if (first_argv("-nomonsters"))
		psp_game_nomonsters = 1;

	psp_game_respawn = 0;
	if (first_argv("-respawn"))
		psp_game_respawn = 1;

	psp_game_fast = 0;
	if (first_argv("-fast"))
		psp_game_fast = 1;

	psp_game_turbo = 0;
	if (first_argv("-turbo"))
		psp_game_turbo = 1;

	psp_game_maponhu = 0;
	if (first_argv("-maponhu"))
		psp_game_maponhu = 1;

	psp_game_rotatemap = 0;
	if (first_argv("-rotatemap"))
		psp_game_rotatemap = 1;

	psp_game_deathmatch = 0;
	if (first_argv("-deathmatch"))
		psp_game_deathmatch = 1;

	psp_game_altdeath = 0;
	if (first_argv("-altdeath"))
		psp_game_altdeath = 1;

	psp_game_record = 0;
	i = first_argv("-record");
	if (i)
		psp_game_record = (int)(myargv[i+1][4]) - 0x30;

	psp_game_playdemo = 0;
	i = first_argv("-playdemo");
	if (i)
		psp_game_playdemo = (int)(myargv[i+1][4]) - 0x30;

	psp_game_forcedemo = 0;
	if (first_argv("-forcedemo"))
		psp_game_forcedemo = 1;

	psp_game_timedemo = 0;
	i = first_argv("-timedemo");
	if (i)
		psp_game_timedemo = (int)(myargv[i+1][4]) - 0x30;

	psp_game_timer = 0;
	i = first_argv("-timer");
	if (i)
		sscanf(myargv[i+1], "%d", &psp_game_timer);

	psp_game_avg = 0;
	if (first_argv("-avg"))
		psp_game_avg = 1;

	psp_game_statcopy = 0;
	if (first_argv("-statcopy"))
		psp_game_statcopy = 1;

	psp_game_version = 110;
	i = first_argv("-forceversion");
	if (i)
		sscanf(myargv[i+1], "%d", &psp_game_version);

	psp_cpu_speed = 0;
	i = first_argv("-cpuMHz");
	if (i)
	{
		sscanf(myargv[i+1], "%d", &psp_cpu_speed);
		switch (psp_cpu_speed)
		{
			case 133:
			psp_cpu_speed = 1;
			break;
			case 222:
			psp_cpu_speed = 2;
			break;
			case 266:
			psp_cpu_speed = 3;
			break;
			case 300:
			psp_cpu_speed = 4;
			break;
			case 333:
			psp_cpu_speed = 5;
			break;
			default:
			psp_cpu_speed = 0;
		}
	}
}
