SCREEN.C

[目次 | 関数 | マクロ]

目次

関数一覧

マクロ一覧


   1|/************************************************************************
   2|*  1. <<< 画面・ワーク画面 (Screen) >>> 
   3|*************************************************************************/
   4|
   5|#include  <screen.ah>  /* Auto include header, Look at mixer-... folder */
   6|
   7| 
   8|/*-------------------------------------------------------------------*/
   9|/*  2. <<< ◆基本設定 >>>                                               */ 
  10|/*-------------------------------------------------------------------*/
  11|
  12|/*********************************************************************
  13|*  3. <<< 初期化する [Screen_init()] >>>
  14|*【引数】
  15|*  ・void*  adr;         バッファまたは VRAM の先頭アドレス
  16|*  ・int width, height;  画面のサイズ
  17|*【補足】
  18|*・adr のバッファに必要なサイズは、width * height / 2 です。
  19|*********************************************************************/
  20|void  Screen_init( Screen* m, void* adr, int width, int height )
  21|{
  22|  m->adr = (char*)adr;
  23|  m->width = width;      m->height = height;
  24|  m->offsetX = 0;        m->offsetY = 0;
  25|  m->clipX = 0;          m->clipY = 0;
  26|  m->clipWidth = width;  m->clipHeight = height;
  27|}
  28|
  29|
  30|/*********************************************************************
  31|*  4. <<< 画面全体を指定の色 color でクリアする [Screen_clear()] >>>
  32|*********************************************************************/
  33|void  Screen_clear( Screen* m, int color )
  34|{
  35|  int  i;
  36|  int*  p = (int*)Screen_getAdr(m);
  37|
  38|  color = (color << 4 ) | color;
  39|  color = (color << 8 ) | color;
  40|  color = (color << 16) | color;
  41|
  42|  for ( i = 0; i < Screen_getWidth(m) * Screen_getHeight(m)
  43|                   / Screen_getPixelPerByte(m) / (int)sizeof(int);
  44|      i++ ) {
  45|    *p = color;  p++;
  46|  }
  47|}
  48|
  49|
  50|/*********************************************************************
  51|*  5. <<< クリッピング領域を設定する [Screen_setClip()] >>>
  52|**********************************************************************/
  53|void  Screen_setClip( Screen* m, int x, int y, int w, int h )
  54|{
  55|  #ifdef _CHECKER
  56|    if ( x < 0 || x >= m->width )  error();
  57|    if ( y < 0 || y >= m->height ) error();
  58|    if ( w < 0 || x + w > m->width )  error();
  59|    if ( h < 0 || y + h > m->height ) error();
  60|  #endif
  61|
  62|  m->clipX = x;      m->clipY = y;
  63|  m->clipWidth = w;  m->clipHeight = h;
  64|}
  65|
  66|
  67|/*********************************************************************
  68|*  6. <<< クリッピングを解除する [Screen_clearClip()] >>>
  69|**********************************************************************/
  70|void  Screen_clearClip( Screen* m )
  71|{
  72|  m->clipX = 0;
  73|  m->clipY = 0;
  74|  m->clipWidth = m->width;
  75|  m->clipHeight = m->height;
  76|}
  77|
  78|
  79|#ifdef USES_TYPES
  80|/*************************************************************************
  81|*  7. <<< 拡張座標値を取得する [Screen_getExAdr()] >>>
  82|*【補足】
  83|*・「拡張座標値」は、ベクトルの和とピクセル描画が高速になるように最適化
  84|*  された x,y 座標値です。
  85|*・拡張座標値は、1つの int 型から構成され、
  86|*  第5ビット以上が、アドレス部、第4ビット以下が、ビット番号部です。
  87|*・32bit = [0123|4567|89AB|CDEF|0123|4567|89AB|CDEF] 4bpp * 8pixels 用です
  88|**************************************************************************/
  89|u_long  Screen_getExAdr( Screen* m, int x, int y )
  90|{
  91|  u_long  adr, adr0;
  92|
  93|  adr = (u_long)(int)Screen_pgetAdr( m, x, y );
  94|  adr0 = (u_long)(int)m->adr;
  95|
  96|  return  ( ((adr - adr0) & 0xFFFFFFFC) << 3 ) | ( (u_long)(x & 0x7) << 2 );
  97|}
  98|#endif /* USES_TYPES */
  99|
 100|
 101|#ifdef USES_TYPES
 102|/*************************************************************************
 103|*  8. <<< 拡張ベクトル値を取得する [Screen_getExVector()] >>>
 104|*【引数】
 105|*  ・u_long  dx, dy;  ベクトルの x,y 成分
 106|*【補足】
 107|*・「拡張ベクトル値」は、次のような性質があります。
 108|*  (x,y)=(100,100) の拡張座標値に、(dx,dy)=(1,-1)の拡張ベクトル値を足すと、
 109|*  (x,y)=(101,99) の拡張座標値を返します。
 110|**************************************************************************/
 111|u_long  Screen_getExVector( Screen* m, int dx, int dy )
 112|{
 113|  return  Screen_getExAdr( m, dx, dy );
 114|}
 115|#endif /* USES_TYPES */
 116|
 117|
 118|#ifdef USES_TYPES
 119|/*************************************************************************
 120|*  9. <<< Draw_line2 用の拡張ベクトル値を取得する [Screen_getExVectors()] >>>
 121|*【引数】
 122|*  ・int   dir;    方向番号
 123|*  ・u_long*  plus0;  水平 or 垂直の拡張ベクトル値(出力)
 124|*  ・u_long*  plus1;  ななめの拡張ベクトル値(出力)
 125|*【補足】
 126|*・方向番号は Draw_getDirec 関数から取得できます。
 127|**************************************************************************/
 128|void  Screen_getExVectors( Screen* m, int dir, u_long* plus0,
 129|  u_long* plus1 )
 130|{
 131|  const int  dxy[] =
 132|    {  1,0, 1,-1,   1,0, 1, 1,   0, 1, 1, 1,   0, 1,-1, 1,
 133|      -1,0,-1, 1,  -1,0,-1,-1,   0,-1,-1,-1,   0,-1, 1,-1 };
 134|
 135|  dir <<= 2;  /* dir *= 4 */
 136|  *plus0 = Screen_getExVector( m, dxy[dir], dxy[dir+1] );
 137|  *plus1 = Screen_getExVector( m, dxy[dir+2], dxy[dir+3] );
 138|}
 139|#endif /* USES_TYPES */
 140|
 141|
 142| 
 143|/*-------------------------------------------------------------------*/
 144|/*  10. <<< ◆描画操作 >>>                                               */ 
 145|/*-------------------------------------------------------------------*/
 146|
 147|/**********************************************************************
 148|*  11. <<< (x,y) の位置に点を打つ [Screen_pset()] >>>
 149|*【補足】
 150|*・クリッピング処理があります。(x,y)がクリッピング領域外の場合、点を
 151|*  描きません。
 152|***********************************************************************/
 153|void  Screen_pset( Screen* m, int x, int y, int color )
 154|{
 155|  unsigned char*  p;
 156|
 157|  /* オフセット */
 158|  x += Screen_getOffsetX(m);
 159|  y += Screen_getOffsetY(m);
 160|
 161|  if ( x < m->clipX || x >= m->clipX + m->clipWidth ||
 162|       y < m->clipY || y >= m->clipY + m->clipHeight )
 163|    return;
 164|
 165|  p = (unsigned char*)Screen_getAdr(m) +
 166|       ( Screen_getWidth(m) * y + x )
 167|       / Screen_getPixelPerByte(m);
 168|
 169|  if ( Screen_getPixelPerByte(m) == 2 ) {
 170|    if ( (x & 1) == 0 ) {
 171|      *p = (*p & 0xF0) | color;
 172|    }
 173|    else {
 174|      *p = (*p & 0x0F) | (color << 4);
 175|    }
 176|  }
 177|  #ifdef _CHECKER
 178|  else if ( Screen_getPixelPerByte(m) != 8 )
 179|      error();
 180|  #endif
 181|  else {   /* Screen_getPixelPerByte(m) == 8 */
 182|    if ( ! color )
 183|      *p = *p & ( 0xFF7F >> ( x & 0x07 ) );
 184|    else
 185|      *p = *p | ( 0x80 >> ( x & 0x07 ) );
 186|  }
 187|}
 188|
 189|
 190|/***********************************************************************
 191|*  12. <<< アクティブ画面の (x,y) の位置の点の色を返す [Screen_pget()] >>>
 192|*【補足】
 193|*・色(パレット・コード)を返します。
 194|*・座標は、オフセット属性に影響します。
 195|*・点の位置が画面の外の場合、0 を返します。
 196|************************************************************************/
 197|int  Screen_pget( Screen* m, int x, int y )
 198|{
 199|  unsigned char*  p;
 200|
 201|  /* x,y にオフセットを加える */
 202|  x += Screen_getOffsetX(m);
 203|  y += Screen_getOffsetY(m);
 204|
 205|  /* もし、x,y が画面の外なら、0 を返す */
 206|  if ( x < 0 || x >= Screen_getWidth(m) ||
 207|       y < 0 || y >= Screen_getHeight(m) )
 208|    return 0;
 209|
 210|  /* アクティブ画面の x,y の位置のアドレス p を取得する */
 211|  p = (unsigned char*)Screen_getAdr(m) +
 212|       ( Screen_getWidth(m) * y + x )
 213|       / Screen_getPixelPerByte(m);
 214|
 215|  /* パレット・コードを返す(4bpp の場合) */
 216|  if ( Screen_getPixelPerByte(m) == 2 ) {
 217|    if ( (x & 1) == 0 ) {
 218|      return  *p & 0x0F;
 219|    }
 220|    else {
 221|      return  *p >> 4;
 222|    }
 223|  }
 224|  #ifdef _CHECKER
 225|  else
 226|      error();
 227|  #endif
 228|  return  0;
 229|}
 230|
 231|
 232|/***********************************************************************
 233|*  13. <<< XOR 演算して点を描く [Screen_psetXor()] >>>
 234|*【補足】
 235|*・クリッピング処理があります。ただし、x 座標が領域外の場合、点を描き
 236|*  ませんが、y 座標が領域外の場合、その領域の境界に描きます。
 237|***********************************************************************/
 238|void  Screen_psetXor( Screen* m, int x, int y, int color )
 239|{
 240|  char*  p;
 241|
 242|  /* オフセット */
 243|  x += Screen_getOffsetX(m);
 244|  y += Screen_getOffsetY(m);
 245|
 246|  /* クリッピング */
 247|  if ( x < m->clipX || x >= m->clipX + m->clipWidth )  return;
 248|
 249|  if ( y < m->clipY )  y = m->clipY;
 250|  if ( y >= m->clipY + m->clipHeight )
 251|    y = m->clipY + m->clipHeight - 1;
 252|
 253|  p = Screen_getAdr(m) +
 254|       ( Screen_getWidth(m) * y + x )
 255|       / Screen_getPixelPerByte(m);
 256|
 257|  #ifdef _CHECKER
 258|    if ( Screen_getPixelPerByte(m) != 2 )
 259|      error();
 260|  #endif
 261|  if ( (x & 1) == 0 ) {
 262|    *p = *p ^ color;
 263|  }
 264|  else {
 265|    *p = *p ^ ( color << 4 );
 266|  }
 267|}
 268|
 269|
 270|#ifdef  USES_MASK
 271|/************************************************************************
 272|*  14. <<< 数ピクセル描画する [Screen_psets()] >>>
 273|*【引数】
 274|*  ・unsigned char*  pattern;  ピクセル・パターンが格納されているアドレス
 275|*  ・int  nPixel;              ピクセル数
 276|*【機能】
 277|*・x,y から水平右方向に、数ピクセルのピクセル・パターンを描画します。
 278|*【補足】
 279|*・UNIT32(32ビット整数)の代入を用いて高速に処理します。
 280|*・ピクセル・パターンは、下位ビット→上位ビットが左→右のピクセルに対応
 281|*  します。ピクセル・パターンは、1bpp です。
 282|*・ピクセル・パターン中のビットが0の位置に相当するピクセルの色は、
 283|*  変化しません。透明色に相当します。
 284|*・たとえば、文字を描くときに使うことができます。
 285|*・4bpp 専用です。
 286|*・クリッピングは無効です。
 287|************************************************************************/
 288|void  Screen_psets( Screen* m, int x, int y, unsigned char* pattern,
 289|  int nPixel, int color )
 290|{
 291|  u_long*  p = (u_long*)Screen_pgetAdr( m, x, y );
 292|  u_long   inMask, outMask, overMask;
 293|  unsigned char*  pattern_over;
 294|  #ifdef _32BIT
 295|    int  sft = (x & 0x07) << 2;  /* シフト数、x/2 の余り×4 (32bitの余り) */
 296|  #endif
 297|  #ifdef _16BIT
 298|    int  sft = (x & 0x01) << 2;  /* シフト数、x/2 の余り×4 (8bitの余り) */
 299|  #endif
 300|
 301|  #ifdef _CHECKER
 302|    if ( nPixel % 8 != 0 || nPixel < 8 )  error();
 303|    if ( Screen_getBitPerPixel(m) != 4 )  error();
 304|    if ( x < 0 || x + nPixel > m->width )  error();
 305|    if ( y < 0 || y >= m->height )  error();
 306|  #endif
 307|
 308|  overMask = 0;
 309|
 310|  /* (nPixel/8) 回だけ 32bit コピーする */
 311|  pattern_over = pattern + (nPixel/8);
 312|  for ( pattern ; pattern < pattern_over; pattern ++ ) {
 313|
 314|    inMask = Mask_bpp1to4[*pattern];
 315|    outMask = (inMask << sft) | overMask;  /* 左シフトでピクセルは右へ */
 316|    *p = ( ( Mask_colors16[color] & outMask ) | ( ~outMask & *p ) );
 317|
 318|    overMask = IntX_shr( inMask, 32-sft );
 319|    p++;
 320|  }
 321|
 322|  /* あふれた分の 32bit コピーをする */
 323|  *p = ( ( Mask_colors16[color] & overMask ) | ( ~overMask & *p ) );
 324|}
 325|#endif  /* USES_MASK */
 326|
 327|
 328|#ifdef USES_TYPES
 329|/*************************************************************************
 330|*  15. <<< 点を描画する(拡張座標値版)[Screen_exPset()] >>>
 331|*【補足】
 332|*・拡張座標値を用いることにより高速に描画します。
 333|*・オフセットとクリッピング領域は、無視されます。
 334|**************************************************************************/
 335|void  Screen_exPset( Screen* m, u_long exAdr, int color )
 336|{
 337|  u_long* adr = Screen_pgetAdr_byExAdr( m, exAdr );
 338|
 339|  #ifdef _CHECKER
 340|    if ( adr < (u_long*)m->adr )  error();
 341|    if ( adr >=(u_long*)Screen_pgetAdr( m, m->width, m->height ) )  error();
 342|  #endif
 343|
 344|  *adr &= ~Screen_getBit_byExAdr( m, exAdr, 0xF );
 345|  *adr |= Screen_getBit_byExAdr( m, exAdr, color );
 346|}
 347|#endif /* USES_TYPES */
 348|
 349|
 350|#ifdef _32BIT
 351|#define  _Screen_line
 352|#include "screen.cc"
 353|#undef   _Screen_line
 354|#endif  /* _32BIT */
 355|
 356|#ifdef _32BIT
 357|#define  _Screen_line2
 358|#include "screen.cc"
 359|#undef   _Screen_line2
 360|#endif  /* _32BIT */
 361|
 362|#ifdef _32BIT
 363|/*
 364|#define  _Screen_loseLine
 365|#include "screen.cc"
 366|#undef   _Screen_loseLine
 367|*/
 368|#endif  /* _32BIT */
 369|
 370| 
 371|#ifdef USES_MASK
 372|#ifdef _32BIT
 373|/************************************************************************
 374|*  16. <<< [Screen_boldLine] 太線を描画する >>> 
 375|*【バグ】
 376|*・太線の垂直に太いと上にずれる
 377|*・太線の右端が 1ピクセル余分に太い
 378|*・水平に太い場合、クリッピングできない
 379|*【内部補足】
 380|*・太線がクリッピング領域の境界に触れない場合、高速になります
 381|*・水平に太い(垂直に近い)太線の場合、マスクを利用した塗りつぶしをしています。
 382|*  (このアルゴリズムは、水平線の高速描画にも用いることが出来ます)
 383|*
 384|*【内部補足・水平に太い太線の塗りつぶし方】
 385|*  次のマスクパターンが用意されているとします。ただし、4bpp の場合で説明します。
 386|*    penMask[0] 0x00000000
 387|*    penMask[1] 0x0000000F
 388|*    penMask[2] 0x000000FF
 389|*    penMask[3] 0x00000FFF
 390|*            :      :
 391|*    penMask[8] 0xFFFFFFFF
 392|*
 393|*  この penMask を使用すると、水平線は次の式で描画されます。
 394|*    xm = x % 8;
 395|*    fst : (penMask[width] & colorMask[color]) << xm    ... xm=1..8
 396|*    mid : 0xFFFFFFFF & colorMask[color]
 397|*    lst : (penMask[width] & colorMask[color]) >> (8-xm)  ... (8-xm)=0..7
 398|*
 399|*  fst は左端を含むワード、mid は fst と lst の間、lst は右端を含むワードを
 400|*  意味します。(下の表を参考)
 401|*  つまり、左端と右端は、penMask で塗りつぶし、その間は 0xFFFFFFFF で
 402|*  塗りつぶします。
 403|*
 404|*  width(太さ)と mid のワード数の関係は次の通りです。
 405|*
 406|*  width   min pixels sample      max pixels sample  mid_min〜mid_max
 407|*  -------------------------------------------------------------------
 408|*    8    |FFFFFFFF|              F|LLLLLLL                0
 409|*    9    |FFFFFFFF|L             F|MMMMMMMM               0〜1
 410|*   10    |FFFFFFFF|LL            F|MMMMMMMM|L             0〜1
 411|*   15    |FFFFFFFF|LLLLLLL |     F|MMMMMMMM|LLLLLL  |     0〜1
 412|*   16    |FFFFFFFF|MMMMMMMM|     F|MMMMMMMM|LLLLLLL |     1
 413|*   17    |FFFFFFFF|MMMMMMMM|L    F|MMMMMMMM|MMMMMMMM|     1〜2
 414|*   18    |FFFFFFFF|MMMMMMMM|LL   F|MMMMMMMM|MMMMMMMM|L    1〜2
 415|*       xm:01234567 01234567 01     7 01234567 01234567 0
 416|*   注:F=fstワードのピクセル, M=midワードのピクセル, L=lstワードのピクセル
 417|*
 418|*  X 座標と mid のワード数の関係は次の通りです。
 419|*
 420|*  width=11, width%8=3
 421|*         sample              mid  xm+wm
 422|*  -------------------------------------------------
 423|*    |FFFFFFFF|LLL     |       0     3
 424|*    | FFFFFFF|LLLL    |       0     4
 425|*    |  FFFFFF|LLLLL   |       0     5
 426|*    |   FFFFF|LLLLLL  |       0     6
 427|*    |    FFFF|LLLLLLL |       0     7
 428|*    |     FFF|MMMMMMMM|       1     8  (xm+wm>=8)
 429|*    |      FF|MMMMMMMM|L      1     9
 430|*    |       F|MMMMMMMM|LL     1    10
 431|*  xm:01234567 01234567 01
 432|*
 433|*  まとめると、ワード数は次の式で求まります。
 434|*    ワード数 = (width/8 - 1) + ((x%8)+(width%8)>=8 ? 1 : 0)
 435|*************************************************************************/
 436|void  Screen_boldLine( Screen* m, int x1, int y1, int x2, int y2,
 437|  int color, int width )
 438|#define  Screen_CLIP_X
 439|{
 440|  /* 太線描画系・共通の変数 */
 441|  register int  exAdr;        /* 拡張座標値(x+y*width) */
 442|  register int  exAdr_plus0;  /* 水平垂直差分 */
 443|  register int  exAdr_plus1;  /* ナナメ差分 */
 444|
 445|  register int  cup, plus, minus;  /* Bresenham のアルゴリズムの3変数 */
 446|  register int  count;             /* 残りピクセル数 - 1 */
 447|
 448|  register int  topAdr;            /* VRAM の先頭アドレス */
 449|  register char*  adr;             /* 描画する VRAM のアドレス */
 450|  register char*  endAdr;          /* 描画を終了する VRAM のアドレス */
 451|  register int  bottomAdr;         /* 1行下のアドレス差 */
 452|
 453|  register int  penMask;
 454|  register int  colorMask;
 455|  register int  xm;
 456|
 457|  int  dx,dy;
 458|  int  horiBold;
 459|
 460|  /* クリッピング処理用の変数 */
 461|  #ifdef Screen_CLIP_X
 462|    register int  x /*, y*/ ;        /* 現在位置 (クリッピング用) */
 463|    register int  plus0x /*, plus0y */;    /* 水平垂直差分 */
 464|    register int  plus1x /*, plus1y */;    /* ナナメ差分 */
 465|
 466|    register int  notNeedClip; /* ピクセルごとにクリッピング判定が不要か */
 467|    register int  clipX1;
 468|    register int  clipX2;
 469|    register int  clipExAdr1; /* Y 座標判定用 */
 470|    register int  clipExAdr2;
 471|  #endif
 472|
 473|  /* 破線用の変数 */
 474|  #ifdef _Screen_loseLine
 475|    register int patternWork;    /* 最上位ビット(b31)を描画する */
 476|    register int patternWork_i;  /* 満n周するまでの残りビット数 */
 477|  #endif
 478|
 479|  /* 動作条件チェック */
 480|  #ifdef _CHECKER
 481|    if ( Screen_getPixelPerByte(m) != 2 )  error();
 482|    if ( color & 0xFFFFFFF0 )  error();
 483|    #ifdef _Screen_loseLine
 484|      #ifdef _32BIT
 485|        if ( pattern_n > 32 )  error();
 486|      #endif
 487|      #ifdef _16BIT
 488|        #error  need 32BIT (Mask)
 489|        if ( pattern_n > 16 )  error();
 490|      #endif
 491|    #endif
 492|  #endif
 493|
 494|  /* 初期化(1)・ライン描画系・共通 */
 495|  #ifdef Screen_CLIP_X
 496|    x = x1;  /* y = y1;*/
 497|  #endif
 498|  /*exAdr = y1 * m->width + x1;*/
 499|  topAdr = (int)m->adr;
 500|  penMask = ( width >= 8 ) ? Mask_rightEnd_for4bpp[7]
 501|                           : Mask_rightEnd_for4bpp[width-1];
 502|  colorMask = Mask_colors16[color];
 503|
 504|  /* 初期化(2)・クリッピング処理用 */
 505|  #ifdef Screen_CLIP_X
 506|  {
 507|    int  clipY1 = m->clipY;
 508|    int  clipY2 = m->clipY + m->clipHeight;
 509|
 510|    clipX1 = m->clipX;
 511|    clipX2 = m->clipX + m->clipWidth;
 512|    clipExAdr1 = m->clipY * m->width;
 513|    clipExAdr2 = (m->clipY + m->clipHeight) * m->width;
 514|    notNeedClip =
 515|      ( x1 >= clipX1 && x1 < clipX2 && y1 >= clipY1 && y1 < clipY2 &&
 516|        x2 >= clipX1 && x2 < clipX2 && y2 >= clipY1 && y2 < clipY2 );
 517|  }
 518|  #endif
 519|
 520|  /* 初期化(3)・破線用 */
 521|  #ifdef _Screen_loseLine
 522|    #ifdef _32BIT
 523|      pattern = pattern << (32 - pattern_n);  /* 初期値 */
 524|    #endif
 525|    #ifdef _16BIT
 526|      pattern = pattern << (16 - pattern_n);  /* 初期値 */
 527|    #endif
 528|    patternWork = pattern;
 529|    patternWork_i = pattern_n;
 530|  #endif
 531|
 532|  /* 初期化(4)・角度によって各種変数を設定する */
 533|  dx = x2 - x1;
 534|  dy = y2 - y1;
 535|  if ( dx > 0 ) {
 536|    if ( dy > 0 ) {
 537|      #ifdef Screen_CLIP_X
 538|        plus1x = 1;  /*plus1y = 1;*/
 539|      #endif
 540|      exAdr_plus1 = m->width + 1;
 541|      if ( dx > dy ) {
 542|        #ifdef Screen_CLIP_X
 543|          plus0x = 1;  /*plus0y = 0;*/
 544|        #endif
 545|        exAdr_plus0 = 1;
 546|        plus = 2 * dy;  cup = plus - dx;  minus = cup - dx;
 547|           /* plus = 2dy,  cup = (dy % dx) * 2,  minus = -2dx */
 548|        count = dx;
 549|        horiBold = 0;  exAdr = (y1 - width/2) * m->width + x1;
 550|        bottomAdr = m->width >> 2;
 551|      }
 552|      else {
 553|        #ifdef Screen_CLIP_X
 554|          plus0x = 0;  /*plus0y = 1;*/
 555|        #endif
 556|        exAdr_plus0 = m->width;
 557|        plus = 2 * dx;  cup = plus - dy;  minus = cup - dy;
 558|        count = dy;
 559|        horiBold = 1;  exAdr = y1 * m->width + (x1 - width/2);
 560|      }
 561|    }
 562|    else {
 563|      #ifdef Screen_CLIP_X
 564|        plus1x = 1;  /*plus1y = -1;*/
 565|      #endif
 566|      exAdr_plus1 = - m->width + 1;
 567|      if ( dx > -dy ) {
 568|        #ifdef Screen_CLIP_X
 569|          plus0x = 1;  /*plus0y = 0;*/
 570|        #endif
 571|        exAdr_plus0 = 1;
 572|        plus = -2 * dy;  cup = plus - dx;  minus = cup - dx;
 573|        count = dx;
 574|        horiBold = 0;  exAdr = (y1 - width/2) * m->width + x1;
 575|        bottomAdr = m->width >> 2;
 576|      }
 577|      else {
 578|        #ifdef Screen_CLIP_X
 579|          plus0x = 0;  /*plus0y = -1;*/
 580|        #endif
 581|        exAdr_plus0 = - m->width;
 582|        plus = 2 * dx;  cup = plus + dy;  minus = cup + dy;
 583|        count = -dy;
 584|        horiBold = 1;  exAdr = y1 * m->width + (x1 - width/2);
 585|      }
 586|    }
 587|  }
 588|  else {
 589|    if ( dy > 0 ) {
 590|      #ifdef Screen_CLIP_X
 591|        plus1x = -1;  /*plus1y = 1;*/
 592|      #endif
 593|      exAdr_plus1 = m->width - 1;
 594|      if ( -dx > dy ) {
 595|        #ifdef Screen_CLIP_X
 596|          plus0x = -1;  /*plus0y = 0;*/
 597|        #endif
 598|        exAdr_plus0 = - 1;
 599|        plus = 2 * dy;  cup = plus + dx;  minus = cup + dx;
 600|        count = -dx;
 601|        horiBold = 0;  exAdr = (y1 - width/2) * m->width + x1;
 602|        bottomAdr = m->width >> 2;
 603|      }
 604|      else {
 605|        #ifdef Screen_CLIP_X
 606|          plus0x = 0;  /*plus0y = 1;*/
 607|        #endif
 608|        exAdr_plus0 = m->width;
 609|        plus = -2 * dx;  cup = plus - dy;  minus = cup - dy;
 610|        count = dy;
 611|        horiBold = 1;  exAdr = y1 * m->width + (x1 - width/2);
 612|      }
 613|    }
 614|    else {
 615|      #ifdef Screen_CLIP_X
 616|        plus1x = -1;  /*plus1y = -1;*/
 617|      #endif
 618|      exAdr_plus1 = - m->width - 1;
 619|      if ( dx < dy ) {
 620|        #ifdef Screen_CLIP_X
 621|          plus0x = -1;  /*plus0y = 0;*/
 622|        #endif
 623|        exAdr_plus0 = -1;
 624|        plus = -2 * dy;  cup = plus + dx;  minus = cup + dx;
 625|        count = -dx;
 626|        horiBold = 0;  exAdr = (y1 - width/2) * m->width + x1;
 627|        bottomAdr = m->width >> 2;
 628|      }
 629|      else {
 630|        #ifdef Screen_CLIP_X
 631|          plus0x =  0;  /*plus0y = -1;*/
 632|        #endif
 633|        exAdr_plus0 = - m->width;
 634|        plus = -2 * dx;  cup = plus + dy;  minus = cup + dy;
 635|        count = -dy;
 636|        horiBold = 1;  exAdr = y1 * m->width + (x1 - width/2);
 637|      }
 638|    }
 639|  }
 640|
 641|  /* 描画する */
 642|  if ( horiBold ) {  /* 水平に太い(垂直に近い線の)場合 */
 643|    for (;;) {
 644|
 645|      /* 破線のピクセル判定(1) */
 646|      #ifdef _Screen_loseLine
 647|        if ( patternWork & 0x80000000 ) {
 648|      #endif
 649|
 650|        /* クリッピング判定(1) */
 651|        #ifdef Screen_CLIP_X
 652|          if ( notNeedClip ||
 653|               ( x >= clipX1 && x < clipX2 &&
 654|                 exAdr >= clipExAdr1 && exAdr < clipExAdr2 ) ) {
 655|        #endif
 656|
 657|          /* 水平に太い点を打つ (for 4bpp)(内部補足を参考)★*/
 658|          /* adr は、レジスタ共有のために char* 型だが、処理的には int* 型 */
 659|          adr = (char*)(topAdr + (exAdr >> 1) & 0xFFFFFFFC);
 660|
 661|          if ( notNeedClip ) {
 662|            xm = (exAdr & 7) << 2;  /* (x % 8) * 4 */
 663|            *(int*)adr = ( (penMask & colorMask) << xm ) |    /* 左端 */
 664|                         ( ~( penMask << xm ) & *(int*)adr );
 665|            endAdr = (char*)( (int*)adr + (width>>3) +
 666|                              ((exAdr & 7) + (width & 7) >=8 ) );
 667|
 668|            if ( adr < endAdr ) {
 669|              adr = (char*)((int*)adr + 1);
 670|              while ( adr < endAdr ) {
 671|                *(int*)adr = colorMask;  /* 中間 */
 672|                adr = (char*)((int*)adr + 1);
 673|              };
 674|              xm = 28 - ( ((exAdr +width) & 7) << 2 );
 675|              *(int*)endAdr = ( (unsigned)colorMask >> xm ) |   /* 右端 */
 676|                              ( ~( 0xFFFFFFFF >> xm ) & *(int*)endAdr );
 677|            }
 678|          }
 679|          else {
 680|            #ifdef _CHECHER
 681|              error();
 682|            #endif
 683|          }
 684|
 685|        /* クリッピング判定(2) */
 686|        #ifdef Screen_CLIP_X
 687|          }
 688|        #endif
 689|
 690|      /* 破線のピクセル判定(2) */
 691|      #ifdef _Screen_loseLine
 692|        }
 693|      #endif
 694|
 695|      /* 終了判定 */
 696|      if ( count <= 0 )  break;
 697|      count --;
 698|
 699|      /* 次の座標へ ★*/
 700|      if ( cup > 0 ) {
 701|        #ifdef Screen_CLIP_X
 702|          x += plus1x;  /* y += plus1y; */
 703|        #endif
 704|        exAdr += exAdr_plus1;
 705|        cup += minus;
 706|      }
 707|      else {
 708|        #ifdef Screen_CLIP_X
 709|          x += plus0x;  /* y += plus0y; */
 710|        #endif
 711|        exAdr += exAdr_plus0;
 712|        cup += plus;
 713|      }
 714|      /* 破線のパターンを次のピクセルへ */
 715|      #ifdef _Screen_loseLine
 716|        patternWork_i --;
 717|        if ( patternWork_i == 0 ) {
 718|          patternWork = pattern;
 719|          patternWork_i = pattern_n;
 720|        }
 721|        else {
 722|          patternWork <<= 1;
 723|        }
 724|      #endif
 725|    }
 726|  }
 727|
 728|  else {  /* 垂直に太い(水平に近い線の)場合 */
 729|    /* 以下のうち、点を打つ部分以外は、水平に太い場合と全く同じ */
 730|    for (;;) {
 731|
 732|      /* 破線のピクセル判定(1) */
 733|      #ifdef _Screen_loseLine
 734|        if ( patternWork & 0x80000000 ) {
 735|      #endif
 736|
 737|        /* クリッピング判定(1) */
 738|        #ifdef Screen_CLIP_X
 739|          if ( notNeedClip ||
 740|               ( x >= clipX1 && x < clipX2 &&
 741|                 exAdr >= clipExAdr1 && exAdr < clipExAdr2 ) ) {
 742|        #endif
 743|
 744|          #if 0  /* 点を打つ基本的なアルゴリズムは次の通り */
 745|            /* 点を打つ (for 4bpp) ★*/
 746|            adr = (char*)(topAdr + (exAdr >> 1));  /* x/2 */
 747|            if ( exAdr & 1 )
 748|              *adr = (color << 4) | *adr & 0x0F;
 749|            else
 750|              *adr = (color) | *adr & 0xF0;
 751|          #endif
 752|
 753|          /* 垂直に太い点を打つ (for 4bpp) */
 754|          adr = (char*)(topAdr + (exAdr >> 1));
 755|          endAdr = adr + bottomAdr * width;
 756|          if ( notNeedClip ) {
 757|            if ( exAdr & 1 ) {
 758|              do {
 759|                *adr = (color << 4) | *adr & 0x0F;
 760|                adr += bottomAdr;
 761|              } while ( adr <= endAdr );
 762|            }
 763|            else {
 764|              do {
 765|                *adr = (color) | *adr & 0xF0;
 766|                adr += bottomAdr;
 767|              } while ( adr <= endAdr );
 768|            }
 769|          }
 770|          else {
 771|            if ( exAdr & 1 ) {
 772|              do {
 773|                if ( exAdr >= clipExAdr1 && exAdr < clipExAdr2 )
 774|                  *adr = (color << 4) | *adr & 0x0F;
 775|                adr += bottomAdr;
 776|              } while ( adr <= endAdr );
 777|            }
 778|            else {
 779|              do {
 780|                if ( exAdr >= clipExAdr1 && exAdr < clipExAdr2 )
 781|                  *adr = (color) | *adr & 0xF0;
 782|                adr += bottomAdr;
 783|              } while ( adr <= endAdr );
 784|            }
 785|          }
 786|
 787|        /* クリッピング判定(2) */
 788|        #ifdef Screen_CLIP_X
 789|        }
 790|        #endif
 791|
 792|      /* 破線のピクセル判定(2) */
 793|      #ifdef _Screen_loseLine
 794|      }
 795|      #endif
 796|
 797|      /* 終了判定 */
 798|      if ( count <= 0 )  break;
 799|      count --;
 800|
 801|      /* 次の座標へ ★*/
 802|      if ( cup > 0 ) {
 803|        #ifdef Screen_CLIP_X
 804|          x += plus1x;  /* y += plus1y; */
 805|        #endif
 806|        exAdr += exAdr_plus1;
 807|        cup += minus;
 808|      }
 809|      else {
 810|        #ifdef Screen_CLIP_X
 811|          x += plus0x;  /* y += plus0y; */
 812|        #endif
 813|        exAdr += exAdr_plus0;
 814|        cup += plus;
 815|      }
 816|      /* 破線のパターンを次のピクセルへ */
 817|      #ifdef _Screen_loseLine
 818|        patternWork_i --;
 819|        if ( patternWork_i == 0 ) {
 820|          patternWork = pattern;
 821|          patternWork_i = pattern_n;
 822|        }
 823|        else {
 824|          patternWork <<= 1;
 825|        }
 826|      #endif
 827|    }
 828|  }
 829|}
 830|#endif  /* _32BIT */
 831|#endif  /* USES_MASK */
 832|
 833|
 834| 
 835|#ifdef  USES_MASK
 836|/***********************************************************************
 837|*  17. <<< 矩形塗りつぶし(高速版)[Screen_rectFill2()] >>> 
 838|*  塗る範囲は u_long のアラインメントにそろえること。
 839|*  たとえば、Screen_getBitParPixel(to) == 4 の場合、
 840|*  if ( x < minX )  minX = ( x & 0xFFF8 );
 841|*  if ( x > maxX )  maxX = ( x & 0xFFF8 ) + 0x7;
 842|************************************************************************/
 843|void  Screen_rectFill2( Screen* m, int x1, int y1, int x2, int y2,
 844|  int color )
 845|{
 846|  int     y;
 847|  u_long  pattern;
 848|  u_long* p = (u_long*)Screen_pgetAdr( m, x1, y1 ); /*(最初に)塗る */
 849|
 850|  u_long* overP;
 851|
 852|  const int  nPixelIn_u_long =
 853|    sizeof(u_long)*8 / Screen_getBitPerPixel(to);
 854|               /* u_long 型変数の1回の代入でコピーされるピクセル数 */
 855|  const int  width = x2 - x1 + 1;
 856|  const int  nWidthOfu_long = /* 1行あたりの u_long の代入回数 */
 857|    width / nPixelIn_u_long;
 858|  const int  add =  /* 次の行の p の増分 */
 859|    ( Screen_getWidth( m ) - width ) / nPixelIn_u_long;
 860|
 861|  #ifdef _CHECKER
 862|    if ( x1 > x2 )  error();
 863|    if ( y1 > y2 )  error();
 864|    /* 塗りつぶす範囲は、u_long のアラインに合わせること */
 865|    if ( x1 % nPixelIn_u_long != 0 )  error();
 866|    if ( x2 % nPixelIn_u_long != nPixelIn_u_long -1 )  error();
 867|  #endif
 868|
 869|  pattern = Mask_colors16[color];
 870|
 871|  for ( y = y1; y <= y2; y++ ) {
 872|    overP = p + nWidthOfu_long;
 873|    for ( ; p < overP; p++ )
 874|      *p = pattern;
 875|    p += add;
 876|  }
 877|}
 878|#endif  /* USES_MASK */
 879|
 880|
 881|/***********************************************************************
 882|*  18. <<< 塗りつぶす(XOR アルゴリズム)[Screen_xorPaint()] >>>
 883|*  塗りつぶす領域は、Draw_lineForXorPaint で指定してあること。
 884|*  境界線は無くなることもあるので、別に境界線を描画すること。
 885|*  全体を塗りつぶす場合でも、いちばん上の水平ラインは塗られない
 886|************************************************************************/
 887|void  Screen_xorPaint( Screen* m )
 888|{
 889|  char*  p = Screen_getAdr(m);
 890|  char*  p2 = p + Screen_getWidth(m)  /* p より1段下 */
 891|                  / Screen_getPixelPerByte(m);
 892|  char*  overP = p + ( Screen_getHeight(m) - 1 )
 893|                     * Screen_getWidth(m)
 894|                     / Screen_getPixelPerByte(m);
 895|
 896|  for ( ; p < overP;  p++, p2++ ) {
 897|    *p2 = *p ^ *p2;
 898|  }
 899|}
 900|
 901|
 902|#ifdef USES_TYPES
 903|#ifdef USES_MASK
 904|
 905|/***********************************************************************
 906|*  19. <<< Screen_xorPaint と flushTo の高速処理 [Screen_xorPartPaintFlushToScreen()] >>>
 907|*【引数】
 908|*  ・mask :         パターン・マスク、NULL可
 909|*  ・baseX, baseY : ターゲットのオフセット(転送先の座標)
 910|*  ・x1,y1,x2,y2 :  コピー先画面 m を塗りつぶし、転送する範囲
 911|*【補足】
 912|*・mask を NULL にすると、ベタ塗りします。
 913|*・画面全体を走査しないで、かつターゲット to へ直接転送するので高速です
 914|*・参照する範囲は (x1,y1)-(x2,y2), 全体を塗りつぶす場合 (x1,y1+1)-(x2,y2)
 915|************************************************************************/
 916|void  Screen_xorPartPaintFlushToScreen( Screen* m, Screen* to,
 917|  Mask_A* mask, int baseX, int baseY,
 918|  int x1, int y1, int x2, int y2 )
 919|{
 920|  int    width = x2 - x1 + 1;
 921|
 922|  const int  nPixelIn_u_long =
 923|    sizeof(u_long)*8 / Screen_getBitPerPixel(to);
 924|             /* u_long 型変数の1回の代入でコピーされるピクセル数 */
 925|
 926|  u_long*  fromP =  /* 塗りつぶすワーク領域の(先頭)アドレス */
 927|    (u_long*)Screen_pgetAdr( m, x1, y1 );
 928|  u_long*  fromP2 = /* fromP の1段下の(先頭)アドレス */
 929|    fromP + Screen_getWidth(m) / nPixelIn_u_long;
 930|  u_long*  toP =    /* コピー先の(先頭)アドレス */
 931|    (u_long*)Screen_pgetAdr( to, baseX, baseY+1 );
 932|
 933|  int  fromAdd =  /* 塗りつぶすワーク領域の次の行への増分 */
 934|    (Screen_getWidth(m) - width) / nPixelIn_u_long;
 935|  int  toAdd =    /* ターゲットの次の行への増分 */
 936|    (Screen_getWidth(to) - width) / nPixelIn_u_long;
 937|
 938|  u_long*  overXP;
 939|  u_long*  overYP = fromP + ( y2 - y1 ) *
 940|                    Screen_getWidth(m) / nPixelIn_u_long;
 941|
 942|  #ifdef _CHECKER
 943|    if ( x1 > x2 || y1 > y2 )  error();
 944|    if ( Screen_getPixelPerByte(m) != Screen_getPixelPerByte(to) ) error();
 945|    if ( Screen_getWidth(m) % nPixelIn_u_long != 0 )
 946|                                       error();
 947|    if ( x1 % nPixelIn_u_long != 0 )  error();
 948|    if ( x2 % nPixelIn_u_long != nPixelIn_u_long -1 )  error();
 949|    if ( baseX % nPixelIn_u_long != 0 )  error();
 950|  #endif
 951|
 952|  /* ベタ塗り */
 953|  if ( mask == NULL ) {
 954|    for ( ; fromP < overYP;
 955|            fromP += fromAdd, fromP2 += fromAdd, toP += toAdd ) {
 956|      overXP = fromP + width / nPixelIn_u_long;
 957|      for ( ; fromP < overXP; fromP++, fromP2++, toP++ ) {
 958|        *toP = *fromP2 = *fromP ^ *fromP2;
 959|      }
 960|    }
 961|  }
 962|  /* マスク模様パターン付き */
 963|  else {
 964|    #ifdef USES_MASK
 965|      int y = 0;
 966|      for ( ; fromP < overYP;
 967|              fromP += fromAdd, fromP2 += fromAdd, toP += toAdd ) {
 968|        overXP = fromP + width / nPixelIn_u_long;
 969|        for ( ; fromP < overXP; fromP++, fromP2++, toP++ ) {
 970|          *fromP2 = *fromP ^ *fromP2;
 971|          *toP = ( ( mask->bpp4[y&7] & *fromP2 )
 972|                | ( ( mask->bpp4Mask[y&7] | ~*fromP2 ) & *toP ) );
 973|        }
 974|        y++;
 975|      }
 976|    #else
 977|      error();
 978|    #endif
 979|  }
 980|}
 981|#endif /* USES_MASK */
 982|#endif /* USES_TYPES */
 983|
 984|
 985|#ifdef USES_MMPAINT
 986|#ifdef USES_MASK
 987|#ifdef USES_TYPES
 988|/*************************************************************************
 989|*  20. <<< ポリゴンを単色で塗りつぶす [Screen_paintByMMPaint()] >>>
 990|**************************************************************************/
 991|void  Screen_paintByMMPaint( Screen* m, MMPaint* paint, int color )
 992|{
 993|  int  y, ymin, ymax;
 994|  u_long *p, *p2;                 /* フレームバッファへのポインタ */
 995|  u_long* p_x0;                                /* X座標が 0 の p */
 996|  u_long  colorMask = Mask_colors16[color];        /* 色のマスク */
 997|  int  add = m->width / 8;  /*1つ下の Y 座標のバッファ・アドレスの差分 */
 998|  int  clipXMin = m->clipX;
 999|  int  clipXMax = m->clipX + m->clipWidth-1;
1000|
1001|  #ifdef _CHECKER
1002|    if ( m->width % 8 != 0 )  error();
1003|  #endif
1004|
1005|  /* paint がクリアされていたら、何もしないで関数を抜ける */
1006|  if ( paint->ymin == INT_MAX )  return;
1007|
1008|  /* 縦のクリッピング */
1009|  ymin = intx_max( paint->ymin, m->clipY );
1010|  ymax = intx_min( paint->ymax, m->clipY + m->clipHeight-1 );
1011|
1012|  /* 塗りつぶす */
1013|  p = (u_long*)Screen_pgetAdr( m, 0, ymin );
1014|  p_x0 = p;
1015|  for ( y = ymin; y <= ymax; y++ ) {
1016|    u_long  pixelMask;
1017|    int  xmin, xmax;
1018|
1019|    /* 横のクリッピング */
1020|    xmin = intx_max( paint->xmin[y], clipXMin );
1021|    xmax = intx_min( paint->xmax[y], clipXMax );
1022|
1023|    /* 左端と右端を塗る */
1024|    p = p_x0 + xmin / 8;
1025|    p2 = p_x0 + xmax / 8;
1026|    if ( p == p2 ) {
1027|      pixelMask = Mask_leftEnd_for4bpp[xmin & 0x07] &
1028|                  Mask_rightEnd_for4bpp[xmax & 0x07];
1029|      *p = (pixelMask & colorMask) | (~pixelMask & *p);
1030|    }
1031|    else if ( p < p2 ) {
1032|      pixelMask = Mask_leftEnd_for4bpp[xmin & 0x07];
1033|      *p = (pixelMask & colorMask) | (~pixelMask & *p);
1034|      pixelMask = Mask_rightEnd_for4bpp[xmax & 0x07];
1035|      *p2 = (pixelMask & colorMask) | (~pixelMask & *p2);
1036|
1037|      /* 32bit 単位で間を水平に塗りつぶす */
1038|      for ( p = p+1;  p < p2;  p++ )
1039|        *p = colorMask;
1040|    }
1041|
1042|    p_x0 += add;
1043|  }
1044|}
1045|#endif /* USES_TYPES */
1046|#endif /* USES_MMPAINT */
1047|#endif /* USES_MASK */
1048|
1049|
1050|/*-------------------------------------------------------------------*/
1051|/*  21. <<< ◆画面コピー >>>                                             */
1052|/*-------------------------------------------------------------------*/
1053|
1054|#ifdef USES_DRAWSCR
1055|#ifdef USES_MASK
1056|
1057|/*****************************************************************
1058|*  22. <<< 画面全体をコピーする [Screen_flushTo2()] >>>
1059|*【引数】
1060|*  ・Screen* m;    コピー元の画面
1061|*  ・DrawScr target;  コピー先の画面
1062|*  ・Mask_A* mask;    マスク
1063|*  ・int baseX,baseY; オフセット
1064|*【機能】
1065|*・画面 m から、画面 target の baseX, baseY の位置へ、
1066|*  mask をかけながらコピーします。
1067|******************************************************************/
1068|void  Screen_flushTo2( Screen* m, DrawScr target, Mask_A* mask,
1069|  int baseX, int baseY )
1070|{
1071|  DrawScr_flushFromScreen2( target, m, mask, baseX, baseY );
1072|}
1073|
1074|#endif /* USES_MASK */
1075|#endif /* USES_DRAWSCR */
1076|
1077|
1078|#ifdef USES_RECT
1079|#ifdef USES_TYPES
1080|#ifdef USES_MASK
1081|
1082|#define  _Screen_flushFromScreen2
1083|#include "screen.cc"
1084|#undef   _Screen_flushFromScreen2
1085|
1086|#define  _Screen_orFlushFromScreen
1087|#include "screen.cc"
1088|#undef   _Screen_orFlushFromScreen
1089|
1090|#endif /* USES_MASK */
1091|#endif /* USES_TYPES */
1092|#endif /* USES_RECT */
1093|
1094|
1095|#ifdef USES_DSCREEN
1096|#ifdef USES_TYPES
1097|#ifdef USES_RECT
1098|
1099|/***********************************************************************
1100|*  23. <<< DScreen 画面の内容をコピーする[Screen_flushFromDScreen2()] >>>
1101|*
1102|*  
1103|*
1104|*【引数】
1105|*  ・Screen*  to;        コピー先画面、(変更される)
1106|*  ・DScreen*  from;     コピー元画面、(参照される)
1107|*  ・int  baseX, baseY;  コピー先の基点位置、ただし baseX は 8 の倍数
1108|*【補足】
1109|*・マスクによって透明色になる部分も正しく処理します。
1110|*・大きい画面から小さい画面へコピーすることは出来ません。
1111|************************************************************************/
1112|void  Screen_flushFromDScreen2( Screen* to, DScreen* from,
1113|  Mask_A* mask, int baseX, int baseY )
1114|{
1115|  #define  pixelPeru_long   (Screen_getPixelPerByte(from) * sizeof(u_long))
1116|
1117|  int  x,y, countX, countY;
1118|  u_long*  to_p;    int to_plus;
1119|  u_long*  from_p;  u_long*  from_p2;  int  from_plus;
1120|
1121|  /* 初期化 */
1122|  {
1123|    Rect  fromR; /* コピー元画面(baseX,baseYも考慮)*/
1124|    Rect  toR;   /* to のクリッピング領域 */
1125|    Rect  comR;  /* from と to の共通 */
1126|
1127|    Rect_init( &fromR, baseX, baseY, from->width, from->height );
1128|    Rect_init( &toR, to->clipX, to->clipY, to->clipWidth, to->clipHeight );
1129|    Rect_toAnd( &comR, &fromR, &toR );
1130|
1131|    /* from, to 両方に関する変数 */
1132|    countX = comR.w / pixelPeru_long;
1133|    countY = comR.h;
1134|
1135|    /* to に関する変数 */
1136|    to_p = (u_long*)Screen_pgetAdr( to, baseX, baseY );
1137|    to_plus = (to->width - comR.w) / pixelPeru_long;
1138|
1139|    /* from に関する変数 */
1140|    from_p = (u_long*)DScreen_pgetAdr( from, 0, 0 );
1141|    from_p2 = (u_long*)DScreen_pgetSubAdr( from, 0, 0 );
1142|    from_plus = (from->width - comR.w) / pixelPeru_long;
1143|  }
1144|
1145|  #ifdef _CHECKER
1146|    /* bpp は同じであること */
1147|    if ( Screen_getPixelPerByte(to) != DScreen_getPixelPerByte(from)) error();
1148|    /* 幅が 32bit アラインメントに整っていること */
1149|    if ( DScreen_getWidth(from) % pixelPeru_long != 0 )  error();
1150|    if ( DScreen_getWidth(to) % pixelPeru_long != 0 )  error();
1151|    /*  大きい画面から小さい画面へコピーすることは出来ない */
1152|    if ( Screen_getWidth(to) < DScreen_getWidth(from) )  error();
1153|  #endif
1154|
1155|  /* ベタ塗り */
1156|  if ( mask == NULL ) {
1157|    for ( y = 0; y < countY; y++ ) {
1158|      /* 32bit でコピー */
1159|      for ( x = 0; x < countX; x++ ) {
1160|        *to_p = ( *from_p | (*from_p2 & *to_p) );
1161|        to_p ++;  from_p ++;  from_p2++;
1162|      }
1163|      /* 次の行へ */
1164|      to_p += to_plus;
1165|      from_p += from_plus;
1166|      from_p2 += from_plus;
1167|    }
1168|  }
1169|  /* マスク模様パターン付き */
1170|  else {
1171|    #ifdef __SCREEN_mask_MASK
1172|      for ( y = 0; y < countY; y++ ) {
1173|        /* 32bit でコピー */
1174|        for ( x = 0; x < countX; x++ ) {
1175|          *to_p = ( ( mask->bpp4[y%8] & *from_p ) \
1176|                 | ( (mask->bpp4Mask[y%8] | *from_p) & *to_p) );
1177|          to_p ++;  from_p ++;  from_p2++;
1178|        }
1179|        /* 次の行へ */
1180|        to_p += to_plus;
1181|        from_p += from_plus;
1182|        from_p2 += from_plus;
1183|      }
1184|    #endif
1185|  }
1186|  #undef  pixelPeru_long
1187|}
1188|
1189|#endif /* USES_RECT */
1190|#endif /* USES_TYPES */
1191|#endif /* USES_DSCREEN */
1192|
1193|#ifdef USES_DSCREEN
1194|#ifdef USES_TYPES
1195|#ifdef USES_RECT
1196|
1197|/***********************************************************************
1198|*  24. <<< DScreen 画面のクリッピング領域をコピーする [Screen_flushFromPartDScreen()] >>>
1199|*
1200|*  
1201|*
1202|*【引数】
1203|*  ・Screen*  to;        コピー先画面、(変更される)
1204|*  ・DScreen*  from;     コピー元画面、(参照される)
1205|*  ・int  baseX, baseY;  to にコピーする領域の左上座標、baseX は 8 の倍数
1206|*【補足】
1207|*・クリッピング領域を必要なだけ小さくすれば、高速に処理します。
1208|************************************************************************/
1209|void  Screen_flushFromPartDScreen( Screen* to, DScreen* from,
1210|  Mask_A* mask, int baseX, int baseY )
1211|{
1212|  #define  pixelPeru_long   (Screen_getPixelPerByte(from) * sizeof(u_long))
1213|
1214|  int  x,y, countX, countY;
1215|  u_long*  to_p;    int to_plus;
1216|  u_long*  from_p;  u_long*  from_p2;  int  from_plus;
1217|
1218|  /* 初期化 */
1219|  {              /* 以下はすべて to の座標系を使用 */
1220|    Rect  fromR; /* コピー元画面(baseX,baseYも考慮)*/
1221|    Rect  toR;   /* to のクリッピング領域 */
1222|    Rect  comR;  /* from と to の共通 */
1223|
1224|    Rect_init( &fromR, baseX + from->clipX, baseY + from->clipY,
1225|               from->clipWidth, from->clipHeight );
1226|    Rect_init( &toR, to->clipX, to->clipY, to->clipWidth, to->clipHeight );
1227|    Rect_toAnd( &comR, &fromR, &toR );
1228|
1229|    /* from, to 両方に関する変数 */
1230|    countX = comR.w / pixelPeru_long;
1231|    countY = comR.h;
1232|
1233|    /* to に関する変数 */
1234|    to_p = (u_long*)Screen_pgetAdr( to, baseX, baseY );
1235|    to_plus = (to->width - comR.w) / pixelPeru_long;
1236|
1237|    /* from に関する変数 */
1238|    from_p = (u_long*)DScreen_pgetAdr( from, 0, 0 );
1239|    from_p2 = (u_long*)DScreen_pgetSubAdr( from, 0, 0 );
1240|    from_plus = (from->width - comR.w) / pixelPeru_long;
1241|  }
1242|
1243|  #ifdef _CHECKER
1244|    /* bpp は同じであること */
1245|    if ( Screen_getPixelPerByte(to) != DScreen_getPixelPerByte(from)) error();
1246|    /* 幅が 32bit アラインメントに整っていること */
1247|    if ( DScreen_getWidth(from) % pixelPeru_long != 0 )  error();
1248|    if ( DScreen_getWidth(to) % pixelPeru_long != 0 )  error();
1249|    /*  大きい画面から小さい画面へコピーすることは出来ない */
1250|    if ( Screen_getWidth(to) < DScreen_getWidth(from) )  error();
1251|  #endif
1252|
1253|  /* ベタ塗り */
1254|  if ( mask == NULL ) {
1255|    for ( y = 0; y < countY; y++ ) {
1256|      /* 32bit でコピー */
1257|      for ( x = 0; x < countX; x++ ) {
1258|        *to_p = ( *from_p | (*from_p2 & *to_p) );
1259|        to_p ++;  from_p ++;  from_p2++;
1260|      }
1261|      /* 次の行へ */
1262|      to_p += to_plus;
1263|      from_p += from_plus;
1264|      from_p2 += from_plus;
1265|    }
1266|  }
1267|  /* マスク模様パターン付き */
1268|  else {
1269|    #ifdef __SCREEN_mask_MASK
1270|      for ( y = 0; y < countY; y++ ) {
1271|        /* 32bit でコピー */
1272|        for ( x = 0; x < countX; x++ ) {
1273|          *to_p = ( ( mask->bpp4[y%8] & *from_p ) \
1274|                 | ( (mask->bpp4Mask[y%8] | *from_p) & *to_p) );
1275|          to_p ++;  from_p ++;  from_p2++;
1276|        }
1277|        /* 次の行へ */
1278|        to_p += to_plus;
1279|        from_p += from_plus;
1280|        from_p2 += from_plus;
1281|      }
1282|    #endif
1283|  }
1284|  #undef  pixelPeru_long
1285|}
1286|
1287|#if 0
1288|void  Screen_flushFromPartDScreen( Screen* m, DScreen* work,
1289|  Mask_A* mask, int x1, int y1, int x2, int y2, int toX, int toY )
1290|{
1291|  #define  to  m
1292|  int    x,y;
1293|
1294|  const int  from_width = x2 - x1 + 1;  /* コピー元の部分の幅 */
1295|  const int  from_height = y2 - y1 + 1; /* コピー元の部分の高さ */
1296|  const int  nPixelIn_u_long =
1297|    sizeof(u_long)*8 / Screen_getBitPerPixel(to);
1298|              /* u_long 型変数の1回の代入でコピーされるピクセル数 */
1299|
1300|  u_long*  toP = /* コピー先の(先頭)アドレス */
1301|    (u_long*)Screen_pgetAdr( to, toX, toY );
1302|  u_long*  fromP = /* コピー元の(先頭)アドレス */
1303|    (u_long*)DScreen_pgetAdr( work, x1, y1 );
1304|  u_long*  fromPD = /* コピー先のもう1画面の(先頭)アドレス */
1305|    (u_long*)( (char*)fromP + DScreen_getSingleSize(work) );
1306|
1307|  const int  toAdd = /* コピー先を次の行にする u_long 型ポインタ増分 */
1308|    ( Screen_getWidth(to) - from_width ) / nPixelIn_u_long;
1309|  const int  fromAdd = /* コピー元を次の行にする u_long 型ポインタ増分 */
1310|    ( DScreen_getWidth(work) - from_width ) / nPixelIn_u_long;
1311|
1312|  #if 0
1313|  /* #include "upd72251.h"  #include "iomem.h" */
1314|  IOMem_outH( _XdispM01, 0 );  IOMem_outH( _YdispM01, 0 );
1315|  watchX( 1, x1 ); watchX( 2, y1 ); watchX( 3, x2 ); watchX( 4, y2 );
1316|   watchX( 5, toX ); watchX( 6, toY ); watchX( 7, (int)mask );
1317|    watchX( 8, (int)toP ); watchX( 9, (int)fromP );
1318|     watchX( 10, (int)fromPD ); watchX( 11, toAdd );
1319|      watchX( 12, fromAdd ); watchX( 13, Screen_getWidth(to) );
1320|       watchX( 14, DScreen_getWidth(work) ); watchX( 15, from_width );
1321|  /* brkX は後に */
1322|  #endif
1323|
1324|  #ifdef _CHECKER
1325|    /* bpp は同じであること */
1326|    if ( Screen_getPixelPerByte(to) != DScreen_getPixelPerByte(work)) error();
1327|    /* x 座標が 32bit アラインメントに整っていること */
1328|    if ( x1 % nPixelIn_u_long != 0 )  error();
1329|    if ( x2 % nPixelIn_u_long != nPixelIn_u_long -1 )  error();
1330|    if ( toX % nPixelIn_u_long != 0 )  error();
1331|    /* 幅が 32bit アラインメントに整っていること */
1332|    if ( DScreen_getWidth(work) % nPixelIn_u_long != 0 )  error();
1333|    if ( Screen_getWidth(to) % nPixelIn_u_long != 0 )  error();
1334|    /*  大きい画面から小さい画面へコピーすることは出来ない */
1335|    if ( Screen_getWidth(to) < DScreen_getWidth(work) )  error();
1336|    /* 値の順序 */
1337|    if ( x1 > x2 || y1 > y2 )  error();
1338|    /* コピー元の部分のx軸方向の範囲は、u_long アラインに合わせること */
1339|    if ( x1 % nPixelIn_u_long != 0  ||
1340|         x2 % nPixelIn_u_long != nPixelIn_u_long -1 )  error();
1341|  #endif
1342|
1343|  /* ベタ塗り */
1344|  if ( mask == NULL ) {
1345|    for ( y = 0; y < from_height; y++ ) {
1346|      /* 32bit でコピー */
1347|      for ( x = 0; x < from_width / nPixelIn_u_long; x++ ) {
1348|        *toP = ( *fromP | (*fromPD & *toP) );
1349|        toP ++;  fromP ++;  fromPD++;
1350|      }
1351|      /* 次の行へ */
1352|      toP += toAdd;  fromP += fromAdd;  fromPD += fromAdd;
1353|    }
1354|  }
1355|  /* マスク模様パターン付き */
1356|  else {
1357|    #ifdef USES_MASK
1358|      for ( y = 0; y < from_height; y++ ) {
1359|        /* 32bit でコピー */
1360|        for ( x = 0; x < from_width / nPixelIn_u_long; x++ ) {
1361|          *toP = ( ( mask->bpp4[y%8] & *fromP ) \
1362|                 | ( (mask->bpp4Mask[y%8] | *fromPD) & *toP) );
1363|          toP ++;  fromP ++;  fromPD++;
1364|        }
1365|        /* 次の行へ */
1366|        toP += toAdd;  fromP += fromAdd;  fromPD += fromAdd;
1367|      }
1368|    #else
1369|      error();
1370|    #endif
1371|  }
1372|
1373|  #if 0
1374|  brkX(1,1,0xAAAA,0xAAAA,1);
1375|  #endif
1376|
1377|  #undef  to
1378|}
1379|#endif
1380|
1381|#endif /* USES_RECT */
1382|#endif /* USES_TYPES */
1383|#endif /* USES_DSCREEN */
1384|
1385|
1386| 
1387|/***********************************************************************
1388|*  25. <<< [Screen_outBmp] 4bpp を任意の bpp に変換する >>> 
1389|*【引数】
1390|*  ・char*  buf;          フレームバッファの先頭アドレス
1391|*  ・int   width,height;  buf の幅と高さ(ピクセル数)
1392|*  ・int   bpp;           buf の BPP(BitParPixel)
1393|*  ・int*  palette;       パレットテーブルの先頭アドレス
1394|*【補足】
1395|*・palette は、 Palet_Color4to16 などデフォルトで用意されているもの
1396|*  または、自分で作成したものを指定します。
1397|*・palette の1要素のサイズは、4byte です。要素数は、16(4bpp分)です。
1398|************************************************************************/
1399|#ifdef USES_COLOR
1400|void  Screen_outBmp( Screen* m, char* buf, int width, int height,
1401|  int bpp, unsigned int* palette )
1402|{
1403|  int  x,y,c;
1404|
1405|  ASSERT( bpp == 8 || bpp == 15 || bpp == 16 || bpp == 24 || bpp == 32 );
1406|
1407|  if ( bpp == 8 ) {
1408|    for ( y = 0; y < height; y++ ) {
1409|      for ( x = 0; x < width; x++ ) {
1410|        c = Screen_pget( m, x, y );
1411|        ((char*)buf)[x+y*width] = palette[c];
1412|      }
1413|    }
1414|  }
1415|  if ( bpp == 15 ) {
1416|    for ( y = 0; y < height; y++ ) {
1417|      for ( x = 0; x < width; x++ ) {
1418|        c = Screen_pget( m, x, y );
1419|        ((short*)buf)[x+y*width] = Color_RGB16_getRGB15(palette[c]);
1420|      }
1421|    }
1422|  }
1423|  if ( bpp == 16 ) {
1424|    for ( y = 0; y < height; y++ ) {
1425|      for ( x = 0; x < width; x++ ) {
1426|        c = Screen_pget( m, x, y );
1427|        ((short*)buf)[x+y*width] = palette[c];
1428|      }
1429|    }
1430|  }
1431|  if ( bpp == 24 ) {
1432|    for ( y = 0; y < height; y++ ) {
1433|      for ( x = 0; x < width; x++ ) {
1434|        c = Screen_pget( m, x, y );
1435|        ((char*)buf)[(x+y*width)*3+0] = ((palette[c] & 0x0000FF));
1436|        ((char*)buf)[(x+y*width)*3+1] = ((palette[c] & 0x00FF00) >> 8);
1437|        ((char*)buf)[(x+y*width)*3+2] = ((palette[c] & 0xFF0000) >> 16);
1438|      }
1439|    }
1440|  }
1441|  if ( bpp == 32 ) {
1442|    for ( y = 0; y < height; y++ ) {
1443|      for ( x = 0; x < width; x++ ) {
1444|        c = Screen_pget( m, x, y );
1445|        ((char*)buf)[(x+y*width)*4+0] = ((palette[c] & 0x0000FF));
1446|        ((char*)buf)[(x+y*width)*4+1] = ((palette[c] & 0x00FF00) >> 8);
1447|        ((char*)buf)[(x+y*width)*4+2] = ((palette[c] & 0xFF0000) >> 16);
1448|        ((char*)buf)[(x+y*width)*4+3] = 0;
1449|      }
1450|    }
1451|  }
1452|}
1453|#endif /* USES_COLOR */
1454|
1455|
1456| 
1457|#ifdef  _STDLIB
1458|/***********************************************************************
1459|*  26. <<< [Screen_print] デバッグ表示 >>> 
1460|************************************************************************/
1461|void  Screen_print( Screen* m, FILE* file )
1462|{
1463|  int  x,y;
1464|  unsigned char  c;
1465|
1466|  #ifdef _CHECKER
1467|  if ( Screen_getPixelPerByte(m) != 2 )  error();
1468|  #endif
1469|
1470|  fprintf( file, "[Screen] adr=%p, width=%d, height=%d, offX=%d, offY=%d",
1471|     m->adr, m->width, m->height, m->offsetX, m->offsetY );
1472|
1473|  for ( y = 0; y < m->height; y++ ) {
1474|    for ( x = 0; x < m->width; x+=2 ) {
1475|      if ( x == 0 )  fprintf( file, "\n " );
1476|      c = m->adr[(y * m->width + x) / Screen_getPixelPerByte(m)];
1477|      fprintf( file, "%01X", c & 0x0F );
1478|      fprintf( file, "%01X", c >> 4 );
1479|    }
1480|  }
1481|  fprintf( file, "\n " );
1482|}
1483|
1484|#endif  /* _STDLIB */
1485|
1486|
1487| 
1488|/*-------------------------------------------------------------------*/
1489|/*  27. <<< ◆インターフェイス >>>                                       */ 
1490|/*-------------------------------------------------------------------*/
1491|#ifdef  USES_DRAWSCR
1492|
1493|INF_SUB_FUNC( Screen, DrawScr, Screen_by_DrawScr )
1494|
1495|DrawScr  Screen_inf_DrawScr( Screen* m )
1496|{
1497|  INF_SUB_SC_START( Screen, DrawScr );
1498|  INF_SUB_SC_METHOD_0( Screen,getWidth,  int, Screen_getWidthX, Screen* );
1499|  INF_SUB_SC_METHOD_0( Screen,getHeight,  int, Screen_getHeightX, Screen* );
1500|  INF_SUB_SC_METHOD_2( Screen,getExAdr,  int, Screen_getExAdr, Screen*,int,int );
1501|  INF_SUB_SC_METHOD_3( Screen,getExVectors,  void, Screen_getExVectors, Screen*,int,unsigned*,unsigned* );
1502|  INF_SUB_SC_METHOD_1( Screen,clear,  void, Screen_clear, Screen*,int );
1503|  INF_SUB_SC_METHOD_3( Screen,pset,  void, Screen_pset, Screen*,int,int,int );
1504|  INF_SUB_SC_METHOD_2( Screen,exPset,  void, Screen_exPset, Screen*,int,int );
1505|  INF_SUB_SC_METHOD_3( Screen,psetXor,  void, Screen_psetXor, Screen*,int,int,int );
1506|  INF_SUB_SC_METHOD_2( Screen,exPset,  void, Screen_exPset, Screen*,int,int );
1507|  #ifdef USES_MASK
1508|   INF_SUB_SC_METHOD_5( Screen,psets,  void, Screen_psets, Screen*,int,int,unsigned char*,int,int );
1509|  #endif
1510|  INF_SUB_SC_METHOD_0( Screen,xorPaint,  void, Screen_xorPaint, Screen* );
1511|  #ifdef USES_MASK
1512|   INF_SUB_SC_METHOD_4( Screen,flushTo2,  void, Screen_flushTo2, Screen*,DrawScr,Mask_A*,int,int );
1513|   #ifdef USES_SCREEN
1514|    INF_SUB_SC_METHOD_4( Screen,flushFromScreen2,  void, Screen_flushFromScreen2, Screen*,Screen*,Mask_A*,int,int );
1515|   #endif
1516|   #ifdef USES_DSCREEN
1517|    INF_SUB_SC_METHOD_4( Screen,flushFromDScreen2,  void, Screen_flushFromDScreen2, Screen*,DScreen*,Mask_A*,int,int );
1518|   #endif
1519|  #endif /* USES_MASK */
1520|
1521|  INF_SUB_SC_END( Screen, DrawScr );
1522|}
1523|
1524|int  Screen_getWidthX( Screen* m )
1525|  { return Screen_getWidth( m ); }
1526|int  Screen_getHeightX( Screen* m )
1527|  { return Screen_getHeight( m ); }
1528|
1529|#endif  /* USES_DRAWSCR */
1530|
1531|
1532| 
1533|/*-------------------------------------------------------------------*/
1534|/*  28. <<< ◆画面スイッチ (Screen_Sw) >>> */ 
1535|/*-------------------------------------------------------------------*/
1536| 
1537|/**************************************************************************
1538|*  29. <<< [Screen_Sw_init] 初期化する >>> 
1539|*【引数】
1540|*  ・Screen*  visi;    始めに表示させる画面
1541|*  ・Screen*  draw;    始めに描画対象になる画面
1542|*  ・Screen*  返り値;  描画対象になる画面のアドレス
1543|*【補足】
1544|*・返り値によって返されるアドレス、つまり描画対象になる画面のアドレスは、
1545|*  画面の切り替えがあっても変わりません。Draw_init 関数の引数に指定する
1546|*  ことができます。
1547|*・front と back の全てのメンバ変数の値は ScrSw_swap 関数によって
1548|*  すべて入れ替えられるので扱いに注意してください。
1549|***************************************************************************/
1550|Screen*  Screen_Sw_init( Screen_Sw* m, Screen* visi, Screen* draw )
1551|{
1552|  m->front = visi;
1553|  m->back = draw;
1554|  return  draw;
1555|}
1556|
1557|
1558| 
1559|/**************************************************************************
1560|*  30. <<< [Screen_Sw_swap] 裏画面と切り替える >>> 
1561|*【引数】
1562|*・void*  返り値;   表示する VRAM の先頭アドレス
1563|***************************************************************************/
1564|void*  Screen_Sw_swap( Screen_Sw* m )
1565|{
1566|  Screen  swap;
1567|
1568|  swap = *m->front;
1569|  *m->front = *m->back;
1570|  *m->back = swap;
1571|
1572|  return  m->front->adr;
1573|}
1574| 
1575|