/* 
	
	コマンドのヘッダーファイル 
	
	3/12 shutdownコマンドの廃止 by is2os
	3/19 debugコマンドの使用変更 by is2os
*/
#include "bootpack.h"
#include <stdio.h>
#include <string.h>

void cmd_mem(struct CONSOLE *cons, int memtotal)
{
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	char s[60];
	cons_putstr0(cons, "\nMemory Data\n------------------\n");
	sprintf(s, "total   	%dMB\nfree		%dKB\n", memtotal / (1024 * 1024), memman_total(memman) / 1024);
	cons_putstr0(cons, s);
	sprintf(s, "lost size	%dMB\nlosts		%dMB\n\n", memman->lostsize, memman->losts);
	cons_putstr0(cons, s);
	return;
}

void cmd_cls(struct CONSOLE *cons)
{
	int x, y;
	struct SHEET *sheet = cons->sht;
	for (y = 28; y < 28 + 264; y++) {
		for (x = 8; x < 8 + 384; x++) {
			sheet->buf[x + y * sheet->bxsize] = COL8_000000;
		}
	}
	sheet_refresh(sheet, 8, 28, 8 + 384, 28 + 264);
	cons->cur_y = 28;
	return;
}

/* デバッグモードのON/OFFを切り替える */
void cmd_debug(struct CONSOLE *cons)
{
	if (taskctl->debug_mode == 1) {
		taskctl->debug_mode = 0;
		cons_putstr0(cons, "Debug mode OFF.\n");
	} else {
		taskctl->debug_mode = 1;
		cons_putstr0(cons, "Debug mode ON.\n");
	}
	return;
}

void cmd_dir(struct CONSOLE *cons, char *cmdline, int memtotal)
{
	struct FILEINFO *finfo = (struct FILEINFO *) (ADR_DISKIMG + 0x002600);
	int i, j;
	char s[128];

	cons_putstr0(cons, "\nFilename		   Size   ClustNo\n");
	cons_putstr0(cons, "---------------------------------\n");

	for (i = 0; i < 224; i++) {
		if (finfo[i].name[0] == 0x00) {
			break;
		}
		if (finfo[i].name[0] != 0xe5) {
			if ((finfo[i].type & 0x18) == 0) {
				sprintf(s, "filename.ext	%7d     %5d\n", finfo[i]. size, finfo[i]. clustno);
				for (j = 0; j < 8; j++) {
					s[j] = finfo[i].name[j];
				}
				s[ 9] = finfo[i].ext[0];
				s[10] = finfo[i].ext[1];
				s[11] = finfo[i].ext[2];
				cons_putstr0(cons, s);
			} else if ((finfo[i].type & 0x18) != 0) {
				strcpy(s, "foldname<DIR>\n");
				for (j = 0;j < 8;j++) {
					s[j] = finfo[i].name[j];
				}
				cons_putstr0(cons, s);
			}
		}
	}
	cons_newline(cons);
	return;
}

void cmd_exit(struct CONSOLE *cons, int *fat)
{
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct TASK *task = task_now();
	struct SHTCTL *shtctl = (struct SHTCTL *) *((int *) 0x0fe4);
	struct FIFO32 *fifo = (struct FIFO32 *) *((int *) 0x0fec);
	if (cons->sht != 0) {
		timer_cancel(cons->timer);
	}
	memman_free_4k(memman, (int) fat, 4 * 2880);
	io_cli();
	if (cons->sht != 0) {
		fifo32_put(fifo, cons->sht - shtctl->sheets0 + 768);	/* 768〜1023 */
	} else {
		fifo32_put(fifo, task - taskctl->tasks0 + 1024);	/* 1024〜2023 */
	}
	io_sti();
	for (;;) {
		task_sleep(task);	
	}
}

