/*******************************************
 *   FM-Towns VRAM access library : vram   *
 *         Program made by K,Ajima         *
 *      Copyright  ajiyan soft l.t.d.      *
 *******************************************/



/*** vram ****************************************************************

  Ｒｅａｌ−ＴＶＲＡＭ・ＧＶＲＡＭ  にアクセスするライブラリです。

ｉｎｖｒｍ＿ｘｘｘｘｘ（）		：  インライン関数
ｖｒｍ＿ｘｘｘｘｘ（）			：  ＶＲＡＭ  メイン関数
ｅｖｒｍ＿ｘｘｘｘｘ（）		：  高レベル関数

**************************************************************************/



									/* 文字アトリビュート */
#define VRM_ATR_WORD_2	0x80			/* WORD 文字 2バイト目 */
#define VRM_ATR_WORD_1	0x40			/* WORD 文字 1バイト目 */
#define VRM_ATR_I		0x20			/* IRGB I */
#define VRM_ATR_BLINK	0x10			/* ブリンク */
#define VRM_ATR_REVERSE	0x08			/* リバース */
#define VRM_ATR_G		0x04			/* IRGB G */
#define VRM_ATR_R		0x02			/* IRGB R */
#define VRM_ATR_B		0x01			/* IRGB B */



/********************************************************************
 *
 *		vrm_xxxxx() 関数群
 *
 *
 *
 *
 *




/********************************************************************
 *	TVRAM へアトリビュート設定
 *		1. x (0-79)
 *		2. y (0-24)
 *		3. アトリビュート
 ********************************************************************/
void _fastcall vrm_set_atr(int vrm_x,int vrm_y,int vrm_attrib)
{
	*(char _far *)( 0xc8000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) +1L ) =
		(char)vrm_attrib;
}



/********************************************************************
 *	TVRAM へ半角文字設定
 *		1. x (0-79)
 *		2. y (0-24)
 *		3. ASCII コード
 ********************************************************************/
void _cdecl vrm_setc(int vrm_x,int vrm_y,int vrm_code)
{
	*(char _far *)( 0xc8000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) ) =
		(char)vrm_code;
}



/********************************************************************
 *	TVRAM へ WORD 文字設定
 *		1. x (0-79)
 *		2. y (0-24)
 *		3. JIS コード
 *		4. アトリビュート
 ********************************************************************/
void _fastcall vrm_setw(int vrm_x,int vrm_y,int vrm_code)
{
	*(int _far *)( 0xca000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) ) =
		(vrm_code>>8) | ( (vrm_code<<8) & 0xff00 );
}



/********************************************************************
 *	TVRAM へ半角文字を書く
 *		1. x (0-79)
 *		2. y (0-24)
 *		3. ASCII コード
 *		4. アトリビュート
 ********************************************************************/
void _cdecl vrm_putc(int vrm_x,int vrm_y,int vrm_code,int vrm_attrib)
{
	*(int _far *)( 0xc8000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) ) =
		vrm_code | (vrm_attrib<<8);
}



/********************************************************************
 *	TVRAM へ WORD 文字を書く
 *		1. x (0-79)
 *		2. y (0-24)
 *		3. JIS コード
 *		4. アトリビュート
 ********************************************************************/
void _fastcall vrm_putw(int vrm_x,int vrm_y,int vrm_code,int vrm_attrib)
{
	*(char _far *)( 0xc8000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) +1L ) =
		(char)( vrm_attrib | 0x40 );

	*(char _far *)( 0xc8000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) +3L ) =
		(char)( vrm_attrib | 0x80 );

	*(int  _far *)( 0xca000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) ) =
		(vrm_code>>8) | ( (vrm_code<<8) & 0xff00 );
}



/********************************************************************
 *	TVRAM アトリビュート取得
 *		1. x (0-79)
 *		2. y (0-24)
 *		ret: アトリビュート
 ********************************************************************/
