- biosfn_set_video_mode: don't load DAC registers if default palette loading is
[vgabios.git] / vgabios.c
blobeff047586dd4b8b2927685780de553e3c67ff27a
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 vgareg_sequ_address = 0x03c4
156 vgareg_grdc_address = 0x03ce
158 MACRO SET_INT_VECTOR
159 push ds
160 xor ax, ax
161 mov ds, ax
162 mov ax, ?3
163 mov ?1*4, ax
164 mov ax, ?2
165 mov ?1*4+2, ax
166 pop ds
167 MEND
169 ASM_END
171 ASM_START
172 .text
173 .rom
174 .org 0
176 use16 386
178 vgabios_start:
179 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
181 .byte 0x40 /* BIOS extension length in units of 512 bytes */
184 vgabios_entry_point:
186 jmp vgabios_init_func
188 vgabios_name:
189 .ascii "Plex86/Bochs VGABios"
190 .ascii " "
191 .byte 0x00
193 // Info from Bart Oldeman
194 .org 0x1e
195 .ascii "IBM"
196 .byte 0x00
198 vgabios_version:
199 #ifndef VGABIOS_VERS
200 .ascii "current-cvs"
201 #else
202 .ascii VGABIOS_VERS
203 #endif
204 .ascii " "
206 vgabios_date:
207 .ascii VGABIOS_DATE
208 .byte 0x0a,0x0d
209 .byte 0x00
211 vgabios_copyright:
212 .ascii "(C) 2003 the LGPL VGABios developers Team"
213 .byte 0x0a,0x0d
214 .byte 0x00
216 vgabios_license:
217 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
218 .byte 0x0a,0x0d
219 .byte 0x0a,0x0d
220 .byte 0x00
222 vgabios_website:
223 .ascii "Please visit :"
224 .byte 0x0a,0x0d
225 ;;.ascii " . http://www.plex86.org"
226 ;;.byte 0x0a,0x0d
227 .ascii " . http://bochs.sourceforge.net"
228 .byte 0x0a,0x0d
229 .ascii " . http://www.nongnu.org/vgabios"
230 .byte 0x0a,0x0d
231 .byte 0x0a,0x0d
232 .byte 0x00
235 ;; ============================================================================================
237 ;; Init Entry point
239 ;; ============================================================================================
240 vgabios_init_func:
242 ;; init vga card
243 call init_vga_card
245 ;; init basic bios vars
246 call init_bios_area
248 #ifdef VBE
249 ;; init vbe functions
250 call _vbe_init
251 #endif
253 ;; set int10 vect
254 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
256 ;; display splash screen
257 call _display_splash_screen
259 ;; init video mode and clear the screen
260 mov ax,#0x0003
261 int #0x10
263 ;; show info
264 call _display_info
266 #ifdef VBE
267 ;; show vbe info
268 call _vbe_display_info
269 #endif
272 retf
273 ASM_END
276 * int10 handled here
278 ASM_START
279 vgabios_int10_handler:
280 pushf
281 cmp ah, #0x0f
282 jne int10_test_1A
283 call biosfn_get_video_mode
284 jmp int10_end
285 int10_test_1A:
286 cmp ah, #0x1a
287 jne int10_normal
288 call biosfn_group_1A
289 jmp int10_end
291 int10_normal:
292 push es
293 push ds
294 pusha
296 ;; We have to set ds to access the right data segment
297 mov bx, #0xc000
298 mov ds, bx
299 call _int10_func
301 popa
302 pop ds
303 pop es
304 int10_end:
305 popf
306 iret
307 ASM_END
309 #include "vgatables.h"
310 #include "vgafonts.h"
313 * Boot time harware inits
315 ASM_START
316 init_vga_card:
317 ;; switch to color mode and enable CPU access 480 lines
318 mov dx, #0x3C2
319 mov al, #0xC3
320 outb dx,al
322 ;; more than 64k 3C4/04
323 mov dx, #0x3C4
324 mov al, #0x04
325 outb dx,al
326 mov dx, #0x3C5
327 mov al, #0x02
328 outb dx,al
330 mov bx, #msg_vga_init
331 push bx
332 call _printf
333 inc sp
334 inc sp
337 msg_vga_init:
338 .ascii "VGABios $Id$"
339 .byte 0x0d,0x0a,0x00
340 ASM_END
342 // --------------------------------------------------------------------------------------------
344 * Boot time bios area inits
346 ASM_START
347 init_bios_area:
348 push ds
349 mov ax, #biosmem_seg
350 mov ds, ax
352 ;; init detected hardware BIOS Area
353 mov bx, #biosmem_initial_mode
354 mov ax, [bx]
355 and ax, #0xffcf
356 mov [bx], ax
358 ;; Just for the first int10 find its children
360 ;; the default char height
361 mov bx, #biosmem_char_height
362 mov al, #0x10
363 mov [bx], al
365 ;; Clear the screen
366 mov bx, #biosmem_video_ctl
367 mov al, #0x60
368 mov [bx], al
370 ;; Set the basic screen we have
371 mov bx, #biosmem_switches
372 mov al, #0xf9
373 mov [bx], al
375 ;; Set the basic modeset options
376 mov bx, #biosmem_modeset_ctl
377 mov al, #0x51
378 mov [bx], al
380 ;; Set the default MSR
381 mov bx, #biosmem_current_msr
382 mov al, #0x09
383 mov [bx], al
385 pop ds
387 ASM_END
389 // --------------------------------------------------------------------------------------------
391 * Boot time Splash screen
393 static void display_splash_screen()
397 // --------------------------------------------------------------------------------------------
399 * Tell who we are
402 static void display_info()
404 ASM_START
405 mov ax,#0xc000
406 mov ds,ax
407 mov si,#vgabios_name
408 call _display_string
409 mov si,#vgabios_version
410 call _display_string
412 ;;mov si,#vgabios_copyright
413 ;;call _display_string
414 ;;mov si,#crlf
415 ;;call _display_string
417 mov si,#vgabios_license
418 call _display_string
419 mov si,#vgabios_website
420 call _display_string
421 ASM_END
424 static void display_string()
426 // Get length of string
427 ASM_START
428 mov ax,ds
429 mov es,ax
430 mov di,si
431 xor cx,cx
432 not cx
433 xor al,al
435 repne
436 scasb
437 not cx
438 dec cx
439 push cx
441 mov ax,#0x0300
442 mov bx,#0x0000
443 int #0x10
445 pop cx
446 mov ax,#0x1301
447 mov bx,#0x000b
448 mov bp,si
449 int #0x10
450 ASM_END
453 // --------------------------------------------------------------------------------------------
455 // --------------------------------------------------------------------------------------------
457 * int10 main dispatcher
459 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
460 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
462 #ifdef DEBUG
463 // 0E is write char...
464 if(GET_AH()!=0x0E)
465 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
466 #endif
468 // BIOS functions
469 switch(GET_AH())
471 case 0x00:
472 biosfn_set_video_mode(GET_AL());
473 switch(GET_AL()&0x7F)
474 {case 6:
475 SET_AL(0x3F);
476 break;
477 case 0:
478 case 1:
479 case 2:
480 case 3:
481 case 4:
482 case 5:
483 case 7:
484 SET_AL(0x30);
485 break;
486 default:
487 SET_AL(0x20);
489 break;
490 case 0x01:
491 biosfn_set_cursor_shape(GET_CH(),GET_CL());
492 break;
493 case 0x02:
494 biosfn_set_cursor_pos(GET_BH(),DX);
495 break;
496 case 0x03:
497 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
498 break;
499 case 0x04:
500 // Read light pen pos (unimplemented)
501 #ifdef DEBUG
502 unimplemented();
503 #endif
504 AX=0x00;
505 BX=0x00;
506 CX=0x00;
507 DX=0x00;
508 break;
509 case 0x05:
510 biosfn_set_active_page(GET_AL());
511 break;
512 case 0x06:
513 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
514 break;
515 case 0x07:
516 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
517 break;
518 case 0x08:
519 biosfn_read_char_attr(GET_BH(),&AX);
520 break;
521 case 0x09:
522 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
523 break;
524 case 0x0A:
525 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
526 break;
527 case 0x0B:
528 if(GET_BH()==0x00)
529 biosfn_set_border_color(GET_BL());
530 else
531 biosfn_set_palette(GET_BL());
532 break;
533 case 0x0C:
534 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
535 break;
536 case 0x0D:
537 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
538 break;
539 case 0x0E:
540 // Ralf Brown Interrupt list is WRONG on bh(page)
541 // We do output only on the current page !
542 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
543 break;
544 case 0x10:
545 switch(GET_AL())
547 case 0x00:
548 biosfn_set_single_palette_reg(GET_BL(),GET_BH());
549 break;
550 case 0x01:
551 biosfn_set_overscan_border_color(GET_BH());
552 break;
553 case 0x02:
554 biosfn_set_all_palette_reg(ES,DX);
555 break;
556 case 0x03:
557 biosfn_toggle_intensity(GET_BL());
558 break;
559 case 0x07:
560 biosfn_get_single_palette_reg(GET_BL(),&BX);
561 break;
562 case 0x08:
563 biosfn_read_overscan_border_color(&BX);
564 break;
565 case 0x09:
566 biosfn_get_all_palette_reg(ES,DX);
567 break;
568 case 0x10:
569 biosfn_set_single_dac_reg(BX,GET_CH(),GET_CL(),GET_DH());
570 break;
571 case 0x12:
572 biosfn_set_all_dac_reg(BX,CX,ES,DX);
573 break;
574 case 0x13:
575 biosfn_select_video_dac_color_page(GET_BL(),GET_BH());
576 break;
577 case 0x15:
578 biosfn_read_single_dac_reg(GET_BL(),&DX,&CX);
579 break;
580 case 0x17:
581 biosfn_read_all_dac_reg(BX,CX,ES,DX);
582 break;
583 case 0x18:
584 biosfn_set_pel_mask(GET_BL());
585 break;
586 case 0x19:
587 biosfn_read_pel_mask(&BX);
588 break;
589 case 0x1A:
590 biosfn_read_video_dac_state(&BX);
591 break;
592 case 0x1B:
593 biosfn_perform_gray_scale_summing(BX,CX);
594 break;
595 #ifdef DEBUG
596 default:
597 unknown();
598 #endif
600 break;
601 case 0x11:
602 switch(GET_AL())
604 case 0x00:
605 case 0x10:
606 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
607 break;
608 case 0x01:
609 case 0x11:
610 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
611 break;
612 case 0x02:
613 case 0x12:
614 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
615 break;
616 case 0x03:
617 biosfn_set_text_block_specifier(GET_BL());
618 break;
619 case 0x04:
620 case 0x14:
621 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
622 break;
623 case 0x20:
624 biosfn_load_gfx_8_8_chars(ES,BP);
625 break;
626 case 0x21:
627 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
628 break;
629 case 0x22:
630 biosfn_load_gfx_8_14_chars(GET_BL());
631 break;
632 case 0x23:
633 biosfn_load_gfx_8_8_dd_chars(GET_BL());
634 break;
635 case 0x24:
636 biosfn_load_gfx_8_16_chars(GET_BL());
637 break;
638 case 0x30:
639 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
640 break;
641 #ifdef DEBUG
642 default:
643 unknown();
644 #endif
647 break;
648 case 0x12:
649 switch(GET_BL())
651 case 0x10:
652 biosfn_get_ega_info(&BX,&CX);
653 break;
654 case 0x20:
655 biosfn_alternate_prtsc();
656 break;
657 case 0x30:
658 biosfn_select_vert_res(GET_AL());
659 SET_AL(0x12);
660 break;
661 case 0x31:
662 biosfn_enable_default_palette_loading(GET_AL());
663 SET_AL(0x12);
664 break;
665 case 0x32:
666 biosfn_enable_video_addressing(GET_AL());
667 SET_AL(0x12);
668 break;
669 case 0x33:
670 biosfn_enable_grayscale_summing(GET_AL());
671 SET_AL(0x12);
672 break;
673 case 0x34:
674 biosfn_enable_cursor_emulation(GET_AL());
675 SET_AL(0x12);
676 break;
677 case 0x35:
678 biosfn_switch_video_interface(GET_AL(),ES,DX);
679 SET_AL(0x12);
680 break;
681 case 0x36:
682 biosfn_enable_video_refresh_control(GET_AL());
683 SET_AL(0x12);
684 break;
685 #ifdef DEBUG
686 default:
687 unknown();
688 #endif
690 break;
691 case 0x13:
692 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
693 break;
694 case 0x1B:
695 biosfn_read_state_info(BX,ES,DI);
696 SET_AL(0x1B);
697 break;
698 case 0x1C:
699 switch(GET_AL())
701 case 0x00:
702 biosfn_read_video_state_size(CX,&BX);
703 break;
704 case 0x01:
705 biosfn_save_video_state(CX,ES,BX);
706 break;
707 case 0x02:
708 biosfn_restore_video_state(CX,ES,BX);
709 break;
710 #ifdef DEBUG
711 default:
712 unknown();
713 #endif
715 SET_AL(0x1C);
716 break;
718 #ifdef VBE
719 case 0x4f:
720 if (vbe_has_vbe_display()) {
721 switch(GET_AL())
723 case 0x00:
724 vbe_biosfn_return_controller_information(&AX,ES,DI);
725 break;
726 case 0x01:
727 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
728 break;
729 case 0x02:
730 vbe_biosfn_set_mode(&AX,BX,ES,DI);
731 break;
732 case 0x03:
733 vbe_biosfn_return_current_mode(&AX,&BX);
734 break;
735 case 0x04:
736 //FIXME
737 #ifdef DEBUG
738 unimplemented();
739 #endif
740 // function failed
741 AX=0x100;
742 break;
743 case 0x05:
744 vbe_biosfn_display_window_control(&AX,BX,&DX);
745 break;
746 case 0x06:
747 vbe_biosfn_set_get_logical_scan_line_length(&AX,&BX,&CX,&DX);
748 break;
749 case 0x07:
750 vbe_biosfn_set_get_display_start(&AX,BX,CX,DX);
751 break;
752 case 0x08:
753 //FIXME
754 #ifdef DEBUG
755 unimplemented();
756 #endif
757 // function failed
758 AX=0x100;
759 break;
760 case 0x09:
761 //FIXME
762 #ifdef DEBUG
763 unimplemented();
764 #endif
765 // function failed
766 AX=0x100;
767 break;
768 case 0x0A:
769 //FIXME
770 #ifdef DEBUG
771 unimplemented();
772 #endif
773 // function failed
774 AX=0x100;
775 break;
776 #ifdef DEBUG
777 default:
778 unknown();
779 #endif
780 // function failed
781 AX=0x100;
784 else {
785 // No VBE display
786 AX=0x0100;
788 break;
789 #endif
791 #ifdef DEBUG
792 default:
793 unknown();
794 #endif
798 // ============================================================================================
800 // BIOS functions
802 // ============================================================================================
804 static void biosfn_set_video_mode(mode) Bit8u mode;
805 {// mode: Bit 7 is 1 if no clear screen
807 // Should we clear the screen ?
808 Bit8u noclearmem=mode&0x80;
809 Bit8u line,mmask,*palette;
810 Bit16u i,twidth,theight,cheight;
811 Bit8u modeset_ctl,video_ctl,vga_switches;
812 Bit16u crtc_addr;
814 #ifdef VBE
815 if (vbe_has_vbe_display()) {
816 dispi_set_enable(VBE_DISPI_DISABLED);
818 #endif // def VBE
820 // The real mode
821 mode=mode&0x7f;
823 // find the entry in the video modes
824 line=find_vga_entry(mode);
826 #ifdef DEBUG
827 printf("mode search %02x found line %02x\n",mode,line);
828 #endif
830 if(line==0xFF)
831 return;
833 twidth=vga_modes[line].twidth;
834 theight=vga_modes[line].theight;
835 cheight=vga_modes[line].cheight;
837 // Read the bios vga control
838 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
840 // Read the bios vga switches
841 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
843 // Read the bios mode set control
844 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
846 // Then we know the number of lines
847 // FIXME
849 // if palette loading (bit 3 of modeset ctl = 0)
850 if((modeset_ctl&0x08)==0)
851 {// Set the PEL mask
852 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
854 // Set the whole dac always, from 0
855 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
857 // From which palette
858 switch(vga_modes[line].dacmodel)
859 {case 0:
860 palette=&palette0;
861 break;
862 case 1:
863 palette=&palette1;
864 break;
865 case 2:
866 palette=&palette2;
867 break;
868 case 3:
869 palette=&palette3;
870 break;
872 // Always 256*3 values
873 for(i=0;i<0x0100;i++)
874 {if(i<=dac_regs[vga_modes[line].dacmodel])
875 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
876 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
877 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
879 else
880 {outb(VGAREG_DAC_DATA,0);
881 outb(VGAREG_DAC_DATA,0);
882 outb(VGAREG_DAC_DATA,0);
885 if((modeset_ctl&0x02)==0x02)
887 biosfn_perform_gray_scale_summing(0x00, 0x100);
891 // Reset Attribute Ctl flip-flop
892 inb(VGAREG_ACTL_RESET);
894 // Set Attribute Ctl
895 for(i=0;i<=ACTL_MAX_REG;i++)
896 {outb(VGAREG_ACTL_ADDRESS,i);
897 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
900 // Set Sequencer Ctl
901 for(i=0;i<=SEQU_MAX_REG;i++)
902 {outb(VGAREG_SEQU_ADDRESS,i);
903 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
906 // Set Grafx Ctl
907 for(i=0;i<=GRDC_MAX_REG;i++)
908 {outb(VGAREG_GRDC_ADDRESS,i);
909 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
912 // Set CRTC address VGA or MDA
913 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
915 // Set CRTC regs
916 for(i=0;i<=CRTC_MAX_REG;i++)
917 {outb(crtc_addr,i);
918 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
921 // Set the misc register
922 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
924 // Enable video
925 outb(VGAREG_ACTL_ADDRESS,0x20);
926 inb(VGAREG_ACTL_RESET);
928 if(noclearmem==0x00)
930 if(vga_modes[line].class==TEXT)
932 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
934 else
936 if(mode<0x0d)
938 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
940 else
942 outb( VGAREG_SEQU_ADDRESS, 0x02 );
943 mmask = inb( VGAREG_SEQU_DATA );
944 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
945 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
946 outb( VGAREG_SEQU_DATA, mmask );
951 // Set the BIOS mem
952 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
953 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
954 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
955 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
956 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
957 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
958 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
959 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
960 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
962 // FIXME We nearly have the good tables. to be reworked
963 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
964 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
965 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
967 // FIXME
968 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
969 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
971 // Set cursor shape
972 if(vga_modes[line].class==TEXT)
974 biosfn_set_cursor_shape(0x06,0x07);
977 // Set cursor pos for page 0..7
978 for(i=0;i<8;i++)
979 biosfn_set_cursor_pos(i,0x0000);
981 // Set active page 0
982 biosfn_set_active_page(0x00);
984 // Write the fonts in memory
985 if(vga_modes[line].class==TEXT)
987 ASM_START
988 ;; copy and activate 8x16 font
989 mov ax, #0x1104
990 mov bl, #0x00
991 int #0x10
992 mov ax, #0x1103
993 mov bl, #0x00
994 int #0x10
995 ASM_END
998 // Set the ints 0x1F and 0x43
999 ASM_START
1000 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
1001 ASM_END
1003 switch(cheight)
1004 {case 8:
1005 ASM_START
1006 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
1007 ASM_END
1008 break;
1009 case 14:
1010 ASM_START
1011 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
1012 ASM_END
1013 break;
1014 case 16:
1015 ASM_START
1016 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
1017 ASM_END
1018 break;
1022 // --------------------------------------------------------------------------------------------
1023 static void biosfn_set_cursor_shape (CH,CL)
1024 Bit8u CH;Bit8u CL;
1025 {Bit16u cheight,curs,crtc_addr;
1027 CH&=0x3f;
1028 CL&=0x1f;
1030 curs=(CH<<8)+CL;
1031 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1033 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1034 if((cheight>8) && (CL<8) && (CH<0x20))
1036 if(CL!=(CH+1))
1038 CH = ((CH+1) * cheight / 8) -1;
1040 else
1042 CH = ((CL+1) * cheight / 8) - 2;
1044 CL = ((CL+1) * cheight / 8) - 1;
1047 // CTRC regs 0x0a and 0x0b
1048 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1049 outb(crtc_addr,0x0a);
1050 outb(crtc_addr+1,CH);
1051 outb(crtc_addr,0x0b);
1052 outb(crtc_addr+1,CL);
1055 // --------------------------------------------------------------------------------------------
1056 static void biosfn_set_cursor_pos (page, cursor)
1057 Bit8u page;Bit16u cursor;
1059 Bit8u xcurs,ycurs,current;
1060 Bit16u nbcols,nbrows,address,crtc_addr;
1062 // Should not happen...
1063 if(page>7)return;
1065 // Bios cursor pos
1066 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1068 // Set the hardware cursor
1069 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1070 if(page==current)
1072 // Get the dimensions
1073 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1074 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1076 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1078 // Calculate the address knowing nbcols nbrows and page num
1079 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1081 // CRTC regs 0x0e and 0x0f
1082 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1083 outb(crtc_addr,0x0e);
1084 outb(crtc_addr+1,(address&0xff00)>>8);
1085 outb(crtc_addr,0x0f);
1086 outb(crtc_addr+1,address&0x00ff);
1090 // --------------------------------------------------------------------------------------------
1091 static void biosfn_get_cursor_pos (page,shape, pos)
1092 Bit8u page;Bit16u *shape;Bit16u *pos;
1094 Bit16u ss=get_SS();
1096 // Default
1097 write_word(ss, shape, 0);
1098 write_word(ss, pos, 0);
1100 if(page>7)return;
1101 // FIXME should handle VGA 14/16 lines
1102 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1103 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1106 // --------------------------------------------------------------------------------------------
1107 static void biosfn_set_active_page (page)
1108 Bit8u page;
1110 Bit16u cursor,dummy,crtc_addr;
1111 Bit16u nbcols,nbrows,address;
1112 Bit8u mode,line;
1114 if(page>7)return;
1116 // Get the mode
1117 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1118 line=find_vga_entry(mode);
1119 if(line==0xFF)return;
1121 // Get pos curs pos for the right page
1122 biosfn_get_cursor_pos(page,&dummy,&cursor);
1124 if(vga_modes[line].class==TEXT)
1126 // Get the dimensions
1127 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1128 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1130 // Calculate the address knowing nbcols nbrows and page num
1131 address=SCREEN_MEM_START(nbcols,nbrows,page);
1132 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1134 // Start address
1135 address=SCREEN_IO_START(nbcols,nbrows,page);
1137 else
1139 address = page*vga_modes[line].slength;
1142 // CRTC regs 0x0c and 0x0d
1143 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1144 outb(crtc_addr,0x0c);
1145 outb(crtc_addr+1,(address&0xff00)>>8);
1146 outb(crtc_addr,0x0d);
1147 outb(crtc_addr+1,address&0x00ff);
1149 // And change the BIOS page
1150 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1152 #ifdef DEBUG
1153 printf("Set active page %02x address %04x\n",page,address);
1154 #endif
1156 // Display the cursor, now the page is active
1157 biosfn_set_cursor_pos(page,cursor);
1160 // --------------------------------------------------------------------------------------------
1161 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1162 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1164 // page == 0xFF if current
1166 Bit8u mode,line;
1167 Bit16u nbcols,nbrows,i;
1168 Bit16u address;
1170 if(rul>rlr)return;
1171 if(cul>clr)return;
1173 // Get the mode
1174 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1175 line=find_vga_entry(mode);
1176 if(line==0xFF)return;
1178 // Get the dimensions
1179 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1180 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1182 // Get the current page
1183 if(page==0xFF)
1184 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1186 if(vga_modes[line].class==TEXT)
1188 // Compute the address
1189 address=SCREEN_MEM_START(nbcols,nbrows,page);
1190 #ifdef DEBUG
1191 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1192 #endif
1194 if(rlr>=nbrows)rlr=nbrows-1;
1195 if(clr>=nbcols)clr=nbcols-1;
1196 if(nblines>nbrows)nblines=0;
1198 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1200 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1202 else
1203 {// if Scroll up
1204 if(dir==SCROLL_UP)
1205 {for(i=rul;i<=rlr;i++)
1207 if((i+nblines>rlr)||(nblines==0))
1208 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1209 else
1210 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,clr-cul+1);
1213 else
1214 {for(i=rlr;i>=rul;i--)
1216 if((i<rul+nblines)||(nblines==0))
1217 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1218 else
1219 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,clr-cul+1);
1224 else
1226 // FIXME gfx mode
1227 #ifdef DEBUG
1228 printf("Scroll in graphics mode ");
1229 unimplemented();
1230 #endif
1234 // --------------------------------------------------------------------------------------------
1235 static void biosfn_read_char_attr (page,car)
1236 Bit8u page;Bit16u *car;
1237 {Bit16u ss=get_SS();
1238 Bit8u xcurs,ycurs,mode,line;
1239 Bit16u nbcols,nbrows,address;
1240 Bit16u cursor,dummy;
1242 // Get the mode
1243 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1244 line=find_vga_entry(mode);
1245 if(line==0xFF)return;
1247 // Get the cursor pos for the page
1248 biosfn_get_cursor_pos(page,&dummy,&cursor);
1249 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1251 // Get the dimensions
1252 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1253 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1255 if(vga_modes[line].class==TEXT)
1257 // Compute the address
1258 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1260 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1262 else
1264 // FIXME gfx mode
1265 #ifdef DEBUG
1266 unimplemented();
1267 #endif
1271 // --------------------------------------------------------------------------------------------
1272 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1273 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1275 Bit8u i,mmask;
1276 Bit8u *fdata;
1277 Bit16u addr,dest,src;
1279 switch(cheight)
1280 {case 14:
1281 fdata = &vgafont14;
1282 break;
1283 case 16:
1284 fdata = &vgafont16;
1285 break;
1286 default:
1287 fdata = &vgafont8;
1289 addr=xcurs+ycurs*cheight*nbcols;
1290 src = car * cheight;
1291 outb( VGAREG_SEQU_ADDRESS, 0x02 );
1292 mmask = inb( VGAREG_SEQU_DATA );
1293 for(i=0;i<cheight;i++)
1295 dest=addr+i*nbcols;
1296 outb( VGAREG_SEQU_DATA, 0x0f );
1297 write_byte(0xa000,dest,0x00);
1298 outb( VGAREG_SEQU_DATA, attr & 0x0f );
1299 write_byte(0xa000,dest,fdata[src+i]);
1301 outb( VGAREG_SEQU_DATA, mmask );
1304 // --------------------------------------------------------------------------------------------
1305 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1306 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1308 Bit8u i,j,mask,data;
1309 Bit8u *fdata;
1310 Bit16u addr,dest,src;
1312 fdata = &vgafont8;
1313 addr=(xcurs*bpp)+ycurs*320;
1314 src = car * 8;
1315 for(i=0;i<8;i++)
1317 dest=addr+(i>>1)*80;
1318 if (i & 1) dest += 0x2000;
1319 mask = 0x80;
1320 if (bpp == 1)
1322 if (attr & 0x80)
1324 data = read_byte(0xb800,dest);
1326 else
1328 data = 0x00;
1330 for(j=0;j<8;j++)
1332 if (fdata[src+i] & mask)
1334 if (attr & 0x80)
1336 data ^= (attr & 0x01) << (7-j);
1338 else
1340 data |= (attr & 0x01) << (7-j);
1343 mask >>= 1;
1345 write_byte(0xb800,dest,data);
1347 else
1349 while (mask > 0)
1351 if (attr & 0x80)
1353 data = read_byte(0xb800,dest);
1355 else
1357 data = 0x00;
1359 for(j=0;j<4;j++)
1361 if (fdata[src+i] & mask)
1363 if (attr & 0x80)
1365 data ^= (attr & 0x03) << ((3-j)*2);
1367 else
1369 data |= (attr & 0x03) << ((3-j)*2);
1372 mask >>= 1;
1374 write_byte(0xb800,dest,data);
1375 dest += 1;
1381 // --------------------------------------------------------------------------------------------
1382 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1383 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1385 Bit8u i,j,mask,data;
1386 Bit8u *fdata;
1387 Bit16u addr,dest,src;
1389 fdata = &vgafont8;
1390 addr=xcurs*8+ycurs*nbcols*64;
1391 src = car * 8;
1392 for(i=0;i<8;i++)
1394 dest=addr+i*nbcols*8;
1395 mask = 0x80;
1396 for(j=0;j<8;j++)
1398 data = 0x00;
1399 if (fdata[src+i] & mask)
1401 data = attr;
1403 write_byte(0xa000,dest+j,data);
1404 mask >>= 1;
1409 // --------------------------------------------------------------------------------------------
1410 static void biosfn_write_char_attr (car,page,attr,count)
1411 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1413 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1414 Bit16u nbcols,nbrows,address;
1415 Bit16u cursor,dummy;
1417 // Get the mode
1418 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1419 line=find_vga_entry(mode);
1420 if(line==0xFF)return;
1422 // Get the cursor pos for the page
1423 biosfn_get_cursor_pos(page,&dummy,&cursor);
1424 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1426 // Get the dimensions
1427 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1428 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1430 if(vga_modes[line].class==TEXT)
1432 // Compute the address
1433 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1435 dummy=((Bit16u)attr<<8)+car;
1436 memsetw(vga_modes[line].sstart,address,dummy,count);
1438 else
1440 // FIXME gfx mode not complete
1441 cheight=vga_modes[line].cheight;
1442 bpp=vga_modes[line].pixbits;
1443 while((count-->0) && (xcurs<nbcols))
1445 if(vga_modes[line].memmodel==PLANAR4)
1447 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1449 else if(vga_modes[line].memmodel==CGA)
1451 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1453 else if(vga_modes[line].memmodel==LINEAR8)
1455 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1457 else
1459 #ifdef DEBUG
1460 unimplemented();
1461 #endif
1463 xcurs++;
1468 // --------------------------------------------------------------------------------------------
1469 static void biosfn_write_char_only (car,page,attr,count)
1470 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1472 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1473 Bit16u nbcols,nbrows,address;
1474 Bit16u cursor,dummy;
1476 // Get the mode
1477 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1478 line=find_vga_entry(mode);
1479 if(line==0xFF)return;
1481 // Get the cursor pos for the page
1482 biosfn_get_cursor_pos(page,&dummy,&cursor);
1483 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1485 // Get the dimensions
1486 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1487 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1489 if(vga_modes[line].class==TEXT)
1491 // Compute the address
1492 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1494 while(count-->0)
1495 {write_byte(vga_modes[line].sstart,address,car);
1496 address+=2;
1499 else
1501 // FIXME gfx mode not complete
1502 cheight=vga_modes[line].cheight;
1503 bpp=vga_modes[line].pixbits;
1504 while((count-->0) && (xcurs<nbcols))
1506 if(vga_modes[line].memmodel==PLANAR4)
1508 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1510 else if(vga_modes[line].memmodel==CGA)
1512 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1514 else if(vga_modes[line].memmodel==LINEAR8)
1516 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1518 else
1520 #ifdef DEBUG
1521 unimplemented();
1522 #endif
1524 xcurs++;
1529 // --------------------------------------------------------------------------------------------
1530 static void biosfn_set_border_color (BL) Bit8u BL;
1531 // FIXME anybody using this function ?
1533 #ifdef DEBUG
1534 unimplemented();
1535 #endif
1538 // --------------------------------------------------------------------------------------------
1539 static void biosfn_set_palette (BL) Bit8u BL;
1540 // FIXME anybody using this function ?
1542 #ifdef DEBUG
1543 unimplemented();
1544 #endif
1547 // --------------------------------------------------------------------------------------------
1548 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1550 Bit8u mode,line,mask,attr;
1551 Bit16u addr,data;
1553 // Get the mode
1554 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1555 line=find_vga_entry(mode);
1556 if(line==0xFF)return;
1557 if(vga_modes[line].class==TEXT)return;
1559 if(vga_modes[line].memmodel==CGA)
1561 if(vga_modes[line].pixbits==2)
1563 addr=(CX>>2)+(DX>>1)*80;
1565 else
1567 addr=(CX>>3)+(DX>>1)*80;
1569 if (DX & 1) addr += 0x2000;
1570 data = read_byte(0xb800,addr);
1571 if(vga_modes[line].pixbits==2)
1573 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1574 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1576 else
1578 attr = (AL & 0x01) << (7 - (CX & 0x07));
1579 mask = 0x01 << (7 - (CX & 0x07));
1581 if (AL & 0x80)
1583 data ^= attr;
1585 else
1587 data &= ~mask;
1588 data |= attr;
1590 write_byte(0xb800,addr,data);
1592 else if(vga_modes[line].memmodel==LINEAR8)
1594 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1595 write_byte(0xa000,addr,AL);
1597 else
1599 #ifdef DEBUG
1600 unimplemented();
1601 #endif
1605 // --------------------------------------------------------------------------------------------
1606 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1608 Bit8u mode,line,attr;
1609 Bit16u addr,data;
1610 Bit16u ss=get_SS();
1612 // Get the mode
1613 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1614 line=find_vga_entry(mode);
1615 if(line==0xFF)return;
1616 if(vga_modes[line].class==TEXT)return;
1618 if(vga_modes[line].memmodel==CGA)
1620 addr=(CX>>2)+(DX>>1)*80;
1621 if (DX & 1) addr += 0x2000;
1622 data = read_byte(0xb800,addr);
1623 if(vga_modes[line].pixbits==2)
1625 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1627 else
1629 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1632 else if(vga_modes[line].memmodel==LINEAR8)
1634 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1635 attr=read_byte(0xa000,addr);
1637 else
1639 #ifdef DEBUG
1640 unimplemented();
1641 #endif
1642 attr = 0;
1644 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1647 // --------------------------------------------------------------------------------------------
1648 static void biosfn_write_teletype (car, page, attr, flag)
1649 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1650 {// flag = WITH_ATTR / NO_ATTR
1652 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1653 Bit16u nbcols,nbrows,address;
1654 Bit16u cursor,dummy;
1656 // special case if page is 0xff, use current page
1657 if(page==0xff)
1658 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1660 // FIXME gfx mode
1662 // Get the mode
1663 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1664 line=find_vga_entry(mode);
1665 if(line==0xFF)return;
1667 // Get the cursor pos for the page
1668 biosfn_get_cursor_pos(page,&dummy,&cursor);
1669 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1671 // Get the dimensions
1672 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1673 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1675 switch(car)
1677 case 7:
1678 //FIXME should beep
1679 break;
1681 case 8:
1682 if(xcurs>0)xcurs--;
1683 break;
1685 case '\r':
1686 xcurs=0;
1687 break;
1689 case '\n':
1690 xcurs=0;
1691 ycurs++;
1692 break;
1694 case '\t':
1697 biosfn_write_teletype(' ',page,attr,flag);
1698 biosfn_get_cursor_pos(page,&dummy,&cursor);
1699 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1700 }while(xcurs%8==0);
1701 break;
1703 default:
1705 if(vga_modes[line].class==TEXT)
1707 // Compute the address
1708 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1710 // Write the char
1711 write_byte(vga_modes[line].sstart,address,car);
1713 if(flag==WITH_ATTR)
1714 write_byte(vga_modes[line].sstart,address+1,attr);
1716 else
1718 // FIXME gfx mode not complete
1719 cheight=vga_modes[line].cheight;
1720 bpp=vga_modes[line].pixbits;
1721 if(vga_modes[line].memmodel==PLANAR4)
1723 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1725 else if(vga_modes[line].memmodel==CGA)
1727 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1729 else if(vga_modes[line].memmodel==LINEAR8)
1731 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1733 else
1735 #ifdef DEBUG
1736 unimplemented();
1737 #endif
1741 xcurs++;
1744 // Do we need to wrap ?
1745 if(xcurs==nbcols)
1746 {xcurs=0;
1747 ycurs++;
1750 // Do we need to scroll ?
1751 if(ycurs==nbrows)
1752 {biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1753 ycurs-=1;
1756 // Set the cursor for the page
1757 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1758 biosfn_set_cursor_pos(page,cursor);
1761 // --------------------------------------------------------------------------------------------
1762 ASM_START
1763 biosfn_get_video_mode:
1764 push ds
1765 mov ax, #biosmem_seg
1766 mov ds, ax
1767 push bx
1768 mov bx, #biosmem_current_page
1769 mov al, [bx]
1770 pop bx
1771 mov bh, al
1772 push bx
1773 mov bx, #biosmem_video_ctl
1774 mov ah, [bx]
1775 and ah, #0x80
1776 mov bx, #biosmem_current_mode
1777 mov al, [bx]
1778 or al, ah
1779 mov bx, #biosmem_nb_cols
1780 mov ah, [bx]
1781 pop bx
1782 pop ds
1784 ASM_END
1786 // --------------------------------------------------------------------------------------------
1787 static void biosfn_set_single_palette_reg (reg,value)
1788 Bit8u reg;Bit8u value;
1790 if(reg<=ACTL_MAX_REG)
1792 inb(VGAREG_ACTL_RESET);
1793 outb(VGAREG_ACTL_ADDRESS,reg);
1794 outb(VGAREG_ACTL_WRITE_DATA,value);
1795 outb(VGAREG_ACTL_ADDRESS,0x20);
1799 // --------------------------------------------------------------------------------------------
1800 static void biosfn_set_overscan_border_color (value)
1801 Bit8u value;
1803 inb(VGAREG_ACTL_RESET);
1804 outb(VGAREG_ACTL_ADDRESS,0x11);
1805 outb(VGAREG_ACTL_WRITE_DATA,value);
1806 outb(VGAREG_ACTL_ADDRESS,0x20);
1809 // --------------------------------------------------------------------------------------------
1810 static void biosfn_set_all_palette_reg (seg,offset)
1811 Bit16u seg;Bit16u offset;
1813 Bit8u i;
1815 inb(VGAREG_ACTL_RESET);
1816 // First the colors
1817 for(i=0;i<0x10;i++)
1819 outb(VGAREG_ACTL_ADDRESS,i);
1820 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1821 offset++;
1824 // Then the border
1825 outb(VGAREG_ACTL_ADDRESS,0x11);
1826 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1827 outb(VGAREG_ACTL_ADDRESS,0x20);
1830 // --------------------------------------------------------------------------------------------
1831 static void biosfn_toggle_intensity (state)
1832 Bit8u state;
1833 {Bit8u value;
1834 state&=0x01;
1835 inb(VGAREG_ACTL_RESET);
1837 outb(VGAREG_ACTL_ADDRESS,0x10);
1838 value=inb(VGAREG_ACTL_READ_DATA);
1839 value&=0xf7;
1840 value|=state<<3;
1841 outb(VGAREG_ACTL_WRITE_DATA,value);
1842 outb(VGAREG_ACTL_ADDRESS,0x20);
1845 // --------------------------------------------------------------------------------------------
1846 static void biosfn_get_single_palette_reg (reg,value)
1847 Bit8u reg;Bit16u *value;
1848 {Bit16u ss=get_SS();
1850 if(reg<=ACTL_MAX_REG)
1852 inb(VGAREG_ACTL_RESET);
1853 outb(VGAREG_ACTL_ADDRESS,reg);
1854 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1855 inb(VGAREG_ACTL_RESET);
1856 outb(VGAREG_ACTL_ADDRESS,0x20);
1860 // --------------------------------------------------------------------------------------------
1861 static void biosfn_read_overscan_border_color (value)
1862 Bit16u *value;
1863 {Bit16u ss=get_SS();
1865 inb(VGAREG_ACTL_RESET);
1866 outb(VGAREG_ACTL_ADDRESS,0x11);
1867 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1868 outb(VGAREG_ACTL_ADDRESS,0x20);
1871 // --------------------------------------------------------------------------------------------
1872 static void biosfn_get_all_palette_reg (seg,offset) Bit16u seg;Bit16u offset;
1874 Bit8u i;
1876 // First the colors
1877 for(i=0;i<0x10;i++)
1879 inb(VGAREG_ACTL_RESET);
1880 outb(VGAREG_ACTL_ADDRESS,i);
1881 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1882 offset++;
1885 // Then the border
1886 outb(VGAREG_ACTL_ADDRESS,0x11);
1887 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1888 outb(VGAREG_ACTL_ADDRESS,0x20);
1891 // --------------------------------------------------------------------------------------------
1892 static void biosfn_set_single_dac_reg (reg,g,b,r)
1893 Bit16u reg;Bit8u g;Bit8u b;Bit8u r;
1895 outb(VGAREG_DAC_WRITE_ADDRESS,reg);
1896 outb(VGAREG_DAC_DATA,r);
1897 outb(VGAREG_DAC_DATA,g);
1898 outb(VGAREG_DAC_DATA,b);
1901 // --------------------------------------------------------------------------------------------
1902 static void biosfn_set_all_dac_reg (start,count,seg,offset)
1903 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1904 {Bit16u i;
1905 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1906 for(i=0;i<count;i++)
1907 {outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1908 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1909 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1913 // --------------------------------------------------------------------------------------------
1914 static void biosfn_select_video_dac_color_page (function,page)
1915 Bit8u function;
1916 {Bit8u value;
1918 inb(VGAREG_ACTL_RESET);
1919 outb(VGAREG_ACTL_ADDRESS,0x10);
1921 value=inb(VGAREG_ACTL_READ_DATA);
1922 function&=0x01;
1923 if(function==0)
1924 {// set paging code
1925 value&=0x7f;
1926 value|=page<<7;
1927 outb(VGAREG_ACTL_WRITE_DATA,value);
1929 else
1930 {// select page
1931 inb(VGAREG_ACTL_RESET);
1932 outb(VGAREG_ACTL_ADDRESS,0x14);
1933 if(value&0x80)
1934 outb(VGAREG_ACTL_WRITE_DATA,page&0x0f);
1935 else
1936 outb(VGAREG_ACTL_WRITE_DATA,(page&0x03)<<2);
1938 outb(VGAREG_ACTL_ADDRESS,0x20);
1941 // --------------------------------------------------------------------------------------------
1942 static void biosfn_read_single_dac_reg (reg,tor,togb)
1943 Bit8u reg;Bit16u *tor;Bit16u *togb;
1944 {Bit16u ss=get_SS();
1945 Bit8u r,g,b;
1947 outb(VGAREG_DAC_READ_ADDRESS,reg);
1948 r=inb(VGAREG_DAC_DATA);
1949 g=inb(VGAREG_DAC_DATA);
1950 b=inb(VGAREG_DAC_DATA);
1951 write_word(ss,tor,((Bit16u)r)<<8);
1952 write_word(ss,togb,(((Bit16u)g)<<8)+b);
1955 // --------------------------------------------------------------------------------------------
1956 static void biosfn_read_all_dac_reg (start,count,seg,offset)
1957 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1958 {Bit16u i;
1959 outb(VGAREG_DAC_READ_ADDRESS,start);
1960 for(i=0;i<count;i++)
1961 {write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1962 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1963 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1967 // --------------------------------------------------------------------------------------------
1968 static void biosfn_set_pel_mask (mask)
1969 Bit8u mask;
1971 outb(VGAREG_PEL_MASK,mask);
1974 // --------------------------------------------------------------------------------------------
1975 static void biosfn_read_pel_mask (mask)
1976 Bit16u *mask;
1977 {Bit16u ss=get_SS();
1979 write_word(ss,mask,inb(VGAREG_PEL_MASK));
1982 // --------------------------------------------------------------------------------------------
1983 static void biosfn_read_video_dac_state (state) Bit16u *state;
1984 {Bit16u ss=get_SS();
1985 Bit8u mcr,csr;
1987 inb(VGAREG_ACTL_RESET);
1988 outb(VGAREG_ACTL_ADDRESS,0x10);
1989 mcr=(inb(VGAREG_ACTL_READ_DATA)>>7)&0x01;
1990 inb(VGAREG_ACTL_RESET);
1991 outb(VGAREG_ACTL_ADDRESS,0x14);
1992 csr=inb(VGAREG_ACTL_READ_DATA)&0x0f;
1993 if(mcr==0)(csr>>2)&0x03;
1995 write_word(ss,state,(mcr<<8)+csr);
1996 outb(VGAREG_ACTL_ADDRESS,0x20);
1999 // --------------------------------------------------------------------------------------------
2000 static void biosfn_perform_gray_scale_summing (start,count)
2001 Bit16u start;Bit16u count;
2002 {Bit8u r,g,b;
2003 Bit16u i;
2004 Bit16u index;
2006 inb(VGAREG_ACTL_RESET);
2007 outb(VGAREG_ACTL_ADDRESS,0x00);
2009 for( index = 0; index < count; index++ )
2011 // set read address and switch to read mode
2012 outb(VGAREG_DAC_READ_ADDRESS,start);
2013 // get 6-bit wide RGB data values
2014 r=inb( VGAREG_DAC_DATA );
2015 g=inb( VGAREG_DAC_DATA );
2016 b=inb( VGAREG_DAC_DATA );
2018 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2019 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2021 if(i>0x3f)i=0x3f;
2023 // set write address and switch to write mode
2024 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2025 // write new intensity value
2026 outb( VGAREG_DAC_DATA, i&0xff );
2027 outb( VGAREG_DAC_DATA, i&0xff );
2028 outb( VGAREG_DAC_DATA, i&0xff );
2029 start++;
2031 inb(VGAREG_ACTL_RESET);
2032 outb(VGAREG_ACTL_ADDRESS,0x20);
2035 // --------------------------------------------------------------------------------------------
2036 static void get_font_access()
2038 ASM_START
2039 mov dx, #vgareg_sequ_address
2040 mov ax, #0x0100
2041 out dx, ax
2042 mov ax, #0x0402
2043 out dx, ax
2044 mov ax, #0x0704
2045 out dx, ax
2046 mov ax, #0x0300
2047 out dx, ax
2048 mov dx, #vgareg_grdc_address
2049 mov ax, #0x0204
2050 out dx, ax
2051 mov ax, #0x0005
2052 out dx, ax
2053 mov ax, #0x0406
2054 out dx, ax
2055 ASM_END
2058 static void release_font_access()
2060 ASM_START
2061 mov dx, #vgareg_sequ_address
2062 mov ax, #0x0100
2063 out dx, ax
2064 mov ax, #0x0302
2065 out dx, ax
2066 mov ax, #0x0304
2067 out dx, ax
2068 mov ax, #0x0300
2069 out dx, ax
2070 mov dx, #vgareg_grdc_address
2071 mov ax, #0x0004
2072 out dx, ax
2073 mov ax, #0x1005
2074 out dx, ax
2075 mov ax, #0x0e06
2076 out dx, ax
2077 ASM_END
2080 ASM_START
2081 idiv_u:
2082 xor dx,dx
2083 div bx
2085 ASM_END
2087 static void set_scan_lines(lines) Bit8u lines;
2089 Bit16u crtc_addr,cols,page,vde;
2090 Bit8u crtc_r9,ovl,rows;
2092 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2093 outb(crtc_addr, 0x09);
2094 crtc_r9 = inb(crtc_addr+1);
2095 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2096 outb(crtc_addr+1, crtc_r9);
2097 if(lines==8)
2099 biosfn_set_cursor_shape(0x06,0x07);
2101 else
2103 biosfn_set_cursor_shape(lines-4,lines-3);
2105 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2106 outb(crtc_addr, 0x12);
2107 vde = inb(crtc_addr+1);
2108 outb(crtc_addr, 0x07);
2109 ovl = inb(crtc_addr+1);
2110 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2111 rows = vde / lines;
2112 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2113 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2114 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2117 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;
2119 Bit16u blockaddr,dest,i,src;
2121 get_font_access();
2122 blockaddr = BL << 13;
2123 for(i=0;i<CX;i++)
2125 src = BP + i * BH;
2126 dest = blockaddr + (DX + i) * 32;
2127 memcpyb(0xA000, dest, ES, src, BH);
2129 release_font_access();
2130 if(AL>=0x10)
2132 set_scan_lines(BH);
2136 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2138 Bit16u blockaddr,dest,i,src;
2140 get_font_access();
2141 blockaddr = BL << 13;
2142 for(i=0;i<0x100;i++)
2144 src = i * 14;
2145 dest = blockaddr + i * 32;
2146 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2148 release_font_access();
2149 if(AL>=0x10)
2151 set_scan_lines(14);
2155 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2157 Bit16u blockaddr,dest,i,src;
2159 get_font_access();
2160 blockaddr = BL << 13;
2161 for(i=0;i<0x100;i++)
2163 src = i * 8;
2164 dest = blockaddr + i * 32;
2165 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2167 release_font_access();
2168 if(AL>=0x10)
2170 set_scan_lines(8);
2174 static void biosfn_set_text_block_specifier (BL) Bit8u BL;
2176 outb( VGAREG_SEQU_ADDRESS, 0x03 );
2177 outb( VGAREG_SEQU_DATA, BL );
2180 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2182 Bit16u blockaddr,dest,i,src;
2184 get_font_access();
2185 blockaddr = BL << 13;
2186 for(i=0;i<0x100;i++)
2188 src = i * 16;
2189 dest = blockaddr + i * 32;
2190 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2192 release_font_access();
2193 if(AL>=0x10)
2195 set_scan_lines(16);
2199 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2201 #ifdef DEBUG
2202 unimplemented();
2203 #endif
2205 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2207 #ifdef DEBUG
2208 unimplemented();
2209 #endif
2211 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2213 #ifdef DEBUG
2214 unimplemented();
2215 #endif
2217 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2219 #ifdef DEBUG
2220 unimplemented();
2221 #endif
2223 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2225 #ifdef DEBUG
2226 unimplemented();
2227 #endif
2229 // --------------------------------------------------------------------------------------------
2230 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2231 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2232 {Bit16u ss=get_SS();
2234 switch(BH)
2235 {case 0x00:
2236 write_word(ss,ES,read_word(0x00,0x1f*4));
2237 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2238 break;
2239 case 0x01:
2240 write_word(ss,ES,read_word(0x00,0x43*4));
2241 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2242 break;
2243 case 0x02:
2244 write_word(ss,ES,0xC000);
2245 write_word(ss,BP,vgafont14);
2246 break;
2247 case 0x03:
2248 write_word(ss,ES,0xC000);
2249 write_word(ss,BP,vgafont8);
2250 break;
2251 case 0x04:
2252 write_word(ss,ES,0xC000);
2253 write_word(ss,BP,vgafont8+128*8);
2254 break;
2255 case 0x05:
2256 write_word(ss,ES,0xC000);
2257 write_word(ss,BP,vgafont14alt);
2258 break;
2259 case 0x06:
2260 write_word(ss,ES,0xC000);
2261 write_word(ss,BP,vgafont16);
2262 break;
2263 case 0x07:
2264 write_word(ss,ES,0xC000);
2265 write_word(ss,BP,vgafont16alt);
2266 break;
2267 default:
2268 #ifdef DEBUG
2269 printf("Get font info BH(%02x) was discarded\n",BH);
2270 #endif
2271 return;
2273 // Set byte/char of on screen font
2274 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2276 // Set Highest char row
2277 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2280 // --------------------------------------------------------------------------------------------
2281 static void biosfn_get_ega_info (BX,CX)
2282 Bit16u *BX;Bit16u *CX;
2283 {Bit16u ss=get_SS();
2284 Bit16u crtc;
2285 Bit8u switches;
2287 crtc=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2288 if(crtc==VGAREG_MDA_CRTC_ADDRESS)
2289 write_word(ss,BX,(1<<8)+0x0003);
2290 else
2291 write_word(ss,BX,0x0003);
2293 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2294 write_word(ss,CX,(switches&0x0f));
2297 // --------------------------------------------------------------------------------------------
2298 static void biosfn_alternate_prtsc()
2300 #ifdef DEBUG
2301 unimplemented();
2302 #endif
2305 // --------------------------------------------------------------------------------------------
2306 static void biosfn_select_vert_res (res)
2307 Bit8u res;
2308 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2309 Bit8u modeset,switches;
2311 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2312 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2313 switch(res)
2314 {case 0x00:
2315 // set modeset ctl bit 7 and reset bit 4
2316 // set switches bit 3-0 to 0x08
2317 modeset|=0x80;modeset&=0xef;
2318 switches&=0xf0;switches|=0x08;
2319 break;
2320 case 0x01:
2321 // reset modeset ctl bit 7 and bit 4
2322 // set switches bit 3-0 to 0x09
2323 modeset&=0x6f;
2324 switches&=0xf0;switches|=0x09;
2325 break;
2326 case 0x02:
2327 // reset modeset ctl bit 7 and set bit 4
2328 // set switches bit 3-0 to 0x09
2329 modeset|=0x10;modeset&=0x7f;
2330 switches&=0xf0;switches|=0x09;
2331 break;
2332 default:
2333 #ifdef DEBUG
2334 printf("Select vert res (%02x) was discarded\n",res);
2335 #endif
2336 return;
2338 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2339 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2342 // --------------------------------------------------------------------------------------------
2343 static void biosfn_enable_default_palette_loading (disable)
2344 Bit8u disable;
2346 Bit8u modeset;
2348 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2350 // Bit 3
2351 if(disable!=0x00)modeset|=0x08;
2352 else modeset&=0xf7;
2354 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2357 // --------------------------------------------------------------------------------------------
2358 static void biosfn_enable_video_addressing (disable)
2359 Bit8u disable;
2361 Bit8u misc;
2363 misc=inb(VGAREG_READ_MISC_OUTPUT);
2364 // bit 1, 0 disable
2365 if(disable!=0x00) misc&=0xfd;
2366 else misc|=0x02;
2367 outb(VGAREG_WRITE_MISC_OUTPUT,misc);
2370 // --------------------------------------------------------------------------------------------
2371 static void biosfn_enable_grayscale_summing (disable)
2372 Bit8u disable;
2374 Bit8u modeset;
2376 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2378 // Bit 1 set if disable=0
2379 if(disable==0x00)modeset|=0x02;
2380 else modeset&=0xfd;
2382 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2385 // --------------------------------------------------------------------------------------------
2386 static void biosfn_enable_cursor_emulation (disable)
2387 Bit8u disable;
2389 Bit8u videoctl;
2391 videoctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
2393 // Bit 0 set if disable!=0
2394 if(disable!=0x00)videoctl|=0x01;
2395 else videoctl&=0xfe;
2397 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,videoctl);
2400 // --------------------------------------------------------------------------------------------
2401 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2403 #ifdef DEBUG
2404 unimplemented();
2405 #endif
2407 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2409 #ifdef DEBUG
2410 unimplemented();
2411 #endif
2414 // --------------------------------------------------------------------------------------------
2415 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2416 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2418 Bit16u newcurs,oldcurs,dummy;
2419 Bit8u car,carattr;
2421 // Read curs info for the page
2422 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2424 // if row=0xff special case : use current cursor position
2425 if(row==0xff)
2426 {col=oldcurs&0x00ff;
2427 row=(oldcurs&0xff00)>>8;
2430 newcurs=row; newcurs<<=8; newcurs+=col;
2431 biosfn_set_cursor_pos(page,newcurs);
2433 while(count--!=0)
2435 car=read_byte(seg,offset++);
2436 if((flag&0x02)!=0)
2437 attr=read_byte(seg,offset++);
2439 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2442 // Set back curs pos
2443 if((flag&0x01)==0)
2444 biosfn_set_cursor_pos(page,oldcurs);
2447 // --------------------------------------------------------------------------------------------
2448 ASM_START
2449 biosfn_group_1A:
2450 cmp al, #0x00
2451 je biosfn_read_display_code
2452 cmp al, #0x01
2453 je biosfn_set_display_code
2454 #ifdef DEBUG
2455 call _unknown
2456 #endif
2458 biosfn_read_display_code:
2459 push ds
2460 push ax
2461 mov ax, #biosmem_seg
2462 mov ds, ax
2463 mov bx, #biosmem_dcc_index
2464 mov al, [bx]
2465 mov bl, al
2466 xor bh, bh
2467 pop ax
2468 mov al, ah
2469 pop ds
2471 biosfn_set_display_code:
2472 push ds
2473 push ax
2474 push bx
2475 mov ax, #biosmem_seg
2476 mov ds, ax
2477 mov ax, bx
2478 mov bx, #biosmem_dcc_index
2479 mov [bx], al
2480 #ifdef DEBUG
2481 mov al, ah
2482 xor ah, ah
2483 push ax
2484 mov bx, #msg_alt_dcc
2485 push bx
2486 call _printf
2487 add sp, #4
2488 #endif
2489 pop bx
2490 pop ax
2491 mov al, ah
2492 pop ds
2495 #ifdef DEBUG
2496 msg_alt_dcc:
2497 .ascii "Alternate Display code (%02x) was discarded"
2498 .byte 0x0d,0x0a,0x00
2499 #endif
2500 ASM_END
2502 // --------------------------------------------------------------------------------------------
2503 static void biosfn_read_state_info (BX,ES,DI)
2504 Bit16u BX;Bit16u ES;Bit16u DI;
2506 // Address of static functionality table
2507 write_word(ES,DI+0x00,&static_functionality);
2508 write_word(ES,DI+0x02,0xC000);
2510 // Hard coded copy from BIOS area. Should it be cleaner ?
2511 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2512 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2514 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2515 write_byte(ES,DI+0x26,0);
2516 write_byte(ES,DI+0x27,16);
2517 write_byte(ES,DI+0x28,0);
2518 write_byte(ES,DI+0x29,8);
2519 write_byte(ES,DI+0x2a,2);
2520 write_byte(ES,DI+0x2b,0);
2521 write_byte(ES,DI+0x2c,0);
2522 write_byte(ES,DI+0x31,3);
2523 write_byte(ES,DI+0x32,0);
2525 memsetb(ES,DI+0x33,0,13);
2528 // --------------------------------------------------------------------------------------------
2529 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2531 #ifdef DEBUG
2532 unimplemented();
2533 #endif
2535 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2537 #ifdef DEBUG
2538 unimplemented();
2539 #endif
2541 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2543 #ifdef DEBUG
2544 unimplemented();
2545 #endif
2548 // ============================================================================================
2550 // Video Utils
2552 // ============================================================================================
2554 // --------------------------------------------------------------------------------------------
2555 static Bit8u find_vga_entry(mode)
2556 Bit8u mode;
2558 Bit8u i,line=0xFF;
2559 for(i=0;i<=MODE_MAX;i++)
2560 if(vga_modes[i].svgamode==mode)
2561 {line=i;
2562 break;
2564 return line;
2567 /* =========================================================== */
2569 * Misc Utils
2571 /* =========================================================== */
2573 // --------------------------------------------------------------------------------------------
2574 static void memsetb(seg,offset,value,count)
2575 Bit16u seg;
2576 Bit16u offset;
2577 Bit16u value;
2578 Bit16u count;
2580 ASM_START
2581 push bp
2582 mov bp, sp
2584 push ax
2585 push cx
2586 push es
2587 push di
2589 mov cx, 10[bp] ; count
2590 cmp cx, #0x00
2591 je memsetb_end
2592 mov ax, 4[bp] ; segment
2593 mov es, ax
2594 mov ax, 6[bp] ; offset
2595 mov di, ax
2596 mov al, 8[bp] ; value
2599 stosb
2601 memsetb_end:
2602 pop di
2603 pop es
2604 pop cx
2605 pop ax
2607 pop bp
2608 ASM_END
2611 // --------------------------------------------------------------------------------------------
2612 static void memsetw(seg,offset,value,count)
2613 Bit16u seg;
2614 Bit16u offset;
2615 Bit16u value;
2616 Bit16u count;
2618 ASM_START
2619 push bp
2620 mov bp, sp
2622 push ax
2623 push cx
2624 push es
2625 push di
2627 mov cx, 10[bp] ; count
2628 cmp cx, #0x00
2629 je memsetw_end
2630 mov ax, 4[bp] ; segment
2631 mov es, ax
2632 mov ax, 6[bp] ; offset
2633 mov di, ax
2634 mov ax, 8[bp] ; value
2637 stosw
2639 memsetw_end:
2640 pop di
2641 pop es
2642 pop cx
2643 pop ax
2645 pop bp
2646 ASM_END
2649 // --------------------------------------------------------------------------------------------
2650 static void memcpyb(dseg,doffset,sseg,soffset,count)
2651 Bit16u dseg;
2652 Bit16u doffset;
2653 Bit16u sseg;
2654 Bit16u soffset;
2655 Bit16u count;
2657 ASM_START
2658 push bp
2659 mov bp, sp
2661 push ax
2662 push cx
2663 push es
2664 push di
2665 push ds
2666 push si
2668 mov cx, 12[bp] ; count
2669 cmp cx, #0x0000
2670 je memcpyb_end
2671 mov ax, 4[bp] ; dsegment
2672 mov es, ax
2673 mov ax, 6[bp] ; doffset
2674 mov di, ax
2675 mov ax, 8[bp] ; ssegment
2676 mov ds, ax
2677 mov ax, 10[bp] ; soffset
2678 mov si, ax
2681 movsb
2683 memcpyb_end:
2684 pop si
2685 pop ds
2686 pop di
2687 pop es
2688 pop cx
2689 pop ax
2691 pop bp
2692 ASM_END
2695 // --------------------------------------------------------------------------------------------
2696 static void memcpyw(dseg,doffset,sseg,soffset,count)
2697 Bit16u dseg;
2698 Bit16u doffset;
2699 Bit16u sseg;
2700 Bit16u soffset;
2701 Bit16u count;
2703 ASM_START
2704 push bp
2705 mov bp, sp
2707 push ax
2708 push cx
2709 push es
2710 push di
2711 push ds
2712 push si
2714 mov cx, 12[bp] ; count
2715 cmp cx, #0x0000
2716 je memcpyw_end
2717 mov ax, 4[bp] ; dsegment
2718 mov es, ax
2719 mov ax, 6[bp] ; doffset
2720 mov di, ax
2721 mov ax, 8[bp] ; ssegment
2722 mov ds, ax
2723 mov ax, 10[bp] ; soffset
2724 mov si, ax
2727 movsw
2729 memcpyw_end:
2730 pop si
2731 pop ds
2732 pop di
2733 pop es
2734 pop cx
2735 pop ax
2737 pop bp
2738 ASM_END
2741 /* =========================================================== */
2743 * These functions where ripped from Kevin's rombios.c
2745 /* =========================================================== */
2747 // --------------------------------------------------------------------------------------------
2748 static Bit8u
2749 read_byte(seg, offset)
2750 Bit16u seg;
2751 Bit16u offset;
2753 ASM_START
2754 push bp
2755 mov bp, sp
2757 push bx
2758 push ds
2759 mov ax, 4[bp] ; segment
2760 mov ds, ax
2761 mov bx, 6[bp] ; offset
2762 mov al, [bx]
2763 ;; al = return value (byte)
2764 pop ds
2765 pop bx
2767 pop bp
2768 ASM_END
2771 // --------------------------------------------------------------------------------------------
2772 static Bit16u
2773 read_word(seg, offset)
2774 Bit16u seg;
2775 Bit16u offset;
2777 ASM_START
2778 push bp
2779 mov bp, sp
2781 push bx
2782 push ds
2783 mov ax, 4[bp] ; segment
2784 mov ds, ax
2785 mov bx, 6[bp] ; offset
2786 mov ax, [bx]
2787 ;; ax = return value (word)
2788 pop ds
2789 pop bx
2791 pop bp
2792 ASM_END
2795 // --------------------------------------------------------------------------------------------
2796 static void
2797 write_byte(seg, offset, data)
2798 Bit16u seg;
2799 Bit16u offset;
2800 Bit8u data;
2802 ASM_START
2803 push bp
2804 mov bp, sp
2806 push ax
2807 push bx
2808 push ds
2809 mov ax, 4[bp] ; segment
2810 mov ds, ax
2811 mov bx, 6[bp] ; offset
2812 mov al, 8[bp] ; data byte
2813 mov [bx], al ; write data byte
2814 pop ds
2815 pop bx
2816 pop ax
2818 pop bp
2819 ASM_END
2822 // --------------------------------------------------------------------------------------------
2823 static void
2824 write_word(seg, offset, data)
2825 Bit16u seg;
2826 Bit16u offset;
2827 Bit16u data;
2829 ASM_START
2830 push bp
2831 mov bp, sp
2833 push ax
2834 push bx
2835 push ds
2836 mov ax, 4[bp] ; segment
2837 mov ds, ax
2838 mov bx, 6[bp] ; offset
2839 mov ax, 8[bp] ; data word
2840 mov [bx], ax ; write data word
2841 pop ds
2842 pop bx
2843 pop ax
2845 pop bp
2846 ASM_END
2849 // --------------------------------------------------------------------------------------------
2850 Bit8u
2851 inb(port)
2852 Bit16u port;
2854 ASM_START
2855 push bp
2856 mov bp, sp
2858 push dx
2859 mov dx, 4[bp]
2860 in al, dx
2861 pop dx
2863 pop bp
2864 ASM_END
2867 Bit16u
2868 inw(port)
2869 Bit16u port;
2871 ASM_START
2872 push bp
2873 mov bp, sp
2875 push dx
2876 mov dx, 4[bp]
2877 in ax, dx
2878 pop dx
2880 pop bp
2881 ASM_END
2884 // --------------------------------------------------------------------------------------------
2885 void
2886 outb(port, val)
2887 Bit16u port;
2888 Bit8u val;
2890 ASM_START
2891 push bp
2892 mov bp, sp
2894 push ax
2895 push dx
2896 mov dx, 4[bp]
2897 mov al, 6[bp]
2898 out dx, al
2899 pop dx
2900 pop ax
2902 pop bp
2903 ASM_END
2906 // --------------------------------------------------------------------------------------------
2907 void
2908 outw(port, val)
2909 Bit16u port;
2910 Bit16u val;
2912 ASM_START
2913 push bp
2914 mov bp, sp
2916 push ax
2917 push dx
2918 mov dx, 4[bp]
2919 mov ax, 6[bp]
2920 out dx, ax
2921 pop dx
2922 pop ax
2924 pop bp
2925 ASM_END
2928 Bit16u get_SS()
2930 ASM_START
2931 mov ax, ss
2932 ASM_END
2935 #ifdef DEBUG
2936 void unimplemented()
2938 printf("--> Unimplemented\n");
2941 void unknown()
2943 printf("--> Unknown int10\n");
2945 #endif
2947 // --------------------------------------------------------------------------------------------
2948 void printf(s)
2949 Bit8u *s;
2951 Bit8u c, format_char;
2952 Boolean in_format;
2953 unsigned format_width, i;
2954 Bit16u *arg_ptr;
2955 Bit16u arg_seg, arg, digit, nibble, shift_count;
2957 arg_ptr = &s;
2958 arg_seg = get_SS();
2960 in_format = 0;
2961 format_width = 0;
2963 while (c = read_byte(0xc000, s)) {
2964 if ( c == '%' ) {
2965 in_format = 1;
2966 format_width = 0;
2968 else if (in_format) {
2969 if ( (c>='0') && (c<='9') ) {
2970 format_width = (format_width * 10) + (c - '0');
2972 else if (c == 'x') {
2973 arg_ptr++; // increment to next arg
2974 arg = read_word(arg_seg, arg_ptr);
2975 if (format_width == 0)
2976 format_width = 4;
2977 i = 0;
2978 digit = format_width - 1;
2979 for (i=0; i<format_width; i++) {
2980 nibble = (arg >> (4 * digit)) & 0x000f;
2981 if (nibble <= 9)
2982 outb(0x0500, nibble + '0');
2983 else
2984 outb(0x0500, (nibble - 10) + 'A');
2985 digit--;
2987 in_format = 0;
2989 //else if (c == 'd') {
2990 // in_format = 0;
2991 // }
2993 else {
2994 outb(0x0500, c);
2996 s ++;
3000 #ifdef VBE
3001 #include "vbe.c"
3002 #endif
3004 // --------------------------------------------------------------------------------------------
3006 ASM_START
3007 ;; DATA_SEG_DEFS_HERE
3008 ASM_END
3010 ASM_START
3011 .ascii "vgabios ends here"
3012 .byte 0x00
3013 vgabios_end:
3014 .byte 0xCB
3015 ;; BLOCK_STRINGS_BEGIN
3016 ASM_END