void cmd_start(struct CONSOLE *cons, char *cmdline, int memtotal)
{
	struct SHTCTL *shtctl = (struct SHTCTL *) *((int *) 0x0fe4);
	struct SHEET *sht = open_console(shtctl, memtotal);
	struct FIFO32 *fifo = &sht->task->fifo;
	int i;
	sheet_slide(sht, 32, 4);
	sheet_updown(sht, shtctl->top);
	/* コマンドラインに入力された文字列を、一文字ずつ新しいコンソールに入力 */
	for (i = 6; cmdline[i] != 0; i++) {
		fifo32_put(fifo, cmdline[i] + 256);
	}
	fifo32_put(fifo, 10 + 256);	/* Enter */
	cons_newline(cons);
	return;
}

void cmd_help(struct CONSOLE *cons)
{
	cons_putstr0(cons, "\n[mem] show memory data\n");
	cons_putstr0(cons, "[fls] you can see files\n");
	cons_putstr0(cons, "[cls] clear console screen\n");
	cons_putstr0(cons, "[exit] close console\n");
	cons_putstr0(cons, "[start] run program\n");
	cons_putstr0(cons, "[ncst] Non Console Start Task\n");
	cons_putstr0(cons, "[langmode] change a language\n");
	cons_putstr0(cons, "[writer] run easy text editor\n");
	cons_putstr0(cons, "[sysinfo] you can see system data\n");
	cons_putstr0(cons, "[shutdown] this computer shutdown\n");
	cons_putstr0(cons, "\n");
}

void cmd_ncst(struct CONSOLE *cons, char *cmdline, int memtotal)
{
	struct TASK *task = open_constask(0, memtotal);
	struct FIFO32 *fifo = &task->fifo;
	int i;
	/* コマンドラインに入力された文字列を、一文字ずつ新しいコンソールに入力 */
	for (i = 5; cmdline[i] != 0; i++) {
		fifo32_put(fifo, cmdline[i] + 256);
	}
	fifo32_put(fifo, 10 + 256);	/* Enter */
	cons_newline(cons);
	return;
}

void cmd_langmode(struct CONSOLE *cons, char *cmdline)
{
	struct TASK *task = task_now();
	unsigned char mode = cmdline[9] - '0';
	if (mode <= 2) {
		task->langmode = mode;
	} else {
		cons_putstr0(cons, "mode number error.\n");
	}
	cons_newline(cons);
	return;
}

