/*
 * PROJECT C Library, X68000 PROGRAMMING INTERFACE DEFINITION
 * --------------------------------------------------------------------
 * This file is written by the Project C Library Group,  and completely
 * in public domain. You can freely use, copy, modify, and redistribute
 * the whole contents, without this notice.
 * --------------------------------------------------------------------
 * $Id:
 */

#ifndef __sprite_h__
#define __sprite_h__

#ifndef __cdecl_h__
#include <cdecl.h>
#endif

#ifndef __sys_iocs_h__
#include <sys/iocs.h>
#endif

#ifndef _NASI
#define _NASI 0x4e415349	/* 'NASI' */
#endif

_EXTERN (int_ bg_fill (char, int_));
_EXTERN (int_ bg_get (char, char, char));
_EXTERN (int_ bg_put (char, char, char, int_));
_EXTERN (int_ bg_scroll (char, int_, int_));
_EXTERN (int_ bg_set (char, int_, int_));
_EXTERN (int_ bg_stat (char, char));
_EXTERN (int_ sp_color (char, int_, int_));
_EXTERN (int_ sp_init (void));
_EXTERN (int_ sp_set (char, int_, int_, int_, int_));
_EXTERN (int_ sp_stat (char, char));
_EXTERN (void sp_clr (int_, int_));
_EXTERN (void sp_def (char, const char *, int_));
_EXTERN (void sp_disp (char));
_EXTERN (void sp_move (char, int_, int_, int_));
_EXTERN (void sp_off (int_, int_));
_EXTERN (void sp_on (int_, int_));
_EXTERN (void sp_pat (char, char *, int_));

static __inline int_ _bg_fill (char page, int_ pat)
{
    /* BG クリア */
    _iocs_bgtextcl (page, pat);
}

static __inline int_ _bg_get (char page, char x, char y)
{
    /* BG 収得 */
    _iocs_bgtextgt (page, x, y);
}

static __inline int_ _bg_put (char page, char x, char y, int_ pat)
{
    /* BG 設定 */
    _iocs_bgtextst (page, x, y, pat);
}

static __inline int_ _bg_scroll (char no, int_ x, int_ y)
{
    if (x > 1023)
	x = -1;
    if (y > 1023)
	y = -1;

    /* BG 表示座標設定 */
    _iocs_bgscrlst (no | (1 << 31), x, y);
}

static __inline int_ _bg_set (char no, int_ page, int_ mode)
{
    if (page > 1)
	page = -1;
    if (mode > 1)
	mode = -1;

    /* BG 制御レジスタ設定 */
    _iocs_bgctrlst (no, page, mode);
}

static __inline int_ _bg_stat (char no, char mode)
{
    int_ x, y;
    int_ rc;

    switch (mode) {
    case 0:
    case 1:
	/* 座標を収得 */
	rc = _iocs_bgscrlgt (no, &x, &y);
	if (rc < 0)
	    return rc;
	return (mode == 0) ? x : y;
    case 2:
    case 3:
	/* モードを収得 */
	rc = _iocs_bgctrlgt (no);
	if (rc < 0)
	    return rc;
	return (mode == 2) ? rc >> 1 : rc & 1;
    default:
	return -2;
    }
}

static __inline int_ _sp_color (char no, int_ color, int_ block)
{
    if (block == _NASI)
	block = 1;
    if (color == _NASI)
	color = -1;

    /* パレット設定 */
    _iocs_spalet (no | (1 << 31), block, color);
}

static __inline int_ _sp_init (void)
{
    /* 初期化 */
    _iocs_sp_init ();
}

static __inline int_ _sp_set (char no, int_ x, int_ y, int_ mode, int_ prw)
{
    if (x > 1023)
	x = -1;
    if (y > 1023)
	y = -1;
    if (mode > 65535)
	mode = -1;
    if (prw > 3)
	prw = -1;

    /* レジスタ設定 */
    _iocs_sp_regst (no | (1 << 31), x, y, mode, prw);
}

static __inline int_ _sp_stat (char no, char mode)
{
    int_ x, y, md, prw;

    /* レジスタ読み出し */
    int rc = _iocs_sp_reggt (no, &x, &y, &md, &prw);

    if (rc < 0)
	return rc;

    /* 指定の情報を返す */
    switch (mode) {
    case 0:
	return x;
    case 1:
	return y;
    case 2:
	return md;
    case 3:
	return prw;
    default:
	return -2;
    }
}

