DSCREEN.C
[目次 | 関数]
1|/***************************************************************************
2|* 1. <<< ダブルバッファ・ワーク画面 [DScreen] >>>
3|*
4|*・透明色を扱うことが出来るように、バッファを 2画面分用意したワーク画面。
5|*・DrawScr インターフェイスに対応しています。
6|*・裏画面を持ついわゆるダブルバッファは、Screen_Sw クラスを参照。
7|*
8|* 2. <<<【属性】>>>
9|*・先頭アドレス [DScreen.adr, DScreen_getAdr()]
10|*・1画面分のバッファ・サイズ(byte) [DScreen_getSingleSize()]
11|*・ワーク画面のサイズ [DScreen.width, DScreen_getWidth(), DScreen.height,
12|* DScreen_getHeight()]
13|*・オフセット [DScreen.offsetX, DScreen_getOffsetX(), DScreen.offsetY,
14|* DScreen_getOffsetY(), DScreen_setOffset()]
15|*・クリップ領域 [DScreen_getClipMinX(), DScreen_getClipMaxX(),
16|* DScreen_getClipMinY(), DScreen_getClipMaxY()]
17|*・1バイトあたりのピクセル数 [DScreen_getPixelPerByte()]
18|*・1ピクセルあたりのビット数 [DScreen_getBitPerPixel()]
19|*
20|* 3. <<< 用語 [オフセット] >>>
21|* pset() の座標をずらす度合い
22|***************************************************************************/
23|
24|#include "mixer_precomp.h"
25|// #pragma hdrstop ("mixer_precomp")
26|
27|#ifdef USES_MXP_AUTOINC
28| #include <DScreen.ah> /* Auto include header, Look at mixer-... folder */
29|#endif
30|
31|/***************************************************************************
32|* 4. <<< 初期化する [DScreen_init()] >>>
33|*【補足】
34|*・adr が指しているバッファは、DScreen_clear 関数で明示的に初期化する
35|* 必要があります。
36|****************************************************************************/
37|void DScreen_init( DScreen* m, char* adr, int width, int height )
38|{
39| m->adr = adr;
40| m->width = width; m->height = height;
41| m->offsetX = 0; m->offsetY = 0;
42| m->clipX = 0; m->clipY = 0;
43| m->clipWidth = width; m->clipHeight = height;
44|}
45|
46|
47|/***************************************************************************
48|* 5. <<< 画面全体を指定の色 color でクリアする [DScreen_clear()] >>>
49|****************************************************************************/
50|void DScreen_clear( DScreen* m, int color )
51|{
52| int i;
53| int* p = (int*)DScreen_getAdr(m);
54|
55| color = (color << 4 ) | color;
56| color = (color << 24) | (color << 16) | (color << 8) | color ;
57|
58| for ( i = 0; i < DScreen_getWidth(m) * DScreen_getHeight(m)
59| * 2 / DScreen_getPixelPerByte(m) / (int)sizeof(int);
60| i++ ) {
61| *p = color; p++;
62| }
63|}
64|
65|
66|/***************************************************************************
67|* 6. <<< 画面全体を透明色でクリアする [DScreen_trueClear()] >>>
68|****************************************************************************/
69|void DScreen_trueClear( DScreen* m )
70|{
71| int i;
72| int* p = (int*)DScreen_getAdr(m);
73|
74| for ( i = 0; i < DScreen_getWidth(m) * DScreen_getHeight(m)
75| / DScreen_getPixelPerByte(m) / (int)sizeof(int);
76| i++ ) {
77| *p = 0; p++;
78| }
79| for ( i = 0; i < DScreen_getWidth(m) * DScreen_getHeight(m)
80| / DScreen_getPixelPerByte(m) / (int)sizeof(int);
81| i++ ) {
82| *p = -1; p++;
83| }
84|}
85|
86|
87|/***************************************************************************
88|* 7. <<< クリッピング領域を設定する [DScreen_setClip()] >>>
89|****************************************************************************/
90|void DScreen_setClip( DScreen* m, int x, int y, int w, int h )
91|{
92| m->clipX = x; m->clipY = y;
93| m->clipWidth = w; m->clipHeight = h;
94|}
95|
96|
97|/***************************************************************************
98|* 8. <<< クリッピング領域の設定を解除する [DScreen_clearClip()] >>>
99|****************************************************************************/
100|void DScreen_clearClip( DScreen* m )
101|{
102| m->clipX = 0; m->clipY = 0;
103| m->clipWidth = m->width; m->clipHeight = m->height;
104|}
105|
106|
107|#ifdef USES_TYPEX
108|
109|/***************************************************************************
110|* 9. <<< 透明色で矩形を塗りつぶす [DScreen_rectFillClear2()] >>>
111|****************************************************************************/
112|void DScreen_rectFillClear2( DScreen* m, int x1, int y1, int x2, int y2 )
113|{
114| int y;
115| UINT32* p = (UINT32*)DScreen_pgetAdr( m, x1, y1 );
116| UINT32* p2 = (UINT32*)DScreen_pgetSubAdr( m, x1, y1 );
117| UINT32* overP;
118|
119| const int nPixelInUINT32 = /* UINT32 型変数の1回の代入でコピーされるピクセル数 */
120| sizeof(UINT32)*8 / DScreen_getBitPerPixel(m);
121| const int width = x2 - x1 + 1;
122|
123| const int countX = /* 1行あたりの UINT32 の代入回数 */
124| width / nPixelInUINT32;
125| const int add = /* 次の行の p の増分 */
126| ( DScreen_getWidth( m ) - width ) / nPixelInUINT32;
127|
128| #ifdef _CHECKER
129| if ( x1 < 0 || x1 > DScreen_getWidth( m ) ) error();
130| if ( x2 < 0 || x2 > DScreen_getWidth( m ) ) error();
131| if ( x1 > x2 ) error();
132| if ( y1 < 0 || y1 > DScreen_getHeight( m ) ) error();
133| if ( y2 < 0 || y2 > DScreen_getHeight( m ) ) error();
134| if ( y1 > y2 ) error();
135| /* 塗りつぶす範囲は、UINT32 のアラインに合わせること */
136| if ( x1 % nPixelInUINT32 != 0 ) error();
137| if ( x2 % nPixelInUINT32 != nPixelInUINT32 -1 ) error();
138| #endif
139|
140| for ( y = y1; y <= y2; y++ ) {
141| overP = p + countX;
142| for ( ; p < overP; p++, p2++ ) {
143| *p = 0; *p2 = 0xFFFFFFFF;
144| }
145| p += add; p2 += add;
146| }
147|}
148|
149|#endif /* USES_TYPEX */
150|
151|
152|/***************************************************************************
153|* 10. <<< (x,y) の位置に点を打つ [DScreen_pset()] >>>
154|* クリッピング処理、オフセットあり
155|* 領域外の場合は点を描かない
156|****************************************************************************/
157|void DScreen_pset( DScreen* m, int x, int y, int color )
158|{
159| char* p;
160|
161| /* オフセット */
162| x += DScreen_getOffsetX(m);
163| y += DScreen_getOffsetY(m);
164|
165| /* クリッピング */
166| if ( x < DScreen_getClipMinX(m) ||
167| x > DScreen_getClipMaxX(m) ||
168| y < DScreen_getClipMinY(m) ||
169| y > DScreen_getClipMaxY(m) )
170| return;
171|
172| /* アドレス */
173| p = DScreen_getAdr(m) +
174| ( DScreen_getWidth(m) * y + x )
175| / DScreen_getPixelPerByte(m);
176|
177| #if DScreen_getPixelPerByte(m) != 2
178| #error
179| #endif
180|
181| color = (color & 0x0F);
182|
183| if ( (x & 1) == 0 ) {
184| *p = (*p & 0xF0) | color;
185| p += DScreen_getSingleSize(m);
186| *p = (*p & 0xF0);
187| }
188| else {
189| *p = (*p & 0x0F) | (color << 4);
190| p += DScreen_getSingleSize(m);
191| *p = (*p & 0x0F);
192| }
193|}
194|
195|
196|/***************************************************************************
197|* 11. <<< XOR 演算して点を描く [DScreen_psetXor()] >>>
198|* クリッピング処理、オフセットあり
199|* x が領域外の場合は点を描かない
200|* y が領域外の場合はその領域の境界に描く
201|* ・x, y : 位置
202|* ・color
203|****************************************************************************/
204|void DScreen_psetXor( DScreen* m, int x, int y, int color )
205|{
206| char* p;
207|
208| /* オフセット */
209| x += DScreen_getOffsetX(m);
210| y += DScreen_getOffsetY(m);
211|
212| /* クリッピング */
213| if ( x < DScreen_getClipMinX(m) ||
214| x > DScreen_getClipMaxX(m) ) return;
215|
216| if ( y < DScreen_getClipMinY(m) )
217| y = DScreen_getClipMinY(m);
218| if ( y > DScreen_getClipMaxY(m) )
219| y = DScreen_getClipMaxY(m);
220|
221| /* アドレス */
222| p = DScreen_getAdr(m) +
223| ( DScreen_getWidth(m) * y + x )
224| / DScreen_getPixelPerByte(m);
225|
226| #if DScreen_getPixelPerByte(m) != 2
227| #error
228| #endif
229|
230| color = (color & 0x0F);
231|
232| if ( (x & 1) == 0 ) {
233| *p = *p ^ color;
234| p += DScreen_getSingleSize(m);
235| *p = *p ^ color;
236| }
237| else {
238| *p = *p ^ ( color << 4 );
239| p += DScreen_getSingleSize(m);
240| *p = *p ^ ( color << 4 );
241| }
242|}
243|
244|
245|#ifdef USES_TYPEX
246|#ifdef USES_MASK
247|
248|/**************************************************************************
249|* 12. <<< 数ピクセル描画する [DScreen_psets()] >>>
250|*【引数】
251|* ・unsigned char* pattern; ピクセル・パターンが格納されているアドレス
252|* ・int nPixel; ピクセル数
253|*【機能】
254|*・x,y から水平右方向に、数ピクセルのピクセル・パターンを描画します。
255|*【補足】
256|*・UNIT32 代入を用いて高速に処理します。
257|*・ピクセル・パターンは、下位ビット→上位ビットが左→右のピクセルに対応
258|* します。ピクセル・パターンは、1bpp です。
259|*・ピクセル・パターン中のビットが0の位置に相当するピクセルの色は、
260|* 変化しません。透明色に相当します。
261|*・たとえば、文字を描くときに使うことができます。
262|*・4bpp 専用です。
263|***************************************************************************/
264|void DScreen_psets( DScreen* m, int x, int y, unsigned char* pattern,
265| int nPixel, int color )
266|{
267| UINT32* p = (UINT32*)DScreen_pgetAdr( m, x, y );
268| UINT32* p2 = (UINT32*)DScreen_pgetSubAdr( m, x, y );
269| UINT32 inMask, outMask, overMask;
270| unsigned char* pattern_over;
271| #ifdef _32BIT
272| int sft = (x & 0x07) << 2; /* シフト数、x/2 の余り×4 (32bitの余り) */
273| #endif
274| #ifdef _16BIT
275| int sft = (x & 0x01) << 2; /* シフト数、x/2 の余り×4 (8bitの余り) */
276| #endif
277|
278| #ifdef _CHECKER
279| if ( nPixel % 8 != 0 || nPixel < 8 ) error();
280| if ( DScreen_getBitPerPixel(m) != 4 ) error();
281| if ( x < 0 || x + nPixel > m->width ) error();
282| if ( y < 0 || y >= m->height ) error();
283| #endif
284|
285| overMask = 0;
286|
287| /* (nPixel/8) 回だけ 32bit コピーする */
288| pattern_over = pattern + (nPixel/8);
289| for ( pattern ; pattern < pattern_over; pattern ++ ) {
290|
291| inMask = Mask_bpp1to4[*pattern];
292| outMask = (inMask << sft) | overMask; /* 左シフトでピクセルは右へ */
293| *p = ( ( Mask_colors16[color] & outMask ) | ( ~outMask & *p ) );
294| *p2 = ( ~outMask & *p2 );
295|
296| overMask = V800X_shr( inMask, 32-sft );
297| p++; p2++;
298| }
299|
300| /* あふれた分の 32bit コピーをする */
301| *p = ( ( Mask_colors16[color] & overMask ) | ( ~overMask & *p ) );
302| *p2 = ( ~overMask & *p2 );
303|}
304|
305|#endif /* USES_MASK */
306|#endif /* USES_TYPEX */
307|
308|
309|/***************************************************************************
310|* 13. <<< 塗りつぶす(XOR アルゴリズム)[DScreen_xorPaint()] >>>
311|* 塗りつぶす領域は、Draw_lineForXorPaint で指定してあること。
312|* 境界線は無くなることもあるので、別に境界線を描画すること。
313|****************************************************************************/
314|void DScreen_xorPaint( DScreen* m )
315|{
316| char* p = DScreen_getAdr(m);
317| char* p2 = p + DScreen_getWidth(m) /* p より1段下 */
318| / DScreen_getPixelPerByte(m);
319| char* overP = p + DScreen_getSingleSize(m);
320| char* overP2 = overP + DScreen_getSingleSize(m);
321|
322| for ( ; p < overP; p++, p2++ ) {
323| *p2 = *p ^ *p2;
324| }
325| for ( ; p < overP2; p++, p2++ ) {
326| *p2 = ~(*p ^ *p2); /* NOT XOR */
327| }
328|}
329|
330|
331|#ifdef USES_DRAWSCR
332|
333|/***************************************************************************
334|* 14. <<< 画面全体を target 画面へコピーする(同期を取る)[DScreen_flushTo2()] >>>
335|* ・target : コピー先画面
336|* ・baseX, baseY : target 基点画面位置、ただし x は 8 の倍数
337|* 透明色は #define DScreen_ClearColor による
338|****************************************************************************/
339|void DScreen_flushTo2( DScreen* m, DrawScr target,
340| Mask_A* mask, int baseX, int baseY )
341|{
342| DrawScr_flushFromDScreen2( target, m, mask, baseX, baseY );
343|}
344|
345|#endif /* USES_DRAWSCR */
346|
347|#ifdef _STDLIB
348|
349|/***************************************************************************
350|* 15. <<< デバッグ表示 [DScreen_print()] >>>
351|****************************************************************************/
352|void DScreen_print( DScreen* m, FILE* file )
353|{
354| int x,y;
355| unsigned char c;
356|
357| #ifdef _CHECKER
358| if ( DScreen_getPixelPerByte(m) != 2 ) error();
359| #endif
360|
361| fprintf( file, "[DScreen] adr=%p, width=%d, height=%d, offX=%d, offY=%d",
362| m->adr, m->width, m->height, m->offsetX, m->offsetY );
363|
364| for ( y = 0; y < m->height*2; y++ ) {
365| for ( x = 0; x < m->width; x+=2 ) {
366| if ( x == 0 ) fprintf( file, "\n " );
367| c = m->adr[(y * m->width + x) / DScreen_getPixelPerByte(m)];
368| fprintf( file, "%01X", c & 0x0F );
369| fprintf( file, "%01X", c >> 4 );
370| }
371| }
372| fprintf( file, "\n " );
373|}
374|
375|#endif /* _STDLIB */
376|
377|
378|#ifdef USES_DRAWSCR
379|
380|/***************************************************************************
381|* 16. <<< DrawScr インターフェイスを返す [DScreen_inf_DrawScr()] >>>
382|****************************************************************************/
383|
384|int DScreen_getWidthF( DScreen* m )
385| { return DScreen_getWidth( m ); }
386|int DScreen_getHeightF( DScreen* m )
387| { return DScreen_getHeight( m ); }
388|
389|/* 具象クラスの関数定義 */
390|INF_SUB_FUNC( DScreen, DrawScr, DScreen_by_DrawScr )
391|
392|/* インターフェイス取得関数の定義(INF_SUB_FUNC より後に書くこと) */
393|DrawScr DScreen_inf_DrawScr( DScreen* m )
394|{
395| INF_SUB_SC_START( DScreen, DrawScr );
396| INF_SUB_SC_METHOD_0( DScreen,getWidth, int, DScreen_getWidthF, DrawScr )
397| INF_SUB_SC_METHOD_0( DScreen,getHeight, int, DScreen_getHeightF, DrawScr )
398| INF_SUB_SC_METHOD_NULL( DScreen,getExAdr )
399| INF_SUB_SC_METHOD_NULL( DScreen,getExVectors )
400| INF_SUB_SC_METHOD_1( DScreen,clear, void, DScreen_clear, DrawScr,int )
401| INF_SUB_SC_METHOD_3( DScreen,pset, void, DScreen_pset, DrawScr,int,int,int )
402| INF_SUB_SC_METHOD_NULL( DScreen,exPset )
403| INF_SUB_SC_METHOD_3( DScreen,psetXor, void, DScreen_psetXor, DrawScr,int,int,int )
404| #ifdef USES_MASK
405| INF_SUB_SC_METHOD_5( DScreen,psets, void, DScreen_psets, DrawScr,int,int,unsigned char*,int,int )
406| #endif
407| INF_SUB_SC_METHOD_0( DScreen,xorPaint, void, DScreen_xorPaint, DrawScr )
408| #ifdef USES_MASK
409| INF_SUB_SC_METHOD_4( DScreen,flushTo2, void, DScreen_flushTo2, DrawScr,DrawScr,Mask_A*,int,int )
410| #ifdef USES_SCREEN
411| INF_SUB_SC_METHOD_NULL( DScreen,flushFromScreen2 )
412| #endif
413| INF_SUB_SC_METHOD_NULL( DScreen,flushFromDScreen2 )
414| #endif /* USES_MASK */
415| INF_SUB_SC_END( DScreen, DrawScr );
416|}
417|
418|
419|#endif /* USES_DRAWSCR */
420|
421|