|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * DOS VESA BIOS / VGA / Mode X graphics interface.
5: *
6: * (c) 1997 Gustavo Goedert
7: */
8:
9: #include "sysconfig.h"
10: #include "sysdeps.h"
11:
12: #include <stdlib.h>
13: #include <dos.h>
14: #include <go32.h>
15: #include <dpmi.h>
16: #include <sys/farptr.h>
17:
18: #include "vbe.h"
19:
20: #define ALIGN(x) ((((int)(x)>>12)<<12)+4096)
21: #define PACKED __attribute__ ((packed))
22:
23: /* externs in vbe.h */
24: int NumberOfModes = 0;
25: T_ModeInfo *ModeList = NULL;
26: T_ModeInfo CurrentMode;
27: int CanMapBuffer = 0;
28: int CurrentBankNumber = 0;
29: /* end from vbe.h */
30:
31: enum VBE_MemoryModels {
32: TextMode, CGA_Graphics, HerculesGraphics, Planar,
33: PackedPixel, ModeX, DirectColor, YUV
34: };
35:
36: typedef struct {
37: char VbeSignature[4] PACKED; // = VBE2
38: short VbeVersion PACKED;
39: char *OemStringPtr PACKED;
40: char Capabilities[4] PACKED;
41: unsigned int VideoModePtr PACKED;
42: short TotalMemory PACKED;
43: short OemSoftwareRev PACKED;
44: char *OemVendorNamePtr PACKED;
45: char *OemProductNamePtr PACKED;
46: char *OemProductRevPtr PACKED;
47: char Reserved[222] PACKED;
48: char OemData[256] PACKED;
49: } T_VBE_VbeInfoBlock;
50:
51: typedef struct {
52: // Mandatory information for all VBE revisions
53: short ModeAttributes PACKED;
54: char WinAAttributes PACKED;
55: char WinBAttributes PACKED;
56: short WinGranularity PACKED;
57: unsigned short WinSize PACKED;
58: unsigned short WinASegment PACKED;
59: unsigned short WinBSegment PACKED;
60: unsigned int WinFuncPtr PACKED;
61: short BytesPerScanLine PACKED;
62: // Mandatory information for VBE 1.2 and above
63: short XResolution PACKED;
64: short YResolution PACKED;
65: char XCharSize PACKED;
66: char YCharSize PACKED;
67: char NumberOfPlanes PACKED;
68: char BitsPerPixel PACKED;
69: char NumberOfBanks PACKED;
70: char MemoryModel PACKED;
71: char BankSize PACKED;
72: char NumberOfImagePages PACKED;
73: char ReservedA PACKED; // = 1
74: // Direct Color fields (required for direct/6 and YUV/7 memory models)
75: char RedMaskSize PACKED;
76: char RedFieldPosition PACKED;
77: char GreenMaskSize PACKED;
78: char GreenFieldPosition PACKED;
79: char BlueMaskSize PACKED;
80: char BlueFieldPosition PACKED;
81: char RsvdMaskSize PACKED;
82: char RsvdFieldPosition PACKED;
83: char DirectColorModeInfo PACKED;
84: // Mandatory information for VBE 2.0 and above
85: unsigned int PhysBasePtr PACKED;
86: unsigned int OffScreenMemOffset PACKED;
87: short OffScreenMemSize PACKED;
88: char ReservedB[206] PACKED;
89: } T_VBE_ModeInfoBlock;
90:
91: typedef struct {
92: short SetWindowOffset PACKED;
93: short SetDisplayStartOffset PACKED;
94: short SetPrimaryPaletteDataOffset PACKED;
95: short PortsMemoryOffset PACKED;
96: } T_VBE_ProtectedModeInterface;
97:
98: typedef enum {TVBE, TVGA, TModeX} T_ControlType;
99:
100: typedef struct {
101: T_ModeType ModeType;
102: int OriginalModeNumber;
103: int ModeWidth, ModeHeight;
104: int BitsPerPixel, BitsPerColor;
105: int RedSize, RedPosition;
106: int GreenSize, GreenPosition;
107: int BlueSize, BluePosition;
108: } T_VBE_Table;
109:
110: typedef struct {
111: T_ControlType ControlType;
112: int OriginalModeNumber;
113: int WriteWindow;
114: int FastWinCalc;
115: int GranularityFix;
116: unsigned int WinMask1, WinMask2;
117: unsigned int WinFuncPtrSegment, WinFuncPtrOffset;
118: unsigned int WindowPosition, LinearPosition;
119: } T_ModeInternalInfo;
120:
121: T_ModeInfo VGA_InfoTable[7] = {
122: {T16, 320, 200, 8, 4, 0, 0, 0, 0, 0, 0, 40, 40, 0, 0, 0x10000, 0xa0000, 0, 0, 0, 0, NULL, NULL, NULL},
123: {T16, 640, 200, 8, 4, 0, 0, 0, 0, 0, 0, 80, 80, 0, 0, 0x10000, 0xa0000, 0, 0, 0, 0, NULL, NULL, NULL},
124: {T16, 640, 350, 8, 4, 0, 0, 0, 0, 0, 0, 80, 80, 0, 0, 0x10000, 0xa0000, 0, 0, 0, 0, NULL, NULL, NULL},
125: {T16, 640, 480, 8, 4, 0, 0, 0, 0, 0, 0, 80, 80, 0, 0, 0x10000, 0xa0000, 0, 0, 0, 0, NULL, NULL, NULL},
126: {T256, 320, 200, 8, 8, 0, 0, 0, 0, 0, 0, 320, 320, 1, 0x10000, 0x12000, 0xa0000, 1, 0x10000, 0x12000, 0xa0000, NULL, NULL, NULL},
127: {T256, 320, 240, 8, 8, 0, 0, 0, 0, 0, 0, 80, 80, 0, 0, 0x10000, 0xa0000, 0, 0, 0, 0, NULL, NULL, NULL},
128: {T256, 320, 400, 8, 8, 0, 0, 0, 0, 0, 0, 80, 80, 0, 0, 0x10000, 0xa0000, 0, 0, 0, 0, NULL, NULL, NULL}
129: /* {T256, 320, 480
130: {T256, 360, 200
131: {T256, 360, 400
132: {T256, 360, 480*/
133: };
134:
135: T_ModeInternalInfo VGA_InternalInfoTable[7] = {
136: {TVGA, 0x0d, 0, 0, 0, 0, 0, 0, 0, 0xa0000, 0},
137: {TVGA, 0x0e, 0, 0, 0, 0, 0, 0, 0, 0xa0000, 0},
138: {TVGA, 0x10, 0, 0, 0, 0, 0, 0, 0, 0xa0000, 0},
139: {TVGA, 0x12, 0, 0, 0, 0, 0, 0, 0, 0xa0000, 0},
140: {TVGA, 0x13, 0, 0, 0, 0, 0, 0, 0, 0xa0000, 0xa0000},
141: {TModeX, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0},
142: {TModeX, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0}
143: /* {TModeX, 0x03
144: {TModeX, 0x04
145: {TModeX, 0x05
146: {TModeX, 0x06*/
147: };
148:
149: T_VBE_Table VBE_Table[24] = {
150: {T16, 0x6a, 800, 600, 8, 4, 0, 0, 0, 0, 0, 0},
151: {T256, 0x100, 640, 400, 8, 8, 0, 0, 0, 0, 0, 0},
152: {T256, 0x101, 640, 480, 8, 8, 0, 0, 0, 0, 0, 0},
153: {T16, 0x102, 800, 600, 8, 4, 0, 0, 0, 0, 0, 0},
154: {T256, 0x103, 800, 600, 8, 8, 0, 0, 0, 0, 0, 0},
155: {T16, 0x104, 1024, 768, 8, 4, 0, 0, 0, 0, 0, 0},
156: {T256, 0x105, 1024, 768, 8, 8, 0, 0, 0, 0, 0, 0},
157: {T16, 0x106, 1280, 1024, 8, 4, 0, 0, 0, 0, 0, 0},
158: {T256, 0x107, 1280, 1024, 8, 8, 0, 0, 0, 0, 0, 0},
159: {T32K, 0x10d, 320, 200, 16, 15, 5, 10, 5, 5, 5, 0},
160: {T64K, 0x10e, 320, 200, 16, 16, 5, 11, 6, 5, 5, 0},
161: {T16M, 0x10f, 320, 200, 24, 24, 8, 16, 8, 8, 8, 0},
162: {T32K, 0x110, 640, 480, 16, 15, 5, 10, 5, 5, 5, 0},
163: {T64K, 0x111, 640, 480, 16, 16, 5, 11, 6, 5, 5, 0},
164: {T16M, 0x112, 640, 480, 24, 24, 8, 16, 8, 8, 8, 0},
165: {T32K, 0x113, 800, 600, 16, 15, 5, 10, 5, 5, 5, 0},
166: {T64K, 0x114, 800, 600, 16, 16, 5, 11, 6, 5, 5, 0},
167: {T16M, 0x115, 800, 600, 24, 24, 8, 16, 8, 8, 8, 0},
168: {T32K, 0x116, 1024, 768, 16, 15, 5, 10, 5, 5, 5, 0},
169: {T64K, 0x117, 1024, 768, 16, 16, 5, 11, 6, 5, 5, 0},
170: {T16M, 0x118, 1024, 768, 24, 24, 8, 16, 8, 8, 8, 0},
171: {T32K, 0x119, 1280, 1024, 16, 15, 5, 10, 5, 5, 5, 0},
172: {T64K, 0x11a, 1280, 1024, 16, 16, 5, 11, 6, 5, 5, 0},
173: {T16M, 0x11b, 1280, 1024, 24, 24, 8, 16, 8, 8, 8, 0}
174: };
175:
176: int HasVbe = 0;
177: int HasProtectedModeInterface = 0;
178: int RestoreOldVGAMode = 0, OldVGAMode;
179:
180: T_VBE_VbeInfoBlock VBE_VbeInfoBlock;
181: T_VBE_ModeInfoBlock VBE_ModeInfoBlock;
182: T_VBE_ProtectedModeInterface *VBE_ProtectedModeInterface;
183: short VBE_ModeList[512];
184: unsigned int WinFuncPtrPM;
185: short *PortsMemory;
186:
187: T_ModeInternalInfo *InternalModeList = NULL;
188: T_ModeInternalInfo CurrentInternalMode;
189: char *LinearVgaBuffer, *AlignedLinearVgaBuffer;
190:
191: unsigned char PaletteData[768];
192: _go32_dpmi_seginfo PaletteMem;
193:
194: int VBE_GetVbeInfoBlock(void);
195: int VBE_GetModeInfoBlock(int mode);
196: int VBE_GetProtectedModeInterface(void);
197: void VBE_ChangeBankRealInterrupt(int BankNumber);
198: void VBE_ChangeBankRealMode(int BankNumber);
199: void VBE_ChangeBankProtectMode(int BankNumber);
200: void NULL_ChangeBank(int BankNumber);
201: void PutLineLinear(char *addr, int target_y);
202: void PutLineBanked(char *addr, int target_y);
203: void PutLineVGA16(char *addr, int target_y);
204: void PutLineVGAX(char *addr, int target_y);
205: void InsertMode(T_ModeInfo *ModeInfo, T_ModeInternalInfo *ModeInternalInfo);
206: void SetModeX(int ModeNumber);
207: void MapVideoMemory(void);
208:
209: int VBE_GetVbeInfoBlock(void) {
210: _go32_dpmi_registers IntRegs;
211:
212: strncpy(VBE_VbeInfoBlock.VbeSignature, "VBE2", 4);
213: dosmemput(&VBE_VbeInfoBlock, sizeof(VBE_VbeInfoBlock), __tb);
214: IntRegs.x.ax = 0x4F00;
215: IntRegs.x.di = __tb & 0x0F;
216: IntRegs.x.es = (__tb >> 4) & 0xFFFF;
217: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
218: _go32_dpmi_simulate_int(0x10, &IntRegs);
219: dosmemget(__tb, sizeof(VBE_VbeInfoBlock), &VBE_VbeInfoBlock);
220: return((IntRegs.x.ax == 0x004F) && (VBE_VbeInfoBlock.VbeVersion >= 0x0100));
221: }
222:
223: int VBE_GetModeInfoBlock(int mode) {
224: _go32_dpmi_registers IntRegs;
225:
226: VBE_ModeInfoBlock.ReservedA = 1;
227: IntRegs.x.ax = 0x4F01;
228: IntRegs.x.cx = mode;
229: IntRegs.x.di = __tb & 0x0F;
230: IntRegs.x.es = (__tb >> 4) & 0xFFFF;
231: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
232: _go32_dpmi_simulate_int(0x10, &IntRegs);
233: dosmemget(__tb, sizeof(VBE_ModeInfoBlock), &VBE_ModeInfoBlock);
234: return(IntRegs.x.ax == 0x004F);
235: }
236:
237: int VBE_GetProtectedModeInterface(void) {
238: _go32_dpmi_registers IntRegs;
239:
240: IntRegs.x.ax = 0x4F0A;
241: IntRegs.x.bx = 0x0000;
242: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
243: _go32_dpmi_simulate_int(0x10, &IntRegs);
244: VBE_ProtectedModeInterface = (T_VBE_ProtectedModeInterface *) malloc(IntRegs.x.cx);
245: if (VBE_ProtectedModeInterface == NULL)
246: return(0);
247: dosmemget(IntRegs.x.es * 16 + IntRegs.x.di, IntRegs.x.cx, VBE_ProtectedModeInterface);
248: WinFuncPtrPM = (unsigned int) VBE_ProtectedModeInterface + VBE_ProtectedModeInterface->SetWindowOffset;
249: PortsMemory = (short *) VBE_ProtectedModeInterface + VBE_ProtectedModeInterface->PortsMemoryOffset;
250: return(IntRegs.x.ax == 0x004F);
251: }
252:
253: void VBE_ChangeBankRealInterrupt(int BankNumber) {
254: _go32_dpmi_registers IntRegs;
255:
256: IntRegs.x.ax = 0x4F05;
257: IntRegs.x.bx = CurrentInternalMode.WriteWindow;
258: IntRegs.x.dx = CurrentInternalMode.GranularityFix ? BankNumber * CurrentInternalMode.GranularityFix : BankNumber;
259: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
260: _go32_dpmi_simulate_int(0x10, &IntRegs);
261: CurrentBankNumber = BankNumber;
262: }
263:
264: void VBE_ChangeBankRealMode(int BankNumber) {
265: _go32_dpmi_registers IntRegs;
266:
267: IntRegs.x.ax = 0x4F05;
268: IntRegs.x.bx = CurrentInternalMode.WriteWindow;
269: IntRegs.x.dx = CurrentInternalMode.GranularityFix ? BankNumber * CurrentInternalMode.GranularityFix : BankNumber;
270: IntRegs.x.cs = CurrentInternalMode.WinFuncPtrSegment;
271: IntRegs.x.ip = CurrentInternalMode.WinFuncPtrOffset;
272: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
273: _go32_dpmi_simulate_fcall(&IntRegs);
274: CurrentBankNumber = BankNumber;
275: }
276:
277: void VBE_ChangeBankProtectMode(int BankNumber) {
278: int BNumber = CurrentInternalMode.GranularityFix ? BankNumber * CurrentInternalMode.GranularityFix : BankNumber;
279:
280: asm __volatile__ ("
281: push %%es
282: movw %0, %%es
283: call %1
284: pop %%es
285: "
286: :
287: : "g" (_dos_ds), "r" (WinFuncPtrPM), "a" (0x4F05), "b" (CurrentInternalMode.WriteWindow), "d" (BNumber)
288: : "%ax", "%bx", "%dx", "cc", "memory"
289: );
290: CurrentBankNumber = BankNumber;
291: _farsetsel(_dos_ds);
292: }
293:
294: void NULL_ChangeBank(int BankNumber) {
295: CurrentBankNumber = BankNumber;
296: }
297:
298: void PutLineLinear(char *addr, int target_y) {
299: unsigned int ptr;
300:
301: ptr = CurrentMode.LinearAddress + target_y * CurrentMode.LogicalLineLength;
302: asm __volatile__ ("
303: push %%es
304: cld
305: movw %0, %%es
306: shrl $2, %%ecx
307: rep
308: movsl
309: pop %%es
310: "
311: :
312: : "g" (_dos_ds), "S" (addr), "D" (ptr), "c" (CurrentMode.LineLength)
313: : "%esi", "%edi", "%ecx", "cc"
314: );
315: }
316:
317: void PutLineBanked(char *addr, int target_y) {
318: unsigned int offs;
319: int page, pos, left;
320: char *ptr;
321:
322: offs = target_y * CurrentMode.LogicalLineLength;
323: if (CurrentInternalMode.FastWinCalc) {
324: page = offs >> CurrentInternalMode.WinMask1;
325: pos = offs & CurrentInternalMode.WinMask2;
326: } else {
327: page = offs / CurrentMode.WindowSize;
328: pos = offs % CurrentMode.WindowSize;
329: }
330: left = CurrentMode.WindowSize - pos;
331: ptr = (char *) CurrentMode.WindowAddress + pos;
332: if (page != CurrentBankNumber)
333: CurrentMode.ChangeBank(page);
334: if (left >= CurrentMode.LineLength)
335: asm __volatile__ ("
336: push %%es
337: cld
338: movw %0, %%es
339: shrl $2, %%ecx
340: rep
341: movsl
342: pop %%es
343: "
344: :
345: : "g" (_dos_ds), "S" (addr), "D" (ptr), "c" (CurrentMode.LineLength)
346: : "%esi", "%edi", "%ecx", "cc"
347: );
348: else {
349: asm __volatile__ ("
350: push %%es
351: cld
352: movw %0, %%es
353: shrl $2, %%ecx
354: rep
355: movsl
356: pop %%es
357: "
358: :
359: : "g" (_dos_ds), "S" (addr), "D" (ptr), "c" (left)
360: : "%esi", "%edi", "%ecx", "cc"
361: );
362: CurrentMode.ChangeBank(page+1);
363: asm __volatile__ ("
364: push %%es
365: cld
366: movw %0, %%es
367: addl %1, %%esi
368: subl %1, %%ecx
369: shrl $2, %%ecx
370: rep
371: movsl
372: pop %%es
373: "
374: :
375: : "g" (_dos_ds), "g" (left), "S" (addr), "D" (CurrentMode.WindowAddress), "c" (CurrentMode.LineLength)
376: : "%esi", "%edi", "%ecx", "cc"
377: );
378: }
379: }
380:
381: void PutLineVGA16(char *addr, int target_y) {
382: unsigned int start, ptr;
383: int i;
384: UBYTE c;
385:
386: #if 0
387: ptr = CurrentMode.WindowAddress + target_y * CurrentMode.LogicalLineLength;
388: outportw(0x3ce, 0x205);
389: outportw(0x3ce, 3);
390: for (i=0; i<CurrentMode.ModeWidth; i++) {
391: outportw(0x3ce, 1<<(((i&7)^7)+8)|8);
392: _farnspeekb(ptr+(i>>3));
393: _farnspokeb(ptr+(i>>3), addr[i]);
394: }
395: #else
396: start = CurrentMode.WindowAddress + target_y * CurrentMode.LogicalLineLength;
397: ptr = start;
398: outportw(0x3c4, 0x802);
399: for (i=0; i<CurrentMode.ModeWidth; i+=8, ptr++) {
400: c = ((addr[i ]<<4)&128)|((addr[i+1]<<3)&64)|((addr[i+2]<<2)&32)|((addr[i+3]<<1)&16)|
401: ((addr[i+4] )&8 )|((addr[i+5]>>1)&4 )|((addr[i+6]>>2)&2 )|((addr[i+7]>>3)&1);
402: _farnspokeb(ptr, c);
403: }
404: ptr = start;
405: outportw(0x3c4, 0x402);
406: for (i=0; i<CurrentMode.ModeWidth; i+=8, ptr++) {
407: c = ((addr[i ]<<5)&128)|((addr[i+1]<<4)&64)|((addr[i+2]<<3)&32)|((addr[i+3]<<2)&16)|
408: ((addr[i+4]<<1)&8 )|((addr[i+5] )&4 )|((addr[i+6]>>1)&2 )|((addr[i+7]>>2)&1 );
409: _farnspokeb(ptr, c);
410: }
411: ptr = start;
412: outportw(0x3c4, 0x202);
413: for (i=0; i<CurrentMode.ModeWidth; i+=8, ptr++) {
414: c = ((addr[i ]<<6)&128)|((addr[i+1]<<5)&64)|((addr[i+2]<<4)&32)|((addr[i+3]<<3)&16)|
415: ((addr[i+4]<<2)&8 )|((addr[i+5]<<1)&4 )|((addr[i+6] )&2 )|((addr[i+7]>>1)&1 );
416: _farnspokeb(ptr, c);
417: }
418: ptr = start;
419: outportw(0x3c4, 0x102);
420: for (i=0; i<CurrentMode.ModeWidth; i+=8, ptr++) {
421: c = ((addr[i ]<<7)&128)|((addr[i+1]<<6)&64)|((addr[i+2]<<5)&32)|((addr[i+3]<<4)&16)|
422: ((addr[i+4]<<3)&8 )|((addr[i+5]<<2)&4 )|((addr[i+6]<<1)&2 )|((addr[i+7] )&1 );
423: _farnspokeb(ptr, c);
424: }
425: #endif
426: }
427:
428: void PutLineVGAX(char *addr, int target_y) {
429: unsigned int start, ptr;
430: int i;
431: UBYTE c;
432:
433: start = CurrentMode.WindowAddress + target_y * CurrentMode.LogicalLineLength;
434: ptr = start;
435: outportw(0x3c4, 0x102);
436: for (i=0; i<CurrentMode.ModeWidth; i+=4, ptr++)
437: _farnspokeb(ptr, addr[i]);
438: ptr = start;
439: outportw(0x3c4, 0x202);
440: for (i=1; i<CurrentMode.ModeWidth; i+=4, ptr++)
441: _farnspokeb(ptr, addr[i]);
442: ptr = start;
443: outportw(0x3c4, 0x402);
444: for (i=2; i<CurrentMode.ModeWidth; i+=4, ptr++)
445: _farnspokeb(ptr, addr[i]);
446: ptr = start;
447: outportw(0x3c4, 0x802);
448: for (i=3; i<CurrentMode.ModeWidth; i+=4, ptr++)
449: _farnspokeb(ptr, addr[i]);
450: }
451:
452: void SetPalette(int Color, int Red, int Green, int Blue) {
453: _go32_dpmi_registers IntRegs;
454:
455: if (CurrentMode.ModeType == T16) {
456: IntRegs.h.ah = 0x10;
457: IntRegs.h.al = 0x00;
458: IntRegs.h.bh = Color;
459: IntRegs.h.bl = Color;
460: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
461: _go32_dpmi_simulate_int(0x10, &IntRegs);
462: }
463: IntRegs.h.ah = 0x10;
464: IntRegs.h.al = 0x10;
465: IntRegs.x.bx = Color;
466: IntRegs.h.ch = Green;
467: IntRegs.h.cl = Blue;
468: IntRegs.h.dh = Red;
469: _go32_dpmi_simulate_int(0x10, &IntRegs);
470: DelayedSetPalette(Color, Red, Green, Blue);
471: }
472:
473: void DelayedSetPalette(int Color, int Red, int Green, int Blue) {
474: PaletteData[Color * 3 + 0] = Red;
475: PaletteData[Color * 3 + 1] = Green;
476: PaletteData[Color * 3 + 2] = Blue;
477: }
478:
479: void ViewPalette(int Color, int *Red, int *Green, int *Blue) {
480: *Red = PaletteData[Color * 3 + 0] << 2;
481: *Green = PaletteData[Color * 3 + 1] << 2;
482: *Blue = PaletteData[Color * 3 + 2] << 2;
483: }
484:
485: void LoadPalette(void) {
486: _go32_dpmi_registers IntRegs;
487: int i;
488:
489: dosmemput(PaletteData, 768, PaletteMem.rm_segment*16);
490: if (CurrentMode.ModeType == T16) {
491: for(i=0; i<16; i++) {
492: IntRegs.h.ah = 0x10;
493: IntRegs.h.al = 0x00;
494: IntRegs.h.bh = i;
495: IntRegs.h.bl = i;
496: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
497: _go32_dpmi_simulate_int(0x10, &IntRegs);
498: }
499: }
500: IntRegs.h.ah = 0x10;
501: IntRegs.h.al = 0x12;
502: IntRegs.x.bx = 0;
503: if (CurrentMode.ModeType == T16)
504: IntRegs.x.cx = 16;
505: else
506: IntRegs.x.cx = 256;
507: IntRegs.x.es = PaletteMem.rm_segment;
508: IntRegs.x.dx = 0x0000;
509: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
510: _go32_dpmi_simulate_int(0x10, &IntRegs);
511: }
512:
513: int InitGfxLib(void) {
514: static int GfxInicilized = 0;
515: _go32_dpmi_registers IntRegs;
516: __dpmi_meminfo MemoryInfo;
517: unsigned int DosMemPos;
518: int DiscartMode;
519: int i, j, TryList=1, CurrentList=0;
520: short ModeNumber;
521: T_ModeInfo ModeInfo;
522: T_ModeInternalInfo ModeInternalInfo;
523:
524: if (GfxInicilized)
525: return(1);
526:
527: /* Save Old VGA Mode */
528: IntRegs.x.ax = 0x1C;
529: IntRegs.h.ah = 0x0F;
530: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
531: _go32_dpmi_simulate_int(0x10, &IntRegs);
532: OldVGAMode = IntRegs.h.al;
533:
534: /* Allocate Palette Memory */
535: PaletteMem.size = 48;
536: if (_go32_dpmi_allocate_dos_memory(&PaletteMem)) {
537: printf ("Can't allocate real mode memory for palette data.\n");
538: return(0);
539: }
540:
541: /* Check for VBE */
542: HasVbe = VBE_GetVbeInfoBlock();
543:
544: /* Build ModeInfo Tables */
545: if (HasVbe) {
546: printf ("VESA BIOS Extension version %d.%d found.\n", VBE_VbeInfoBlock.VbeVersion >> 8, VBE_VbeInfoBlock.VbeVersion & 0xFF);
547: if (VBE_VbeInfoBlock.VbeVersion >= 0x0200)
548: HasProtectedModeInterface = VBE_GetProtectedModeInterface();
549: DosMemPos = (VBE_VbeInfoBlock.VideoModePtr >> 16) * 16 +
550: (VBE_VbeInfoBlock.VideoModePtr & 0xffff);
551: dosmemget(DosMemPos, 1024, VBE_ModeList);
552: VBE_ModeList[511] = -1;
553: i = 0;
554: while(1) {
555: if (TryList) {
556: ModeNumber = VBE_Table[CurrentList].OriginalModeNumber;
557: CurrentList++;
558: if (CurrentList == 25)
559: TryList = 0;
560: } else {
561: ModeNumber = VBE_ModeList[i];
562: if (ModeNumber == -1)
563: break;
564: i++;
565: if ((ModeNumber == 0x6a) || ((ModeNumber >= 0x100) && (ModeNumber <= 0x107)) || ((ModeNumber >= 0x10d) && (ModeNumber <= 0x11b)))
566: continue;
567: }
568: if ((ModeNumber != (short)0x81ff) && VBE_GetModeInfoBlock(ModeNumber)) {
569: DiscartMode = 0;
570: if (!(VBE_ModeInfoBlock.ModeAttributes & 0x1))
571: DiscartMode = 1;
572: ModeInternalInfo.OriginalModeNumber = ModeNumber;
573: ModeInternalInfo.ControlType = TVBE;
574: ModeInfo.RedSize = 0;
575: ModeInfo.RedPosition = 0;
576: ModeInfo.GreenSize = 0;
577: ModeInfo.GreenPosition = 0;
578: ModeInfo.BlueSize = 0;
579: ModeInfo.BluePosition = 0;
580: if (VBE_VbeInfoBlock.VbeVersion < 0x0102) {
581: if (VBE_ModeInfoBlock.ModeAttributes & 0x2) {
582: ModeInfo.ModeWidth = VBE_ModeInfoBlock.XResolution;
583: ModeInfo.ModeHeight = VBE_ModeInfoBlock.YResolution;
584: ModeInfo.BitsPerPixel = VBE_ModeInfoBlock.BitsPerPixel;
585: if (ModeInfo.BitsPerPixel == 15)
586: ModeInfo.BitsPerPixel = 16;
587: if (ModeInfo.BitsPerPixel == 4) {
588: ModeInfo.ModeType = T16;
589: ModeInfo.BitsPerPixel = 8;
590: ModeInfo.BitsPerColor = 4;
591: if (VBE_ModeInfoBlock.MemoryModel != Planar)
592: DiscartMode = 1;
593: } else if (ModeInfo.BitsPerPixel == 8) {
594: ModeInfo.ModeType = T256;
595: ModeInfo.BitsPerColor = 8;
596: if (VBE_ModeInfoBlock.MemoryModel != PackedPixel)
597: DiscartMode = 1;
598: } else if (ModeInfo.BitsPerPixel == 16) {
599: ModeInfo.ModeType = T32K;
600: ModeInfo.BitsPerColor = 15;
601: ModeInfo.RedSize = 5;
602: ModeInfo.RedPosition = 10;
603: ModeInfo.GreenSize = 5;
604: ModeInfo.GreenPosition = 5;
605: ModeInfo.BlueSize = 5;
606: ModeInfo.BluePosition = 0;
607: if (VBE_ModeInfoBlock.MemoryModel != PackedPixel)
608: DiscartMode = 1;
609: } else if ((ModeInfo.BitsPerPixel == 24) || (ModeInfo.BitsPerPixel == 32)) {
610: ModeInfo.ModeType = T16M;
611: ModeInfo.BitsPerColor = 24;
612: ModeInfo.RedSize = 8;
613: ModeInfo.RedPosition = 16;
614: ModeInfo.GreenSize = 8;
615: ModeInfo.GreenPosition = 8;
616: ModeInfo.BlueSize = 8;
617: ModeInfo.BluePosition = 0;
618: if (VBE_ModeInfoBlock.MemoryModel != PackedPixel)
619: DiscartMode = 1;
620: } else
621: DiscartMode = 1;
622: } else {
623: for (j = 0; j < 24; j++) {
624: if (VBE_Table[j].OriginalModeNumber == ModeInternalInfo.OriginalModeNumber) {
625: ModeInfo.ModeType = VBE_Table[j].ModeType;
626: ModeInfo.ModeWidth = VBE_Table[j].ModeWidth;
627: ModeInfo.ModeHeight = VBE_Table[j].ModeHeight;
628: ModeInfo.BitsPerPixel = VBE_Table[j].BitsPerPixel;
629: ModeInfo.BitsPerColor = VBE_Table[j].BitsPerColor;
630: ModeInfo.RedSize = VBE_Table[j].RedSize;
631: ModeInfo.RedPosition = VBE_Table[j].RedPosition;
632: ModeInfo.GreenSize = VBE_Table[j].GreenSize;
633: ModeInfo.GreenPosition = VBE_Table[j].GreenPosition;
634: ModeInfo.BlueSize = VBE_Table[j].BlueSize;
635: ModeInfo.BluePosition = VBE_Table[j].BluePosition;
636: break;
637: }
638: }
639: if (j == 24)
640: DiscartMode = 1;
641: }
642: } else {
643: ModeInfo.ModeWidth = VBE_ModeInfoBlock.XResolution;
644: ModeInfo.ModeHeight = VBE_ModeInfoBlock.YResolution;
645: ModeInfo.BitsPerPixel = VBE_ModeInfoBlock.BitsPerPixel;
646: if (ModeInfo.BitsPerPixel == 15)
647: ModeInfo.BitsPerPixel = 16;
648: if (ModeInfo.BitsPerPixel == 4) {
649: ModeInfo.ModeType = T16;
650: ModeInfo.BitsPerPixel = 8;
651: ModeInfo.BitsPerColor = 4;
652: if (VBE_ModeInfoBlock.MemoryModel != Planar)
653: DiscartMode = 1;
654: } else if (ModeInfo.BitsPerPixel == 8) {
655: ModeInfo.ModeType = T256;
656: ModeInfo.BitsPerColor = 8;
657: if (VBE_ModeInfoBlock.MemoryModel != PackedPixel)
658: DiscartMode = 1;
659: } else {
660: ModeInfo.RedSize = VBE_ModeInfoBlock.RedMaskSize;
661: ModeInfo.RedPosition = VBE_ModeInfoBlock.RedFieldPosition;
662: ModeInfo.GreenSize = VBE_ModeInfoBlock.GreenMaskSize;
663: ModeInfo.GreenPosition = VBE_ModeInfoBlock.GreenFieldPosition;
664: ModeInfo.BlueSize = VBE_ModeInfoBlock.BlueMaskSize;
665: ModeInfo.BluePosition = VBE_ModeInfoBlock.BlueFieldPosition;
666: ModeInfo.BitsPerColor = ModeInfo.RedSize + ModeInfo.GreenSize + ModeInfo.BlueSize;
667: if (ModeInfo.BitsPerColor == 15) {
668: ModeInfo.ModeType = T32K;
669: if (ModeInfo.BitsPerPixel != 16)
670: DiscartMode = 1;
671: } else if (ModeInfo.BitsPerColor == 16) {
672: ModeInfo.ModeType = T64K;
673: if (ModeInfo.BitsPerPixel != 16)
674: DiscartMode = 1;
675: } else if (ModeInfo.BitsPerColor == 24) {
676: ModeInfo.ModeType = T16M;
677: if ((ModeInfo.BitsPerPixel != 24) && (ModeInfo.BitsPerPixel != 32))
678: DiscartMode = 1;
679: } else
680: DiscartMode = 1;
681: if (VBE_ModeInfoBlock.MemoryModel != DirectColor)
682: DiscartMode = 1;
683: }
684: }
685: ModeInfo.LineLength = (ModeInfo.BitsPerPixel >> 3) * ModeInfo.ModeWidth;
686: ModeInfo.LogicalLineLength = VBE_ModeInfoBlock.BytesPerScanLine;
687: ModeInfo.HasWindow = 0;
688: ModeInfo.HasLinear = 0;
689: if ((VBE_ModeInfoBlock.MemoryModel == PackedPixel) || (VBE_ModeInfoBlock.MemoryModel == DirectColor)) {
690: if (!(VBE_ModeInfoBlock.ModeAttributes & 0x40)) {
691: ModeInfo.HasWindow = 1;
692: if (VBE_ModeInfoBlock.WinFuncPtr != 0) {
693: ModeInternalInfo.WinFuncPtrSegment = VBE_ModeInfoBlock.WinFuncPtr >> 16;
694: ModeInternalInfo.WinFuncPtrOffset = VBE_ModeInfoBlock.WinFuncPtr & 0xffff;
695: } else {
696: ModeInternalInfo.WinFuncPtrSegment = 0;
697: ModeInternalInfo.WinFuncPtrOffset = 0;
698: }
699: ModeInfo.WindowSize = VBE_ModeInfoBlock.WinSize * 1024;
700: if ((VBE_ModeInfoBlock.WinAAttributes & 1) || (VBE_ModeInfoBlock.WinBAttributes & 1)) {
701: if ((!(VBE_ModeInfoBlock.WinBAttributes & 4)) || (VBE_ModeInfoBlock.WinAAttributes & 4)) {
702: ModeInternalInfo.WriteWindow = 0;
703: ModeInternalInfo.WindowPosition = ModeInfo.WindowAddress = VBE_ModeInfoBlock.WinASegment * 16;
704: } else {
705: ModeInternalInfo.WriteWindow = 1;
706: ModeInternalInfo.WindowPosition = ModeInfo.WindowAddress = VBE_ModeInfoBlock.WinBSegment * 16;
707: }
708: if (VBE_ModeInfoBlock.WinGranularity) {
709: ModeInternalInfo.GranularityFix = VBE_ModeInfoBlock.WinSize / VBE_ModeInfoBlock.WinGranularity;
710: if (ModeInternalInfo.GranularityFix == 1)
711: ModeInternalInfo.GranularityFix = 0;
712: } else
713: ModeInternalInfo.GranularityFix = 0;
714: } else
715: ModeInfo.WindowSize = ModeInfo.WindowAddress = ModeInternalInfo.GranularityFix = 0;
716: /* You never know... */
717: if (ModeInfo.WindowSize == 0)
718: ModeInfo.WindowSize = 0x10000;
719: if (ModeInfo.WindowAddress == 0)
720: ModeInternalInfo.WindowPosition = ModeInfo.WindowAddress = 0xa0000;
721: ModeInternalInfo.FastWinCalc = 0;
722: for (j=1; j<32; j++) {
723: if (((unsigned int) 1<<j) == ModeInfo.WindowSize) {
724: ModeInternalInfo.FastWinCalc = 1;
725: ModeInternalInfo.WinMask1 = j;
726: ModeInternalInfo.WinMask2 = ModeInfo.WindowSize-1;
727: break;
728: }
729: }
730: ModeInfo.WindowMappingSize = ModeInfo.WindowSize + 0x2000;
731: }
732: if (VBE_ModeInfoBlock.ModeAttributes & 0x80) {
733: ModeInfo.HasLinear = 1;
734: ModeInternalInfo.LinearPosition = VBE_ModeInfoBlock.PhysBasePtr;
735: ModeInfo.LinearSize = ModeInfo.ModeHeight * ModeInfo.LogicalLineLength;
736: MemoryInfo.size = ModeInfo.LinearSize;
737: MemoryInfo.address = ModeInternalInfo.LinearPosition;
738: if (!__dpmi_physical_address_mapping(&MemoryInfo))
739: ModeInfo.LinearAddress = MemoryInfo.address;
740: else
741: ModeInfo.LinearAddress = 0;
742: ModeInfo.LinearMappingSize = ModeInfo.LinearSize + 0x2000;
743: }
744: }
745: ModeInfo.ChangeBank = NULL;
746: ModeInfo.PutLine = NULL;
747: ModeInfo.MappedAddress = NULL;
748: if ((ModeInfo.ModeType == T16) && (ModeInfo.ModeHeight > 600)) //FIXME! not supported yeat
749: DiscartMode = 1;
750: if (!DiscartMode)
751: InsertMode(&ModeInfo, &ModeInternalInfo);
752: }
753: }
754: }
755: for (i = 0; i < 7; i++)
756: InsertMode(&VGA_InfoTable[i], &VGA_InternalInfoTable[i]);
757:
758: /* See if we can map */
759: LinearVgaBuffer = malloc(0x11000);
760: if (LinearVgaBuffer != NULL) {
761: AlignedLinearVgaBuffer = (char *) ALIGN(LinearVgaBuffer);
762: if (!__djgpp_map_physical_memory(AlignedLinearVgaBuffer, 0x10000, 0xa0000))
763: CanMapBuffer = 1;
764: }
765:
766: GfxInicilized = 1;
767: return(1);
768: }
769:
770: void CloseGfxLib(void) {
771: _go32_dpmi_registers IntRegs;
772:
773: if (RestoreOldVGAMode) {
774: IntRegs.x.ax = 0x1C;
775: IntRegs.h.ah = 0x00;
776: IntRegs.h.al = OldVGAMode;
777: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
778: _go32_dpmi_simulate_int(0x10, &IntRegs);
779: }
780: _go32_dpmi_free_dos_memory(&PaletteMem);
781: }
782:
783: void InsertMode(T_ModeInfo *ModeInfo, T_ModeInternalInfo *ModeInternalInfo) {
784: if (NumberOfModes == 0) {
785: ModeList = malloc(sizeof(T_ModeInfo));
786: InternalModeList = malloc(sizeof(T_ModeInternalInfo));
787: } else {
788: ModeList = realloc(ModeList, sizeof(T_ModeInfo) * (NumberOfModes + 1));
789: InternalModeList = realloc(InternalModeList, sizeof(T_ModeInternalInfo) * (NumberOfModes + 1));
790: }
791: ModeList[NumberOfModes] = *ModeInfo;
792: InternalModeList[NumberOfModes] = *ModeInternalInfo;
793: NumberOfModes++;
794: }
795:
1.1.1.2 ! root 796: int SetMode(int ModeNumber, int Linear, int Debug) {
1.1 root 797: _go32_dpmi_registers IntRegs;
798:
799: switch(InternalModeList[ModeNumber].ControlType) {
800: case TVBE:
1.1.1.2 ! root 801: if (Debug) printf ("Using VESA BIOS.\n");
1.1 root 802: IntRegs.x.ax = 0x4F02;
803: if (ModeList[ModeNumber].ModeType == T16) {
804: if (Linear)
805: return(0);
806: IntRegs.x.bx = InternalModeList[ModeNumber].OriginalModeNumber;
807: ModeList[ModeNumber].ChangeBank = NULL_ChangeBank;
808: ModeList[ModeNumber].PutLine = PutLineVGA16;
809: } else if (Linear) {
810: if (!ModeList[ModeNumber].HasLinear)
811: return(0);
812: IntRegs.x.bx = InternalModeList[ModeNumber].OriginalModeNumber | (1<<14);
813: ModeList[ModeNumber].ChangeBank = NULL_ChangeBank;
814: ModeList[ModeNumber].PutLine = PutLineLinear;
815: } else {
816: if (!ModeList[ModeNumber].HasWindow)
817: return(0);
818: IntRegs.x.bx = InternalModeList[ModeNumber].OriginalModeNumber;
819: if (HasProtectedModeInterface) {
1.1.1.2 ! root 820: if (Debug) printf ("Using Protected Mode Bank Switch Function.\n");
1.1 root 821: ModeList[ModeNumber].ChangeBank = VBE_ChangeBankProtectMode;
822: } else if ((InternalModeList[ModeNumber].WinFuncPtrSegment != 0) && (InternalModeList[ModeNumber].WinFuncPtrOffset != 0)) {
1.1.1.2 ! root 823: if (Debug) printf ("Using Real Mode Bank Switch Function.\n");
1.1 root 824: ModeList[ModeNumber].ChangeBank = VBE_ChangeBankRealMode;
825: } else {
1.1.1.2 ! root 826: if (Debug) printf ("Using Real Mode Bank Switch Interrupt Function.\n");
1.1 root 827: ModeList[ModeNumber].ChangeBank = VBE_ChangeBankRealInterrupt;
828: }
829: ModeList[ModeNumber].PutLine = PutLineBanked;
830: }
831: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
832: _go32_dpmi_simulate_int(0x10, &IntRegs);
833: break;
834: case TVGA:
1.1.1.2 ! root 835: if (Debug) printf ("Using normal VGA.\n");
1.1 root 836: IntRegs.h.ah = 0x00;
837: IntRegs.h.al = InternalModeList[ModeNumber].OriginalModeNumber;
838: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
839: _go32_dpmi_simulate_int(0x10, &IntRegs);
840: ModeList[ModeNumber].ChangeBank = NULL_ChangeBank;
841: if (ModeList[ModeNumber].ModeType == T16)
842: ModeList[ModeNumber].PutLine = PutLineVGA16;
843: else
844: ModeList[ModeNumber].PutLine = PutLineLinear;
845: break;
846: case TModeX:
1.1.1.2 ! root 847: if (Debug) printf ("Using VGA Mode X.\n");
1.1 root 848: SetModeX(InternalModeList[ModeNumber].OriginalModeNumber);
849: ModeList[ModeNumber].ChangeBank = NULL_ChangeBank;
850: ModeList[ModeNumber].PutLine = PutLineVGAX;
851: break;
852: }
853: CurrentMode = ModeList[ModeNumber];
854: CurrentInternalMode = InternalModeList[ModeNumber];
855: RestoreOldVGAMode = 1;
856: MapVideoMemory();
857: return(1);
858: }
859:
860: void SetModeX(int ModeNumber) {
861: _go32_dpmi_registers IntRegs;
862: int i;
863: char cleared[320];
864:
865: IntRegs.h.ah = 0x00;
866: IntRegs.h.al = 0x13;
867: IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
868: _go32_dpmi_simulate_int(0x10, &IntRegs);
869: for (i=0; i<320; i++)
870: cleared[i] = 0;
871: outportw(0x3c4, 0x604);
872: if (ModeNumber == 1) {
873: outportw(0x3c4, 0x0100);
874: outportb(0x3c2, 0x00e3);
875: outportw(0x3c4, 0x0300);
876: outportw(0x3d4, 0x2c11);
877: outportw(0x3d4, 0x5f00);
878: outportw(0x3d4, 0x4f01);
879: outportw(0x3d4, 0x5002);
880: outportw(0x3d4, 0x8203);
881: outportw(0x3d4, 0x5404);
882: outportw(0x3d4, 0x8005);
883: outportw(0x3d4, 0x0d06);
884: outportw(0x3d4, 0x3e07);
885: outportw(0x3d4, 0x0008);
886: outportw(0x3d4, 0x4109);
887: outportw(0x3d4, 0x000a);
888: outportw(0x3d4, 0x000b);
889: outportw(0x3d4, 0x000c);
890: outportw(0x3d4, 0x000d);
891: outportw(0x3d4, 0x000e);
892: outportw(0x3d4, 0x000f);
893: outportw(0x3d4, 0xea10);
894: outportw(0x3d4, 0xac11);
895: outportw(0x3d4, 0xdf12);
896: outportw(0x3d4, 0x2813);
897: outportw(0x3d4, 0x0014);
898: outportw(0x3d4, 0xe715);
899: outportw(0x3d4, 0x0616);
900: outportw(0x3d4, 0xe317);
901: for (i=0; i<240; i++)
902: PutLineVGAX(cleared, i);
903: } else {
904: outportw(0x3d4, 0x0e11);
905: outportw(0x3d4, 0x5f00);
906: outportw(0x3d4, 0x4f01);
907: outportw(0x3d4, 0x5002);
908: outportw(0x3d4, 0x8203);
909: outportw(0x3d4, 0x5404);
910: outportw(0x3d4, 0x8005);
911: outportw(0x3d4, 0xbf06);
912: outportw(0x3d4, 0x1f07);
913: outportw(0x3d4, 0x0008);
914: outportw(0x3d4, 0x4009);
915: outportw(0x3d4, 0x000a);
916: outportw(0x3d4, 0x000b);
917: outportw(0x3d4, 0x000c);
918: outportw(0x3d4, 0x000d);
919: outportw(0x3d4, 0x000e);
920: outportw(0x3d4, 0x000f);
921: outportw(0x3d4, 0x9c10);
922: outportw(0x3d4, 0x8e11);
923: outportw(0x3d4, 0x8f12);
924: outportw(0x3d4, 0x2813);
925: outportw(0x3d4, 0x0014);
926: outportw(0x3d4, 0x9615);
927: outportw(0x3d4, 0xb916);
928: outportw(0x3d4, 0xe317);
929: for (i=0; i<400; i++)
930: PutLineVGAX(cleared, i);
931: }
932: }
933:
934: void MapVideoMemory(void) {
935: int Amont, AlignedAmont;
936: unsigned int PhysicalPosition;
937: char *NearPosition, *AlignedBufferPtr;
938:
939: if ((!CanMapBuffer) || (CurrentMode.MappedAddress != NULL))
940: return;
941: if ((CurrentMode.HasLinear) && (CurrentMode.ChangeBank == NULL_ChangeBank)) {
942: Amont = CurrentMode.LinearSize;
943: PhysicalPosition = CurrentInternalMode.LinearPosition;
944: NearPosition = malloc(CurrentMode.LinearMappingSize);
945: } else if (CurrentMode.HasWindow) {
946: Amont = CurrentMode.WindowSize;
947: PhysicalPosition = CurrentInternalMode.WindowPosition;
948: NearPosition = malloc(CurrentMode.WindowMappingSize);
949: } else
950: return;
951: if (NearPosition == NULL)
952: return;
953: AlignedBufferPtr = (char *) ALIGN(NearPosition);
954: AlignedAmont = ALIGN(Amont);
955: if (__djgpp_map_physical_memory(AlignedBufferPtr, AlignedAmont, PhysicalPosition)) {
956: free(NearPosition);
957: CurrentMode.MappedAddress = NULL;
958: } else
959: CurrentMode.MappedAddress = AlignedBufferPtr;
960: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.