static __inline void _sp_clr (int_ start, int_ end)
{
    if (start > end) {
	int_ tmp = start;

	/* start と end を交換 */
	start = end;
	end = tmp;
    }

    if (start == _NASI) {
	start = 0;
	end = 255;
    }
    else if (end == _NASI)
	end = start;

    do {
	/* パターンをクリア */
	_iocs_sp_cgclr (start);
    } while (++start <= end);
}

static __inline void _sp_def (char pat, const char *buf, int_ size)
{
    char tmp[128];
    char d;

    /* 8x8 */
    if (size == 0) {
	char *p = tmp;
	int_ i;

	for (i = 0; i < 32; i++) {
	    d = *buf++ << 4;
	    d |= *buf++ & 0x0f;
	    *p++ = d;
	}
    }

    /* 16x16 */
    else {
	int_ i, j;
	char *p = tmp;
	const char *buf2 = buf + 64;

	for (i = 0; i < 16; i++) {
	    for (j = 0; j < 4; j++) {
		d = *buf++ << 4;
		d |= *buf++ & 0x0f;
		*p++ = d;
	    }
	    for (j = 0; j < 4; j++) {
		d = *buf2++ << 4;
		d |= *buf2++ & 0x0f;
		*p++ = d;
	    }
	}
	size = 1;
    }

    /* パターン定義 */
    _iocs_sp_defcg (pat, size, buf);
}

static __inline void _sp_disp (char mode)
{
    /* 非表示 */
    if (mode == 0)
	_iocs_sp_off ();

    /* 表示 */
    else if (mode == 1)
	_iocs_sp_on ();

}

static __inline void _sp_move (char no, int_ x, int_ y, int_ mode)
{
    /* レンジ調整 */
    x += 16;
    y += 16;

    /* 前回指定値を使用 */
    if (x > 1023)
	x = -1;
    if (y > 1023)
	y = -1;
    if (mode > 255)
	mode = -1;
    else
	mode |= 0x100;

    /* レジスタ設定 */
    _iocs_sp_regst (no | (1 << 31), x, y, mode, 3);
}

static __inline void _sp_off (int_ start, int_ end)
{
    if (start == _NASI) {
	start = 0;
	if (end == _NASI)
	    end = 127;
    }
    else if (end == _NASI)
	end = start;

    /* エラーチェック */
    if (start < 0 || start > 127 || end < 0 || end > 127)
	return;

    do {
	/* レジスタ設定 */
	_iocs_sp_regst (start | (1 << 31), -1, -1, -1, 0);
    } while (++start <= end);
}

static __inline void _sp_on (int_ start, int_ end)
{
    if (start == _NASI) {
	start = 0;
	if (end == _NASI)
	    end = 127;
    }
    else if (end == _NASI)
	end = start;

    /* エラーチェック */
    if (start < 0 || start > 127 || end < 0 || end > 127)
	return;

    do {
	/* レジスタ設定 */
	_iocs_sp_regst (start | (1 << 31), -1, -1, -1, 3);
    } while (++start <= end);
}

static __inline void _sp_pat (char pat, char *buf, int_ size)
{
    char tmp[128];

    if (size)
	size = 1;

    /* パターン収得 */
    _iocs_sp_gtpcg (pat, size, tmp);

    /* 8x8 */
    if (size == 0) {
	int_ i;
	unsigned char *p = (unsigned char *) tmp;

	for (i = 0; i < 32; i++) {
	    *buf++ = *p >> 4;
	    *buf++ = *p++ & 0x0f;
	}
    }

    /* 16x16 */
    else {
	int_ i, j;
	unsigned char *p = (unsigned char *) tmp;
	unsigned char *p2 = (unsigned char *) tmp + 64;

	for (i = 0; i < 16; i++) {
	    for (j = 0; j < 4; j++) {
		*buf++ = *p >> 4;
		*buf++ = *p++ & 0x0f;
	    }
	    for (j = 0; j < 4; j++) {
		*buf++ = *p2 >> 4;
		*buf++ = *p2++ & 0x0f;
	    }
	}
    }
}

#define bg_fill		_bg_fill
#define bg_get		_bg_get
#define bg_put		_bg_put
#define bg_scroll	_bg_scroll
#define bg_set		_bg_set
#define bg_stat		_bg_stat
#define sp_color	_sp_color
#define sp_init		_sp_init
#define sp_set		_sp_set
#define sp_stat		_sp_stat
#define sp_clr		_sp_clr
#define sp_def		_sp_def
#define sp_disp		_sp_disp
#define sp_move		_sp_move
#define sp_off		_sp_off
#define sp_on		_sp_on
#define sp_pat		_sp_pat

#endif
