1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Video driver using the VBE/AF 2.0 hardware accelerator API,
12 * plus extensions added by the FreeBE/AF project.
13 *
14 * This driver provides accelerated support for:
15 *
16 * - scanline fills (solid, XOR, and patterned)
17 * - area fills (solid, XOR, and patterned)
18 * - line drawing (solid and XOR)
19 * - triangle drawing (solid and XOR)
20 * - monochrome character expansion
21 * - blitting within the video memory
22 * - masked blitting within the video memory
23 * - blits from system memory
24 * - masked blits from system memory
25 * - hardware mouse cursors
26 *
27 * The FreeBE/AF project (http://www.talula.demon.co.uk/freebe/)
28 * has defined a number of API extensions, of which this driver
29 * implements:
30 *
31 * FAFEXT_INIT - extension init and new driver relocation mechanism
32 * FAFEXT_HWPTR - farptr access to video memory (no more Fat DS hack)
33 * FAFEXT_LIBC - exports a bunch of callback functions from libc
34 * FAFEXT_PMODE - exports the SciTech pmode API callback functions
35 *
36 * On the subject of VBE/AF in general:
37 *
38 * Kendall Bennett and Tom Ryan of SciTech software deserve
39 * significant thanks for coming up with such a magnificent API and
40 * then helping me write this driver, after the VESA people (may they
41 * be smitten with plagues of locusts and then develop subtle memory
42 * leaks in their code :-) decided to charge stupid sums of money for
43 * copies of the /AF specification. Unfortunately, SciTech have
44 * subsequently abandoned VBE/AF in favour of a closed, proprietary
45 * system called Nucleus. Ah well, I'm sure that this makes sense
46 * for them in commercial terms, even if it is something of a
47 * disappointment for us idealistic hacker types...
48 *
49 * The problem with Nucleus is that the spec is only available under
50 * NDA, so I cannot support it directly in Allegro. The plan,
51 * therefore, is to write a Nucleus to VBE/AF wrapper driver.
52 * This requires a few callback routines that stock VBE/AF doesn't
53 * provide, hence the Nucleus-specific extensions in this file. It
54 * doesn't provide direct Nucleus support, but hopefully will enable
55 * someone (whether us or SciTech) to add that support in the future
56 * via an external driver binary.
57 *
58 * By Shawn Hargreaves.
59 *
60 * See readme.txt for copyright information.
61 */
62
63
64 #include <string.h>
65
66 #include "allegro.h"
67
68 #if (defined ALLEGRO_DOS) || (defined ALLEGRO_LINUX_VBEAF)
69
70 #include "allegro/internal/aintern.h"
71
72 #ifdef ALLEGRO_INTERNAL_HEADER
73 #include ALLEGRO_INTERNAL_HEADER
74 #endif
75
76 #if (defined ALLEGRO_DJGPP) && (!defined SCAN_DEPEND)
77 #include <crt0.h>
78 #include <sys/nearptr.h>
79 #include <sys/exceptn.h>
80 #endif
81
82
83
84 /* main driver routines */
85 static BITMAP *vbeaf_init(int w, int h, int v_w, int v_h, int color_depth);
86 static void vbeaf_exit(BITMAP *b);
87 static void vbeaf_save(void);
88 static void vbeaf_restore(void);
89 static GFX_MODE_LIST *vbeaf_fetch_mode_list(void);
90 static void vbeaf_vsync(void);
91 static int vbeaf_scroll(int x, int y);
92 static void vbeaf_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync);
93 static int vbeaf_request_scroll(int x, int y);
94 static int vbeaf_poll_scroll(void);
95 static int vbeaf_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus);
96 static int vbeaf_show_mouse(BITMAP *bmp, int x, int y);
97 static void vbeaf_hide_mouse(void);
98 static void vbeaf_move_mouse(int x, int y);
99 static void vbeaf_drawing_mode(void);
100 static int vbeaf_locate_driver(void);
101 static int vbeaf_lowlevel_init(void);
102
103
104 /* accelerated drawing functions */
105 static void vbeaf_hline(BITMAP *bmp, int x1, int y, int x2, int color);
106 static void vbeaf_vline_a(BITMAP *bmp, int x, int y1, int y2, int color);
107 static void vbeaf_vline_b(BITMAP *bmp, int x, int y1, int y2, int color);
108 static void vbeaf_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
109 static void vbeaf_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
110 static void vbeaf_triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color);
111 static void vbeaf_draw_glyph(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg);
112 static void vbeaf_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y);
113 static void vbeaf_blit_from_memory(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
114 static void vbeaf_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
115 static void vbeaf_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
116 static void vbeaf_clear_to_color(BITMAP *bitmap, int color);
117
118
119 #ifdef ALLEGRO_DOS
120 static void vbeaf_move_mouse_end(void);
121 static void vbeaf_draw_sprite_end(void);
122 static void vbeaf_blit_from_memory_end(void);
123 #endif
124
125
126 /* original software drawing functions */
127 static void (*orig_vline)(BITMAP *bmp, int x, int y1, int y2, int color);
128 static void (*orig_hline)(BITMAP *bmp, int x1, int y, int x2, int color);
129 static void (*orig_line)(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
130 static void (*orig_rectfill)(BITMAP *bmp, int x1, int y1, int x2, int y2, int color);
131 static void (*orig_draw_glyph)(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg);
132 static void (*orig_draw_sprite)(BITMAP *bmp, BITMAP *sprite, int x, int y);
133 static void (*orig_masked_blit)(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height);
134
135
136 static char vbeaf_desc[256] = EMPTY_STRING;
137
138
139
140 /* the video driver structure */
141 GFX_DRIVER gfx_vbeaf =
142 {
143 GFX_VBEAF,
144 empty_string,
145 empty_string,
146 "VBE/AF",
147 vbeaf_init,
148 vbeaf_exit,
149 vbeaf_scroll,
150 vbeaf_vsync,
151 vbeaf_set_palette_range,
152 vbeaf_request_scroll,
153 vbeaf_poll_scroll,
154 NULL, /* enable triple buffer */
155 NULL, NULL, NULL, NULL, /* no video bitmaps */
156 NULL, NULL, /* no system bitmaps */
157 NULL, NULL, NULL, NULL, /* no hardware cursor (yet) */
158 NULL, /* no drawing mode hook */
159 vbeaf_save,
160 vbeaf_restore,
161 NULL, /* AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); */
162 vbeaf_fetch_mode_list, /* fetch mode hook */
163 0, 0, FALSE, 0, 0, 0, 0, FALSE
164 };
165
166
167
168 typedef struct AF_FIX_POINT /* fixed point coordinate pair */
169 {
170 fixed x;
171 fixed y;
172 } AF_FIX_POINT;
173
174
175
176 typedef struct AF_TRAP /* trapezium information block */
177 {
178 long y;
179 long count;
180 fixed x1;
181 fixed x2;
182 fixed slope1;
183 fixed slope2;
184 } AF_TRAP;
185
186
187
188 typedef struct AF_CURSOR /* hardware cursor description */
189 {
190 unsigned long xorMask[32];
191 unsigned long andMask[32];
192 unsigned long hotx;
193 unsigned long hoty;
194 } AF_CURSOR;
195
196
197
198 typedef struct AF_PALETTE /* color value (not in Allegro order) */
199 {
200 unsigned char blue;
201 unsigned char green;
202 unsigned char red;
203 unsigned char alpha;
204 } AF_PALETTE;
205
206
207
208 #ifdef ALLEGRO_GCC
209 #define __PACKED__ __attribute__ ((packed))
210 #else
211 #define __PACKED__
212 #endif
213
214 #ifdef ALLEGRO_WATCOM
215 #pragma pack (1)
216 #endif
217
218
219
220 typedef struct AF_MODE_INFO /* mode information structure */
221 {
222 unsigned short Attributes __PACKED__;
223 unsigned short XResolution __PACKED__;
224 unsigned short YResolution __PACKED__;
225 unsigned short BytesPerScanLine __PACKED__;
226 unsigned short BitsPerPixel __PACKED__;
227 unsigned short MaxBuffers __PACKED__;
228 unsigned char RedMaskSize;
229 unsigned char RedFieldPosition;
230 unsigned char GreenMaskSize;
231 unsigned char GreenFieldPosition;
232 unsigned char BlueMaskSize;
233 unsigned char BlueFieldPosition;
234 unsigned char RsvdMaskSize;
235 unsigned char RsvdFieldPosition;
236 unsigned short MaxBytesPerScanLine __PACKED__;
237 unsigned short MaxScanLineWidth __PACKED__;
238
239 /* VBE/AF 2.0 extensions */
240 unsigned short LinBytesPerScanLine __PACKED__;
241 unsigned char BnkMaxBuffers;
242 unsigned char LinMaxBuffers;
243 unsigned char LinRedMaskSize;
244 unsigned char LinRedFieldPosition;
245 unsigned char LinGreenMaskSize;
246 unsigned char LinGreenFieldPosition;
247 unsigned char LinBlueMaskSize;
248 unsigned char LinBlueFieldPosition;
249 unsigned char LinRsvdMaskSize;
250 unsigned char LinRsvdFieldPosition;
251 unsigned long MaxPixelClock __PACKED__;
252 unsigned long VideoCapabilities __PACKED__;
253 unsigned short VideoMinXScale __PACKED__;
254 unsigned short VideoMinYScale __PACKED__;
255 unsigned short VideoMaxXScale __PACKED__;
256 unsigned short VideoMaxYScale __PACKED__;
257
258 unsigned char reserved[76];
259
260 } AF_MODE_INFO;
261
262
263
264 #define DC struct AF_DRIVER *dc
265
266
267
268 typedef struct AF_DRIVER /* VBE/AF driver structure */
269 {
270 /* driver header */
271 char Signature[12];
272 unsigned long Version __PACKED__;
273 unsigned long DriverRev __PACKED__;
274 char OemVendorName[80];
275 char OemCopyright[80];
276 unsigned short *AvailableModes __PACKED__;
277 unsigned long TotalMemory __PACKED__;
278 unsigned long Attributes __PACKED__;
279 unsigned long BankSize __PACKED__;
280 unsigned long BankedBasePtr __PACKED__;
281 unsigned long LinearSize __PACKED__;
282 unsigned long LinearBasePtr __PACKED__;
283 unsigned long LinearGranularity __PACKED__;
284 unsigned short *IOPortsTable __PACKED__;
285 unsigned long IOMemoryBase[4] __PACKED__;
286 unsigned long IOMemoryLen[4] __PACKED__;
287 unsigned long LinearStridePad __PACKED__;
288 unsigned short PCIVendorID __PACKED__;
289 unsigned short PCIDeviceID __PACKED__;
290 unsigned short PCISubSysVendorID __PACKED__;
291 unsigned short PCISubSysID __PACKED__;
292 unsigned long Checksum __PACKED__;
293 unsigned long res2[6] __PACKED__;
294
295 /* near pointers mapped by the application */
296 void *IOMemMaps[4] __PACKED__;
297 void *BankedMem __PACKED__;
298 void *LinearMem __PACKED__;
299 unsigned long res3[5] __PACKED__;
300
301 /* driver state variables */
302 unsigned long BufferEndX __PACKED__;
303 unsigned long BufferEndY __PACKED__;
304 unsigned long OriginOffset __PACKED__;
305 unsigned long OffscreenOffset __PACKED__;
306 unsigned long OffscreenStartY __PACKED__;
307 unsigned long OffscreenEndY __PACKED__;
308 unsigned long res4[10] __PACKED__;
309
310 /* relocatable 32 bit bank switch routine, for Windows (ugh!) */
311 unsigned long SetBank32Len __PACKED__;
312 void *SetBank32 __PACKED__;
313
314 /* callback functions provided by the application */
315 void *Int86 __PACKED__;
316 void *CallRealMode __PACKED__;
317
318 /* main driver setup routine */
319 void *InitDriver __PACKED__;
320
321 /* VBE/AF 1.0 asm interface (obsolete and not supported by Allegro) */
322 void *af10Funcs[40] __PACKED__;
323
324 /* VBE/AF 2.0 extensions */
325 void *PlugAndPlayInit __PACKED__;
326
327 /* FreeBE/AF extension query function */
328 void *(*OemExt)(DC, unsigned long id);
329
330 /* extension hook for implementing additional VESA interfaces */
331 void *SupplementalExt __PACKED__;
332
333 /* device driver functions */
334 long (*GetVideoModeInfo)(DC, short mode, AF_MODE_INFO *modeInfo);
335 long (*SetVideoMode)(DC, short mode, long virtualX, long virtualY, long *bytesPerLine, int numBuffers, void *crtc);
336 void (*RestoreTextMode)(DC);
337 long (*GetClosestPixelClock)(DC, short mode, unsigned long pixelClock);
338 void (*SaveRestoreState)(DC, int subfunc, void *saveBuf);
339 void (*SetDisplayStart)(DC, long x, long y, long waitVRT);
340 void (*SetActiveBuffer)(DC, long index);
341 void (*SetVisibleBuffer)(DC, long index, long waitVRT);
342 int (*GetDisplayStartStatus)(DC);
343 void (*EnableStereoMode)(DC, int enable);
344 void (*SetPaletteData)(DC, AF_PALETTE *pal, long num, long index, long waitVRT);
345 void (*SetGammaCorrectData)(DC, AF_PALETTE *pal, long num, long index);
346 void (*SetBank)(DC, long bank);
347
348 /* hardware cursor functions */
349 void (*SetCursor)(DC, AF_CURSOR *cursor);
350 void (*SetCursorPos)(DC, long x, long y);
351 void (*SetCursorColor)(DC, unsigned char red, unsigned char green, unsigned char blue);
352 void (*ShowCursor)(DC, long visible);
353
354 /* 2D rendering functions */
355 void (*WaitTillIdle)(DC);
356 void (*EnableDirectAccess)(DC);
357 void (*DisableDirectAccess)(DC);
358 void (*SetMix)(DC, long foreMix, long backMix);
359 void (*Set8x8MonoPattern)(DC, unsigned char *pattern);
360 void (*Set8x8ColorPattern)(DC, int index, unsigned long *pattern);
361 void (*Use8x8ColorPattern)(DC, int index);
362 void (*SetLineStipple)(DC, unsigned short stipple);
363 void (*SetLineStippleCount)(DC, unsigned long count);
364 void (*SetClipRect)(DC, long minx, long miny, long maxx, long maxy);
365 void (*DrawScan)(DC, long color, long y, long x1, long x2);
366 void (*DrawPattScan)(DC, long foreColor, long backColor, long y, long x1, long x2);
367 void (*DrawColorPattScan)(DC, long y, long x1, long x2);
368 void (*DrawScanList)(DC, unsigned long color, long y, long length, short *scans);
369 void (*DrawPattScanList)(DC, unsigned long foreColor, unsigned long backColor, long y, long length, short *scans);
370 void (*DrawColorPattScanList)(DC, long y, long length, short *scans);
371 void (*DrawRect)(DC, unsigned long color, long left, long top, long width, long height);
372 void (*DrawPattRect)(DC, unsigned long foreColor, unsigned long backColor, long left, long top, long width, long height);
373 void (*DrawColorPattRect)(DC, long left, long top, long width, long height);
374 void (*DrawLine)(DC, unsigned long color, fixed x1, fixed y1, fixed x2, fixed y2);
375 void (*DrawStippleLine)(DC, unsigned long foreColor, unsigned long backColor, fixed x1, fixed y1, fixed x2, fixed y2);
376 void (*DrawTrap)(DC, unsigned long color, AF_TRAP *trap);
377 void (*DrawTri)(DC, unsigned long color, AF_FIX_POINT *v1, AF_FIX_POINT *v2, AF_FIX_POINT *v3, fixed xOffset, fixed yOffset);
378 void (*DrawQuad)(DC, unsigned long color, AF_FIX_POINT *v1, AF_FIX_POINT *v2, AF_FIX_POINT *v3, AF_FIX_POINT *v4, fixed xOffset, fixed yOffset);
379 void (*PutMonoImage)(DC, long foreColor, long backColor, long dstX, long dstY, long byteWidth, long srcX, long srcY, long width, long height, unsigned char *image);
380 void (*PutMonoImageLin)(DC, long foreColor, long backColor, long dstX, long dstY, long byteWidth, long srcX, long srcY, long width, long height, long imageOfs);
381 void (*PutMonoImageBM)(DC, long foreColor, long backColor, long dstX, long dstY, long byteWidth, long srcX, long srcY, long width, long height, long imagePhysAddr);
382 void (*BitBlt)(DC, long left, long top, long width, long height, long dstLeft, long dstTop, long op);
383 void (*BitBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op);
384 void (*BitBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op);
385 void (*BitBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op);
386 void (*SrcTransBlt)(DC, long left, long top, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent);
387 void (*SrcTransBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent);
388 void (*SrcTransBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent);
389 void (*SrcTransBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent);
390 void (*DstTransBlt)(DC, long left, long top, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent);
391 void (*DstTransBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent);
392 void (*DstTransBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent);
393 void (*DstTransBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long width, long height, long dstLeft, long dstTop, long op, unsigned long transparent);
394 void (*StretchBlt)(DC, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op);
395 void (*StretchBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op);
396 void (*StretchBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op);
397 void (*StretchBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op);
398 void (*SrcTransStretchBlt)(DC, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent);
399 void (*SrcTransStretchBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent);
400 void (*SrcTransStretchBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent);
401 void (*SrcTransStretchBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent);
402 void (*DstTransStretchBlt)(DC, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent);
403 void (*DstTransStretchBltSys)(DC, void *srcAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent);
404 void (*DstTransStretchBltLin)(DC, long srcOfs, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent);
405 void (*DstTransStretchBltBM)(DC, long srcPhysAddr, long srcPitch, long srcLeft, long srcTop, long srcWidth, long srcHeight, long dstLeft, long dstTop, long dstWidth, long dstHeight, long flags, long op, unsigned long transparent);
406
407 /* hardware video functions */
408 void (*SetVideoInput)(DC, long width, long height, long format);
409 void *(*SetVideoOutput)(DC, long left, long top, long width, long height);
410 void (*StartVideoFrame)(DC);
411 void (*EndVideoFrame)(DC);
412
413 } AF_DRIVER;
414
415
416
417 #undef DC
418
419
420
421 /* FreeBE/AF API extensions use 32 bit magic numbers */
422 #define FAF_ID(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d)
423
424
425
426 /* ID code and magic return value for initialising the extensions */
427 #define FAFEXT_INIT FAF_ID('I','N','I','T')
428 #define FAFEXT_MAGIC FAF_ID('E','X', 0, 0)
429
430
431
432 /* function exporting extensions (needed for Nucleus compatibility) */
433 #define FAFEXT_LIBC FAF_ID('L','I','B','C')
434 #define FAFEXT_PMODE FAF_ID('P','M','O','D')
435
436
437
438 /* extension providing a hardware-specific way to access video memory */
439 #define FAFEXT_HWPTR FAF_ID('H','P','T','R')
440
441
442 typedef struct FAF_HWPTR
443 {
444 int sel;
445 unsigned long offset;
446 } FAF_HWPTR;
447
448
449 typedef struct FAF_HWPTR_DATA
450 {
451 FAF_HWPTR IOMemMaps[4];
452 FAF_HWPTR BankedMem;
453 FAF_HWPTR LinearMem;
454 } FAF_HWPTR_DATA;
455
456
457
458 #ifdef ALLEGRO_LINUX
459
460 #include <sys/stat.h>
461 #include <sys/mman.h>
462
463 /* quick and dirty Linux emulation of the DOS memory mapping routines */
464 #define _create_linear_mapping(_addr, _base, _len) \
465 ({ \
466 (_addr)->base = _base; \
467 (_addr)->size = _len; \
468 (_addr)->perms = PROT_READ | PROT_WRITE; \
469 __al_linux_map_memory(_addr); \
470 })
471
472 #define _remove_linear_mapping(_addr) \
473 { \
474 if ((_addr)->data) \
475 __al_linux_unmap_memory(_addr); \
476 }
477
478 #define _create_selector(sel, addr, len) -1
479
480 #define _remove_selector(sel)
481
482 #define MMAP struct MAPPED_MEMORY
483 #define NOMM { 0, 0, 0, 0 }
484 #define MVAL(a) a.data
485
486 #else
487
488 /* DOS version */
489 #define MMAP unsigned long
490 #define NOMM 0
491 #define MVAL(a) (void *)((a)-__djgpp_base_address)
492
493 #endif
494
495
496
497 static AF_DRIVER *af_driver = NULL; /* the VBE/AF driver */
498
499 void *_accel_driver = NULL; /* externally visible driver pointer */
500
501 int _accel_active = FALSE; /* is the accelerator busy? */
502
503 void *_accel_set_bank; /* shortcuts to driver functions */
504 void *_accel_idle;
505
506 static int in_af_mode = FALSE; /* true if VBE/AF is in use */
507
508 static int faf_id = FALSE; /* true if FreeBE/AF detected */
509 static int faf_ext = 0; /* FreeBE/AF extensions version */
510
511 static FAF_HWPTR_DATA *faf_farptr; /* FreeBE/AF farptr data */
512
513 static int vbeaf_xscroll = 0; /* current display start address */
514 static int vbeaf_yscroll = 0;
515
516 static int vbeaf_fg_mix = 0; /* current hardware mix mode */
517 static int vbeaf_bg_mix = 0;
518
519 static int vbeaf_cur_c1 = -1; /* hardware cursor colors */
520 static int vbeaf_cur_c2 = -1;
521
522 static BITMAP *vbeaf_cur_bmp = NULL; /* bitmap showing the cursor */
523
524 static int vbeaf_cur_x; /* cursor position */
525 static int vbeaf_cur_y;
526 static int vbeaf_cur_on;
527
528 static BITMAP *vbeaf_pattern = NULL; /* currently loaded pattern bitmap */
529
530 static MMAP af_memmap[4] = { NOMM, NOMM, NOMM, NOMM };
531 static MMAP af_banked_mem = NOMM;
532 static MMAP af_linear_mem = NOMM;
533
534 #ifdef ALLEGRO_DOS
535 static int vbeaf_nearptr = FALSE; /* did we enable nearptrs ourselves? */
536 #endif
537
538 #ifdef ALLEGRO_LINUX
539 int _vbeaf_selector = 0; /* Linux version of __djgpp_ds_alias */
540 #endif
541
542 static int saved_mode; /* state info for console switches */
543 static int saved_vw;
544 static int saved_vh;
545 static int saved_wret;
546
547 extern void _af_int86(void), _af_call_rm(void), _af_wrapper(void), _af_wrapper_end(void);
548
549
550
551 #ifdef ALLEGRO_DJGPP
552
553 /* djgpp wrapper to disable exceptions during critical operations */
554 #define SAFE_CALL(FUNC) \
555 { \
556 int _ds, _es, _ss; \
557 \
558 asm volatile ( \
559 " movw %%ds, %w0 ; " \
560 " movw %%es, %w1 ; " \
561 " movw %%ss, %w2 ; " \
562 " movw %w3, %%ds ; " \
563 " movw %w3, %%es ; " \
564 " movw %w3, %%ss ; " \
565 \
566 : "=&q" (_ds), \
567 "=&q" (_es), \
568 "=&q" (_ss) \
569 \
570 : "q" (__djgpp_ds_alias) \
571 ); \
572 \
573 FUNC \
574 \
575 asm volatile ( \
576 "movw %w0, %%ds ; " \
577 "movw %w1, %%es ; " \
578 "movw %w2, %%ss ; " \
579 : \
580 : "q" (_ds), \
581 "q" (_es), \
582 "q" (_ss) \
583 ); \
584 }
585
586 #define SAFISH_CALL(FUNC) FUNC
587
588 #elif defined ALLEGRO_LINUX
589
590 /* Linux wrapper to disable console switches during critical operations */
591 #define SAFE_CALL(FUNC) \
592 { \
593 __al_linux_switching_blocked++; \
594 \
595 FUNC \
596 \
597 __al_linux_release_bitmap(NULL); \
598 }
599
600 #define SAFISH_CALL(FUNC) SAFE_CALL(FUNC)
601
602 #else
603
604 #define SAFE_CALL(FUNC) FUNC
605 #define SAFISH_CALL(FUNC) FUNC
606
607 #endif
608
609
610
611 /* bswap:
612 * Toggles the endianess of a 32 bit integer.
613 */
bswap(unsigned long n)614 static unsigned long bswap(unsigned long n)
615 {
616 unsigned long a = n & 0xFF;
617 unsigned long b = (n>>8) & 0xFF;
618 unsigned long c = (n>>16) & 0xFF;
619 unsigned long d = (n>>24) & 0xFF;
620
621 return (a<<24) | (b<<16) | (c<<8) | d;
622 }
623
624
625
626 /* call_vbeaf_asm:
627 * Calls a VBE/AF function using the version 1.0 style asm interface.
628 */
call_vbeaf_asm(void * proc)629 static int call_vbeaf_asm(void *proc)
630 {
631 int ret;
632
633 proc = (void *)((long)af_driver + (long)proc);
634
635 #ifdef ALLEGRO_GCC
636
637 /* use gcc-style inline asm */
638 asm (
639 " pushl %%ebx ; "
640 " movl %%ecx, %%ebx ; "
641 " call *%%edx ; "
642 " popl %%ebx ; "
643
644 : "=&a" (ret) /* return value in eax */
645
646 : "c" (af_driver), /* VBE/AF driver in ds:ebx */
647 "d" (proc) /* function ptr in edx */
648
649 : "memory" /* assume everything is clobbered */
650 );
651
652 #elif defined ALLEGRO_WATCOM
653
654 /* use Watcom-style inline asm */
655 {
656 int _af(void *func, AF_DRIVER *driver);
657
658 #pragma aux _af = \
659 " call esi " \
660 \
661 parm [esi] [ebx] \
662 modify [ecx edx edi] \
663 value [eax];
664
665 ret = _af(proc, af_driver);
666 }
667
668 #else
669
670 /* don't know what to do on this compiler */
671 ret = -1;
672
673 #endif
674
675 return ret;
676 }
677
678
679
680 /* vbeaf_no_wait:
681 * Dummy wait-till-idle routine for non-accelerated drivers.
682 */
vbeaf_no_wait(void)683 static void vbeaf_no_wait(void)
684 {
685 }
686
687 END_OF_STATIC_FUNCTION(vbeaf_no_wait);
688
689
690
691 /* load_vbeaf_driver:
692 * Tries to load the specified VBE/AF driver file, returning TRUE on
693 * success. Allocates memory and reads the driver into it.
694 */
load_vbeaf_driver(AL_CONST char * filename)695 static int load_vbeaf_driver(AL_CONST char *filename)
696 {
697 long size;
698 PACKFILE *f;
699
700 #ifdef ALLEGRO_LINUX
701
702 /* on Linux. be paranoid and insist that vbeaf.drv belongs to root */
703 char tmp[128];
704 struct stat s;
705
706 if (stat(uconvert_toascii(filename, tmp), &s) != 0)
707 return 0;
708
709 if ((s.st_uid != 0) || (s.st_mode & (S_IWGRP | S_IWOTH))) {
710 uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s must only be writeable by root"), filename);
711 return -1;
712 }
713
714 size = s.st_size;
715 if (size <= 0)
716 return 0;
717
718 #else
719
720 /* simple version for other platforms */
721 size = file_size_ex(filename);
722 if (size <= 0)
723 return 0;
724
725 #endif
726
727 f = pack_fopen(filename, F_READ);
728 if (!f)
729 return 0;
730
731 af_driver = _accel_driver = _AL_MALLOC(size);
732
733 if (pack_fread(af_driver, size, f) != size) {
734 _AL_FREE(af_driver);
735 af_driver = _accel_driver = NULL;
736 return 0;
737 }
738
739 pack_fclose(f);
740
741 LOCK_DATA(af_driver, size);
742
743 return 1;
744 }
745
746
747
748 /* initialise_freebeaf_extensions:
749 * Prepares the FreeBE/AF extension functions.
750 */
initialise_freebeaf_extensions(void)751 static void initialise_freebeaf_extensions(void)
752 {
753 typedef unsigned long (*EXT_INIT_FUNC)(AF_DRIVER *af, unsigned long id);
754 EXT_INIT_FUNC ext_init;
755 unsigned long magic;
756 int v1, v2;
757
758 #ifdef ALLEGRO_DOS
759 void *ptr;
760 #endif
761
762 /* safety check */
763 if (!af_driver->OemExt) {
764 faf_ext = 0;
765 return;
766 }
767
768 /* call the extension init function */
769 ext_init = (EXT_INIT_FUNC)((long)af_driver + (long)af_driver->OemExt);
770
771 magic = ext_init(af_driver, FAFEXT_INIT);
772
773 /* check that it returned a nice magic number */
774 v1 = (magic>>8)&0xFF;
775 v2 = magic&0xFF;
776
777 if (((magic&0xFFFF0000) != FAFEXT_MAGIC) || (!uisdigit(v1)) || (!uisdigit(v2))) {
778 faf_ext = 0;
779 return;
780 }
781
782 faf_ext = (v1-'0')*10 + (v2-'0');
783
784 /* export libc and pmode functions if the driver wants them */
785 #ifdef ALLEGRO_DOS
786
787 ptr = af_driver->OemExt(af_driver, FAFEXT_LIBC);
788 if (ptr)
789 _fill_vbeaf_libc_exports(ptr);
790
791 ptr = af_driver->OemExt(af_driver, FAFEXT_PMODE);
792 if (ptr)
793 _fill_vbeaf_pmode_exports(ptr);
794
795 #endif
796 }
797
798
799
800 /* initialise_vbeaf_driver:
801 * Sets up the DPMI memory mappings required by the VBE/AF driver,
802 * returning zero on success.
803 */
initialise_vbeaf_driver(void)804 static int initialise_vbeaf_driver(void)
805 {
806 int c;
807
808 #ifdef ALLEGRO_DJGPP
809
810 /* query driver for the FreeBE/AF farptr extension */
811 if (faf_ext > 0)
812 faf_farptr = af_driver->OemExt(af_driver, FAFEXT_HWPTR);
813 else
814 faf_farptr = NULL;
815
816 #else
817
818 /* don't use farptr on any other platforms */
819 faf_farptr = NULL;
820
821 #endif
822
823 #ifdef ALLEGRO_DOS
824
825 if (faf_farptr) {
826 /* use farptr access */
827 for (c=0; c<4; c++) {
828 faf_farptr->IOMemMaps[c].sel = 0;
829 faf_farptr->IOMemMaps[c].offset = 0;
830 }
831
832 faf_farptr->BankedMem.sel = 0;
833 faf_farptr->BankedMem.offset = 0;
834
835 faf_farptr->LinearMem.sel = 0;
836 faf_farptr->LinearMem.offset = 0;
837
838 vbeaf_nearptr = FALSE;
839 }
840 else {
841 /* enable nearptr access */
842 if (_crt0_startup_flags & _CRT0_FLAG_NEARPTR) {
843 vbeaf_nearptr = FALSE;
844 }
845 else {
846 if (__djgpp_nearptr_enable() == 0)
847 return -2;
848
849 vbeaf_nearptr = TRUE;
850 }
851 }
852
853 #endif
854
855 /* create mapping for MMIO ports */
856 for (c=0; c<4; c++) {
857 if (af_driver->IOMemoryBase[c]) {
858 if (_create_linear_mapping(af_memmap+c, af_driver->IOMemoryBase[c],
859 af_driver->IOMemoryLen[c]) != 0)
860 return -1;
861
862 if (faf_farptr) {
863 /* farptr IO mapping */
864 if (_create_selector(&faf_farptr->IOMemMaps[c].sel, af_memmap[c],
865 af_driver->IOMemoryLen[c]) != 0) {
866 _remove_linear_mapping(af_memmap+c);
867 return -1;
868 }
869 faf_farptr->IOMemMaps[c].offset = 0;
870 af_driver->IOMemMaps[c] = NULL;
871 }
872 else {
873 /* nearptr IO mapping */
874 af_driver->IOMemMaps[c] = MVAL(af_memmap[c]);
875 }
876 }
877 }
878
879 /* create mapping for banked video RAM */
880 if (af_driver->BankedBasePtr) {
881 if (_create_linear_mapping(&af_banked_mem, af_driver->BankedBasePtr, 0x10000) != 0)
882 return -1;
883
884 if (faf_farptr) {
885 /* farptr banked vram mapping */
886 if (_create_selector(&faf_farptr->BankedMem.sel, af_banked_mem, 0x10000) != 0) {
887 _remove_linear_mapping(&af_banked_mem);
888 return -1;
889 }
890 faf_farptr->BankedMem.offset = 0;
891 af_driver->BankedMem = NULL;
892 }
893 else {
894 /* nearptr banked vram mapping */
895 af_driver->BankedMem = MVAL(af_banked_mem);
896 }
897 }
898
899 /* create mapping for linear video RAM */
900 if (af_driver->LinearBasePtr) {
901 if (_create_linear_mapping(&af_linear_mem, af_driver->LinearBasePtr, af_driver->LinearSize*1024) != 0)
902 return -1;
903
904 if (faf_farptr) {
905 /* farptr linear vram mapping */
906 if (_create_selector(&faf_farptr->LinearMem.sel, af_linear_mem, af_driver->LinearSize*1024) != 0) {
907 _remove_linear_mapping(&af_linear_mem);
908 return -1;
909 }
910 faf_farptr->LinearMem.offset = 0;
911 af_driver->LinearMem = NULL;
912 }
913 else {
914 /* nearptr linear vram mapping */
915 af_driver->LinearMem = MVAL(af_linear_mem);
916 }
917 }
918
919 /* callback functions: why are these needed? ugly, IMHO */
920 af_driver->Int86 = _af_int86;
921 af_driver->CallRealMode = _af_call_rm;
922
923 return 0;
924 }
925
926
927
928 /* find_vbeaf_mode:
929 * Tries to find a VBE/AF mode number for the specified screen size.
930 */
find_vbeaf_mode(int w,int h,int v_w,int v_h,int color_depth,AF_MODE_INFO * mode_info)931 static int find_vbeaf_mode(int w, int h, int v_w, int v_h, int color_depth, AF_MODE_INFO *mode_info)
932 {
933 unsigned short *mode;
934
935 /* search the list of modes */
936 for (mode = af_driver->AvailableModes; *mode != 0xFFFF; mode++) {
937
938 /* retrieve the mode information block */
939 if (af_driver->GetVideoModeInfo(af_driver, *mode, mode_info) == 0) {
940
941 /* check size and color depth */
942 if ((mode_info->XResolution == w) &&
943 (mode_info->YResolution == h) &&
944 (mode_info->BitsPerPixel == color_depth) &&
945 (mode_info->MaxScanLineWidth >= v_w)) {
946
947 /* make sure the mode supports scrolling */
948 if ((v_w > w) || (v_h > h)) {
949 if (!(mode_info->Attributes & 2)) {
950 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Hardware scrolling not supported"));
951 return 0;
952 }
953 }
954
955 /* if it isn't FreeBE/AF, it must be UniVBE, so if we don't
956 * have hardware acceleration we may as well just fail this
957 * call and use VBE 3.0 instead.
958 */
959 if ((!(mode_info->Attributes & 16)) && (!faf_id)) {
960 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Hardware acceleration not available"));
961 return 0;
962 }
963
964 return *mode;
965 }
966 }
967 }
968
969 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Resolution not supported"));
970 return 0;
971 }
972
973
974
975 /* set_vbeaf_mode:
976 * Selects a VBE/AF graphics mode.
977 */
set_vbeaf_mode(int mode,int w,int h,int v_w,int v_h,int * width,int * scrollable)978 static int set_vbeaf_mode(int mode, int w, int h, int v_w, int v_h, int *width, int *scrollable)
979 {
980 long wret = *width;
981 int ret;
982
983 if (gfx_vbeaf.linear)
984 mode |= 0x4000;
985
986 /* try to set a large virtual screen */
987 mode |= 0x1000;
988 *scrollable = TRUE;
989
990 saved_mode = mode;
991 saved_vw = v_w;
992 saved_vh = v_h;
993 saved_wret = wret;
994
995 ret = af_driver->SetVideoMode(af_driver, mode, v_w, v_h, &wret, 1, NULL);
996
997 if ((ret != 0) && (v_w <= w) && (v_h <= h)) {
998 /* if that didn't work, try to set a non-scrolling framebuffer */
999 mode &= ~0x1000;
1000 *scrollable = FALSE;
1001
1002 saved_mode = mode;
1003 saved_wret = wret;
1004
1005 ret = af_driver->SetVideoMode(af_driver, mode, v_w, v_h, &wret, 1, NULL);
1006 }
1007
1008 *width = wret;
1009 return ret;
1010 }
1011
1012
1013
1014 /* vbeaf_locate_driver:
1015 * locates and loads a VBE/AF driver.
1016 */
vbeaf_locate_driver(void)1017 static int vbeaf_locate_driver(void)
1018 {
1019 static char *possible_filenames[] =
1020 {
1021 #ifdef ALLEGRO_DOS
1022 "c:\\vbeaf.drv",
1023 #else
1024 "/usr/local/lib/vbeaf.drv",
1025 "/usr/lib/vbeaf.drv",
1026 "/lib/vbeaf.drv",
1027 "/vbeaf.drv",
1028 #endif
1029 NULL
1030 };
1031
1032 char filename[1024], tmp1[1024], tmp2[128];
1033 AL_CONST char *p;
1034 int ret, i, attrib;
1035
1036 /* look for driver in the config file location */
1037 p = get_config_string(uconvert_ascii("graphics", tmp1), uconvert_ascii("vbeaf_driver", tmp2), NULL);
1038
1039 if ((p) && (ugetc(p))) {
1040 ustrzcpy(filename, sizeof(filename), p);
1041
1042 if (ugetc(get_filename(filename)) == 0) {
1043 append_filename(filename, filename, uconvert_ascii("vbeaf.drv", tmp1), sizeof(filename));
1044 }
1045 else {
1046 if (file_exists(filename, FA_DIREC, &attrib)) {
1047 if (attrib & FA_DIREC)
1048 append_filename(filename, filename, uconvert_ascii("vbeaf.drv", tmp1), sizeof(filename));
1049 }
1050 }
1051
1052 ret = load_vbeaf_driver(filename);
1053 if (ret)
1054 goto found_it;
1055 }
1056
1057 /* look for driver in the same directory as the program */
1058 get_executable_name(tmp1, sizeof(tmp1));
1059 replace_filename(filename, tmp1, uconvert_ascii("vbeaf.drv", tmp2), sizeof(filename));
1060 ret = load_vbeaf_driver(filename);
1061 if (ret)
1062 goto found_it;
1063
1064 /* look for driver in the default location */
1065 for (i=0; possible_filenames[i]; i++) {
1066 ret = load_vbeaf_driver(uconvert_ascii(possible_filenames[i], tmp1));
1067 if (ret)
1068 goto found_it;
1069 }
1070
1071 /* check the environment for a location */
1072 p = getenv("VBEAF_PATH");
1073 if (p) {
1074 append_filename(filename, uconvert_ascii(p, tmp1), uconvert_ascii("vbeaf.drv", tmp2), sizeof(filename));
1075 ret = load_vbeaf_driver(filename);
1076 if (ret)
1077 goto found_it;
1078 }
1079
1080 /* oops, no driver */
1081 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't find VBEAF.DRV"));
1082 ret = FALSE;
1083
1084 /* got it! */
1085 found_it:
1086
1087 return ret;
1088 }
1089
1090
1091
1092 /* vbeaf_lowlevel_init:
1093 * loads the VBE/AF driver and initializes it.
1094 */
vbeaf_lowlevel_init(void)1095 static int vbeaf_lowlevel_init(void)
1096 {
1097 int ret;
1098
1099 /* check the driver ID string */
1100 if (strcmp(af_driver->Signature, "VBEAF.DRV") != 0) {
1101 vbeaf_exit(NULL);
1102 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Bad VBE/AF driver ID string"));
1103 return FALSE;
1104 }
1105
1106 /* check the VBE/AF version number */
1107 if (af_driver->Version < 0x200) {
1108 vbeaf_exit(NULL);
1109 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Obsolete VBE/AF version (need 2.0 or greater)"));
1110 return FALSE;
1111 }
1112
1113 /* to run on Linux, we need to be God */
1114 #ifdef ALLEGRO_LINUX
1115
1116 if (!__al_linux_have_ioperms) {
1117 vbeaf_exit(NULL);
1118 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("This driver needs root privileges"));
1119 return FALSE;
1120 }
1121
1122 _vbeaf_selector = _default_ds();
1123
1124 #endif
1125
1126 /* detect and initialise the FreeBE/AF extensions */
1127 if (strstr(af_driver->OemVendorName, "FreeBE")) {
1128 faf_id = TRUE;
1129 initialise_freebeaf_extensions();
1130 }
1131 else {
1132 faf_id = FALSE;
1133 faf_ext = 0;
1134 }
1135
1136 /* special setup for Plug and Play hardware */
1137 if (call_vbeaf_asm(af_driver->PlugAndPlayInit) != 0) {
1138 vbeaf_exit(NULL);
1139 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VBE/AF Plug and Play initialisation failed"));
1140 return FALSE;
1141 }
1142
1143 /* deal with all that DPMI memory mapping crap */
1144 ret = initialise_vbeaf_driver();
1145 if (ret != 0) {
1146 vbeaf_exit(NULL);
1147 if (ret == -2)
1148 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VBE/AF nearptrs not supported on this platform"));
1149 else
1150 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can't map memory for VBE/AF"));
1151 return FALSE;
1152 }
1153
1154 /* low level driver initialisation */
1155 if (call_vbeaf_asm(af_driver->InitDriver) != 0) {
1156 vbeaf_exit(NULL);
1157 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("VBE/AF device not present"));
1158 return FALSE;
1159 }
1160
1161 return TRUE;
1162 }
1163
1164
1165
1166 /* vbeaf_init:
1167 * Tries to enter the specified graphics mode, and makes a screen bitmap
1168 * for it.
1169 */
vbeaf_init(int w,int h,int v_w,int v_h,int color_depth)1170 static BITMAP *vbeaf_init(int w, int h, int v_w, int v_h, int color_depth)
1171 {
1172 BITMAP *b;
1173 AF_MODE_INFO mode_info;
1174 int bpp = BYTES_PER_PIXEL(color_depth);
1175 int bytes_per_scanline, width, height;
1176 int scrollable, mode;
1177 int vseg;
1178 int rs, gs, bs;
1179 char tmp1[512];
1180 void *vaddr;
1181
1182 /* Do not continue if this version of Allegro was built in C-only mode.
1183 * The bank switchers assume asm-mode calling conventions, but the
1184 * library would try to call them with C calling conventions.
1185 */
1186 #ifdef ALLEGRO_NO_ASM
1187 return NULL;
1188 #endif
1189
1190 /* locate and load VBE/AF driver from disk */
1191 if (!vbeaf_locate_driver())
1192 return NULL;
1193
1194 LOCK_VARIABLE(af_driver);
1195 LOCK_VARIABLE(_accel_driver);
1196 LOCK_VARIABLE(_accel_active);
1197 LOCK_VARIABLE(_accel_set_bank);
1198 LOCK_VARIABLE(_accel_idle);
1199 LOCK_VARIABLE(vbeaf_cur_on);
1200 LOCK_VARIABLE(vbeaf_cur_x);
1201 LOCK_VARIABLE(vbeaf_cur_y);
1202 LOCK_FUNCTION(_accel_bank_switch);
1203 LOCK_FUNCTION(_accel_bank_stub);
1204 LOCK_FUNCTION(_af_wrapper);
1205 LOCK_FUNCTION(vbeaf_no_wait);
1206 LOCK_FUNCTION(vbeaf_move_mouse);
1207 LOCK_FUNCTION(vbeaf_draw_sprite);
1208 LOCK_FUNCTION(vbeaf_blit_from_memory);
1209
1210 /* init the currently loaded VBE/AF driver */
1211 if (!vbeaf_lowlevel_init())
1212 return NULL;
1213
1214 /* bodge to work around bugs in the present (6.51) version of UniVBE */
1215 if ((v_w > w) && (!faf_id)) {
1216 vbeaf_exit(NULL);
1217 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("SciTech VBE/AF drivers do not support wide virtual screens"));
1218 return NULL;
1219 }
1220
1221 /* get ourselves a mode number */
1222 mode = find_vbeaf_mode(w, h, v_w, v_h, color_depth, &mode_info);
1223 if (mode == 0) {
1224 vbeaf_exit(NULL);
1225 return NULL;
1226 }
1227
1228 gfx_vbeaf.vid_mem = af_driver->TotalMemory * 1024;
1229
1230 vaddr = NULL;
1231
1232 if (mode_info.Attributes & 8) {
1233 /* linear framebuffer */
1234 gfx_vbeaf.linear = TRUE;
1235 gfx_vbeaf.bank_size = gfx_vbeaf.bank_gran = 0;
1236 gfx_vbeaf.vid_phys_base = af_driver->LinearBasePtr;
1237 bytes_per_scanline = mode_info.LinBytesPerScanLine;
1238
1239 if (faf_farptr) {
1240 vaddr = (void *)faf_farptr->LinearMem.offset;
1241 vseg = faf_farptr->LinearMem.sel;
1242 }
1243 else {
1244 vaddr = af_driver->LinearMem;
1245 vseg = _default_ds();
1246 }
1247 }
1248 else {
1249 /* banked framebuffer */
1250 gfx_vbeaf.linear = FALSE;
1251 gfx_vbeaf.bank_size = 65536;
1252 gfx_vbeaf.bank_gran = af_driver->BankSize * 1024;
1253 gfx_vbeaf.vid_phys_base = af_driver->BankedBasePtr;
1254 bytes_per_scanline = mode_info.BytesPerScanLine;
1255
1256 if (faf_farptr) {
1257 vaddr = (void *)faf_farptr->BankedMem.offset;
1258 vseg = faf_farptr->BankedMem.sel;
1259 }
1260 else {
1261 vaddr = af_driver->BankedMem;
1262 vseg = _default_ds();
1263 }
1264 }
1265
1266 width = MAX(bytes_per_scanline, v_w*bpp);
1267 height = MAX(h, v_h);
1268 _sort_out_virtual_width(&width, &gfx_vbeaf);
1269
1270 if (width * height > gfx_vbeaf.vid_mem) {
1271 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Insufficient video memory"));
1272 vbeaf_exit(NULL);
1273 return NULL;
1274 }
1275
1276 /* set the mode */
1277 if (set_vbeaf_mode(mode, w, h, width/bpp, height, &width, &scrollable) != 0) {
1278 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed to set VBE/AF mode"));
1279 vbeaf_exit(NULL);
1280 return NULL;
1281 }
1282
1283 in_af_mode = TRUE;
1284 _accel_active = FALSE;
1285
1286 if (scrollable)
1287 height = MAX(height, (int)af_driver->OffscreenEndY+1);
1288
1289 if ((width/bpp < v_w) || (width/bpp < w) || (height < v_h) || (height < h)) {
1290 ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Virtual screen size too large"));
1291 vbeaf_exit(NULL);
1292 return NULL;
1293 }
1294
1295 /* construct the screen bitmap */
1296 b = _make_bitmap(width/bpp, height, (unsigned long)vaddr, &gfx_vbeaf, color_depth, width);
1297 if (!b) {
1298 vbeaf_exit(NULL);
1299 return NULL;
1300 }
1301
1302 b->seg = vseg;
1303
1304 /* set up the /AF driver state */
1305 af_driver->SetActiveBuffer(af_driver, 0);
1306 af_driver->SetVisibleBuffer(af_driver, 0, 0);
1307
1308 if (af_driver->EnableDirectAccess)
1309 af_driver->EnableDirectAccess(af_driver);
1310
1311 if (af_driver->SetClipRect)
1312 af_driver->SetClipRect(af_driver, 0, 0, b->w-1, b->h-1);
1313
1314 _accel_set_bank = af_driver->SetBank;
1315
1316 if (af_driver->EnableDirectAccess)
1317 _accel_idle = af_driver->EnableDirectAccess;
1318 else if (af_driver->WaitTillIdle)
1319 _accel_idle = af_driver->WaitTillIdle;
1320 else
1321 _accel_idle = vbeaf_no_wait;
1322
1323 if (gfx_vbeaf.linear) {
1324 if (_accel_idle == vbeaf_no_wait)
1325 b->write_bank = b->read_bank = _stub_bank_switch;
1326 else
1327 b->write_bank = b->read_bank = _accel_bank_stub;
1328 }
1329 else {
1330 b->write_bank = b->read_bank = _accel_bank_switch;
1331 b->id |= BMP_ID_NOBLIT;
1332 }
1333
1334 vbeaf_xscroll = vbeaf_yscroll = 0;
1335
1336 gfx_vbeaf.w = b->cr = w;
1337 gfx_vbeaf.h = b->cb = h;
1338
1339 /* set up the truecolor pixel format */
1340 #if (defined ALLEGRO_COLOR16) || (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32)
1341
1342 if (gfx_vbeaf.linear) {
1343 rs = mode_info.LinRedFieldPosition;
1344 gs = mode_info.LinGreenFieldPosition;
1345 bs = mode_info.LinBlueFieldPosition;
1346 }
1347 else {
1348 rs = mode_info.RedFieldPosition;
1349 gs = mode_info.GreenFieldPosition;
1350 bs = mode_info.BlueFieldPosition;
1351 }
1352
1353 switch (color_depth) {
1354
1355 #ifdef ALLEGRO_COLOR16
1356
1357 case 15:
1358 _rgb_r_shift_15 = rs;
1359 _rgb_g_shift_15 = gs;
1360 _rgb_b_shift_15 = bs;
1361 break;
1362
1363 case 16:
1364 _rgb_r_shift_16 = rs;
1365 _rgb_g_shift_16 = gs;
1366 _rgb_b_shift_16 = bs;
1367 break;
1368
1369 #endif
1370
1371 #ifdef ALLEGRO_COLOR24
1372
1373 case 24:
1374 _rgb_r_shift_24 = rs;
1375 _rgb_g_shift_24 = gs;
1376 _rgb_b_shift_24 = bs;
1377 break;
1378
1379 #endif
1380
1381 #ifdef ALLEGRO_COLOR32
1382
1383 case 32:
1384 _rgb_r_shift_32 = rs;
1385 _rgb_g_shift_32 = gs;
1386 _rgb_b_shift_32 = bs;
1387 break;
1388
1389 #endif
1390 }
1391
1392 #endif
1393
1394 orig_vline = _screen_vtable.vline;
1395 orig_hline = _screen_vtable.hline;
1396 orig_line = _screen_vtable.line;
1397 orig_rectfill = _screen_vtable.rectfill;
1398 orig_draw_glyph = _screen_vtable.draw_glyph;
1399 orig_draw_sprite = _screen_vtable.draw_sprite;
1400 orig_masked_blit = _screen_vtable.masked_blit;
1401
1402 /* is triple buffering supported? */
1403 if (mode_info.Attributes & 2048) {
1404 gfx_vbeaf.request_scroll = vbeaf_request_scroll;
1405 gfx_vbeaf.poll_scroll = vbeaf_poll_scroll;
1406 }
1407 else {
1408 gfx_vbeaf.request_scroll = NULL;
1409 gfx_vbeaf.poll_scroll = NULL;
1410 }
1411
1412 /* are hardware cursors supported? */
1413 if ((mode_info.Attributes & 64) && (af_driver->SetCursor)) {
1414 gfx_vbeaf.set_mouse_sprite = vbeaf_set_mouse_sprite;
1415 gfx_vbeaf.show_mouse = vbeaf_show_mouse;
1416 gfx_vbeaf.hide_mouse = vbeaf_hide_mouse;
1417 gfx_vbeaf.move_mouse = vbeaf_move_mouse;
1418 }
1419 else {
1420 gfx_vbeaf.set_mouse_sprite = NULL;
1421 gfx_vbeaf.show_mouse = NULL;
1422 gfx_vbeaf.hide_mouse = NULL;
1423 gfx_vbeaf.move_mouse = NULL;
1424 }
1425
1426 /* accelerated scanline fills? */
1427 if (af_driver->DrawScan)
1428 gfx_capabilities |= (GFX_HW_HLINE | GFX_HW_HLINE_XOR);
1429
1430 if (af_driver->DrawPattScan)
1431 gfx_capabilities |= GFX_HW_HLINE_SOLID_PATTERN;
1432
1433 if (af_driver->DrawColorPattScan)
1434 gfx_capabilities |= GFX_HW_HLINE_COPY_PATTERN;
1435
1436 /* accelerated line drawing? */
1437 if (af_driver->DrawLine)
1438 gfx_capabilities |= (GFX_HW_LINE | GFX_HW_LINE_XOR);
1439
1440 /* accelerated rectangle fills? */
1441 if (af_driver->DrawRect) {
1442 _screen_vtable.clear_to_color = vbeaf_clear_to_color;
1443 gfx_capabilities |= (GFX_HW_FILL | GFX_HW_FILL_XOR);
1444 }
1445
1446 if (af_driver->DrawPattRect)
1447 gfx_capabilities |= GFX_HW_FILL_SOLID_PATTERN;
1448
1449 if (af_driver->DrawColorPattRect)
1450 gfx_capabilities |= GFX_HW_FILL_COPY_PATTERN;
1451
1452 /* accelerated triangle drawing? */
1453 if (af_driver->DrawTrap)
1454 gfx_capabilities |= (GFX_HW_TRIANGLE | GFX_HW_TRIANGLE_XOR);
1455
1456 /* accelerated monochrome text output? */
1457 if (af_driver->PutMonoImage) {
1458 _screen_vtable.draw_glyph = vbeaf_draw_glyph;
1459 gfx_capabilities |= GFX_HW_GLYPH;
1460 }
1461
1462 /* accelerated video memory blits? */
1463 if (af_driver->BitBlt) {
1464 _screen_vtable.blit_to_self = vbeaf_blit_to_self;
1465 _screen_vtable.blit_to_self_forward = vbeaf_blit_to_self;
1466 _screen_vtable.blit_to_self_backward = vbeaf_blit_to_self;
1467 gfx_capabilities |= GFX_HW_VRAM_BLIT;
1468 }
1469
1470 /* accelerated blits from system memory? */
1471 if (af_driver->BitBltSys) {
1472 _screen_vtable.blit_from_memory = vbeaf_blit_from_memory;
1473 _screen_vtable.blit_from_system = vbeaf_blit_from_memory;
1474 gfx_capabilities |= GFX_HW_MEM_BLIT;
1475 }
1476
1477 /* accelerated masked blits? */
1478 if ((af_driver->SrcTransBlt) || (af_driver->SrcTransBltSys)) {
1479 _screen_vtable.masked_blit = vbeaf_masked_blit;
1480 _screen_vtable.draw_sprite = vbeaf_draw_sprite;
1481
1482 if (_screen_vtable.draw_256_sprite == orig_draw_sprite)
1483 _screen_vtable.draw_256_sprite = vbeaf_draw_sprite;
1484
1485 if (af_driver->SrcTransBlt)
1486 gfx_capabilities |= GFX_HW_VRAM_BLIT_MASKED;
1487
1488 if (af_driver->SrcTransBltSys)
1489 gfx_capabilities |= GFX_HW_MEM_BLIT_MASKED;
1490 }
1491
1492 /* set up the VBE/AF description string */
1493 ustrzcpy(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(af_driver->OemVendorName, tmp1));
1494
1495 if (gfx_vbeaf.linear)
1496 ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", linear", tmp1));
1497 else
1498 ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", banked", tmp1));
1499
1500 if (faf_ext > 0)
1501 uszprintf(vbeaf_desc+ustrsize(vbeaf_desc), sizeof(vbeaf_desc) - ustrsize(vbeaf_desc),
1502 uconvert_ascii(", FreeBE ex%02d", tmp1), faf_ext);
1503 else if (faf_id)
1504 ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", FreeBE noex", tmp1));
1505
1506 if (faf_farptr)
1507 ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", farptr", tmp1));
1508
1509 /* is this an accelerated or dumb framebuffer mode? */
1510 if (mode_info.Attributes & 16) {
1511 gfx_vbeaf.drawing_mode = vbeaf_drawing_mode;
1512 vbeaf_drawing_mode();
1513 ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", accel", tmp1));
1514 }
1515 else {
1516 gfx_vbeaf.drawing_mode = NULL;
1517 ustrzcat(vbeaf_desc, sizeof(vbeaf_desc), uconvert_ascii(", noaccel", tmp1));
1518 }
1519
1520 gfx_vbeaf.desc = vbeaf_desc;
1521
1522 #ifdef ALLEGRO_LINUX
1523
1524 __al_linux_console_graphics();
1525
1526 b->vtable->acquire = __al_linux_acquire_bitmap;
1527 b->vtable->release = __al_linux_release_bitmap;
1528
1529 #endif
1530
1531 return b;
1532 }
1533
1534
1535
1536 /* vbeaf_exit:
1537 * Shuts down the VBE/AF driver.
1538 */
vbeaf_exit(BITMAP * b)1539 static void vbeaf_exit(BITMAP *b)
1540 {
1541 int c;
1542
1543 /* shut down the driver */
1544 if (in_af_mode) {
1545 if (af_driver->EnableDirectAccess)
1546 af_driver->EnableDirectAccess(af_driver);
1547 else if (af_driver->WaitTillIdle)
1548 af_driver->WaitTillIdle(af_driver);
1549
1550 af_driver->RestoreTextMode(af_driver);
1551 in_af_mode = FALSE;
1552 }
1553
1554 /* undo memory mappings */
1555 if (faf_farptr) {
1556 for (c=0; c<4; c++)
1557 _remove_selector(&faf_farptr->IOMemMaps[c].sel);
1558
1559 _remove_selector(&faf_farptr->BankedMem.sel);
1560 _remove_selector(&faf_farptr->LinearMem.sel);
1561 }
1562
1563 for (c=0; c<4; c++)
1564 _remove_linear_mapping(af_memmap+c);
1565
1566 _remove_linear_mapping(&af_banked_mem);
1567 _remove_linear_mapping(&af_linear_mem);
1568
1569 if (af_driver) {
1570 _AL_FREE(af_driver);
1571 af_driver = _accel_driver = NULL;
1572 }
1573
1574 #ifdef ALLEGRO_DOS
1575
1576 if (vbeaf_nearptr) {
1577 __djgpp_nearptr_disable();
1578 vbeaf_nearptr = FALSE;
1579 }
1580
1581 #endif
1582
1583 #ifdef ALLEGRO_LINUX
1584
1585 __al_linux_console_text();
1586
1587 #endif
1588 }
1589
1590
1591
1592 /* vbeaf_save:
1593 * Saves the graphics state.
1594 */
vbeaf_save(void)1595 static void vbeaf_save(void)
1596 {
1597 if (af_driver->EnableDirectAccess)
1598 af_driver->EnableDirectAccess(af_driver);
1599 else if (af_driver->WaitTillIdle)
1600 af_driver->WaitTillIdle(af_driver);
1601
1602 af_driver->RestoreTextMode(af_driver);
1603
1604 in_af_mode = FALSE;
1605 }
1606
1607
1608
1609 /* vbeaf_restore:
1610 * Restores the graphics state.
1611 */
vbeaf_restore(void)1612 static void vbeaf_restore(void)
1613 {
1614 long wret = saved_wret;
1615
1616 af_driver->SetVideoMode(af_driver, saved_mode, saved_vw, saved_vh, &wret, 1, NULL);
1617
1618 af_driver->SetActiveBuffer(af_driver, 0);
1619 af_driver->SetVisibleBuffer(af_driver, 0, 0);
1620
1621 if (af_driver->EnableDirectAccess)
1622 af_driver->EnableDirectAccess(af_driver);
1623
1624 if (af_driver->SetClipRect)
1625 af_driver->SetClipRect(af_driver, 0, 0, SCREEN_W-1, SCREEN_H-1);
1626
1627 if (gfx_vbeaf.drawing_mode)
1628 gfx_vbeaf.drawing_mode();
1629
1630 vbeaf_scroll(vbeaf_xscroll, vbeaf_yscroll);
1631
1632 in_af_mode = TRUE;
1633 }
1634
1635
1636
1637 /* vbeaf_fetch_mode_list:
1638 * Attempts to create a list of valid video modes for the VBE/AF driver.
1639 * Returns the mode list on success or NULL on failure.
1640 */
vbeaf_fetch_mode_list(void)1641 static GFX_MODE_LIST *vbeaf_fetch_mode_list(void)
1642 {
1643 GFX_MODE_LIST *gfx_mode_list;
1644 AF_MODE_INFO *mode_info;
1645 unsigned short *mode;
1646 int vbeaf_was_off;
1647
1648 mode_info = _AL_MALLOC(sizeof(AF_MODE_INFO));
1649 if (!mode_info) return NULL;
1650
1651 /* make sure VBE/AF interface is enabled! */
1652 if (!af_driver) {
1653 if (!vbeaf_locate_driver()) {
1654 if (mode_info) _AL_FREE(mode_info);
1655
1656 return NULL;
1657 }
1658 if (!vbeaf_lowlevel_init()) {
1659 if (mode_info) _AL_FREE(mode_info);
1660
1661 return NULL;
1662 }
1663 vbeaf_was_off = TRUE;
1664 }
1665 else
1666 vbeaf_was_off = FALSE;
1667
1668 /* start building mode-list */
1669 gfx_mode_list = _AL_MALLOC(sizeof(GFX_MODE_LIST));
1670 if (!gfx_mode_list) {
1671 if (mode_info) _AL_FREE(mode_info);
1672
1673 return NULL;
1674 }
1675 gfx_mode_list->mode = NULL;
1676 gfx_mode_list->num_modes = 0;
1677
1678 /* create mode list */
1679 for (mode = af_driver->AvailableModes; *mode != 0xFFFF; mode++) {
1680 gfx_mode_list->mode = _al_sane_realloc(gfx_mode_list->mode, sizeof(GFX_MODE) * (gfx_mode_list->num_modes + 1));
1681 if (!gfx_mode_list->mode) {
1682 if (mode_info) _AL_FREE(mode_info);
1683 if (gfx_mode_list) _AL_FREE(gfx_mode_list);
1684
1685 return NULL;
1686 }
1687 if (af_driver->GetVideoModeInfo(af_driver, *mode, mode_info) != 0) {
1688 if (mode_info) _AL_FREE(mode_info);
1689 if (gfx_mode_list->mode) _AL_FREE(gfx_mode_list->mode);
1690 if (gfx_mode_list) _AL_FREE(gfx_mode_list);
1691
1692 return NULL;
1693 }
1694
1695 gfx_mode_list->mode[gfx_mode_list->num_modes].width = mode_info->XResolution;
1696 gfx_mode_list->mode[gfx_mode_list->num_modes].height = mode_info->YResolution;
1697 gfx_mode_list->mode[gfx_mode_list->num_modes].bpp = mode_info->BitsPerPixel;
1698
1699 gfx_mode_list->num_modes++;
1700 }
1701
1702 /* terminate mode list */
1703 gfx_mode_list->mode = _al_sane_realloc(gfx_mode_list->mode, sizeof(GFX_MODE) * (gfx_mode_list->num_modes + 1));
1704 if (!gfx_mode_list->mode) {
1705 if (mode_info) _AL_FREE(mode_info);
1706 if (gfx_mode_list) _AL_FREE(gfx_mode_list);
1707
1708 return NULL;
1709 }
1710
1711 gfx_mode_list->mode[gfx_mode_list->num_modes].width = 0;
1712 gfx_mode_list->mode[gfx_mode_list->num_modes].height = 0;
1713 gfx_mode_list->mode[gfx_mode_list->num_modes].bpp = 0;
1714
1715 /* shut down VBE/AF interface if it wasn't previously loaded */
1716 if (vbeaf_was_off)
1717 vbeaf_exit(NULL);
1718
1719 if (mode_info) _AL_FREE(mode_info);
1720
1721 return gfx_mode_list;
1722 }
1723
1724
1725
1726 /* vbeaf_vsync:
1727 * VBE/AF vsync routine, needed for cards that don't emulate the VGA
1728 * blanking registers. VBE/AF doesn't provide a vsync function, but we
1729 * can emulate it by altering the display start address with the vsync
1730 * flag set.
1731 */
vbeaf_vsync(void)1732 static void vbeaf_vsync(void)
1733 {
1734 vbeaf_scroll(vbeaf_xscroll, vbeaf_yscroll);
1735 }
1736
1737
1738
1739 /* vbeaf_scroll:
1740 * Hardware scrolling routine.
1741 */
vbeaf_scroll(int x,int y)1742 static int vbeaf_scroll(int x, int y)
1743 {
1744 int moved = (vbeaf_xscroll != x) || (vbeaf_yscroll != y);
1745
1746 vbeaf_xscroll = x;
1747 vbeaf_yscroll = y;
1748
1749 SAFISH_CALL(
1750 if (_wait_for_vsync && af_driver->WaitTillIdle)
1751 af_driver->WaitTillIdle(af_driver);
1752
1753 af_driver->SetDisplayStart(af_driver, x, y, 1);
1754 );
1755
1756 if ((vbeaf_cur_bmp) && (moved))
1757 vbeaf_move_mouse(vbeaf_cur_x, vbeaf_cur_y);
1758
1759 return 0;
1760 }
1761
1762
1763
1764 /* vbeaf_set_palette_range:
1765 * Uses VBE/AF functions to set the palette.
1766 */
vbeaf_set_palette_range(AL_CONST PALETTE p,int from,int to,int vsync)1767 static void vbeaf_set_palette_range(AL_CONST PALETTE p, int from, int to, int vsync)
1768 {
1769 AF_PALETTE tmp[256];
1770 int c;
1771
1772 for (c=from; c<=to; c++) {
1773 tmp[c-from].red = p[c].r << 2;
1774 tmp[c-from].green = p[c].g << 2;
1775 tmp[c-from].blue = p[c].b << 2;
1776 tmp[c-from].alpha = 0;
1777 }
1778
1779 SAFISH_CALL(
1780 af_driver->SetPaletteData(af_driver, tmp, to-from+1, from, (vsync ? 1 : 0));
1781 );
1782 }
1783
1784
1785
1786 /* vbeaf_request_scroll:
1787 * Triple buffering initiate routine.
1788 */
vbeaf_request_scroll(int x,int y)1789 static int vbeaf_request_scroll(int x, int y)
1790 {
1791 vbeaf_xscroll = x;
1792 vbeaf_yscroll = y;
1793
1794 SAFISH_CALL(
1795 if (af_driver->WaitTillIdle)
1796 af_driver->WaitTillIdle(af_driver);
1797
1798 af_driver->SetDisplayStart(af_driver, x, y, 0);
1799 );
1800
1801 if (vbeaf_cur_bmp)
1802 vbeaf_move_mouse(vbeaf_cur_x, vbeaf_cur_y);
1803
1804 return 0;
1805 }
1806
1807
1808
1809 /* vbeaf_poll_scroll:
1810 * Triple buffering test routine.
1811 */
vbeaf_poll_scroll(void)1812 static int vbeaf_poll_scroll(void)
1813 {
1814 int ret;
1815
1816 SAFISH_CALL(
1817 ret = af_driver->GetDisplayStartStatus(af_driver);
1818 );
1819
1820 return (ret) ? FALSE : TRUE;
1821 }
1822
1823
1824
1825 /* vbeaf_set_mouse_sprite:
1826 * Attempts to download a new hardware cursor graphic, returning zero on
1827 * success or non-zero if this image is unsuitable.
1828 */
vbeaf_set_mouse_sprite(BITMAP * sprite,int xfocus,int yfocus)1829 static int vbeaf_set_mouse_sprite(BITMAP *sprite, int xfocus, int yfocus)
1830 {
1831 AF_CURSOR cursor;
1832 int bpp = bitmap_color_depth(sprite);
1833 int c, x, y;
1834 int iszero;
1835
1836 /* hardware cursors cannot be larger than 32x32 */
1837 if ((sprite->w > 32) || (sprite->h > 32))
1838 return -1;
1839
1840 /* clear the cursor data */
1841 for (c=0; c<32; c++) {
1842 cursor.andMask[c] = 0;
1843 cursor.xorMask[c] = 0;
1844 }
1845
1846 vbeaf_cur_c1 = -1;
1847 vbeaf_cur_c2 = -1;
1848
1849 /* scan through the pointer image */
1850 for (y=0; y<sprite->h; y++) {
1851 for (x=0; x<sprite->w; x++) {
1852
1853 c = getpixel(sprite, x, y);
1854
1855 if (c == bitmap_mask_color(sprite)) {
1856 /* skip masked pixels */
1857 }
1858 else if (c == vbeaf_cur_c1) {
1859 /* color #1 pixel */
1860 cursor.andMask[y] |= 0x80000000>>x;
1861 cursor.xorMask[y] |= 0x80000000>>x;
1862 }
1863 else if (c == vbeaf_cur_c2) {
1864 /* color #2 pixel */
1865 cursor.andMask[y] |= 0x80000000>>x;
1866 }
1867 else {
1868 /* check whether this pixel value is zero */
1869 if (bpp == 8) {
1870 iszero = ((getr_depth(bpp, c) == getr_depth(bpp, 0)) &&
1871 (getg_depth(bpp, c) == getg_depth(bpp, 0)) &&
1872 (getb_depth(bpp, c) == getb_depth(bpp, 0)));
1873 }
1874 else {
1875 iszero = ((getr_depth(bpp, c) == 0) &&
1876 (getg_depth(bpp, c) == 0) &&
1877 (getb_depth(bpp, c) == 0));
1878 }
1879
1880 if ((vbeaf_cur_c2 < 0) && (iszero)) {
1881 /* zero pixel value = color #2 */
1882 vbeaf_cur_c2 = c;
1883 cursor.andMask[y] |= 0x80000000>>x;
1884 }
1885 else if (vbeaf_cur_c1 < 0) {
1886 /* other pixel value = color #1 */
1887 vbeaf_cur_c1 = c;
1888 cursor.andMask[y] |= 0x80000000>>x;
1889 cursor.xorMask[y] |= 0x80000000>>x;
1890 }
1891 else {
1892 /* it's not cool if there are more than two colors! */
1893 return -1;
1894 }
1895 }
1896 }
1897 }
1898
1899 /* flip the endianess */
1900 for (c=0; c<32; c++) {
1901 cursor.andMask[c] = bswap(cursor.andMask[c]);
1902 cursor.xorMask[c] = bswap(cursor.xorMask[c]);
1903 }
1904
1905 cursor.hotx = xfocus;
1906 cursor.hoty = yfocus;
1907
1908 /* download to the hardware */
1909 SAFISH_CALL(
1910 af_driver->SetCursor(af_driver, &cursor);
1911
1912 if ((bpp > 8) && (vbeaf_cur_c1 >= 0)) {
1913 af_driver->SetCursorColor(af_driver,
1914 getr_depth(bpp, vbeaf_cur_c1),
1915 getg_depth(bpp, vbeaf_cur_c1),
1916 getb_depth(bpp, vbeaf_cur_c1));
1917 }
1918 );
1919
1920 return 0;
1921 }
1922
1923
1924
1925 /* vbeaf_show_mouse:
1926 * Turns on the hardware cursor, returning zero on success.
1927 */
vbeaf_show_mouse(BITMAP * bmp,int x,int y)1928 static int vbeaf_show_mouse(BITMAP *bmp, int x, int y)
1929 {
1930 if (bitmap_color_depth(bmp) == 8) {
1931 if (vbeaf_cur_c2 >= 0) {
1932 /* check that the palette contains a valid zero color */
1933 if ((getr_depth(8, vbeaf_cur_c2) != getr_depth(8, 0)) ||
1934 (getg_depth(8, vbeaf_cur_c2) != getg_depth(8, 0)) ||
1935 (getb_depth(8, vbeaf_cur_c2) != getb_depth(8, 0)))
1936 return -1;
1937 }
1938
1939 /* set the cursor color */
1940 if (vbeaf_cur_c1 >= 0) {
1941 SAFISH_CALL(
1942 af_driver->SetCursorColor(af_driver, vbeaf_cur_c1, 0, 0);
1943 );
1944 }
1945 }
1946
1947 vbeaf_cur_bmp = bmp;
1948 vbeaf_cur_on = FALSE;
1949
1950 vbeaf_move_mouse(x, y);
1951
1952 return 0;
1953 }
1954
1955
1956
1957 /* vbeaf_hide_mouse:
1958 * Gets rid of the hardware cursor.
1959 */
vbeaf_hide_mouse(void)1960 static void vbeaf_hide_mouse(void)
1961 {
1962 SAFISH_CALL(
1963 af_driver->ShowCursor(af_driver, 0);
1964 );
1965
1966 vbeaf_cur_bmp = NULL;
1967 vbeaf_cur_on = FALSE;
1968 }
1969
1970
1971
1972 /* vbeaf_move_mouse:
1973 * Sets the hardware cursor position.
1974 */
vbeaf_move_mouse(int x,int y)1975 static void vbeaf_move_mouse(int x, int y)
1976 {
1977 int hx, hy;
1978 int onscreen;
1979
1980 hx = x + vbeaf_cur_bmp->x_ofs - vbeaf_xscroll;
1981 hy = y + vbeaf_cur_bmp->y_ofs - vbeaf_yscroll;
1982
1983 onscreen = (hx >= 0) && (hx < SCREEN_W) && (hy >= 0) && (hy < SCREEN_H);
1984
1985 SAFISH_CALL(
1986 if (onscreen) {
1987 af_driver->SetCursorPos(af_driver, hx, hy);
1988
1989 if (!vbeaf_cur_on) {
1990 af_driver->ShowCursor(af_driver, 1);
1991 vbeaf_cur_on = TRUE;
1992 }
1993 }
1994 else {
1995 if (vbeaf_cur_on) {
1996 af_driver->ShowCursor(af_driver, 0);
1997 vbeaf_cur_on = FALSE;
1998 }
1999 }
2000 );
2001
2002 vbeaf_cur_x = x;
2003 vbeaf_cur_y = y;
2004 }
2005
2006 END_OF_STATIC_FUNCTION(vbeaf_move_mouse);
2007
2008
2009
2010 /* vbeaf_drawing_mode:
2011 * Hook to tell us that the drawing mode has been changed, so we may need
2012 * to alter some of our vtable entries.
2013 */
vbeaf_drawing_mode(void)2014 static void vbeaf_drawing_mode(void)
2015 {
2016 vbeaf_pattern = NULL;
2017
2018 if ((_drawing_mode == DRAW_MODE_SOLID) || (_drawing_mode == DRAW_MODE_XOR)) {
2019 /* easy, everything supports solid and XOR drawing */
2020 _screen_vtable.hline = (af_driver->DrawScan) ? vbeaf_hline : orig_hline;
2021 _screen_vtable.vline = (af_driver->DrawLine) ? vbeaf_vline_a : ((af_driver->DrawRect) ? vbeaf_vline_b : orig_vline);
2022 _screen_vtable.line = (af_driver->DrawLine) ? vbeaf_line : orig_line;
2023 _screen_vtable.rectfill = (af_driver->DrawRect) ? vbeaf_rectfill : orig_rectfill;
2024 _screen_vtable.triangle = (af_driver->DrawTrap) ? vbeaf_triangle : NULL;
2025
2026 vbeaf_fg_mix = vbeaf_bg_mix = (_drawing_mode == DRAW_MODE_XOR) ? 3 : 0;
2027
2028 SAFISH_CALL(
2029 af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix);
2030 );
2031 return;
2032 }
2033
2034 if ((_drawing_mode == DRAW_MODE_COPY_PATTERN) &&
2035 (_drawing_pattern->w <= 8) && (_drawing_pattern->h <= 8)) {
2036 /* color patterns can be done in hardware if they are small enough */
2037 _screen_vtable.hline = (af_driver->DrawColorPattScan) ? vbeaf_hline : orig_hline;
2038 _screen_vtable.vline = (af_driver->DrawColorPattRect) ? vbeaf_vline_b : orig_vline;
2039 _screen_vtable.line = orig_line;
2040 _screen_vtable.rectfill = (af_driver->DrawColorPattRect) ? vbeaf_rectfill : orig_rectfill;
2041 _screen_vtable.triangle = NULL;
2042
2043 vbeaf_fg_mix = vbeaf_bg_mix = 0;
2044
2045 SAFISH_CALL(
2046 af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix);
2047 );
2048 return;
2049 }
2050
2051 if (((_drawing_mode == DRAW_MODE_SOLID_PATTERN) || (_drawing_mode == DRAW_MODE_MASKED_PATTERN)) &&
2052 (_drawing_pattern->w <= 8) && (_drawing_pattern->h <= 8)) {
2053 /* mono patterns can be done in hardware if they are small enough */
2054 _screen_vtable.hline = (af_driver->DrawPattScan) ? vbeaf_hline : orig_hline;
2055 _screen_vtable.vline = (af_driver->DrawPattRect) ? vbeaf_vline_b : orig_vline;
2056 _screen_vtable.line = orig_line;
2057 _screen_vtable.rectfill = (af_driver->DrawPattRect) ? vbeaf_rectfill : orig_rectfill;
2058 _screen_vtable.triangle = NULL;
2059
2060 vbeaf_fg_mix = 0;
2061 vbeaf_bg_mix = (_drawing_mode == DRAW_MODE_MASKED_PATTERN) ? 4 : 0;
2062
2063 SAFISH_CALL(
2064 af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix);
2065 );
2066 return;
2067 }
2068
2069 /* urgh, have to use software drawing functions for this mode */
2070 _screen_vtable.vline = orig_vline;
2071 _screen_vtable.hline = orig_hline;
2072 _screen_vtable.line = orig_line;
2073 _screen_vtable.rectfill = orig_rectfill;
2074 _screen_vtable.triangle = NULL;
2075
2076 vbeaf_fg_mix = vbeaf_bg_mix = 0;
2077
2078 SAFISH_CALL(
2079 af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix);
2080 );
2081 }
2082
2083
2084
2085 /* prepare_color_pattern:
2086 * Sets up the hardware ready for a colored pattern drawing operation.
2087 */
prepare_color_pattern(BITMAP * bmp)2088 static void prepare_color_pattern(BITMAP *bmp)
2089 {
2090 static unsigned long pattern[64];
2091 int x, y, xx, yy, xo, yo;
2092
2093 if (vbeaf_pattern != bmp) {
2094 xo = _drawing_x_anchor + bmp->x_ofs;
2095 yo = _drawing_y_anchor + bmp->y_ofs;
2096
2097 switch (bitmap_color_depth(bmp)) {
2098
2099 #ifdef ALLEGRO_COLOR8
2100
2101 case 8:
2102 for (y=0; y<8; y++) {
2103 for (x=0; x<8; x++) {
2104 xx = (x-xo) & _drawing_x_mask;
2105 yy = (y-yo) & _drawing_y_mask;
2106 pattern[y*8+x] = _drawing_pattern->line[yy][xx];
2107 }
2108 }
2109 break;
2110
2111 #endif
2112
2113 #ifdef ALLEGRO_COLOR16
2114
2115 case 15:
2116 case 16:
2117 for (y=0; y<8; y++) {
2118 for (x=0; x<8; x++) {
2119 xx = (x-xo) & _drawing_x_mask;
2120 yy = (y-yo) & _drawing_y_mask;
2121 pattern[y*8+x] = ((unsigned short *)_drawing_pattern->line[yy])[xx];
2122 }
2123 }
2124 break;
2125
2126 #endif
2127
2128 #ifdef ALLEGRO_COLOR24
2129
2130 case 24:
2131 for (y=0; y<8; y++) {
2132 for (x=0; x<8; x++) {
2133 xx = (x-xo) & _drawing_x_mask;
2134 yy = (y-yo) & _drawing_y_mask;
2135 pattern[y*8+x] = *((unsigned long *)(_drawing_pattern->line[yy]+xx*3)) & 0xFFFFFF;
2136 }
2137 }
2138 break;
2139
2140 #endif
2141
2142 #ifdef ALLEGRO_COLOR32
2143
2144 case 32:
2145 for (y=0; y<8; y++) {
2146 for (x=0; x<8; x++) {
2147 xx = (x-xo) & _drawing_x_mask;
2148 yy = (y-yo) & _drawing_y_mask;
2149 pattern[y*8+x] = ((unsigned long *)_drawing_pattern->line[yy])[xx];
2150 }
2151 }
2152 break;
2153
2154 #endif
2155 }
2156
2157 af_driver->Set8x8ColorPattern(af_driver, 0, pattern);
2158 af_driver->Use8x8ColorPattern(af_driver, 0);
2159
2160 vbeaf_pattern = bmp;
2161 }
2162 }
2163
2164
2165
2166 /* prepare_mono_pattern:
2167 * Sets up the hardware ready for a mono pattern drawing operation.
2168 */
prepare_mono_pattern(BITMAP * bmp)2169 static void prepare_mono_pattern(BITMAP *bmp)
2170 {
2171 static unsigned char pattern[8];
2172 int x, y, xx, yy, xo, yo;
2173
2174 if (vbeaf_pattern != bmp) {
2175 xo = _drawing_x_anchor + bmp->x_ofs;
2176 yo = _drawing_y_anchor + bmp->y_ofs;
2177
2178 switch (bitmap_color_depth(bmp)) {
2179
2180 #ifdef ALLEGRO_COLOR16
2181
2182 case 8:
2183 for (y=0; y<8; y++) {
2184 pattern[y] = 0;
2185 for (x=0; x<8; x++) {
2186 xx = (x-xo) & _drawing_x_mask;
2187 yy = (y-yo) & _drawing_y_mask;
2188 if (_drawing_pattern->line[yy][xx])
2189 pattern[y] |= (0x80>>x);
2190 }
2191 }
2192 break;
2193
2194 #endif
2195
2196 #ifdef ALLEGRO_COLOR16
2197
2198 case 15:
2199 case 16:
2200 for (y=0; y<8; y++) {
2201 pattern[y] = 0;
2202 for (x=0; x<8; x++) {
2203 xx = (x-xo) & _drawing_x_mask;
2204 yy = (y-yo) & _drawing_y_mask;
2205 if (((unsigned short *)_drawing_pattern->line[yy])[xx] != bitmap_mask_color(bmp))
2206 pattern[y] |= (0x80>>x);
2207 }
2208 }
2209 break;
2210
2211 #endif
2212
2213 #ifdef ALLEGRO_COLOR24
2214
2215 case 24:
2216 for (y=0; y<8; y++) {
2217 pattern[y] = 0;
2218 for (x=0; x<8; x++) {
2219 xx = (x-xo) & _drawing_x_mask;
2220 yy = (y-yo) & _drawing_y_mask;
2221 if ((*((unsigned long *)(_drawing_pattern->line[yy]+xx*3)) & 0xFFFFFF) != MASK_COLOR_24)
2222 pattern[y] |= (0x80>>x);
2223 }
2224 }
2225 break;
2226
2227 #endif
2228
2229 #ifdef ALLEGRO_COLOR32
2230
2231 case 32:
2232 for (y=0; y<8; y++) {
2233 pattern[y] = 0;
2234 for (x=0; x<8; x++) {
2235 xx = (x-xo) & _drawing_x_mask;
2236 yy = (y-yo) & _drawing_y_mask;
2237 if (((unsigned long *)_drawing_pattern->line[yy])[xx] != MASK_COLOR_32)
2238 pattern[y] |= (0x80>>x);
2239 }
2240 }
2241 break;
2242
2243 #endif
2244 }
2245
2246 af_driver->Set8x8MonoPattern(af_driver, pattern);
2247
2248 vbeaf_pattern = bmp;
2249 }
2250 }
2251
2252
2253
2254 /* go_accel:
2255 * Prepares the hardware for an accelerated drawing operation.
2256 */
go_accel(void)2257 static INLINE void go_accel(void)
2258 {
2259 /* turn on the accelerator */
2260 if (!_accel_active) {
2261 if (af_driver->DisableDirectAccess)
2262 af_driver->DisableDirectAccess(af_driver);
2263
2264 _accel_active = TRUE;
2265 }
2266 }
2267
2268
2269
2270 /* vbeaf_hline:
2271 * Accelerated scanline filling routine.
2272 */
vbeaf_hline(BITMAP * bmp,int x1,int y,int x2,int color)2273 static void vbeaf_hline(BITMAP *bmp, int x1, int y, int x2, int color)
2274 {
2275 if (x1 > x2) {
2276 int tmp = x1;
2277 x1 = x2;
2278 x2 = tmp;
2279 }
2280
2281 if (bmp->clip) {
2282 if ((y < bmp->ct) || (y >= bmp->cb))
2283 return;
2284
2285 if (x1 < bmp->cl)
2286 x1 = bmp->cl;
2287
2288 if (x2 >= bmp->cr)
2289 x2 = bmp->cr-1;
2290
2291 if (x2 < x1)
2292 return;
2293 }
2294
2295 SAFISH_CALL(
2296 go_accel();
2297
2298 switch (_drawing_mode) {
2299
2300 case DRAW_MODE_SOLID:
2301 case DRAW_MODE_XOR:
2302 /* normal scanline fill */
2303 af_driver->DrawScan(af_driver, color, y+bmp->y_ofs,
2304 x1+bmp->x_ofs, x2+bmp->x_ofs+1);
2305 break;
2306
2307 case DRAW_MODE_COPY_PATTERN:
2308 /* colored pattern scanline fill */
2309 prepare_color_pattern(bmp);
2310
2311 af_driver->DrawColorPattScan(af_driver, y+bmp->y_ofs,
2312 x1+bmp->x_ofs, x2+bmp->x_ofs+1);
2313 break;
2314
2315 case DRAW_MODE_SOLID_PATTERN:
2316 case DRAW_MODE_MASKED_PATTERN:
2317 /* mono pattern scanline fill */
2318 prepare_mono_pattern(bmp);
2319
2320 af_driver->DrawPattScan(af_driver, color, 0, y+bmp->y_ofs,
2321 x1+bmp->x_ofs, x2+bmp->x_ofs+1);
2322 break;
2323 }
2324 );
2325 }
2326
2327
2328
2329 /* vbeaf_vline_a:
2330 * Accelerated vertical line drawer, using the VBE/AF line primitive.
2331 */
vbeaf_vline_a(BITMAP * bmp,int x,int y1,int y2,int color)2332 static void vbeaf_vline_a(BITMAP *bmp, int x, int y1, int y2, int color)
2333 {
2334 if (y1 > y2) {
2335 int tmp = y1;
2336 y1 = y2;
2337 y2 = tmp;
2338 }
2339
2340 if (bmp->clip) {
2341 if ((x < bmp->cl) || (x >= bmp->cr))
2342 return;
2343
2344 if (y1 < bmp->ct)
2345 y1 = bmp->ct;
2346
2347 if (y2 >= bmp->cb)
2348 y2 = bmp->cb-1;
2349
2350 if (y2 < y1)
2351 return;
2352 }
2353
2354 SAFISH_CALL(
2355 go_accel();
2356
2357 af_driver->DrawLine(af_driver, color,
2358 itofix(x+bmp->x_ofs), itofix(y1+bmp->y_ofs),
2359 itofix(x+bmp->x_ofs), itofix(y2+bmp->y_ofs));
2360 );
2361 }
2362
2363
2364
2365 /* vbeaf_vline_b:
2366 * Accelerated vertical line drawer, using the VBE/AF rectangle primitive.
2367 */
vbeaf_vline_b(BITMAP * bmp,int x,int y1,int y2,int color)2368 static void vbeaf_vline_b(BITMAP *bmp, int x, int y1, int y2, int color)
2369 {
2370 if (y1 > y2) {
2371 int tmp = y1;
2372 y1 = y2;
2373 y2 = tmp;
2374 }
2375
2376 if (bmp->clip) {
2377 if ((x < bmp->cl) || (x >= bmp->cr))
2378 return;
2379
2380 if (y1 < bmp->ct)
2381 y1 = bmp->ct;
2382
2383 if (y2 >= bmp->cb)
2384 y2 = bmp->cb-1;
2385
2386 if (y2 < y1)
2387 return;
2388 }
2389
2390 SAFISH_CALL(
2391 go_accel();
2392
2393 switch (_drawing_mode) {
2394
2395 case DRAW_MODE_SOLID:
2396 case DRAW_MODE_XOR:
2397 /* mono vertical line */
2398 af_driver->DrawRect(af_driver, color,
2399 x+bmp->x_ofs, y1+bmp->y_ofs, 1, y2-y1+1);
2400 break;
2401
2402 case DRAW_MODE_COPY_PATTERN:
2403 /* colored pattern vertical line */
2404 prepare_color_pattern(bmp);
2405
2406 af_driver->DrawColorPattRect(af_driver,
2407 x+bmp->x_ofs, y1+bmp->y_ofs, 1, y2-y1+1);
2408 break;
2409
2410 case DRAW_MODE_SOLID_PATTERN:
2411 case DRAW_MODE_MASKED_PATTERN:
2412 /* mono pattern vertical line */
2413 prepare_mono_pattern(bmp);
2414
2415 af_driver->DrawPattRect(af_driver, color, 0,
2416 x+bmp->x_ofs, y1+bmp->y_ofs, 1, y2-y1+1);
2417 break;
2418 }
2419 );
2420 }
2421
2422
2423
2424 /* vbeaf_line:
2425 * Accelerated line drawer.
2426 */
vbeaf_line(BITMAP * bmp,int x1,int y1,int x2,int y2,int color)2427 static void vbeaf_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
2428 {
2429 int sx, sy, dx, dy, t;
2430
2431 if (bmp->clip) {
2432 sx = x1;
2433 sy = y1;
2434 dx = x2;
2435 dy = y2;
2436
2437 if (sx > dx) {
2438 t = sx;
2439 sx = dx;
2440 dx = t;
2441 }
2442
2443 if (sy > dy) {
2444 t = sy;
2445 sy = dy;
2446 dy = t;
2447 }
2448
2449 if ((sx >= bmp->cr) || (sy >= bmp->cb) || (dx < bmp->cl) || (dy < bmp->ct))
2450 return;
2451
2452 if ((sx < bmp->cl) || (sy < bmp->ct) || (dx >= bmp->cr) || (dy >= bmp->cb)) {
2453 orig_line(bmp, x1, y1, x2, y2, color);
2454 return;
2455 }
2456 }
2457
2458 SAFISH_CALL(
2459 go_accel();
2460
2461 af_driver->DrawLine(af_driver, color,
2462 itofix(x1+bmp->x_ofs), itofix(y1+bmp->y_ofs),
2463 itofix(x2+bmp->x_ofs), itofix(y2+bmp->y_ofs));
2464 );
2465 }
2466
2467
2468
2469 /* vbeaf_rectfill:
2470 * Accelerated rectangle filling routine.
2471 */
vbeaf_rectfill(BITMAP * bmp,int x1,int y1,int x2,int y2,int color)2472 static void vbeaf_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color)
2473 {
2474 if (x2 < x1) {
2475 int tmp = x1;
2476 x1 = x2;
2477 x2 = tmp;
2478 }
2479
2480 if (y2 < y1) {
2481 int tmp = y1;
2482 y1 = y2;
2483 y2 = tmp;
2484 }
2485
2486 if (bmp->clip) {
2487 if (x1 < bmp->cl)
2488 x1 = bmp->cl;
2489
2490 if (x2 >= bmp->cr)
2491 x2 = bmp->cr-1;
2492
2493 if (x2 < x1)
2494 return;
2495
2496 if (y1 < bmp->ct)
2497 y1 = bmp->ct;
2498
2499 if (y2 >= bmp->cb)
2500 y2 = bmp->cb-1;
2501
2502 if (y2 < y1)
2503 return;
2504 }
2505
2506 SAFISH_CALL(
2507 go_accel();
2508
2509 switch (_drawing_mode) {
2510
2511 case DRAW_MODE_SOLID:
2512 case DRAW_MODE_XOR:
2513 /* mono rectangle fill */
2514 af_driver->DrawRect(af_driver, color,
2515 x1+bmp->x_ofs, y1+bmp->y_ofs,
2516 x2-x1+1, y2-y1+1);
2517 break;
2518
2519 case DRAW_MODE_COPY_PATTERN:
2520 /* colored pattern rectangle fill */
2521 prepare_color_pattern(bmp);
2522
2523 af_driver->DrawColorPattRect(af_driver,
2524 x1+bmp->x_ofs, y1+bmp->y_ofs,
2525 x2-x1+1, y2-y1+1);
2526 break;
2527
2528 case DRAW_MODE_SOLID_PATTERN:
2529 case DRAW_MODE_MASKED_PATTERN:
2530 /* mono pattern rectangle fill */
2531 prepare_mono_pattern(bmp);
2532
2533 af_driver->DrawPattRect(af_driver, color, 0,
2534 x1+bmp->x_ofs, y1+bmp->y_ofs,
2535 x2-x1+1, y2-y1+1);
2536 break;
2537 }
2538 );
2539 }
2540
2541
2542
2543 /* vbeaf_triangle:
2544 * Hardware accelerated triangle drawing function.
2545 */
vbeaf_triangle(BITMAP * bmp,int x1,int y1,int x2,int y2,int x3,int y3,int color)2546 static void vbeaf_triangle(BITMAP *bmp, int x1, int y1, int x2, int y2, int x3, int y3, int color)
2547 {
2548 AF_TRAP trap;
2549
2550 /* bounding box test */
2551 if (bmp->clip) {
2552 if ((x1 < bmp->cl) || (x2 < bmp->cl) || (x3 < bmp->cl)) {
2553 _soft_triangle(bmp, x1, y1, x2, y2, x3, y3, color);
2554 return;
2555 }
2556
2557 if ((y1 < bmp->ct) || (y2 < bmp->ct) || (y3 < bmp->ct)) {
2558 _soft_triangle(bmp, x1, y1, x2, y2, x3, y3, color);
2559 return;
2560 }
2561
2562 if ((x1 >= bmp->cr) || (x2 >= bmp->cr) || (x3 >= bmp->cr)) {
2563 _soft_triangle(bmp, x1, y1, x2, y2, x3, y3, color);
2564 return;
2565 }
2566
2567 if ((y1 >= bmp->cb) || (y2 >= bmp->cb) || (y3 >= bmp->cb)) {
2568 _soft_triangle(bmp, x1, y1, x2, y2, x3, y3, color);
2569 return;
2570 }
2571 }
2572
2573 /* sort along the vertical axis */
2574 #define TRI_SWAP(a, b) \
2575 { \
2576 int tmp = x##a; \
2577 x##a = x##b; \
2578 x##b = tmp; \
2579 \
2580 tmp = y##a; \
2581 y##a = y##b; \
2582 y##b = tmp; \
2583 }
2584
2585 if (y2 < y1)
2586 TRI_SWAP(1, 2);
2587
2588 if (y3 < y1) {
2589 TRI_SWAP(1, 3);
2590 TRI_SWAP(2, 3);
2591 }
2592 else if (y3 < y2)
2593 TRI_SWAP(2, 3);
2594
2595 SAFISH_CALL(
2596 go_accel();
2597
2598 if (y2 > y1) {
2599 /* draw the top half of the triangle as one trapezoid */
2600 trap.y = y1+bmp->y_ofs;
2601 trap.count = y2-y1;
2602 trap.x1 = trap.x2 = itofix(x1+bmp->x_ofs);
2603 trap.slope1 = itofix(x2-x1) / (y2-y1);
2604 trap.slope2 = itofix(x3-x1) / (y3-y1);
2605
2606 if (trap.slope1 < 0)
2607 trap.x1 += MIN(trap.slope1+itofix(1), 0);
2608
2609 if (trap.slope2 < 0)
2610 trap.x2 += MIN(trap.slope2+itofix(1), 0);
2611
2612 if (trap.slope1 > trap.slope2)
2613 trap.x1 += MAX(ABS(trap.slope1), itofix(1));
2614 else
2615 trap.x2 += MAX(ABS(trap.slope2), itofix(1));
2616
2617 af_driver->DrawTrap(af_driver, color, &trap);
2618
2619 if (y3 > y2) {
2620 /* draw the bottom half as a second trapezoid */
2621 if (trap.slope1 < 0)
2622 trap.x1 -= MIN(trap.slope1+itofix(1), 0);
2623
2624 if (trap.slope1 > trap.slope2)
2625 trap.x1 -= MAX(ABS(trap.slope1), itofix(1));
2626
2627 trap.count = y3-y2;
2628 trap.slope1 = itofix(x3-x2) / (y3-y2);
2629
2630 if (trap.slope1 < 0)
2631 trap.x1 += MIN(trap.slope1+itofix(1), 0);
2632
2633 if (trap.x1 > trap.x2)
2634 trap.x1 += MAX(ABS(trap.slope1), itofix(1));
2635
2636 af_driver->DrawTrap(af_driver, color, &trap);
2637 }
2638 }
2639 else if (y3 > y2) {
2640 /* we can draw the entire thing with a single trapezoid */
2641 trap.y = y1+bmp->y_ofs;
2642 trap.count = y3-y2;
2643 trap.x1 = itofix(x2+bmp->x_ofs);
2644 trap.x2 = itofix(x1+bmp->x_ofs);
2645 trap.slope1 = itofix(x3-x2) / (y3-y2);
2646 trap.slope2 = (y3 > y1) ? (itofix(x3-x1) / (y3-y1)) : 0;
2647
2648 if (trap.slope1 < 0)
2649 trap.x1 += MIN(trap.slope1+itofix(1), 0);
2650
2651 if (trap.slope2 < 0)
2652 trap.x2 += MIN(trap.slope2+itofix(1), 0);
2653
2654 if (trap.x1 > trap.x2)
2655 trap.x1 += MAX(ABS(trap.slope1), itofix(1));
2656 else
2657 trap.x2 += MAX(ABS(trap.slope2), itofix(1));
2658
2659 af_driver->DrawTrap(af_driver, color, &trap);
2660 }
2661 );
2662 }
2663
2664
2665
2666 /* vbeaf_draw_glyph:
2667 * Monochrome text plotter.
2668 */
vbeaf_draw_glyph(BITMAP * bmp,AL_CONST FONT_GLYPH * glyph,int x,int y,int color,int bg)2669 static void vbeaf_draw_glyph(BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)
2670 {
2671 AL_CONST unsigned char *data = glyph->dat;
2672 int w = glyph->w;
2673 int h = glyph->h;
2674 int stride = (w+7)/8;
2675 int d;
2676
2677 /* give up if we can't draw this */
2678 if ((x < bmp->cl) || (x+w >= bmp->cr) || ((w&7) && (bg >= 0))) {
2679 orig_draw_glyph(bmp, glyph, x, y, color, bg);
2680 return;
2681 }
2682
2683 /* clip the top */
2684 if (y < bmp->ct) {
2685 d = bmp->ct - y;
2686
2687 h -= d;
2688 if (h <= 0)
2689 return;
2690
2691 data += d*stride;
2692 y = bmp->ct;
2693 }
2694
2695 /* clip the bottom */
2696 if (y+h >= bmp->cb) {
2697 h = bmp->cb - y;
2698 if (h <= 0)
2699 return;
2700 }
2701
2702 SAFE_CALL(
2703 /* set the mix mode */
2704 if (bg >= 0) {
2705 af_driver->SetMix(af_driver, 0, 0);
2706 d = bg;
2707 }
2708 else {
2709 af_driver->SetMix(af_driver, 0, 4);
2710 d = 0;
2711 }
2712
2713 /* draw the letter */
2714 go_accel();
2715
2716 af_driver->PutMonoImage(af_driver, color, d,
2717 x+bmp->x_ofs, y+bmp->y_ofs,
2718 stride, 0, 0, stride*8, h, (unsigned char *)data);
2719
2720 af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix);
2721 );
2722 }
2723
2724
2725
2726 /* vbeaf_draw_sprite:
2727 * Accelerated sprite drawing routine.
2728 */
vbeaf_draw_sprite(BITMAP * bmp,BITMAP * sprite,int x,int y)2729 static void vbeaf_draw_sprite(BITMAP *bmp, BITMAP *sprite, int x, int y)
2730 {
2731 int sx, sy, w, h;
2732 int pitch;
2733
2734 if (((sprite->vtable == &_screen_vtable) && (af_driver->SrcTransBlt)) ||
2735 ((sprite->vtable != &_screen_vtable) && (af_driver->SrcTransBltSys))) {
2736
2737 /* this sprite can be drawn in hardware */
2738 sx = sprite->x_ofs;
2739 sy = sprite->y_ofs;
2740 w = sprite->w;
2741 h = sprite->h;
2742
2743 if (bmp->clip) {
2744 if (x < bmp->cl) {
2745 sx += bmp->cl-x;
2746 w -= bmp->cl-x;
2747 x = bmp->cl;
2748 }
2749
2750 if (y < bmp->ct) {
2751 sy += bmp->ct-y;
2752 h -= bmp->ct-y;
2753 y = bmp->ct;
2754 }
2755
2756 if (x+w > bmp->cr)
2757 w = bmp->cr-x;
2758
2759 if (w <= 0)
2760 return;
2761
2762 if (y+h > bmp->cb)
2763 h = bmp->cb-y;
2764
2765 if (h <= 0)
2766 return;
2767 }
2768
2769 if (sprite->vtable == &_screen_vtable) {
2770 /* hardware blit within the video memory */
2771 SAFISH_CALL(
2772 go_accel();
2773
2774 af_driver->SrcTransBlt(af_driver, sx, sy, w, h,
2775 x+bmp->x_ofs, y+bmp->y_ofs,
2776 0, sprite->vtable->mask_color);
2777 );
2778 }
2779 else {
2780 /* hardware blit from system memory */
2781 if (sprite->h > 1)
2782 pitch = (long)sprite->line[1] - (long)sprite->line[0];
2783 else
2784 pitch = sprite->w;
2785
2786 SAFE_CALL(
2787 go_accel();
2788
2789 af_driver->SrcTransBltSys(af_driver,
2790 sprite->line[0], pitch,
2791 sx, sy, w, h,
2792 x+bmp->x_ofs, y+bmp->y_ofs,
2793 0, sprite->vtable->mask_color);
2794 );
2795 }
2796 }
2797 else {
2798 /* have to use the original software version */
2799 orig_draw_sprite(bmp, sprite, x, y);
2800 }
2801 }
2802
2803 END_OF_STATIC_FUNCTION(vbeaf_draw_sprite);
2804
2805
2806
2807 /* vbeaf_blit_from_memory:
2808 * Accelerated system memory -> vram blitting routine.
2809 */
vbeaf_blit_from_memory(BITMAP * source,BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)2810 static void vbeaf_blit_from_memory(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
2811 {
2812 int pitch;
2813
2814 if (source->h > 1)
2815 pitch = (long)source->line[1] - (long)source->line[0];
2816 else
2817 pitch = source->w;
2818
2819 SAFE_CALL(
2820 go_accel();
2821
2822 af_driver->BitBltSys(af_driver,
2823 source->line[0], pitch,
2824 source_x, source_y,
2825 width, height,
2826 dest_x+dest->x_ofs,
2827 dest_y+dest->y_ofs,
2828 0);
2829 );
2830 }
2831
2832 END_OF_STATIC_FUNCTION(vbeaf_blit_from_memory);
2833
2834
2835
2836 /* vbeaf_blit_to_self:
2837 * Accelerated vram -> vram blitting routine.
2838 */
vbeaf_blit_to_self(BITMAP * source,BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)2839 static void vbeaf_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
2840 {
2841 SAFISH_CALL(
2842 go_accel();
2843
2844 af_driver->BitBlt(af_driver,
2845 source_x+source->x_ofs,
2846 source_y+source->y_ofs,
2847 width, height,
2848 dest_x+dest->x_ofs,
2849 dest_y+dest->y_ofs,
2850 0);
2851 );
2852 }
2853
2854
2855
2856 /* vbeaf_masked_blit:
2857 * Accelerated masked blitting routine.
2858 */
vbeaf_masked_blit(BITMAP * source,BITMAP * dest,int source_x,int source_y,int dest_x,int dest_y,int width,int height)2859 static void vbeaf_masked_blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)
2860 {
2861 int pitch;
2862
2863 if ((source->vtable == &_screen_vtable) && (af_driver->SrcTransBlt)) {
2864 /* hardware blit within the video memory */
2865 SAFISH_CALL(
2866 go_accel();
2867
2868 af_driver->SrcTransBlt(af_driver,
2869 source_x+source->x_ofs,
2870 source_y+source->y_ofs,
2871 width, height,
2872 dest_x+dest->x_ofs,
2873 dest_y+dest->y_ofs,
2874 0, source->vtable->mask_color);
2875 );
2876 }
2877 else if (af_driver->SrcTransBltSys) {
2878 /* hardware blit from system memory */
2879 if (source->h > 1)
2880 pitch = (long)source->line[1] - (long)source->line[0];
2881 else
2882 pitch = source->w;
2883
2884 SAFE_CALL(
2885 go_accel();
2886
2887 af_driver->SrcTransBltSys(af_driver,
2888 source->line[0], pitch,
2889 source_x, source_y,
2890 width, height,
2891 dest_x+dest->x_ofs,
2892 dest_y+dest->y_ofs,
2893 0, source->vtable->mask_color);
2894 );
2895 }
2896 else {
2897 /* have to use the original software version */
2898 orig_masked_blit(source, dest, source_x, source_y, dest_x, dest_y, width, height);
2899 }
2900 }
2901
2902
2903
2904 /* vbeaf_clear_to_color:
2905 * Accelerated screen clear routine.
2906 */
vbeaf_clear_to_color(BITMAP * bitmap,int color)2907 static void vbeaf_clear_to_color(BITMAP *bitmap, int color)
2908 {
2909 SAFISH_CALL(
2910 go_accel();
2911
2912 if ((vbeaf_fg_mix != 0) || (vbeaf_bg_mix != 0))
2913 af_driver->SetMix(af_driver, 0, 0);
2914
2915 af_driver->DrawRect(af_driver, color,
2916 bitmap->cl+bitmap->x_ofs,
2917 bitmap->ct+bitmap->y_ofs,
2918 bitmap->cr-bitmap->cl,
2919 bitmap->cb-bitmap->ct);
2920
2921 if ((vbeaf_fg_mix != 0) || (vbeaf_bg_mix != 0))
2922 af_driver->SetMix(af_driver, vbeaf_fg_mix, vbeaf_bg_mix);
2923 );
2924 }
2925
2926
2927
2928 #endif /* ifdef VBE/AF is cool on this platform */
2929