/*
 *  FCイメージリソースビューワ
 *
 *  2001/1/30  N.Honda
 *
 * このプログラムの内容は自由に再利用する事が出来ます。
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/bios.h>
#include <sys/libwwc.h>

typedef struct {
	char magic[2];
	char type[2];
	unsigned int size;
	short id;
	unsigned char width;            /* イメージの幅・キャラクタ単位   */
	unsigned char height;           /* イメージの高さ・キャラクタ単位 */
	unsigned char format;           /* フォーマット                   */
	unsigned char reserved;         /* 予約                           */
	unsigned char colorFrom;        /* 色開始番号                     */
	unsigned char colorSize;        /* パレットサイズ                 */
	unsigned char paletteFrom;      /* パレット開始番号               */ 
	unsigned char paletteNum;       /* パレット個数                   */
	unsigned char paletteCompress;  /* パレット圧縮フラグ             */
	unsigned char imageCompress;    /* イメージ圧縮フラグ             */
} FullColorImageResource;

#define MAX_SELECT 18

static char far *dir = "/rom0/";
unsigned int CharBuffer[512];

/* カラーでなければ終了させる */
int SysCheck(void)
{
	if (wwc_get_hardarch() == HARDARCH_WS) {
		text_screen_init();
		text_put_string(0, 1, "このプログラムはWonderSwanColor専用です");
		text_put_string(0, 2, "WonderSwanColorで実行してください");
		key_wait();
		return 1;
	}

	return 0;
}

/* ファイル選択 */
int SelectFile(char far *path) {
	int maxEntries;
	int count, cy, i, p;
	int index[MAX_SELECT];
	struct stat fstat;
	
	/* .frファイルをリストアップする */
	wwc_set_color_mode(COLOR_MODE_GRAYSCALE);
	text_screen_init();

	count = 0;
	maxEntries = nument(dir);
	for (i = 0; i < MAX_SELECT && i < maxEntries; i++) {
		if (getent(dir, i, &fstat) != E_FS_SUCCESS) continue;
		if (fstat.count == -1) continue;
		p = 0;
		while (fstat.name[p] != '\0') p++;
		if (p < 3) continue;
		if (fstat.name[p - 3] == '.' && fstat.name[p - 2] == 'f' && fstat.name[p - 1] == 'r') {
			index[count] = i;
			text_put_string(1, count++, fstat.name);
		}
	}
	if (count == 0) {
		text_put_string(0, 0, "no files");
	}

	/* ファイル選択 */
	cy = 0;
	do {
		text_put_char(0, cy, '>');
		switch(key_wait()) {
		case KEY_A:  /* ファイル決定 */
			getent(dir, index[cy], &fstat);
			sprintf(path, "/rom0/");
			for (i = 0; i < 16; i++) path[6 + i] = fstat.name[i];
			return 1;
			break;
		case KEY_START: /* プログラム終了 */
			return 0;
			break;
		case KEY_UP1:
			if (cy > 0) {
				text_put_char(0, cy, ' ');
				cy--;
			}
			break;
		case KEY_DOWN1:
			if (cy < count - 1) {
				text_put_char(0, cy, ' ');
				cy++;
			}
		}
	} while (1);
}

/* ファイルタイプ違い */
void IllegalType(void) {
	screen_fIll_char(SCREEN2, 0, 0, 24, 18, 0); 
	text_screen_init();
	text_put_string(0, 0, "ファイルの種類が違います");
}

/* 未サポートのフォーマット */
void NoSupport(void) {
	screen_fIll_char(SCREEN2, 0, 0, 24, 18, 0); 
	text_screen_init();
	text_put_string(0, 0, "サポートしていないフォーマットです");
}

/* イメージ表示メイン */
void DrawImage(FullColorImageResource far *header) {
	int width, height, paletteFrom, colorFrom, paletteNum, colorSize;
	int i, j;
	unsigned int far *pPalette;
	unsigned char far *pMap;
	unsigned char far *pImage;

	width = header->width;
	height= header->height;
	paletteFrom = header->paletteFrom;
	colorFrom = header->colorFrom;
	paletteNum = header->paletteNum;
	colorSize = header->colorSize;
	
	pPalette = (unsigned int far *)header;
	pPalette += sizeof(FullColorImageResource) / 2;
	pMap = (unsigned char far *)pPalette;
	pMap += paletteNum * colorSize * 2;
	pImage = pMap + width * height;
	
	display_control(DCM_SCR2);                      /* スクリーン2表示 */
	screen_fIll_char(SCREEN2, 0, 0, 28, 18, 0x00);  /* クリア */

	/* パレットの設定 */
	for (i = paletteFrom; i < paletteFrom + paletteNum; i++) {
		for (j = colorFrom ; j < colorFrom + colorSize; j++) {
			wwc_palette_set_color(i, j, *pPalette++);	
		}
	}

	/* フォントデータの設定 */
 	wwc_font_set_colordata(0, width * height, (void far *)pImage);

	for (i = 0; i < width * height; i++) {
		CharBuffer[i] = (*pMap++ << 9) | i;
	}
	screen_set_char(SCREEN2, 0, 0, width, height, (void far *)CharBuffer);

}

/* イメージ表示 */
void Draw(char far *path) {
	FullColorImageResource far *header;
	
	if ((header = mmap(path)) == NULL) return;

	/* リソースタイプチェック */
	if (!(header->magic[0] == 'F' && header->magic[1] == 'R' && header->type[0] == 'F' && header->type[1] == 'C')) {
		IllegalType();
		return;
	}

	switch (header->format) {
	case 0:
		wwc_set_color_mode(COLOR_MODE_16PACKED);        /* モードの設定 */
		DrawImage(header);
		break;
	case 1:
		wwc_set_color_mode(COLOR_MODE_16COLOR);        /* モードの設定 */
		DrawImage(header);
		break;
	case 2:
	case 3:
	case 4:
		NoSupport();
		break;
	default:
		return;
	}
}

/* メインルーチン */
int main(void)
{
	static char path[MAXPATHLEN];
	
	if (SysCheck()) return -1;

	while (1) {
		if (!SelectFile(path)) {
			break;
		}
		Draw(path);
		if (key_wait() == KEY_START) break;
	}

	/* カラーモードをグレースケールモードにする  */
	wwc_set_color_mode(COLOR_MODE_GRAYSCALE);
	return 0;
}
