#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <egb.h>
#include    <mos.h>
#include    <snd.h>
#include    <msdos.cf>
#include    "graphic.h"

#define	TRUE	1
#define	FALSE	0
#define	ERR	(-1)

char	*xopen(char *file);
void	xclose(char *buf);

int	page_ofs=0;
char	work[EgbWorkSize];
char	mwork[MosWorkSize];
char	swork[16384];
int	col_cnv[]={
	0x00000000,0x11111111,0x22222222,0x33333333,
	0x44444444,0x55555555,0x66666666,0x77777777,
	0x88888888,0x99999999,0xAAAAAAAA,0xBBBBBBBB,
	0xCCCCCCCC,0xDDDDDDDD,0xEEEEEEEE,0xFFFFFFFF };

static int	mode_flg=FALSE;
static int	now_mos_type=0;
static char	mosptn[][66]={
	{ 2, 16,
	0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 
	0x30, 0x00, 0x58, 0x00, 0x3C, 0x00, 0x5E, 0x00, 
	0x2F, 0x00, 0x5F, 0x80, 0x2E, 0x00, 0x7C, 0x00, 
	0x66, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 
	0x7F, 0xFF, 0x3F, 0xFF, 0x5F, 0xFF, 0x6F, 0xFF, 
	0x37, 0xFF, 0x5B, 0xFF, 0x3D, 0xFF, 0x5E, 0xFF, 
	0x2F, 0x7F, 0x5F, 0xBF, 0x2E, 0x7F, 0x7D, 0xFF, 
	0x66, 0xFF, 0x16, 0xFF, 0x7B, 0x7F, 0xF8, 0x7F },
	{ 2, 16,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 
	0x05, 0x40, 0x05, 0x50, 0x15, 0x50, 0x15, 0x50, 
	0x1F, 0xF0, 0x1F, 0xF0, 0x1F, 0xF0, 0x0F, 0xF0, 
	0x07, 0xE0, 0x03, 0xC0, 0x00, 0x00, 0x00, 0x00,
	0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0xBF, 0xF5, 0x5F, 
	0xF5, 0x4F, 0xE5, 0x57, 0xD5, 0x57, 0xD5, 0x57, 
	0xDF, 0xF7, 0xDF, 0xF7, 0xDF, 0xF7, 0xEF, 0xF7, 
	0xF7, 0xEF, 0xFB, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF },
	{ 2, 16,
	0x00, 0x00, 0x2F, 0xF4, 0x2F, 0xF4, 0x2F, 0xF4, 
	0x37, 0xEC, 0x39, 0x9C, 0x3C, 0x3C, 0x3E, 0x7C, 
	0x3E, 0x7C, 0x3D, 0xBC, 0x3B, 0xDC, 0x36, 0x6C, 
	0x2C, 0x34, 0x28, 0x14, 0x20, 0x04, 0x00, 0x00,
	0x00, 0x00, 0xAF, 0xF5, 0xAF, 0xF5, 0xAF, 0xF5, 
	0xB7, 0xED, 0xB9, 0x9D, 0xBC, 0x3D, 0xBE, 0x7D, 
	0xBE, 0x7D, 0xBD, 0xBD, 0xBB, 0xDD, 0xB6, 0x6D, 
	0xAC, 0x35, 0xA8, 0x15, 0xA0, 0x05, 0x00, 0x00 },
	{ 2, 16,
	0x03, 0x00, 0x03, 0x80, 0x02, 0xC0, 0x02, 0x40, 
	0x02, 0x40, 0x02, 0x00, 0x0E, 0x00, 0x1E, 0x00, 
	0x1E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x6A, 0xE0, 
	0x4A, 0xA0, 0x6A, 0xE0, 0x4A, 0x80, 0x6E, 0x80,
	0xFB, 0x7F, 0xFB, 0xBF, 0xFA, 0xDF, 0xFA, 0x5F, 
	0xFA, 0x5F, 0xE2, 0x9F, 0xCE, 0xFF, 0xDE, 0xFF, 
	0xDE, 0xFF, 0xCD, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
	{ 2, 16,
	0x00, 0x00, 0x07, 0x00, 0x08, 0x80, 0x0A, 0x40, 
	0x01, 0x40, 0x05, 0x40, 0x02, 0x40, 0x08, 0x40, 
	0x04, 0x80, 0x07, 0x00, 0x00, 0x00, 0x75, 0x60, 
	0x47, 0x50, 0x77, 0x50, 0x17, 0x50, 0x75, 0x60,
	0xF0, 0x7F, 0xF7, 0x7F, 0xE8, 0xBF, 0xEA, 0x5F, 
	0xE1, 0x5F, 0xE5, 0x5F, 0xE2, 0x5F, 0xE8, 0x5F, 
	0xF4, 0xBF, 0xF7, 0x7F, 0xF0, 0x7F, 0xFF, 0xFF, 
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } };

void	DSP_writePage(int pg)
{
    int     x,y,sw;

    MOS_rdpos(&sw,&x,&y);
    MOS_disp(FALSE);
    MOS_writePage(pg);
    MOS_horizon(0,632);
    MOS_vertical(0,464);
    DSP_mos(now_mos_type);
    MOS_setpos(x,y);
    MOS_disp(TRUE);

    EGB_writePage(work,pg);
    page_ofs = (pg == 0 ? 0:0x40000);
}

void	DSP_mos(int no)
{
    MOS_type(1,0,0,mosptn[no]);
    now_mos_type = no;
}

BLOCK	*DSP_push_vram(int x1,int y1,int x2,int y2)
{
    register BLOCK *para;
    int     n;

    n = ((x2 - x1 + 8) / 8 * 4) * (y2 - y1 + 1) + 16;	/* 4 Bit Pix */

    if ( (para = (BLOCK *)malloc(n)) == NULL )
	return NULL;

    para->ptn = para->img;
    para->sel = getds();
    para->x1 = x1;
    para->y1 = y1;
    para->x2 = x2;
    para->y2 = y2;
    EGB_getBlock(work,(char *)para);
    return para;
}

void	DSP_pop_vram(BLOCK *para)
{
    if ( para == NULL )
	return;
    EGB_putBlock(work,0,(char *)para);
    free(para);
}

void	DSP_putptn(char *ptn,int x,int y,int col,int md)
{
    BLOCK para;

    para.ptn = ptn;
    para.sel = getds();
    para.x1 = x;
    para.y1 = y;
    para.x2 = x + 7;
    para.y2 = y + 15;
    EGB_color(work,0,col);
    EGB_writeMode(work,md);
    EGB_putBlockColor(work,0,(char *)(&para));
    EGB_writeMode(work,0);
}

void	DSP_msg(char *str,int x,int y,int font,int forcol,int bakcol)
{
    struct {
	short int	x,y;
	short int	len;
	char		str[120];
    } msg;

    msg.x = x;
    msg.y = y;
    msg.len = strlen(str);
    strcpy(msg.str,str);

    EGB_fontStyle(work,font);
    EGB_color(work,0,forcol);
    EGB_color(work,1,bakcol);
    EGB_sjisString(work,(char *)&msg);
}

void	DSP_box(int x1,int y1,int x2,int y2,
		int forcol,int boxcol)
{
    struct {
	short int	x1,y1,x2,y2;
    } line;
    struct {
	short int	count;
	short int	x1,y1,x2,y2,x3,y3,x4,y4;
    } connect;

    line.x1 = x1+1;
    line.y1 = y1+1;
    line.x2 = x2-1;
    line.y2 = y2-1;
    EGB_paintMode(work,0x020);
    EGB_color(work,2,boxcol);
    EGB_rectangle(work,(char *)&line);

    connect.count = 4;
    connect.x1 = x1;
    connect.y1 = y2-1;
    connect.x2 = x1;
    connect.y2 = y1+1;
    connect.x3 = x1+1;
    connect.y3 = y1;
    connect.x4 = x2-1;
    connect.y4 = y1;
    EGB_paintMode(work,0x002);
    EGB_color(work,0,forcol);
    EGB_connect(work,(char *)&connect);

    connect.x1 = x2;
    connect.y1 = y1+1;
    connect.x2 = x2;
    connect.y2 = y2-1;
    connect.x3 = x2-1;
    connect.y3 = y2;
    connect.x4 = x1+1;
    connect.y4 = y2;
    EGB_connect(work,(char *)&connect);
}

void	DSP_line(int x1,int y1,int x2,int y2,int col,int mod)
{
    struct {
	short int	x1,y1,x2,y2;
    } line;

    line.x1 = x1;
    line.y1 = y1;
    line.x2 = x2;
    line.y2 = y2;
    EGB_paintMode(work,0x002);
    EGB_color(work,0,col);
    EGB_writeMode(work,mod);
    EGB_rectangle(work,(char *)&line);
    EGB_writeMode(work,0);
}

void	DSP_xline(int x1,int y1,int x2,int y2,int col,int mod)
{
    struct {
	short int	x1,y1,x2,y2;
    } line;

    line.x1 = x1;
    line.y1 = y1;
    line.x2 = x2;
    line.y2 = y2;
    EGB_paintMode(work,0x022);
    EGB_color(work,0,col);
    EGB_color(work,2,col);
    EGB_writeMode(work,mod);
    EGB_rectangle(work,(char *)&line);
    EGB_writeMode(work,0);
}

void	DSP_opline(x1,y1,x2,y2)
{
    int     i;
    int     ix1,iy1,ix2,iy2;
    int     sx1,sy1,sx2,sy2;

    ix1 = (x1 + x2) / 2 - 16;
    ix2 = ix1 + 31;
    iy1 = (y1 + y2) / 2 - 16;
    iy2 = iy1 + 31;

    sx1 = (ix1 - x1) / 5;
    sy1 = (iy1 - y1) / 5;
    sx2 = (x2 - ix2) / 5;
    sy2 = (y2 - iy2) / 5;

    for ( i = 5 ; i >= 0 ; i-- ) {
	DSP_line(ix1,iy1,ix2,iy2,15,4);
	EGB_displayStart(work,1,0,0);
	DSP_line(ix1,iy1,ix2,iy2,15,4);
	ix1 -= sx1;
	iy1 -= sy1;
	ix2 += sx2;
	iy2 += sy2;
    }
}

void	DSP_rbox(int x1,int y1,int x2,int y2,
		int forcol,int bakcol,int boxcol)
{
    struct {
	short int	x1,y1,x2,y2;
    } line;
    struct {
	short int	count;
	short int	x1,y1,x2,y2,x3,y3;
    } connect;

    DSP_opline(x1,y1,x2,y2);

    line.x1 = x1;
    line.y1 = y1;
    line.x2 = x2;
    line.y2 = y2;
    EGB_paintMode(work,0x022);
    EGB_color(work,0,forcol);
    EGB_color(work,2,boxcol);
    EGB_rectangle(work,(char *)&line);

    connect.count = 3;
    connect.x1 = x1+1;
    connect.y1 = y2-1;
    connect.x2 = x1+1;
    connect.y2 = y1+1;
    connect.x3 = x2-1;
    connect.y3 = y1+1;
    EGB_connect(work,(char *)&connect);

    connect.x1 = x1;
    connect.y1 = y2;
    connect.x2 = x2;
    connect.y2 = y2;
    connect.x3 = x2;
    connect.y3 = y1;
/*    EGB_color(work,0,bakcol); */
    EGB_connect(work,(char *)&connect);
    connect.x1 = x1+1;
    connect.y1 = y2-1;
    connect.x2 = x2-1;
    connect.y2 = y2-1;
    connect.x3 = x2-1;
    connect.y3 = y1+1;
    EGB_connect(work,(char *)&connect);
}

static struct _PLT {
	char	b,r,g;
    } plt_tbl[16]={
	{ 0x20,0x20,0x20 },{ 0x70,0x00,0x80 },
	{ 0x90,0xD0,0x80 },{ 0x80,0x70,0x60 },
	{ 0x50,0x00,0x70 },{ 0x50,0x00,0x40 },
	{ 0xF0,0x00,0xF0 },{ 0x80,0x80,0x80 },
	{ 0x70,0xC0,0x40 },{ 0x50,0x00,0x50 },
	{ 0x70,0xC0,0x60 },{ 0x50,0x50,0x30 },
	{ 0x10,0x10,0x40 },{ 0x70,0x00,0x60 },
	{ 0xC0,0x60,0xC0 },{ 0xF0,0xF0,0xF0 }
    };

void	DSP_palette(void)
{
    struct {
	int	cnt;
	int	col;
	char	b,r,g;
	char	btm;
    } para;
    int     i;

    for ( i = 0 ; i < 16 ; i++ ) {
	para.cnt = 1;
	para.col = i;
	para.b = plt_tbl[i].b;
	para.r = plt_tbl[i].r;
	para.g = plt_tbl[i].g;
	para.btm = 0;
        EGB_palette(work,0,(char *)&para);
    }
}

void	DSP_one_pal(int c,int r,int g,int b)
{
    struct {
	int	cnt;
	int	col;
	char	b,r,g;
	char	btm;
    } para;

    para.cnt = 1;
    para.col = c;
    para.b = b << 4;
    para.r = r << 4;
    para.g = g << 4;
    para.btm = 0;
    EGB_writePage(work,1);
    EGB_palette(work,0,(char *)&para);
    EGB_writePage(work,0);
}

void	DSP_init(void)
{
    FILE    *fp;

    SND_init(swork);
    SND_elevol_mute(0xB3);

    EGB_init(work,EgbWorkSize);
    EGB_resolution(work,0,3);
    EGB_resolution(work,1,3);
    EGB_displayPage(work,1,3);

    MOS_start(mwork,MosWorkSize);
    MOS_resolution(0,3);
    MOS_resolution(1,3);
    MOS_writePage(0);
    MOS_horizon(0,632);
    MOS_vertical(0,470);
    MOS_type(1,0,0,mosptn[0]);

    if ( (fp = fopen("PLAT.TBL","rb")) != NULL ) {
	fread(plt_tbl,sizeof(struct _PLT),16,fp);
	fclose(fp);
    }

    EGB_writePage(work,0);
    DSP_palette();

    ctblset(col_cnv[15],0);

    wrtstr("ちょっと待ってね・・・・・",
	page_ofs,200/2+220*512,col_cnv[15],col_cnv[0],16);
}
void	DSP_reinit(void)
{
    EGB_init(work,EgbWorkSize);
    EGB_resolution(work,0,3);
    EGB_resolution(work,1,3);
    EGB_displayPage(work,1,3);
    EGB_writePage(work,0);
    DSP_palette();
}
void	DSP_end(void)
{
    MOS_end();
    SND_elevol_mute(0x00);
    SND_end();
}
void	DSP_mode_chk(int len)
{
    if ( len == 16 && mode_flg == FALSE ) {
        EGB_resolution(work,1,10);
	EGB_writePage(work,0);
	DSP_palette();
	EGB_writePage(work,1);
	EGB_displayStart(work,0,160,120);
	mode_flg = TRUE;
    }
    if ( len != 16 && mode_flg != FALSE ) {
        EGB_resolution(work,1,3);
	EGB_writePage(work,0);
	DSP_palette();
	mode_flg = FALSE;
    }
    EGB_writePage(work,1);
    EGB_color(work,1,0);
    EGB_clearScreen(work);
    EGB_writePage(work,0);
}
void	DSP_push_tiff(char *file)
{
    int	    l,n;
    int     x,y,len;
    BLOCK   para;
    char    *buf;
    struct _TIF {
	short	tf_tag;
	short	tf_type;
	int	tf_len;
	int	tf_data;
    } *ifd;

    if ( (buf = xopen(file)) == NULL )
	return;

    if ( buf[0] != 0x49 || buf[1] != 0x49 || buf[2] != 0x2A )
	goto ENDOF;

    x = y = len = 0;
    n = WORD(buf + DWORD(buf+4));
    ifd = (struct _TIF *)(buf + DWORD(buf+4) + 2);

    while ( n-- > 0) {
	if ( ifd->tf_tag == 0 )
	    break;
	switch(ifd->tf_tag){
	case 0x0100: x = ifd->tf_data; break;
	case 0x0101: y = ifd->tf_data; break;
	case 0x0102: len = ifd->tf_data; break;
	case 0x0111: l = ifd->tf_data; break;
	}
	ifd++;
    }

    para.ptn = buf + l;
    para.sel = getds();
    para.x1 = 0;
    para.y1 = 0;
    para.x2 = x-1;
    para.y2 = y-1;

    DSP_mode_chk(len);
    EGB_writePage(work,1);
    EGB_putBlock(work,0,(char *)&para);
    EGB_writePage(work,0);

ENDOF:
    xclose(buf);
}

void	DSP_pop_tiff(void)
{
    EGB_writePage(work,1);
    EGB_color(work,1,0);
    EGB_clearScreen(work);
    if ( mode_flg != FALSE )
        EGB_resolution(work,1,3);
    EGB_writePage(work,0);
    DSP_palette();
    EGB_displayPage(work,1,3);
    mode_flg = FALSE;
}

void	DSP_anime(char *file)
{
    char    *buf;

    if ( (buf = xopen(file)) == NULL )
	return;

    DSP_mode_chk(*buf);
    ANI_decode(0x40000,buf+1);
    xclose(buf);
}

#include    "event.h"

#define	PLT_X	280
#define	PLT_Y	320
#define	PLT_BX	(PLT_X+324)
#define	PLT_BY	(PLT_Y+108)

void	PLT_col();

static int plt_event=FALSE;

void	PLT_event(register EVENT *ep,int x,int y,int sw)
{
    switch(ep->now) {
    case EVT_CLIP_MOS:
	EVT_clip_on(ep);
    case EVT_ON_MOS:
	DSP_mos(1);
	break;

    case EVT_SELECT_MOS:
	EVT_clip_off(ep);
	DSP_mos(0);
	if ( ep->level == 516 ) {
	    plt_event = ERR;
	    break;
	}
	switch(ep->no){
	case 0: plt_tbl[ep->level-500].b+=16; break;
	case 1: plt_tbl[ep->level-500].b-=16; break;
	case 2: plt_tbl[ep->level-500].r+=16; break;
	case 3: plt_tbl[ep->level-500].r-=16; break;
	case 4: plt_tbl[ep->level-500].g+=16; break;
	case 5: plt_tbl[ep->level-500].g-=16; break;
	}
	PLT_col(ep->level-500);
	EGB_writePage(work,0);
	DSP_palette();
	break;

    case EVT_DOLACK_MOS:
	ep->now = EVT_NON;
    case EVT_MOVE_MOS:
	EVT_clip_off(ep);
    case EVT_OFF_MOS:
	DSP_mos(0);
	break;
    }
}

void	PLT_col(int col)
{
    int    x,y,c;
    char   tmp[40];

    MOS_disp(FALSE);

    x = PLT_X + (col % 8) * 40 + 8;
    y = PLT_Y + (col / 8) * 50 + 18;
    c = (col == 8 ? 0 : col);

    sprintf(tmp,"\x1B\x87%2d\x1B\x87",col);
    DSP_string(tmp,x,y+2,c,8);
    sprintf(tmp,"<%02d>",plt_tbl[col].b>>4);
    DSP_string(tmp,x,y+10,c,8);
    sprintf(tmp,"<%02d>",plt_tbl[col].r>>4);
    DSP_string(tmp,x,y+18,c,8);
    sprintf(tmp,"<%02d>",plt_tbl[col].g>>4);
    DSP_string(tmp,x,y+26,c,8);

    EVT_level_free(500+col);
    EVT_set_node(x,y+10,x+7,y+17,500+col,PLT_event,0);
    EVT_set_node(x+24,y+10,x+31,y+17,500+col,PLT_event,1);

    EVT_set_node(x,y+18,x+7,y+25,500+col,PLT_event,2);
    EVT_set_node(x+24,y+18,x+31,y+25,500+col,PLT_event,3);

    EVT_set_node(x,y+26,x+7,y+33,500+col,PLT_event,4);
    EVT_set_node(x+24,y+26,x+31,y+33,500+col,PLT_event,5);

    MOS_disp(TRUE);
}

void	PLT_set(void)
{
    int     i;
    BLOCK   *save;
    FILE    *fp;

    MOS_disp(FALSE);
    save = DSP_push_vram(PLT_X,PLT_Y,PLT_BX,PLT_BY);
    DSP_box(PLT_X,PLT_Y,PLT_BX,PLT_BY,7,8);

    EVT_sw(PLT_X+2,PLT_Y+2,"END",15,8,516,PLT_event,0);

    for ( i = 0 ; i < 16 ; i++ )
        PLT_col(i);

    for ( plt_event = FALSE ; plt_event == FALSE ; )
	EVT_loop(500);

    for ( i = 0 ; i <= 16 ; i++ )
        EVT_level_free(500+i);

    MOS_disp(FALSE);
    DSP_pop_vram(save);

    if ( (fp = fopen("PLAT.TBL","wb")) != NULL ) {
	fwrite(plt_tbl,sizeof(struct _PLT),16,fp);
	fclose(fp);
    }
}

void	DSP_super(char *str)
{
    struct {
	int	cnt;
	int	col;
	char	b,r,g;
	char	btm;
    } para;
    int     i;
    static int ofs_y=0;

    EGB_writePage(work,1);
    page_ofs = 0x40000;

    if ( str == NULL ) {
	para.cnt = 1;
	para.col = 15;
	para.btm = 0;
	for ( i = 255 ; i >= 0 ; i -= 8 ) {
	    para.b = para.r = para.g = i & 0xF0;
            EGB_palette(work,0,(char *)&para);
	    EGB_displayStart(work,1,0,ofs_y);
	}
	EGB_color(work,1,0);
	EGB_clearScreen(work);
	para.b = para.r = para.g = 0xF0;
        EGB_palette(work,0,(char *)&para);
	EGB_displayStart(work,1,0,0);
    	EGB_displayPage(work,1,3);
	ofs_y = 0;
    } else {
	EGB_displayPage(work,1,2);
	i = ((480 + ofs_y) & 511) * 512;
	putstr(i,str);
	for ( i = 0 ; i < 16 ; i++ ) {
	    EGB_displayStart(work,1,0,ofs_y++);
	    ofs_y &= 511;
	}
    }

    EGB_writePage(work,0);
    page_ofs = 0;
}

void	DSP_pause(int x,int y,int cl,int bk,char *str)
{
    int     i,n;
    char    tmp[4];

    EGB_writePage(work,1);
    page_ofs = 0x40000;
    EGB_displayPage(work,1,2);

    while ( *str != '\0' ) {
	if ( iskan(str) ) {
	    tmp[0] = *(str++);
	    tmp[1] = *(str++);
	    tmp[2] = '\0';
	    n = 16;
	} else {
	    tmp[0] = *(str++);
	    tmp[1] = '\0';
	    n = 8;
	}
	wrtstr(tmp,page_ofs,x/2+y*512,col_cnv[cl],col_cnv[bk],16);
	x += n;

	for ( i = 0 ; i < 8 ; i++ )
	    EGB_displayStart(work,1,0,0);
    }

    EGB_writePage(work,0);
    page_ofs = 0;
}
