/***  スプライト制御ルーチン  ***/

#include <stdio .h>
#include <stdlib.h>
#include <string.h>
#include <spr.h>
#include <egb.h>

#include "spr_defs.h"
#include "spr_drv .h"

#define CARD		unsigned short
#define ABS(x)		( 0 <= (x) ? (x) : -(x) )
#define SGN(n,v)	( 0 <= (n) ? (v) * ( (n) != 0 ) : -(v) )

int		pattern_idx[ IDX_MAX ];

CARD	*imgmap_p = NULL ;
int		imgmap_wx, imgmap_wy ;
int		spr_vx , spr_vy ;
int		scr_chx, scr_chy, scr_dtx, scr_dty ;
int		map_chx, map_chy, map_dtx, map_dty ;

/*  スプライト初期化  */

void sprite_init( void )
{
	int n ;

	for( n=0 ; n <= SPR_MAX ; n++ ) SPR_SET1( n,0,SPR_OFF ), SPR_POS1( n,0,0 );
	SPR_START();
}

void sprite_end( void )
{
	SPR_STOP();
}

/*	スプライトマップスクロールルーチン	*/

void scroll( int xm, int ym )
{
	register CARD *p ;
	CARD	ch ;
	int		ofs, sign, x, y, sn, i ;

	if( 16 < ABS(xm) || 16 < ABS(ym) ){
		/*  安全装置  */
		if( xm != 0 ){
			x = SGN( xm, 16 );
			while( 16 < ABS(xm) ) scroll( x, 0 ), xm -= x ;
			scroll( xm, 0 );
		}
		if( ym != 0 ){
			y = SGN( ym, 16 );
			while( 16 < ABS(ym) ) scroll( 0, y ), ym -= y ;
			scroll( 0, ym );
		}
		return ;
	}

	spr_vx	= ( spr_vx - xm )& 511, spr_vy = ( spr_vy - ym )& 511 ;
	scr_dtx = ( scr_dtx + xm + SCR_WD )% SCR_WD, x = scr_dtx>>4 ;
	scr_dty = ( scr_dty + ym + SCR_WD )% SCR_WD, y = scr_dty>>4 ;
	map_dtx = ( map_dtx + xm + IMGMAP_WDX )% IMGMAP_WDX, map_chx = map_dtx>>4 ;
	map_dty = ( map_dty + ym + IMGMAP_WDY )% IMGMAP_WDY, map_chy = map_dty>>4 ;

	SPR_setOffset( spr_vx, spr_vy );

	if( scr_chy != y ){
		ofs = ( (scr_chy + ( ym < 0 ? SCR_WC-1:0 ) )% SCR_WC)*SCR_WC+BACK_IDX ;
		p	= &IMGMAP_BUF( 0, (map_chy+( 0 < ym ? SCR_WC-1 :0 )) % imgmap_wy );
		scr_chy = y ;
		sign = ( 0 < ym ? SCR_WD : -SCR_WD );

		for( i = 0 ; i < SCR_WC ; i++ ){
			ch = p[ ( map_chx + i )% imgmap_wx ];
			sn = ofs +( x + i )% SCR_WC ;
			SPR_MOVE1( sn, 0, sign ), SPR_SET0( sn, ch | OFS_ON ) ;
		}
	}

	if( scr_chx != x ){
		ofs = ( scr_chx +( xm < 0 ? SCR_WC-1 : 0 ) )% SCR_WC + BACK_IDX ;
		p	= &IMGMAP_BUF( (map_chx+( 0 < xm ? SCR_WC-1 :0 )) % imgmap_wx, 0 );
		scr_chx = x ;
		sign = ( 0 < xm ? SCR_WD : -SCR_WD );
		
		for( i = 0 ; i < SCR_WC ; i++ ){
			ch = p[ (( map_chy + i )% imgmap_wy )*imgmap_wx ];
			sn = ofs +( ( scr_chy + i )% SCR_WC )*SCR_WC ;
			SPR_MOVE1( sn, sign, 0 ), SPR_SET0( sn, ch | OFS_ON );
		}
	}
}

