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|