1 /*
2 NatFeat VDI driver
3
4 ARAnyM (C) 2005,2006 Patrice Mandin
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "sysdeps.h"
22 #include "cpu_emulation.h"
23 #include "parameters.h"
24 #include "dirty_rects.h"
25 #include "host_surface.h"
26 #include "nfvdi.h"
27 #include "fvdidrv_nfapi.h" // keep in sync with same file in fVDI CVS
28 #include "hostscreen.h"
29 #include "host.h"
30
31 #include "cpu_emulation.h"
32
33 #define DEBUG 0
34 #include "debug.h"
35
36 #include <new>
37
38 /*--- Defines ---*/
39
40 #define EINVFN -32
41
42 /*--- Types ---*/
43
44 /*--- Variables ---*/
45
46 /*--- Public functions ---*/
47
dispatch(uint32 fncode)48 int32 VdiDriver::dispatch(uint32 fncode)
49 {
50 int32 ret = EINVFN;
51
52 D(bug("nfvdi: dispatch(%u)", fncode));
53
54 if (fncode & 0x80000000) {
55 if (!events)
56 return 1;
57
58 fncode &= 0x7fffffff;
59 if (fncode & 0x8000) {
60 mouse_x = fncode >> 16;
61 mouse_y = fncode & 0x7fff;
62 new_event |= 1;
63 } else {
64 switch (fncode >> 28) {
65 case 3:
66 buttons = ((fncode & 1) << 1) | ((fncode & 2) >> 1);
67 new_event |= 2;
68 break;
69 case 4:
70 wheel += (signed char)(fncode & 0xff);
71 new_event |= 4;
72 break;
73 case 5:
74 vblank++;
75 new_event |= 8;
76 break;
77 }
78 }
79 TriggerInt3();
80
81 return 0;
82 }
83
84 if (fncode == FVDI_EVENT) {
85 memptr array = getParameter(0);
86 switch((int)array) {
87 case 0:
88 return bx_options.nfvdi.use_host_mouse_cursor;
89 case 1:
90 new_event = buttons = wheel = vblank = 0;
91 events = 1;
92 break;
93 default:
94 int n = 0;
95 if (new_event & 1) {
96 WriteInt32(array + n++ * 4, 2);
97 WriteInt32(array + n++ * 4,
98 (mouse_x << 16) | (mouse_y & 0xffff));
99 }
100 if (new_event & 2) {
101 WriteInt32(array + n++ * 4, 3);
102 WriteInt32(array + n++ * 4, buttons);
103 }
104 if (new_event & 4) {
105 WriteInt32(array + n++ * 4, 4);
106 WriteInt32(array + n++ * 4, 0x00000000 | (wheel & 0xffff));
107 }
108 if (new_event & 8) {
109 WriteInt32(array + n++ * 4, 5);
110 WriteInt32(array + n++ * 4, vblank);
111 }
112 if (n < 8)
113 WriteInt32(array + n * 4, 0);
114 new_event = wheel = vblank = 0;
115 break;
116 }
117 return 1;
118 }
119
120 switch(fncode) {
121 case FVDI_GET_VERSION:
122 ret = FVDIDRV_NFAPI_VERSION;
123 break;
124 case FVDI_GET_PIXEL:
125 ret = getPixel((memptr)getParameter(0),(memptr)getParameter(1),getParameter(2),getParameter(3));
126 break;
127 case FVDI_PUT_PIXEL:
128 ret = putPixel((memptr)getParameter(0),(memptr)getParameter(1),getParameter(2),getParameter(3),getParameter(4));
129 break;
130 case FVDI_MOUSE:
131 {
132 // mode (0/1 - move, 2 - hide, 3 - show)
133 // These are only valid when not mode
134 uint32 mask = getParameter(3);
135 if ( mask > 7 ) {
136 ret = drawMouse((memptr)getParameter(0), // wk
137 getParameter(1), getParameter(2), // x, y
138 mask, // mask*
139 getParameter(4), // data*
140 getParameter(5), getParameter(6), // hot_x, hot_y
141 getParameter(7), // fgColor
142 getParameter(8), // bgColor
143 getParameter(9)); // type
144 } else {
145 ret = drawMouse((memptr)getParameter(0), // wk
146 getParameter(1), getParameter(2), // x, y
147 mask,
148 0, 0, 0, 0, 0, 0); // dummy
149 }
150 }
151 break;
152 case FVDI_EXPAND_AREA:
153 ret = expandArea((memptr)getParameter(0), // vwk
154 (memptr)getParameter(1), // src MFDB*
155 getParameter(2), getParameter(3), // sx, sy
156 (memptr)getParameter(4), // dest MFDB*
157 getParameter(5), getParameter(6), // dx, dy
158 getParameter(7), // width
159 getParameter(8), // height
160 getParameter(9), // logical operation
161 getParameter(10), // fgColor
162 getParameter(11)); // bgColor
163 break;
164 case FVDI_FILL_AREA:
165 ret = fillArea((memptr)getParameter(0), // vwk
166 getParameter(1), getParameter(2), // x, y
167 // table*, table length/type (0 - y/x1/x2 spans)
168 getParameter(3), getParameter(4), // width, height
169 (memptr)getParameter(5), // pattern*
170 getParameter(6), // fgColor
171 getParameter(7), // bgColor
172 getParameter(8), // mode
173 getParameter(9)); // interior style
174 break;
175 case FVDI_BLIT_AREA:
176 ret = blitArea((memptr)getParameter(0), // vwk
177 (memptr)getParameter(1), // src MFDB*
178 getParameter(2), getParameter(3), // sx, sy
179 (memptr)getParameter(4), // dest MFDB*
180 getParameter(5), getParameter(6), // dx, dy
181 getParameter(7), // width
182 getParameter(8), // height
183 getParameter(9)); // logical operation
184 break;
185 case FVDI_LINE:
186 ret = drawLine((memptr)getParameter(0), // vwk
187 getParameter(1), getParameter(2), // x1, y1
188 // table*, table length/type (0 - coordinate pairs, 1 - pairs + moves)
189 getParameter(3), getParameter(4), // x2, y2
190 // move point count, move index*
191 getParameter(5) & 0xffff, // pattern
192 getParameter(6), // fgColor
193 getParameter(7), // bgColor
194 getParameter(8) & 0xffff, // logical operation
195 (memptr)getParameter(9)); // clip rectangle* (0 or long[4])
196 break;
197 case FVDI_FILL_POLYGON:
198 ret = fillPoly((memptr)getParameter(0), // vwk
199 (memptr)getParameter(1), // points*
200 getParameter(2), // point count
201 (memptr)getParameter(3), // index*
202 getParameter(4), // index count
203 (memptr)getParameter(5), // pattern*
204 getParameter(6), // fgColor
205 getParameter(7), // bgColor
206 getParameter(8), // logic operation
207 getParameter(9), // interior style
208 (memptr)getParameter(10)); // clip rectangle
209 break;
210 case FVDI_TEXT_AREA:
211 ret = drawText((memptr)getParameter(0), // vwk
212 (memptr)getParameter(1), // text*
213 getParameter(2), // length
214 getParameter(3), // dst_x
215 getParameter(4), // dst_y
216 (memptr)getParameter(5), // font*
217 getParameter(6), // width
218 getParameter(7), // height
219 getParameter(8), // fgColor
220 getParameter(9), // bgColor
221 getParameter(10), // logic operation
222 (memptr)getParameter(11)); // clip rectangle
223 break;
224 case FVDI_GET_HWCOLOR:
225 getHwColor(getParameter(0), getParameter(1), getParameter(2), getParameter(3), getParameter(4));
226 break;
227 case FVDI_SET_COLOR:
228 setColor(getParameter(4), getParameter(0), getParameter(1), getParameter(2), getParameter(3));
229 break;
230 case FVDI_GET_FBADDR:
231 ret = getFbAddr();
232 break;
233 case FVDI_SET_RESOLUTION:
234 setResolution(getParameter(0),getParameter(1),getParameter(2));
235 ret = 0;
236 break;
237 case FVDI_GET_WIDTH:
238 ret = getWidth();
239 break;
240 case FVDI_GET_HEIGHT:
241 ret = getHeight();
242 break;
243 case FVDI_OPENWK:
244 ret = openWorkstation();
245 break;
246 case FVDI_CLOSEWK:
247 ret = closeWorkstation();
248 break;
249 case FVDI_GETBPP:
250 ret = getBpp();
251 break;
252 default:
253 D(bug("nfvdi: unimplemented function #%d", fncode));
254 break;
255 }
256
257 D(bug("nfvdi: function returning with 0x%08x", ret));
258 return ret;
259 }
260
VdiDriver()261 VdiDriver::VdiDriver()
262 : surface(NULL)
263 {
264 index_count = crossing_count = point_count = 0;
265 alloc_index = alloc_crossing = alloc_point = NULL;
266 cursor = NULL;
267 Mouse.storage.x = Mouse.storage.y = Mouse.storage.width = Mouse.storage.height = 0;
268 events = 0;
269 }
270
~VdiDriver()271 VdiDriver::~VdiDriver()
272 {
273 delete[] alloc_index;
274 delete[] alloc_crossing;
275 delete[] alloc_point;
276
277 if (cursor) {
278 SDL_FreeCursor(cursor);
279 cursor = NULL;
280 }
281
282 if (surface) {
283 host->video->destroySurface(surface);
284 }
285 }
286
reset()287 void VdiDriver::reset()
288 {
289 host->video->setVidelRendering(true);
290 }
291
292 /*--- Protected functions ---*/
293
chunkyToBitplane(uint8 * sdlPixelData,uint16 bpp,uint16 bitplaneWords[8])294 void VdiDriver::chunkyToBitplane(uint8 *sdlPixelData, uint16 bpp,
295 uint16 bitplaneWords[8])
296 {
297 DUNUSED(bpp);
298 for (int l=0; l<16; l++) {
299 uint8 data = sdlPixelData[l]; // note: this is about 2000 dryhstones speedup (the local variable)
300
301 bitplaneWords[0] <<= 1; bitplaneWords[0] |= (data >> 0) & 1;
302 bitplaneWords[1] <<= 1; bitplaneWords[1] |= (data >> 1) & 1;
303 bitplaneWords[2] <<= 1; bitplaneWords[2] |= (data >> 2) & 1;
304 bitplaneWords[3] <<= 1; bitplaneWords[3] |= (data >> 3) & 1;
305 bitplaneWords[4] <<= 1; bitplaneWords[4] |= (data >> 4) & 1;
306 bitplaneWords[5] <<= 1; bitplaneWords[5] |= (data >> 5) & 1;
307 bitplaneWords[6] <<= 1; bitplaneWords[6] |= (data >> 6) & 1;
308 bitplaneWords[7] <<= 1; bitplaneWords[7] |= (data >> 7) & 1;
309 }
310 }
311
applyBlitLogOperation(int logicalOperation,uint32 destinationData,uint32 sourceData)312 uint32 VdiDriver::applyBlitLogOperation(int logicalOperation,
313 uint32 destinationData, uint32 sourceData)
314 {
315 switch(logicalOperation) {
316 case ALL_WHITE:
317 destinationData = 0;
318 break;
319 case S_AND_D:
320 destinationData = sourceData & destinationData;
321 break;
322 case S_AND_NOTD:
323 destinationData = sourceData & ~destinationData;
324 break;
325 case S_ONLY:
326 destinationData = sourceData;
327 break;
328 case NOTS_AND_D:
329 destinationData = ~sourceData & destinationData;
330 break;
331 /*
332 case D_ONLY:
333 destinationData = destinationData;
334 break;
335 */
336 case S_XOR_D:
337 destinationData = sourceData ^ destinationData;
338 break;
339 case S_OR_D:
340 destinationData = sourceData | destinationData;
341 break;
342 case NOT_SORD:
343 destinationData = ~(sourceData | destinationData);
344 break;
345 case NOT_SXORD:
346 destinationData = ~(sourceData ^ destinationData);
347 break;
348 case D_INVERT:
349 destinationData = ~destinationData;
350 break;
351 case S_OR_NOTD:
352 destinationData = sourceData | ~destinationData;
353 break;
354 case NOT_S:
355 destinationData = ~sourceData;
356 break;
357 case NOTS_OR_D:
358 destinationData = ~sourceData | destinationData;
359 break;
360 case NOT_SANDD:
361 destinationData = ~(sourceData & destinationData);
362 break;
363 case ALL_BLACK:
364 destinationData = 0xffffffffUL;
365 break;
366 }
367
368 return destinationData;
369 }
370
getSurface(void)371 HostSurface *VdiDriver::getSurface(void)
372 {
373 return surface;
374 }
375
setResolution(int32 width,int32 height,int32 depth)376 void VdiDriver::setResolution(int32 width, int32 height, int32 depth)
377 {
378 if (bx_options.autozoom.fixedsize) {
379 width = bx_options.autozoom.width;
380 height = bx_options.autozoom.height;
381 if ((bx_options.autozoom.width == 0)
382 && (bx_options.autozoom.height == 0))
383 {
384 width = host->video->getWidth();
385 height = host->video->getHeight();
386 }
387 }
388
389 if (width<64) {
390 width = 64;
391 }
392 if (height<64) {
393 height = 64;
394 }
395 if (depth<8) {
396 depth = 8;
397 }
398
399 /* Recreate surface if needed */
400 if (surface) {
401 if (surface->getBpp() == depth) {
402 if ((surface->getWidth() != width) || (surface->getHeight() != height)) {
403 surface->resize(width, height);
404 }
405 } else {
406 delete surface;
407 surface = NULL;
408 }
409 }
410 if (surface==NULL) {
411 surface = host->video->createSurface(width,height,depth);
412 }
413
414 /* TODO: restore palette ? */
415 }
416
getWidth(void)417 int32 VdiDriver::getWidth(void)
418 {
419 return (surface ? surface->getWidth() : 0);
420 }
421
getHeight(void)422 int32 VdiDriver::getHeight(void)
423 {
424 return (surface ? surface->getHeight() : 0);
425 }
426
openWorkstation(void)427 int32 VdiDriver::openWorkstation(void)
428 {
429 host->video->setVidelRendering(false);
430 return 1;
431 }
432
closeWorkstation(void)433 int32 VdiDriver::closeWorkstation(void)
434 {
435 host->video->setVidelRendering(true);
436 return 1;
437 }
438
getBpp(void)439 int32 VdiDriver::getBpp(void)
440 {
441 if (!surface) {
442 return 0;
443 }
444 SDL_Surface *sdl_surf = surface->getSdlSurface();
445 return (sdl_surf ? sdl_surf->format->BitsPerPixel : 0);
446 }
447
448 // The polygon code needs some arrays of unknown size
449 // These routines and members are used so that no unnecessary allocations are done
AllocIndices(int n)450 bool VdiDriver::AllocIndices(int n)
451 {
452 if (n > index_count) {
453 D2(bug("More indices %d->%d\n", index_count, n));
454 int count = n * 2; // Take a few extra right away
455 int16* tmp = new(std::nothrow) int16[count];
456 if (!tmp) {
457 count = n;
458 tmp = new(std::nothrow) int16[count];
459 }
460 if (tmp) {
461 delete[] alloc_index;
462 alloc_index = tmp;
463 index_count = count;
464 }
465 }
466
467 return index_count >= n;
468 }
469
AllocCrossings(int n)470 bool VdiDriver::AllocCrossings(int n)
471 {
472 if (n > crossing_count) {
473 D2(bug("More crossings %d->%d\n", crossing_count, n));
474 int count = n * 2; // Take a few extra right away
475 int16* tmp = new(std::nothrow) int16[count];
476 if (!tmp) {
477 count = (n * 3) / 2; // Try not so many extra
478 tmp = new(std::nothrow) int16[count];
479 }
480 if (!tmp) {
481 count = n; // This is going to be slow if it goes on...
482 tmp = new(std::nothrow) int16[count];
483 }
484 if (tmp) {
485 memcpy(tmp, alloc_crossing, crossing_count * sizeof(*alloc_crossing));
486 delete[] alloc_crossing;
487 alloc_crossing = tmp;
488 crossing_count = count;
489 }
490 }
491
492 return crossing_count >= n;
493 }
494
AllocPoints(int n)495 bool VdiDriver::AllocPoints(int n)
496 {
497 if (n > point_count) {
498 D2(bug("More points %d->%d", point_count, n));
499 int count = n * 2; // Take a few extra right away
500 int16* tmp = new(std::nothrow) int16[count * 2];
501 if (!tmp) {
502 count = n;
503 tmp = new(std::nothrow) int16[count * 2];
504 }
505 if (tmp) {
506 delete[] alloc_point;
507 alloc_point = tmp;
508 point_count = count;
509 }
510 }
511
512 return point_count >= n;
513 }
514
515
516 /*--- Virtual functions ---*/
517
518 /**
519 * Get a coloured pixel.
520 *
521 * c_read_pixel(Virtual *vwk, MFDB *mfdb, long x, long y)
522 * read_pixel
523 * In: a1 VDI struct, source MFDB
524 * d1 x
525 * d2 y
526 *
527 * Only one mode here.
528 *
529 * Note that a1 does not point to the VDI struct, but to a place in memory
530 * where the VDI struct pointer can be found. Four bytes beyond that address
531 * is a pointer to the destination MFDB.
532 *
533 * Since an MFDB is passed, the source is not necessarily the screen.
534 **/
535
getPixel(memptr vwk,memptr src,int32 x,int32 y)536 int32 VdiDriver::getPixel(memptr vwk, memptr src, int32 x, int32 y)
537 {
538 DUNUSED(vwk);
539 uint32 row_address, color = 0;
540 uint16 planes;
541
542 if (!src) {
543 D(bug("VdiDriver::getPixel(): source is NULL"));
544 return color;
545 }
546
547 planes = ReadInt16(src + MFDB_NPLANES);
548 row_address = ReadInt32(src + MFDB_ADDRESS) +
549 ReadInt16(src + MFDB_WDWIDTH) * 2 * planes * y;
550
551 switch (planes) {
552 case 8:
553 color = ReadInt8(row_address + x);
554 break;
555 case 16:
556 color = ReadInt16(row_address + x * 2);
557 break;
558 case 24:
559 color = ((uint32)ReadInt8(row_address + x * 3) << 16) +
560 ((uint32)ReadInt8(row_address + x * 3 + 1) << 8) +
561 (uint32)ReadInt8(row_address + x * 3 + 2);
562 break;
563 case 32:
564 color = ReadInt32(row_address + x * 4);
565 break;
566 }
567
568 return color;
569 }
570
571 /**
572 * Set a coloured pixel.
573 *
574 * c_write_pixel(Virtual *vwk, MFDB *mfdb, long x, long y, long colour)
575 * write_pixel
576 * In: a1 VDI struct, destination MFDB
577 * d0 colour
578 * d1 x or table address
579 * d2 y or table length (high) and type (low)
580 * XXX: ?
581 *
582 * This function has two modes:
583 * - single pixel
584 * - table based multi pixel (special mode 0 (low word of 'y'))
585 *
586 * Note that a1 does not point to the VDI struct, but to a place in memory
587 * where the VDI struct pointer can be found. Four bytes beyond that address
588 * is a pointer to the destination MFDB.
589 *
590 * As usual, only the first one is necessary, and a return with d0 = -1
591 * signifies that a special mode should be broken down to the basic one.
592 *
593 * Since an MFDB is passed, the destination is not necessarily the screen.
594 **/
595
putPixel(memptr vwk,memptr dst,int32 x,int32 y,uint32 color)596 int32 VdiDriver::putPixel(memptr vwk, memptr dst, int32 x, int32 y,
597 uint32 color)
598 {
599 if (vwk & 1)
600 return 0;
601
602 if (!dst) {
603 D(bug("VdiDriver::putPixel(): destination is NULL"));
604 return color;
605 }
606
607 uint16 planes = ReadInt16(dst + MFDB_NPLANES);
608 uint32 row_address = ReadInt32(dst + MFDB_ADDRESS) +
609 ReadInt16(dst + MFDB_WDWIDTH) * 2 * planes * y;
610
611 switch (planes) {
612 case 8:
613 WriteInt8(row_address + x, color);
614 break;
615 case 16:
616 WriteInt16(row_address + x * 2, color);
617 break;
618 case 24:
619 WriteInt8(row_address + x * 3, (color >> 16) & 0xff);
620 WriteInt8(row_address + x * 3 + 1, (color >> 8) & 0xff);
621 WriteInt8(row_address + x * 3 + 2, color & 0xff);
622 break;
623 case 32:
624 WriteInt32(row_address + x * 4, color);
625 break;
626 }
627
628 return 1;
629 }
630
631 /**
632 * Draw the mouse
633 *
634 * Draw a coloured line between two points.
635 *
636 * c_mouse_draw(Workstation *wk, long x, long y, Mouse *mouse)
637 * mouse_draw
638 * In: a1 Pointer to Workstation struct
639 * d0/d1 x,y
640 * d2 0 - move shown 1 - move hidden 2 - hide 3 - show >3 - change shape (pointer to mouse struct)
641 *
642 * Unlike all the other functions, this does not receive a pointer to a VDI
643 * struct, but rather one to the screen's workstation struct. This is
644 * because the mouse handling concerns the screen as a whole (and the
645 * routine is also called from inside interrupt routines).
646 *
647 * The Mouse structure pointer doubles as a mode variable. If it is a small
648 * number, the mouse's state is supposed to change somehow, while a large
649 * number is a pointer to a new mouse shape.
650 *
651 * This is currently not a required function, but it probably should be.
652 * The fallback handling is not done in the usual way, and to make it
653 * at least somewhat usable, the mouse pointer is reduced to 4x4 pixels.
654 *
655 * typedef struct Fgbg_ {
656 * short background;
657 * short foreground;
658 * } Fgbg;
659 *
660 * typedef struct Mouse_ {
661 * 0 short type;
662 * 2 short hide;
663 * struct position_ {
664 * 4 short x;
665 * 6 short y;
666 * } position;
667 * struct hotspot_ {
668 * 8 short x;
669 * 10 short y;
670 * } hotspot;
671 * 12 Fgbg colour;
672 * 16 short mask[16];
673 * 48 short data[16];
674 * 80 void *extra_info;
675 * } Mouse;
676 **/
677
restoreMouseBackground(void)678 void VdiDriver::restoreMouseBackground(void)
679 {
680 }
681
saveMouseBackground(int16,int16,int16,int16)682 void VdiDriver::saveMouseBackground(int16 /*x*/, int16 /*y*/, int16 /*width*/,
683 int16 /*height*/)
684 {
685 }
686
drawMouse(memptr wk,int32 x,int32 y,uint32 mode,uint32 data,uint32 hot_x,uint32 hot_y,uint32 fgColor,uint32 bgColor,uint32 mouse_type)687 int32 VdiDriver::drawMouse(memptr wk, int32 x, int32 y, uint32 mode,
688 uint32 data, uint32 hot_x, uint32 hot_y, uint32 fgColor, uint32 bgColor,
689 uint32 mouse_type)
690 {
691 DUNUSED(wk);
692 DUNUSED(fgColor);
693 DUNUSED(bgColor);
694 DUNUSED(mouse_type);
695
696 D(bug("VdiDriver::drawMouse(): x,y = [%ld,%ld] mode=%ld", x, y, mode));
697
698 switch (mode) {
699 case 0:
700 case 1:
701 break;
702 case 2:
703 #if 0
704 SDL_ShowCursor(SDL_DISABLE);
705 #endif
706 break;
707 case 3:
708 SDL_ShowCursor(SDL_ENABLE);
709 break;
710 case 4:
711 case 5:
712 host->video->WarpMouse(x, y);
713 break;
714 case 6:
715 case 7:
716 break;
717 default:
718 {
719 if (cursor)
720 SDL_FreeCursor(cursor);
721
722 cursor = SDL_CreateCursor(
723 (Uint8 *)Atari2HostAddr(data),
724 (Uint8 *)Atari2HostAddr(mode),
725 16, 16, hot_x, hot_y
726 );
727
728 SDL_SetCursor(cursor);
729 }
730 break;
731 }
732
733 return 1;
734 }
735
736 /**
737 * Expand a monochrome area to a coloured one.
738 *
739 * c_expand_area(Virtual *vwk, MFDB *src, long src_x, long src_y,
740 * MFDB *dst, long dst_x, long dst_y,
741 * long w, long h, long operation, long colour)
742 * expand_area
743 * In: a1 VDI struct, destination MFDB, VDI struct, source MFDB
744 * d0 height and width to move (high and low word)
745 * d1-d2 source coordinates
746 * d3-d4 destination coordinates
747 * d6 background and foreground colour
748 * d7 logic operation
749 *
750 * Only one mode here.
751 *
752 * Note that a1 does not point to the VDI struct, but to a place in memory
753 * where the VDI struct pointer can be found. Four bytes beyond that address
754 * is a pointer to the destination MFDB, and then comes a VDI struct
755 * pointer again (the same) and a pointer to the source MFDB.
756 *
757 * Since MFDBs are passed, the screen is not necessarily involved.
758 *
759 * A return with 0 gives a fallback (normally pixel by pixel drawing by
760 * the fVDI engine).
761 *
762 * typedef struct MFDB_ {
763 * short *address;
764 * short width;
765 * short height;
766 * short wdwidth;
767 * short standard;
768 * short bitplanes;
769 * short reserved[3];
770 * } MFDB;
771 **/
772
expandArea(memptr vwk,memptr src,int32 sx,int32 sy,memptr dest,int32 dx,int32 dy,int32 w,int32 h,uint32 logOp,uint32 fgColor,uint32 bgColor)773 int32 VdiDriver::expandArea(memptr vwk, memptr src, int32 sx, int32 sy,
774 memptr dest, int32 dx, int32 dy, int32 w, int32 h, uint32 logOp,
775 uint32 fgColor, uint32 bgColor)
776 {
777 DUNUSED(vwk);
778
779 if (!dest) {
780 D(bug("VdiDriver::expandArea(): destination is NULL"));
781 return 1;
782 }
783
784 if (getBpp() == 8) {
785 fgColor &= 0xff;
786 bgColor &= 0xff;
787 }
788
789 uint16 pitch = ReadInt16(src + MFDB_WDWIDTH) * 2; // the byte width (always monochrom);
790 memptr data = ReadInt32(src + MFDB_ADDRESS) + sy * pitch; // MFDB *src->address;
791
792 D(bug("fVDI: %s %x %d,%d:%d,%d:%d,%d (%lx, %lx)", "expandArea", logOp, sx, sy, dx, dy, w, h, fgColor, bgColor ));
793 D2(bug("fVDI: %s %x,%x : %x,%x", "expandArea - MFDB addresses", src, dest, ReadInt32( src ),ReadInt32( dest )));
794 D2(bug("fVDI: %s %x, %d, %d", "expandArea - src: data address, MFDB wdwidth << 1, bitplanes", data, pitch, ReadInt16( src + MFDB_NPLANES )));
795 D2(bug("fVDI: %s %x, %d, %d", "expandArea - dst: data address, MFDB wdwidth << 1, bitplanes", ReadInt32(dest), ReadInt16(dest + MFDB_WDWIDTH) * (ReadInt16(dest + MFDB_NPLANES) >> 2), ReadInt16(dest + MFDB_NPLANES)));
796
797 uint32 destPlanes = (uint32)ReadInt16( dest + MFDB_NPLANES );
798 uint32 destPitch = ReadInt16(dest + MFDB_WDWIDTH) * destPlanes << 1; // MFDB *dest->pitch
799 uint32 destAddress = ReadInt32(dest);
800
801 switch(destPlanes) {
802 case 16:
803 for(uint16 j = 0; j < h; j++) {
804 D2(fprintf(stderr, "fVDI: bmp:"));
805
806 uint16 theWord = ReadInt16(data + j * pitch + ((sx >> 3) & 0xfffe));
807 for(uint16 i = sx; i < sx + w; i++) {
808 uint32 offset = (dx + i - sx) * 2 + (dy + j) * destPitch;
809 if (i % 16 == 0)
810 theWord = ReadInt16(data + j * pitch + ((i >> 3) & 0xfffe));
811
812 D2(fprintf(stderr, "%s", ((theWord >> (15 - (i & 0xf))) & 1) ? "1" : " "));
813 switch(logOp) {
814 case 1:
815 WriteInt16(destAddress + offset, ((theWord >> (15 - (i & 0xf))) & 1) ? fgColor : bgColor);
816 break;
817 case 2:
818 if ((theWord >> (15 - (i & 0xf))) & 1)
819 WriteInt16(destAddress + offset, fgColor);
820 break;
821 case 3:
822 if ((theWord >> (15 - (i & 0xf))) & 1)
823 WriteInt16(destAddress + offset, ~ReadInt16(destAddress + offset));
824 break;
825 case 4:
826 if (!((theWord >> (15 - (i & 0xf))) & 1))
827 WriteInt16(destAddress + offset, bgColor);
828 break;
829 }
830 }
831 D2(bug("")); //newline
832 }
833 break;
834 case 24:
835 for(uint16 j = 0; j < h; j++) {
836 D2(fprintf(stderr, "fVDI: bmp:"));
837
838 uint16 theWord = ReadInt16(data + j * pitch + ((sx >> 3) & 0xfffe));
839 for(uint16 i = sx; i < sx + w; i++) {
840 uint32 offset = (dx + i - sx) * 3 + (dy + j) * destPitch;
841 if (i % 16 == 0)
842 theWord = ReadInt16(data + j * pitch + ((i >> 3) & 0xfffe));
843
844 D2(fprintf(stderr, "%s", ((theWord >> (15 - (i & 0xf))) & 1) ? "1" : " "));
845 switch(logOp) {
846 case 1:
847 put_dtriplet(destAddress + offset, ((theWord >> (15 - (i & 0xf))) & 1) ? fgColor : bgColor);
848 break;
849 case 2:
850 if ((theWord >> (15 - (i & 0xf))) & 1)
851 put_dtriplet(destAddress + offset, fgColor);
852 break;
853 case 3:
854 if ((theWord >> (15-(i&0xf))) & 1)
855 put_dtriplet(destAddress + offset, ~get_dtriplet(destAddress + offset));
856 break;
857 case 4:
858 if (!((theWord >> (15 - (i & 0xf))) & 1))
859 put_dtriplet(destAddress + offset, bgColor);
860 break;
861 }
862 }
863 D2(bug("")); //newline
864 }
865 break;
866 case 32:
867 for(uint16 j = 0; j < h; j++) {
868 D2(fprintf(stderr, "fVDI: bmp:"));
869
870 uint16 theWord = ReadInt16(data + j * pitch + ((sx >> 3) & 0xfffe));
871 for(uint16 i = sx; i < sx + w; i++) {
872 uint32 offset = (dx + i - sx) * 4 + (dy + j) * destPitch;
873 if (i % 16 == 0)
874 theWord = ReadInt16(data + j * pitch + ((i >> 3) & 0xfffe));
875
876 D2(fprintf(stderr, "%s", ((theWord >> (15 - (i & 0xf))) & 1) ? "1" : " "));
877 switch(logOp) {
878 case 1:
879 WriteInt32(destAddress + offset, ((theWord >> (15 - (i & 0xf))) & 1) ? fgColor : bgColor);
880 break;
881 case 2:
882 if ((theWord >> (15-(i&0xf))) & 1)
883 WriteInt32(destAddress + offset, fgColor);
884 break;
885 case 3:
886 if ((theWord >> (15 - (i & 0xf))) & 1)
887 WriteInt32(destAddress + offset, ~ReadInt32(destAddress + offset));
888 break;
889 case 4:
890 if (!((theWord >> (15 - (i & 0xf))) & 1))
891 WriteInt32(destAddress + offset, bgColor);
892 break;
893 }
894 }
895 D2(bug("")); //newline
896 }
897 break;
898 default:
899 { // do the mangling for bitplanes. TOS<->VDI color conversions implemented.
900 uint8 color[16];
901 uint16 bitplanePixels[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // initialized just to quiet GCC warning
902
903 for(uint16 j = 0; j < h; j++) {
904 D2(fprintf(stderr, "fVDI: bmp:"));
905
906 uint32 address = destAddress + ((((dx >> 4) * destPlanes) << 1) + (dy + j) * destPitch);
907 HostScreen::bitplaneToChunky((uint16*)Atari2HostAddr(address), destPlanes, color);
908
909 uint16 theWord = ReadInt16(data + j * pitch + ((sx >> 3) & 0xfffe));
910 for(uint16 i = sx; i < sx + w; i++) {
911 if (i % 16 == 0) {
912 uint32 wordIndex = ((dx + i - sx) >> 4) * destPlanes;
913
914 // convert the 16pixels (VDI->TOS colors - within the chunkyToBitplane
915 // function) into the bitplane and write it to the destination
916 //
917 // note: we can't do the conversion directly
918 // because it needs the little->bigendian conversion
919 chunkyToBitplane(color, destPlanes, bitplanePixels);
920 for(uint32 d = 0; d < destPlanes; d++)
921 WriteInt16(address + (d<<1), bitplanePixels[d]);
922
923 // convert next 16pixels to chunky
924 address = destAddress + ((wordIndex << 1) + (dy + j) * destPitch);
925 HostScreen::bitplaneToChunky((uint16*)Atari2HostAddr(address), destPlanes, color);
926 theWord = ReadInt16(data + j * pitch + ((i >> 3) & 0xfffe));
927 }
928
929 D2(fprintf(stderr, "%s", ((theWord >> (15 - (i & 0xf))) & 1) ? "1" : " "));
930 switch(logOp) {
931 case 1:
932 color[i&0xf] = ((theWord >> (15 - (i & 0xf))) & 1) ? fgColor : bgColor;
933 break;
934 case 2:
935 if ((theWord >> (15-(i&0xf))) & 1)
936 color[i&0xf] = fgColor;
937 break;
938 case 3:
939 if ((theWord >> (15 - (i & 0xf))) & 1)
940 color[i&0xf] = ~color[i&0xf];
941 break;
942 case 4:
943 if (!((theWord >> (15 - (i & 0xf))) & 1))
944 color[i&0xf] = bgColor;
945 break;
946 }
947 }
948 chunkyToBitplane(color, destPlanes, bitplanePixels);
949 for(uint32 d = 0; d < destPlanes; d++)
950 WriteInt16(address + (d<<1), bitplanePixels[d]);
951
952 D2(bug("")); //newline
953 }
954 }
955 break;
956 }
957
958 return 1;
959 }
960
961 /**
962 * Fill a coloured area using a monochrome pattern.
963 *
964 * c_fill_area(Virtual *vwk, long x, long y, long w, long h,
965 * short *pattern, long colour, long mode, long interior_style)
966 * fill_area
967 * In: a1 VDI struct
968 * d0 height and width to fill (high and low word)
969 * d1 x or table address
970 * d2 y or table length (high) and type (low)
971 * d3 pattern address
972 * d4 colour
973 *
974 * This function has two modes:
975 * - single block to fill
976 * - table based y/x1/x2 spans to fill (special mode 0 (low word of 'y'))
977 *
978 * As usual, only the first one is necessary, and a return with d0 = -1
979 * signifies that a special mode should be broken down to the basic one.
980 *
981 * An immediate return with 0 gives a fallback (normally line based drawing
982 * by the fVDI engine for solid fills, otherwise pixel by pixel).
983 * A negative return will break down the special mode into separate calls,
984 * with no more fallback possible.
985 **/
986
fillArea(memptr vwk,uint32 x_,uint32 y_,int32 w,int32 h,memptr pattern_addr,uint32 fgColor,uint32 bgColor,uint32 logOp,uint32 interior_style)987 int32 VdiDriver::fillArea(memptr vwk, uint32 x_, uint32 y_, int32 w,
988 int32 h, memptr pattern_addr, uint32 fgColor, uint32 bgColor,
989 uint32 logOp, uint32 interior_style)
990 {
991 DUNUSED(vwk);
992 DUNUSED(x_);
993 DUNUSED(y_);
994 DUNUSED(w);
995 DUNUSED(h);
996 DUNUSED(pattern_addr);
997 DUNUSED(fgColor);
998 DUNUSED(bgColor);
999 DUNUSED(logOp);
1000 DUNUSED(interior_style);
1001
1002 return -1;
1003 }
1004
1005 /**
1006 * Blit an area
1007 *
1008 * c_blit_area(Virtual *vwk, MFDB *src, long src_x, long src_y,
1009 * MFDB *dst, long dst_x, long dst_y,
1010 * long w, long h, long operation)
1011 * blit_area
1012 * In: a1 VDI struct, destination MFDB, VDI struct, source MFDB
1013 * d0 height and width to move (high and low word)
1014 * d1-d2 source coordinates
1015 * d3-d4 destination coordinates
1016 * d7 logic operation
1017 *
1018 * Only one mode here.
1019 *
1020 * Note that a1 does not point to the VDI struct, but to a place in memory
1021 * where the VDI struct pointer can be found. Four bytes beyond that address
1022 * is a pointer to the destination MFDB, and then comes a VDI struct
1023 * pointer again (the same) and a pointer to the source MFDB.
1024 *
1025 * Since MFDBs are passed, the screen is not necessarily involved.
1026 *
1027 * A return with 0 gives a fallback (normally pixel by pixel drawing by the
1028 * fVDI engine).
1029 **/
1030
blitArea(memptr vwk,memptr src,int32 sx,int32 sy,memptr dest,int32 dx,int32 dy,int32 w,int32 h,uint32 logOp)1031 int32 VdiDriver::blitArea(memptr vwk, memptr src, int32 sx, int32 sy,
1032 memptr dest, int32 dx, int32 dy, int32 w, int32 h, uint32 logOp)
1033 {
1034 int32 ret;
1035
1036 if (src) {
1037 if (dest) {
1038 ret=blitArea_M2M(vwk, src, sx, sy, dest, dx, dy, w, h, logOp);
1039 } else {
1040 ret=blitArea_M2S(vwk, src, sx, sy, dest, dx, dy, w, h, logOp);
1041 }
1042 } else {
1043 if (dest) {
1044 ret=blitArea_S2M(vwk, src, sx, sy, dest, dx, dy, w, h, logOp);
1045 } else {
1046 ret=blitArea_S2S(vwk, src, sx, sy, dest, dx, dy, w, h, logOp);
1047 }
1048 }
1049
1050 return ret;
1051 }
1052
blitArea_M2M(memptr vwk,memptr src,int32 sx,int32 sy,memptr dest,int32 dx,int32 dy,int32 w,int32 h,uint32 logOp)1053 int32 VdiDriver::blitArea_M2M(memptr vwk, memptr src, int32 sx, int32 sy,
1054 memptr dest, int32 dx, int32 dy, int32 w, int32 h, uint32 logOp)
1055 {
1056 DUNUSED(vwk);
1057
1058 uint32 planes = ReadInt16(src + MFDB_NPLANES); // MFDB *src->bitplanes
1059 uint32 pitch = ReadInt16(src + MFDB_WDWIDTH) * planes * 2; // MFDB *src->pitch
1060 memptr data = ReadInt32(src) + sy * pitch; // MFDB *src->address host OS address
1061
1062 // the destPlanes is always the same?
1063 planes = ReadInt16(dest + MFDB_NPLANES); // MFDB *dest->bitplanes
1064 uint32 destPitch = ReadInt16(dest + MFDB_WDWIDTH) * planes * 2; // MFDB *dest->pitch
1065 memptr destAddress = (memptr)ReadInt32(dest);
1066
1067 D(bug("fVDI: blitArea M->M"));
1068
1069 uint32 srcData;
1070 uint32 destData;
1071
1072 switch(planes) {
1073 case 16:
1074 for(int32 j = 0; j < h; j++)
1075 for(int32 i = sx; i < sx + w; i++) {
1076 uint32 offset = (dx + i - sx) * 2 + (dy + j) * destPitch;
1077 srcData = ReadInt16(data + j * pitch + i * 2);
1078 destData = ReadInt16(destAddress + offset);
1079 destData = applyBlitLogOperation(logOp, destData, srcData);
1080 WriteInt16(destAddress + offset, destData);
1081 }
1082 break;
1083 case 24:
1084 for(int32 j = 0; j < h; j++)
1085 for(int32 i = sx; i < sx + w; i++) {
1086 uint32 offset = (dx + i - sx) * 3 + (dy + j) * destPitch;
1087 srcData = get_dtriplet(data + j * pitch + i * 3);
1088 destData = get_dtriplet(destAddress + offset);
1089 destData = applyBlitLogOperation(logOp, destData, srcData);
1090 put_dtriplet(destAddress + offset, destData);
1091 }
1092 break;
1093 case 32:
1094 for(int32 j = 0; j < h; j++)
1095 for(int32 i = sx; i < sx + w; i++) {
1096 uint32 offset = (dx + i - sx) * 4 + (dy + j) * destPitch;
1097 srcData = ReadInt32(data + j * pitch + i * 4);
1098 destData = ReadInt32(destAddress + offset);
1099 destData = applyBlitLogOperation(logOp, destData, srcData);
1100 WriteInt32(destAddress + offset, destData);
1101 }
1102 break;
1103 default:
1104 if (planes < 16) {
1105 D(bug("fVDI: blitArea M->M: NOT TESTED bitplaneToCunky conversion"));
1106 }
1107 }
1108
1109 return 1;
1110 }
1111
blitArea_M2S(memptr vwk,memptr src,int32 sx,int32 sy,memptr dest,int32 dx,int32 dy,int32 w,int32 h,uint32 logOp)1112 int32 VdiDriver::blitArea_M2S(memptr vwk, memptr src, int32 sx, int32 sy,
1113 memptr dest, int32 dx, int32 dy, int32 w, int32 h, uint32 logOp)
1114 {
1115 DUNUSED(vwk);
1116 DUNUSED(src);
1117 DUNUSED(sx);
1118 DUNUSED(sy);
1119 DUNUSED(dest);
1120 DUNUSED(dx);
1121 DUNUSED(dy);
1122 DUNUSED(w);
1123 DUNUSED(h);
1124 DUNUSED(logOp);
1125 return -1;
1126 }
1127
blitArea_S2M(memptr vwk,memptr src,int32 sx,int32 sy,memptr dest,int32 dx,int32 dy,int32 w,int32 h,uint32 logOp)1128 int32 VdiDriver::blitArea_S2M(memptr vwk, memptr src, int32 sx, int32 sy,
1129 memptr dest, int32 dx, int32 dy, int32 w, int32 h, uint32 logOp)
1130 {
1131 DUNUSED(vwk);
1132 DUNUSED(src);
1133 DUNUSED(sx);
1134 DUNUSED(sy);
1135 DUNUSED(dest);
1136 DUNUSED(dx);
1137 DUNUSED(dy);
1138 DUNUSED(w);
1139 DUNUSED(h);
1140 DUNUSED(logOp);
1141 return -1;
1142 }
1143
blitArea_S2S(memptr vwk,memptr src,int32 sx,int32 sy,memptr dest,int32 dx,int32 dy,int32 w,int32 h,uint32 logOp)1144 int32 VdiDriver::blitArea_S2S(memptr vwk, memptr src, int32 sx, int32 sy,
1145 memptr dest, int32 dx, int32 dy, int32 w, int32 h, uint32 logOp)
1146 {
1147 DUNUSED(vwk);
1148 DUNUSED(src);
1149 DUNUSED(sx);
1150 DUNUSED(sy);
1151 DUNUSED(dest);
1152 DUNUSED(dx);
1153 DUNUSED(dy);
1154 DUNUSED(w);
1155 DUNUSED(h);
1156 DUNUSED(logOp);
1157 return -1;
1158 }
1159
1160 /**
1161 * Draw a coloured line between two points
1162 *
1163 * c_draw_line(Virtual *vwk, long x1, long y1, long x2, long y2,
1164 * long pattern, long colour)
1165 * draw_line
1166 * In: a1 VDI struct
1167 * d0 logic operation
1168 * d1 x1 or table address
1169 * d2 y1 or table length (high) and type (low)
1170 * d3 x2 or move point count
1171 * d4 y2 or move index address
1172 * d5 pattern
1173 * d6 colour
1174 *
1175 * This function has three modes:
1176 * - single line
1177 * - table based coordinate pairs (special mode 0 (low word of 'y1'))
1178 * - table based coordinate pairs+moves (special mode 1)
1179 *
1180 * As usual, only the first one is necessary, and a return with d0 = -1
1181 * signifies that a special mode should be broken down to the basic one.
1182 *
1183 * An immediate return with 0 gives a fallback (normally pixel by pixel
1184 * drawing by the fVDI engine).
1185 * A negative return will break down the special modes into separate calls,
1186 * with no more fallback possible.
1187 **/
1188
drawLine(memptr vwk,uint32 x1_,uint32 y1_,uint32 x2_,uint32 y2_,uint32 pattern,uint32 fgColor,uint32 bgColor,uint32 logOp,memptr clip)1189 int32 VdiDriver::drawLine(memptr vwk, uint32 x1_, uint32 y1_, uint32 x2_,
1190 uint32 y2_, uint32 pattern, uint32 fgColor, uint32 bgColor,
1191 uint32 logOp, memptr clip)
1192 {
1193 DUNUSED(vwk);
1194 DUNUSED(x1_);
1195 DUNUSED(y1_);
1196 DUNUSED(x2_);
1197 DUNUSED(y2_);
1198 DUNUSED(pattern);
1199 DUNUSED(fgColor);
1200 DUNUSED(bgColor);
1201 DUNUSED(logOp);
1202 DUNUSED(clip);
1203
1204 return -1;
1205 }
1206
fillPoly(memptr vwk,memptr points_addr,int n,memptr index_addr,int moves,memptr pattern_addr,uint32 fgColor,uint32 bgColor,uint32 logOp,uint32 interior_style,memptr clip)1207 int32 VdiDriver::fillPoly(memptr vwk, memptr points_addr, int n,
1208 memptr index_addr, int moves, memptr pattern_addr, uint32 fgColor,
1209 uint32 bgColor, uint32 logOp, uint32 interior_style, memptr clip)
1210 {
1211 DUNUSED(interior_style);
1212 if (vwk & 1)
1213 return -1; // Don't know about any special fills
1214
1215 // Allocate arrays for data
1216 if (!AllocPoints(n) || !AllocIndices(moves) || !AllocCrossings(200))
1217 return -1;
1218
1219 uint16 pattern[16];
1220 for(int i = 0; i < 16; ++i)
1221 pattern[i] = ReadInt16(pattern_addr + i * 2);
1222
1223 int cliparray[4];
1224 int* cliprect = 0;
1225 if (clip) { // Clipping is not off
1226 cliprect = cliparray;
1227 cliprect[0] = (int16)ReadInt32(clip);
1228 cliprect[1] = (int16)ReadInt32(clip + 4);
1229 cliprect[2] = (int16)ReadInt32(clip + 8);
1230 cliprect[3] = (int16)ReadInt32(clip + 12);
1231 D2(bug("fVDI: %s %d,%d:%d,%d", "clipLineTO", cliprect[0], cliprect[1],
1232 cliprect[2], cliprect[3]));
1233 }
1234
1235 Points p(alloc_point);
1236 int16* index = alloc_index;
1237 int16* crossing = alloc_crossing;
1238
1239 for(int i = 0; i < n; ++i) {
1240 p[i][0] = (int16)ReadInt16(points_addr + i * 4);
1241 p[i][1] = (int16)ReadInt16(points_addr + i * 4 + 2);
1242 }
1243 bool indices = moves;
1244 for(int i = 0; i < moves; ++i)
1245 index[i] = (int16)ReadInt16(index_addr + i * 2);
1246
1247
1248 if (!n)
1249 return 1;
1250
1251 if (!indices) {
1252 if ((p[0][0] == p[n - 1][0]) && (p[0][1] == p[n - 1][1]))
1253 n--;
1254 } else {
1255 moves--;
1256 if (index[moves] == -4)
1257 moves--;
1258 if (index[moves] == -2)
1259 moves--;
1260 }
1261
1262 int miny = p[0][1];
1263 int maxy = miny;
1264 for(int i = 1; i < n; ++i) {
1265 int16 y = p[i][1];
1266 if (y < miny) {
1267 miny = y;
1268 }
1269 if (y > maxy) {
1270 maxy = y;
1271 }
1272 }
1273 if (cliprect) {
1274 if (miny < cliprect[1])
1275 miny = cliprect[1];
1276 if (maxy > cliprect[3])
1277 maxy = cliprect[3];
1278 }
1279
1280 int minx = 1000000;
1281 int maxx = -1000000;
1282
1283 for(int16 y = miny; y <= maxy; ++y) {
1284 int ints = 0;
1285 int16 x1 = 0; // Make the compiler happy with some initializations
1286 int16 y1 = 0;
1287 int16 x2 = 0;
1288 int16 y2 = 0;
1289 int move_n = 0;
1290 int movepnt = 0;
1291 if (indices) {
1292 move_n = moves;
1293 movepnt = (index[move_n] + 4) / 2;
1294 x2 = p[0][0];
1295 y2 = p[0][1];
1296 } else {
1297 x1 = p[n - 1][0];
1298 y1 = p[n - 1][1];
1299 }
1300
1301 for(int i = indices; i < n; ++i) {
1302 if (EnoughCrossings(ints + 1) || AllocCrossings(ints + 1))
1303 crossing = alloc_crossing;
1304 else
1305 break; // At least something will get drawn
1306
1307 if (indices) {
1308 x1 = x2;
1309 y1 = y2;
1310 }
1311 x2 = p[i][0];
1312 y2 = p[i][1];
1313 if (indices) {
1314 if (i == movepnt) {
1315 if (--move_n >= 0)
1316 movepnt = (index[move_n] + 4) / 2;
1317 else
1318 movepnt = -1; // Never again equal to n
1319 continue;
1320 }
1321 }
1322
1323 if (y1 < y2) {
1324 if ((y >= y1) && (y < y2)) {
1325 crossing[ints++] = SMUL_DIV((y - y1), (x2 - x1), (y2 - y1)) + x1;
1326 }
1327 } else if (y1 > y2) {
1328 if ((y >= y2) && (y < y1)) {
1329 crossing[ints++] = SMUL_DIV((y - y2), (x1 - x2), (y1 - y2)) + x2;
1330 }
1331 }
1332 if (!indices) {
1333 x1 = x2;
1334 y1 = y2;
1335 }
1336 }
1337
1338 for(int i = 0; i < ints - 1; ++i) {
1339 for(int j = i + 1; j < ints; ++j) {
1340 if (crossing[i] > crossing[j]) {
1341 int16 tmp = crossing[i];
1342 crossing[i] = crossing[j];
1343 crossing[j] = tmp;
1344 }
1345 }
1346 }
1347
1348 x1 = cliprect[0];
1349 x2 = cliprect[2];
1350 for(int i = 0; i < ints - 1; i += 2) {
1351 y1 = crossing[i]; // Really x-values, but...
1352 y2 = crossing[i + 1];
1353 if (y1 < x1)
1354 y1 = x1;
1355 if (y2 > x2)
1356 y2 = x2;
1357 if (y1 <= y2) {
1358 fillArea(y1, y, y2 - y1 + 1, 1, pattern,
1359 fgColor, bgColor, logOp);
1360 if (y1 < minx)
1361 minx = y1;
1362 if (y2 > maxx)
1363 maxx = y2;
1364 }
1365 }
1366 }
1367
1368 return 1;
1369 }
1370
drawText(memptr vwk,memptr text,uint32 length,int32 dst_x,int32 dst_y,memptr font,uint32 w,uint32 h,uint32 fgColor,uint32 bgColor,uint32 logOp,memptr clip)1371 int32 VdiDriver::drawText(memptr vwk, memptr text, uint32 length, int32 dst_x, int32 dst_y,
1372 memptr font, uint32 w, uint32 h, uint32 fgColor, uint32 bgColor,
1373 uint32 logOp, memptr clip)
1374 {
1375 DUNUSED(vwk);
1376 DUNUSED(text);
1377 DUNUSED(length);
1378 DUNUSED(dst_x);
1379 DUNUSED(dst_y);
1380 DUNUSED(font);
1381 DUNUSED(w);
1382 DUNUSED(h);
1383 DUNUSED(fgColor);
1384 DUNUSED(bgColor);
1385 DUNUSED(logOp);
1386 DUNUSED(clip);
1387
1388 return -1;
1389 }
1390
getHwColor(uint16 index,uint32 red,uint32 green,uint32 blue,memptr hw_value)1391 void VdiDriver::getHwColor(uint16 index, uint32 red, uint32 green,
1392 uint32 blue, memptr hw_value)
1393 {
1394 DUNUSED(index);
1395 DUNUSED(red);
1396 DUNUSED(green);
1397 DUNUSED(blue);
1398 DUNUSED(hw_value);
1399 }
1400
setColor(memptr vwk,uint32 paletteIndex,uint32 red,uint32 green,uint32 blue)1401 void VdiDriver::setColor(memptr vwk, uint32 paletteIndex, uint32 red,
1402 uint32 green, uint32 blue)
1403 {
1404 DUNUSED(vwk);
1405 DUNUSED(paletteIndex);
1406 DUNUSED(red);
1407 DUNUSED(green);
1408 DUNUSED(blue);
1409 }
1410
getFbAddr(void)1411 int32 VdiDriver::getFbAddr(void)
1412 {
1413 return 0;
1414 }
1415
1416