dos gcc 2.95 asm fixes (d1x r1.2)
[btb/d2x.git] / arch / dos / vesa.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/dos/vesa.c,v $
3  * $Revision: 1.4 $
4  * $Author: btb $
5  * $Date: 2004-05-21 01:31:49 $
6  *
7  * Dos VESA
8  *
9  * $Log: not supported by cvs2svn $
10  * Revision 1.3  2001/10/19 09:01:56  bradleyb
11  * Moved arch/sdl_* to arch/sdl
12  *
13  * Revision 1.2  2001/01/29 13:35:08  bradleyb
14  * Fixed build system, minor fixes
15  *
16  */
17
18 #ifdef HAVE_CONFIG_H
19 #include <conf.h>
20 #endif
21
22 #include <string.h>
23 #include "gr.h"
24 #include "grdef.h"
25 #include "u_dpmi.h"
26 #include "vesa.h"
27
28 #define SC_INDEX   0x3c4
29 #define CRTC_INDEX 0x3d4
30 #define CRTC_DATA  0x3d5
31
32 static int bankshift;
33 static int lastbank;
34
35 /* this comes from Allegro */
36 typedef struct vesa_mode_info
37 {
38    unsigned short ModeAttributes;
39    unsigned char  WinAAttributes;
40    unsigned char  WinBAttributes;
41    unsigned short WinGranularity;
42    unsigned short WinSize;
43    unsigned short WinASegment;
44    unsigned short WinBSegment;
45    unsigned long  WinFuncPtr;
46    unsigned short BytesPerScanLine;
47    unsigned short XResolution;
48    unsigned short YResolution;
49    unsigned char  XCharSize;
50    unsigned char  YCharSize;
51    unsigned char  NumberOfPlanes;
52    unsigned char  BitsPerPixel;
53    unsigned char  NumberOfBanks;
54    unsigned char  MemoryModel;
55    unsigned char  BankSize;
56    unsigned char  NumberOfImagePages;
57    unsigned char  Reserved_page;
58    unsigned char  RedMaskSize;
59    unsigned char  RedMaskPos;
60    unsigned char  GreenMaskSize;
61    unsigned char  GreenMaskPos;
62    unsigned char  BlueMaskSize;
63    unsigned char  BlueMaskPos;
64    unsigned char  ReservedMaskSize;
65    unsigned char  ReservedMaskPos;
66    unsigned char  DirectColorModeInfo;
67    unsigned long  PhysBasePtr;
68    unsigned long  OffScreenMemOffset;
69    unsigned short OffScreenMemSize;
70    unsigned char  Reserved[206];
71 } __attribute__ ((packed)) vesa_mode_info;
72
73
74 int gr_vesa_checkmode(int mode) {
75         int i;
76         dpmi_real_regs rregs;
77         vesa_mode_info *mode_info;
78
79         if (!(mode_info = dpmi_get_temp_low_buffer( 1024 )))
80             return 7;
81         rregs.eax = 0x4f01;
82         rregs.ecx = mode;
83         rregs.edi = DPMI_real_offset(mode_info);
84         rregs.es = DPMI_real_segment(mode_info);
85         dpmi_real_int386x( 0x10, &rregs );
86         if (rregs.eax != 0x4f)
87                 return 5; /* no vesa */
88         if (!(mode_info->ModeAttributes & 1))
89                 return 4; /* unsupported mode */
90
91         bankshift = 0;
92         i = mode_info->WinGranularity;
93         while (i < 64) {
94                 i <<= 1;
95                 bankshift++;
96         }
97         if (i != 64)
98                 return 2; /* incompatible window granularity */
99         return 0;
100 }
101
102 int gr_vesa_setmode(int mode) {
103     int ret;
104     lastbank = -1;
105     if ((ret = gr_vesa_checkmode(mode)))
106         return ret;
107     asm volatile("int $0x10" : "=a" (ret) : "a" (0x4f02), "b" (mode));
108     return (ret == 0x4f) ? 0 : 4;
109 }
110
111 inline void gr_vesa_setpage(int bank)
112 {
113         int dummy[1];
114
115     if (bank != lastbank)
116                 asm volatile("int $0x10"
117                  : "a" (dummy[0])
118                  : "0" (0x4f05), "b" (0), "d" ((lastbank = bank) << bankshift));
119 }
120
121 void gr_vesa_incpage() {
122     gr_vesa_setpage(lastbank + 1);
123 }
124
125 void gr_vesa_setstart(int col, int row)
126 {
127         int dummy;
128
129     asm volatile("int $0x10"
130      : "=a" (dummy) : "0" (0x4f07), "b" (0), "c" (col), "d" (row));
131 }
132
133 int gr_vesa_setlogical(int line_width)
134 {
135     int ret;
136         int dummy;
137
138     asm volatile("int $0x10"
139      : "=c" (ret), "=a" (dummy) : "1" (0x4f07), "b" (0), "c" (line_width));
140     return ret;
141 }
142
143 void gr_vesa_scanline(int x1, int x2, int y, unsigned char color) {
144     int addr = (y * gr_var_bwidth) + x1;
145     int left = x2 - x1 + 1;
146     gr_vesa_setpage(addr >> 16);
147     addr &= 0xffff;
148     while (left) {
149         if (left > (65536 - addr)) {
150             left -= (65536 - addr);
151             memset(gr_video_memory + addr, color, 65536 - addr);
152             addr = 0;
153             gr_vesa_incpage();
154         } else {
155             memset(gr_video_memory + addr, color, left);
156             left = 0;
157         }
158     }
159 }
160
161 void gr_vesa_pixel(unsigned char color, unsigned int addr) {
162     gr_vesa_setpage(addr >> 16);
163     gr_video_memory[addr & 0xffff] = color;
164 }