#include <string.h>
#include <stdio .h>
#include <stdlib.h>
#include <egb.h>
#include <mos.h>

#include "calc   .h"
#include "graphic.h"

struct PUT_ST { char *adr ; short seg, x, y, xe, ye, ox, oy ; };

char	ework[1536], mwork[MosWorkSize] ;
char	para[256] ;
int		page1_px, page1_py, write_page = PAGE0, mouse_page ;

int cvcl[] = {
	0x8000		 , GRB( 0, 0,31), GRB( 0,31, 0), GRB( 0,31,31),
	GRB(31, 0, 0), GRB(31, 0,31), GRB(31,31, 0), GRB(31,31,31),
	GRB( 0, 0, 0), GRB(12,12,31), GRB(12,31,12), GRB(12,31,31),
	GRB(31,12,12), GRB(31,12,31), GRB(31,31,12), GRB(18,18,18),
	GRB( 3, 3, 3), GRB( 7, 7, 7), GRB(11,11,11), GRB(15,15,15),
	GRB(19,19,19), GRB(23,23,23), GRB(27,27,27), GRB(31,31,31),
};

PALET_S palette_buf = {
	16,
	 0,   0,  0,  0, 0,
	 1, 196,  0,  0, 0,
	 2,   0,196,  0, 0,
	 3, 128,128,  0, 0,
	 4,   0,  0,196, 0,
	 5, 128,  0,128, 0,
	 6,   0,128,128, 0,
	 7, 128,128,128, 0,
	 8,  96, 96, 96, 0,
	 9, 255,  0,  0, 0,
	10,   0,255,  0, 0,
	11, 255,255,  0, 0,
	12,   0,  0,255, 0,
	13, 255,  0,255, 0,
	14,   0,255,255, 0,
	15, 255,255,255, 0,
};

/*  スクリーンモード  */
struct SCRMODE_S scr_mode[]={
	 3,	4,	/*	0	 16色・ 640*480  */
	10,16,	/*	1	32k色・ 512*256  */
	12, 8,	/*	2	256色・1024*512  */
	 5,16,	/*	3	32k色・ 256*512  */
};
int		display_mode[2] ;

/***  ウエイト  ***/

void wait( int n )
{
	for( ; 0 < n ; n-- );
}

void wait_vsync( int c )
{
	LCARD pal_dmy ;

	for( pal_dmy = 0 ; 0 < c ; --c ) EGB_palette( ework, 1, (char *)&pal_dmy );
}

/***  ドットデータ表示・取り込み  ***/

void put_dotdata( int x, int y, int wx, int wy, int mode, void *adr, int clp )
{
	struct PUT_ST p ;

	p.adr = (char *)adr, p.seg = 0x14 ;
	p.x = x, p.y = y, p.xe = x + wx-1, p.ye = y + wy-1 ;
	EGB_writeMode( ework, mode );
	EGB_putBlock ( ework, clp, (char *)&p );
}

void put_dotzoom(
	int x, int y, int wx, int wy, int mode, void *adr, int ox, int oy, int clp
){
	struct PUT_ST p ;

	p.adr = (char *)adr, p.seg = 0x14 ;
	p.x = x, p.y = y, p.xe = x + wx-1, p.ye = y + wy-1, p.ox = ox, p.oy = oy ;
	EGB_writeMode	( ework, mode );
	EGB_putBlockZoom( ework, clp, (char *)&p );
}

void get_dotdata( int x, int y, int wx, int wy, void *adr )
{
	struct PUT_ST p ;

	p.adr = (char *)adr, p.seg = 0x14 ;
	p.x = x, p.y = y, p.xe = x + wx-1, p.ye = y + wy-1 ;
	EGB_getBlock( ework, (char *)&p );
}

void put_dotplane(
	int x, int y, int wx, int wy, int w_mode, void *adr, int col, int clp
){
	struct PUT_ST p ;

	p.adr = (char *)adr, p.seg = 0x14 ;
	p.x = x, p.y = y, p.xe = x + wx-1, p.ye = y + wy-1 ;
	EGB_writeMode	 ( ework, w_mode ), EGB_color( ework, 0, col );
	EGB_putBlockColor( ework, clp, (char *)&p );
}

void get_dotplane( int x, int y, int wx, int wy, void *adr, int *col, int vol )
{
	struct { char *adr ; short seg, x, y, xe, ye, v ; long col[32] ; } p ;

	p.adr = (char *)adr, p.seg = 0x14 ;
	p.x = x, p.y = y, p.xe = x + wx-1, p.ye = y + wy-1 ;
	for( p.v = 0 ; p.v < vol ; ++p.v ) p.col[ p.v ] = col[ p.v ];
	EGB_getBlockColor( ework, (char *)&p );
}

/***  描画命令  ***/

void line( int x1, int y1, int x2, int y2, int w_mode, int l_color )
{
	EGB_writeMode( ework, w_mode );
	EGB_paintMode( ework, 0x02 );
	EGB_color	 ( ework, 0, l_color );
	WORD( para + 0 ) = 2 ;
	WORD( para + 2 ) = x1, WORD( para + 4 ) = y1 ;
	WORD( para + 6 ) = x2, WORD( para + 8 ) = y2 ;
	EGB_connect( ework, para );
}