int _fastcall vrm_get_atr(int vrm_x,int vrm_y)
{
	return(*(unsigned char _far *)( 0xc8000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) +1L ));
}



/********************************************************************
 *	TVRAM 半角文字取得
 *		1. x (0-79)
 *		2. y (0-24)
 *		ret: ASCII コード
 ********************************************************************/
char _fastcall vrm_getc(int vrm_x,int vrm_y)
{
	return(*(char _far *)( 0xc8000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) ));
}



/********************************************************************
 *	TVRAM WORD 文字取得
 *		1. x (0-79)
 *		2. y (0-24)
 *		ret: JIS コード
 ********************************************************************/
int _fastcall vrm_getw(int vrm_x,int vrm_y)
{
	return(*(int _far *)( 0xca000000L | (long)( (vrm_x<<1) + (vrm_y*0xa0) ) ));
}



/********************************************************************
 *	TVRAM 保存
 *		1. 保存先アドレス( Need 25*80*2 bytes )
 ********************************************************************/
void _fastcall vrm_save_vram(char * vrm_buff)
{
	int x;

	for(x=0;x<25*80;x++) {
		vrm_buff[(x<<1)+1]=*(char _far *)( 0xc8000000L | (long)(x<<1) +1L );
		switch((unsigned char)vrm_buff[(x<<1)+1]>>6) {
			case 0:
				vrm_buff[x<<1]=
					*(char _far *)( 0xc8000000L | (long)(x<<1) );
				break;

			case 1:
				vrm_buff[x<<1]=
					*(char _far *)( 0xca000000L | (long)(x<<1) );
				break;

			case 2:
				vrm_buff[x<<1]=
					*(char _far *)( 0xca000000L | (long)(x<<1) -1L );
				break;
		}
	}
}



/********************************************************************
 *	TVRAM 復元
 *		1. 復元もとアドレス( Need 25*80*2 bytes )
 ********************************************************************/
void _fastcall vrm_restore_vram(char * vrm_buff)
{
	int x;

	for(x=0;x<25*80;x++) {
		*(char _far *)( 0xc8000000L | (long)(x<<1) +1L )=vrm_buff[(x<<1)+1];
		switch((unsigned char)vrm_buff[(x<<1)+1]>>6) {
			case 0:
				*(char _far *)( 0xc8000000L | (long)(x<<1) )=
					vrm_buff[x<<1];
				break;

			case 1:
				*(char _far *)( 0xca000000L | (long)(x<<1) )=
					vrm_buff[x<<1];
				break;

			case 2:
				*(char _far *)( 0xca000000L | (long)(x<<1) -1L )=
					vrm_buff[x<<1];
				break;
		}
	}
}



/********************************************************************
 *	TVRAM 矩形領域保存
 *		1. x1 左上
 *		2. y1
 *		3. x2 右下
 *		4. y2
 *		5. 保存先アドレス ( Need (x2-x1+1)*(y2-y1+1)*2 bytes )
 ********************************************************************/
void _fastcall vrm_save_vram_box(
					int vrm_x1,
					int vrm_y1,
					int vrm_x2,
					int vrm_y2,
					char * vrm_buff)
{
	int x,y,s;

	s=vrm_x2-vrm_x1+1;
	for(y=0;y<=vrm_y2-vrm_y1;y++) {
		for(x=0;x<=vrm_x2-vrm_x1;x++) {
			vrm_buff[(x<<1)+1]=
				*(char _far *)( 0xc8000000L | (long)( ((x+vrm_x1)<<1) + ((y+vrm_y1)*0xa0) ) +1L );
			switch((unsigned char)vrm_buff[(x<<1)+1]>>6) {
				case 0:
					vrm_buff[x<<1]=
						*(char _far *)( 0xc8000000L | (long)( ((x+vrm_x1)<<1) + ((y+vrm_y1)*0xa0) ) );
					break;

				case 1:
					vrm_buff[x<<1]=
						*(char _far *)( 0xca000000L | (long)( ((x+vrm_x1)<<1) + ((y+vrm_y1)*0xa0) ) );
					break;

				case 2:
					vrm_buff[x<<1]=
						*(char _far *)( 0xca000000L | (long)(x<<1) -1L );
					break;
			}
		}
	}
}



