- init functions rewitten in assembler
[vgabios.git] / vgabios.c
blobc0636c2c908cd6ffb653a4b00dabe6a8e636a50a
1 // ============================================================================================
2 /*
3 * vgabios.c
4 */
5 // ============================================================================================
6 //
7 // Copyright (C) 2001,2002 the LGPL VGABios developers Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // ============================================================================================
24 //
25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26 // You can NOT drive any physical vga card with it.
27 //
28 // ============================================================================================
29 //
30 // This file contains code ripped from :
31 // - rombios.c of plex86
33 // This VGA Bios contains fonts from :
34 // - fntcol16.zip (c) by Joseph Gil avalable at :
35 // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
36 // These fonts are public domain
38 // This VGA Bios is based on information taken from :
39 // - Kevin Lawton's vga card emulation for bochs/plex86
40 // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
41 // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
42 // - Michael Abrash's Graphics Programming Black Book
43 // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
44 // - DOSEMU 1.0.1 source code for several tables values and formulas
46 // Thanks for patches, comments and ideas to :
47 // - techt@pikeonline.net
49 // ============================================================================================
51 #include "vgabios.h"
53 #ifdef VBE
54 #include "vbe.h"
55 #endif
57 /* Declares */
58 static Bit8u read_byte();
59 static Bit16u read_word();
60 static void write_byte();
61 static void write_word();
62 static Bit8u inb();
63 static Bit16u inw();
64 static void outb();
65 static void outw();
67 static Bit16u get_SS();
69 // Output
70 static void printf();
71 static void unimplemented();
72 static void unknown();
74 static Bit8u find_vga_entry();
76 static void memsetb();
77 static void memsetw();
78 static void memcpyb();
79 static void memcpyw();
81 static void biosfn_set_video_mode();
82 static void biosfn_set_cursor_shape();
83 static void biosfn_set_cursor_pos();
84 static void biosfn_get_cursor_pos();
85 static void biosfn_set_active_page();
86 static void biosfn_scroll();
87 static void biosfn_read_char_attr();
88 static void biosfn_write_char_attr();
89 static void biosfn_write_char_only();
90 static void biosfn_set_border_color();
91 static void biosfn_set_palette();
92 static void biosfn_write_pixel();
93 static void biosfn_read_pixel();
94 static void biosfn_write_teletype();
95 static void biosfn_set_single_palette_reg();
96 static void biosfn_set_overscan_border_color();
97 static void biosfn_set_all_palette_reg();
98 static void biosfn_toggle_intensity();
99 static void biosfn_get_single_palette_reg();
100 static void biosfn_read_overscan_border_color();
101 static void biosfn_get_all_palette_reg();
102 static void biosfn_set_single_dac_reg();
103 static void biosfn_set_all_dac_reg();
104 static void biosfn_select_video_dac_color_page();
105 static void biosfn_read_single_dac_reg();
106 static void biosfn_read_all_dac_reg();
107 static void biosfn_set_pel_mask();
108 static void biosfn_read_pel_mask();
109 static void biosfn_read_video_dac_state();
110 static void biosfn_perform_gray_scale_summing();
111 static void biosfn_load_text_user_pat();
112 static void biosfn_load_text_8_14_pat();
113 static void biosfn_load_text_8_8_pat();
114 static void biosfn_set_text_block_specifier();
115 static void biosfn_load_text_8_16_pat();
116 static void biosfn_load_gfx_8_8_chars();
117 static void biosfn_load_gfx_user_chars();
118 static void biosfn_load_gfx_8_14_chars();
119 static void biosfn_load_gfx_8_8_dd_chars();
120 static void biosfn_load_gfx_8_16_chars();
121 static void biosfn_get_font_info();
122 static void biosfn_get_ega_info();
123 static void biosfn_alternate_prtsc();
124 static void biosfn_select_vert_res();
125 static void biosfn_enable_default_palette_loading();
126 static void biosfn_enable_video_addressing();
127 static void biosfn_enable_grayscale_summing();
128 static void biosfn_enable_cursor_emulation();
129 static void biosfn_switch_video_interface();
130 static void biosfn_enable_video_refresh_control();
131 static void biosfn_write_string();
132 static void biosfn_read_state_info();
133 static void biosfn_read_video_state_size();
134 static void biosfn_save_video_state();
135 static void biosfn_restore_video_state();
137 // This is for compiling with gcc2 and gcc3
138 #define ASM_START #asm
139 #define ASM_END #endasm
141 ASM_START
143 biosmem_seg = 0x40
144 biosmem_initial_mode = 0x10
145 biosmem_current_mode = 0x49
146 biosmem_nb_cols = 0x4a
147 biosmem_current_page = 0x62
148 biosmem_current_msr = 0x65
149 biosmem_char_height = 0x85
150 biosmem_video_ctl = 0x87
151 biosmem_switches = 0x88
152 biosmem_modeset_ctl = 0x89
153 biosmem_dcc_index = 0x8a
155 MACRO SET_INT_VECTOR
156 push ds
157 xor ax, ax
158 mov ds, ax
159 mov ax, ?3
160 mov ?1*4, ax
161 mov ax, ?2
162 mov ?1*4+2, ax
163 pop ds
164 MEND
166 ASM_END
168 ASM_START
169 .text
170 .rom
171 .org 0
173 use16 386
175 vgabios_start:
176 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
178 .byte 0x40 /* BIOS extension length in units of 512 bytes */
181 vgabios_entry_point:
183 jmp vgabios_init_func
185 vgabios_name:
186 .ascii "Plex86/Bochs VGABios"
187 .ascii " "
188 .byte 0x00
190 // Info from Bart Oldeman
191 .org 0x1e
192 .ascii "IBM"
193 .byte 0x00
195 vgabios_version:
196 #ifndef VGABIOS_VERS
197 .ascii "current-cvs"
198 #else
199 .ascii VGABIOS_VERS
200 #endif
201 .ascii " "
203 vgabios_date:
204 .ascii VGABIOS_DATE
205 .byte 0x0a,0x0d
206 .byte 0x00
208 vgabios_copyright:
209 .ascii "(C) 2003 the LGPL VGABios developers Team"
210 .byte 0x0a,0x0d
211 .byte 0x00
213 vgabios_license:
214 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
215 .byte 0x0a,0x0d
216 .byte 0x0a,0x0d
217 .byte 0x00
219 vgabios_website:
220 .ascii "Please visit :"
221 .byte 0x0a,0x0d
222 ;;.ascii " . http://www.plex86.org"
223 ;;.byte 0x0a,0x0d
224 .ascii " . http://bochs.sourceforge.net"
225 .byte 0x0a,0x0d
226 .ascii " . http://www.nongnu.org/vgabios"
227 .byte 0x0a,0x0d
228 .byte 0x0a,0x0d
229 .byte 0x00
232 ;; ============================================================================================
234 ;; Init Entry point
236 ;; ============================================================================================
237 vgabios_init_func:
239 ;; init vga card
240 call init_vga_card
242 ;; init basic bios vars
243 call init_bios_area
245 #ifdef VBE
246 ;; init vbe functions
247 call _vbe_init
248 #endif
250 ;; set int10 vect
251 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
253 ;; display splash screen
254 call _display_splash_screen
256 ;; init video mode and clear the screen
257 mov ax,#0x0003
258 int #0x10
260 ;; show info
261 call _display_info
263 #ifdef VBE
264 ;; show vbe info
265 call _vbe_display_info
266 #endif
269 retf
270 ASM_END
273 * int10 handled here
275 ASM_START
276 vgabios_int10_handler:
277 pushf
278 cmp ah, #0x0f
279 jne int10_test_1A
280 call biosfn_get_video_mode
281 jmp int10_end
282 int10_test_1A:
283 cmp ah, #0x1a
284 jne int10_normal
285 call biosfn_group_1A
286 jmp int10_end
288 int10_normal:
289 push es
290 push ds
291 pusha
293 ;; We have to set ds to access the right data segment
294 mov bx, #0xc000
295 mov ds, bx
296 call _int10_func
298 popa
299 pop ds
300 pop es
301 int10_end:
302 popf
303 iret
304 ASM_END
306 #include "vgatables.h"
307 #include "vgafonts.h"
310 * Boot time harware inits
312 ASM_START
313 init_vga_card:
314 ;; switch to color mode and enable CPU access 480 lines
315 mov dx, #0x3C2
316 mov al, #0xC3
317 outb dx,al
319 ;; more than 64k 3C4/04
320 mov dx, #0x3C4
321 mov al, #0x04
322 outb dx,al
323 mov dx, #0x3C5
324 mov al, #0x02
325 outb dx,al
327 mov bx, #msg_vga_init
328 push bx
329 call _printf
330 inc sp
331 inc sp
334 msg_vga_init:
335 .ascii "VGABios $Id$"
336 .byte 0x0d,0x0a,0x00
337 ASM_END
339 // --------------------------------------------------------------------------------------------
341 * Boot time bios area inits
343 ASM_START
344 init_bios_area:
345 push ds
346 mov ax, #biosmem_seg
347 mov ds, ax
349 ;; init detected hardware BIOS Area
350 mov bx, #biosmem_initial_mode
351 mov ax, [bx]
352 and ax, #0xffcf
353 mov [bx], ax
355 ;; Just for the first int10 find its children
357 ;; the default char height
358 mov bx, #biosmem_char_height
359 mov al, #0x10
360 mov [bx], al
362 ;; Clear the screen
363 mov bx, #biosmem_video_ctl
364 mov al, #0x60
365 mov [bx], al
367 ;; Set the basic screen we have
368 mov bx, #biosmem_switches
369 mov al, #0xf9
370 mov [bx], al
372 ;; Set the basic modeset options
373 mov bx, #biosmem_modeset_cl
374 mov al, #0x51
375 mov [bx], al
377 ;; Set the default MSR
378 mov bx, #biosmem_current_msr
379 mov al, #0x09
380 mov [bx], al
382 pop ds
384 ASM_END
386 // --------------------------------------------------------------------------------------------
388 * Boot time Splash screen
390 static void display_splash_screen()
394 // --------------------------------------------------------------------------------------------
396 * Tell who we are
399 static void display_info()
401 ASM_START
402 mov ax,#0xc000
403 mov ds,ax
404 mov si,#vgabios_name
405 call _display_string
406 mov si,#vgabios_version
407 call _display_string
409 ;;mov si,#vgabios_copyright
410 ;;call _display_string
411 ;;mov si,#crlf
412 ;;call _display_string
414 mov si,#vgabios_license
415 call _display_string
416 mov si,#vgabios_website
417 call _display_string
418 ASM_END
421 static void display_string()
423 // Get length of string
424 ASM_START
425 mov ax,ds
426 mov es,ax
427 mov di,si
428 xor cx,cx
429 not cx
430 xor al,al
432 repne
433 scasb
434 not cx
435 dec cx
436 push cx
438 mov ax,#0x0300
439 mov bx,#0x0000
440 int #0x10
442 pop cx
443 mov ax,#0x1301
444 mov bx,#0x000b
445 mov bp,si
446 int #0x10
447 ASM_END
450 // --------------------------------------------------------------------------------------------
452 // --------------------------------------------------------------------------------------------
454 * int10 main dispatcher
456 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
457 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
459 #ifdef DEBUG
460 // 0E is write char...
461 if(GET_AH()!=0x0E)
462 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
463 #endif
465 // BIOS functions
466 switch(GET_AH())
468 case 0x00:
469 biosfn_set_video_mode(GET_AL());
470 switch(GET_AL()&0x7F)
471 {case 6:
472 SET_AL(0x3F);
473 break;
474 case 0:
475 case 1:
476 case 2:
477 case 3:
478 case 4:
479 case 5:
480 case 7:
481 SET_AL(0x30);
482 break;
483 default:
484 SET_AL(0x20);
486 break;
487 case 0x01:
488 biosfn_set_cursor_shape(GET_CH(),GET_CL());
489 break;
490 case 0x02:
491 biosfn_set_cursor_pos(GET_BH(),DX);
492 break;
493 case 0x03:
494 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
495 break;
496 case 0x04:
497 // Read light pen pos (unimplemented)
498 #ifdef DEBUG
499 unimplemented();
500 #endif
501 AX=0x00;
502 BX=0x00;
503 CX=0x00;
504 DX=0x00;
505 break;
506 case 0x05:
507 biosfn_set_active_page(GET_AL());
508 break;
509 case 0x06:
510 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
511 break;
512 case 0x07:
513 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
514 break;
515 case 0x08:
516 biosfn_read_char_attr(GET_BH(),&AX);
517 break;
518 case 0x09:
519 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
520 break;
521 case 0x0A:
522 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
523 break;
524 case 0x0B:
525 if(GET_BH()==0x00)
526 biosfn_set_border_color(GET_BL());
527 else
528 biosfn_set_palette(GET_BL());
529 break;
530 case 0x0C:
531 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
532 break;
533 case 0x0D:
534 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
535 break;
536 case 0x0E:
537 // Ralf Brown Interrupt list is WRONG on bh(page)
538 // We do output only on the current page !
539 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
540 break;
541 case 0x10:
542 switch(GET_AL())
544 case 0x00:
545 biosfn_set_single_palette_reg(GET_BL(),GET_BH());
546 break;
547 case 0x01:
548 biosfn_set_overscan_border_color(GET_BH());
549 break;
550 case 0x02:
551 biosfn_set_all_palette_reg(ES,DX);
552 break;
553 case 0x03:
554 biosfn_toggle_intensity(GET_BL());
555 break;
556 case 0x07:
557 biosfn_get_single_palette_reg(GET_BL(),&BX);
558 break;
559 case 0x08:
560 biosfn_read_overscan_border_color(&BX);
561 break;
562 case 0x09:
563 biosfn_get_all_palette_reg(ES,DX);
564 break;
565 case 0x10:
566 biosfn_set_single_dac_reg(BX,GET_CH(),GET_CL(),GET_DH());
567 break;
568 case 0x12:
569 biosfn_set_all_dac_reg(BX,CX,ES,DX);
570 break;
571 case 0x13:
572 biosfn_select_video_dac_color_page(GET_BL(),GET_BH());
573 break;
574 case 0x15:
575 biosfn_read_single_dac_reg(GET_BL(),&DX,&CX);
576 break;
577 case 0x17:
578 biosfn_read_all_dac_reg(BX,CX,ES,DX);
579 break;
580 case 0x18:
581 biosfn_set_pel_mask(GET_BL());
582 break;
583 case 0x19:
584 biosfn_read_pel_mask(&BX);
585 break;
586 case 0x1A:
587 biosfn_read_video_dac_state(&BX);
588 break;
589 case 0x1B:
590 biosfn_perform_gray_scale_summing(BX,CX);
591 break;
592 #ifdef DEBUG
593 default:
594 unknown();
595 #endif
597 break;
598 case 0x11:
599 switch(GET_AL())
601 case 0x00:
602 case 0x10:
603 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
604 break;
605 case 0x01:
606 case 0x11:
607 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
608 break;
609 case 0x02:
610 case 0x12:
611 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
612 break;
613 case 0x03:
614 biosfn_set_text_block_specifier(GET_BL());
615 break;
616 case 0x04:
617 case 0x14:
618 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
619 break;
620 case 0x20:
621 biosfn_load_gfx_8_8_chars(ES,BP);
622 break;
623 case 0x21:
624 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
625 break;
626 case 0x22:
627 biosfn_load_gfx_8_14_chars(GET_BL());
628 break;
629 case 0x23:
630 biosfn_load_gfx_8_8_dd_chars(GET_BL());
631 break;
632 case 0x24:
633 biosfn_load_gfx_8_16_chars(GET_BL());
634 break;
635 case 0x30:
636 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
637 break;
638 #ifdef DEBUG
639 default:
640 unknown();
641 #endif
644 break;
645 case 0x12:
646 switch(GET_BL())
648 case 0x10:
649 biosfn_get_ega_info(&BX,&CX);
650 break;
651 case 0x20:
652 biosfn_alternate_prtsc();
653 break;
654 case 0x30:
655 biosfn_select_vert_res(GET_AL());
656 SET_AL(0x12);
657 break;
658 case 0x31:
659 biosfn_enable_default_palette_loading(GET_AL());
660 SET_AL(0x12);
661 break;
662 case 0x32:
663 biosfn_enable_video_addressing(GET_AL());
664 SET_AL(0x12);
665 break;
666 case 0x33:
667 biosfn_enable_grayscale_summing(GET_AL());
668 SET_AL(0x12);
669 break;
670 case 0x34:
671 biosfn_enable_cursor_emulation(GET_AL());
672 SET_AL(0x12);
673 break;
674 case 0x35:
675 biosfn_switch_video_interface(GET_AL(),ES,DX);
676 SET_AL(0x12);
677 break;
678 case 0x36:
679 biosfn_enable_video_refresh_control(GET_AL());
680 SET_AL(0x12);
681 break;
682 #ifdef DEBUG
683 default:
684 unknown();
685 #endif
687 break;
688 case 0x13:
689 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
690 break;
691 case 0x1B:
692 biosfn_read_state_info(BX,ES,DI);
693 SET_AL(0x1B);
694 break;
695 case 0x1C:
696 switch(GET_AL())
698 case 0x00:
699 biosfn_read_video_state_size(CX,&BX);
700 break;
701 case 0x01:
702 biosfn_save_video_state(CX,ES,BX);
703 break;
704 case 0x02:
705 biosfn_restore_video_state(CX,ES,BX);
706 break;
707 #ifdef DEBUG
708 default:
709 unknown();
710 #endif
712 SET_AL(0x1C);
713 break;
715 #ifdef VBE
716 case 0x4f:
717 if (vbe_has_vbe_display()) {
718 switch(GET_AL())
720 case 0x00:
721 vbe_biosfn_return_controller_information(&AX,ES,DI);
722 break;
723 case 0x01:
724 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
725 break;
726 case 0x02:
727 vbe_biosfn_set_mode(&AX,BX,ES,DI);
728 break;
729 case 0x03:
730 vbe_biosfn_return_current_mode(&AX,&BX);
731 break;
732 case 0x04:
733 //FIXME
734 #ifdef DEBUG
735 unimplemented();
736 #endif
737 // function failed
738 AX=0x100;
739 break;
740 case 0x05:
741 vbe_biosfn_display_window_control(&AX,BX,&DX);
742 break;
743 case 0x06:
744 vbe_biosfn_set_get_logical_scan_line_length(&AX,&BX,&CX,&DX);
745 break;
746 case 0x07:
747 vbe_biosfn_set_get_display_start(&AX,BX,CX,DX);
748 break;
749 case 0x08:
750 //FIXME
751 #ifdef DEBUG
752 unimplemented();
753 #endif
754 // function failed
755 AX=0x100;
756 break;
757 case 0x09:
758 //FIXME
759 #ifdef DEBUG
760 unimplemented();
761 #endif
762 // function failed
763 AX=0x100;
764 break;
765 case 0x0A:
766 //FIXME
767 #ifdef DEBUG
768 unimplemented();
769 #endif
770 // function failed
771 AX=0x100;
772 break;
773 #ifdef DEBUG
774 default:
775 unknown();
776 #endif
777 // function failed
778 AX=0x100;
781 else {
782 // No VBE display
783 AX=0x0100;
785 break;
786 #endif
788 #ifdef DEBUG
789 default:
790 unknown();
791 #endif
795 // ============================================================================================
797 // BIOS functions
799 // ============================================================================================
801 static void biosfn_set_video_mode(mode) Bit8u mode;
802 {// mode: Bit 7 is 1 if no clear screen
804 // Should we clear the screen ?
805 Bit8u noclearmem=mode&0x80;
806 Bit8u line,mmask,*palette;
807 Bit16u i,twidth,theight,cheight;
808 Bit8u modeset_ctl,video_ctl,vga_switches;
809 Bit16u crtc_addr;
811 #ifdef VBE
812 if (vbe_has_vbe_display()) {
813 dispi_set_enable(VBE_DISPI_DISABLED);
815 #endif // def VBE
817 // The real mode
818 mode=mode&0x7f;
820 // find the entry in the video modes
821 line=find_vga_entry(mode);
823 #ifdef DEBUG
824 printf("mode search %02x found line %02x\n",mode,line);
825 #endif
827 if(line==0xFF)
828 return;
830 twidth=vga_modes[line].twidth;
831 theight=vga_modes[line].theight;
832 cheight=vga_modes[line].cheight;
834 // Read the bios vga control
835 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
837 // Read the bios vga switches
838 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
840 // Read the bios mode set control
841 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
843 // Then we know the number of lines
844 // FIXME
846 // if palette loading (bit 3 of modeset ctl = 0)
847 if((modeset_ctl&0x08)==0)
848 {// Set the PEL mask
849 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
851 // Set the whole dac always, from 0
852 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
854 // From which palette
855 switch(vga_modes[line].dacmodel)
856 {case 0:
857 palette=&palette0;
858 break;
859 case 1:
860 palette=&palette1;
861 break;
862 case 2:
863 palette=&palette2;
864 break;
865 case 3:
866 palette=&palette3;
867 break;
871 // Always 256*3 values
872 for(i=0;i<0x0100;i++)
873 {if(i<=dac_regs[vga_modes[line].dacmodel])
874 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
875 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
876 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
878 else
879 {outb(VGAREG_DAC_DATA,0);
880 outb(VGAREG_DAC_DATA,0);
881 outb(VGAREG_DAC_DATA,0);
885 // Reset Attribute Ctl flip-flop
886 inb(VGAREG_ACTL_RESET);
888 // Set Attribute Ctl
889 for(i=0;i<=ACTL_MAX_REG;i++)
890 {outb(VGAREG_ACTL_ADDRESS,i);
891 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
894 // Set Sequencer Ctl
895 for(i=0;i<=SEQU_MAX_REG;i++)
896 {outb(VGAREG_SEQU_ADDRESS,i);
897 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
900 // Set Grafx Ctl
901 for(i=0;i<=GRDC_MAX_REG;i++)
902 {outb(VGAREG_GRDC_ADDRESS,i);
903 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
906 // Set CRTC address VGA or MDA
907 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
909 // Set CRTC regs
910 for(i=0;i<=CRTC_MAX_REG;i++)
911 {outb(crtc_addr,i);
912 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
915 // Set the misc register
916 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
918 // Enable video
919 outb(VGAREG_ACTL_ADDRESS,0x20);
920 inb(VGAREG_ACTL_RESET);
922 if(noclearmem==0x00)
924 if(vga_modes[line].class==TEXT)
926 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
928 else
930 if(mode<0x0d)
932 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
934 else
936 outb( VGAREG_SEQU_ADDRESS, 0x02 );
937 mmask = inb( VGAREG_SEQU_DATA );
938 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
939 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
940 outb( VGAREG_SEQU_DATA, mmask );
945 // Set the BIOS mem
946 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
947 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
948 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
949 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
950 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
951 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
952 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
953 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
954 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
956 // FIXME We nearly have the good tables. to be reworked
957 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
958 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
959 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
961 // FIXME
962 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
963 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
965 // Set cursor shape
966 if(vga_modes[line].class==TEXT)
968 biosfn_set_cursor_shape(0x06,0x07);
971 // Set cursor pos for page 0..7
972 for(i=0;i<8;i++)
973 biosfn_set_cursor_pos(i,0x0000);
975 // Set active page 0
976 biosfn_set_active_page(0x00);
978 // Write the fonts in memory
979 if(vga_modes[line].class==TEXT)
981 ASM_START
982 ;; copy and activate 8x16 font
983 mov ax, #0x1104
984 mov bl, #0x00
985 int #0x10
986 mov ax, #0x1103
987 mov bl, #0x00
988 int #0x10
989 ASM_END
992 // Set the ints 0x1F and 0x43
993 ASM_START
994 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
995 ASM_END
997 switch(cheight)
998 {case 8:
999 ASM_START
1000 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1001 ASM_END
1002 break;
1003 case 14:
1004 ASM_START
1005 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1006 ASM_END
1007 break;
1008 case 16:
1009 ASM_START
1010 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1011 ASM_END
1012 break;
1016 // --------------------------------------------------------------------------------------------
1017 static void biosfn_set_cursor_shape (CH,CL)
1018 Bit8u CH;Bit8u CL;
1019 {Bit16u cheight,curs,crtc_addr;
1021 CH&=0x3f;
1022 CL&=0x1f;
1024 curs=(CH<<8)+CL;
1025 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1027 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1028 if((cheight>8) && (CL<8) && (CH<0x20))
1030 if(CL!=(CH+1))
1032 CH = ((CH+1) * cheight / 8) -1;
1034 else
1036 CH = ((CL+1) * cheight / 8) - 2;
1038 CL = ((CL+1) * cheight / 8) - 1;
1041 // CTRC regs 0x0a and 0x0b
1042 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1043 outb(crtc_addr,0x0a);
1044 outb(crtc_addr+1,CH);
1045 outb(crtc_addr,0x0b);
1046 outb(crtc_addr+1,CL);
1049 // --------------------------------------------------------------------------------------------
1050 static void biosfn_set_cursor_pos (page, cursor)
1051 Bit8u page;Bit16u cursor;
1053 Bit8u xcurs,ycurs,current;
1054 Bit16u nbcols,nbrows,address,crtc_addr;
1056 // Should not happen...
1057 if(page>7)return;
1059 // Bios cursor pos
1060 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1062 // Set the hardware cursor
1063 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1064 if(page==current)
1066 // Get the dimensions
1067 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1068 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1070 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1072 // Calculate the address knowing nbcols nbrows and page num
1073 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1075 // CRTC regs 0x0e and 0x0f
1076 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1077 outb(crtc_addr,0x0e);
1078 outb(crtc_addr+1,(address&0xff00)>>8);
1079 outb(crtc_addr,0x0f);
1080 outb(crtc_addr+1,address&0x00ff);
1084 // --------------------------------------------------------------------------------------------
1085 static void biosfn_get_cursor_pos (page,shape, pos)
1086 Bit8u page;Bit16u *shape;Bit16u *pos;
1088 Bit16u ss=get_SS();
1090 // Default
1091 write_word(ss, shape, 0);
1092 write_word(ss, pos, 0);
1094 if(page>7)return;
1095 // FIXME should handle VGA 14/16 lines
1096 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1097 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1100 // --------------------------------------------------------------------------------------------
1101 static void biosfn_set_active_page (page)
1102 Bit8u page;
1104 Bit16u cursor,dummy,crtc_addr;
1105 Bit16u nbcols,nbrows,address;
1106 Bit8u mode,line;
1108 if(page>7)return;
1110 // Get the mode
1111 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1112 line=find_vga_entry(mode);
1113 if(line==0xFF)return;
1115 // Get pos curs pos for the right page
1116 biosfn_get_cursor_pos(page,&dummy,&cursor);
1118 if(vga_modes[line].class==TEXT)
1120 // Get the dimensions
1121 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1122 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1124 // Calculate the address knowing nbcols nbrows and page num
1125 address=SCREEN_MEM_START(nbcols,nbrows,page);
1126 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1128 // Start address
1129 address=SCREEN_IO_START(nbcols,nbrows,page);
1131 else
1133 address = page*vga_modes[line].slength;
1136 // CRTC regs 0x0c and 0x0d
1137 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1138 outb(crtc_addr,0x0c);
1139 outb(crtc_addr+1,(address&0xff00)>>8);
1140 outb(crtc_addr,0x0d);
1141 outb(crtc_addr+1,address&0x00ff);
1143 // And change the BIOS page
1144 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1146 #ifdef DEBUG
1147 printf("Set active page %02x address %04x\n",page,address);
1148 #endif
1150 // Display the cursor, now the page is active
1151 biosfn_set_cursor_pos(page,cursor);
1154 // --------------------------------------------------------------------------------------------
1155 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1156 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1158 // page == 0xFF if current
1160 Bit8u mode,line;
1161 Bit16u nbcols,nbrows,i;
1162 Bit16u address;
1164 if(rul>rlr)return;
1165 if(cul>clr)return;
1167 // Get the mode
1168 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1169 line=find_vga_entry(mode);
1170 if(line==0xFF)return;
1172 // Get the dimensions
1173 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1174 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1176 // Get the current page
1177 if(page==0xFF)
1178 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1180 if(vga_modes[line].class==TEXT)
1182 // Compute the address
1183 address=SCREEN_MEM_START(nbcols,nbrows,page);
1184 #ifdef DEBUG
1185 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1186 #endif
1188 if(rlr>=nbrows)rlr=nbrows-1;
1189 if(clr>=nbcols)clr=nbcols-1;
1190 if(nblines>nbrows)nblines=0;
1192 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1194 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1196 else
1197 {// if Scroll up
1198 if(dir==SCROLL_UP)
1199 {for(i=rul;i<=rlr;i++)
1201 if((i+nblines>rlr)||(nblines==0))
1202 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1203 else
1204 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,clr-cul+1);
1207 else
1208 {for(i=rlr;i>=rul;i--)
1210 if((i<rul+nblines)||(nblines==0))
1211 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1212 else
1213 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,clr-cul+1);
1218 else
1220 // FIXME gfx mode
1221 #ifdef DEBUG
1222 printf("Scroll in graphics mode ");
1223 unimplemented();
1224 #endif
1228 // --------------------------------------------------------------------------------------------
1229 static void biosfn_read_char_attr (page,car)
1230 Bit8u page;Bit16u *car;
1231 {Bit16u ss=get_SS();
1232 Bit8u xcurs,ycurs,mode,line;
1233 Bit16u nbcols,nbrows,address;
1234 Bit16u cursor,dummy;
1236 // Get the mode
1237 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1238 line=find_vga_entry(mode);
1239 if(line==0xFF)return;
1241 // Get the cursor pos for the page
1242 biosfn_get_cursor_pos(page,&dummy,&cursor);
1243 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1245 // Get the dimensions
1246 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1247 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1249 if(vga_modes[line].class==TEXT)
1251 // Compute the address
1252 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1254 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1256 else
1258 // FIXME gfx mode
1259 #ifdef DEBUG
1260 unimplemented();
1261 #endif
1265 // --------------------------------------------------------------------------------------------
1266 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1267 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1269 Bit8u i,mmask;
1270 Bit8u *fdata;
1271 Bit16u addr,dest,src;
1273 switch(cheight)
1274 {case 14:
1275 fdata = &vgafont14;
1276 break;
1277 case 16:
1278 fdata = &vgafont16;
1279 break;
1280 default:
1281 fdata = &vgafont8;
1283 addr=xcurs+ycurs*cheight*nbcols;
1284 src = car * cheight;
1285 outb( VGAREG_SEQU_ADDRESS, 0x02 );
1286 mmask = inb( VGAREG_SEQU_DATA );
1287 for(i=0;i<cheight;i++)
1289 dest=addr+i*nbcols;
1290 outb( VGAREG_SEQU_DATA, 0x0f );
1291 write_byte(0xa000,dest,0x00);
1292 outb( VGAREG_SEQU_DATA, attr & 0x0f );
1293 write_byte(0xa000,dest,fdata[src+i]);
1295 outb( VGAREG_SEQU_DATA, mmask );
1298 // --------------------------------------------------------------------------------------------
1299 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1300 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1302 Bit8u i,j,mask,data;
1303 Bit8u *fdata;
1304 Bit16u addr,dest,src;
1306 fdata = &vgafont8;
1307 addr=(xcurs*bpp)+ycurs*320;
1308 src = car * 8;
1309 for(i=0;i<8;i++)
1311 dest=addr+(i>>1)*80;
1312 if (i & 1) dest += 0x2000;
1313 mask = 0x80;
1314 if (bpp == 1)
1316 if (attr & 0x80)
1318 data = read_byte(0xb800,dest);
1320 else
1322 data = 0x00;
1324 for(j=0;j<8;j++)
1326 if (fdata[src+i] & mask)
1328 if (attr & 0x80)
1330 data ^= (attr & 0x01) << (7-j);
1332 else
1334 data |= (attr & 0x01) << (7-j);
1337 mask >>= 1;
1339 write_byte(0xb800,dest,data);
1341 else
1343 while (mask > 0)
1345 if (attr & 0x80)
1347 data = read_byte(0xb800,dest);
1349 else
1351 data = 0x00;
1353 for(j=0;j<4;j++)
1355 if (fdata[src+i] & mask)
1357 if (attr & 0x80)
1359 data ^= (attr & 0x03) << ((3-j)*2);
1361 else
1363 data |= (attr & 0x03) << ((3-j)*2);
1366 mask >>= 1;
1368 write_byte(0xb800,dest,data);
1369 dest += 1;
1375 // --------------------------------------------------------------------------------------------
1376 static void biosfn_write_char_attr (car,page,attr,count)
1377 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1379 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1380 Bit16u nbcols,nbrows,address;
1381 Bit16u cursor,dummy;
1383 // Get the mode
1384 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1385 line=find_vga_entry(mode);
1386 if(line==0xFF)return;
1388 // Get the cursor pos for the page
1389 biosfn_get_cursor_pos(page,&dummy,&cursor);
1390 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1392 // Get the dimensions
1393 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1394 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1396 if(vga_modes[line].class==TEXT)
1398 // Compute the address
1399 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1401 dummy=((Bit16u)attr<<8)+car;
1402 memsetw(vga_modes[line].sstart,address,dummy,count);
1404 else
1406 // FIXME gfx mode not complete
1407 cheight=vga_modes[line].cheight;
1408 bpp=vga_modes[line].pixbits;
1409 while((count-->0) && (xcurs<nbcols))
1411 if(vga_modes[line].memmodel==PLANAR4)
1413 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1415 else if(vga_modes[line].memmodel==CGA)
1417 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1419 else
1421 #ifdef DEBUG
1422 unimplemented();
1423 #endif
1425 xcurs++;
1430 // --------------------------------------------------------------------------------------------
1431 static void biosfn_write_char_only (car,page,attr,count)
1432 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1434 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1435 Bit16u nbcols,nbrows,address;
1436 Bit16u cursor,dummy;
1438 // Get the mode
1439 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1440 line=find_vga_entry(mode);
1441 if(line==0xFF)return;
1443 // Get the cursor pos for the page
1444 biosfn_get_cursor_pos(page,&dummy,&cursor);
1445 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1447 // Get the dimensions
1448 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1449 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1451 if(vga_modes[line].class==TEXT)
1453 // Compute the address
1454 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1456 while(count-->0)
1457 {write_byte(vga_modes[line].sstart,address,car);
1458 address+=2;
1461 else
1463 // FIXME gfx mode not complete
1464 cheight=vga_modes[line].cheight;
1465 bpp=vga_modes[line].pixbits;
1466 while((count-->0) && (xcurs<nbcols))
1468 if(vga_modes[line].memmodel==PLANAR4)
1470 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1472 else if(vga_modes[line].memmodel==CGA)
1474 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1476 else
1478 #ifdef DEBUG
1479 unimplemented();
1480 #endif
1482 xcurs++;
1487 // --------------------------------------------------------------------------------------------
1488 static void biosfn_set_border_color (BL) Bit8u BL;
1489 // FIXME anybody using this function ?
1491 #ifdef DEBUG
1492 unimplemented();
1493 #endif
1496 // --------------------------------------------------------------------------------------------
1497 static void biosfn_set_palette (BL) Bit8u BL;
1498 // FIXME anybody using this function ?
1500 #ifdef DEBUG
1501 unimplemented();
1502 #endif
1505 // --------------------------------------------------------------------------------------------
1506 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1508 Bit8u mode,line,mask,attr;
1509 Bit16u addr,data;
1511 // Get the mode
1512 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1513 line=find_vga_entry(mode);
1514 if(line==0xFF)return;
1515 if(vga_modes[line].class==TEXT)return;
1517 if(vga_modes[line].memmodel==CGA)
1519 if(vga_modes[line].pixbits==2)
1521 addr=(CX>>2)+(DX>>1)*80;
1523 else
1525 addr=(CX>>3)+(DX>>1)*80;
1527 if (DX & 1) addr += 0x2000;
1528 data = read_byte(0xb800,addr);
1529 if(vga_modes[line].pixbits==2)
1531 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1532 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1534 else
1536 attr = (AL & 0x01) << (7 - (CX & 0x07));
1537 mask = 0x01 << (7 - (CX & 0x07));
1539 if (AL & 0x80)
1541 data ^= attr;
1543 else
1545 data &= ~mask;
1546 data |= attr;
1548 write_byte(0xb800,addr,data);
1550 else if(vga_modes[line].memmodel==LINEAR8)
1552 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1553 write_byte(0xa000,addr,AL);
1555 else
1557 #ifdef DEBUG
1558 unimplemented();
1559 #endif
1563 // --------------------------------------------------------------------------------------------
1564 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1566 Bit8u mode,line,attr;
1567 Bit16u addr,data;
1568 Bit16u ss=get_SS();
1570 // Get the mode
1571 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1572 line=find_vga_entry(mode);
1573 if(line==0xFF)return;
1574 if(vga_modes[line].class==TEXT)return;
1576 if(vga_modes[line].memmodel==CGA)
1578 addr=(CX>>2)+(DX>>1)*80;
1579 if (DX & 1) addr += 0x2000;
1580 data = read_byte(0xb800,addr);
1581 if(vga_modes[line].pixbits==2)
1583 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1585 else
1587 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1590 else if(vga_modes[line].memmodel==LINEAR8)
1592 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1593 attr=read_byte(0xa000,addr);
1595 else
1597 #ifdef DEBUG
1598 unimplemented();
1599 #endif
1600 attr = 0;
1602 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1605 // --------------------------------------------------------------------------------------------
1606 static void biosfn_write_teletype (car, page, attr, flag)
1607 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1608 {// flag = WITH_ATTR / NO_ATTR
1610 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1611 Bit16u nbcols,nbrows,address;
1612 Bit16u cursor,dummy;
1614 // special case if page is 0xff, use current page
1615 if(page==0xff)
1616 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1618 // FIXME gfx mode
1620 // Get the mode
1621 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1622 line=find_vga_entry(mode);
1623 if(line==0xFF)return;
1625 // Get the cursor pos for the page
1626 biosfn_get_cursor_pos(page,&dummy,&cursor);
1627 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1629 // Get the dimensions
1630 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1631 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1633 switch(car)
1635 case 7:
1636 //FIXME should beep
1637 break;
1639 case 8:
1640 if(xcurs>0)xcurs--;
1641 break;
1643 case '\r':
1644 xcurs=0;
1645 break;
1647 case '\n':
1648 xcurs=0;
1649 ycurs++;
1650 break;
1652 case '\t':
1655 biosfn_write_teletype(' ',page,attr,flag);
1656 biosfn_get_cursor_pos(page,&dummy,&cursor);
1657 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1658 }while(xcurs%8==0);
1659 break;
1661 default:
1663 if(vga_modes[line].class==TEXT)
1665 // Compute the address
1666 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1668 // Write the char
1669 write_byte(vga_modes[line].sstart,address,car);
1671 if(flag==WITH_ATTR)
1672 write_byte(vga_modes[line].sstart,address+1,attr);
1674 else
1676 // FIXME gfx mode not complete
1677 cheight=vga_modes[line].cheight;
1678 bpp=vga_modes[line].pixbits;
1679 if(vga_modes[line].memmodel==PLANAR4)
1681 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1683 else if(vga_modes[line].memmodel==CGA)
1685 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1687 else
1689 #ifdef DEBUG
1690 unimplemented();
1691 #endif
1695 xcurs++;
1698 // Do we need to wrap ?
1699 if(xcurs==nbcols)
1700 {xcurs=0;
1701 ycurs++;
1704 // Do we need to scroll ?
1705 if(ycurs==nbrows)
1706 {biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1707 ycurs-=1;
1710 // Set the cursor for the page
1711 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1712 biosfn_set_cursor_pos(page,cursor);
1715 // --------------------------------------------------------------------------------------------
1716 ASM_START
1717 biosfn_get_video_mode:
1718 push ds
1719 mov ax, #biosmem_seg
1720 mov ds, ax
1721 push bx
1722 mov bx, #biosmem_current_page
1723 mov al, [bx]
1724 pop bx
1725 mov bh, al
1726 push bx
1727 mov bx, #biosmem_video_ctl
1728 mov ah, [bx]
1729 and ah, #0x80
1730 mov bx, #biosmem_current_mode
1731 mov al, [bx]
1732 or al, ah
1733 mov bx, #biosmem_nb_cols
1734 mov ah, [bx]
1735 pop bx
1736 pop ds
1738 ASM_END
1740 // --------------------------------------------------------------------------------------------
1741 static void biosfn_set_single_palette_reg (reg,value)
1742 Bit8u reg;Bit8u value;
1744 if(reg<=ACTL_MAX_REG)
1746 inb(VGAREG_ACTL_RESET);
1747 outb(VGAREG_ACTL_ADDRESS,reg);
1748 outb(VGAREG_ACTL_WRITE_DATA,value);
1749 outb(VGAREG_ACTL_ADDRESS,0x20);
1753 // --------------------------------------------------------------------------------------------
1754 static void biosfn_set_overscan_border_color (value)
1755 Bit8u value;
1757 inb(VGAREG_ACTL_RESET);
1758 outb(VGAREG_ACTL_ADDRESS,0x11);
1759 outb(VGAREG_ACTL_WRITE_DATA,value);
1760 outb(VGAREG_ACTL_ADDRESS,0x20);
1763 // --------------------------------------------------------------------------------------------
1764 static void biosfn_set_all_palette_reg (seg,offset)
1765 Bit16u seg;Bit16u offset;
1767 Bit8u i;
1769 inb(VGAREG_ACTL_RESET);
1770 // First the colors
1771 for(i=0;i<0x10;i++)
1773 outb(VGAREG_ACTL_ADDRESS,i);
1774 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1775 offset++;
1778 // Then the border
1779 outb(VGAREG_ACTL_ADDRESS,0x11);
1780 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1781 outb(VGAREG_ACTL_ADDRESS,0x20);
1784 // --------------------------------------------------------------------------------------------
1785 static void biosfn_toggle_intensity (state)
1786 Bit8u state;
1787 {Bit8u value;
1788 state&=0x01;
1789 inb(VGAREG_ACTL_RESET);
1791 outb(VGAREG_ACTL_ADDRESS,0x10);
1792 value=inb(VGAREG_ACTL_READ_DATA);
1793 value&=0xf7;
1794 value|=state<<3;
1795 outb(VGAREG_ACTL_WRITE_DATA,value);
1796 outb(VGAREG_ACTL_ADDRESS,0x20);
1799 // --------------------------------------------------------------------------------------------
1800 static void biosfn_get_single_palette_reg (reg,value)
1801 Bit8u reg;Bit16u *value;
1802 {Bit16u ss=get_SS();
1804 if(reg<=ACTL_MAX_REG)
1806 inb(VGAREG_ACTL_RESET);
1807 outb(VGAREG_ACTL_ADDRESS,reg);
1808 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1809 inb(VGAREG_ACTL_RESET);
1810 outb(VGAREG_ACTL_ADDRESS,0x20);
1814 // --------------------------------------------------------------------------------------------
1815 static void biosfn_read_overscan_border_color (value)
1816 Bit16u *value;
1817 {Bit16u ss=get_SS();
1819 inb(VGAREG_ACTL_RESET);
1820 outb(VGAREG_ACTL_ADDRESS,0x11);
1821 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1822 outb(VGAREG_ACTL_ADDRESS,0x20);
1825 // --------------------------------------------------------------------------------------------
1826 static void biosfn_get_all_palette_reg (seg,offset) Bit16u seg;Bit16u offset;
1828 Bit8u i;
1830 // First the colors
1831 for(i=0;i<0x10;i++)
1833 inb(VGAREG_ACTL_RESET);
1834 outb(VGAREG_ACTL_ADDRESS,i);
1835 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1836 offset++;
1839 // Then the border
1840 outb(VGAREG_ACTL_ADDRESS,0x11);
1841 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1842 outb(VGAREG_ACTL_ADDRESS,0x20);
1845 // --------------------------------------------------------------------------------------------
1846 static void biosfn_set_single_dac_reg (reg,g,b,r)
1847 Bit16u reg;Bit8u g;Bit8u b;Bit8u r;
1849 outb(VGAREG_DAC_WRITE_ADDRESS,reg);
1850 outb(VGAREG_DAC_DATA,r);
1851 outb(VGAREG_DAC_DATA,g);
1852 outb(VGAREG_DAC_DATA,b);
1855 // --------------------------------------------------------------------------------------------
1856 static void biosfn_set_all_dac_reg (start,count,seg,offset)
1857 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1858 {Bit16u i;
1859 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1860 for(i=0;i<count;i++)
1861 {outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1862 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1863 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1867 // --------------------------------------------------------------------------------------------
1868 static void biosfn_select_video_dac_color_page (function,page)
1869 Bit8u function;
1870 {Bit8u value;
1872 inb(VGAREG_ACTL_RESET);
1873 outb(VGAREG_ACTL_ADDRESS,0x10);
1875 value=inb(VGAREG_ACTL_READ_DATA);
1876 function&=0x01;
1877 if(function==0)
1878 {// set paging code
1879 value&=0x7f;
1880 value|=page<<7;
1881 outb(VGAREG_ACTL_WRITE_DATA,value);
1883 else
1884 {// select page
1885 inb(VGAREG_ACTL_RESET);
1886 outb(VGAREG_ACTL_ADDRESS,0x14);
1887 if(value&0x80)
1888 outb(VGAREG_ACTL_WRITE_DATA,page&0x0f);
1889 else
1890 outb(VGAREG_ACTL_WRITE_DATA,(page&0x03)<<2);
1892 outb(VGAREG_ACTL_ADDRESS,0x20);
1895 // --------------------------------------------------------------------------------------------
1896 static void biosfn_read_single_dac_reg (reg,tor,togb)
1897 Bit8u reg;Bit16u *tor;Bit16u *togb;
1898 {Bit16u ss=get_SS();
1899 Bit8u r,g,b;
1901 outb(VGAREG_DAC_READ_ADDRESS,reg);
1902 r=inb(VGAREG_DAC_DATA);
1903 g=inb(VGAREG_DAC_DATA);
1904 b=inb(VGAREG_DAC_DATA);
1905 write_word(ss,tor,((Bit16u)r)<<8);
1906 write_word(ss,togb,(((Bit16u)g)<<8)+b);
1909 // --------------------------------------------------------------------------------------------
1910 static void biosfn_read_all_dac_reg (start,count,seg,offset)
1911 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1912 {Bit16u i;
1913 outb(VGAREG_DAC_READ_ADDRESS,start);
1914 for(i=0;i<count;i++)
1915 {write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1916 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1917 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1921 // --------------------------------------------------------------------------------------------
1922 static void biosfn_set_pel_mask (mask)
1923 Bit8u mask;
1925 outb(VGAREG_PEL_MASK,mask);
1928 // --------------------------------------------------------------------------------------------
1929 static void biosfn_read_pel_mask (mask)
1930 Bit16u *mask;
1931 {Bit16u ss=get_SS();
1933 write_word(ss,mask,inb(VGAREG_PEL_MASK));
1936 // --------------------------------------------------------------------------------------------
1937 static void biosfn_read_video_dac_state (state) Bit16u *state;
1938 {Bit16u ss=get_SS();
1939 Bit8u mcr,csr;
1941 inb(VGAREG_ACTL_RESET);
1942 outb(VGAREG_ACTL_ADDRESS,0x10);
1943 mcr=(inb(VGAREG_ACTL_READ_DATA)>>7)&0x01;
1944 inb(VGAREG_ACTL_RESET);
1945 outb(VGAREG_ACTL_ADDRESS,0x14);
1946 csr=inb(VGAREG_ACTL_READ_DATA)&0x0f;
1947 if(mcr==0)(csr>>2)&0x03;
1949 write_word(ss,state,(mcr<<8)+csr);
1950 outb(VGAREG_ACTL_ADDRESS,0x20);
1953 // --------------------------------------------------------------------------------------------
1954 static void biosfn_perform_gray_scale_summing (start,count)
1955 Bit16u start;Bit16u count;
1956 {Bit8u r,g,b,d;
1957 Bit16u i,m;
1958 Bit16u index;
1960 inb(VGAREG_ACTL_RESET);
1961 outb(VGAREG_ACTL_ADDRESS,0x10);
1962 d=(inb(VGAREG_ACTL_READ_DATA)>>6)&0x01;
1964 // depth is 8 or 6 bits
1965 if(d==0)m=0x3f;
1966 else m=0xff;
1969 // We start overwriting at
1970 outb(VGAREG_DAC_READ_ADDRESS,start);
1971 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1973 for( index = 0; index < count; index++ )
1975 // get 6-bit wide RGB data values
1976 r=inb( VGAREG_DAC_DATA );
1977 g=inb( VGAREG_DAC_DATA );
1978 b=inb( VGAREG_DAC_DATA );
1980 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
1981 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
1983 if(i>m)i=m;
1985 // write new intensity value
1986 outb( VGAREG_DAC_DATA, i&0xff );
1987 outb( VGAREG_DAC_DATA, i&0xff );
1988 outb( VGAREG_DAC_DATA, i&0xff );
1990 outb(VGAREG_ACTL_ADDRESS,0x20);
1993 // --------------------------------------------------------------------------------------------
1994 static void get_font_access()
1996 outw( VGAREG_SEQU_ADDRESS, 0x0100 );
1997 outw( VGAREG_SEQU_ADDRESS, 0x0402 );
1998 outw( VGAREG_SEQU_ADDRESS, 0x0704 );
1999 outw( VGAREG_SEQU_ADDRESS, 0x0300 );
2000 outw( VGAREG_GRDC_ADDRESS, 0x0204 );
2001 outw( VGAREG_GRDC_ADDRESS, 0x0005 );
2002 outw( VGAREG_GRDC_ADDRESS, 0x0406 );
2005 static void release_font_access()
2007 outw( VGAREG_SEQU_ADDRESS, 0x0100 );
2008 outw( VGAREG_SEQU_ADDRESS, 0x0302 );
2009 outw( VGAREG_SEQU_ADDRESS, 0x0304 );
2010 outw( VGAREG_SEQU_ADDRESS, 0x0300 );
2011 outw( VGAREG_GRDC_ADDRESS, 0x0004 );
2012 outw( VGAREG_GRDC_ADDRESS, 0x1005 );
2013 outw( VGAREG_GRDC_ADDRESS, 0x0e06 );
2016 ASM_START
2017 idiv_u:
2018 xor dx,dx
2019 div bx
2021 ASM_END
2023 static void set_scan_lines(lines) Bit8u lines;
2025 Bit16u crtc_addr,cols,page,vde;
2026 Bit8u crtc_r9,ovl,rows;
2028 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2029 outb(crtc_addr, 0x09);
2030 crtc_r9 = inb(crtc_addr+1);
2031 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2032 outb(crtc_addr+1, crtc_r9);
2033 if(lines==8)
2035 biosfn_set_cursor_shape(0x06,0x07);
2037 else
2039 biosfn_set_cursor_shape(lines-4,lines-3);
2041 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2042 outb(crtc_addr, 0x12);
2043 vde = inb(crtc_addr+1);
2044 outb(crtc_addr, 0x07);
2045 ovl = inb(crtc_addr+1);
2046 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2047 rows = vde / lines;
2048 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2049 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2050 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2053 static void biosfn_load_text_user_pat (AL,ES,BP,CX,DX,BL,BH) Bit8u AL;Bit16u ES;Bit16u BP;Bit16u CX;Bit16u DX;Bit8u BL;Bit8u BH;
2055 Bit16u blockaddr,dest,i,src;
2057 get_font_access();
2058 blockaddr = BL << 13;
2059 for(i=0;i<CX;i++)
2061 src = BP + i * BH;
2062 dest = blockaddr + (DX + i) * 32;
2063 memcpyb(0xA000, dest, ES, src, BH);
2065 release_font_access();
2066 if(AL>=0x10)
2068 set_scan_lines(BH);
2072 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2074 Bit16u blockaddr,dest,i,src;
2076 get_font_access();
2077 blockaddr = BL << 13;
2078 for(i=0;i<0x100;i++)
2080 src = i * 14;
2081 dest = blockaddr + i * 32;
2082 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2084 release_font_access();
2085 if(AL>=0x10)
2087 set_scan_lines(14);
2091 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2093 Bit16u blockaddr,dest,i,src;
2095 get_font_access();
2096 blockaddr = BL << 13;
2097 for(i=0;i<0x100;i++)
2099 src = i * 8;
2100 dest = blockaddr + i * 32;
2101 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2103 release_font_access();
2104 if(AL>=0x10)
2106 set_scan_lines(8);
2110 static void biosfn_set_text_block_specifier (BL) Bit8u BL;
2112 outb( VGAREG_SEQU_ADDRESS, 0x03 );
2113 outb( VGAREG_SEQU_DATA, BL );
2116 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2118 Bit16u blockaddr,dest,i,src;
2120 get_font_access();
2121 blockaddr = BL << 13;
2122 for(i=0;i<0x100;i++)
2124 src = i * 16;
2125 dest = blockaddr + i * 32;
2126 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2128 release_font_access();
2129 if(AL>=0x10)
2131 set_scan_lines(16);
2135 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2137 #ifdef DEBUG
2138 unimplemented();
2139 #endif
2141 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2143 #ifdef DEBUG
2144 unimplemented();
2145 #endif
2147 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2149 #ifdef DEBUG
2150 unimplemented();
2151 #endif
2153 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2155 #ifdef DEBUG
2156 unimplemented();
2157 #endif
2159 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2161 #ifdef DEBUG
2162 unimplemented();
2163 #endif
2165 // --------------------------------------------------------------------------------------------
2166 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2167 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2168 {Bit16u ss=get_SS();
2170 switch(BH)
2171 {case 0x00:
2172 write_word(ss,ES,read_word(0x00,0x1f*4));
2173 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2174 break;
2175 case 0x01:
2176 write_word(ss,ES,read_word(0x00,0x43*4));
2177 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2178 break;
2179 case 0x02:
2180 write_word(ss,ES,0xC000);
2181 write_word(ss,BP,vgafont14);
2182 break;
2183 case 0x03:
2184 write_word(ss,ES,0xC000);
2185 write_word(ss,BP,vgafont8);
2186 break;
2187 case 0x04:
2188 write_word(ss,ES,0xC000);
2189 write_word(ss,BP,vgafont8+128*8);
2190 break;
2191 case 0x05:
2192 write_word(ss,ES,0xC000);
2193 write_word(ss,BP,vgafont14alt);
2194 break;
2195 case 0x06:
2196 write_word(ss,ES,0xC000);
2197 write_word(ss,BP,vgafont16);
2198 break;
2199 case 0x07:
2200 write_word(ss,ES,0xC000);
2201 write_word(ss,BP,vgafont16alt);
2202 break;
2203 default:
2204 #ifdef DEBUG
2205 printf("Get font info BH(%02x) was discarded\n",BH);
2206 #endif
2207 return;
2209 // Set byte/char of on screen font
2210 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2212 // Set Highest char row
2213 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2216 // --------------------------------------------------------------------------------------------
2217 static void biosfn_get_ega_info (BX,CX)
2218 Bit16u *BX;Bit16u *CX;
2219 {Bit16u ss=get_SS();
2220 Bit16u crtc;
2221 Bit8u switches;
2223 crtc=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2224 if(crtc==VGAREG_MDA_CRTC_ADDRESS)
2225 write_word(ss,BX,(1<<8)+0x0003);
2226 else
2227 write_word(ss,BX,0x0003);
2229 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2230 write_word(ss,CX,(switches&0x0f));
2233 // --------------------------------------------------------------------------------------------
2234 static void biosfn_alternate_prtsc()
2236 #ifdef DEBUG
2237 unimplemented();
2238 #endif
2241 // --------------------------------------------------------------------------------------------
2242 static void biosfn_select_vert_res (res)
2243 Bit8u res;
2244 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2245 Bit8u modeset,switches;
2247 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2248 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2249 switch(res)
2250 {case 0x00:
2251 // set modeset ctl bit 7 and reset bit 4
2252 // set switches bit 3-0 to 0x08
2253 modeset|=0x80;modeset&=0xef;
2254 switches&=0xf0;switches|=0x08;
2255 break;
2256 case 0x01:
2257 // reset modeset ctl bit 7 and bit 4
2258 // set switches bit 3-0 to 0x09
2259 modeset&=0x6f;
2260 switches&=0xf0;switches|=0x09;
2261 break;
2262 case 0x02:
2263 // reset modeset ctl bit 7 and set bit 4
2264 // set switches bit 3-0 to 0x09
2265 modeset|=0x10;modeset&=0x7f;
2266 switches&=0xf0;switches|=0x09;
2267 break;
2268 default:
2269 #ifdef DEBUG
2270 printf("Select vert res (%02x) was discarded\n",res);
2271 #endif
2272 return;
2274 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2275 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2278 // --------------------------------------------------------------------------------------------
2279 static void biosfn_enable_default_palette_loading (disable)
2280 Bit8u disable;
2282 Bit8u modeset;
2284 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2286 // Bit 3
2287 if(disable!=0x00)modeset|=0x08;
2288 else modeset&=0xf7;
2290 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2293 // --------------------------------------------------------------------------------------------
2294 static void biosfn_enable_video_addressing (disable)
2295 Bit8u disable;
2297 Bit8u misc;
2299 misc=inb(VGAREG_READ_MISC_OUTPUT);
2300 // bit 1, 0 disable
2301 if(disable!=0x00) misc&=0xfd;
2302 else misc|=0x02;
2303 outb(VGAREG_WRITE_MISC_OUTPUT,misc);
2306 // --------------------------------------------------------------------------------------------
2307 static void biosfn_enable_grayscale_summing (disable)
2308 Bit8u disable;
2310 Bit8u modeset;
2312 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2314 // Bit 1 set if disable=0
2315 if(disable==0x00)modeset|=0x02;
2316 else modeset&=0xfd;
2318 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2321 // --------------------------------------------------------------------------------------------
2322 static void biosfn_enable_cursor_emulation (disable)
2323 Bit8u disable;
2325 Bit8u videoctl;
2327 videoctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
2329 // Bit 0 set if disable!=0
2330 if(disable!=0x00)videoctl|=0x01;
2331 else videoctl&=0xfe;
2333 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,videoctl);
2336 // --------------------------------------------------------------------------------------------
2337 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2339 #ifdef DEBUG
2340 unimplemented();
2341 #endif
2343 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2345 #ifdef DEBUG
2346 unimplemented();
2347 #endif
2350 // --------------------------------------------------------------------------------------------
2351 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2352 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2354 Bit16u newcurs,oldcurs,dummy;
2355 Bit8u car,carattr;
2357 // Read curs info for the page
2358 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2360 // if row=0xff special case : use current cursor position
2361 if(row==0xff)
2362 {col=oldcurs&0x00ff;
2363 row=(oldcurs&0xff00)>>8;
2366 newcurs=row; newcurs<<=8; newcurs+=col;
2367 biosfn_set_cursor_pos(page,newcurs);
2369 while(count--!=0)
2371 car=read_byte(seg,offset++);
2372 if((flag&0x02)!=0)
2373 attr=read_byte(seg,offset++);
2375 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2378 // Set back curs pos
2379 if((flag&0x01)==0)
2380 biosfn_set_cursor_pos(page,oldcurs);
2383 // --------------------------------------------------------------------------------------------
2384 ASM_START
2385 biosfn_group_1A:
2386 cmp al, #0x00
2387 je biosfn_read_display_code
2388 cmp al, #0x01
2389 je biosfn_set_display_code
2390 #ifdef DEBUG
2391 call _unknown
2392 #endif
2394 biosfn_read_display_code:
2395 push ds
2396 push ax
2397 mov ax, #biosmem_seg
2398 mov ds, ax
2399 mov bx, #biosmem_dcc_index
2400 mov al, [bx]
2401 mov bl, al
2402 xor bh, bh
2403 pop ax
2404 mov al, ah
2405 pop ds
2407 biosfn_set_display_code:
2408 push ds
2409 push ax
2410 push bx
2411 mov ax, #biosmem_seg
2412 mov ds, ax
2413 mov ax, bx
2414 mov bx, #biosmem_dcc_index
2415 mov [bx], al
2416 #ifdef DEBUG
2417 mov al, ah
2418 xor ah, ah
2419 push ax
2420 mov bx, #msg_alt_dcc
2421 push bx
2422 call _printf
2423 add sp, #4
2424 #endif
2425 pop bx
2426 pop ax
2427 mov al, ah
2428 pop ds
2431 #ifdef DEBUG
2432 msg_alt_dcc:
2433 .ascii "Alternate Display code (%02x) was discarded"
2434 .byte 0x0d,0x0a,0x00
2435 #endif
2436 ASM_END
2438 // --------------------------------------------------------------------------------------------
2439 static void biosfn_read_state_info (BX,ES,DI)
2440 Bit16u BX;Bit16u ES;Bit16u DI;
2442 // Address of static functionality table
2443 write_word(ES,DI+0x00,&static_functionality);
2444 write_word(ES,DI+0x02,0xC000);
2446 // Hard coded copy from BIOS area. Should it be cleaner ?
2447 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2448 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2450 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2451 write_byte(ES,DI+0x26,0);
2452 write_byte(ES,DI+0x27,16);
2453 write_byte(ES,DI+0x28,0);
2454 write_byte(ES,DI+0x29,8);
2455 write_byte(ES,DI+0x2a,2);
2456 write_byte(ES,DI+0x2b,0);
2457 write_byte(ES,DI+0x2c,0);
2458 write_byte(ES,DI+0x31,3);
2459 write_byte(ES,DI+0x32,0);
2461 memsetb(ES,DI+0x33,0,13);
2464 // --------------------------------------------------------------------------------------------
2465 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2467 #ifdef DEBUG
2468 unimplemented();
2469 #endif
2471 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2473 #ifdef DEBUG
2474 unimplemented();
2475 #endif
2477 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2479 #ifdef DEBUG
2480 unimplemented();
2481 #endif
2484 // ============================================================================================
2486 // Video Utils
2488 // ============================================================================================
2490 // --------------------------------------------------------------------------------------------
2491 static Bit8u find_vga_entry(mode)
2492 Bit8u mode;
2494 Bit8u i,line=0xFF;
2495 for(i=0;i<=MODE_MAX;i++)
2496 if(vga_modes[i].svgamode==mode)
2497 {line=i;
2498 break;
2500 return line;
2503 /* =========================================================== */
2505 * Misc Utils
2507 /* =========================================================== */
2509 // --------------------------------------------------------------------------------------------
2510 static void memsetb(seg,offset,value,count)
2511 Bit16u seg;
2512 Bit16u offset;
2513 Bit16u value;
2514 Bit16u count;
2516 ASM_START
2517 push bp
2518 mov bp, sp
2520 push ax
2521 push cx
2522 push es
2523 push di
2525 mov cx, 10[bp] ; count
2526 cmp cx, #0x00
2527 je memsetb_end
2528 mov ax, 4[bp] ; segment
2529 mov es, ax
2530 mov ax, 6[bp] ; offset
2531 mov di, ax
2532 mov al, 8[bp] ; value
2535 stosb
2537 memsetb_end:
2538 pop di
2539 pop es
2540 pop cx
2541 pop ax
2543 pop bp
2544 ASM_END
2547 // --------------------------------------------------------------------------------------------
2548 static void memsetw(seg,offset,value,count)
2549 Bit16u seg;
2550 Bit16u offset;
2551 Bit16u value;
2552 Bit16u count;
2554 ASM_START
2555 push bp
2556 mov bp, sp
2558 push ax
2559 push cx
2560 push es
2561 push di
2563 mov cx, 10[bp] ; count
2564 cmp cx, #0x00
2565 je memsetw_end
2566 mov ax, 4[bp] ; segment
2567 mov es, ax
2568 mov ax, 6[bp] ; offset
2569 mov di, ax
2570 mov ax, 8[bp] ; value
2573 stosw
2575 memsetw_end:
2576 pop di
2577 pop es
2578 pop cx
2579 pop ax
2581 pop bp
2582 ASM_END
2585 // --------------------------------------------------------------------------------------------
2586 static void memcpyb(dseg,doffset,sseg,soffset,count)
2587 Bit16u dseg;
2588 Bit16u doffset;
2589 Bit16u sseg;
2590 Bit16u soffset;
2591 Bit16u count;
2593 ASM_START
2594 push bp
2595 mov bp, sp
2597 push ax
2598 push cx
2599 push es
2600 push di
2601 push ds
2602 push si
2604 mov cx, 12[bp] ; count
2605 cmp cx, #0x0000
2606 je memcpyb_end
2607 mov ax, 4[bp] ; dsegment
2608 mov es, ax
2609 mov ax, 6[bp] ; doffset
2610 mov di, ax
2611 mov ax, 8[bp] ; ssegment
2612 mov ds, ax
2613 mov ax, 10[bp] ; soffset
2614 mov si, ax
2617 movsb
2619 memcpyb_end:
2620 pop si
2621 pop ds
2622 pop di
2623 pop es
2624 pop cx
2625 pop ax
2627 pop bp
2628 ASM_END
2631 // --------------------------------------------------------------------------------------------
2632 static void memcpyw(dseg,doffset,sseg,soffset,count)
2633 Bit16u dseg;
2634 Bit16u doffset;
2635 Bit16u sseg;
2636 Bit16u soffset;
2637 Bit16u count;
2639 ASM_START
2640 push bp
2641 mov bp, sp
2643 push ax
2644 push cx
2645 push es
2646 push di
2647 push ds
2648 push si
2650 mov cx, 12[bp] ; count
2651 cmp cx, #0x0000
2652 je memcpyw_end
2653 mov ax, 4[bp] ; dsegment
2654 mov es, ax
2655 mov ax, 6[bp] ; doffset
2656 mov di, ax
2657 mov ax, 8[bp] ; ssegment
2658 mov ds, ax
2659 mov ax, 10[bp] ; soffset
2660 mov si, ax
2663 movsw
2665 memcpyw_end:
2666 pop si
2667 pop ds
2668 pop di
2669 pop es
2670 pop cx
2671 pop ax
2673 pop bp
2674 ASM_END
2677 /* =========================================================== */
2679 * These functions where ripped from Kevin's rombios.c
2681 /* =========================================================== */
2683 // --------------------------------------------------------------------------------------------
2684 static Bit8u
2685 read_byte(seg, offset)
2686 Bit16u seg;
2687 Bit16u offset;
2689 ASM_START
2690 push bp
2691 mov bp, sp
2693 push bx
2694 push ds
2695 mov ax, 4[bp] ; segment
2696 mov ds, ax
2697 mov bx, 6[bp] ; offset
2698 mov al, [bx]
2699 ;; al = return value (byte)
2700 pop ds
2701 pop bx
2703 pop bp
2704 ASM_END
2707 // --------------------------------------------------------------------------------------------
2708 static Bit16u
2709 read_word(seg, offset)
2710 Bit16u seg;
2711 Bit16u offset;
2713 ASM_START
2714 push bp
2715 mov bp, sp
2717 push bx
2718 push ds
2719 mov ax, 4[bp] ; segment
2720 mov ds, ax
2721 mov bx, 6[bp] ; offset
2722 mov ax, [bx]
2723 ;; ax = return value (word)
2724 pop ds
2725 pop bx
2727 pop bp
2728 ASM_END
2731 // --------------------------------------------------------------------------------------------
2732 static void
2733 write_byte(seg, offset, data)
2734 Bit16u seg;
2735 Bit16u offset;
2736 Bit8u data;
2738 ASM_START
2739 push bp
2740 mov bp, sp
2742 push ax
2743 push bx
2744 push ds
2745 mov ax, 4[bp] ; segment
2746 mov ds, ax
2747 mov bx, 6[bp] ; offset
2748 mov al, 8[bp] ; data byte
2749 mov [bx], al ; write data byte
2750 pop ds
2751 pop bx
2752 pop ax
2754 pop bp
2755 ASM_END
2758 // --------------------------------------------------------------------------------------------
2759 static void
2760 write_word(seg, offset, data)
2761 Bit16u seg;
2762 Bit16u offset;
2763 Bit16u data;
2765 ASM_START
2766 push bp
2767 mov bp, sp
2769 push ax
2770 push bx
2771 push ds
2772 mov ax, 4[bp] ; segment
2773 mov ds, ax
2774 mov bx, 6[bp] ; offset
2775 mov ax, 8[bp] ; data word
2776 mov [bx], ax ; write data word
2777 pop ds
2778 pop bx
2779 pop ax
2781 pop bp
2782 ASM_END
2785 // --------------------------------------------------------------------------------------------
2786 Bit8u
2787 inb(port)
2788 Bit16u port;
2790 ASM_START
2791 push bp
2792 mov bp, sp
2794 push dx
2795 mov dx, 4[bp]
2796 in al, dx
2797 pop dx
2799 pop bp
2800 ASM_END
2803 Bit16u
2804 inw(port)
2805 Bit16u port;
2807 ASM_START
2808 push bp
2809 mov bp, sp
2811 push dx
2812 mov dx, 4[bp]
2813 in ax, dx
2814 pop dx
2816 pop bp
2817 ASM_END
2820 // --------------------------------------------------------------------------------------------
2821 void
2822 outb(port, val)
2823 Bit16u port;
2824 Bit8u val;
2826 ASM_START
2827 push bp
2828 mov bp, sp
2830 push ax
2831 push dx
2832 mov dx, 4[bp]
2833 mov al, 6[bp]
2834 out dx, al
2835 pop dx
2836 pop ax
2838 pop bp
2839 ASM_END
2842 // --------------------------------------------------------------------------------------------
2843 void
2844 outw(port, val)
2845 Bit16u port;
2846 Bit16u val;
2848 ASM_START
2849 push bp
2850 mov bp, sp
2852 push ax
2853 push dx
2854 mov dx, 4[bp]
2855 mov ax, 6[bp]
2856 out dx, ax
2857 pop dx
2858 pop ax
2860 pop bp
2861 ASM_END
2864 Bit16u get_SS()
2866 ASM_START
2867 mov ax, ss
2868 ASM_END
2871 #ifdef DEBUG
2872 void unimplemented()
2874 printf("--> Unimplemented\n");
2877 void unknown()
2879 printf("--> Unknown int10\n");
2881 #endif
2883 // --------------------------------------------------------------------------------------------
2884 void printf(s)
2885 Bit8u *s;
2887 Bit8u c, format_char;
2888 Boolean in_format;
2889 unsigned format_width, i;
2890 Bit16u *arg_ptr;
2891 Bit16u arg_seg, arg, digit, nibble, shift_count;
2893 arg_ptr = &s;
2894 arg_seg = get_SS();
2896 in_format = 0;
2897 format_width = 0;
2899 while (c = read_byte(0xc000, s)) {
2900 if ( c == '%' ) {
2901 in_format = 1;
2902 format_width = 0;
2904 else if (in_format) {
2905 if ( (c>='0') && (c<='9') ) {
2906 format_width = (format_width * 10) + (c - '0');
2908 else if (c == 'x') {
2909 arg_ptr++; // increment to next arg
2910 arg = read_word(arg_seg, arg_ptr);
2911 if (format_width == 0)
2912 format_width = 4;
2913 i = 0;
2914 digit = format_width - 1;
2915 for (i=0; i<format_width; i++) {
2916 nibble = (arg >> (4 * digit)) & 0x000f;
2917 if (nibble <= 9)
2918 outb(0x0500, nibble + '0');
2919 else
2920 outb(0x0500, (nibble - 10) + 'A');
2921 digit--;
2923 in_format = 0;
2925 //else if (c == 'd') {
2926 // in_format = 0;
2927 // }
2929 else {
2930 outb(0x0500, c);
2932 s ++;
2936 #ifdef VBE
2937 #include "vbe.c"
2938 #endif
2940 // --------------------------------------------------------------------------------------------
2942 ASM_START
2943 ;; DATA_SEG_DEFS_HERE
2944 ASM_END
2946 ASM_START
2947 .ascii "vgabios ends here"
2948 .byte 0x00
2949 vgabios_end:
2950 .byte 0xCB
2951 ;; BLOCK_STRINGS_BEGIN
2952 ASM_END