- fixed a few functions accessing the attribute controller
[vgabios.git] / vgabios.c
blob055310c73c237d379a04b0a90b71c6cdb28259ad
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 void init_vga_card();
75 static void init_bios_area();
77 static Bit8u find_vga_entry();
79 static void memsetb();
80 static void memsetw();
81 static void memcpyb();
82 static void memcpyw();
84 static void biosfn_set_video_mode();
85 static void biosfn_set_cursor_shape();
86 static void biosfn_set_cursor_pos();
87 static void biosfn_get_cursor_pos();
88 static void biosfn_set_active_page();
89 static void biosfn_scroll();
90 static void biosfn_read_char_attr();
91 static void biosfn_write_char_attr();
92 static void biosfn_write_char_only();
93 static void biosfn_set_border_color();
94 static void biosfn_set_palette();
95 static void biosfn_write_pixel();
96 static void biosfn_read_pixel();
97 static void biosfn_write_teletype();
98 static void biosfn_get_video_mode();
99 static void biosfn_set_single_palette_reg();
100 static void biosfn_set_overscan_border_color();
101 static void biosfn_set_all_palette_reg();
102 static void biosfn_toggle_intensity();
103 static void biosfn_get_single_palette_reg();
104 static void biosfn_read_overscan_border_color();
105 static void biosfn_get_all_palette_reg();
106 static void biosfn_set_single_dac_reg();
107 static void biosfn_set_all_dac_reg();
108 static void biosfn_select_video_dac_color_page();
109 static void biosfn_read_single_dac_reg();
110 static void biosfn_read_all_dac_reg();
111 static void biosfn_set_pel_mask();
112 static void biosfn_read_pel_mask();
113 static void biosfn_read_video_dac_state();
114 static void biosfn_perform_gray_scale_summing();
115 static void biosfn_load_text_user_pat();
116 static void biosfn_load_text_8_14_pat();
117 static void biosfn_load_text_8_8_pat();
118 static void biosfn_set_text_block_specifier();
119 static void biosfn_load_text_8_16_pat();
120 static void biosfn_load_gfx_8_8_chars();
121 static void biosfn_load_gfx_user_chars();
122 static void biosfn_load_gfx_8_14_chars();
123 static void biosfn_load_gfx_8_8_dd_chars();
124 static void biosfn_load_gfx_8_16_chars();
125 static void biosfn_get_font_info();
126 static void biosfn_get_ega_info();
127 static void biosfn_alternate_prtsc();
128 static void biosfn_select_vert_res();
129 static void biosfn_enable_default_palette_loading();
130 static void biosfn_enable_video_addressing();
131 static void biosfn_enable_grayscale_summing();
132 static void biosfn_enable_cursor_emulation();
133 static void biosfn_switch_video_interface();
134 static void biosfn_enable_video_refresh_control();
135 static void biosfn_write_string();
136 static void biosfn_read_display_code();
137 static void biosfn_set_display_code();
138 static void biosfn_read_state_info();
139 static void biosfn_read_video_state_size();
140 static void biosfn_save_video_state();
141 static void biosfn_restore_video_state();
143 // This is for compiling with gcc2 and gcc3
144 #define ASM_START #asm
145 #define ASM_END #endasm
147 ASM_START
148 MACRO SET_INT_VECTOR
149 push ds
150 xor ax, ax
151 mov ds, ax
152 mov ax, ?3
153 mov ?1*4, ax
154 mov ax, ?2
155 mov ?1*4+2, ax
156 pop ds
157 MEND
159 ASM_END
161 ASM_START
162 .text
163 .rom
164 .org 0
166 use16 386
168 vgabios_start:
169 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
171 .byte 0x40 /* BIOS extension length in units of 512 bytes */
174 vgabios_entry_point:
176 jmp vgabios_init_func
178 vgabios_name:
179 .ascii "Plex86/Bochs VGABios"
180 .ascii " "
181 .byte 0x00
183 // Info from Bart Oldeman
184 .org 0x1e
185 .ascii "IBM"
186 .byte 0x00
188 vgabios_version:
189 .ascii "current-cvs"
190 .ascii " "
192 vgabios_date:
193 .ascii VGABIOS_DATE
194 .byte 0x0a,0x0d
195 .byte 0x00
197 vgabios_copyright:
198 .ascii "(C) 2003 the LGPL VGABios developers Team"
199 .byte 0x0a,0x0d
200 .byte 0x00
202 vgabios_license:
203 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
204 .byte 0x0a,0x0d
205 .byte 0x0a,0x0d
206 .byte 0x00
208 vgabios_website:
209 .ascii "Please visit :"
210 .byte 0x0a,0x0d
211 .ascii " . http://www.plex86.org"
212 .byte 0x0a,0x0d
213 .ascii " . http://bochs.sourceforge.net"
214 .byte 0x0a,0x0d
215 .ascii " . http://www.nongnu.org/vgabios"
216 .byte 0x0a,0x0d
217 .byte 0x0a,0x0d
218 .byte 0x00
221 ;; ============================================================================================
223 ;; Init Entry point
225 ;; ============================================================================================
226 vgabios_init_func:
228 ;; init vga card
229 call _init_vga_card
231 ;; init basic bios vars
232 call _init_bios_area
234 #ifdef VBE
235 call _vbe_has_vbe_display
236 cmp al, #0x00
237 je init_no_vbe_display
239 ;; init vbe functions
240 call _vbe_init
242 init_no_vbe_display:
243 #endif
245 ;; set int10 vect
246 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
248 ;; display splash screen
249 call _display_splash_screen
251 ;; init video mode and clear the screen
252 mov ax,#0x0003
253 int #0x10
255 ;; copy and activate 8x16 font
256 mov ax, #0x1104
257 mov bl, #0x00
258 int #0x10
259 mov ax, #0x1103
260 mov bl, #0x00
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 push es
282 push ds
283 pusha
285 ;; We have to set ds to access the right data segment
286 mov bx, #0xc000
287 mov ds, bx
288 call _int10_func
290 popa
291 pop ds
292 pop es
293 popf
294 iret
295 ASM_END
297 #include "vgatables.h"
298 #include "vgafonts.h"
301 * Boot time harware inits
303 static void init_vga_card()
305 ASM_START
306 ;; switch to color mode and enable CPU access 480 lines
307 mov dx, #0x3C2
308 mov al, #0xC3
309 outb dx,al
311 ;; more than 64k 3C4/04
312 mov dx, #0x3C4
313 mov al, #0x04
314 outb dx,al
317 mov dx, #0x3C5
318 mov al, #0x02
319 outb dx,al
321 ASM_END
323 printf("VGABios $Id$\n");
326 // --------------------------------------------------------------------------------------------
328 * Boot time bios area inits
330 static void init_bios_area()
332 // init detected hardware BIOS Area
333 write_word(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,read_word(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE)&0xFFCF);
335 // Just for the first int10 find its children
337 // the default chat height
338 write_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,16);
340 // Clear the screen
341 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,0x60);
343 // Set the basic screen we have
344 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
346 // Set the basic modeset options
347 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,0x51);
349 // Set the default MSR
350 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x09);
353 // --------------------------------------------------------------------------------------------
355 * Boot time Splash screen
357 static void display_splash_screen()
361 // --------------------------------------------------------------------------------------------
363 * Tell who we are
366 static void display_info()
368 ASM_START
369 mov ax,#0xc000
370 mov ds,ax
371 mov si,#vgabios_name
372 call _display_string
373 mov si,#vgabios_version
374 call _display_string
376 ;;mov si,#vgabios_copyright
377 ;;call _display_string
378 ;;mov si,#crlf
379 ;;call _display_string
381 mov si,#vgabios_license
382 call _display_string
383 mov si,#vgabios_website
384 call _display_string
385 ASM_END
388 static void display_string()
390 // Get length of string
391 ASM_START
392 mov ax,ds
393 mov es,ax
394 mov di,si
395 xor cx,cx
396 not cx
397 xor al,al
399 repne
400 scasb
401 not cx
402 dec cx
403 push cx
405 mov ax,#0x0300
406 mov bx,#0x0000
407 int #0x10
409 pop cx
410 mov ax,#0x1301
411 mov bx,#0x000b
412 mov bp,si
413 int #0x10
414 ASM_END
417 // --------------------------------------------------------------------------------------------
419 // --------------------------------------------------------------------------------------------
421 * int10 main dispatcher
423 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
424 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
426 #ifdef DEBUG
427 // 0E is write char...
428 if(GET_AH()!=0x0E)
429 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
430 #endif
432 // BIOS functions
433 switch(GET_AH())
435 case 0x00:
436 biosfn_set_video_mode(GET_AL());
437 switch(GET_AL()&0x7F)
438 {case 6:
439 SET_AL(0x3F);
440 break;
441 case 0:
442 case 1:
443 case 2:
444 case 3:
445 case 4:
446 case 5:
447 case 7:
448 SET_AL(0x30);
449 break;
450 default:
451 SET_AL(0x20);
453 break;
454 case 0x01:
455 biosfn_set_cursor_shape(GET_CH(),GET_CL());
456 break;
457 case 0x02:
458 biosfn_set_cursor_pos(GET_BH(),DX);
459 break;
460 case 0x03:
461 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
462 break;
463 case 0x04:
464 // Read light pen pos (unimplemented)
465 #ifdef DEBUG
466 unimplemented();
467 #endif
468 AX=0x00;
469 BX=0x00;
470 CX=0x00;
471 DX=0x00;
472 break;
473 case 0x05:
474 biosfn_set_active_page(GET_AL());
475 break;
476 case 0x06:
477 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
478 break;
479 case 0x07:
480 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
481 break;
482 case 0x08:
483 biosfn_read_char_attr(GET_BH(),&AX);
484 break;
485 case 0x09:
486 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
487 break;
488 case 0x0A:
489 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
490 break;
491 case 0x0B:
492 if(GET_BH()==0x00)
493 biosfn_set_border_color(GET_BL());
494 else
495 biosfn_set_palette(GET_BL());
496 break;
497 case 0x0C:
498 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
499 break;
500 case 0x0D:
501 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
502 break;
503 case 0x0E:
504 // Ralf Brown Interrupt list is WRONG on bh(page)
505 // We do output only on the current page !
506 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
507 break;
508 case 0x0F:
509 biosfn_get_video_mode(&AX,&BX);
510 break;
511 case 0x10:
512 switch(GET_AL())
514 case 0x00:
515 biosfn_set_single_palette_reg(GET_BL(),GET_BH());
516 break;
517 case 0x01:
518 biosfn_set_overscan_border_color(GET_BH());
519 break;
520 case 0x02:
521 biosfn_set_all_palette_reg(ES,DX);
522 break;
523 case 0x03:
524 biosfn_toggle_intensity(GET_BL());
525 break;
526 case 0x07:
527 biosfn_get_single_palette_reg(GET_BL(),&BX);
528 break;
529 case 0x08:
530 biosfn_read_overscan_border_color(&BX);
531 break;
532 case 0x09:
533 biosfn_get_all_palette_reg(ES,DX);
534 break;
535 case 0x10:
536 biosfn_set_single_dac_reg(BX,GET_CH(),GET_CL(),GET_DH());
537 break;
538 case 0x12:
539 biosfn_set_all_dac_reg(BX,CX,ES,DX);
540 break;
541 case 0x13:
542 biosfn_select_video_dac_color_page(GET_BL(),GET_BH());
543 break;
544 case 0x15:
545 biosfn_read_single_dac_reg(GET_BL(),&DX,&CX);
546 break;
547 case 0x17:
548 biosfn_read_all_dac_reg(BX,CX,ES,DX);
549 break;
550 case 0x18:
551 biosfn_set_pel_mask(GET_BL());
552 break;
553 case 0x19:
554 biosfn_read_pel_mask(&BX);
555 break;
556 case 0x1A:
557 biosfn_read_video_dac_state(&BX);
558 break;
559 case 0x1B:
560 biosfn_perform_gray_scale_summing(BX,CX);
561 break;
562 #ifdef DEBUG
563 default:
564 unknown();
565 #endif
567 break;
568 case 0x11:
569 switch(GET_AL())
571 case 0x00:
572 case 0x10:
573 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
574 break;
575 case 0x01:
576 case 0x11:
577 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
578 break;
579 case 0x02:
580 case 0x12:
581 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
582 break;
583 case 0x03:
584 biosfn_set_text_block_specifier(GET_BL());
585 break;
586 case 0x04:
587 case 0x14:
588 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
589 break;
590 case 0x20:
591 biosfn_load_gfx_8_8_chars(ES,BP);
592 break;
593 case 0x21:
594 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
595 break;
596 case 0x22:
597 biosfn_load_gfx_8_14_chars(GET_BL());
598 break;
599 case 0x23:
600 biosfn_load_gfx_8_8_dd_chars(GET_BL());
601 break;
602 case 0x24:
603 biosfn_load_gfx_8_16_chars(GET_BL());
604 break;
605 case 0x30:
606 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
607 break;
608 #ifdef DEBUG
609 default:
610 unknown();
611 #endif
614 break;
615 case 0x12:
616 switch(GET_BL())
618 case 0x10:
619 biosfn_get_ega_info(&BX,&CX);
620 break;
621 case 0x20:
622 biosfn_alternate_prtsc();
623 break;
624 case 0x30:
625 biosfn_select_vert_res(GET_AL());
626 SET_AL(0x12);
627 break;
628 case 0x31:
629 biosfn_enable_default_palette_loading(GET_AL());
630 SET_AL(0x12);
631 break;
632 case 0x32:
633 biosfn_enable_video_addressing(GET_AL());
634 SET_AL(0x12);
635 break;
636 case 0x33:
637 biosfn_enable_grayscale_summing(GET_AL());
638 SET_AL(0x12);
639 break;
640 case 0x34:
641 biosfn_enable_cursor_emulation(GET_AL());
642 SET_AL(0x12);
643 break;
644 case 0x35:
645 biosfn_switch_video_interface(GET_AL(),ES,DX);
646 SET_AL(0x12);
647 break;
648 case 0x36:
649 biosfn_enable_video_refresh_control(GET_AL());
650 SET_AL(0x12);
651 break;
652 #ifdef DEBUG
653 default:
654 unknown();
655 #endif
657 break;
658 case 0x13:
659 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
660 break;
661 case 0x1A:
662 switch(GET_AL())
664 case 0x00:
665 biosfn_read_display_code(&BX);
666 break;
667 case 0x01:
668 biosfn_set_display_code(GET_BL(),GET_BH());
669 break;
670 #ifdef DEBUG
671 default:
672 unknown();
673 #endif
675 SET_AL(0x1A);
676 break;
677 case 0x1B:
678 biosfn_read_state_info(BX,ES,DI);
679 SET_AL(0x1B);
680 break;
681 case 0x1C:
682 switch(GET_AL())
684 case 0x00:
685 biosfn_read_video_state_size(CX,&BX);
686 break;
687 case 0x01:
688 biosfn_save_video_state(CX,ES,BX);
689 break;
690 case 0x02:
691 biosfn_restore_video_state(CX,ES,BX);
692 break;
693 #ifdef DEBUG
694 default:
695 unknown();
696 #endif
698 SET_AL(0x1C);
699 break;
701 #ifdef VBE
702 case 0x4f:
703 if (vbe_has_vbe_display()) {
704 switch(GET_AL())
706 case 0x00:
707 vbe_biosfn_return_controller_information(&AX,ES,DI);
708 break;
709 case 0x01:
710 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
711 break;
712 case 0x02:
713 vbe_biosfn_set_mode(&AX,BX,ES,DI);
714 break;
715 case 0x03:
716 vbe_biosfn_return_current_mode(&AX,&BX);
717 break;
718 case 0x04:
719 //FIXME
720 #ifdef DEBUG
721 unimplemented();
722 #endif
723 // function failed
724 AX=0x100;
725 break;
726 case 0x05:
727 vbe_biosfn_display_window_control(&AX,BX,&DX);
728 break;
729 case 0x06:
730 vbe_biosfn_set_get_logical_scan_line_length(&AX,&BX,&CX,&DX);
731 break;
732 case 0x07:
733 vbe_biosfn_set_get_display_start(&AX,BX,CX,DX);
734 break;
735 case 0x08:
736 //FIXME
737 #ifdef DEBUG
738 unimplemented();
739 #endif
740 // function failed
741 AX=0x100;
742 break;
743 case 0x09:
744 //FIXME
745 #ifdef DEBUG
746 unimplemented();
747 #endif
748 // function failed
749 AX=0x100;
750 break;
751 case 0x0A:
752 //FIXME
753 #ifdef DEBUG
754 unimplemented();
755 #endif
756 // function failed
757 AX=0x100;
758 break;
759 #ifdef DEBUG
760 default:
761 unknown();
762 #endif
763 // function failed
764 AX=0x100;
767 else {
768 // No VBE display
769 AX=0x0100;
771 break;
772 #endif
774 #ifdef DEBUG
775 default:
776 unknown();
777 #endif
781 // ============================================================================================
783 // BIOS functions
785 // ============================================================================================
787 static void biosfn_set_video_mode(mode) Bit8u mode;
788 {// mode: Bit 7 is 1 if no clear screen
790 // Should we clear the screen ?
791 Bit8u noclearmem=mode&0x80;
792 Bit8u line,mmask,*palette;
793 Bit16u i,twidth,theight,cheight;
794 Bit8u modeset_ctl,video_ctl,vga_switches;
795 Bit16u crtc_addr;
797 #ifdef VBE
798 if (vbe_has_vbe_display()) {
799 dispi_set_enable(VBE_DISPI_DISABLED);
801 #endif // def VBE
803 // The real mode
804 mode=mode&0x7f;
806 // find the entry in the video modes
807 line=find_vga_entry(mode);
809 #ifdef DEBUG
810 printf("mode search %02x found line %02x\n",mode,line);
811 #endif
813 if(line==0xFF)
814 return;
816 twidth=vga_modes[line].twidth;
817 theight=vga_modes[line].theight;
818 cheight=vga_modes[line].cheight;
820 // Read the bios vga control
821 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
823 // Read the bios vga switches
824 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
826 // Read the bios mode set control
827 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
829 // Then we know the number of lines
830 // FIXME
832 // if palette loading (bit 3 of modeset ctl = 0)
833 if((modeset_ctl&0x08)==0)
834 {// Set the PEL mask
835 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
837 // Set the whole dac always, from 0
838 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
840 // From which palette
841 switch(vga_modes[line].dacmodel)
842 {case 0:
843 palette=&palette0;
844 break;
845 case 1:
846 palette=&palette1;
847 break;
848 case 2:
849 palette=&palette2;
850 break;
851 case 3:
852 palette=&palette3;
853 break;
857 // Always 256*3 values
858 for(i=0;i<0x0100;i++)
859 {if(i<=dac_regs[vga_modes[line].dacmodel])
860 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
861 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
862 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
864 else
865 {outb(VGAREG_DAC_DATA,0);
866 outb(VGAREG_DAC_DATA,0);
867 outb(VGAREG_DAC_DATA,0);
871 // Reset Attribute Ctl flip-flop
872 inb(VGAREG_ACTL_RESET);
874 // Set Attribute Ctl
875 for(i=0;i<=ACTL_MAX_REG;i++)
876 {outb(VGAREG_ACTL_ADDRESS,i);
877 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
880 // Set Sequencer Ctl
881 for(i=0;i<=SEQU_MAX_REG;i++)
882 {outb(VGAREG_SEQU_ADDRESS,i);
883 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
886 // Set Grafx Ctl
887 for(i=0;i<=GRDC_MAX_REG;i++)
888 {outb(VGAREG_GRDC_ADDRESS,i);
889 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
892 // Set CRTC address VGA or MDA
893 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
895 // Set CRTC regs
896 for(i=0;i<=CRTC_MAX_REG;i++)
897 {outb(crtc_addr,i);
898 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
901 // Set the misc register
902 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
904 // Enable video
905 outb(VGAREG_ACTL_ADDRESS,0x20);
906 inb(VGAREG_ACTL_RESET);
908 if(noclearmem==0x00)
910 if(vga_modes[line].class==TEXT)
912 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
914 else
916 if(mode<0x0d)
918 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
920 else
922 outb( VGAREG_SEQU_ADDRESS, 0x02 );
923 mmask = inb( VGAREG_SEQU_DATA );
924 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
925 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
926 outb( VGAREG_SEQU_DATA, mmask );
931 // Set the BIOS mem
932 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode|noclearmem);
933 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
934 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
935 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
936 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
937 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
938 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
939 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
940 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
942 // FIXME We nearly have the good tables. to be reworked
943 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
944 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
945 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
947 // FIXME
948 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
949 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
951 // Set cursor shape
952 if(vga_modes[line].class==TEXT)
954 biosfn_set_cursor_shape(0x06,0x07);
957 // Set cursor pos for page 0..7
958 for(i=0;i<8;i++)
959 biosfn_set_cursor_pos(i,0x0000);
961 // Set active page 0
962 biosfn_set_active_page(0x00);
964 // Write the fonts in memory
965 if(vga_modes[line].class==TEXT)
967 biosfn_load_text_8_16_pat(0x04,0x00);
970 // Set the ints 0x1F and 0x43
971 ASM_START
972 SET_INT_VECTOR(0x1f, #0xC000, #vgafont8+128*8)
973 ASM_END
975 switch(cheight)
976 {case 8:
977 ASM_START
978 SET_INT_VECTOR(0x43, #0xC000, #vgafont8)
979 ASM_END
980 break;
981 case 14:
982 ASM_START
983 SET_INT_VECTOR(0x43, #0xC000, #vgafont14)
984 ASM_END
985 break;
986 case 16:
987 ASM_START
988 SET_INT_VECTOR(0x43, #0xC000, #vgafont16)
989 ASM_END
990 break;
994 // --------------------------------------------------------------------------------------------
995 static void biosfn_set_cursor_shape (CH,CL)
996 Bit8u CH;Bit8u CL;
997 {Bit16u cheight,curs;
999 CH&=0x3f;
1000 CL&=0x1f;
1002 curs=(CH<<8)+CL;
1003 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1005 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1006 if((cheight>8) && (CL<8) && (CH<0x20))
1008 if(CL!=(CH+1))
1010 CH = ((CH+1) * cheight / 8) -1;
1012 else
1014 CH = ((CL+1) * cheight / 8) - 2;
1016 CL = ((CL+1) * cheight / 8) - 1;
1019 // CTRC regs 0x0a and 0x0b
1020 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0a);
1021 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,CH);
1022 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0b);
1023 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,CL);
1026 // --------------------------------------------------------------------------------------------
1027 static void biosfn_set_cursor_pos (page, cursor)
1028 Bit8u page;Bit16u cursor;
1030 Bit8u xcurs,ycurs,current;
1031 Bit16u nbcols,nbrows,address;
1033 // Should not happen...
1034 if(page>7)return;
1036 // Bios cursor pos
1037 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1039 // Set the hardware cursor
1040 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1041 if(page==current)
1043 // Get the dimensions
1044 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1045 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1047 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1049 // Calculate the address knowing nbcols nbrows and page num
1050 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1052 // CRTC regs 0x0e and 0x0f
1053 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0e);
1054 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(address&0xff00)>>8);
1055 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0f);
1056 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,address&0x00ff);
1060 // --------------------------------------------------------------------------------------------
1061 static void biosfn_get_cursor_pos (page,shape, pos)
1062 Bit8u page;Bit16u *shape;Bit16u *pos;
1064 Bit16u ss=get_SS();
1066 // Default
1067 write_word(ss, shape, 0);
1068 write_word(ss, pos, 0);
1070 if(page>7)return;
1071 // FIXME should handle VGA 14/16 lines
1072 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1073 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1076 // --------------------------------------------------------------------------------------------
1077 static void biosfn_set_active_page (page)
1078 Bit8u page;
1080 Bit16u cursor,dummy;
1081 Bit16u nbcols,nbrows,address;
1082 Bit8u mode,line;
1084 if(page>7)return;
1086 // Get the mode
1087 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1088 line=find_vga_entry(mode);
1089 if(line==0xFF)return;
1091 // Get pos curs pos for the right page
1092 biosfn_get_cursor_pos(page,&dummy,&cursor);
1094 if(vga_modes[line].class==TEXT)
1096 // Get the dimensions
1097 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1098 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1100 // Calculate the address knowing nbcols nbrows and page num
1101 address=SCREEN_MEM_START(nbcols,nbrows,page);
1102 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1104 // Start address
1105 address=SCREEN_IO_START(nbcols,nbrows,page);
1107 else
1109 address = page*vga_modes[line].slength;
1112 // CRTC regs 0x0c and 0x0d
1113 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0c);
1114 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(address&0xff00)>>8);
1115 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0d);
1116 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,address&0x00ff);
1118 // And change the BIOS page
1119 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1121 #ifdef DEBUG
1122 printf("Set active page %02x address %04x\n",page,address);
1123 #endif
1125 // Display the cursor, now the page is active
1126 biosfn_set_cursor_pos(page,cursor);
1129 // --------------------------------------------------------------------------------------------
1130 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1131 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1133 // page == 0xFF if current
1135 Bit8u mode,line;
1136 Bit16u nbcols,nbrows,i;
1137 Bit16u address;
1139 if(rul>rlr)return;
1140 if(cul>clr)return;
1142 // Get the mode
1143 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1144 line=find_vga_entry(mode);
1145 if(line==0xFF)return;
1147 // Get the dimensions
1148 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1149 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1151 // Get the current page
1152 if(page==0xFF)
1153 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1155 if(vga_modes[line].class==TEXT)
1157 // Compute the address
1158 address=SCREEN_MEM_START(nbcols,nbrows,page);
1159 #ifdef DEBUG
1160 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1161 #endif
1163 if(rlr>=nbrows)rlr=nbrows-1;
1164 if(clr>=nbcols)clr=nbcols-1;
1165 if(nblines>nbrows)nblines=0;
1167 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1169 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1171 else
1172 {// if Scroll up
1173 if(dir==SCROLL_UP)
1174 {for(i=rul;i<=rlr;i++)
1176 if((i+nblines>rlr)||(nblines==0))
1177 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1178 else
1179 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,clr-cul+1);
1182 else
1183 {for(i=rlr;i>=rul;i--)
1185 if((i<rul+nblines)||(nblines==0))
1186 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1187 else
1188 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,clr-cul+1);
1193 else
1195 // FIXME gfx mode
1196 #ifdef DEBUG
1197 printf("Scroll in graphics mode !\n");
1198 unimplemented();
1199 #endif
1203 // --------------------------------------------------------------------------------------------
1204 static void biosfn_read_char_attr (page,car)
1205 Bit8u page;Bit16u *car;
1206 {Bit16u ss=get_SS();
1207 Bit8u xcurs,ycurs,mode,line;
1208 Bit16u nbcols,nbrows,address;
1209 Bit16u cursor,dummy;
1211 // Get the mode
1212 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1213 line=find_vga_entry(mode);
1214 if(line==0xFF)return;
1216 // Get the cursor pos for the page
1217 biosfn_get_cursor_pos(page,&dummy,&cursor);
1218 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1220 // Get the dimensions
1221 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1222 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1224 if(vga_modes[line].class==TEXT)
1226 // Compute the address
1227 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1229 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1231 else
1233 // FIXME gfx mode
1234 #ifdef DEBUG
1235 unimplemented();
1236 #endif
1240 // --------------------------------------------------------------------------------------------
1241 static void write_gfx_char(car,attr,xcurs,ycurs,nbcols,cheight)
1242 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1244 Bit8u i,mmask;
1245 Bit8u *fdata;
1246 Bit16u addr,dest,src;
1248 switch(cheight)
1249 {case 14:
1250 fdata = &vgafont14;
1251 break;
1252 case 16:
1253 fdata = &vgafont16;
1254 break;
1255 default:
1256 fdata = &vgafont8;
1258 addr=xcurs+ycurs*cheight*nbcols;
1259 src = car * cheight;
1260 outb( VGAREG_SEQU_ADDRESS, 0x02 );
1261 mmask = inb( VGAREG_SEQU_DATA );
1262 for(i=0;i<cheight;i++)
1264 dest=addr+i*nbcols;
1265 outb( VGAREG_SEQU_DATA, 0x0f );
1266 write_byte(0xa000,dest,0x00);
1267 outb( VGAREG_SEQU_DATA, attr & 0x0f );
1268 write_byte(0xa000,dest,fdata[src+i]);
1270 outb( VGAREG_SEQU_DATA, mmask );
1273 // --------------------------------------------------------------------------------------------
1274 static void biosfn_write_char_attr (car,page,attr,count)
1275 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1277 Bit8u cheight,xcurs,ycurs,mode,line;
1278 Bit16u nbcols,nbrows,address;
1279 Bit16u cursor,dummy;
1281 // Get the mode
1282 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1283 line=find_vga_entry(mode);
1284 if(line==0xFF)return;
1286 // Get the cursor pos for the page
1287 biosfn_get_cursor_pos(page,&dummy,&cursor);
1288 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1290 // Get the dimensions
1291 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1292 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1294 if(vga_modes[line].class==TEXT)
1296 // Compute the address
1297 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1299 dummy=((Bit16u)attr<<8)+car;
1300 memsetw(vga_modes[line].sstart,address,dummy,count);
1302 else
1304 // FIXME gfx mode not complete
1305 if(vga_modes[line].memmodel==PLANAR4)
1307 cheight=vga_modes[line].cheight;
1308 while((count-->0) && (xcurs<nbcols))
1310 write_gfx_char(car,attr,xcurs,ycurs,nbcols,cheight);
1311 xcurs++;
1314 else
1316 #ifdef DEBUG
1317 unimplemented();
1318 #endif
1323 // --------------------------------------------------------------------------------------------
1324 static void biosfn_write_char_only (car,page,attr,count)
1325 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1327 Bit8u cheight,xcurs,ycurs,mode,line;
1328 Bit16u nbcols,nbrows,address;
1329 Bit16u cursor,dummy;
1331 // Get the mode
1332 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1333 line=find_vga_entry(mode);
1334 if(line==0xFF)return;
1336 // Get the cursor pos for the page
1337 biosfn_get_cursor_pos(page,&dummy,&cursor);
1338 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1340 // Get the dimensions
1341 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1342 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1344 if(vga_modes[line].class==TEXT)
1346 // Compute the address
1347 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1349 while(count-->0)
1350 {write_byte(vga_modes[line].sstart,address,car);
1351 address+=2;
1354 else
1356 // FIXME gfx mode not complete
1357 if(vga_modes[line].memmodel==PLANAR4)
1359 cheight=vga_modes[line].cheight;
1360 while((count-->0) && (xcurs<nbcols))
1362 write_gfx_char(car,attr,xcurs,ycurs,nbcols,cheight);
1363 xcurs++;
1366 else
1368 #ifdef DEBUG
1369 unimplemented();
1370 #endif
1375 // --------------------------------------------------------------------------------------------
1376 static void biosfn_set_border_color (BL) Bit8u BL;
1377 // FIXME anybody using this function ?
1379 #ifdef DEBUG
1380 unimplemented();
1381 #endif
1384 // --------------------------------------------------------------------------------------------
1385 static void biosfn_set_palette (BL) Bit8u BL;
1386 // FIXME anybody using this function ?
1388 #ifdef DEBUG
1389 unimplemented();
1390 #endif
1393 // --------------------------------------------------------------------------------------------
1394 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1395 // FIXME anybody using this function ?
1397 #ifdef DEBUG
1398 unimplemented();
1399 #endif
1402 // --------------------------------------------------------------------------------------------
1403 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1404 // FIXME anybody using this function ?
1406 #ifdef DEBUG
1407 unimplemented();
1408 #endif
1411 // --------------------------------------------------------------------------------------------
1412 static void biosfn_write_teletype (car, page, attr, flag)
1413 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1414 {// flag = WITH_ATTR / NO_ATTR
1416 Bit8u cheight,xcurs,ycurs,mode,line;
1417 Bit16u nbcols,nbrows,address;
1418 Bit16u cursor,dummy;
1420 // special case if page is 0xff, use current page
1421 if(page==0xff)
1422 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1424 // FIXME gfx mode
1426 // Get the mode
1427 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1428 line=find_vga_entry(mode);
1429 if(line==0xFF)return;
1431 // Get the cursor pos for the page
1432 biosfn_get_cursor_pos(page,&dummy,&cursor);
1433 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1435 // Get the dimensions
1436 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1437 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1439 switch(car)
1441 case 7:
1442 //FIXME should beep
1443 break;
1445 case 8:
1446 if(xcurs>0)xcurs--;
1447 break;
1449 case '\r':
1450 xcurs=0;
1451 break;
1453 case '\n':
1454 xcurs=0;
1455 ycurs++;
1456 break;
1458 case '\t':
1461 biosfn_write_teletype(' ',page,attr,flag);
1462 biosfn_get_cursor_pos(page,&dummy,&cursor);
1463 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1464 }while(xcurs%8==0);
1465 break;
1467 default:
1469 if(vga_modes[line].class==TEXT)
1471 // Compute the address
1472 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1474 // Write the char
1475 write_byte(vga_modes[line].sstart,address,car);
1477 if(flag==WITH_ATTR)
1478 write_byte(vga_modes[line].sstart,address+1,attr);
1480 else
1482 // FIXME gfx mode not complete
1483 if(vga_modes[line].memmodel==PLANAR4)
1485 cheight=vga_modes[line].cheight;
1486 write_gfx_char(car,attr,xcurs,ycurs,nbcols,cheight);
1488 else
1490 #ifdef DEBUG
1491 unimplemented();
1492 #endif
1496 xcurs++;
1499 // Do we need to wrap ?
1500 if(xcurs==nbcols)
1501 {xcurs=0;
1502 ycurs++;
1505 // Do we need to scroll ?
1506 if(ycurs==nbrows)
1507 {biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1508 ycurs-=1;
1511 // Set the cursor for the page
1512 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1513 biosfn_set_cursor_pos(page,cursor);
1516 // --------------------------------------------------------------------------------------------
1517 static void biosfn_get_video_mode (AX,BX)
1518 Bit16u *AX;Bit16u *BX;
1519 {Bit16u ss=get_SS();
1520 Bit8u mode,page;
1521 Bit16u nbcars;
1523 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1524 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1525 nbcars=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1527 write_word(ss,AX,(nbcars<<8)+mode);
1528 write_word(ss,BX,((Bit16u)page)<<8);
1531 // --------------------------------------------------------------------------------------------
1532 static void biosfn_set_single_palette_reg (reg,value)
1533 Bit8u reg;Bit8u value;
1535 if(reg<=ACTL_MAX_REG)
1537 inb(VGAREG_ACTL_RESET);
1538 outb(VGAREG_ACTL_ADDRESS,reg);
1539 outb(VGAREG_ACTL_WRITE_DATA,value);
1540 outb(VGAREG_ACTL_ADDRESS,0x20);
1544 // --------------------------------------------------------------------------------------------
1545 static void biosfn_set_overscan_border_color (value)
1546 Bit8u value;
1548 inb(VGAREG_ACTL_RESET);
1549 outb(VGAREG_ACTL_ADDRESS,0x11);
1550 outb(VGAREG_ACTL_WRITE_DATA,value);
1551 outb(VGAREG_ACTL_ADDRESS,0x20);
1554 // --------------------------------------------------------------------------------------------
1555 static void biosfn_set_all_palette_reg (seg,offset)
1556 Bit16u seg;Bit16u offset;
1558 Bit8u i;
1560 inb(VGAREG_ACTL_RESET);
1561 // First the colors
1562 for(i=0;i<0x10;i++)
1564 outb(VGAREG_ACTL_ADDRESS,i);
1565 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1566 offset++;
1569 // Then the border
1570 outb(VGAREG_ACTL_ADDRESS,0x11);
1571 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1572 outb(VGAREG_ACTL_ADDRESS,0x20);
1575 // --------------------------------------------------------------------------------------------
1576 static void biosfn_toggle_intensity (state)
1577 Bit8u state;
1578 {Bit8u value;
1579 state&=0x01;
1580 inb(VGAREG_ACTL_RESET);
1582 outb(VGAREG_ACTL_ADDRESS,0x10);
1583 value=inb(VGAREG_ACTL_READ_DATA);
1584 value&=0xf7;
1585 value|=state<<3;
1586 outb(VGAREG_ACTL_WRITE_DATA,value);
1587 outb(VGAREG_ACTL_ADDRESS,0x20);
1590 // --------------------------------------------------------------------------------------------
1591 static void biosfn_get_single_palette_reg (reg,value)
1592 Bit8u reg;Bit16u *value;
1593 {Bit16u ss=get_SS();
1595 if(reg<=ACTL_MAX_REG)
1597 inb(VGAREG_ACTL_RESET);
1598 outb(VGAREG_ACTL_ADDRESS,reg);
1599 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1600 inb(VGAREG_ACTL_RESET);
1601 outb(VGAREG_ACTL_ADDRESS,0x20);
1605 // --------------------------------------------------------------------------------------------
1606 static void biosfn_read_overscan_border_color (value)
1607 Bit16u *value;
1608 {Bit16u ss=get_SS();
1610 inb(VGAREG_ACTL_RESET);
1611 outb(VGAREG_ACTL_ADDRESS,0x11);
1612 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1613 outb(VGAREG_ACTL_ADDRESS,0x20);
1616 // --------------------------------------------------------------------------------------------
1617 static void biosfn_get_all_palette_reg (seg,offset) Bit16u seg;Bit16u offset;
1619 Bit8u i;
1621 // First the colors
1622 for(i=0;i<=0x10;i++)
1624 inb(VGAREG_ACTL_RESET);
1625 outb(VGAREG_ACTL_ADDRESS,i);
1626 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1627 offset++;
1630 // Then the border
1631 outb(VGAREG_ACTL_ADDRESS,0x11);
1632 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1633 outb(VGAREG_ACTL_ADDRESS,0x20);
1636 // --------------------------------------------------------------------------------------------
1637 static void biosfn_set_single_dac_reg (reg,g,b,r)
1638 Bit16u reg;Bit8u g;Bit8u b;Bit8u r;
1640 outb(VGAREG_DAC_WRITE_ADDRESS,reg);
1641 outb(VGAREG_DAC_DATA,r);
1642 outb(VGAREG_DAC_DATA,g);
1643 outb(VGAREG_DAC_DATA,b);
1646 // --------------------------------------------------------------------------------------------
1647 static void biosfn_set_all_dac_reg (start,count,seg,offset)
1648 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1649 {Bit16u i;
1650 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1651 for(i=0;i<count;i++)
1652 {outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1653 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1654 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1658 // --------------------------------------------------------------------------------------------
1659 static void biosfn_select_video_dac_color_page (function,page)
1660 Bit8u function;
1661 {Bit8u value;
1663 inb(VGAREG_ACTL_RESET);
1664 outb(VGAREG_ACTL_ADDRESS,0x10);
1666 value=inb(VGAREG_ACTL_READ_DATA);
1667 function&=0x01;
1668 if(function==0)
1669 {// set paging code
1670 value&=0x7f;
1671 value|=page<<7;
1672 outb(VGAREG_ACTL_WRITE_DATA,value);
1674 else
1675 {// select page
1676 inb(VGAREG_ACTL_RESET);
1677 outb(VGAREG_ACTL_ADDRESS,0x14);
1678 if(value&0x80)
1679 outb(VGAREG_ACTL_WRITE_DATA,page&0x0f);
1680 else
1681 outb(VGAREG_ACTL_WRITE_DATA,(page&0x03)<<2);
1683 outb(VGAREG_ACTL_ADDRESS,0x20);
1686 // --------------------------------------------------------------------------------------------
1687 static void biosfn_read_single_dac_reg (reg,tor,togb)
1688 Bit8u reg;Bit16u *tor;Bit16u *togb;
1689 {Bit16u ss=get_SS();
1690 Bit8u r,g,b;
1692 outb(VGAREG_DAC_READ_ADDRESS,reg);
1693 r=inb(VGAREG_DAC_DATA);
1694 g=inb(VGAREG_DAC_DATA);
1695 b=inb(VGAREG_DAC_DATA);
1696 write_word(ss,tor,((Bit16u)r)<<8);
1697 write_word(ss,togb,(((Bit16u)g)<<8)+b);
1700 // --------------------------------------------------------------------------------------------
1701 static void biosfn_read_all_dac_reg (start,count,seg,offset)
1702 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1703 {Bit16u i;
1704 outb(VGAREG_DAC_READ_ADDRESS,start);
1705 for(i=0;i<count;i++)
1706 {write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1707 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1708 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1712 // --------------------------------------------------------------------------------------------
1713 static void biosfn_set_pel_mask (mask)
1714 Bit8u mask;
1716 outb(VGAREG_PEL_MASK,mask);
1719 // --------------------------------------------------------------------------------------------
1720 static void biosfn_read_pel_mask (mask)
1721 Bit16u *mask;
1722 {Bit16u ss=get_SS();
1724 write_word(ss,mask,inb(VGAREG_PEL_MASK));
1727 // --------------------------------------------------------------------------------------------
1728 static void biosfn_read_video_dac_state (state) Bit16u *state;
1729 {Bit16u ss=get_SS();
1730 Bit8u mcr,csr;
1732 inb(VGAREG_ACTL_RESET);
1733 outb(VGAREG_ACTL_ADDRESS,0x10);
1734 mcr=(inb(VGAREG_ACTL_READ_DATA)>>7)&0x01;
1735 inb(VGAREG_ACTL_RESET);
1736 outb(VGAREG_ACTL_ADDRESS,0x14);
1737 csr=inb(VGAREG_ACTL_READ_DATA)&0x0f;
1738 if(mcr==0)(csr>>2)&0x03;
1740 write_word(ss,state,(mcr<<8)+csr);
1741 outb(VGAREG_ACTL_ADDRESS,0x20);
1744 // --------------------------------------------------------------------------------------------
1745 static void biosfn_perform_gray_scale_summing (start,count)
1746 Bit16u start;Bit16u count;
1747 {Bit8u r,g,b,d;
1748 Bit16u i,m;
1749 Bit16u index;
1751 inb(VGAREG_ACTL_RESET);
1752 outb(VGAREG_ACTL_ADDRESS,0x10);
1753 d=(inb(VGAREG_ACTL_READ_DATA)>>6)&0x01;
1755 // depth is 8 or 6 bits
1756 if(d==0)m=0x3f;
1757 else m=0xff;
1760 // We start overwriting at
1761 outb(VGAREG_DAC_READ_ADDRESS,start);
1762 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1764 for( index = 0; index < count; index++ )
1766 // get 6-bit wide RGB data values
1767 r=inb( VGAREG_DAC_DATA );
1768 g=inb( VGAREG_DAC_DATA );
1769 b=inb( VGAREG_DAC_DATA );
1771 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
1772 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
1774 if(i>m)i=m;
1776 // write new intensity value
1777 outb( VGAREG_DAC_DATA, i&0xff );
1778 outb( VGAREG_DAC_DATA, i&0xff );
1779 outb( VGAREG_DAC_DATA, i&0xff );
1781 outb(VGAREG_ACTL_ADDRESS,0x20);
1784 // --------------------------------------------------------------------------------------------
1785 static void get_font_access()
1787 outw( VGAREG_SEQU_ADDRESS, 0x0100 );
1788 outw( VGAREG_SEQU_ADDRESS, 0x0402 );
1789 outw( VGAREG_SEQU_ADDRESS, 0x0704 );
1790 outw( VGAREG_SEQU_ADDRESS, 0x0300 );
1791 outw( VGAREG_GRDC_ADDRESS, 0x0204 );
1792 outw( VGAREG_GRDC_ADDRESS, 0x0005 );
1793 outw( VGAREG_GRDC_ADDRESS, 0x0406 );
1796 static void release_font_access()
1798 outw( VGAREG_SEQU_ADDRESS, 0x0100 );
1799 outw( VGAREG_SEQU_ADDRESS, 0x0302 );
1800 outw( VGAREG_SEQU_ADDRESS, 0x0304 );
1801 outw( VGAREG_SEQU_ADDRESS, 0x0300 );
1802 outw( VGAREG_GRDC_ADDRESS, 0x0004 );
1803 outw( VGAREG_GRDC_ADDRESS, 0x1005 );
1804 outw( VGAREG_GRDC_ADDRESS, 0x0e06 );
1807 ASM_START
1808 idiv_u:
1809 xor dx,dx
1810 div bx
1812 ASM_END
1814 static void set_scan_lines(lines) Bit8u lines;
1816 Bit16u cols,page,vde;
1817 Bit8u crtc9,ovl,rows;
1819 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS), 0x09);
1820 crtc9 = inb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1);
1821 crtc9 = (crtc9 & 0xe0) | (lines - 1);
1822 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1, crtc9);
1823 if(lines==8)
1825 biosfn_set_cursor_shape(0x06,0x07);
1827 else
1829 biosfn_set_cursor_shape(lines-4,lines-3);
1831 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
1832 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS), 0x12);
1833 vde = inb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1);
1834 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS), 0x07);
1835 ovl = inb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1);
1836 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
1837 rows = vde / lines;
1838 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
1839 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1840 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
1843 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;
1845 Bit16u blockaddr,dest,i,src;
1847 get_font_access();
1848 blockaddr = BL << 13;
1849 for(i=0;i<CX;i++)
1851 src = BP + i * BH;
1852 dest = blockaddr + (DX + i) * 32;
1853 memcpyb(0xA000, dest, ES, src, BH);
1855 release_font_access();
1856 if(AL>=0x10)
1858 set_scan_lines(BH);
1862 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
1864 Bit16u blockaddr,dest,i,src;
1866 get_font_access();
1867 blockaddr = BL << 13;
1868 for(i=0;i<0x100;i++)
1870 src = i * 14;
1871 dest = blockaddr + i * 32;
1872 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
1874 release_font_access();
1875 if(AL>=0x10)
1877 set_scan_lines(14);
1881 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
1883 Bit16u blockaddr,dest,i,src;
1885 get_font_access();
1886 blockaddr = BL << 13;
1887 for(i=0;i<0x100;i++)
1889 src = i * 8;
1890 dest = blockaddr + i * 32;
1891 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
1893 release_font_access();
1894 if(AL>=0x10)
1896 set_scan_lines(8);
1900 static void biosfn_set_text_block_specifier (BL) Bit8u BL;
1902 outb( VGAREG_SEQU_ADDRESS, 0x03 );
1903 outb( VGAREG_SEQU_DATA, BL );
1906 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
1908 Bit16u blockaddr,dest,i,src;
1910 get_font_access();
1911 blockaddr = BL << 13;
1912 for(i=0;i<0x100;i++)
1914 src = i * 16;
1915 dest = blockaddr + i * 32;
1916 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
1918 release_font_access();
1919 if(AL>=0x10)
1921 set_scan_lines(16);
1925 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
1927 #ifdef DEBUG
1928 unimplemented();
1929 #endif
1931 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
1933 #ifdef DEBUG
1934 unimplemented();
1935 #endif
1937 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
1939 #ifdef DEBUG
1940 unimplemented();
1941 #endif
1943 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
1945 #ifdef DEBUG
1946 unimplemented();
1947 #endif
1949 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
1951 #ifdef DEBUG
1952 unimplemented();
1953 #endif
1955 // --------------------------------------------------------------------------------------------
1956 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
1957 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
1958 {Bit16u ss=get_SS();
1960 switch(BH)
1961 {case 0x00:
1962 write_word(ss,ES,read_word(0x00,0x1f*4));
1963 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
1964 break;
1965 case 0x01:
1966 write_word(ss,ES,read_word(0x00,0x43*4));
1967 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
1968 break;
1969 case 0x02:
1970 write_word(ss,ES,0xC000);
1971 write_word(ss,BP,vgafont14);
1972 break;
1973 case 0x03:
1974 write_word(ss,ES,0xC000);
1975 write_word(ss,BP,vgafont8);
1976 break;
1977 case 0x04:
1978 write_word(ss,ES,0xC000);
1979 write_word(ss,BP,vgafont8+128*8);
1980 break;
1981 case 0x05:
1982 write_word(ss,ES,0xC000);
1983 write_word(ss,BP,vgafont14alt);
1984 break;
1985 case 0x06:
1986 write_word(ss,ES,0xC000);
1987 write_word(ss,BP,vgafont16);
1988 break;
1989 case 0x07:
1990 write_word(ss,ES,0xC000);
1991 write_word(ss,BP,vgafont16alt);
1992 break;
1993 default:
1994 #ifdef DEBUG
1995 printf("Get font info BH(%02x) was discarded\n",BH);
1996 #endif
1997 return;
1999 // Set byte/char of on screen font
2000 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2002 // Set Highest char row
2003 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2006 // --------------------------------------------------------------------------------------------
2007 static void biosfn_get_ega_info (BX,CX)
2008 Bit16u *BX;Bit16u *CX;
2009 {Bit16u ss=get_SS();
2010 Bit16u crtc;
2011 Bit8u switches;
2013 crtc=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2014 if(crtc==VGAREG_MDA_CRTC_ADDRESS)
2015 write_word(ss,BX,(1<<8)+0x0003);
2016 else
2017 write_word(ss,BX,0x0003);
2019 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2020 write_word(ss,CX,(switches&0x0f));
2023 // --------------------------------------------------------------------------------------------
2024 static void biosfn_alternate_prtsc()
2026 #ifdef DEBUG
2027 unimplemented();
2028 #endif
2031 // --------------------------------------------------------------------------------------------
2032 static void biosfn_select_vert_res (res)
2033 Bit8u res;
2034 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2035 Bit8u modeset,switches;
2037 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2038 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2039 switch(res)
2040 {case 0x00:
2041 // set modeset ctl bit 7 and reset bit 4
2042 // set switches bit 3-0 to 0x08
2043 modeset|=0x80;modeset&=0xef;
2044 switches&=0xf0;switches|=0x08;
2045 break;
2046 case 0x01:
2047 // reset modeset ctl bit 7 and bit 4
2048 // set switches bit 3-0 to 0x09
2049 modeset&=0x6f;
2050 switches&=0xf0;switches|=0x09;
2051 break;
2052 case 0x02:
2053 // reset modeset ctl bit 7 and set bit 4
2054 // set switches bit 3-0 to 0x09
2055 modeset|=0x10;modeset&=0x7f;
2056 switches&=0xf0;switches|=0x09;
2057 break;
2058 default:
2059 #ifdef DEBUG
2060 printf("Select vert res (%02x) was discarded\n",res);
2061 #endif
2062 return;
2064 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2065 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2068 // --------------------------------------------------------------------------------------------
2069 static void biosfn_enable_default_palette_loading (disable)
2070 Bit8u disable;
2072 Bit8u modeset;
2074 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2076 // Bit 3
2077 if(disable!=0x00)modeset|=0x08;
2078 else modeset&=0xf7;
2080 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2083 // --------------------------------------------------------------------------------------------
2084 static void biosfn_enable_video_addressing (disable)
2085 Bit8u disable;
2087 Bit8u misc;
2089 misc=inb(VGAREG_READ_MISC_OUTPUT);
2090 // bit 1, 0 disable
2091 if(disable!=0x00) misc&=0xfd;
2092 else misc|=0x02;
2093 outb(VGAREG_WRITE_MISC_OUTPUT,misc);
2096 // --------------------------------------------------------------------------------------------
2097 static void biosfn_enable_grayscale_summing (disable)
2098 Bit8u disable;
2100 Bit8u modeset;
2102 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2104 // Bit 1 set if disable=0
2105 if(disable==0x00)modeset|=0x02;
2106 else modeset&=0xfd;
2108 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2111 // --------------------------------------------------------------------------------------------
2112 static void biosfn_enable_cursor_emulation (disable)
2113 Bit8u disable;
2115 Bit8u videoctl;
2117 videoctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
2119 // Bit 0 set if disable!=0
2120 if(disable!=0x00)videoctl|=0x01;
2121 else videoctl&=0xfe;
2123 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,videoctl);
2126 // --------------------------------------------------------------------------------------------
2127 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2129 #ifdef DEBUG
2130 unimplemented();
2131 #endif
2133 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2135 #ifdef DEBUG
2136 unimplemented();
2137 #endif
2140 // --------------------------------------------------------------------------------------------
2141 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2142 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2144 Bit16u newcurs,oldcurs,dummy;
2145 Bit8u car,carattr;
2147 // Read curs info for the page
2148 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2150 // if row=0xff special case : use current cursor position
2151 if(row==0xff)
2152 {col=oldcurs&0x00ff;
2153 row=(oldcurs&0xff00)>>8;
2156 newcurs=row; newcurs<<=8; newcurs+=col;
2157 biosfn_set_cursor_pos(page,newcurs);
2159 while(count--!=0)
2161 car=read_byte(seg,offset++);
2162 if((flag&0x02)!=0)
2163 attr=read_byte(seg,offset++);
2165 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2168 // Set back curs pos
2169 if((flag&0x01)==0)
2170 biosfn_set_cursor_pos(page,oldcurs);
2173 // --------------------------------------------------------------------------------------------
2174 static void biosfn_read_display_code (BX)
2175 Bit16u *BX;
2177 Bit16u ss=get_SS();
2178 write_word(ss,BX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2181 // --------------------------------------------------------------------------------------------
2182 static void biosfn_set_display_code (BL,BH)
2183 Bit8u BL;Bit8u BH;
2185 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,BL);
2187 #ifdef DEBUG
2188 printf("Alternate Display code (%02x) was discarded\n",BH);
2189 #endif
2192 // --------------------------------------------------------------------------------------------
2193 static void biosfn_read_state_info (BX,ES,DI)
2194 Bit16u BX;Bit16u ES;Bit16u DI;
2196 // Address of static functionality table
2197 write_word(ES,DI+0x00,&static_functionality);
2198 write_word(ES,DI+0x02,0xC000);
2200 // Hard coded copy from BIOS area. Should it be cleaner ?
2201 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2202 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2204 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2205 write_byte(ES,DI+0x26,0);
2206 write_byte(ES,DI+0x27,16);
2207 write_byte(ES,DI+0x28,0);
2208 write_byte(ES,DI+0x29,8);
2209 write_byte(ES,DI+0x2a,2);
2210 write_byte(ES,DI+0x2b,0);
2211 write_byte(ES,DI+0x2c,0);
2212 write_byte(ES,DI+0x31,3);
2213 write_byte(ES,DI+0x32,0);
2215 memsetb(ES,DI+0x33,0,13);
2218 // --------------------------------------------------------------------------------------------
2219 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2221 #ifdef DEBUG
2222 unimplemented();
2223 #endif
2225 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2227 #ifdef DEBUG
2228 unimplemented();
2229 #endif
2231 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2233 #ifdef DEBUG
2234 unimplemented();
2235 #endif
2238 // ============================================================================================
2240 // Video Utils
2242 // ============================================================================================
2244 // --------------------------------------------------------------------------------------------
2245 static Bit8u find_vga_entry(mode)
2246 Bit8u mode;
2248 Bit8u i,line=0xFF;
2249 for(i=0;i<=MODE_MAX;i++)
2250 if(vga_modes[i].svgamode==mode)
2251 {line=i;
2252 break;
2254 return line;
2257 /* =========================================================== */
2259 * Misc Utils
2261 /* =========================================================== */
2263 // --------------------------------------------------------------------------------------------
2264 static void memsetb(seg,offset,value,count)
2265 Bit16u seg;
2266 Bit16u offset;
2267 Bit16u value;
2268 Bit16u count;
2270 ASM_START
2271 push bp
2272 mov bp, sp
2274 push ax
2275 push cx
2276 push es
2277 push di
2279 mov cx, 10[bp] ; count
2280 cmp cx, #0x00
2281 je memsetb_end
2282 mov ax, 4[bp] ; segment
2283 mov es, ax
2284 mov ax, 6[bp] ; offset
2285 mov di, ax
2286 mov al, 8[bp] ; value
2289 stosb
2291 memsetb_end:
2292 pop di
2293 pop es
2294 pop cx
2295 pop ax
2297 pop bp
2298 ASM_END
2301 // --------------------------------------------------------------------------------------------
2302 static void memsetw(seg,offset,value,count)
2303 Bit16u seg;
2304 Bit16u offset;
2305 Bit16u value;
2306 Bit16u count;
2308 ASM_START
2309 push bp
2310 mov bp, sp
2312 push ax
2313 push cx
2314 push es
2315 push di
2317 mov cx, 10[bp] ; count
2318 cmp cx, #0x00
2319 je memsetw_end
2320 mov ax, 4[bp] ; segment
2321 mov es, ax
2322 mov ax, 6[bp] ; offset
2323 mov di, ax
2324 mov ax, 8[bp] ; value
2327 stosw
2329 memsetw_end:
2330 pop di
2331 pop es
2332 pop cx
2333 pop ax
2335 pop bp
2336 ASM_END
2339 // --------------------------------------------------------------------------------------------
2340 static void memcpyb(dseg,doffset,sseg,soffset,count)
2341 Bit16u dseg;
2342 Bit16u doffset;
2343 Bit16u sseg;
2344 Bit16u soffset;
2345 Bit16u count;
2347 ASM_START
2348 push bp
2349 mov bp, sp
2351 push ax
2352 push cx
2353 push es
2354 push di
2355 push ds
2356 push si
2358 mov cx, 12[bp] ; count
2359 cmp cx, #0x0000
2360 je memcpyb_end
2361 mov ax, 4[bp] ; dsegment
2362 mov es, ax
2363 mov ax, 6[bp] ; doffset
2364 mov di, ax
2365 mov ax, 8[bp] ; ssegment
2366 mov ds, ax
2367 mov ax, 10[bp] ; soffset
2368 mov si, ax
2371 movsb
2373 memcpyb_end:
2374 pop si
2375 pop ds
2376 pop di
2377 pop es
2378 pop cx
2379 pop ax
2381 pop bp
2382 ASM_END
2385 // --------------------------------------------------------------------------------------------
2386 static void memcpyw(dseg,doffset,sseg,soffset,count)
2387 Bit16u dseg;
2388 Bit16u doffset;
2389 Bit16u sseg;
2390 Bit16u soffset;
2391 Bit16u count;
2393 ASM_START
2394 push bp
2395 mov bp, sp
2397 push ax
2398 push cx
2399 push es
2400 push di
2401 push ds
2402 push si
2404 mov cx, 12[bp] ; count
2405 cmp cx, #0x0000
2406 je memcpyw_end
2407 mov ax, 4[bp] ; dsegment
2408 mov es, ax
2409 mov ax, 6[bp] ; doffset
2410 mov di, ax
2411 mov ax, 8[bp] ; ssegment
2412 mov ds, ax
2413 mov ax, 10[bp] ; soffset
2414 mov si, ax
2417 movsw
2419 memcpyw_end:
2420 pop si
2421 pop ds
2422 pop di
2423 pop es
2424 pop cx
2425 pop ax
2427 pop bp
2428 ASM_END
2431 /* =========================================================== */
2433 * These functions where ripped from Kevin's rombios.c
2435 /* =========================================================== */
2437 // --------------------------------------------------------------------------------------------
2438 static Bit8u
2439 read_byte(seg, offset)
2440 Bit16u seg;
2441 Bit16u offset;
2443 ASM_START
2444 push bp
2445 mov bp, sp
2447 push bx
2448 push ds
2449 mov ax, 4[bp] ; segment
2450 mov ds, ax
2451 mov bx, 6[bp] ; offset
2452 mov al, [bx]
2453 ;; al = return value (byte)
2454 pop ds
2455 pop bx
2457 pop bp
2458 ASM_END
2461 // --------------------------------------------------------------------------------------------
2462 static Bit16u
2463 read_word(seg, offset)
2464 Bit16u seg;
2465 Bit16u offset;
2467 ASM_START
2468 push bp
2469 mov bp, sp
2471 push bx
2472 push ds
2473 mov ax, 4[bp] ; segment
2474 mov ds, ax
2475 mov bx, 6[bp] ; offset
2476 mov ax, [bx]
2477 ;; ax = return value (word)
2478 pop ds
2479 pop bx
2481 pop bp
2482 ASM_END
2485 // --------------------------------------------------------------------------------------------
2486 static void
2487 write_byte(seg, offset, data)
2488 Bit16u seg;
2489 Bit16u offset;
2490 Bit8u data;
2492 ASM_START
2493 push bp
2494 mov bp, sp
2496 push ax
2497 push bx
2498 push ds
2499 mov ax, 4[bp] ; segment
2500 mov ds, ax
2501 mov bx, 6[bp] ; offset
2502 mov al, 8[bp] ; data byte
2503 mov [bx], al ; write data byte
2504 pop ds
2505 pop bx
2506 pop ax
2508 pop bp
2509 ASM_END
2512 // --------------------------------------------------------------------------------------------
2513 static void
2514 write_word(seg, offset, data)
2515 Bit16u seg;
2516 Bit16u offset;
2517 Bit16u data;
2519 ASM_START
2520 push bp
2521 mov bp, sp
2523 push ax
2524 push bx
2525 push ds
2526 mov ax, 4[bp] ; segment
2527 mov ds, ax
2528 mov bx, 6[bp] ; offset
2529 mov ax, 8[bp] ; data word
2530 mov [bx], ax ; write data word
2531 pop ds
2532 pop bx
2533 pop ax
2535 pop bp
2536 ASM_END
2539 // --------------------------------------------------------------------------------------------
2540 Bit8u
2541 inb(port)
2542 Bit16u port;
2544 ASM_START
2545 push bp
2546 mov bp, sp
2548 push dx
2549 mov dx, 4[bp]
2550 in al, dx
2551 pop dx
2553 pop bp
2554 ASM_END
2557 Bit16u
2558 inw(port)
2559 Bit16u port;
2561 ASM_START
2562 push bp
2563 mov bp, sp
2565 push dx
2566 mov dx, 4[bp]
2567 in ax, dx
2568 pop dx
2570 pop bp
2571 ASM_END
2574 // --------------------------------------------------------------------------------------------
2575 void
2576 outb(port, val)
2577 Bit16u port;
2578 Bit8u val;
2580 ASM_START
2581 push bp
2582 mov bp, sp
2584 push ax
2585 push dx
2586 mov dx, 4[bp]
2587 mov al, 6[bp]
2588 out dx, al
2589 pop dx
2590 pop ax
2592 pop bp
2593 ASM_END
2596 // --------------------------------------------------------------------------------------------
2597 void
2598 outw(port, val)
2599 Bit16u port;
2600 Bit16u val;
2602 ASM_START
2603 push bp
2604 mov bp, sp
2606 push ax
2607 push dx
2608 mov dx, 4[bp]
2609 mov ax, 6[bp]
2610 out dx, ax
2611 pop dx
2612 pop ax
2614 pop bp
2615 ASM_END
2618 Bit16u get_SS()
2620 ASM_START
2621 mov ax, ss
2622 ASM_END
2625 #ifdef DEBUG
2626 void unimplemented()
2628 printf("--> Unimplemented\n");
2631 void unknown()
2633 printf("--> Unknown int10\n");
2635 #endif
2637 // --------------------------------------------------------------------------------------------
2638 void printf(s)
2639 Bit8u *s;
2641 Bit8u c, format_char;
2642 Boolean in_format;
2643 unsigned format_width, i;
2644 Bit16u *arg_ptr;
2645 Bit16u arg_seg, arg, digit, nibble, shift_count;
2647 arg_ptr = &s;
2648 arg_seg = get_SS();
2650 in_format = 0;
2651 format_width = 0;
2653 while (c = read_byte(0xc000, s)) {
2654 if ( c == '%' ) {
2655 in_format = 1;
2656 format_width = 0;
2658 else if (in_format) {
2659 if ( (c>='0') && (c<='9') ) {
2660 format_width = (format_width * 10) + (c - '0');
2662 else if (c == 'x') {
2663 arg_ptr++; // increment to next arg
2664 arg = read_word(arg_seg, arg_ptr);
2665 if (format_width == 0)
2666 format_width = 4;
2667 i = 0;
2668 digit = format_width - 1;
2669 for (i=0; i<format_width; i++) {
2670 nibble = (arg >> (4 * digit)) & 0x000f;
2671 if (nibble <= 9)
2672 outb(0x0500, nibble + '0');
2673 else
2674 outb(0x0500, (nibble - 10) + 'A');
2675 digit--;
2677 in_format = 0;
2679 //else if (c == 'd') {
2680 // in_format = 0;
2681 // }
2683 else {
2684 outb(0x0500, c);
2686 s ++;
2690 #ifdef VBE
2691 #include "vbe.c"
2692 #endif
2694 // --------------------------------------------------------------------------------------------
2696 ASM_START
2697 ;; DATA_SEG_DEFS_HERE
2698 ASM_END
2700 ASM_START
2701 .ascii "vgabios ends here"
2702 .byte 0x00
2703 vgabios_end:
2704 .byte 0xCB
2705 ;; BLOCK_STRINGS_BEGIN
2706 ASM_END