small cleanup. remove old code which was corrupting the init tags. use the obtained...
[AROS.git] / arch / all-native / hidd / vgagfx / vgagfx_hiddclass.c
blob03a2c366f82d0c273b0ecc2857a542bcfb0851fc
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Class for VGA and compatible cards.
6 Lang: English.
7 */
9 #define DEBUG 0
10 #include <aros/debug.h>
12 #define __OOP_NOATTRBASES__
14 #include <aros/asmcall.h>
15 #include <proto/exec.h>
16 #include <proto/utility.h>
17 #include <proto/oop.h>
18 #include <oop/oop.h>
20 #include <exec/alerts.h>
21 #include <exec/memory.h>
23 #include <hidd/hidd.h>
24 #include <hidd/gfx.h>
26 #include <aros/symbolsets.h>
28 #include <hardware/custom.h>
30 #include <devices/inputevent.h>
31 #include <string.h>
33 #include LC_LIBDEFS_FILE
35 static AROS_INTH1(ResetHandler, struct VGAGfx_staticdata *, xsd)
37 AROS_INTFUNC_INIT
39 struct VGAGfxBitMapData *data = NULL;
41 /* On my machine this fills the screen with colorful vertical stripes
42 instead of blanking. So for now we use software method.
43 Pavel Fedin.
44 vgaBlankScreen(0); */
46 if (xsd->visible)
47 data = OOP_INST_DATA(xsd->bmclass, xsd->visible);
49 if (data)
51 struct Box box = {0, 0, data->width - 1, data->height - 1};
53 vgaEraseArea(data, &box);
56 return 0;
58 AROS_INTFUNC_EXIT
61 /* Default graphics modes */
63 struct vgaModeDesc
64 vgaDefMode[NUM_MODES]={
65 {"640x480x4 @ 60Hz", // h: 31.5 kHz v: 60Hz
66 640,480,4,0,
68 640,664,760,800,0,
69 480,491,493,525}
70 #ifndef ONLY640
71 ,{"768x576x4 @ 54Hz", // h: 32.5 kHz v: 54Hz
72 768,576,4,1,
74 768,795,805,872,0,
75 576,577,579,600},
76 {"800x600x4 @ 52Hz", // h: 31.5 kHz v: 52Hz
77 800,600,4,1,
79 800,826,838,900,0, // 900
80 600,601,603,617} // 617
81 #endif
84 /*********************
85 ** GfxHidd::New() **
86 *********************/
88 #define NUM_SYNC_TAGS 11
89 #define SET_SYNC_TAG(taglist, idx, tag, val) \
90 taglist[idx].ti_Tag = aHidd_Sync_ ## tag; \
91 taglist[idx].ti_Data = val
93 VOID synctags_init(OOP_Class *cl, struct TagItem *tags, struct vgaModeDesc *md, STRPTR name)
95 ULONG clock = (md->clock == 1) ? 28322000 : 25175000;
97 SET_SYNC_TAG(tags, 0, PixelClock, clock );
98 SET_SYNC_TAG(tags, 1, HDisp, md->HDisplay );
99 SET_SYNC_TAG(tags, 2, VDisp, md->VDisplay );
100 SET_SYNC_TAG(tags, 3, HSyncStart, md->HSyncStart );
101 SET_SYNC_TAG(tags, 4, HSyncEnd, md->HSyncEnd );
102 SET_SYNC_TAG(tags, 5, HTotal, md->HTotal );
103 SET_SYNC_TAG(tags, 6, VSyncStart, md->VSyncStart );
104 SET_SYNC_TAG(tags, 7, VSyncEnd, md->VSyncEnd );
105 SET_SYNC_TAG(tags, 8, VTotal, md->VTotal );
106 SET_SYNC_TAG(tags, 9, Description, (IPTR)name );
107 tags[10].ti_Tag = TAG_DONE;
110 #define init_sync_tags(tags, md, name) synctags_init(cl, tags, md, name)
112 OOP_Object *VGAGfx__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
114 struct TagItem pftags[] = {
115 { aHidd_PixFmt_RedShift , 0 }, /* 0 */
116 { aHidd_PixFmt_GreenShift , 0 }, /* 1 */
117 { aHidd_PixFmt_BlueShift , 0 }, /* 2 */
118 { aHidd_PixFmt_AlphaShift , 0 }, /* 3 */
119 { aHidd_PixFmt_RedMask , 0x000000FC }, /* 4 */
120 { aHidd_PixFmt_GreenMask , 0x0000FC00 }, /* 5 */
121 { aHidd_PixFmt_BlueMask , 0x00FC0000 }, /* 6 */
122 { aHidd_PixFmt_AlphaMask , 0x00000000 }, /* 7 */
123 { aHidd_PixFmt_ColorModel , vHidd_ColorModel_Palette}, /* 8 */
124 { aHidd_PixFmt_Depth , 4 }, /* 9 */
125 { aHidd_PixFmt_BytesPerPixel, 1 }, /* 10 */
126 { aHidd_PixFmt_BitsPerPixel , 4 }, /* 11 */
127 { aHidd_PixFmt_StdPixFmt , vHidd_StdPixFmt_LUT8 }, /* 12 */
128 { aHidd_PixFmt_CLUTShift , 0 }, /* 13 */
129 { aHidd_PixFmt_CLUTMask , 0x0f }, /* 14 */
130 { aHidd_PixFmt_BitMapType , vHidd_BitMapType_Chunky }, /* 15 */
131 { TAG_DONE , 0UL }
134 struct TagItem sync_640_480[NUM_SYNC_TAGS];
135 #ifndef ONLY640
136 struct TagItem sync_758_576[NUM_SYNC_TAGS];
137 struct TagItem sync_800_600[NUM_SYNC_TAGS];
138 #endif
140 struct TagItem modetags[] = {
141 { aHidd_Sync_HMax , 16384 },
142 { aHidd_Sync_VMax , 16384 },
143 { aHidd_Gfx_PixFmtTags, (IPTR)pftags },
144 { aHidd_Gfx_SyncTags , (IPTR)sync_640_480 },
145 #ifndef ONLY640
146 { aHidd_Gfx_SyncTags , (IPTR)sync_758_576 },
147 { aHidd_Gfx_SyncTags , (IPTR)sync_800_600 },
148 #endif
149 { TAG_DONE, 0UL }
152 struct TagItem mytags[] = {
153 { aHidd_Gfx_ModeTags, (IPTR)modetags },
154 { aHidd_Name , (IPTR)"vgagfx.hidd" },
155 { aHidd_HardwareName , (IPTR)"VGA Compatible Controller" },
156 { aHidd_ProducerName , (IPTR)"IBM" },
157 { TAG_MORE, (IPTR)msg->attrList }
159 struct pRoot_New mymsg;
161 /* Do not allow to create more than one object */
162 if (XSD(cl)->vgahidd)
163 return NULL;
165 /* First init the sync tags */
166 init_sync_tags(sync_640_480, &vgaDefMode[0], "VGA:640x480");
167 #ifndef ONLY640
168 init_sync_tags(sync_758_576, &vgaDefMode[1], "VGA:758x576");
169 init_sync_tags(sync_800_600, &vgaDefMode[2], "VGA:800x600");
170 #endif
172 /* Init mymsg. We have to use our own message struct because
173 one should not alter the one passed to this method.
174 message structs passed to a method are always read-only.
175 (The user who called us might want to reuse the same msg struct
176 for several calls, but that will break if some method changes the
177 msg struct contents)
179 mymsg.mID = msg->mID; /* We got New() method and we are sending
180 the same method to the superclass */
181 mymsg.attrList = mytags;
182 msg = &mymsg;
184 EnterFunc(bug("VGAGfx::New()\n"));
186 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
187 XSD(cl)->vgahidd = o;
188 if (o) {
189 struct VGAGfxDriverData *data = OOP_INST_DATA(cl, o);
191 data->ResetInterrupt.is_Node.ln_Name = cl->ClassNode.ln_Name;
192 data->ResetInterrupt.is_Code = (VOID_FUNC)ResetHandler;
193 data->ResetInterrupt.is_Data = XSD(cl);
194 AddResetCallback(&data->ResetInterrupt);
196 ReturnPtr("VGAGfx::New", OOP_Object *, o);
199 VOID VGAGfx__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
201 struct VGAGfxDriverData *data = OOP_INST_DATA(cl, o);
203 RemResetCallback(&data->ResetInterrupt);
204 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
205 XSD(cl)->vgahidd = NULL;
208 VOID VGAGfx__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
210 ULONG idx;
211 BOOL found = FALSE;
212 if (IS_GFX_ATTR(msg->attrID, idx)) {
213 switch (idx) {
214 case aoHidd_Gfx_SupportsHWCursor:
215 case aoHidd_Gfx_NoFrameBuffer:
216 *msg->storage = (IPTR)TRUE;
217 found = TRUE;
218 break;
222 if (!found)
223 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
225 return;
228 /********** GfxHidd::CreateObject() ****************************/
229 OOP_Object *VGAGfx__Hidd_Gfx__CreateObject(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CreateObject *msg)
231 OOP_Object *object = NULL;
233 EnterFunc(bug("VGAGfx::CreateObject()\n"));
235 if (msg->cl == XSD(cl)->basebm)
237 struct TagItem mytags[] =
239 { TAG_IGNORE, TAG_IGNORE }, /* Placeholder for aHidd_BitMap_ClassPtr */
240 { TAG_MORE, (IPTR)msg->attrList }
243 struct pHidd_Gfx_CreateObject mymsg;
244 HIDDT_ModeID modeid;
246 modeid = (HIDDT_ModeID)GetTagData(aHidd_BitMap_ModeID, vHidd_ModeID_Invalid, msg->attrList);
247 if (vHidd_ModeID_Invalid != modeid) {
248 /* User supplied a valid modeid. We can use our class */
249 mytags[0].ti_Tag = aHidd_BitMap_ClassPtr;
250 mytags[0].ti_Data = (IPTR)XSD(cl)->bmclass;
252 /* Like in Gfx::New() we init a new message struct */
253 mymsg.mID = msg->mID;
254 mymsg.cl = msg->cl;
255 mymsg.attrList = mytags;
257 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)&mymsg);
259 else
260 object = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
262 ReturnPtr("VGAGfx::CreateObject", OOP_Object *, object);
265 /********* GfxHidd::Show() ***************************/
267 OOP_Object *VGAGfx__Hidd_Gfx__Show(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_Show *msg)
269 /* We currently use class static data instead of
270 object data. In addition we directly access
271 bitmap's private data. This is horribly wrong
272 and needs further refactoring */
273 struct VGAGfx_staticdata *data = XSD(cl);
274 struct Box box;
276 D(bug("[VGAGfx] Show(0x%p)\n", msg->bitMap));
277 ObtainSemaphore(&data->sema);
279 /* Remove old bitmap from the screen */
280 if (data->visible) {
281 IPTR tags[] = {aHidd_BitMap_Visible, FALSE, TAG_DONE};
283 D(bug("[VGAGfx] Old displayed bitmap: 0x%p\n", data->visible));
284 OOP_SetAttrs(data->visible, (struct TagItem *)tags);
287 if (msg->bitMap) {
288 /* If we have a bitmap to show, set it as visible */
289 IPTR tags[] = {aHidd_BitMap_Visible, TRUE, TAG_DONE};
290 OOP_Object *pixfmt;
291 IPTR depth;
293 OOP_GetAttr(msg->bitMap, aHidd_BitMap_PixFmt, (IPTR *)&pixfmt);
294 OOP_GetAttr(pixfmt, aHidd_PixFmt_Depth, &depth);
295 /* TODO: this should be brought in from SpriteBase of the colormap */
296 data->mouseBase = (depth > 4) ? 16 : (1 << depth) - 8;
298 OOP_SetAttrs(msg->bitMap, (struct TagItem *)tags);
299 data->visible = msg->bitMap;
300 } else {
301 /* Otherwise simply clear the framebuffer */
302 box.x1 = 0;
303 box.y1 = 0;
304 box.x2 = 639;
305 box.y2 = 479;
306 ObtainSemaphore(&data->HW_acc);
307 /* We use old visible bitmap pointer here since this bitmap
308 contains data about the current video mode */
309 vgaEraseArea(OOP_INST_DATA(data->bmclass, data->visible), &box);
310 draw_mouse(data);
311 ReleaseSemaphore(&data->HW_acc);
313 data->visible = NULL;
315 D(bug("[VGAGfx] New displayed bitmap: 0x%p\n", data->visible));
316 D(bug("[VGAGfx] Mouse pointer base color: %u\n", data->mouseBase));
318 ReleaseSemaphore(&data->sema);
319 return msg->bitMap;
322 /********* GfxHidd::CopyBox() ***************************/
324 VOID VGAGfx__Hidd_Gfx__CopyBox(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_CopyBox *msg)
326 ULONG mode;
327 unsigned char *src = 0, *dest = 0;
329 mode = GC_DRMD(msg->gc);
331 EnterFunc(bug("VGAGfx.BitMap::CopyBox (%d,%d) to (%d,%d) of dim %d,%d\n",
332 msg->srcX, msg->srcY, msg->destX, msg->destY, msg->width, msg->height));
333 D(bug("[VGAGfx] Src: 0x%p, dest: 0x%p\n", msg->src, msg->dest));
334 OOP_GetAttr(msg->src, aHidd_VGABitMap_Drawable, (IPTR *)&src);
335 OOP_GetAttr(msg->dest, aHidd_VGABitMap_Drawable, (IPTR *)&dest);
337 if (!dest || !src ||
338 ((mode != vHidd_GC_DrawMode_Copy) &&
339 (mode != vHidd_GC_DrawMode_And) &&
340 (mode != vHidd_GC_DrawMode_Xor) &&
341 (mode != vHidd_GC_DrawMode_Clear) &&
342 (mode != vHidd_GC_DrawMode_Invert)))
344 /* The source and/or destination object is no VGA bitmap, onscreen nor offscreen.
345 Or drawmode is not one of those we accelerate. Let the superclass do the
346 copying in a more general way
348 OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
349 return;
354 struct VGAGfxBitMapData *data = OOP_INST_DATA(OOP_OCLASS(msg->src), msg->src);
355 struct VGAGfxBitMapData *ddata = OOP_INST_DATA(OOP_OCLASS(msg->dest), msg->dest);
356 int i, width, phase, j;
357 BOOL descending;
359 // start of Source data
360 unsigned char *s_start = data->VideoData +
361 msg->srcX + (msg->srcY * data->bpr);
362 // adder for each line
363 ULONG s_add = data->bpr - msg->width;
364 ULONG cnt = msg->height;
366 unsigned char *d_start = ddata->VideoData +
367 msg->destX + (msg->destY * ddata->bpr);
368 ULONG d_add = ddata->bpr - msg->width;
370 width = msg->width;
372 if ((msg->srcY > msg->destY) || ((msg->srcY == msg->destY) && (msg->srcX >= msg->destX)))
374 if ((phase = ((IPTR)s_start & 3L)))
376 phase = 4 - phase;
377 if (phase > width) phase = width;
378 width -= phase;
380 descending = FALSE;
382 else
384 s_start += (cnt - 1) * data->bpr + width;
385 d_start += (cnt - 1) * ddata->bpr + width;
387 phase = ((IPTR)s_start & 3L);
388 if (phase > width) phase = width;
389 width -= phase;
391 descending = TRUE;
394 switch(mode)
396 case vHidd_GC_DrawMode_Copy:
397 HIDD_BM_CopyMemBox8(msg->dest,
398 data->VideoData,
399 msg->srcX,
400 msg->srcY,
401 ddata->VideoData,
402 msg->destX,
403 msg->destY,
404 msg->width,
405 msg->height,
406 data->bpr,
407 ddata->bpr);
408 break;
410 case vHidd_GC_DrawMode_And:
411 if (!descending)
413 while (cnt--)
415 i = width;
416 j = phase;
417 while (j--)
419 *d_start++ &= *s_start++;
421 while (i >= 4)
423 *((ULONG*)d_start) &= *((ULONG*)s_start);
424 d_start += 4;
425 s_start += 4;
426 i -= 4;
428 while (i--)
430 *d_start++ &= *s_start++;
432 d_start += d_add;
433 s_start += s_add;
436 else
438 while (cnt--)
440 i = width;
441 j = phase;
442 while (j--)
444 *--d_start &= *--s_start;
446 while (i >= 4)
448 d_start -= 4;
449 s_start -= 4;
450 *((ULONG*)d_start) &= *((ULONG*)s_start);
451 i -= 4;
453 while (i--)
455 *--d_start &= *--s_start;
457 d_start -= d_add;
458 s_start -= s_add;
462 break;
464 case vHidd_GC_DrawMode_Xor:
465 if (!descending)
467 while (cnt--)
469 i = width;
470 j = phase;
471 while (j--)
473 *d_start++ ^= *s_start++;
475 while (i >= 4)
477 *((ULONG*)d_start) ^= *((ULONG*)s_start);
478 d_start += 4;
479 s_start += 4;
480 i -= 4;
482 while (i--)
484 *d_start++ ^= *s_start++;
486 d_start += d_add;
487 s_start += s_add;
490 else
492 while (cnt--)
494 i = width;
495 j = phase;
496 while (j--)
498 *--d_start ^= *--s_start;
500 while (i >= 4)
502 d_start -= 4;
503 s_start -= 4;
504 *((ULONG*)d_start) ^= *((ULONG*)s_start);
505 i -= 4;
507 while (i--)
509 *--d_start ^= *--s_start;
511 d_start -= d_add;
512 s_start -= s_add;
515 break;
517 case vHidd_GC_DrawMode_Clear:
518 if (!descending)
520 while (cnt--)
522 i = width;
523 j = phase;
524 while (j--)
526 *d_start++ = 0;
528 while (i >= 4)
530 *((ULONG*)d_start) = 0;
531 d_start += 4;
532 i -= 4;
534 while (i--)
536 *d_start++ = 0;
538 d_start += d_add;
541 else
543 while (cnt--)
545 i = width;
546 j = phase;
547 while (j--)
549 *--d_start = 0;
551 while (i >= 4)
553 d_start -= 4;
554 *((ULONG*)d_start) = 0;
555 i -= 4;
557 while (i--)
559 *--d_start = 0;
561 d_start -= d_add;
564 break;
566 case vHidd_GC_DrawMode_Invert:
567 if (!descending)
569 while (cnt--)
571 i = width;
572 j = phase;
573 while (j--)
575 *d_start = ~*d_start;
576 d_start++;
578 while (i >= 4)
580 *((ULONG*)d_start) = ~*((ULONG*)d_start);
581 d_start += 4;
582 i -= 4;
584 while (i--)
586 *d_start = ~*d_start;
587 d_start++;
589 d_start += d_add;
592 else
594 while (cnt--)
596 i = width;
597 j = phase;
598 while (j--)
600 *d_start = ~*d_start;
601 d_start--;
603 while (i >= 4)
605 d_start -= 4;
606 *((ULONG*)d_start) = ~*((ULONG*)d_start);
607 i -= 4;
609 while (i--)
611 *d_start = ~*d_start;
612 d_start--;
614 d_start -= d_add;
616 break;
618 break;
620 } /* switch(mode) */
622 ReturnVoid("VGAGfx.BitMap::CopyBox");
625 /********** GfxHidd::SetCursorShape() ****************************/
627 BOOL VGAGfx__Hidd_Gfx__SetCursorShape(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorShape *msg)
629 struct VGAGfx_staticdata *data = XSD(cl);
630 IPTR curs_width, curs_height;
631 UBYTE *new_curs_pixels;
633 OOP_GetAttr(msg->shape, aHidd_BitMap_Width, &curs_width);
634 OOP_GetAttr(msg->shape, aHidd_BitMap_Height, &curs_height);
636 new_curs_pixels = AllocMem(curs_width * curs_height, MEMF_ANY);
637 if (!new_curs_pixels)
638 return FALSE;
640 HIDD_BM_GetImage(msg->shape, new_curs_pixels, curs_width, 0, 0, curs_width, curs_height, vHidd_StdPixFmt_LUT8);
642 ObtainSemaphore(&data->HW_acc);
643 erase_mouse(data);
644 if (data->mouseShape)
645 FreeMem(data->mouseShape, data->mouseW * data->mouseH);
647 data->mouseW = curs_width;
648 data->mouseH = curs_height;
649 data->mouseShape = new_curs_pixels;
650 draw_mouse(data);
652 ReleaseSemaphore(&data->HW_acc);
653 return TRUE;
656 /********** GfxHidd::SetCursorPos() ****************************/
658 BOOL VGAGfx__Hidd_Gfx__SetCursorPos(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorPos *msg)
660 ObtainSemaphore(&XSD(cl)->HW_acc);
662 erase_mouse(XSD(cl));
664 XSD(cl)->mouseX = (short)msg->x;
665 XSD(cl)->mouseY = (short)msg->y;
667 if (XSD(cl)->visible)
669 struct VGAGfxBitMapData *bm_data =
670 OOP_INST_DATA(XSD(cl)->bmclass, XSD(cl)->visible);
672 if (XSD(cl)->mouseX < 0) XSD(cl)->mouseX = 0;
673 if (XSD(cl)->mouseY < 0) XSD(cl)->mouseY = 0;
674 if (XSD(cl)->mouseX >= bm_data->width) XSD(cl)->mouseX =
675 bm_data->width - 1;
676 if (XSD(cl)->mouseY >= bm_data->height) XSD(cl)->mouseY =
677 bm_data->height - 1;
680 draw_mouse(XSD(cl));
682 ReleaseSemaphore(&XSD(cl)->HW_acc);
684 return TRUE;
687 /********** GfxHidd::SetCursorVisible() ****************************/
689 VOID VGAGfx__Hidd_Gfx__SetCursorVisible(OOP_Class *cl, OOP_Object *o, struct pHidd_Gfx_SetCursorVisible *msg)
691 XSD(cl)->mouseVisible = msg->visible;
693 ObtainSemaphore(&XSD(cl)->HW_acc);
694 erase_mouse(XSD(cl));
695 draw_mouse(XSD(cl));
696 ReleaseSemaphore(&XSD(cl)->HW_acc);
699 /* end of stuff added by stegerg */
700 /*******************************************************************/
702 void draw_mouse(struct VGAGfx_staticdata *xsd)
704 int pix;
705 unsigned char *ptr, *data;
706 int x, y, width, fg, x_i, y_i;
708 if (!xsd->mouseShape)
709 return;
711 if (xsd->mouseVisible)
713 if (xsd->visible)
715 struct VGAGfxBitMapData *bm_data =
716 OOP_INST_DATA(xsd->bmclass, xsd->visible);
718 /* Get display width */
719 width = bm_data->disp_width;
721 /* And pointer data */
722 data = xsd->mouseShape;
724 ObtainSemaphore(&xsd->HW_acc);
726 outw(0x3c4,0x0f02);
727 outw(0x3ce,0x0005);
728 outw(0x3ce,0x0003);
729 outw(0x3ce,0x0f01);
731 for (y_i = 0, y = xsd->mouseY ; y_i < xsd->mouseH; y_i++, y++)
733 for (x_i = 0, x = xsd->mouseX; x_i < xsd->mouseW; x_i++, x++)
735 ptr = (char *)(IPTR)(0xa0000 + (x + (y * width)) / 8);
736 pix = 0x8000 >> (x % 8);
738 fg = (char)*data++;
740 if (fg && (x < width))
742 fg += xsd->mouseBase;
743 outw(0x3ce,pix | 8);
744 outw(0x3ce,(fg << 8));
746 *ptr |= 1; // This or'ed value isn't important
751 ReleaseSemaphore(&xsd->HW_acc);
756 void erase_mouse(struct VGAGfx_staticdata *data)
758 if (data->visible) {
759 struct Box box = {0, 0, 0, 0};
761 box.x1 = data->mouseX;
762 box.y1 = data->mouseY;
763 box.x2 = box.x1 + data->mouseW;
764 box.y2 = box.y1 + data->mouseH;
766 vgaRefreshArea(OOP_INST_DATA(data->bmclass, data->visible), &box);