1 /*
2 * Copyright (C) 2002-2015 The DOSBox Team
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19
20 #include "dosbox.h"
21 #include "mem.h"
22 #include "callback.h"
23 #include "regs.h"
24 #include "inout.h"
25 #include "int10.h"
26 #include "mouse.h"
27 #include "setup.h"
28
29 Int10Data int10;
30 static Bitu call_10;
31 static bool warned_ff=false;
32
INT10_Handler(void)33 static Bitu INT10_Handler(void) {
34 #if 0
35 switch (reg_ah) {
36 case 0x02:
37 case 0x03:
38 case 0x09:
39 case 0xc:
40 case 0xd:
41 case 0x0e:
42 case 0x10:
43 case 0x4f:
44
45 break;
46 default:
47 LOG(LOG_INT10,LOG_NORMAL)("Function AX:%04X , BX %04X DX %04X",reg_ax,reg_bx,reg_dx);
48 break;
49 }
50 #endif
51 INT10_SetCurMode();
52
53 switch (reg_ah) {
54 case 0x00: /* Set VideoMode */
55 Mouse_BeforeNewVideoMode(true);
56 INT10_SetVideoMode(reg_al);
57 Mouse_AfterNewVideoMode(true);
58 break;
59 case 0x01: /* Set TextMode Cursor Shape */
60 INT10_SetCursorShape(reg_ch,reg_cl);
61 break;
62 case 0x02: /* Set Cursor Pos */
63 INT10_SetCursorPos(reg_dh,reg_dl,reg_bh);
64 break;
65 case 0x03: /* get Cursor Pos and Cursor Shape*/
66 // reg_ah=0;
67 reg_dl=CURSOR_POS_COL(reg_bh);
68 reg_dh=CURSOR_POS_ROW(reg_bh);
69 reg_cx=real_readw(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE);
70 break;
71 case 0x04: /* read light pen pos YEAH RIGHT */
72 /* Light pen is not supported */
73 reg_ax=0;
74 break;
75 case 0x05: /* Set Active Page */
76 if ((reg_al & 0x80) && IS_TANDY_ARCH) {
77 Bit8u crtcpu=real_readb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE);
78 switch (reg_al) {
79 case 0x80:
80 reg_bh=crtcpu & 7;
81 reg_bl=(crtcpu >> 3) & 0x7;
82 break;
83 case 0x81:
84 crtcpu=(crtcpu & 0xc7) | ((reg_bl & 7) << 3);
85 break;
86 case 0x82:
87 crtcpu=(crtcpu & 0xf8) | (reg_bh & 7);
88 break;
89 case 0x83:
90 crtcpu=(crtcpu & 0xc0) | (reg_bh & 7) | ((reg_bl & 7) << 3);
91 break;
92 }
93 if (machine==MCH_PCJR) {
94 /* always return graphics mapping, even for invalid values of AL */
95 reg_bh=crtcpu & 7;
96 reg_bl=(crtcpu >> 3) & 0x7;
97 }
98 IO_WriteB(0x3df,crtcpu);
99 real_writeb(BIOSMEM_SEG, BIOSMEM_CRTCPU_PAGE,crtcpu);
100 }
101 else INT10_SetActivePage(reg_al);
102 break;
103 case 0x06: /* Scroll Up */
104 INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,-reg_al,reg_bh,0xFF);
105 break;
106 case 0x07: /* Scroll Down */
107 INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF);
108 break;
109 case 0x08: /* Read character & attribute at cursor */
110 INT10_ReadCharAttr(®_ax,reg_bh);
111 break;
112 case 0x09: /* Write Character & Attribute at cursor CX times */
113 if (real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)==0x11)
114 INT10_WriteChar(reg_al,(reg_bl&0x80)|0x3f,reg_bh,reg_cx,true);
115 else INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,true);
116 break;
117 case 0x0A: /* Write Character at cursor CX times */
118 INT10_WriteChar(reg_al,reg_bl,reg_bh,reg_cx,false);
119 break;
120 case 0x0B: /* Set Background/Border Colour & Set Palette*/
121 switch (reg_bh) {
122 case 0x00: //Background/Border color
123 INT10_SetBackgroundBorder(reg_bl);
124 break;
125 case 0x01: //Set color Select
126 default:
127 INT10_SetColorSelect(reg_bl);
128 break;
129 }
130 break;
131 case 0x0C: /* Write Graphics Pixel */
132 INT10_PutPixel(reg_cx,reg_dx,reg_bh,reg_al);
133 break;
134 case 0x0D: /* Read Graphics Pixel */
135 INT10_GetPixel(reg_cx,reg_dx,reg_bh,®_al);
136 break;
137 case 0x0E: /* Teletype OutPut */
138 INT10_TeletypeOutput(reg_al,reg_bl);
139 break;
140 case 0x0F: /* Get videomode */
141 reg_bh=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
142 reg_al=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)|(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)&0x80);
143 reg_ah=(Bit8u)real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
144 break;
145 case 0x10: /* Palette functions */
146 if (!IS_EGAVGA_ARCH && (reg_al>0x02)) break;
147 else if (!IS_VGA_ARCH && (reg_al>0x03)) break;
148 switch (reg_al) {
149 case 0x00: /* SET SINGLE PALETTE REGISTER */
150 INT10_SetSinglePaletteRegister(reg_bl,reg_bh);
151 break;
152 case 0x01: /* SET BORDER (OVERSCAN) COLOR*/
153 INT10_SetOverscanBorderColor(reg_bh);
154 break;
155 case 0x02: /* SET ALL PALETTE REGISTERS */
156 INT10_SetAllPaletteRegisters(SegPhys(es)+reg_dx);
157 break;
158 case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
159 INT10_ToggleBlinkingBit(reg_bl);
160 break;
161 case 0x07: /* GET SINGLE PALETTE REGISTER */
162 INT10_GetSinglePaletteRegister(reg_bl,®_bh);
163 break;
164 case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER */
165 INT10_GetOverscanBorderColor(®_bh);
166 break;
167 case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */
168 INT10_GetAllPaletteRegisters(SegPhys(es)+reg_dx);
169 break;
170 case 0x10: /* SET INDIVIDUAL DAC REGISTER */
171 INT10_SetSingleDACRegister(reg_bl,reg_dh,reg_ch,reg_cl);
172 break;
173 case 0x12: /* SET BLOCK OF DAC REGISTERS */
174 INT10_SetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
175 break;
176 case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
177 INT10_SelectDACPage(reg_bl,reg_bh);
178 break;
179 case 0x15: /* GET INDIVIDUAL DAC REGISTER */
180 INT10_GetSingleDACRegister(reg_bl,®_dh,®_ch,®_cl);
181 break;
182 case 0x17: /* GET BLOCK OF DAC REGISTER */
183 INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
184 break;
185 case 0x18: /* undocumented - SET PEL MASK */
186 INT10_SetPelMask(reg_bl);
187 break;
188 case 0x19: /* undocumented - GET PEL MASK */
189 INT10_GetPelMask(reg_bl);
190 reg_bh=0; // bx for get mask
191 break;
192 case 0x1A: /* GET VIDEO DAC COLOR PAGE */
193 INT10_GetDACPage(®_bl,®_bh);
194 break;
195 case 0x1B: /* PERFORM GRAY-SCALE SUMMING */
196 INT10_PerformGrayScaleSumming(reg_bx,reg_cx);
197 break;
198 case 0xF0: /* ET4000: SET HiColor GRAPHICS MODE */
199 case 0xF1: /* ET4000: GET DAC TYPE */
200 case 0xF2: /* ET4000: CHECK/SET HiColor MODE */
201 default:
202 LOG(LOG_INT10,LOG_ERROR)("Function 10:Unhandled EGA/VGA Palette Function %2X",reg_al);
203 break;
204 }
205 break;
206 case 0x11: /* Character generator functions */
207 if (!IS_EGAVGA_ARCH)
208 break;
209 if ((reg_al&0xf0)==0x10) Mouse_BeforeNewVideoMode(false);
210 switch (reg_al) {
211 /* Textmode calls */
212 case 0x00: /* Load user font */
213 case 0x10:
214 INT10_LoadFont(SegPhys(es)+reg_bp,reg_al==0x10,reg_cx,reg_dx,reg_bl&0x7f,reg_bh);
215 break;
216 case 0x01: /* Load 8x14 font */
217 case 0x11:
218 INT10_LoadFont(Real2Phys(int10.rom.font_14),reg_al==0x11,256,0,reg_bl&0x7f,14);
219 break;
220 case 0x02: /* Load 8x8 font */
221 case 0x12:
222 INT10_LoadFont(Real2Phys(int10.rom.font_8_first),reg_al==0x12,256,0,reg_bl&0x7f,8);
223 break;
224 case 0x03: /* Set Block Specifier */
225 IO_Write(0x3c4,0x3);IO_Write(0x3c5,reg_bl);
226 break;
227 case 0x04: /* Load 8x16 font */
228 case 0x14:
229 if (!IS_VGA_ARCH) break;
230 INT10_LoadFont(Real2Phys(int10.rom.font_16),reg_al==0x14,256,0,reg_bl&0x7f,16);
231 break;
232 /* Graphics mode calls */
233 case 0x20: /* Set User 8x8 Graphics characters */
234 RealSetVec(0x1f,RealMake(SegValue(es),reg_bp));
235 break;
236 case 0x21: /* Set user graphics characters */
237 RealSetVec(0x43,RealMake(SegValue(es),reg_bp));
238 real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,reg_cx);
239 goto graphics_chars;
240 case 0x22: /* Rom 8x14 set */
241 RealSetVec(0x43,int10.rom.font_14);
242 real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,14);
243 goto graphics_chars;
244 case 0x23: /* Rom 8x8 double dot set */
245 RealSetVec(0x43,int10.rom.font_8_first);
246 real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,8);
247 goto graphics_chars;
248 case 0x24: /* Rom 8x16 set */
249 if (!IS_VGA_ARCH) break;
250 RealSetVec(0x43,int10.rom.font_16);
251 real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,16);
252 goto graphics_chars;
253 graphics_chars:
254 switch (reg_bl) {
255 case 0x00:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,reg_dl-1);break;
256 case 0x01:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,13);break;
257 case 0x03:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,42);break;
258 case 0x02:
259 default:real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,24);break;
260 }
261 break;
262 /* General */
263 case 0x30:/* Get Font Information */
264 switch (reg_bh) {
265 case 0x00: /* interupt 0x1f vector */
266 {
267 RealPt int_1f=RealGetVec(0x1f);
268 SegSet16(es,RealSeg(int_1f));
269 reg_bp=RealOff(int_1f);
270 }
271 break;
272 case 0x01: /* interupt 0x43 vector */
273 {
274 RealPt int_43=RealGetVec(0x43);
275 SegSet16(es,RealSeg(int_43));
276 reg_bp=RealOff(int_43);
277 }
278 break;
279 case 0x02: /* font 8x14 */
280 SegSet16(es,RealSeg(int10.rom.font_14));
281 reg_bp=RealOff(int10.rom.font_14);
282 break;
283 case 0x03: /* font 8x8 first 128 */
284 SegSet16(es,RealSeg(int10.rom.font_8_first));
285 reg_bp=RealOff(int10.rom.font_8_first);
286 break;
287 case 0x04: /* font 8x8 second 128 */
288 SegSet16(es,RealSeg(int10.rom.font_8_second));
289 reg_bp=RealOff(int10.rom.font_8_second);
290 break;
291 case 0x05: /* alpha alternate 9x14 */
292 SegSet16(es,RealSeg(int10.rom.font_14_alternate));
293 reg_bp=RealOff(int10.rom.font_14_alternate);
294 break;
295 case 0x06: /* font 8x16 */
296 if (!IS_VGA_ARCH) break;
297 SegSet16(es,RealSeg(int10.rom.font_16));
298 reg_bp=RealOff(int10.rom.font_16);
299 break;
300 case 0x07: /* alpha alternate 9x16 */
301 if (!IS_VGA_ARCH) break;
302 SegSet16(es,RealSeg(int10.rom.font_16_alternate));
303 reg_bp=RealOff(int10.rom.font_16_alternate);
304 break;
305 default:
306 LOG(LOG_INT10,LOG_ERROR)("Function 11:30 Request for font %2X",reg_bh);
307 break;
308 }
309 if ((reg_bh<=7) || (svgaCard==SVGA_TsengET4K)) {
310 reg_cx=real_readw(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
311 reg_dl=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS);
312 }
313 break;
314 default:
315 LOG(LOG_INT10,LOG_ERROR)("Function 11:Unsupported character generator call %2X",reg_al);
316 break;
317 }
318 if ((reg_al&0xf0)==0x10) Mouse_AfterNewVideoMode(false);
319 break;
320 case 0x12: /* alternate function select */
321 if (!IS_EGAVGA_ARCH)
322 break;
323 switch (reg_bl) {
324 case 0x10: /* Get EGA Information */
325 reg_bh=(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)==0x3B4);
326 reg_bl=3; //256 kb
327 reg_cl=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) & 0x0F;
328 reg_ch=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) >> 4;
329 break;
330 case 0x20: /* Set alternate printscreen */
331 break;
332 case 0x30: /* Select vertical resolution */
333 {
334 if (!IS_VGA_ARCH) break;
335 LOG(LOG_INT10,LOG_WARN)("Function 12:Call %2X (select vertical resolution)",reg_bl);
336 if (svgaCard != SVGA_None) {
337 if (reg_al > 2) {
338 reg_al=0; // invalid subfunction
339 break;
340 }
341 }
342 Bit8u modeset_ctl = real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
343 Bit8u video_switches = real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES)&0xf0;
344 switch(reg_al) {
345 case 0: // 200
346 modeset_ctl &= 0xef;
347 modeset_ctl |= 0x80;
348 video_switches |= 8; // ega normal/cga emulation
349 break;
350 case 1: // 350
351 modeset_ctl &= 0x6f;
352 video_switches |= 9; // ega enhanced
353 break;
354 case 2: // 400
355 modeset_ctl &= 0x6f;
356 modeset_ctl |= 0x10; // use 400-line mode at next mode set
357 video_switches |= 9; // ega enhanced
358 break;
359 default:
360 modeset_ctl &= 0xef;
361 video_switches |= 8; // ega normal/cga emulation
362 break;
363 }
364 real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset_ctl);
365 real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,video_switches);
366 reg_al=0x12; // success
367 break;
368 }
369 case 0x31: /* Palette loading on modeset */
370 {
371 if (!IS_VGA_ARCH) break;
372 if (svgaCard==SVGA_TsengET4K) reg_al&=1;
373 if (reg_al>1) {
374 reg_al=0; //invalid subfunction
375 break;
376 }
377 Bit8u temp = real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 0xf7;
378 if (reg_al&1) temp|=8; // enable if al=0
379 real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,temp);
380 reg_al=0x12;
381 break;
382 }
383 case 0x32: /* Video addressing */
384 if (!IS_VGA_ARCH) break;
385 LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl);
386 if (svgaCard==SVGA_TsengET4K) reg_al&=1;
387 if (reg_al>1) reg_al=0; //invalid subfunction
388 else reg_al=0x12; //fake a success call
389 break;
390 case 0x33: /* SWITCH GRAY-SCALE SUMMING */
391 {
392 if (!IS_VGA_ARCH) break;
393 if (svgaCard==SVGA_TsengET4K) reg_al&=1;
394 if (reg_al>1) {
395 reg_al=0;
396 break;
397 }
398 Bit8u temp = real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 0xfd;
399 if (!(reg_al&1)) temp|=2; // enable if al=0
400 real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,temp);
401 reg_al=0x12;
402 break;
403 }
404 case 0x34: /* ALTERNATE FUNCTION SELECT (VGA) - CURSOR EMULATION */
405 {
406 // bit 0: 0=enable, 1=disable
407 if (!IS_VGA_ARCH) break;
408 if (svgaCard==SVGA_TsengET4K) reg_al&=1;
409 if (reg_al>1) {
410 reg_al=0;
411 break;
412 }
413 Bit8u temp = real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0xfe;
414 real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,temp|reg_al);
415 reg_al=0x12;
416 break;
417 }
418 case 0x35:
419 if (!IS_VGA_ARCH) break;
420 LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl);
421 reg_al=0x12;
422 break;
423 case 0x36: { /* VGA Refresh control */
424 if (!IS_VGA_ARCH) break;
425 if ((svgaCard==SVGA_S3Trio) && (reg_al>1)) {
426 reg_al=0;
427 break;
428 }
429 IO_Write(0x3c4,0x1);
430 Bit8u clocking = IO_Read(0x3c5);
431
432 if (reg_al==0) clocking &= ~0x20;
433 else clocking |= 0x20;
434
435 IO_Write(0x3c4,0x1);
436 IO_Write(0x3c5,clocking);
437
438 reg_al=0x12; // success
439 break;
440 }
441 default:
442 LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl);
443 if (machine!=MCH_EGA) reg_al=0;
444 break;
445 }
446 break;
447 case 0x13: /* Write String */
448 INT10_WriteString(reg_dh,reg_dl,reg_al,reg_bl,SegPhys(es)+reg_bp,reg_cx,reg_bh);
449 break;
450 case 0x1A: /* Display Combination */
451 if (!IS_VGA_ARCH) break;
452 if (reg_al==0) { // get dcc
453 // walk the tables...
454 RealPt vsavept=real_readd(BIOSMEM_SEG,BIOSMEM_VS_POINTER);
455 RealPt svstable=real_readd(RealSeg(vsavept),RealOff(vsavept)+0x10);
456 if (svstable) {
457 RealPt dcctable=real_readd(RealSeg(svstable),RealOff(svstable)+0x02);
458 Bit8u entries=real_readb(RealSeg(dcctable),RealOff(dcctable)+0x00);
459 Bit8u idx=real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX);
460 // check if index within range
461 if (idx<entries) {
462 Bit16u dccentry=real_readw(RealSeg(dcctable),RealOff(dcctable)+0x04+idx*2);
463 if ((dccentry&0xff)==0) reg_bx=dccentry>>8;
464 else reg_bx=dccentry;
465 } else reg_bx=0xffff;
466 } else reg_bx=0xffff;
467 reg_ax=0x1A; // high part destroyed or zeroed depending on BIOS
468 } else if (reg_al==1) { // set dcc
469 Bit8u newidx=0xff;
470 // walk the tables...
471 RealPt vsavept=real_readd(BIOSMEM_SEG,BIOSMEM_VS_POINTER);
472 RealPt svstable=real_readd(RealSeg(vsavept),RealOff(vsavept)+0x10);
473 if (svstable) {
474 RealPt dcctable=real_readd(RealSeg(svstable),RealOff(svstable)+0x02);
475 Bit8u entries=real_readb(RealSeg(dcctable),RealOff(dcctable)+0x00);
476 if (entries) {
477 Bitu ct;
478 Bit16u swpidx=reg_bh|(reg_bl<<8);
479 // search the ddc index in the dcc table
480 for (ct=0; ct<entries; ct++) {
481 Bit16u dccentry=real_readw(RealSeg(dcctable),RealOff(dcctable)+0x04+ct*2);
482 if ((dccentry==reg_bx) || (dccentry==swpidx)) {
483 newidx=(Bit8u)ct;
484 break;
485 }
486 }
487 }
488 }
489
490 real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,newidx);
491 reg_ax=0x1A; // high part destroyed or zeroed depending on BIOS
492 }
493 break;
494 case 0x1B: /* functionality State Information */
495 if (!IS_VGA_ARCH) break;
496 switch (reg_bx) {
497 case 0x0000:
498 INT10_GetFuncStateInformation(SegPhys(es)+reg_di);
499 reg_al=0x1B;
500 break;
501 default:
502 LOG(LOG_INT10,LOG_ERROR)("1B:Unhandled call BX %2X",reg_bx);
503 reg_al=0;
504 break;
505 }
506 break;
507 case 0x1C: /* Video Save Area */
508 if (!IS_VGA_ARCH) break;
509 switch (reg_al) {
510 case 0: {
511 Bitu ret=INT10_VideoState_GetSize(reg_cx);
512 if (ret) {
513 reg_al=0x1c;
514 reg_bx=(Bit16u)ret;
515 } else reg_al=0;
516 }
517 break;
518 case 1:
519 if (INT10_VideoState_Save(reg_cx,RealMake(SegValue(es),reg_bx))) reg_al=0x1c;
520 else reg_al=0;
521 break;
522 case 2:
523 if (INT10_VideoState_Restore(reg_cx,RealMake(SegValue(es),reg_bx))) reg_al=0x1c;
524 else reg_al=0;
525 break;
526 default:
527 if (svgaCard==SVGA_TsengET4K) reg_ax=0;
528 else reg_al=0;
529 break;
530 }
531 break;
532 case 0x4f: /* VESA Calls */
533 if ((!IS_VGA_ARCH) || (svgaCard!=SVGA_S3Trio)) break;
534 switch (reg_al) {
535 case 0x00: /* Get SVGA Information */
536 reg_al=0x4f;
537 reg_ah=VESA_GetSVGAInformation(SegValue(es),reg_di);
538 break;
539 case 0x01: /* Get SVGA Mode Information */
540 reg_al=0x4f;
541 reg_ah=VESA_GetSVGAModeInformation(reg_cx,SegValue(es),reg_di);
542 break;
543 case 0x02: /* Set videomode */
544 Mouse_BeforeNewVideoMode(true);
545 reg_al=0x4f;
546 reg_ah=VESA_SetSVGAMode(reg_bx);
547 Mouse_AfterNewVideoMode(true);
548 break;
549 case 0x03: /* Get videomode */
550 reg_al=0x4f;
551 reg_ah=VESA_GetSVGAMode(reg_bx);
552 break;
553 case 0x04: /* Save/restore state */
554 reg_al=0x4f;
555 switch (reg_dl) {
556 case 0: {
557 Bitu ret=INT10_VideoState_GetSize(reg_cx);
558 if (ret) {
559 reg_ah=0;
560 reg_bx=(Bit16u)ret;
561 } else reg_ah=1;
562 }
563 break;
564 case 1:
565 if (INT10_VideoState_Save(reg_cx,RealMake(SegValue(es),reg_bx))) reg_ah=0;
566 else reg_ah=1;
567 break;
568 case 2:
569 if (INT10_VideoState_Restore(reg_cx,RealMake(SegValue(es),reg_bx))) reg_ah=0;
570 else reg_ah=1;
571 break;
572 default:
573 reg_ah=1;
574 break;
575 }
576 break;
577 case 0x05:
578 if (reg_bh==0) { /* Set CPU Window */
579 reg_ah=VESA_SetCPUWindow(reg_bl,reg_dl);
580 reg_al=0x4f;
581 } else if (reg_bh == 1) { /* Get CPU Window */
582 reg_ah=VESA_GetCPUWindow(reg_bl,reg_dx);
583 reg_al=0x4f;
584 } else {
585 LOG(LOG_INT10,LOG_ERROR)("Unhandled VESA Function %X Subfunction %X",reg_al,reg_bh);
586 reg_ah=0x01;
587 }
588 break;
589 case 0x06:
590 reg_al=0x4f;
591 reg_ah=VESA_ScanLineLength(reg_bl,reg_cx,reg_bx,reg_cx,reg_dx);
592 break;
593 case 0x07:
594 switch (reg_bl) {
595 case 0x80: /* Set Display Start during retrace ?? */
596 case 0x00: /* Set display Start */
597 reg_al=0x4f;
598 reg_ah=VESA_SetDisplayStart(reg_cx,reg_dx);
599 break;
600 case 0x01:
601 reg_al=0x4f;
602 reg_bh=0x00; //reserved
603 reg_ah=VESA_GetDisplayStart(reg_cx,reg_dx);
604 break;
605 default:
606 LOG(LOG_INT10,LOG_ERROR)("Unhandled VESA Function %X Subfunction %X",reg_al,reg_bl);
607 reg_ah=0x1;
608 break;
609 }
610 break;
611 case 0x09:
612 switch (reg_bl) {
613 case 0x80: /* Set Palette during retrace */
614 //TODO
615 case 0x00: /* Set Palette */
616 reg_ah=VESA_SetPalette(SegPhys(es)+reg_di,reg_dx,reg_cx);
617 reg_al=0x4f;
618 break;
619 case 0x01: /* Get Palette */
620 reg_ah=VESA_GetPalette(SegPhys(es)+reg_di,reg_dx,reg_cx);
621 reg_al=0x4f;
622 break;
623 default:
624 LOG(LOG_INT10,LOG_ERROR)("Unhandled VESA Function %X Subfunction %X",reg_al,reg_bl);
625 reg_ah=0x01;
626 break;
627 }
628 break;
629 case 0x0a: /* Get Pmode Interface */
630 if (int10.vesa_oldvbe) {
631 reg_ax=0x014f;
632 break;
633 }
634 switch (reg_bl) {
635 case 0x00:
636 reg_edi=RealOff(int10.rom.pmode_interface);
637 SegSet16(es,RealSeg(int10.rom.pmode_interface));
638 reg_cx=int10.rom.pmode_interface_size;
639 reg_ax=0x004f;
640 break;
641 case 0x01: /* Get code for "set window" */
642 reg_edi=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_window;
643 SegSet16(es,RealSeg(int10.rom.pmode_interface));
644 reg_cx=0x10; //0x10 should be enough for the callbacks
645 reg_ax=0x004f;
646 break;
647 case 0x02: /* Get code for "set display start" */
648 reg_edi=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_start;
649 SegSet16(es,RealSeg(int10.rom.pmode_interface));
650 reg_cx=0x10; //0x10 should be enough for the callbacks
651 reg_ax=0x004f;
652 break;
653 case 0x03: /* Get code for "set palette" */
654 reg_edi=RealOff(int10.rom.pmode_interface)+int10.rom.pmode_interface_palette;
655 SegSet16(es,RealSeg(int10.rom.pmode_interface));
656 reg_cx=0x10; //0x10 should be enough for the callbacks
657 reg_ax=0x004f;
658 break;
659 default:
660 reg_ax=0x014f;
661 break;
662 }
663 break;
664
665 default:
666 LOG(LOG_INT10,LOG_ERROR)("Unhandled VESA Function %X",reg_al);
667 reg_al=0x0;
668 break;
669 }
670 break;
671 case 0xf0:
672 INT10_EGA_RIL_ReadRegister(reg_bl, reg_dx);
673 break;
674 case 0xf1:
675 INT10_EGA_RIL_WriteRegister(reg_bl, reg_bh, reg_dx);
676 break;
677 case 0xf2:
678 INT10_EGA_RIL_ReadRegisterRange(reg_ch, reg_cl, reg_dx, SegPhys(es)+reg_bx);
679 break;
680 case 0xf3:
681 INT10_EGA_RIL_WriteRegisterRange(reg_ch, reg_cl, reg_dx, SegPhys(es)+reg_bx);
682 break;
683 case 0xf4:
684 INT10_EGA_RIL_ReadRegisterSet(reg_cx, SegPhys(es)+reg_bx);
685 break;
686 case 0xf5:
687 INT10_EGA_RIL_WriteRegisterSet(reg_cx, SegPhys(es)+reg_bx);
688 break;
689 case 0xfa: {
690 RealPt pt=INT10_EGA_RIL_GetVersionPt();
691 SegSet16(es,RealSeg(pt));
692 reg_bx=RealOff(pt);
693 }
694 break;
695 case 0xff:
696 if (!warned_ff) LOG(LOG_INT10,LOG_NORMAL)("INT10:FF:Weird NC call");
697 warned_ff=true;
698 break;
699 default:
700 LOG(LOG_INT10,LOG_ERROR)("Function %4X not supported",reg_ax);
701 // reg_al=0x00; //Successfull, breaks marriage
702 break;
703 };
704 return CBRET_NONE;
705 }
706
INT10_Seg40Init(void)707 static void INT10_Seg40Init(void) {
708 // the default char height
709 real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,16);
710 // Clear the screen
711 real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,0x60);
712 // Set the basic screen we have
713 real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
714 // Set the basic modeset options
715 real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,0x51);
716 // Set the default MSR
717 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x09);
718 // Set the pointer to video save pointer table
719 real_writed(BIOSMEM_SEG,BIOSMEM_VS_POINTER,int10.rom.video_save_pointers);
720 }
721
722
INT10_InitVGA(void)723 static void INT10_InitVGA(void) {
724 if (IS_EGAVGA_ARCH) {
725 /* switch to color mode and enable CPU access 480 lines */
726 IO_Write(0x3c2,0xc3);
727 /* More than 64k */
728 IO_Write(0x3c4,0x04);
729 IO_Write(0x3c5,0x02);
730 if (IS_VGA_ARCH) {
731 /* Initialize DAC */
732 IO_Write(0x3c8,0);
733 for (Bitu i=0;i<3*256;i++) IO_Write(0x3c9,0);
734 }
735 }
736 }
737
SetupTandyBios(void)738 static void SetupTandyBios(void) {
739 static Bit8u TandyConfig[130]= {
740 0x21, 0x42, 0x49, 0x4f, 0x53, 0x20, 0x52, 0x4f, 0x4d, 0x20, 0x76, 0x65, 0x72,
741 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x30, 0x32, 0x2e, 0x30, 0x30, 0x2e, 0x30, 0x30,
742 0x0d, 0x0a, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69,
743 0x74, 0x79, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0d, 0x0a,
744 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29,
745 0x20, 0x31, 0x39, 0x38, 0x34, 0x2c, 0x31, 0x39, 0x38, 0x35, 0x2c, 0x31, 0x39,
746 0x38, 0x36, 0x2c, 0x31, 0x39, 0x38, 0x37, 0x0d, 0x0a, 0x50, 0x68, 0x6f, 0x65,
747 0x6e, 0x69, 0x78, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20,
748 0x41, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x73, 0x20, 0x4c, 0x74,
749 0x64, 0x2e, 0x0d, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x61, 0x6e, 0x64, 0x79
750 };
751 if (machine==MCH_TANDY) {
752 Bitu i;
753 for(i=0;i<130;i++) {
754 phys_writeb(0xf0000+i+0xc000, TandyConfig[i]);
755 }
756 }
757 }
758
INT10_Init(Section *)759 void INT10_Init(Section* /*sec*/) {
760 INT10_InitVGA();
761 if (IS_TANDY_ARCH) SetupTandyBios();
762 /* Setup the INT 10 vector */
763 call_10=CALLBACK_Allocate();
764 CALLBACK_Setup(call_10,&INT10_Handler,CB_IRET,"Int 10 video");
765 RealSetVec(0x10,CALLBACK_RealPointer(call_10));
766 //Init the 0x40 segment and init the datastructures in the the video rom area
767 INT10_SetupRomMemory();
768 INT10_Seg40Init();
769 INT10_SetVideoMode(0x3);
770 }
771