2 /* TODO: Make the 320x200x256-color override hack optional (and off by default).
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. */
12 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
22 #include <hw/dos/dos.h>
23 #include <hw/vesa/vesa.h>
32 void (__interrupt __far *old_int10)();
33 struct mode_remap remap[MAX_REMAP];
37 void __interrupt __far new_int10(union INTPACK ip) {
38 if (ip.h.ah == 0x00) {
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);
51 callf dword ptr [old_int10]
59 else if (ip.w.ax == 0x4F02) {
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);
70 _chain_intr(old_int10);
74 printf("VESA240 /INSTALL\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");
82 void end_of_resident();
84 void install_320x200x256_remap() {
85 struct vbe_mode_info nmi;
86 uint16_t nmode,tnmode;
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;
107 printf(" Remapping mode 0x13 to 0x%03x (%ux%ux%u)\n",nmode,
108 nmi.x_resolution,nmi.y_resolution,nmi.bits_per_pixel);
110 if (remap_count < MAX_REMAP) {
111 remap[remap_count].source_mode = 0x13;
112 remap[remap_count].target_mode = nmode&0x3FFF;
117 printf(" No mapping available for mode 0x13\n");
121 int main(int argc,char **argv) {
122 char *a,*command=NULL;
127 #if TARGET_MSDOS != 16
128 # error you are not supposed to compile this for protected mode!
131 for (i=1;i < argc;) {
133 if (*a == '/' || *a == '-') {
134 do { a++; } while (*a == '/' || *a == '-');
136 if (!strcasecmp(a,"i") || !strcasecmp(a,"install")) {
140 fprintf(stderr,"Unknown switch %s\n",a);
146 fprintf(stderr,"Unknown switch %s\n",a);
152 if (command == NULL) {
156 if (!vbe_probe() || vbe_info == NULL) {
157 printf("VESA BIOS not found\n");
160 if (vbe_info->video_mode_ptr == 0UL) {
161 printf("VBE bios does not provide a mode list\n");
165 /* also find a mapping from mode 0x13 (320x200x256) to VESA BIOS */
166 install_320x200x256_remap();
168 for (entry=0;entry < 1024;entry++) {
169 struct vbe_mode_info mi={0},nmi;
170 uint16_t nmode,tnmode;
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;
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);
183 /* look for a target mode to remap to */
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;
198 if (mi.y_resolution < 240 && nmi.y_resolution == 240) {
199 /* found one: should remap 320x200 -> 320x240 */
203 else if (mi.y_resolution >= 240 && nmi.y_resolution == 480) {
204 /* found one: should remap 320/640x350/400 to 320/640x480 */
211 printf(" Remap to 0x%03x (%ux%ux%u)\n",nmode,
212 nmi.x_resolution,nmi.y_resolution,nmi.bits_per_pixel);
215 printf(" Remap to nothing\n");
218 if (remap_count >= MAX_REMAP) break;
219 remap[remap_count].source_mode = mode&0x3FFF;
220 remap[remap_count].target_mode = nmode&0x3FFF;
225 if (remap_count == 0) {
226 printf("Nothing to remap\n");
231 old_int10 = _dos_getvect(0x10);
232 _dos_setvect(0x10,new_int10);
234 printf("INT 10h hooked\n"); fflush(stdout);
235 _dos_keep(0,(34000+sizeof(remap))>>4); /* FIXME! */
239 void end_of_resident() {