1 // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
2 // Ken Silverman's official web site: "http://www.advsys.net/ken"
3 // See the included license file "BUILDLIC.TXT" for license info.
4 // This file has been modified from Ken Silverman's original release
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <conio.h>
10 #include <dos.h>
11
12 #pragma pack(push,1);
13
14 typedef struct
15 {
16 char VESASignature[4];
17 short VESAVersion;
18 long OemStringPtr, Capabilities, VideoModePtr;
19 short TotalMemory, OemSoftwareRev;
20 long OemVendorNamePtr, OemProductNamePtr, OemProductRevPtr;
21 char reserved[222], OemDATA[256];
22 } VBE_vgaInfo;
23
24 typedef struct
25 {
26 short ModeAttributes;
27 char WinAAtributes, WinBAttributes;
28 short WinGranularity, WinSize, WinASegment, WinBSegment;
29 long WinFuncPtr;
30 short BytesPerScanLine, XResolution, YResolution;
31 char XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel;
32 char NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages;
33 char res1;
34 char RedMaskSize, RedFieldPosition;
35 char GreenMaskSize, GreenFieldPosition;
36 char BlueMaskSize, BlueFieldPosition;
37 char RsvdMaskSize, RsvdFieldPosition, DirectColorModeInfo;
38 long PhysBasePtr, OffScreenMemOffset;
39 short OffScreenMemSize;
40 char res2[206];
41 } VBE_modeInfo;
42
43 struct _RMWORDREGS { unsigned short ax, bx, cx, dx, si, di, cflag; };
44 struct _RMBYTEREGS { unsigned char al, ah, bl, bh, cl, ch, dl, dh; };
45 typedef union { struct _RMWORDREGS x; struct _RMBYTEREGS h; } RMREGS;
46 typedef struct { unsigned short es, cs, ss, ds; } RMSREGS;
47
48 typedef struct
49 {
50 long edi, esi, ebp, reserved, ebx, edx, ecx, eax;
51 short flags, es, ds, fs, gs, ip, cs, sp, ss;
52 } _RMREGS;
53
54 #pragma pack(pop);
55
56 long VESABuf_len = 1024, VESABuf_sel = 0, VESABuf_rseg;
57 short modelist[256];
58 static char *screen = NULL, vesachecked = 0;
59 long xres, yres, bytesperline, frameplace, imageSize, maxpages;
60 long buffermode, origbuffermode, linearmode;
61 long setactiveentry = 0, setvisualentry = 0, setpaletteentry = 0;
62 char permanentupdate = 0, vgacompatible;
63 short visualpagelookup[64][2];
64 long activepagelookup[64];
65 static long ves2lastx[MAXYDIM];
66 static long davesapageshift;
67 static VBE_vgaInfo vgaInfo;
68 long globlinplace;
69
70 #pragma aux qlimitrate =\
71 "mov dx, 0x3da",\
72 "wait1: in al, dx",\
73 "test al, 1",\
74 "jnz wait1",\
75 modify exact [eax edx]\
76
77 short ods, oes, oss;
78 #pragma aux backupsegs =\
79 "mov ods, ds",\
80 "mov oes, es",\
81 "mov oss, ss",\
82 modify [eax]\
83
84 #pragma aux restoresegs =\
85 "mov ds, ods",\
86 "mov es, oes",\
87 "mov ss, oss",\
88 modify [eax]\
89
90 #pragma aux setvmode =\
91 "int 0x10",\
92 parm [eax]\
93
94 #pragma aux copybufbyte =\
95 "cmp ecx, 4",\
96 "jae longcopy",\
97 "test cl, 1",\
98 "jz preskip",\
99 "movsb",\
100 "preskip: shr ecx, 1",\
101 "rep movsw",\
102 "jmp endit",\
103 "longcopy: test edi, 1",\
104 "jz skip1",\
105 "movsb",\
106 "dec ecx",\
107 "skip1: test edi, 2",\
108 "jz skip2",\
109 "movsw",\
110 "sub ecx, 2",\
111 "skip2: mov ebx, ecx",\
112 "shr ecx, 2",\
113 "rep movsd",\
114 "test bl, 2",\
115 "jz skip3",\
116 "movsw",\
117 "skip3: test bl, 1",\
118 "jz endit",\
119 "movsb",\
120 "endit:",\
121 parm [esi][edi][ecx]\
122 modify [ebx]\
123
124 /* //64-bit copybufbyte
125 #pragma aux copybufbyte =\
126 "cmp ecx, 8",\
127 "jae longcopy",\
128 "test cl, 1",\
129 "jz shortskip1",\
130 "movsb",\
131 "shortskip1: shr ecx, 2",\
132 "jnc shortskip2",\
133 "movsw",\
134 "shortskip2: rep movsd",\
135 "jmp endit",\
136 "longcopy: test edi, 1",\
137 "jz skip1",\
138 "movsb",\
139 "dec ecx",\
140 "skip1: test edi, 2",\
141 "jz skip2",\
142 "movsw",\
143 "sub ecx, 2",\
144 "skip2: test edi, 4",\
145 "jz skip3",\
146 "movsd",\
147 "sub ecx, 4",\
148 "skip3: mov ebx, ecx",\
149 "shr ecx, 3",\
150 "jz skip4",\
151 "begloop: fld qword ptr [esi]",\
152 "fstp qword ptr [edi]",\
153 "add esi, 8",\
154 "add edi, 8",\
155 "dec ecx",\
156 "jnz begloop",\
157 "skip4: test bl, 4",\
158 "jz skip5",\
159 "movsd",\
160 "skip5: test bl, 2",\
161 "jz skip6",\
162 "movsw",\
163 "skip6: test bl, 1",\
164 "jz endit",\
165 "movsb",\
166 "endit:",\
167 parm [esi][edi][ecx]\
168 modify [ebx]\
169 */
170
171 #pragma aux vesasetactive =\
172 "call dword ptr [setactiveentry]",\
173 parm [eax][ebx][ecx][edx]\
174
175 #pragma aux vesasetvisual =\
176 "call dword ptr [setvisualentry]",\
177 parm [eax][ebx][ecx][edx]\
178
179 #pragma aux vesasetpalette =\
180 "call dword ptr [setpaletteentry]",\
181 parm [eax][ebx][ecx][edx][esi][edi]\
182
DPMI_int86(long intno,RMREGS * in,RMREGS * out)183 long DPMI_int86(long intno, RMREGS *in, RMREGS *out)
184 {
185 _RMREGS rmregs;
186 union REGS r;
187 struct SREGS sr;
188
189 memset(&rmregs,0,sizeof(rmregs));
190 rmregs.eax = in->x.ax; rmregs.ebx = in->x.bx;
191 rmregs.ecx = in->x.cx; rmregs.edx = in->x.dx;
192 rmregs.esi = in->x.si; rmregs.edi = in->x.di;
193
194 segread(&sr);
195 r.w.ax = 0x300; r.h.bl = intno; r.h.bh = 0; r.w.cx = 0; sr.es = sr.ds;
196 r.x.edi = (unsigned)&rmregs;
197 backupsegs(); int386x(0x31,&r,&r,&sr); restoresegs();
198
199 out->x.ax = rmregs.eax; out->x.bx = rmregs.ebx;
200 out->x.cx = rmregs.ecx; out->x.dx = rmregs.edx;
201 out->x.si = rmregs.esi; out->x.di = rmregs.edi;
202 out->x.cflag = rmregs.flags&1;
203 return(out->x.ax);
204 }
205
DPMI_int86x(long intno,RMREGS * in,RMREGS * out,RMSREGS * sregs)206 long DPMI_int86x(long intno, RMREGS *in, RMREGS *out, RMSREGS *sregs)
207 {
208 _RMREGS rmregs;
209 union REGS r;
210 struct SREGS sr;
211
212 memset(&rmregs, 0, sizeof(rmregs));
213 rmregs.eax = in->x.ax; rmregs.ebx = in->x.bx;
214 rmregs.ecx = in->x.cx; rmregs.edx = in->x.dx;
215 rmregs.esi = in->x.si; rmregs.edi = in->x.di;
216 rmregs.es = sregs->es;
217 rmregs.ds = sregs->ds;
218
219 segread(&sr);
220 r.w.ax = 0x300; r.h.bl = intno; r.h.bh = 0; r.w.cx = 0; sr.es = sr.ds;
221 r.x.edi = (unsigned)&rmregs;
222 backupsegs(); int386x(0x31,&r,&r,&sr); restoresegs();
223
224 out->x.ax = rmregs.eax; out->x.bx = rmregs.ebx;
225 out->x.cx = rmregs.ecx; out->x.dx = rmregs.edx;
226 out->x.si = rmregs.esi; out->x.di = rmregs.edi;
227 sregs->es = rmregs.es; sregs->cs = rmregs.cs;
228 sregs->ss = rmregs.ss; sregs->ds = rmregs.ds;
229 out->x.cflag = rmregs.flags&1;
230 return(out->x.ax);
231 }
232
ExitVBEBuf(void)233 static void ExitVBEBuf(void)
234 {
235 union REGS r;
236 r.w.ax = 0x101; r.w.dx = VESABuf_sel; //DPMI free real seg
237 backupsegs(); int386(0x31,&r,&r); restoresegs();
238 }
239
VBE_callESDI(RMREGS * regs,void * buffer,long size)240 void VBE_callESDI(RMREGS *regs, void *buffer, long size)
241 {
242 RMSREGS sregs;
243 union REGS r;
244
245 if (!VESABuf_sel) //Init Real mode buffer
246 {
247 r.w.ax = 0x100; r.w.bx = (VESABuf_len+15)>>4;
248 backupsegs(); int386(0x31,&r,&r); restoresegs();
249 if (r.w.cflag) { printf("DPMI_allocRealSeg failed!\n"); exit(0); }
250 VESABuf_sel = r.w.dx;
251 VESABuf_rseg = r.w.ax;
252 atexit(ExitVBEBuf);
253 }
254 sregs.es = VESABuf_rseg;
255 regs->x.di = 0;
256 _fmemcpy(MK_FP(VESABuf_sel,0),buffer,size);
257 DPMI_int86x(0x10,regs,regs,&sregs);
258 _fmemcpy(buffer,MK_FP(VESABuf_sel,0),size);
259 }
260
VBE_getModeInfo(long mode,VBE_modeInfo * modeInfo)261 long VBE_getModeInfo(long mode, VBE_modeInfo *modeInfo)
262 {
263 RMREGS regs;
264
265 regs.x.ax = 0x4f01;
266 regs.x.cx = mode;
267 VBE_callESDI(®s, modeInfo, sizeof(VBE_modeInfo));
268 if (regs.x.ax != 0x004f) return(0);
269 if ((modeInfo->ModeAttributes&1) == 0) return(0); //1 is vbeMdAvailable
270 return(1);
271 }
272
GetPtrToLFB(long physAddr)273 GetPtrToLFB(long physAddr)
274 {
275 #define LIMIT (4096*1024)-1
276 long sel;
277 union REGS r;
278
279 r.w.ax = 0; r.w.cx = 1;
280 backupsegs(); int386(0x31,&r,&r); restoresegs();
281 if (r.x.cflag) { printf("DPMI_allocSelector() failed!\n"); exit(0); }
282 sel = r.w.ax;
283 r.w.ax = 9; r.w.bx = sel; r.w.cx = 0x8092;
284 backupsegs(); int386(0x31,&r,&r); restoresegs();
285
286 r.w.ax = 0x800; r.w.bx = physAddr >> 16; r.w.cx = physAddr & 0xffff;
287 r.w.si = LIMIT>>16; r.w.di = LIMIT&0xffff;
288 backupsegs(); int386(0x31,&r,&r); restoresegs();
289 if (r.x.cflag) { printf("DPMI_mapPhysicalToLinear() failed!\n"); exit(0); }
290 globlinplace = ((long)r.w.bx<<16)+r.w.cx;
291
292 r.w.ax = 7; r.w.bx = sel;
293 r.w.cx = globlinplace>>16; r.w.dx = globlinplace&0xffff;
294 backupsegs(); int386(0x31,&r,&r); restoresegs();
295 if (r.x.cflag) { printf("DPMI_setSelectorBase() failed!\n"); exit(0); }
296
297 r.w.ax = 8; r.w.bx = sel;
298 r.w.cx = LIMIT>>16; r.w.dx = LIMIT&0xffff;
299 backupsegs(); int386(0x31,&r,&r); restoresegs();
300 if (r.x.cflag) { printf("DPMI_setSelectorLimit() failed!\n"); exit(0); }
301 }
302
getvalidvesamodes()303 getvalidvesamodes()
304 {
305 long i, j, k;
306 short *p, *p2;
307 VBE_modeInfo modeInfo;
308 RMREGS regs;
309
310 if (vesachecked) return;
311 vesachecked = 1;
312
313 validmodecnt = 0;
314 modelist[0] = -1;
315
316 strncpy(vgaInfo.VESASignature,"VBE2",4);
317 regs.x.ax = 0x4f00;
318 VBE_callESDI(®s,&vgaInfo,sizeof(VBE_vgaInfo));
319 if ((regs.x.ax != 0x004f) || (strncmp(vgaInfo.VESASignature,"VESA",4)))
320 return;
321
322 //if (vgaInfo.VESAVersion < 0x200) return;
323
324 //LfbMapRealPointer
325 p = (short *)(((vgaInfo.VideoModePtr&0xffff0000)>>12)+((vgaInfo.VideoModePtr)&0xffff));
326 p2 = modelist;
327 while (*p != -1) *p2++ = *p++;
328 *p2 = -1;
329
330 for(p=modelist;*p!=-1;p++)
331 {
332 regs.x.ax = 0x4f01; regs.x.cx = *p;
333 VBE_callESDI(®s,&modeInfo,sizeof(VBE_modeInfo));
334 if (regs.x.ax != 0x004f) continue;
335 if (!(modeInfo.ModeAttributes&1)) continue; //1 is vbeMdAvailable
336 if (modeInfo.MemoryModel != 4) continue; //4 is vbeMemPK
337 if (modeInfo.BitsPerPixel != 8) continue;
338 if (modeInfo.NumberOfPlanes != 1) continue;
339
340 validmode[validmodecnt] = *p;
341 validmodexdim[validmodecnt] = modeInfo.XResolution;
342 validmodeydim[validmodecnt] = modeInfo.YResolution;
343 validmodecnt++;
344 }
345
346 for(i=1;i<validmodecnt;i++)
347 for(j=0;j<i;j++)
348 if (validmodeydim[i] < validmodeydim[j])
349 {
350 k = validmode[i]; validmode[i] = validmode[j]; validmode[j] = k;
351 k = validmodexdim[i]; validmodexdim[i] = validmodexdim[j]; validmodexdim[j] = k;
352 k = validmodeydim[i]; validmodeydim[i] = validmodeydim[j]; validmodeydim[j] = k;
353 }
354
355 for(i=1;i<validmodecnt;i++)
356 for(j=0;j<i;j++)
357 if (validmodexdim[i] < validmodexdim[j])
358 {
359 k = validmode[i]; validmode[i] = validmode[j]; validmode[j] = k;
360 k = validmodexdim[i]; validmodexdim[i] = validmodexdim[j]; validmodexdim[j] = k;
361 k = validmodeydim[i]; validmodeydim[i] = validmodeydim[j]; validmodeydim[j] = k;
362 }
363 }
364
setvesa(long x,long y)365 setvesa(long x, long y)
366 {
367 div_t dived;
368 long i, j, k;
369 short *p, *p1, *p2;
370 VBE_modeInfo modeInfo;
371 RMREGS regs;
372 RMSREGS sregs;
373
374 getvalidvesamodes();
375
376 xres = x; yres = y;
377 for(k=0;k<validmodecnt;k++)
378 {
379 regs.x.ax = 0x4f01; regs.x.cx = validmode[k];
380 VBE_callESDI(®s,&modeInfo,sizeof(VBE_modeInfo));
381 if (regs.x.ax != 0x004f) continue;
382 if (!(modeInfo.ModeAttributes&1)) continue; //1 is vbeMdAvailable
383
384 if (modeInfo.MemoryModel != 4) continue; //4 is vbeMemPK
385 if (modeInfo.BitsPerPixel != 8) continue;
386 if (modeInfo.NumberOfPlanes != 1) continue;
387 if (modeInfo.XResolution != x) continue;
388 if (modeInfo.YResolution != y) continue;
389
390 bytesperline = modeInfo.BytesPerScanLine;
391 maxpages = min(modeInfo.NumberOfImagePages+1,64);
392
393 regs.x.ax = 0x4f02;
394 regs.x.bx = validmode[k] | ((modeInfo.ModeAttributes&128)<<7);
395 DPMI_int86(0x10,®s,®s);
396
397 if (modeInfo.ModeAttributes&32) vgacompatible = 0;
398 else vgacompatible = 1;
399
400 regs.x.ax = 0x4f0a; regs.x.bx = 0;
401 DPMI_int86x(0x10,®s,®s,&sregs);
402 if (regs.x.ax == 0x004f) //cx is length of protected mode code
403 {
404 i = (((long)sregs.es)<<4)+((long)regs.x.di);
405 p1 = (short *)i;
406 setactiveentry = ((long)p1[0]) + i;
407 setvisualentry = ((long)p1[1]) + i;
408 setpaletteentry = ((long)p1[2]) + i;
409 //p1[2] is useless palette function - see vesprot.asm for code
410 }
411
412 //Linear mode
413 if (modeInfo.ModeAttributes&128) //128 is vbeMdLinear
414 {
415 GetPtrToLFB(modeInfo.PhysBasePtr);
416
417 linearmode = 1;
418 buffermode = (maxpages<=1);
419 imageSize = bytesperline*yres;
420 frameplace = globlinplace;
421 j = 0;
422 for(i=0;i<maxpages;i++)
423 {
424 activepagelookup[i] = globlinplace+j;
425 j += imageSize;
426 }
427 }
428 else //Banked mode
429 {
430 //Get granularity
431 switch(modeInfo.WinGranularity)
432 {
433 case 64: davesapageshift = 0; break;
434 case 32: davesapageshift = 1; break;
435 case 16: davesapageshift = 2; break;
436 case 8: davesapageshift = 3; break;
437 case 4: davesapageshift = 4; break;
438 case 2: davesapageshift = 5; break;
439 case 1: davesapageshift = 6; break;
440 }
441
442 linearmode = 0;
443 if ((x == 320) && (y == 200) && (maxpages >= 2))
444 {
445 buffermode = 0;
446 imageSize = 65536;
447 frameplace = 0xa0000;
448 }
449 else
450 {
451 buffermode = 1;
452 imageSize = bytesperline*yres;
453 frameplace = FP_OFF(screen);
454 maxpages = 1;
455 }
456 }
457
458 origbuffermode = buffermode;
459
460 j = 0;
461 for(i=0;i<maxpages;i++)
462 {
463 dived = div(j,bytesperline);
464 visualpagelookup[i][0] = (short)dived.rem;
465 visualpagelookup[i][1] = (short)dived.quot;
466 j += imageSize;
467 }
468 return(0);
469 }
470 return(-1);
471 }
472
setdacbits(long newdacbits)473 setdacbits(long newdacbits)
474 {
475 RMREGS regs;
476
477 if ((vgaInfo.Capabilities&1) == 0) return(6L);
478 regs.x.ax = 0x4f08;
479 regs.x.bx = (((long)newdacbits)<<8);
480 DPMI_int86(0x10,®s,®s);
481 return((long)regs.h.bh);
482 }
483
484 #define setvesapage(i) \
485 { \
486 if (setactiveentry) \
487 vesasetactive(0x4f05,0L,0L,i); \
488 else \
489 { \
490 regs.x.ax = 0x4f05; regs.x.bx = 0; regs.x.dx = i; \
491 DPMI_int86(0x10,®s,®s); \
492 } \
493 }
494
setactivepage(long dapagenum)495 void setactivepage(long dapagenum)
496 {
497 RMREGS regs;
498
499 if ((origbuffermode == 0) && (linearmode == 0))
500 {
501 frameplace = 0xa0000;
502 setvesapage(dapagenum<<davesapageshift);
503 }
504 if (buffermode != 0) { frameplace = FP_OFF(screen); return; }
505 if (linearmode != 0) { frameplace = activepagelookup[dapagenum]; return; }
506 }
507
508 static long curpag = 0;
setvisualpage(long dapagenum)509 void setvisualpage(long dapagenum)
510 {
511 RMREGS regs;
512 long i, j, p, dx, cx1, cy1, cx2, cy2, delta, x, y, y1, y2, ny1, ny2;
513
514 if (buffermode != 0)
515 {
516 cx1 = windowx1; cy1 = windowy1; cx2 = windowx2; cy2 = windowy2;
517 if (permanentupdate) { cx1 = 0; cy1 = 0; cx2 = xdim-1; cy2 = ydim-1; }
518 dx = cx2-cx1+1;
519 if (linearmode)
520 {
521 p = FP_OFF(screen);
522 delta = activepagelookup[dapagenum&0x7fffffff]-FP_OFF(screen);
523 if (permanentupdate == 0)
524 {
525 y1 = startumost[cx1]; y2 = y1;
526 for(x=cx1;x<=cx2;x++)
527 {
528 ny1 = startumost[x]-1; ny2 = startdmost[x];
529 if (ny1 < ny2-1)
530 {
531 if (ny1 >= y2)
532 {
533 while (y1 < y2-1)
534 {
535 y1++; if ((y1&31) == 0) faketimerhandler();
536 //x,y1
537 i = p+ylookup[y1]+ves2lastx[y1];
538 copybufbyte(i,i+delta,x-ves2lastx[y1]);
539 }
540 y1 = ny1;
541 }
542 else
543 {
544 while (y1 < ny1)
545 {
546 y1++; if ((y1&31) == 0) faketimerhandler();
547 //x-1,y1
548 i = p+ylookup[y1]+ves2lastx[y1];
549 copybufbyte(i,i+delta,x-ves2lastx[y1]);
550 }
551 while (y1 > ny1) ves2lastx[y1--] = x;
552 }
553 while (y2 > ny2)
554 {
555 y2--; if ((y2&31) == 0) faketimerhandler();
556 //x-1,y2
557 i = p+ylookup[y2]+ves2lastx[y2];
558 copybufbyte(i,i+delta,x-ves2lastx[y2]);
559 }
560 while (y2 < ny2) ves2lastx[y2++] = x;
561 }
562 else
563 {
564 while (y1 < y2-1)
565 {
566 y1++; if ((y1&31) == 0) faketimerhandler();
567 //x-1,y1
568 i = p+ylookup[y1]+ves2lastx[y1];
569 copybufbyte(i,i+delta,x-ves2lastx[y1]);
570 }
571 if (x == cx2) break;
572 y1 = startumost[x+1]; y2 = y1;
573 }
574 }
575 while (y1 < y2-1)
576 {
577 y1++; if ((y1&31) == 0) faketimerhandler();
578 //cx2+1,y1
579 i = p+ylookup[y1]+ves2lastx[y1];
580 copybufbyte(i,i+delta,cx2+1-ves2lastx[y1]);
581 }
582 }
583 else
584 {
585 p += ylookup[cy1]+cx1;
586 delta = activepagelookup[dapagenum&0x7fffffff]-FP_OFF(screen);
587 for(y=cy1;y<=cy2;y++)
588 {
589 copybufbyte(p,p+delta,dx);
590 p += ylookup[1];
591 if ((y&31) == 0) faketimerhandler();
592 }
593 }
594 }
595 else
596 {
597 p = ylookup[cy1]+cx1;
598 for(y=cy1;y<=cy2;y++)
599 {
600 if ((p>>16) != curpag)
601 {
602 curpag = (p>>16);
603
604 setvesapage(curpag<<davesapageshift);
605 faketimerhandler();
606 }
607
608 i = (p&65535)+dx-65536;
609 if (i <= 0)
610 copybufbyte(p+FP_OFF(screen),(p&65535)+0xa0000,dx);
611 else
612 {
613 copybufbyte(p+FP_OFF(screen),0xb0000-(dx-i),dx-i);
614
615 curpag = ((p+dx-1)>>16);
616 setvesapage(curpag<<davesapageshift);
617 faketimerhandler();
618
619 copybufbyte(p+(dx-i)+FP_OFF(screen),0xa0000,i);
620 }
621 p += ylookup[1];
622 }
623 }
624 permanentupdate = 0;
625 }
626 if (origbuffermode == 0)
627 {
628 if (setvisualentry)
629 {
630 i = imageSize*(dapagenum&0x7fffffff);
631 if (vgacompatible)
632 {
633 if (dapagenum >= 0) qlimitrate();
634 vesasetvisual(0x4f07,0L,i>>2,i>>18);
635 }
636 else
637 { vesasetvisual(0x4f07,0x80,i>>2,i>>18); }
638
639 }
640 else
641 {
642 regs.x.ax = 0x4f07;
643 regs.x.cx = visualpagelookup[dapagenum&0x7fffffff][0]; //X-coordinate
644 regs.x.dx = visualpagelookup[dapagenum&0x7fffffff][1]; //Y-coordinate
645 if (vgacompatible)
646 {
647 regs.x.bx = 0;
648 if (dapagenum >= 0) qlimitrate();
649 DPMI_int86(0x10,®s,®s);
650 }
651 else
652 { regs.x.bx = 0x80; DPMI_int86(0x10,®s,®s); }
653 }
654 if (dapagenum >= 0) faketimerhandler();
655 }
656 }
657
uninitvesa()658 uninitvesa()
659 {
660 VESABuf_len = 1024;
661 VESABuf_sel = 0;
662 vesachecked = 0;
663 }
664
665 #pragma aux setpalettequick =\
666 "mov edx, 0x3c8",\
667 "out dx, al",\
668 "inc edx",\
669 "lea ecx, [ecx+ecx*2]",\
670 "cld",\
671 "rep outsb",\
672 parm [eax][ecx][esi]\
673 modify exact [ecx edx esi]\
674
VBE_setPalette(long start,long num,char * dapal)675 VBE_setPalette(long start, long num, char *dapal)
676 {
677 RMREGS regs;
678 long i, j, k;
679 char palquick[768];
680
681 if (stereomode == 1)
682 {
683 if ((unsigned)((blackband&255)-start) < (unsigned)num)
684 {
685 dapal[(((blackband&255)-start)<<2)+0] = 0;
686 dapal[(((blackband&255)-start)<<2)+1] = 0;
687 dapal[(((blackband&255)-start)<<2)+2] = 0;
688 }
689 if ((unsigned)((whiteband&255)-start) < (unsigned)num)
690 {
691 dapal[(((whiteband&255)-start)<<2)+0] = 255;
692 dapal[(((whiteband&255)-start)<<2)+1] = 255;
693 dapal[(((whiteband&255)-start)<<2)+2] = 255;
694 }
695 }
696 if ((vgacompatible) || (vgaInfo.VESAVersion < 0x200) || (vidoption != 1))
697 {
698 j = 0; k = (start<<2);
699 for(i=0;i<num;i++)
700 {
701 palquick[j] = dapal[k+2];
702 palquick[j+1] = dapal[k+1];
703 palquick[j+2] = dapal[k];
704 j += 3; k += 4;
705 }
706 //setpalettequick(start,num,palquick);
707 koutp(0x3c8,start);
708 for(i=(num>>1);i>0;i--)
709 {
710 koutp(0x3c9,dapal[2]);
711 while (kinp(0x3da)&1); while (!(kinp(0x3da)&1));
712 koutp(0x3c9,dapal[1]); koutp(0x3c9,dapal[0]);
713 koutp(0x3c9,dapal[6]); koutp(0x3c9,dapal[5]); koutp(0x3c9,dapal[4]);
714 dapal += 8;
715 }
716 if (num&1)
717 {
718 koutp(0x3c9,dapal[2]);
719 while (kinp(0x3da)&1); while (!(kinp(0x3da)&1));
720 koutp(0x3c9,dapal[1]); koutp(0x3c9,dapal[0]);
721 }
722 return(1);
723 }
724
725 if (setpaletteentry)
726 {
727 i = (vesasetpalette(0x4f09,(vgaInfo.Capabilities&4)<<5,
728 num,start,0L,dapal)&65535);
729 }
730 else
731 {
732 regs.x.ax = 0x4f09; regs.h.bl = ((vgaInfo.Capabilities&4)<<5);
733 regs.x.cx = num; regs.x.dx = start;
734 VBE_callESDI(®s,dapal,sizeof(dapal)*num);
735 i = regs.x.ax;
736 }
737 if (i != 0x004f) return(0);
738 return(1);
739 }
740
VBE_getPalette(long start,long num,char * dapal)741 VBE_getPalette(long start, long num, char *dapal)
742 {
743 RMREGS regs;
744 long i;
745
746 if ((vgacompatible) || (vgaInfo.VESAVersion < 0x200) || (vidoption != 1))
747 {
748 koutp(0x3c7,start);
749 for(i=num;i>0;i--)
750 {
751 dapal[2] = kinp(0x3c9);
752 dapal[1] = kinp(0x3c9);
753 dapal[0] = kinp(0x3c9);
754 dapal += 4;
755 }
756 return(1);
757 }
758
759 regs.x.ax = 0x4f09; regs.h.bl = 1;
760 regs.x.cx = num; regs.x.dx = start;
761 VBE_callESDI(®s,dapal,sizeof(dapal)*num);
762 i = regs.x.ax;
763 if (i != 0x004f) return(0);
764 return(1);
765 }
766