]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/vesa/vesa240.c
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / vesa / vesa240.c
1
2 /* TODO: Make the 320x200x256-color override hack optional (and off by default).
3  *       
4  *       On an S3 Virge PCI card I own, substituting a VESA BIOS mode for mode
5  *       13h causes additional compatability problems because things like
6  *       horizontal pel and other standard VGA tricks don't work at all.
7  *       Considering you just finished the Standard VGA version of this hack,
8  *       the mode 13h hack is no longer necessary and it should be disabled by
9  *       default though available as an option. */
10
11 #include <stdio.h>
12 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
13 #include <stddef.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <assert.h>
18 #include <fcntl.h>
19 #include <math.h>
20 #include <dos.h>
21
22 #include <hw/dos/dos.h>
23 #include <hw/vesa/vesa.h>
24
25 struct mode_remap {
26         uint16_t        source_mode;
27         uint16_t        target_mode;
28 };
29
30 #define MAX_REMAP       256
31
32 void                    (__interrupt __far *old_int10)();
33 struct mode_remap       remap[MAX_REMAP];
34 int                     remap_count=0;
35 union REGS              remap_rr;
36
37 void __interrupt __far new_int10(union INTPACK ip) {
38         if (ip.h.ah == 0x00) {
39                 unsigned int i,j;
40
41                 for (i=0;i < remap_count;i++) {
42                         if (remap[i].source_mode == (ip.h.al&0x7F)) {
43                                 j = remap[i].target_mode | ((ip.h.al&0x80)?0x8000:0x0000);
44                                 __asm {
45                                         push    ds
46                                         mov     ax,seg old_int10
47                                         mov     ds,ax
48                                         mov     ax,0x4F02
49                                         mov     bx,j
50                                         pushf
51                                         callf   dword ptr [old_int10]
52                                         pop     ds
53                                 }
54
55                                 return;
56                         }
57                 }
58         }
59         else if (ip.w.ax == 0x4F02) {
60                 unsigned int i;
61
62                 for (i=0;i < remap_count;i++) {
63                         if (remap[i].source_mode == (ip.w.bx&0x3FFF)) {
64                                 ip.w.bx = remap[i].target_mode | (ip.w.bx & 0xC000);
65                                 break;
66                         }
67                 }
68         }
69
70         _chain_intr(old_int10);
71 }
72
73 static void help() {
74         printf("VESA240 /INSTALL\n");
75         printf("\n");
76         printf("Intercept VESA BIOS calls to force video modes with at least 480 scan lines,\n");
77         printf("which may improve video quality with scan converters or enable capture/viewing\n");
78         printf("where devices would normally ignore 400-line output.\n");
79         printf("(C) 2014 Jonathan Campbell\n");
80 }
81
82 void end_of_resident();
83
84 void install_320x200x256_remap() {
85         struct vbe_mode_info nmi;
86         uint16_t nmode,tnmode;
87         int nentry;
88
89         nmode=0;
90         for (nentry=0;nentry < 1024;nentry++) {
91                 tnmode = vbe_read_mode_entry(vbe_info->video_mode_ptr,nentry);
92                 if (tnmode == 0xFFFF) break;
93                 memset(&nmi,0,sizeof(nmi));
94                 if (!vbe_read_mode_info(tnmode,&nmi)) continue;
95                 if (!(nmi.mode_attributes & VESA_MODE_ATTR_HW_SUPPORTED)) continue;
96                 if (!(nmi.mode_attributes & VESA_MODE_ATTR_GRAPHICS_MODE)) continue;
97                 if (nmi.x_resolution != 320) continue;
98                 if (nmi.y_resolution != 240) continue;
99                 if (nmi.number_of_planes != 1) continue;
100                 if (nmi.bits_per_pixel != 8) continue;
101                 if (!(nmi.memory_model == 5/*non-chain 4 256-color*/ || nmi.memory_model == 4/*packed*/ || nmi.memory_model == 3/*4-plane*/)) continue;
102                 nmode = tnmode;
103                 break;
104         }
105
106         if (nmode != 0) {
107                 printf("  Remapping mode 0x13 to 0x%03x (%ux%ux%u)\n",nmode,
108                                 nmi.x_resolution,nmi.y_resolution,nmi.bits_per_pixel);
109
110                 if (remap_count < MAX_REMAP) {
111                         remap[remap_count].source_mode = 0x13;
112                         remap[remap_count].target_mode = nmode&0x3FFF;
113                         remap_count++;
114                 }
115         }
116         else {
117                 printf("  No mapping available for mode 0x13\n");
118         }
119 }
120
121 int main(int argc,char **argv) {
122         char *a,*command=NULL;
123         unsigned int entry;
124         uint16_t mode;
125         int i;
126
127 #if TARGET_MSDOS != 16
128 # error you are not supposed to compile this for protected mode!
129 #endif
130
131         for (i=1;i < argc;) {
132                 a = argv[i++];
133                 if (*a == '/' || *a == '-') {
134                         do { a++; } while (*a == '/' || *a == '-');
135
136                         if (!strcasecmp(a,"i") || !strcasecmp(a,"install")) {
137                                 command = a;
138                         }
139                         else {
140                                 fprintf(stderr,"Unknown switch %s\n",a);
141                                 command = NULL;
142                                 break;
143                         }
144                 }
145                 else {
146                         fprintf(stderr,"Unknown switch %s\n",a);
147                         command = NULL;
148                         break;
149                 }
150         }
151
152         if (command == NULL) {
153                 help();
154                 return 1;
155         }
156         if (!vbe_probe() || vbe_info == NULL) {
157                 printf("VESA BIOS not found\n");
158                 return 1;
159         }
160         if (vbe_info->video_mode_ptr == 0UL) {
161                 printf("VBE bios does not provide a mode list\n");
162                 return 1;
163         }
164
165         /* also find a mapping from mode 0x13 (320x200x256) to VESA BIOS */
166         install_320x200x256_remap();
167
168         for (entry=0;entry < 1024;entry++) {
169                 struct vbe_mode_info mi={0},nmi;
170                 uint16_t nmode,tnmode;
171                 int nentry;
172
173                 mode = vbe_read_mode_entry(vbe_info->video_mode_ptr,entry);
174                 if (mode == 0xFFFF) break;
175                 if (!vbe_read_mode_info(mode,&mi)) continue;
176                 if (!(mi.mode_attributes & VESA_MODE_ATTR_HW_SUPPORTED)) continue;
177                 if (!(mi.mode_attributes & VESA_MODE_ATTR_GRAPHICS_MODE)) continue;
178
179                 if (mi.y_resolution < 240 || (mi.y_resolution > 240 && mi.y_resolution < 480)) {
180                         printf("Mode 0x%03x (%ux%ux%u) has less than 480 lines\n",mode,
181                                 mi.x_resolution,mi.y_resolution,mi.bits_per_pixel);
182
183                         /* look for a target mode to remap to */
184                         nmode=0;
185                         for (nentry=0;nentry < 1024;nentry++) {
186                                 tnmode = vbe_read_mode_entry(vbe_info->video_mode_ptr,nentry);
187                                 if (tnmode == 0xFFFF) break;
188                                 memset(&nmi,0,sizeof(nmi));
189                                 if (!vbe_read_mode_info(tnmode,&nmi)) continue;
190                                 if (!(nmi.mode_attributes & VESA_MODE_ATTR_HW_SUPPORTED)) continue;
191                                 if (!(nmi.mode_attributes & VESA_MODE_ATTR_GRAPHICS_MODE)) continue;
192                                 if (nmi.x_resolution != mi.x_resolution) continue;
193                                 if (nmi.number_of_planes != mi.number_of_planes) continue;
194                                 if (nmi.bits_per_pixel != mi.bits_per_pixel) continue;
195                                 if (nmi.number_of_banks != mi.number_of_banks) continue;
196                                 if (nmi.memory_model != mi.memory_model) continue;
197
198                                 if (mi.y_resolution < 240 && nmi.y_resolution == 240) {
199                                         /* found one: should remap 320x200 -> 320x240 */
200                                         nmode = tnmode;
201                                         break;
202                                 }
203                                 else if (mi.y_resolution >= 240 && nmi.y_resolution == 480) {
204                                         /* found one: should remap 320/640x350/400 to 320/640x480 */
205                                         nmode = tnmode;
206                                         break;
207                                 }
208                         }
209
210                         if (nmode != 0) {
211                                 printf("  Remap to 0x%03x (%ux%ux%u)\n",nmode,
212                                         nmi.x_resolution,nmi.y_resolution,nmi.bits_per_pixel);
213                         }
214                         else {
215                                 printf("  Remap to nothing\n");
216                         }
217
218                         if (remap_count >= MAX_REMAP) break;
219                         remap[remap_count].source_mode = mode&0x3FFF;
220                         remap[remap_count].target_mode = nmode&0x3FFF;
221                         remap_count++;
222                 }
223         }
224
225         if (remap_count == 0) {
226                 printf("Nothing to remap\n");
227                 return 0;
228         }
229
230         _cli();
231         old_int10 = _dos_getvect(0x10);
232         _dos_setvect(0x10,new_int10);
233         _sti();
234         printf("INT 10h hooked\n"); fflush(stdout);
235         _dos_keep(0,(34000+sizeof(remap))>>4); /* FIXME! */
236         return 0;
237 }
238
239 void end_of_resident() {
240 }
241