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(&regs, 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(&regs,&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(&regs,&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(&regs,&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,&regs,&regs);
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,&regs,&regs,&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,&regs,&regs);
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,&regs,&regs);                         \
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,&regs,&regs);
650 			}
651 			else
652 				{ regs.x.bx = 0x80; DPMI_int86(0x10,&regs,&regs); }
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 ((vgacompatible) || (vgaInfo.VESAVersion < 0x200) || (vidoption != 1))
682 	{
683 		j = 0; k = (start<<2);
684 		for(i=0;i<num;i++)
685 		{
686 			palquick[j] = dapal[k+2];
687 			palquick[j+1] = dapal[k+1];
688 			palquick[j+2] = dapal[k];
689 			j += 3; k += 4;
690 		}
691 		setpalettequick(start,num,palquick);
692 		return(1);
693 	}
694 
695 	if (setpaletteentry)
696 	{
697 		i = (vesasetpalette(0x4f09,(vgaInfo.Capabilities&4)<<5,
698 								  num,start,0L,dapal)&65535);
699 	}
700 	else
701 	{
702 		regs.x.ax = 0x4f09; regs.h.bl = ((vgaInfo.Capabilities&4)<<5);
703 		regs.x.cx = num; regs.x.dx = start;
704 		VBE_callESDI(&regs,dapal,sizeof(dapal)*num);
705 		i = regs.x.ax;
706 	}
707 	if (i != 0x004f) return(0);
708 	return(1);
709 }
710 
VBE_getPalette(long start,long num,char * dapal)711 VBE_getPalette(long start, long num, char *dapal)
712 {
713 	RMREGS regs;
714 	long i;
715 
716 	if ((vgacompatible) || (vgaInfo.VESAVersion < 0x200) || (vidoption != 1))
717 	{
718 		koutp(0x3c7,start);
719 		for(i=num;i>0;i--)
720 		{
721 			dapal[2] = kinp(0x3c9);
722 			dapal[1] = kinp(0x3c9);
723 			dapal[0] = kinp(0x3c9);
724 			dapal += 4;
725 		}
726 		return(1);
727 	}
728 
729 	regs.x.ax = 0x4f09; regs.h.bl = 1;
730 	regs.x.cx = num; regs.x.dx = start;
731 	VBE_callESDI(&regs,dapal,sizeof(dapal)*num);
732 	i = regs.x.ax;
733 	if (i != 0x004f) return(0);
734 	return(1);
735 }
736