int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct FILEINFO *finfo;
	char name[18], *p, *q, string_buf[18], start_buf[18];
	struct TASK *task = task_now();
	int i, segsiz, datsiz, esp, dathrb, appsiz;
	struct SHTCTL *shtctl;
	struct SHEET *sht;
	char base_command[60], size_set[20];
	int current;

	/* コマンドラインからファイル名を生成 */
	for (i = 0, current = 0; i < 13; i++, current++) {
		if (cmdline[i] <= ' ') {
			break;
		}
		name[i] = cmdline[i];
	}

	/* とりあえずファイル名の後ろを0にする */
	name[i] = 0; 

	/* ファイル名のコピー */
	strcpy(string_buf, (name+strlen(name)-4));
	if (strcmp(string_buf, ".jpg") == 0 || strcmp(string_buf, ".JPG") == 0 ||
	 	strcmp(string_buf, ".bmp") == 0 || strcmp(string_buf, ".BMP") == 0) { goto search_picture; }
	if (strcmp(string_buf, ".txt") == 0 || strcmp(string_buf, ".TXT") == 0) { goto search_text; }

	/* ファイルを探す */
	strcpy(start_buf, name);
	finfo = file_search(start_buf, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
	if (finfo == 0) {
		start_buf[i    ] = '.';
		start_buf[i + 1] = 'H';
		start_buf[i + 2] = 'R';
		start_buf[i + 3] = 'B';
		start_buf[i + 4] = 0;
		finfo = file_search(start_buf, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
	}
	if (finfo != 0) goto process_hrb_app;
	
search_text:
	strcpy(start_buf, name);
	finfo = file_search(start_buf, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
	if (finfo == 0) {
		/* TXTファイルを探す */
		start_buf[i    ] = '.';
		start_buf[i + 1] = 'T';
		start_buf[i + 2] = 'X';
		start_buf[i + 3] = 'T';
		start_buf[i + 4] = 0;
		finfo = file_search(start_buf, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
	}
	if (finfo != 0) goto show_textdata;

search_picture:
	strcpy(start_buf, name);
	finfo = file_search(start_buf, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
	if (finfo == 0) {
		/* JPEGファイルを探す */
		start_buf[i    ] = '.';
		start_buf[i + 1] = 'J';
		start_buf[i + 2] = 'P';
		start_buf[i + 3] = 'G';
		start_buf[i + 4] = 0;
		finfo = file_search(start_buf, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
		if (finfo != 0) goto show_picture;
		
		/* BMPファイルを探す */
		strcpy(start_buf, name);
		start_buf[i    ] = '.';
		start_buf[i + 1] = 'B';
		start_buf[i + 2] = 'M';
		start_buf[i + 3] = 'P';
		start_buf[i + 4] = 0;
		finfo = file_search(start_buf, (struct FILEINFO *) (ADR_DISKIMG + 0x002600), 224);
	}
	if (finfo != 0) goto show_picture;
	
	goto command_app_end;	

process_hrb_app:
	/* ファイルが見つかった場合 */
	appsiz = finfo->size;
	p = file_loadfile2(finfo->clustno, &appsiz, fat);
	if (appsiz >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {
		segsiz = *((int *) (p + 0x0000));
		esp    = *((int *) (p + 0x000c));
		datsiz = *((int *) (p + 0x0010));
		dathrb = *((int *) (p + 0x0014));
		q = (char *) memman_alloc_4k(memman, segsiz);
		task->ds_base = (int) q;
		set_segmdesc(task->ldt + 0, appsiz - 1, (int) p, AR_CODE32_ER + 0x60);
		set_segmdesc(task->ldt + 1, segsiz - 1, (int) q, AR_DATA32_RW + 0x60);
		for (i = 0; i < datsiz; i++) {
			q[esp + i] = p[dathrb + i];
		}
		start_app(0x1b, 0 * 8 + 4, esp, 1 * 8 + 4, &(task->tss.esp0));
		shtctl = (struct SHTCTL *) *((int *) 0x0fe4);
		for (i = 0; i < MAX_SHEETS; i++) {
			sht = &(shtctl->sheets0[i]);
			if ((sht->flags & 0x11) == 0x11 && sht->task == task) {
				/* アプリが開きっぱなしにした下じきを発見 */
				sheet_free(sht);	/* 閉じる */
			}
		}
		for (i = 0; i < 8; i++) {	/* クローズしてないファイルをクローズ */
			if (task->fhandle[i].buf != 0) {
				memman_free_4k(memman, (int) task->fhandle[i].buf, task->fhandle[i].size);
				task->fhandle[i].buf = 0;
			}
		}
		timer_cancelall(&task->fifo);
		memman_free_4k(memman, (int) q, segsiz);
		task->langbyte1 = 0;
	} else {
		cons_putstr0(cons, ".hrb file format error.\n");
	}
	memman_free_4k(memman, (int) p, appsiz);
	cons_newline(cons);
	return 1;

	/* 画像ファイルを表示する処理 */
show_picture:
	strcpy(base_command, "ncst gview ");
	strcat(base_command, start_buf);
	cmd_ncst(cons, base_command, memtest(0x00400000, 0xbfffffff));
	return 1;

	/* テキストデータを表示する処理 */
show_textdata:
	sprintf(size_set, " -w%d -h%d", (int)binfo->scrnx / 14, (int)binfo->scrny / 28);
	strcpy(base_command, "ncst tview ");
	strcat(base_command, start_buf);
	strcat(base_command, size_set);
	cmd_ncst(cons, base_command, memtest(0x00400000, 0xbfffffff));
	return 1;	

command_app_end:
	return 0;
}