void map_init( void )
{
	int x, y, sn ;

	scr_dtx = scr_dty = scr_chx = scr_chy = spr_vx = spr_vy = 0 ;
	map_dtx = map_dty = 0 ;

	SPR_setOffset( spr_vx , spr_vy );

	for( y = 0 ; y < SCR_WC ; y++ ){
		for( x = 0 ; x < SCR_WC ; x++ ){
			sn = x + y * SCR_WC + BACK_IDX ;
			SPR_SET0( sn, 0 | OFS_ON );
			SPR_POS1( sn, ( x*16 + SCR_OFSX )& 511, ( y*16 + SCR_OFSY )& 511 );
		}
	}
}

void map_reset( int x, int y )
{
	int xm, ym ;
	int ch, sn ;

	xm = map_dtx & 15, ym = map_dty & 15 ;
	if( 0 < xm || 0 < ym ) scroll( -xm, -ym );
	map_chx = ( imgmap_wx + x )% imgmap_wx, map_dtx = map_chx << 4 ;
	map_chy = ( imgmap_wy + y )% imgmap_wy, map_dty = map_chy << 4 ;

	for( y = 0 ; y < SCR_WC ; y++ ){
		sn = ( ( scr_chy + y )% SCR_WC )*SCR_WC + BACK_IDX ;
		for( x = 0 ; x < SCR_WC ;x++ ){
			ch = IMGMAP_BUF( (map_chx+x)% imgmap_wx, (map_chy+y)% imgmap_wy );
			SPR_SET0( sn +(scr_chx+x)% SCR_WC, ch | OFS_ON );
		}
	}
}

/***  データ読み込み  ***/

int load_imagemap( char *fname )
{
	FILE	*fp ;
	char	head[16];

	if( ( fp = fopen(fname,"rb") ) == NULL ) return 1 ;

	fread( (char *)head, 16, 1 , fp );
	if( memcmp( head, "MAP_DATA", 8 ) != 0 ) return 1 ;
	imgmap_wx = WORD( head + 12 ), imgmap_wy = WORD( head + 14 );
	if( imgmap_p != NULL ) free( imgmap_p );
	imgmap_p = malloc( imgmap_wx * imgmap_wy * 2 );
	if( imgmap_p == NULL ) return 1 ;
	fread( imgmap_p, imgmap_wx * 2, imgmap_wy, fp );

	fclose(fp);

	return 0 ;
}

int load_sprite( char *fname, int spr_ofs, int pal_ofs )
{
	FILE	*fp ;
	CARD	pat_idx ;
	char	head[16], spr_buf[ SPR_BK32K ], *p ;
	int 	pal_sz, pat_sz, sn, bksz, PTR_f ;

	if( ( fp = fopen( fname, "rb" ) ) == NULL ) return 1 ;
	fread( head, 16, 1, fp );

	PTR_f = ( _memicmp( strchr( fname, '.' ), ".PTR", 4 ) == 0 );
	if( PTR_f == 0 ){
		pat_sz = DWORD( head +  8 );
		pal_sz = DWORD( head + 12 );
	}else{
		pat_sz = WORD( head + 14 )*( SPR_BH + SPR_BK32K );
		pal_sz = 0 ;
	}

	/* PALETTE READ */
	if( 0 < pal_sz ){
		p = malloc( pal_sz );
		fread( p, pal_sz, 1, fp );
		SPR_setPaletteBlock( pal_ofs + 256, pal_sz / PAL_BLOCK, p );
		free( p );
	}

	/* SPRITE READ */
	for( sn = spr_ofs ; 0 < pat_sz ; pat_sz -= bksz*128 + SPR_BH, sn += bksz ){

		fread( &pat_idx, SPR_BH, 1, fp );
		if( ( pat_idx & 0x8000 ) == 0 || PTR_f ){
			bksz = 4, pattern_idx[ sn ] = 0x8100 ;
		}else{
			bksz = 1, pattern_idx[ sn ] = pat_idx + pal_ofs ;
		}
		fread( spr_buf, bksz * 128, 1, fp );
		SPR_define( ( bksz == 4 ), sn + 128, 1, 1, spr_buf );
	}

	fclose(fp);
	return 0 ;
}
