/*============================================================================
  wsSprite.c ver.1.00 「ワンダースワンスプライト制御」
------------------------------------------------------------------------------
												Programmed by Keiichi.Tago.
============================================================================*/
#include "wsSprite.h"

/* ==================== スタティック変数定義 */
int nSpColorMode;							/* カラーモード (0=モノクロ, 1=カラー) */
WORD wSpPriority;							/* スクリーン 2 に対する優先順位 (0x0000=後, 0x2000=手前) */
BYTE far *lpObjectAddress[ OBJECT_MAX ];
BYTE far SpFontWork[8];						/* フォント格納用ワークエリア */
BYTE far SpFontDrawWork[32];				/* フォント格納用ワークエリア */

/*============================================================
	スプライトの初期化
--------------------------------------------------------------
In  : nSetColorMode (0=白黒モード,
    :                1=ワンダースワンカラーならカラーモードに設定する )
Out : なし
============================================================*/
void wsSpInit( int nSetColorMode )
{
	int i;
	/* 適切なモードに設定する */
	if ( ( wwc_get_hardarch() == HARDARCH_WS ) || ( nSetColorMode == 0 ) ) {
		/* モノクロモード設定 */
		wwc_set_color_mode( COLOR_MODE_GRAYSCALE );
		nSpColorMode = 0;
	} else {
		/* カラーモード設定 */
		wwc_set_color_mode( COLOR_MODE_16COLOR );
		nSpColorMode = 1;
	}
	/* スプライト表示許可範囲設定 */
	sprite_set_range( 0, 128 );
	for ( i=0; i<128; i++ ) {
		sprite_set_location( i, 224, 144 );
	}
	/* スクリーン 2 よりも手前に表示 */
	wSpPriority = 0x2000;
	/* スプライト 表示 */
	display_control( display_status() | DCM_SPR );
}

/*============================================================
	オブジェクトファイルの設定
--------------------------------------------------------------
In  : nObjectNumber = オブジェクト番号
    : lpPath = オブジェクトのファイルネーム
Out : なし
============================================================*/
void wsSpSetObjectFile( int nObjectNumber, char far *lpPath )
{
	lpObjectAddress[ nObjectNumber ] = mmap( lpPath );
}


/*============================================================
	キャラクタ定義
--------------------------------------------------------------
In  : nObjectNumber = BG オブジェクト番号
    : nChrNumber = 定義するキャラクタ番号
    : nDefineNumber = キャラクタ定義位置
    : nNumOfDefine = 定義するキャラクタ数
Out : なし
============================================================*/
void wsSpSetChr( int nObjectNumber, int nChrNumber, int nDefineNumber, int nNumOfDefine )
{
	WORD far *lpChrHead;
	BYTE far *lpChrData;
	lpChrHead = (WORD far *)( lpObjectAddress[ nObjectNumber ] + 6 );
	lpChrData = (BYTE far *)( (DWORD)lpObjectAddress[ nObjectNumber ] + (DWORD)lpChrHead[ 0 ] );
	/* ヘッダを見てデータ形式を判断する */
	if ( *(BYTE far *)( lpObjectAddress[ nObjectNumber ] + 5 ) == 0 ) {
		/* モノクロデータ */
		lpChrData += ( nChrNumber * 16 );
		font_set_colordata( nDefineNumber, nNumOfDefine, lpChrData );
	} else {
		/* カラーデータ */
		lpChrData += ( nChrNumber * 32 );
		wwc_font_set_colordata( nDefineNumber, nNumOfDefine, lpChrData );
	}
}

/*============================================================
	パレット定義
--------------------------------------------------------------
In  : nObjectNumber = BG オブジェクト番号
    : nPaletNumber = 選択パレット番号
    : nDefineNumber = 定義パレット番号 (0〜7)
Out : なし
============================================================*/
void wsSpSetPalet( int nObjectNumber, int nPaletNumber, int nDefineNumber )
{
	WORD far *lpChrHead;
	WORD far *lpPalData;
	int i;
	lpChrHead = (WORD far *)( lpObjectAddress[ nObjectNumber ] + 6 );
	lpPalData = (WORD far *)( (DWORD)lpObjectAddress[ nObjectNumber ] + (DWORD)lpChrHead[ 1 ] );
	/* ヘッダを見てデータ形式を判断する */
	if ( *(BYTE far *)( lpObjectAddress[ nObjectNumber ] + 5 ) == 0 ) {
		/* モノクロデータ */
		palette_set_color( nDefineNumber + 8, lpPalData[ nPaletNumber ] );
	} else {
		/* カラーデータ */
		for( i=0; i<16; i++ ) {
			wsPalSetColorPalet( nDefineNumber + 8, i, lpPalData[ nPaletNumber * 16 + i ] );
		}
	}
}

