- 15 bpp VBE modes added
[vgabios.git] / vgabios.c
blob6a412fcef1b1b90a22b7a1058cee7d4714f70b6c
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) 2002 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);
1543 // --------------------------------------------------------------------------------------------
1544 static void biosfn_set_overscan_border_color (value)
1545 Bit8u value;
1547 inb(VGAREG_ACTL_RESET);
1548 outb(VGAREG_ACTL_ADDRESS,0x11);
1549 outb(VGAREG_ACTL_WRITE_DATA,value);
1552 // --------------------------------------------------------------------------------------------
1553 static void biosfn_set_all_palette_reg (seg,offset)
1554 Bit16u seg;Bit16u offset;
1556 Bit8u i;
1558 inb(VGAREG_ACTL_RESET);
1559 // First the colors
1560 for(i=0;i<=0x10;i++)
1562 outb(VGAREG_ACTL_ADDRESS,i);
1563 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1564 offset++;
1567 // Then the border
1568 outb(VGAREG_ACTL_ADDRESS,0x11);
1569 outb(VGAREG_ACTL_WRITE_DATA,read_byte(seg,offset));
1572 // --------------------------------------------------------------------------------------------
1573 static void biosfn_toggle_intensity (state)
1574 Bit8u state;
1575 {Bit8u value;
1576 state&=0x01;
1577 inb(VGAREG_ACTL_RESET);
1579 outb(VGAREG_ACTL_ADDRESS,0x10);
1580 value=inb(VGAREG_ACTL_READ_DATA);
1581 value&=0xf7;
1582 value|=state<<3;
1584 inb(VGAREG_ACTL_RESET);
1585 outb(VGAREG_ACTL_ADDRESS,0x10);
1586 outb(VGAREG_ACTL_WRITE_DATA,value);
1589 // --------------------------------------------------------------------------------------------
1590 static void biosfn_get_single_palette_reg (reg,value)
1591 Bit8u reg;Bit16u *value;
1592 {Bit16u ss=get_SS();
1594 if(reg<=ACTL_MAX_REG)
1596 inb(VGAREG_ACTL_RESET);
1597 outb(VGAREG_ACTL_ADDRESS,reg);
1598 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1602 // --------------------------------------------------------------------------------------------
1603 static void biosfn_read_overscan_border_color (value)
1604 Bit16u *value;
1605 {Bit16u ss=get_SS();
1607 inb(VGAREG_ACTL_RESET);
1608 outb(VGAREG_ACTL_ADDRESS,0x11);
1609 write_word(ss,value,((Bit16u)inb(VGAREG_ACTL_READ_DATA))<<8);
1612 // --------------------------------------------------------------------------------------------
1613 static void biosfn_get_all_palette_reg (seg,offset) Bit16u seg;Bit16u offset;
1615 Bit8u i;
1617 inb(VGAREG_ACTL_RESET);
1618 // First the colors
1619 for(i=0;i<=0x10;i++)
1621 outb(VGAREG_ACTL_ADDRESS,i);
1622 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1623 offset++;
1626 // Then the border
1627 outb(VGAREG_ACTL_ADDRESS,0x11);
1628 write_byte(seg,offset,inb(VGAREG_ACTL_READ_DATA));
1631 // --------------------------------------------------------------------------------------------
1632 static void biosfn_set_single_dac_reg (reg,g,b,r)
1633 Bit16u reg;Bit8u g;Bit8u b;Bit8u r;
1635 outb(VGAREG_DAC_WRITE_ADDRESS,reg);
1636 outb(VGAREG_DAC_DATA,r);
1637 outb(VGAREG_DAC_DATA,g);
1638 outb(VGAREG_DAC_DATA,b);
1641 // --------------------------------------------------------------------------------------------
1642 static void biosfn_set_all_dac_reg (start,count,seg,offset)
1643 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1644 {Bit16u i;
1645 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1646 for(i=0;i<count;i++)
1647 {outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1648 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1649 outb(VGAREG_DAC_DATA,read_byte(seg,offset++));
1653 // --------------------------------------------------------------------------------------------
1654 static void biosfn_select_video_dac_color_page (function,page)
1655 Bit8u function;
1656 {Bit8u value;
1658 inb(VGAREG_ACTL_RESET);
1659 outb(VGAREG_ACTL_ADDRESS,0x10);
1661 value=inb(VGAREG_ACTL_READ_DATA);
1662 function&=0x01;
1663 if(function==0)
1664 {// 4 of 64
1665 value&=0x7f;
1666 value|=function<<7;
1668 inb(VGAREG_ACTL_RESET);
1669 outb(VGAREG_ACTL_ADDRESS,0x10);
1670 outb(VGAREG_ACTL_WRITE_DATA,value);
1672 else
1673 {// 16 of 16
1674 inb(VGAREG_ACTL_RESET);
1675 outb(VGAREG_ACTL_ADDRESS,0x14);
1676 if(value&0x80)
1677 outb(VGAREG_ACTL_WRITE_DATA,page&0x0f);
1678 else
1679 outb(VGAREG_ACTL_WRITE_DATA,(page&0x03)<<2);
1683 // --------------------------------------------------------------------------------------------
1684 static void biosfn_read_single_dac_reg (reg,tor,togb)
1685 Bit8u reg;Bit16u *tor;Bit16u *togb;
1686 {Bit16u ss=get_SS();
1687 Bit8u r,g,b;
1689 outb(VGAREG_DAC_READ_ADDRESS,reg);
1690 r=inb(VGAREG_DAC_DATA);
1691 g=inb(VGAREG_DAC_DATA);
1692 b=inb(VGAREG_DAC_DATA);
1693 write_word(ss,tor,((Bit16u)r)<<8);
1694 write_word(ss,togb,(((Bit16u)g)<<8)+b);
1697 // --------------------------------------------------------------------------------------------
1698 static void biosfn_read_all_dac_reg (start,count,seg,offset)
1699 Bit16u start;Bit16u count;Bit16u seg;Bit16u offset;
1700 {Bit16u i;
1701 outb(VGAREG_DAC_READ_ADDRESS,start);
1702 for(i=0;i<count;i++)
1703 {write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1704 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1705 write_byte(seg,offset++,inb(VGAREG_DAC_DATA));
1709 // --------------------------------------------------------------------------------------------
1710 static void biosfn_set_pel_mask (mask)
1711 Bit8u mask;
1713 outb(VGAREG_PEL_MASK,mask);
1716 // --------------------------------------------------------------------------------------------
1717 static void biosfn_read_pel_mask (mask)
1718 Bit16u *mask;
1719 {Bit16u ss=get_SS();
1721 write_word(ss,mask,inb(VGAREG_PEL_MASK));
1724 // --------------------------------------------------------------------------------------------
1725 static void biosfn_read_video_dac_state (state) Bit16u *state;
1726 {Bit16u ss=get_SS();
1727 Bit8u mcr,csr;
1729 inb(VGAREG_ACTL_RESET);
1730 outb(VGAREG_ACTL_ADDRESS,0x10);
1731 mcr=(inb(VGAREG_ACTL_READ_DATA)>>7)&0x01;
1732 inb(VGAREG_ACTL_RESET);
1733 outb(VGAREG_ACTL_ADDRESS,0x14);
1734 csr=inb(VGAREG_ACTL_READ_DATA)&0x0f;
1735 if(mcr==0)(csr>>2)&0x03;
1737 write_word(ss,state,(mcr<<8)+csr);
1740 // --------------------------------------------------------------------------------------------
1741 static void biosfn_perform_gray_scale_summing (start,count)
1742 Bit16u start;Bit16u count;
1743 {Bit8u r,g,b,d;
1744 Bit16u i,m;
1745 Bit16u index;
1747 inb(VGAREG_ACTL_RESET);
1748 outb(VGAREG_ACTL_ADDRESS,0x10);
1749 d=(inb(VGAREG_ACTL_READ_DATA)>>6)&0x01;
1751 // depth is 8 or 6 bits
1752 if(d==0)m=0x3f;
1753 else m=0xff;
1756 // We start overwriting at
1757 outb(VGAREG_DAC_READ_ADDRESS,start);
1758 outb(VGAREG_DAC_WRITE_ADDRESS,start);
1760 for( index = 0; index < count; index++ )
1762 // get 6-bit wide RGB data values
1763 r=inb( VGAREG_DAC_DATA );
1764 g=inb( VGAREG_DAC_DATA );
1765 b=inb( VGAREG_DAC_DATA );
1767 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
1768 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
1770 if(i>m)i=m;
1772 // write new intensity value
1773 outb( VGAREG_DAC_DATA, i&0xff );
1774 outb( VGAREG_DAC_DATA, i&0xff );
1775 outb( VGAREG_DAC_DATA, i&0xff );
1779 // --------------------------------------------------------------------------------------------
1780 static void get_font_access()
1782 outw( VGAREG_SEQU_ADDRESS, 0x0100 );
1783 outw( VGAREG_SEQU_ADDRESS, 0x0402 );
1784 outw( VGAREG_SEQU_ADDRESS, 0x0704 );
1785 outw( VGAREG_SEQU_ADDRESS, 0x0300 );
1786 outw( VGAREG_GRDC_ADDRESS, 0x0204 );
1787 outw( VGAREG_GRDC_ADDRESS, 0x0005 );
1788 outw( VGAREG_GRDC_ADDRESS, 0x0406 );
1791 static void release_font_access()
1793 outw( VGAREG_SEQU_ADDRESS, 0x0100 );
1794 outw( VGAREG_SEQU_ADDRESS, 0x0302 );
1795 outw( VGAREG_SEQU_ADDRESS, 0x0304 );
1796 outw( VGAREG_SEQU_ADDRESS, 0x0300 );
1797 outw( VGAREG_GRDC_ADDRESS, 0x0004 );
1798 outw( VGAREG_GRDC_ADDRESS, 0x1005 );
1799 outw( VGAREG_GRDC_ADDRESS, 0x0e06 );
1802 ASM_START
1803 idiv_u:
1804 xor dx,dx
1805 div bx
1807 ASM_END
1809 static void set_scan_lines(lines) Bit8u lines;
1811 Bit16u cols,page,vde;
1812 Bit8u crtc9,ovl,rows;
1814 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS), 0x09);
1815 crtc9 = inb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1);
1816 crtc9 = (crtc9 & 0xe0) | (lines - 1);
1817 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1, crtc9);
1818 if(lines==8)
1820 biosfn_set_cursor_shape(0x06,0x07);
1822 else
1824 biosfn_set_cursor_shape(lines-4,lines-3);
1826 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
1827 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS), 0x12);
1828 vde = inb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1);
1829 outb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS), 0x07);
1830 ovl = inb(read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1);
1831 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
1832 rows = vde / lines;
1833 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
1834 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1835 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
1838 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;
1840 Bit16u blockaddr,dest,i,src;
1842 get_font_access();
1843 blockaddr = BL << 13;
1844 for(i=0;i<CX;i++)
1846 src = BP + i * BH;
1847 dest = blockaddr + (DX + i) * 32;
1848 memcpyb(0xA000, dest, ES, src, BH);
1850 release_font_access();
1851 if(AL>=0x10)
1853 set_scan_lines(BH);
1857 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
1859 Bit16u blockaddr,dest,i,src;
1861 get_font_access();
1862 blockaddr = BL << 13;
1863 for(i=0;i<0x100;i++)
1865 src = i * 14;
1866 dest = blockaddr + i * 32;
1867 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
1869 release_font_access();
1870 if(AL>=0x10)
1872 set_scan_lines(14);
1876 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
1878 Bit16u blockaddr,dest,i,src;
1880 get_font_access();
1881 blockaddr = BL << 13;
1882 for(i=0;i<0x100;i++)
1884 src = i * 8;
1885 dest = blockaddr + i * 32;
1886 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
1888 release_font_access();
1889 if(AL>=0x10)
1891 set_scan_lines(8);
1895 static void biosfn_set_text_block_specifier (BL) Bit8u BL;
1897 outb( VGAREG_SEQU_ADDRESS, 0x03 );
1898 outb( VGAREG_SEQU_DATA, BL );
1901 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
1903 Bit16u blockaddr,dest,i,src;
1905 get_font_access();
1906 blockaddr = BL << 13;
1907 for(i=0;i<0x100;i++)
1909 src = i * 16;
1910 dest = blockaddr + i * 32;
1911 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
1913 release_font_access();
1914 if(AL>=0x10)
1916 set_scan_lines(16);
1920 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
1922 #ifdef DEBUG
1923 unimplemented();
1924 #endif
1926 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
1928 #ifdef DEBUG
1929 unimplemented();
1930 #endif
1932 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
1934 #ifdef DEBUG
1935 unimplemented();
1936 #endif
1938 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
1940 #ifdef DEBUG
1941 unimplemented();
1942 #endif
1944 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
1946 #ifdef DEBUG
1947 unimplemented();
1948 #endif
1950 // --------------------------------------------------------------------------------------------
1951 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
1952 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
1953 {Bit16u ss=get_SS();
1955 switch(BH)
1956 {case 0x00:
1957 write_word(ss,ES,read_word(0x00,0x1f*4));
1958 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
1959 break;
1960 case 0x01:
1961 write_word(ss,ES,read_word(0x00,0x43*4));
1962 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
1963 break;
1964 case 0x02:
1965 write_word(ss,ES,0xC000);
1966 write_word(ss,BP,vgafont14);
1967 break;
1968 case 0x03:
1969 write_word(ss,ES,0xC000);
1970 write_word(ss,BP,vgafont8);
1971 break;
1972 case 0x04:
1973 write_word(ss,ES,0xC000);
1974 write_word(ss,BP,vgafont8+128*8);
1975 break;
1976 case 0x05:
1977 write_word(ss,ES,0xC000);
1978 write_word(ss,BP,vgafont14alt);
1979 break;
1980 case 0x06:
1981 write_word(ss,ES,0xC000);
1982 write_word(ss,BP,vgafont16);
1983 break;
1984 case 0x07:
1985 write_word(ss,ES,0xC000);
1986 write_word(ss,BP,vgafont16alt);
1987 break;
1988 default:
1989 #ifdef DEBUG
1990 printf("Get font info BH(%02x) was discarded\n",BH);
1991 #endif
1992 return;
1994 // Set byte/char of on screen font
1995 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
1997 // Set Highest char row
1998 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2001 // --------------------------------------------------------------------------------------------
2002 static void biosfn_get_ega_info (BX,CX)
2003 Bit16u *BX;Bit16u *CX;
2004 {Bit16u ss=get_SS();
2005 Bit16u crtc;
2006 Bit8u switches;
2008 crtc=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2009 if(crtc==VGAREG_MDA_CRTC_ADDRESS)
2010 write_word(ss,BX,(1<<8)+0x0003);
2011 else
2012 write_word(ss,BX,0x0003);
2014 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2015 write_word(ss,CX,(switches&0x0f));
2018 // --------------------------------------------------------------------------------------------
2019 static void biosfn_alternate_prtsc()
2021 #ifdef DEBUG
2022 unimplemented();
2023 #endif
2026 // --------------------------------------------------------------------------------------------
2027 static void biosfn_select_vert_res (res)
2028 Bit8u res;
2029 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2030 Bit8u modeset,switches;
2032 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2033 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2034 switch(res)
2035 {case 0x00:
2036 // set modeset ctl bit 7 and reset bit 4
2037 // set switches bit 3-0 to 0x08
2038 modeset|=0x80;modeset&=0xef;
2039 switches&=0xf0;switches|=0x08;
2040 break;
2041 case 0x01:
2042 // reset modeset ctl bit 7 and bit 4
2043 // set switches bit 3-0 to 0x09
2044 modeset&=0x6f;
2045 switches&=0xf0;switches|=0x09;
2046 break;
2047 case 0x02:
2048 // reset modeset ctl bit 7 and set bit 4
2049 // set switches bit 3-0 to 0x09
2050 modeset|=0x10;modeset&=0x7f;
2051 switches&=0xf0;switches|=0x09;
2052 break;
2053 default:
2054 #ifdef DEBUG
2055 printf("Select vert res (%02x) was discarded\n",res);
2056 #endif
2057 return;
2059 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2060 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2063 // --------------------------------------------------------------------------------------------
2064 static void biosfn_enable_default_palette_loading (disable)
2065 Bit8u disable;
2067 Bit8u modeset;
2069 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2071 // Bit 3
2072 if(disable!=0x00)modeset|=0x08;
2073 else modeset&=0xf7;
2075 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2078 // --------------------------------------------------------------------------------------------
2079 static void biosfn_enable_video_addressing (disable)
2080 Bit8u disable;
2082 Bit8u misc;
2084 misc=inb(VGAREG_READ_MISC_OUTPUT);
2085 // bit 1, 0 disable
2086 if(disable!=0x00) misc&=0xfd;
2087 else misc|=0x02;
2088 outb(VGAREG_WRITE_MISC_OUTPUT,misc);
2091 // --------------------------------------------------------------------------------------------
2092 static void biosfn_enable_grayscale_summing (disable)
2093 Bit8u disable;
2095 Bit8u modeset;
2097 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2099 // Bit 1 set if disable=0
2100 if(disable==0x00)modeset|=0x02;
2101 else modeset&=0xfd;
2103 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2106 // --------------------------------------------------------------------------------------------
2107 static void biosfn_enable_cursor_emulation (disable)
2108 Bit8u disable;
2110 Bit8u videoctl;
2112 videoctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
2114 // Bit 0 set if disable!=0
2115 if(disable!=0x00)videoctl|=0x01;
2116 else videoctl&=0xfe;
2118 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,videoctl);
2121 // --------------------------------------------------------------------------------------------
2122 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2124 #ifdef DEBUG
2125 unimplemented();
2126 #endif
2128 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2130 #ifdef DEBUG
2131 unimplemented();
2132 #endif
2135 // --------------------------------------------------------------------------------------------
2136 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2137 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2139 Bit16u newcurs,oldcurs,dummy;
2140 Bit8u car,carattr;
2142 // Read curs info for the page
2143 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2145 // if row=0xff special case : use current cursor position
2146 if(row==0xff)
2147 {col=oldcurs&0x00ff;
2148 row=(oldcurs&0xff00)>>8;
2151 newcurs=row; newcurs<<=8; newcurs+=col;
2152 biosfn_set_cursor_pos(page,newcurs);
2154 while(count--!=0)
2156 car=read_byte(seg,offset++);
2157 if((flag&0x02)!=0)
2158 attr=read_byte(seg,offset++);
2160 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2163 // Set back curs pos
2164 if((flag&0x01)==0)
2165 biosfn_set_cursor_pos(page,oldcurs);
2168 // --------------------------------------------------------------------------------------------
2169 static void biosfn_read_display_code (BX)
2170 Bit16u *BX;
2172 Bit16u ss=get_SS();
2173 write_word(ss,BX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2176 // --------------------------------------------------------------------------------------------
2177 static void biosfn_set_display_code (BL,BH)
2178 Bit8u BL;Bit8u BH;
2180 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,BL);
2182 #ifdef DEBUG
2183 printf("Alternate Display code (%02x) was discarded\n",BH);
2184 #endif
2187 // --------------------------------------------------------------------------------------------
2188 static void biosfn_read_state_info (BX,ES,DI)
2189 Bit16u BX;Bit16u ES;Bit16u DI;
2191 // Address of static functionality table
2192 write_word(ES,DI+0x00,&static_functionality);
2193 write_word(ES,DI+0x02,0xC000);
2195 // Hard coded copy from BIOS area. Should it be cleaner ?
2196 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2197 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2199 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2200 write_byte(ES,DI+0x26,0);
2201 write_byte(ES,DI+0x27,16);
2202 write_byte(ES,DI+0x28,0);
2203 write_byte(ES,DI+0x29,8);
2204 write_byte(ES,DI+0x2a,2);
2205 write_byte(ES,DI+0x2b,0);
2206 write_byte(ES,DI+0x2c,0);
2207 write_byte(ES,DI+0x31,3);
2208 write_byte(ES,DI+0x32,0);
2210 memsetb(ES,DI+0x33,0,13);
2213 // --------------------------------------------------------------------------------------------
2214 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2216 #ifdef DEBUG
2217 unimplemented();
2218 #endif
2220 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2222 #ifdef DEBUG
2223 unimplemented();
2224 #endif
2226 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2228 #ifdef DEBUG
2229 unimplemented();
2230 #endif
2233 // ============================================================================================
2235 // Video Utils
2237 // ============================================================================================
2239 // --------------------------------------------------------------------------------------------
2240 static Bit8u find_vga_entry(mode)
2241 Bit8u mode;
2243 Bit8u i,line=0xFF;
2244 for(i=0;i<=MODE_MAX;i++)
2245 if(vga_modes[i].svgamode==mode)
2246 {line=i;
2247 break;
2249 return line;
2252 /* =========================================================== */
2254 * Misc Utils
2256 /* =========================================================== */
2258 // --------------------------------------------------------------------------------------------
2259 static void memsetb(seg,offset,value,count)
2260 Bit16u seg;
2261 Bit16u offset;
2262 Bit16u value;
2263 Bit16u count;
2265 ASM_START
2266 push bp
2267 mov bp, sp
2269 push ax
2270 push cx
2271 push es
2272 push di
2274 mov cx, 10[bp] ; count
2275 cmp cx, #0x00
2276 je memsetb_end
2277 mov ax, 4[bp] ; segment
2278 mov es, ax
2279 mov ax, 6[bp] ; offset
2280 mov di, ax
2281 mov al, 8[bp] ; value
2284 stosb
2286 memsetb_end:
2287 pop di
2288 pop es
2289 pop cx
2290 pop ax
2292 pop bp
2293 ASM_END
2296 // --------------------------------------------------------------------------------------------
2297 static void memsetw(seg,offset,value,count)
2298 Bit16u seg;
2299 Bit16u offset;
2300 Bit16u value;
2301 Bit16u count;
2303 ASM_START
2304 push bp
2305 mov bp, sp
2307 push ax
2308 push cx
2309 push es
2310 push di
2312 mov cx, 10[bp] ; count
2313 cmp cx, #0x00
2314 je memsetw_end
2315 mov ax, 4[bp] ; segment
2316 mov es, ax
2317 mov ax, 6[bp] ; offset
2318 mov di, ax
2319 mov ax, 8[bp] ; value
2322 stosw
2324 memsetw_end:
2325 pop di
2326 pop es
2327 pop cx
2328 pop ax
2330 pop bp
2331 ASM_END
2334 // --------------------------------------------------------------------------------------------
2335 static void memcpyb(dseg,doffset,sseg,soffset,count)
2336 Bit16u dseg;
2337 Bit16u doffset;
2338 Bit16u sseg;
2339 Bit16u soffset;
2340 Bit16u count;
2342 ASM_START
2343 push bp
2344 mov bp, sp
2346 push ax
2347 push cx
2348 push es
2349 push di
2350 push ds
2351 push si
2353 mov cx, 12[bp] ; count
2354 cmp cx, #0x0000
2355 je memcpyb_end
2356 mov ax, 4[bp] ; dsegment
2357 mov es, ax
2358 mov ax, 6[bp] ; doffset
2359 mov di, ax
2360 mov ax, 8[bp] ; ssegment
2361 mov ds, ax
2362 mov ax, 10[bp] ; soffset
2363 mov si, ax
2366 movsb
2368 memcpyb_end:
2369 pop si
2370 pop ds
2371 pop di
2372 pop es
2373 pop cx
2374 pop ax
2376 pop bp
2377 ASM_END
2380 // --------------------------------------------------------------------------------------------
2381 static void memcpyw(dseg,doffset,sseg,soffset,count)
2382 Bit16u dseg;
2383 Bit16u doffset;
2384 Bit16u sseg;
2385 Bit16u soffset;
2386 Bit16u count;
2388 ASM_START
2389 push bp
2390 mov bp, sp
2392 push ax
2393 push cx
2394 push es
2395 push di
2396 push ds
2397 push si
2399 mov cx, 12[bp] ; count
2400 cmp cx, #0x0000
2401 je memcpyw_end
2402 mov ax, 4[bp] ; dsegment
2403 mov es, ax
2404 mov ax, 6[bp] ; doffset
2405 mov di, ax
2406 mov ax, 8[bp] ; ssegment
2407 mov ds, ax
2408 mov ax, 10[bp] ; soffset
2409 mov si, ax
2412 movsw
2414 memcpyw_end:
2415 pop si
2416 pop ds
2417 pop di
2418 pop es
2419 pop cx
2420 pop ax
2422 pop bp
2423 ASM_END
2426 /* =========================================================== */
2428 * These functions where ripped from Kevin's rombios.c
2430 /* =========================================================== */
2432 // --------------------------------------------------------------------------------------------
2433 static Bit8u
2434 read_byte(seg, offset)
2435 Bit16u seg;
2436 Bit16u offset;
2438 ASM_START
2439 push bp
2440 mov bp, sp
2442 push bx
2443 push ds
2444 mov ax, 4[bp] ; segment
2445 mov ds, ax
2446 mov bx, 6[bp] ; offset
2447 mov al, [bx]
2448 ;; al = return value (byte)
2449 pop ds
2450 pop bx
2452 pop bp
2453 ASM_END
2456 // --------------------------------------------------------------------------------------------
2457 static Bit16u
2458 read_word(seg, offset)
2459 Bit16u seg;
2460 Bit16u offset;
2462 ASM_START
2463 push bp
2464 mov bp, sp
2466 push bx
2467 push ds
2468 mov ax, 4[bp] ; segment
2469 mov ds, ax
2470 mov bx, 6[bp] ; offset
2471 mov ax, [bx]
2472 ;; ax = return value (word)
2473 pop ds
2474 pop bx
2476 pop bp
2477 ASM_END
2480 // --------------------------------------------------------------------------------------------
2481 static void
2482 write_byte(seg, offset, data)
2483 Bit16u seg;
2484 Bit16u offset;
2485 Bit8u data;
2487 ASM_START
2488 push bp
2489 mov bp, sp
2491 push ax
2492 push bx
2493 push ds
2494 mov ax, 4[bp] ; segment
2495 mov ds, ax
2496 mov bx, 6[bp] ; offset
2497 mov al, 8[bp] ; data byte
2498 mov [bx], al ; write data byte
2499 pop ds
2500 pop bx
2501 pop ax
2503 pop bp
2504 ASM_END
2507 // --------------------------------------------------------------------------------------------
2508 static void
2509 write_word(seg, offset, data)
2510 Bit16u seg;
2511 Bit16u offset;
2512 Bit16u data;
2514 ASM_START
2515 push bp
2516 mov bp, sp
2518 push ax
2519 push bx
2520 push ds
2521 mov ax, 4[bp] ; segment
2522 mov ds, ax
2523 mov bx, 6[bp] ; offset
2524 mov ax, 8[bp] ; data word
2525 mov [bx], ax ; write data word
2526 pop ds
2527 pop bx
2528 pop ax
2530 pop bp
2531 ASM_END
2534 // --------------------------------------------------------------------------------------------
2535 Bit8u
2536 inb(port)
2537 Bit16u port;
2539 ASM_START
2540 push bp
2541 mov bp, sp
2543 push dx
2544 mov dx, 4[bp]
2545 in al, dx
2546 pop dx
2548 pop bp
2549 ASM_END
2552 Bit16u
2553 inw(port)
2554 Bit16u port;
2556 ASM_START
2557 push bp
2558 mov bp, sp
2560 push dx
2561 mov dx, 4[bp]
2562 in ax, dx
2563 pop dx
2565 pop bp
2566 ASM_END
2569 // --------------------------------------------------------------------------------------------
2570 void
2571 outb(port, val)
2572 Bit16u port;
2573 Bit8u val;
2575 ASM_START
2576 push bp
2577 mov bp, sp
2579 push ax
2580 push dx
2581 mov dx, 4[bp]
2582 mov al, 6[bp]
2583 out dx, al
2584 pop dx
2585 pop ax
2587 pop bp
2588 ASM_END
2591 // --------------------------------------------------------------------------------------------
2592 void
2593 outw(port, val)
2594 Bit16u port;
2595 Bit16u val;
2597 ASM_START
2598 push bp
2599 mov bp, sp
2601 push ax
2602 push dx
2603 mov dx, 4[bp]
2604 mov ax, 6[bp]
2605 out dx, ax
2606 pop dx
2607 pop ax
2609 pop bp
2610 ASM_END
2613 Bit16u get_SS()
2615 ASM_START
2616 mov ax, ss
2617 ASM_END
2620 #ifdef DEBUG
2621 void unimplemented()
2623 printf("--> Unimplemented\n");
2626 void unknown()
2628 printf("--> Unknown int10\n");
2630 #endif
2632 // --------------------------------------------------------------------------------------------
2633 void printf(s)
2634 Bit8u *s;
2636 Bit8u c, format_char;
2637 Boolean in_format;
2638 unsigned format_width, i;
2639 Bit16u *arg_ptr;
2640 Bit16u arg_seg, arg, digit, nibble, shift_count;
2642 arg_ptr = &s;
2643 arg_seg = get_SS();
2645 in_format = 0;
2646 format_width = 0;
2648 while (c = read_byte(0xc000, s)) {
2649 if ( c == '%' ) {
2650 in_format = 1;
2651 format_width = 0;
2653 else if (in_format) {
2654 if ( (c>='0') && (c<='9') ) {
2655 format_width = (format_width * 10) + (c - '0');
2657 else if (c == 'x') {
2658 arg_ptr++; // increment to next arg
2659 arg = read_word(arg_seg, arg_ptr);
2660 if (format_width == 0)
2661 format_width = 4;
2662 i = 0;
2663 digit = format_width - 1;
2664 for (i=0; i<format_width; i++) {
2665 nibble = (arg >> (4 * digit)) & 0x000f;
2666 if (nibble <= 9)
2667 outb(0x0500, nibble + '0');
2668 else
2669 outb(0x0500, (nibble - 10) + 'A');
2670 digit--;
2672 in_format = 0;
2674 //else if (c == 'd') {
2675 // in_format = 0;
2676 // }
2678 else {
2679 outb(0x0500, c);
2681 s ++;
2685 #ifdef VBE
2686 #include "vbe.c"
2687 #endif
2689 // --------------------------------------------------------------------------------------------
2691 ASM_START
2692 ;; DATA_SEG_DEFS_HERE
2693 ASM_END
2695 ASM_START
2696 .ascii "vgabios ends here"
2697 .byte 0x00
2698 vgabios_end:
2699 .byte 0xCB
2700 ;; BLOCK_STRINGS_BEGIN
2701 ASM_END