void box_line( int x, int y, int wx, int wy, int w_mode, int l_color )
{
	EGB_writeMode( ework, w_mode );
	EGB_paintMode( ework, 0x02 );
	EGB_color	 ( ework, 0, l_color );
	WORD( para + 0 ) = x, WORD( para + 4 ) = x+wx-1 ;
	WORD( para + 2 ) = y, WORD( para + 6 ) = y+wy-1 ;
	EGB_rectangle( ework, para );
}

void box_fill( int x,int y, int wx,int wy, int w_mode,int l_color,int p_color )
{
	EGB_writeMode( ework, w_mode );
	EGB_paintMode( ework, 0x22 );
	EGB_color	 ( ework, 0, l_color );
	EGB_color	 ( ework, 2, p_color );
	WORD( para + 0 ) = x, WORD( para + 4 ) = x+wx-1 ;
	WORD( para + 2 ) = y, WORD( para + 6 ) = y+wy-1;
	EGB_rectangle( ework, para );
}

/***  文字表示 ***/

int symbol(
	int x, int y, char *str, int zx, int zy,
	int col, int s_col, int w_mode, int style
){
	struct { short x, y, len ; char str[256] ; } p ;

	EGB_writeMode( ework, w_mode );
	EGB_color	 ( ework, 0, col );
	EGB_color	 ( ework, 1, s_col );
	EGB_textZoom ( ework, 0, zx* 8, zy*16 );
	EGB_textZoom ( ework, 1, zx*16, zy*16 );
	EGB_fontStyle( ework, style );

	if( 255 < ( p.len = strlen( str ) ) ) p.len = 255 ;
	_move( str, p.str, p.len + 1 );
	p.x = x, p.y = y ;

	return EGB_sjisString( ework, ( char *)&p );
}

int symbol_ch( int x, int y, int ch, int col, int s_col, int w_mode )
{
	struct { short x, y, len ; char str[256] ; } p ;

	EGB_writeMode( ework, w_mode );
	EGB_color	 ( ework, 0, col ), EGB_color( ework, 1, s_col ) ;
	EGB_fontStyle( ework, 0 );

	if( ( ch >> 8 ) == 0 ) p.len = 1, p.str[0] = ch & 255 ;
	else				   p.len = 2, p.str[0] = ch >> 8, p.str[1] = ch & 255 ;
	p.x = x, p.y = y + 15 ;

	return EGB_sjisString( ework, (char *)&p );
}

/***  表示画面の初期化  ***/

void select_screenMode( int page, int mode )
{
	if( mode <= 3 ){
		display_mode[ page ] = mode ;
		EGB_resolution( ework, page, scr_mode[ mode ].mode );
	}
}

void screen_offset( int set_page, int *para )
{
	EGB_writePage	( ework, set_page );
	EGB_displayStart( ework, 2, para[6], para[6] );	/*	拡大率設定		*/
	EGB_displayStart( ework, 3, para[2], para[3] );	/*	表示領域		*/
	EGB_displayStart( ework, 0, para[0], para[1] ); /*	表示位置		*/
	EGB_displayStart( ework, 1, para[4], para[5] ); /*	仮想画面位置	*/
	EGB_writePage	( ework, write_page );
	if( set_page == PAGE1 ){
		page1_px = para[0] - para[4] ;
		page1_py = para[1] - para[5] ;
	}
}

void screen_roll( int page, int x, int y )
{
	EGB_writePage	( ework, page );
	EGB_displayStart( ework, 1, x, y );
	EGB_writePage	( ework, write_page );
}

void screen_init( int mode0, int mode1, int mpage )
{
	EGB_init( ework,1536 );
	if( 0 <= ( mouse_page = mpage ) ) MOS_start( mwork, MosWorkSize );
	select_screenMode( 0, mode0 ), select_screenMode( 1, mode1 );

	if( mode1 == SPRITE_MODE ){
		EGB_writePage( ework, PAGE1 );
		EGB_color( ework, 1, 0x8000 ), EGB_clearScreen( ework );
	}
	EGB_writePage	( ework, PAGE0 );
	EGB_displayPage	( ework, 0, 3 );
	EGB_palette		( ework, 1, (char *)( &palette_buf ) );
	EGB_fontStyle	( ework, 0 );

	if( 0 <= mouse_page ){
		MOS_resolution( mouse_page, scr_mode[ display_mode[mouse_page] ].mode);
		MOS_writePage ( mouse_page );
		MOS_disp( 0 );
	}
}

void screen_clear( void )
{
	EGB_writePage( ework,1 ), EGB_color( ework,1,0 ), EGB_clearScreen( ework );
	EGB_writePage( ework,0 ), EGB_color( ework,1,0 ), EGB_clearScreen( ework );
}

void view( int x1, int y1, int x2, int y2 )
{
	WORD( para + 0 ) = x1, WORD( para + 2 ) = y1 ;
	WORD( para + 4 ) = x2, WORD( para + 6 ) = y2 ;
	EGB_viewport( ework, para );
}