/*============================================================
	オブジェクトの設定
--------------------------------------------------------------
In  : nObjectNumber = オブジェクト番号
    : nPatternNumber = キャラクタパターン番号
    : nSpriteNumber = 使用するスプライトの先頭番号
    : nDefineNumber = キャラクタ定義の先頭番号
    : nPalet = パレット番号 ( 指定しない場合は 0 )
    : nX = 表示 X 座標
    : nY = 表示 Y 座標
Out : なし
============================================================*/
void wsSpSetObject( int nObjectNumber, int nPatternNumber, int nSpriteNumber, int nDefineNumber, int nPalet, int nX, int nY )
{
/*	CHRHEAD lpChrHead;	*/
	WORD far *lpChrHead;
	BYTE far *lpChrData;
	WORD far *lpPalData;
	WORD far *lpObjData;
	int nNumOfSprite;
	int nObjPointer;
	int i;
	lpChrHead = (WORD far *)( lpObjectAddress[ nObjectNumber ] + 6 );
	lpChrData = (BYTE far *)( (DWORD)lpObjectAddress[ nObjectNumber ] + (DWORD)lpChrHead[ 0 ] );
	lpPalData = (WORD far *)( (DWORD)lpObjectAddress[ nObjectNumber ] + (DWORD)lpChrHead[ 1 ] );
	lpObjData = (WORD far *)( (DWORD)lpObjectAddress[ nObjectNumber ] + (DWORD)lpChrHead[ 2 + nPatternNumber ] );
	nNumOfSprite = lpObjData[ 1 ];
	nObjPointer = 3;
	if ( lpObjData[ 0 ] & SP_DEFCHR ) {
		/* キャラクタ再定義の必要あり */
		for ( i=0; i<nNumOfSprite; i++ ) {
			if ( lpObjData[ nObjPointer ] == -1 ) {
				sprite_set_location( nSpriteNumber + i, 224, 144 );
			} else {
				/* ヘッダを見てデータ形式を判断する */
				if ( *(BYTE far *)( lpObjectAddress[ nObjectNumber ] + 5 ) == 0 ) {
					/* モノクロデータ */
					font_set_colordata( nDefineNumber + i, 1, lpChrData + 16 * lpObjData[ nObjPointer ] );
				} else {
					/* カラーデータ */
					wwc_font_set_colordata( nDefineNumber + i, 1, lpChrData + 32 * lpObjData[ nObjPointer ] );
				}
				sprite_set_char( nSpriteNumber + i, ( nDefineNumber + i ) | ( lpObjData[ 0 ] & 0xC000 ) | ( ( lpObjData[ 2 ] + nPalet ) << 9 ) | wSpPriority );
				sprite_set_location( nSpriteNumber + i, nX + lpObjData[ nObjPointer + 1 ], nY + lpObjData[ nObjPointer + 2 ] );
			}
			nObjPointer += 3;
		}
	} else {
		/* キャラクタ再定義の必要なし */
		for ( i=0; i<nNumOfSprite; i++ ) {
			if ( lpObjData[ nObjPointer ] == -1 ) {
				sprite_set_location( nSpriteNumber + i, 224, 144 );
			} else {
				sprite_set_char( nSpriteNumber + i, ( nDefineNumber + i ) | ( lpObjData[ 0 ] & 0xC000 ) | ( ( lpObjData[ 2 ] + nPalet ) << 9 ) | wSpPriority );
				sprite_set_location( nSpriteNumber + i, nX + lpObjData[ nObjPointer + 1 ], nY + lpObjData[ nObjPointer + 2 ] );
			}
			nObjPointer += 3;
		}
	}
}

/*============================================================
	オブジェクトの移動
--------------------------------------------------------------
In  : nObjectNumber = オブジェクト番号
    : nPatternNumber = キャラクタパターン番号
    : nSpriteNumber = 使用するスプライトの先頭番号
    : nX = 表示 X 座標
    : nY = 表示 Y 座標
Out : なし
============================================================*/
void wsSpMoveObject( int nObjectNumber, int nPatternNumber, int nSpriteNumber, int nX, int nY )
{
	WORD far *lpChrHead;
	WORD far *lpObjData;
	int nNumOfSprite;
	int nObjPointer;
	int i;
	lpChrHead = (WORD far *)( lpObjectAddress[ nObjectNumber ] + 6 );
	lpObjData = (WORD far *)( (DWORD)lpObjectAddress[ nObjectNumber ] + (DWORD)lpChrHead[ 2 + nPatternNumber ] );
	nNumOfSprite = lpObjData[ 1 ];
	nObjPointer = 3;
	for ( i=0; i<nNumOfSprite; i++ ) {
		if ( lpObjData[ nObjPointer ] == -1 ) {
			sprite_set_location( nSpriteNumber + i, 224, 144 );
		} else {
			sprite_set_location( nSpriteNumber + i, nX + lpObjData[ nObjPointer + 1 ], nY + lpObjData[ nObjPointer + 2 ] );
		}
		nObjPointer += 3;
	}
}

