/*
 * 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 __graph_h__
#define __graph_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_ hsv (int_, int_, int_));
_EXTERN (int_ point (int_, int_));
_EXTERN (int_ rgb (int_, int_, int_));
_EXTERN (void apage (char));
_EXTERN (void box (int_, int_, int_, int_, int_, int_));
_EXTERN (void circle (int_, int_, int_, int_, int_, int_, int_));
_EXTERN (void contrast (int_));
_EXTERN (void fill (int_, int_, int_, int_, int_));
_EXTERN (void get (int_, int_, int_, int_, void *, int_));
_EXTERN (void home (int_, int_, int_));
_EXTERN (void line (int_, int_, int_, int_, int_, int_));
_EXTERN (void paint (int_, int_, int_));
_EXTERN (void palet (int_, int_));
_EXTERN (void pset (int_, int_, int_));
_EXTERN (void put (int_, int_, int_, int_, const void *, int_));
_EXTERN (void symbol (int_, int_, const char *, char, char, int_, int_, int_));
_EXTERN (void vpage (char));
_EXTERN (void window (int_, int_, int_, int_));
_EXTERN (void wipe (void_));

static __inline int_ _hsv (int_ h, int_ s, int_ v)
{
    /* エラーチェック */
    if (h < 0 || h > 191 || s < 0 || s > 31 || v < 0 || v > 31)
	return -1;

    /* HSV から RGB に変換 */
    return _iocs_hsvtorgb (h, s, v);
}

static __inline int_ _point (int_ x, int_ y)
{
    struct _pointptr pointbuf;
    int rc;

    /* パラメータをセット */
    pointbuf.x = x;
    pointbuf.y = y;

    /* パレットコードを収得 */
    rc = _iocs_point (&pointbuf);

    /* エラーコードまたはパレットコードを返す */
    return (rc < 0) ? rc : (int_) pointbuf.color;
}

static __inline int_ _rgb (int_ r, int_ g, int_ b)
{
    /* エラーチェック */
    if (r < 0 || r > 31 || g < 0 || g > 31 || b < 0 || b > 31)
	return -1;

    /* カラーコードに変換 */
    return ((g << 10) | (r << 5) | b) << 1;
}

static __inline void _apage (char mode)
{
    /* 描画ページを設定 */
    _iocs_apage ((unsigned char) mode);
}

static __inline void
_box (int_ x1, int_ y1, int_ x2, int_ y2, int_ color, int_ linestyle)
{
    struct _boxptr boxbuf;

    /* パラメータをセット */
    boxbuf.x1 = x1;
    boxbuf.y1 = y1;
    boxbuf.x2 = x2;
    boxbuf.y2 = y2;
    boxbuf.color = color;
    boxbuf.linestyle = (linestyle == _NASI) ? -1 : linestyle;

    /* 長方形を描画 */
    _iocs_box (&boxbuf);
}

static __inline void
_circle (int_ x, int_ y, int_ radius, int_ color,int_ start, int_ end, int_ ratio)
{
    struct _circleptr circlebuf;

    /* パラメータをセット */
    circlebuf.x = x;
    circlebuf.y = y;
    circlebuf.radius = radius;
    circlebuf.color = color;
    circlebuf.start = (start == _NASI) ? 0 : start;
    circlebuf.end = (end == _NASI) ? 360 : end;
    circlebuf.ratio = (ratio == _NASI) ? 256 : ratio;

    /* 円を描画 */
    _iocs_circle (&circlebuf);
}

static __inline void _contrast (int_ mode)
{
    /* コントラストを設定 */
    _iocs_contrast (mode);
}

static __inline void _fill (int_ x1, int_ y1, int_ x2, int_ y2, int_ color)
{
    struct _fillptr fillbuf;

    /* パラメータをセット */
    fillbuf.x1 = x1;
    fillbuf.y1 = y1;
    fillbuf.x2 = x2;
    fillbuf.y2 = y2;
    fillbuf.color = color;

    /* 矩形を描画 */
    _iocs_fill (&fillbuf);
}