/********************************************************************
 *	TVRAM 矩形領域復元
 *		1. x1 左上
 *		2. y1
 *		3. x2 右下
 *		4. y2
 *		5. 復元もとアドレス ( Need (x2-x1+1)*(y2-y1+1)*2 bytes )
 ********************************************************************/
void _fastcall vrm_restore_vram_box(
					int vrm_x1,
					int vrm_y1,
					int vrm_x2,
					int vrm_y2,
					char * vrm_buff)
{
	int x,y,s;

	s=vrm_x2-vrm_x1+1;
	for(y=0;y<=vrm_y2-vrm_y1;y++) {
		for(x=0;x<=vrm_x2-vrm_x1;x++) {
			*(char _far *)( 0xc8000000L | (long)( ((x+vrm_x1)<<1) + ((y+vrm_y1)*0xa0) ) +1L )=
				vrm_buff[(x<<1)+1];
			switch((unsigned char)vrm_buff[(x<<1)+1]>>6) {
				case 0:
					*(char _far *)( 0xc8000000L | (long)( ((x+vrm_x1)<<1) + ((y+vrm_y1)*0xa0) ) )=
						vrm_buff[x<<1];
					break;

				case 1:
					*(char _far *)( 0xca000000L | (long)( ((x+vrm_x1)<<1) + ((y+vrm_y1)*0xa0) ) )=
						vrm_buff[x<<1];
					break;

				case 2:
					*(char _far *)( 0xca000000L | (long)(x<<1) -1L )=
						vrm_buff[x<<1];
					break;
			}
		}
	}
}



/********************************************************************
 *	TVRAM 複写
 *		1. x1 左上
 *		2. y1
 *		3. x2 右下
 *		4. y2
 *		5. x3 移動先左上
 *		6. y3
 ********************************************************************/
void _fastcall vrm_copy_vram_box(
					int vrm_x1,
					int vrm_y1,
					int vrm_x2,
					int vrm_y2,
					int vrm_x3,
					int vrm_y3)
{
	int x,y,										/* カウンタ(移動先座標) */
		mx=vrm_x3-vrm_x1,							/* 移動量 */
		my=vrm_y3-vrm_y1,
		cx=( vrm_x1>vrm_x3 ? 1 : -1 ),				/* カウンタ加算値 */
		cy=( vrm_y1>vrm_y3 ? 1 : -1 ),
		sx=( cx==1 ? vrm_x1 : vrm_x2 )+mx,			/* カウンタ初期値 */
		sy=( cy==1 ? vrm_y1 : vrm_y2 )+my,
		ex=( cx==1 ? vrm_x2+1 : vrm_x1-1 )+mx,		/* カウンタ終了値 */
		ey=( cy==1 ? vrm_y2+1 : vrm_y1-1 )+my;

	sx=( sx<0 ? 0 : sx );	sx=( sx>79 ? 79 : sx );
	sy=( sy<0 ? 0 : sy );	sy=( sy>24 ? 24 : sy );

	ex=( ex<0 ? 0 : ex );	ex=( ex>79 ? 79 : ex );
	ey=( ey<0 ? 0 : ey );	ey=( ey>24 ? 24 : ey );

	for(y=sx;y!=ey;y+=cy) {
		for(x=sy;x!=ex;x+=cx) {
			*(int _far *)( 0xc8000000L | (long)( (x<<1) + (y*0xa0) ) )=
				*(int _far *)( 0xc8000000L | (long)( ((x-mx)<<1) + ((y-my)*0xa0) ) );
			*(int _far *)( 0xca000000L | (long)( (x<<1) + (y*0xa0) ) )=
				*(int _far *)( 0xca000000L | (long)( ((x-mx)<<1) + ((y-my)*0xa0) ) );
		}
	}
}