/*============================================================
	1 文字定義
--------------------------------------------------------------
In  : nDefineNumber = 最初のキャラクタ番号
    : nCode = 文字コード
    : nColor = 色 (0〜15) ※カラーモードのみ
    : nShadowColor = 影の色 (0〜15) ※カラーモードのみ
Out : なし
============================================================*/
void wsSpSetLetter( int nDefineNumber, int nCode, int nColor, int nShadowColor )
{
	int i, j, k;
	text_get_fontdata( nCode, SpFontWork );
	if ( nSpColorMode == 0 ) {
		/* モノクロモード */
		font_set_monodata( nDefineNumber, 1, SpFontWork );
	} else {
		int nFlag;
		/* カラーモード */
		if ( nShadowColor != 0 ) {
			memset( SpFontDrawWork, 0, sizeof( SpFontDrawWork ) );
		}
		for( i=7; i>=0; i-- ) {
			if ( nShadowColor != 0 ) {
				for( j=0; j<4; j++ ) {
					nFlag = ( nShadowColor >> j ) & 1;
					if ( nFlag == 1 ) {
						for( k=-1; k<2; k++ ) {
							if ( ( ( i + k ) >= 0 ) && ( ( i + k ) < 8 ) ) {
								SpFontDrawWork[ ( i + k ) * 4 + j ] |= SpFontWork[ i ] >> 1;
								SpFontDrawWork[ ( i + k ) * 4 + j ] |= SpFontWork[ i ];
								SpFontDrawWork[ ( i + k ) * 4 + j ] |= SpFontWork[ i ] << 1;
							}
						}
					} else {
						SpFontDrawWork[ i * 4 + j ] = 0;
					}
				}
			}
			for( j=0; j<4; j++ ) {
				BYTE by1Line;
				nFlag = ( nColor >> j ) & 1;
				if ( nFlag == 1 ) {
					by1Line = SpFontWork[ i ];
				} else {
					by1Line = 0;
				}
				if ( nShadowColor != 0 ) {
					SpFontDrawWork[ i * 4 + j ] &= ~SpFontWork[ i ];
					SpFontDrawWork[ i * 4 + j ] |= by1Line;
				} else {
					SpFontDrawWork[ i * 4 + j ] = by1Line;
				}
			}
		}
		wwc_font_set_colordata( nDefineNumber, 1, SpFontDrawWork );
	}
}

/*============================================================
	スプライト表示
--------------------------------------------------------------
In  : nSpriteNumber = スプライト番号
    : nDefineNumber = キャラクタ番号
    : nX = 横表示位置
    : nY = 縦表示位置
    : nColor = パレット
Out : なし
============================================================*/
void wsSpPutChar( int nSpriteNumber, int nDefineNumber, int nX, int nY, int nColor )
{
	sprite_set_char( nSpriteNumber, nDefineNumber | ( nColor << 9 ) | wSpPriority );
	sprite_set_location( nSpriteNumber, nX, nY );
}

/*============================================================
	文字列表示 (全角のみ)
--------------------------------------------------------------
In  : nSpriteNumber = 最初のスプライト番号
    : nDefineNumber = 最初のキャラクタ番号
    : nX = 横表示位置
    : nY = 縦表示位置
    : nPalet = パレット番号
    : nColor = 色 (0〜15) ※カラーモードのみ
    : nShadowColor = 影の色 (0〜15) ※カラーモードのみ
    : lpString = 文字列
Out : なし
============================================================*/
void wsSpPutString( int nSpriteNumber, int nDefineNumber, int nX, int nY, int nPalet, int nColor, int nShadowColor, char *lpString )
{
	int nCode;
	while( *lpString != '\0' ) {
#ifdef LSI_C
		nCode = lpString[0] * 256 + lpString[1];
#else
		nCode = lpString[1] * 256 + lpString[0];
#endif
		wsSpSetLetter( nDefineNumber, nCode, nColor, nShadowColor );
		wsSpPutChar( nSpriteNumber, nDefineNumber, nX, nY, nPalet );
		nX += 8;
		nSpriteNumber++;
		nDefineNumber++;
		lpString += 2;
	}
}

/*
{
	char str[100];
	display_control( DCM_SCR2 );
	lcd_set_sleep( 1 );
	text_screen_init();
	text_set_screen( 1 );
	sprintf( str, "lpObjData = %x:%x", FP_SEG( lpObjData ), FP_OFF( lpObjData ) );
	text_put_string( 0, 0, str );
	sprintf( str, "Hedadr = %x:%x", FP_SEG( lpChrHead ), FP_OFF( lpChrHead ) );
	text_put_string( 0, 0, str );
	sprintf( str, "Chradr = %x:%x", FP_SEG( lpChrData ), FP_OFF( lpChrData ) );
	text_put_string( 0, 1, str );
	sprintf( str, "Chr = %d,%d,%d", lpChrData[0],lpChrData[1],lpChrData[2] );
	text_put_string( 0, 2, str );
	key_wait();
}
*/