static __inline void _get (int_ x1, int_ y1, int_ x2, int_ y2, void *buf, int_ size)
{
    struct _getptr getbuf;

    /* パラメータをセット */
    getbuf.x1 = x1;
    getbuf.y1 = y1;
    getbuf.x2 = x2;
    getbuf.y2 = y2;
    getbuf.buf_start = buf;
    getbuf.buf_end = (void *) ((int_) buf + size);

    /* GVRAM から読み込み */
    _iocs_getgrm (&getbuf);
}

static __inline void _home (int_ page, int_ x, int_ y)
{
    /* 表示位置を設定 */
    _iocs_home (1 << page, x, y);
}

static __inline void
_line (int_ x1, int_ y1, int_ x2, int_ y2, int_ color, int_ linestyle)
{
    struct _lineptr linebuf;

    /* パラメータをセット */
    linebuf.x1 = x1;
    linebuf.y1 = y1;
    linebuf.x2 = x2;
    linebuf.y2 = y2;
    linebuf.color = color;
    linebuf.linestyle = (linestyle == _NASI) ? -1 : linestyle;

    /* 直線を描画 */
    _iocs_line (&linebuf);
}

static __inline void _paint (int_ x, int_ y, int_ color)
{
    unsigned char workbuf[4096];
    struct _paintptr paintbuf;

    /* パラメータをセット */
    paintbuf.x = x;
    paintbuf.y = y;
    paintbuf.color = color;
    paintbuf.buf_start = workbuf;
    paintbuf.buf_end = workbuf + sizeof (workbuf);

    /* 塗り潰し */
    _iocs_paint (&paintbuf);
}

static __inline void _palet (int_ no, int_ color)
{
    /* パレット設定 */
    _iocs_gpalet (no, color);
}

static __inline void _pset (int_ x, int_ y, int_ color)
{
    struct _psetptr psetbuf;

    /* パラメータをセット */
    psetbuf.x = x;
    psetbuf.y = y;
    psetbuf.color = color;

    /* 点を描画 */
    _iocs_pset (&psetbuf);
}

static __inline void
_put (int_ x1, int_ y1, int_ x2, int_ y2, const void *buf, int_ size)
{
    struct _putptr putbuf;

    /* パラメータをセット */
    putbuf.x1 = x1;
    putbuf.y1 = y1;
    putbuf.x2 = x2;
    putbuf.y2 = y2;
    putbuf.buf_start = buf;
    putbuf.buf_end = (void *) ((int_) buf + size);

    /* GVRAM に書き込み */
    _iocs_putgrm (&putbuf);
}

static __inline void _symbol (int_ x1, int_ y1, const char *str, char mag_x,
				char mag_y, int_ font_type, int_ color, int_ angle)
{
    struct _symbolptr symbolbuf;

    /* パラメータをセット */
    symbolbuf.x1 = x1;
    symbolbuf.y1 = y1;
    symbolbuf.string_address = (unsigned char *) str;
    symbolbuf.mag_x = mag_x;
    symbolbuf.mag_y = mag_y;
    symbolbuf.color = color;
    symbolbuf.font_type = font_type;
    symbolbuf.angle = angle;

    /* エラーチェック */
    if (font_type < 0 || font_type > 2 || angle < 0 || angle > 3)
	return;

    /* 文字列を描画 */
    _iocs_symbol (&symbolbuf);
}

static __inline void _vpage (char mode)
{
    /* 表示ページを設定 */
    _iocs_vpage ((unsigned char) mode);
}

static __inline void _window (int_ sx, int_ sy, int_ ex, int_ ey)
{
    /* 描画範囲を設定 */
    _iocs_window (sx, sy, ex, ey);
}

static __inline void _wipe (void_)
{
    /* 画面を消去 */
    _iocs_wipe ();
}

#define hsv		_hsv
#define point		_point
#define rgb		_rgb
#define apage		_apage
#define box		_box
#define circle		_circle
#define contrast	_contrast
#define fill		_fill
#define get		_get
#define home		_home
#define line		_line
#define paint		_paint
#define palet		_palet
#define pset		_pset
#define put		_put
#define symbol		_symbol
#define vpage		_vpage
#define window		_window
#define wipe		_wipe

#endif
