]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/vesa.c
54791301af4503e6927e86e3a401b9c2233d213b
[btb/d2x.git] / arch / dos / vesa.c
1 #include <string.h>
2 #include "gr.h"
3 #include "grdef.h"
4 #include "u_dpmi.h"
5 #include "vesa.h"
6
7 #define SC_INDEX   0x3c4
8 #define CRTC_INDEX 0x3d4
9 #define CRTC_DATA  0x3d5
10
11 static int bankshift;
12 static int lastbank;
13
14 /* this comes from Allegro */
15 typedef struct vesa_mode_info
16 {
17    unsigned short ModeAttributes;
18    unsigned char  WinAAttributes;
19    unsigned char  WinBAttributes;
20    unsigned short WinGranularity;
21    unsigned short WinSize;
22    unsigned short WinASegment;
23    unsigned short WinBSegment;
24    unsigned long  WinFuncPtr;
25    unsigned short BytesPerScanLine;
26    unsigned short XResolution;
27    unsigned short YResolution;
28    unsigned char  XCharSize;
29    unsigned char  YCharSize;
30    unsigned char  NumberOfPlanes;
31    unsigned char  BitsPerPixel;
32    unsigned char  NumberOfBanks;
33    unsigned char  MemoryModel;
34    unsigned char  BankSize;
35    unsigned char  NumberOfImagePages;
36    unsigned char  Reserved_page;
37    unsigned char  RedMaskSize;
38    unsigned char  RedMaskPos;
39    unsigned char  GreenMaskSize;
40    unsigned char  GreenMaskPos;
41    unsigned char  BlueMaskSize;
42    unsigned char  BlueMaskPos;
43    unsigned char  ReservedMaskSize;
44    unsigned char  ReservedMaskPos;
45    unsigned char  DirectColorModeInfo;
46    unsigned long  PhysBasePtr;
47    unsigned long  OffScreenMemOffset;
48    unsigned short OffScreenMemSize;
49    unsigned char  Reserved[206];
50 } __attribute__ ((packed)) vesa_mode_info;
51
52
53 int gr_vesa_checkmode(int mode) {
54         int i;
55         dpmi_real_regs rregs;
56         vesa_mode_info *mode_info;
57
58         if (!(mode_info = dpmi_get_temp_low_buffer( 1024 )))
59             return 7;
60         rregs.eax = 0x4f01;
61         rregs.ecx = mode;
62         rregs.edi = DPMI_real_offset(mode_info);
63         rregs.es = DPMI_real_segment(mode_info);
64         dpmi_real_int386x( 0x10, &rregs );
65         if (rregs.eax != 0x4f)
66                 return 5; /* no vesa */
67         if (!(mode_info->ModeAttributes & 1))
68                 return 4; /* unsupported mode */
69
70         bankshift = 0;
71         i = mode_info->WinGranularity;
72         while (i < 64) {
73                 i <<= 1;
74                 bankshift++;
75         }
76         if (i != 64)
77                 return 2; /* incompatible window granularity */
78         return 0;
79 }
80
81 int gr_vesa_setmode(int mode) {
82     int ret;
83     lastbank = -1;
84     if ((ret = gr_vesa_checkmode(mode)))
85         return ret;
86     asm volatile("int $0x10" : "=a" (ret) : "a" (0x4f02), "b" (mode));
87     return (ret == 0x4f) ? 0 : 4;
88 }
89
90 inline void gr_vesa_setpage(int bank) {
91     if (bank != lastbank)
92         asm volatile("int $0x10"
93          : : "a" (0x4f05), "b" (0), "d" ((lastbank = bank) << bankshift)
94          : "%eax");
95 }
96
97 void gr_vesa_incpage() {
98     gr_vesa_setpage(lastbank + 1);
99 }
100
101 void gr_vesa_setstart(int col, int row) {
102     asm volatile("int $0x10"
103      : : "a" (0x4f07), "b" (0), "c" (col), "d" (row) : "%eax");
104 }
105
106 int gr_vesa_setlogical(int line_width) {
107     int ret;
108     asm volatile("int $0x10"
109      : "=c" (ret) : "a" (0x4f07), "b" (0), "c" (line_width) : "%eax");
110     return ret;
111 }
112
113 void gr_vesa_scanline(int x1, int x2, int y, unsigned char color) {
114     int addr = (y * gr_var_bwidth) + x1;
115     int left = x2 - x1 + 1;
116     gr_vesa_setpage(addr >> 16);
117     addr &= 0xffff;
118     while (left) {
119         if (left > (65536 - addr)) {
120             left -= (65536 - addr);
121             memset(gr_video_memory + addr, color, 65536 - addr);
122             addr = 0;
123             gr_vesa_incpage();
124         } else {
125             memset(gr_video_memory + addr, color, left);
126             left = 0;
127         }
128     }
129 }
130
131 void gr_vesa_pixel(unsigned char color, unsigned int addr) {
132     gr_vesa_setpage(addr >> 16);
133     gr_video_memory[addr & 0xffff] = color;
134 }