- remaining palette and dac read/write functions (except gray scale summing)
[vgabios.git] / vgabios.c
blob636e9c940bb5c0720b967a6881c9a54fbc6f2af4
1 // ============================================================================================
2 /*
3 * vgabios.c
4 */
5 // ============================================================================================
6 //
7 // Copyright (C) 2001,2002 the LGPL VGABios developers Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // ============================================================================================
24 //
25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26 // You can NOT drive any physical vga card with it.
27 //
28 // ============================================================================================
29 //
30 // This file contains code ripped from :
31 // - rombios.c of plex86
33 // This VGA Bios contains fonts from :
34 // - fntcol16.zip (c) by Joseph Gil avalable at :
35 // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
36 // These fonts are public domain
38 // This VGA Bios is based on information taken from :
39 // - Kevin Lawton's vga card emulation for bochs/plex86
40 // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
41 // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
42 // - Michael Abrash's Graphics Programming Black Book
43 // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
44 // - DOSEMU 1.0.1 source code for several tables values and formulas
46 // Thanks for patches, comments and ideas to :
47 // - techt@pikeonline.net
49 // ============================================================================================
51 #include "vgabios.h"
53 #ifdef VBE
54 #include "vbe.h"
55 #endif
57 /* Declares */
58 static Bit8u read_byte();
59 static Bit16u read_word();
60 static void write_byte();
61 static void write_word();
62 static Bit8u inb();
63 static Bit16u inw();
64 static void outb();
65 static void outw();
67 static Bit16u get_SS();
69 // Output
70 static void printf();
71 static void unimplemented();
72 static void unknown();
74 static Bit8u find_vga_entry();
76 static void memsetb();
77 static void memsetw();
78 static void memcpyb();
79 static void memcpyw();
81 static void biosfn_set_video_mode();
82 static void biosfn_set_cursor_shape();
83 static void biosfn_set_cursor_pos();
84 static void biosfn_get_cursor_pos();
85 static void biosfn_set_active_page();
86 static void biosfn_scroll();
87 static void biosfn_read_char_attr();
88 static void biosfn_write_char_attr();
89 static void biosfn_write_char_only();
90 static void biosfn_set_border_color();
91 static void biosfn_set_palette();
92 static void biosfn_write_pixel();
93 static void biosfn_read_pixel();
94 static void biosfn_write_teletype();
95 static void biosfn_perform_gray_scale_summing();
96 static void biosfn_load_text_user_pat();
97 static void biosfn_load_text_8_14_pat();
98 static void biosfn_load_text_8_8_pat();
99 static void biosfn_set_text_block_specifier();
100 static void biosfn_load_text_8_16_pat();
101 static void biosfn_load_gfx_8_8_chars();
102 static void biosfn_load_gfx_user_chars();
103 static void biosfn_load_gfx_8_14_chars();
104 static void biosfn_load_gfx_8_8_dd_chars();
105 static void biosfn_load_gfx_8_16_chars();
106 static void biosfn_get_font_info();
107 static void biosfn_get_ega_info();
108 static void biosfn_alternate_prtsc();
109 static void biosfn_select_vert_res();
110 static void biosfn_enable_default_palette_loading();
111 static void biosfn_enable_video_addressing();
112 static void biosfn_enable_grayscale_summing();
113 static void biosfn_enable_cursor_emulation();
114 static void biosfn_switch_video_interface();
115 static void biosfn_enable_video_refresh_control();
116 static void biosfn_write_string();
117 static void biosfn_read_state_info();
118 static void biosfn_read_video_state_size();
119 static void biosfn_save_video_state();
120 static void biosfn_restore_video_state();
122 // This is for compiling with gcc2 and gcc3
123 #define ASM_START #asm
124 #define ASM_END #endasm
126 ASM_START
128 biosmem_seg = 0x40
129 biosmem_initial_mode = 0x10
130 biosmem_current_mode = 0x49
131 biosmem_nb_cols = 0x4a
132 biosmem_current_page = 0x62
133 biosmem_current_msr = 0x65
134 biosmem_char_height = 0x85
135 biosmem_video_ctl = 0x87
136 biosmem_switches = 0x88
137 biosmem_modeset_ctl = 0x89
138 biosmem_dcc_index = 0x8a
140 vgareg_actl_address = 0x03c0
141 vgareg_actl_read_data = 0x03c1
142 vgareg_sequ_address = 0x03c4
143 vgareg_pel_mask = 0x03c6
144 vgareg_dac_read_address = 0x03c7
145 vgareg_dac_write_address = 0x03c8
146 vgareg_dac_data = 0x03c9
147 vgareg_grdc_address = 0x03ce
148 vgareg_actl_reset = 0x03da
150 MACRO SET_INT_VECTOR
151 push ds
152 xor ax, ax
153 mov ds, ax
154 mov ax, ?3
155 mov ?1*4, ax
156 mov ax, ?2
157 mov ?1*4+2, ax
158 pop ds
159 MEND
161 ASM_END
163 ASM_START
164 .text
165 .rom
166 .org 0
168 use16 386
170 vgabios_start:
171 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
173 .byte 0x40 /* BIOS extension length in units of 512 bytes */
176 vgabios_entry_point:
178 jmp vgabios_init_func
180 vgabios_name:
181 .ascii "Plex86/Bochs VGABios"
182 .ascii " "
183 .byte 0x00
185 // Info from Bart Oldeman
186 .org 0x1e
187 .ascii "IBM"
188 .byte 0x00
190 vgabios_version:
191 #ifndef VGABIOS_VERS
192 .ascii "current-cvs"
193 #else
194 .ascii VGABIOS_VERS
195 #endif
196 .ascii " "
198 vgabios_date:
199 .ascii VGABIOS_DATE
200 .byte 0x0a,0x0d
201 .byte 0x00
203 vgabios_copyright:
204 .ascii "(C) 2003 the LGPL VGABios developers Team"
205 .byte 0x0a,0x0d
206 .byte 0x00
208 vgabios_license:
209 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
210 .byte 0x0a,0x0d
211 .byte 0x0a,0x0d
212 .byte 0x00
214 vgabios_website:
215 .ascii "Please visit :"
216 .byte 0x0a,0x0d
217 ;;.ascii " . http://www.plex86.org"
218 ;;.byte 0x0a,0x0d
219 .ascii " . http://bochs.sourceforge.net"
220 .byte 0x0a,0x0d
221 .ascii " . http://www.nongnu.org/vgabios"
222 .byte 0x0a,0x0d
223 .byte 0x0a,0x0d
224 .byte 0x00
227 ;; ============================================================================================
229 ;; Init Entry point
231 ;; ============================================================================================
232 vgabios_init_func:
234 ;; init vga card
235 call init_vga_card
237 ;; init basic bios vars
238 call init_bios_area
240 #ifdef VBE
241 ;; init vbe functions
242 call _vbe_init
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 ;; show info
256 call _display_info
258 #ifdef VBE
259 ;; show vbe info
260 call _vbe_display_info
261 #endif
264 retf
265 ASM_END
268 * int10 handled here
270 ASM_START
271 vgabios_int10_handler:
272 pushf
273 #ifdef DEBUG
274 push es
275 push ds
276 pusha
277 mov bx, #0xc000
278 mov ds, bx
279 call _int10_debugmsg
280 popa
281 pop ds
282 pop es
283 #endif
284 cmp ah, #0x0f
285 jne int10_test_1A
286 call biosfn_get_video_mode
287 jmp int10_end
288 int10_test_1A:
289 cmp ah, #0x1a
290 jne int10_test_101B
291 call biosfn_group_1A
292 jmp int10_end
293 int10_test_101B:
294 cmp ax, #0x101b
295 je int10_normal
296 cmp ah, #0x10
297 jne int10_normal
298 call biosfn_group_10
299 jmp int10_end
301 int10_normal:
302 push es
303 push ds
304 pusha
306 ;; We have to set ds to access the right data segment
307 mov bx, #0xc000
308 mov ds, bx
309 call _int10_func
311 popa
312 pop ds
313 pop es
314 int10_end:
315 popf
316 iret
317 ASM_END
319 #include "vgatables.h"
320 #include "vgafonts.h"
323 * Boot time harware inits
325 ASM_START
326 init_vga_card:
327 ;; switch to color mode and enable CPU access 480 lines
328 mov dx, #0x3C2
329 mov al, #0xC3
330 outb dx,al
332 ;; more than 64k 3C4/04
333 mov dx, #0x3C4
334 mov al, #0x04
335 outb dx,al
336 mov dx, #0x3C5
337 mov al, #0x02
338 outb dx,al
340 mov bx, #msg_vga_init
341 push bx
342 call _printf
343 inc sp
344 inc sp
347 msg_vga_init:
348 .ascii "VGABios $Id$"
349 .byte 0x0d,0x0a,0x00
350 ASM_END
352 // --------------------------------------------------------------------------------------------
354 * Boot time bios area inits
356 ASM_START
357 init_bios_area:
358 push ds
359 mov ax, #biosmem_seg
360 mov ds, ax
362 ;; init detected hardware BIOS Area
363 mov bx, #biosmem_initial_mode
364 mov ax, [bx]
365 and ax, #0xffcf
366 mov [bx], ax
368 ;; Just for the first int10 find its children
370 ;; the default char height
371 mov bx, #biosmem_char_height
372 mov al, #0x10
373 mov [bx], al
375 ;; Clear the screen
376 mov bx, #biosmem_video_ctl
377 mov al, #0x60
378 mov [bx], al
380 ;; Set the basic screen we have
381 mov bx, #biosmem_switches
382 mov al, #0xf9
383 mov [bx], al
385 ;; Set the basic modeset options
386 mov bx, #biosmem_modeset_ctl
387 mov al, #0x51
388 mov [bx], al
390 ;; Set the default MSR
391 mov bx, #biosmem_current_msr
392 mov al, #0x09
393 mov [bx], al
395 pop ds
397 ASM_END
399 // --------------------------------------------------------------------------------------------
401 * Boot time Splash screen
403 static void display_splash_screen()
407 // --------------------------------------------------------------------------------------------
409 * Tell who we are
412 static void display_info()
414 ASM_START
415 mov ax,#0xc000
416 mov ds,ax
417 mov si,#vgabios_name
418 call _display_string
419 mov si,#vgabios_version
420 call _display_string
422 ;;mov si,#vgabios_copyright
423 ;;call _display_string
424 ;;mov si,#crlf
425 ;;call _display_string
427 mov si,#vgabios_license
428 call _display_string
429 mov si,#vgabios_website
430 call _display_string
431 ASM_END
434 static void display_string()
436 // Get length of string
437 ASM_START
438 mov ax,ds
439 mov es,ax
440 mov di,si
441 xor cx,cx
442 not cx
443 xor al,al
445 repne
446 scasb
447 not cx
448 dec cx
449 push cx
451 mov ax,#0x0300
452 mov bx,#0x0000
453 int #0x10
455 pop cx
456 mov ax,#0x1301
457 mov bx,#0x000b
458 mov bp,si
459 int #0x10
460 ASM_END
463 // --------------------------------------------------------------------------------------------
464 #ifdef DEBUG
465 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
466 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
468 // 0E is write char...
469 if(GET_AH()!=0x0E)
470 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
472 #endif
474 // --------------------------------------------------------------------------------------------
476 * int10 main dispatcher
478 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
479 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
482 // BIOS functions
483 switch(GET_AH())
485 case 0x00:
486 biosfn_set_video_mode(GET_AL());
487 switch(GET_AL()&0x7F)
488 {case 6:
489 SET_AL(0x3F);
490 break;
491 case 0:
492 case 1:
493 case 2:
494 case 3:
495 case 4:
496 case 5:
497 case 7:
498 SET_AL(0x30);
499 break;
500 default:
501 SET_AL(0x20);
503 break;
504 case 0x01:
505 biosfn_set_cursor_shape(GET_CH(),GET_CL());
506 break;
507 case 0x02:
508 biosfn_set_cursor_pos(GET_BH(),DX);
509 break;
510 case 0x03:
511 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
512 break;
513 case 0x04:
514 // Read light pen pos (unimplemented)
515 #ifdef DEBUG
516 unimplemented();
517 #endif
518 AX=0x00;
519 BX=0x00;
520 CX=0x00;
521 DX=0x00;
522 break;
523 case 0x05:
524 biosfn_set_active_page(GET_AL());
525 break;
526 case 0x06:
527 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
528 break;
529 case 0x07:
530 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
531 break;
532 case 0x08:
533 biosfn_read_char_attr(GET_BH(),&AX);
534 break;
535 case 0x09:
536 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
537 break;
538 case 0x0A:
539 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
540 break;
541 case 0x0B:
542 if(GET_BH()==0x00)
543 biosfn_set_border_color(GET_BL());
544 else
545 biosfn_set_palette(GET_BL());
546 break;
547 case 0x0C:
548 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
549 break;
550 case 0x0D:
551 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
552 break;
553 case 0x0E:
554 // Ralf Brown Interrupt list is WRONG on bh(page)
555 // We do output only on the current page !
556 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
557 break;
558 case 0x10:
559 // All other functions of group AH=0x10 rewritten in assembler
560 biosfn_perform_gray_scale_summing(BX,CX);
561 break;
562 case 0x11:
563 switch(GET_AL())
565 case 0x00:
566 case 0x10:
567 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
568 break;
569 case 0x01:
570 case 0x11:
571 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
572 break;
573 case 0x02:
574 case 0x12:
575 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
576 break;
577 case 0x03:
578 biosfn_set_text_block_specifier(GET_BL());
579 break;
580 case 0x04:
581 case 0x14:
582 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
583 break;
584 case 0x20:
585 biosfn_load_gfx_8_8_chars(ES,BP);
586 break;
587 case 0x21:
588 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
589 break;
590 case 0x22:
591 biosfn_load_gfx_8_14_chars(GET_BL());
592 break;
593 case 0x23:
594 biosfn_load_gfx_8_8_dd_chars(GET_BL());
595 break;
596 case 0x24:
597 biosfn_load_gfx_8_16_chars(GET_BL());
598 break;
599 case 0x30:
600 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
601 break;
602 #ifdef DEBUG
603 default:
604 unknown();
605 #endif
608 break;
609 case 0x12:
610 switch(GET_BL())
612 case 0x10:
613 biosfn_get_ega_info(&BX,&CX);
614 break;
615 case 0x20:
616 biosfn_alternate_prtsc();
617 break;
618 case 0x30:
619 biosfn_select_vert_res(GET_AL());
620 SET_AL(0x12);
621 break;
622 case 0x31:
623 biosfn_enable_default_palette_loading(GET_AL());
624 SET_AL(0x12);
625 break;
626 case 0x32:
627 biosfn_enable_video_addressing(GET_AL());
628 SET_AL(0x12);
629 break;
630 case 0x33:
631 biosfn_enable_grayscale_summing(GET_AL());
632 SET_AL(0x12);
633 break;
634 case 0x34:
635 biosfn_enable_cursor_emulation(GET_AL());
636 SET_AL(0x12);
637 break;
638 case 0x35:
639 biosfn_switch_video_interface(GET_AL(),ES,DX);
640 SET_AL(0x12);
641 break;
642 case 0x36:
643 biosfn_enable_video_refresh_control(GET_AL());
644 SET_AL(0x12);
645 break;
646 #ifdef DEBUG
647 default:
648 unknown();
649 #endif
651 break;
652 case 0x13:
653 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
654 break;
655 case 0x1B:
656 biosfn_read_state_info(BX,ES,DI);
657 SET_AL(0x1B);
658 break;
659 case 0x1C:
660 switch(GET_AL())
662 case 0x00:
663 biosfn_read_video_state_size(CX,&BX);
664 break;
665 case 0x01:
666 biosfn_save_video_state(CX,ES,BX);
667 break;
668 case 0x02:
669 biosfn_restore_video_state(CX,ES,BX);
670 break;
671 #ifdef DEBUG
672 default:
673 unknown();
674 #endif
676 SET_AL(0x1C);
677 break;
679 #ifdef VBE
680 case 0x4f:
681 if (vbe_has_vbe_display()) {
682 switch(GET_AL())
684 case 0x00:
685 vbe_biosfn_return_controller_information(&AX,ES,DI);
686 break;
687 case 0x01:
688 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
689 break;
690 case 0x02:
691 vbe_biosfn_set_mode(&AX,BX,ES,DI);
692 break;
693 case 0x03:
694 vbe_biosfn_return_current_mode(&AX,&BX);
695 break;
696 case 0x04:
697 //FIXME
698 #ifdef DEBUG
699 unimplemented();
700 #endif
701 // function failed
702 AX=0x100;
703 break;
704 case 0x05:
705 vbe_biosfn_display_window_control(&AX,BX,&DX);
706 break;
707 case 0x06:
708 vbe_biosfn_set_get_logical_scan_line_length(&AX,&BX,&CX,&DX);
709 break;
710 case 0x07:
711 vbe_biosfn_set_get_display_start(&AX,BX,CX,DX);
712 break;
713 case 0x08:
714 //FIXME
715 #ifdef DEBUG
716 unimplemented();
717 #endif
718 // function failed
719 AX=0x100;
720 break;
721 case 0x09:
722 //FIXME
723 #ifdef DEBUG
724 unimplemented();
725 #endif
726 // function failed
727 AX=0x100;
728 break;
729 case 0x0A:
730 //FIXME
731 #ifdef DEBUG
732 unimplemented();
733 #endif
734 // function failed
735 AX=0x100;
736 break;
737 #ifdef DEBUG
738 default:
739 unknown();
740 #endif
741 // function failed
742 AX=0x100;
745 else {
746 // No VBE display
747 AX=0x0100;
749 break;
750 #endif
752 #ifdef DEBUG
753 default:
754 unknown();
755 #endif
759 // ============================================================================================
761 // BIOS functions
763 // ============================================================================================
765 static void biosfn_set_video_mode(mode) Bit8u mode;
766 {// mode: Bit 7 is 1 if no clear screen
768 // Should we clear the screen ?
769 Bit8u noclearmem=mode&0x80;
770 Bit8u line,mmask,*palette;
771 Bit16u i,twidth,theight,cheight;
772 Bit8u modeset_ctl,video_ctl,vga_switches;
773 Bit16u crtc_addr;
775 #ifdef VBE
776 if (vbe_has_vbe_display()) {
777 dispi_set_enable(VBE_DISPI_DISABLED);
779 #endif // def VBE
781 // The real mode
782 mode=mode&0x7f;
784 // find the entry in the video modes
785 line=find_vga_entry(mode);
787 #ifdef DEBUG
788 printf("mode search %02x found line %02x\n",mode,line);
789 #endif
791 if(line==0xFF)
792 return;
794 twidth=vga_modes[line].twidth;
795 theight=vga_modes[line].theight;
796 cheight=vga_modes[line].cheight;
798 // Read the bios vga control
799 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
801 // Read the bios vga switches
802 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
804 // Read the bios mode set control
805 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
807 // Then we know the number of lines
808 // FIXME
810 // if palette loading (bit 3 of modeset ctl = 0)
811 if((modeset_ctl&0x08)==0)
812 {// Set the PEL mask
813 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
815 // Set the whole dac always, from 0
816 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
818 // From which palette
819 switch(vga_modes[line].dacmodel)
820 {case 0:
821 palette=&palette0;
822 break;
823 case 1:
824 palette=&palette1;
825 break;
826 case 2:
827 palette=&palette2;
828 break;
829 case 3:
830 palette=&palette3;
831 break;
833 // Always 256*3 values
834 for(i=0;i<0x0100;i++)
835 {if(i<=dac_regs[vga_modes[line].dacmodel])
836 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
837 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
838 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
840 else
841 {outb(VGAREG_DAC_DATA,0);
842 outb(VGAREG_DAC_DATA,0);
843 outb(VGAREG_DAC_DATA,0);
846 if((modeset_ctl&0x02)==0x02)
848 biosfn_perform_gray_scale_summing(0x00, 0x100);
852 // Reset Attribute Ctl flip-flop
853 inb(VGAREG_ACTL_RESET);
855 // Set Attribute Ctl
856 for(i=0;i<=ACTL_MAX_REG;i++)
857 {outb(VGAREG_ACTL_ADDRESS,i);
858 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
861 // Set Sequencer Ctl
862 for(i=0;i<=SEQU_MAX_REG;i++)
863 {outb(VGAREG_SEQU_ADDRESS,i);
864 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
867 // Set Grafx Ctl
868 for(i=0;i<=GRDC_MAX_REG;i++)
869 {outb(VGAREG_GRDC_ADDRESS,i);
870 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
873 // Set CRTC address VGA or MDA
874 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
876 // Set CRTC regs
877 for(i=0;i<=CRTC_MAX_REG;i++)
878 {outb(crtc_addr,i);
879 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
882 // Set the misc register
883 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
885 // Enable video
886 outb(VGAREG_ACTL_ADDRESS,0x20);
887 inb(VGAREG_ACTL_RESET);
889 if(noclearmem==0x00)
891 if(vga_modes[line].class==TEXT)
893 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
895 else
897 if(mode<0x0d)
899 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
901 else
903 outb( VGAREG_SEQU_ADDRESS, 0x02 );
904 mmask = inb( VGAREG_SEQU_DATA );
905 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
906 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
907 outb( VGAREG_SEQU_DATA, mmask );
912 // Set the BIOS mem
913 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
914 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
915 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
916 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
917 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
918 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
919 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
920 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
921 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
923 // FIXME We nearly have the good tables. to be reworked
924 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
925 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
926 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
928 // FIXME
929 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
930 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
932 // Set cursor shape
933 if(vga_modes[line].class==TEXT)
935 biosfn_set_cursor_shape(0x06,0x07);
938 // Set cursor pos for page 0..7
939 for(i=0;i<8;i++)
940 biosfn_set_cursor_pos(i,0x0000);
942 // Set active page 0
943 biosfn_set_active_page(0x00);
945 // Write the fonts in memory
946 if(vga_modes[line].class==TEXT)
948 ASM_START
949 ;; copy and activate 8x16 font
950 mov ax, #0x1104
951 mov bl, #0x00
952 int #0x10
953 mov ax, #0x1103
954 mov bl, #0x00
955 int #0x10
956 ASM_END
959 // Set the ints 0x1F and 0x43
960 ASM_START
961 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
962 ASM_END
964 switch(cheight)
965 {case 8:
966 ASM_START
967 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
968 ASM_END
969 break;
970 case 14:
971 ASM_START
972 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
973 ASM_END
974 break;
975 case 16:
976 ASM_START
977 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
978 ASM_END
979 break;
983 // --------------------------------------------------------------------------------------------
984 static void biosfn_set_cursor_shape (CH,CL)
985 Bit8u CH;Bit8u CL;
986 {Bit16u cheight,curs,crtc_addr;
988 CH&=0x3f;
989 CL&=0x1f;
991 curs=(CH<<8)+CL;
992 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
994 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
995 if((cheight>8) && (CL<8) && (CH<0x20))
997 if(CL!=(CH+1))
999 CH = ((CH+1) * cheight / 8) -1;
1001 else
1003 CH = ((CL+1) * cheight / 8) - 2;
1005 CL = ((CL+1) * cheight / 8) - 1;
1008 // CTRC regs 0x0a and 0x0b
1009 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1010 outb(crtc_addr,0x0a);
1011 outb(crtc_addr+1,CH);
1012 outb(crtc_addr,0x0b);
1013 outb(crtc_addr+1,CL);
1016 // --------------------------------------------------------------------------------------------
1017 static void biosfn_set_cursor_pos (page, cursor)
1018 Bit8u page;Bit16u cursor;
1020 Bit8u xcurs,ycurs,current;
1021 Bit16u nbcols,nbrows,address,crtc_addr;
1023 // Should not happen...
1024 if(page>7)return;
1026 // Bios cursor pos
1027 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1029 // Set the hardware cursor
1030 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1031 if(page==current)
1033 // Get the dimensions
1034 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1035 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1037 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1039 // Calculate the address knowing nbcols nbrows and page num
1040 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1042 // CRTC regs 0x0e and 0x0f
1043 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1044 outb(crtc_addr,0x0e);
1045 outb(crtc_addr+1,(address&0xff00)>>8);
1046 outb(crtc_addr,0x0f);
1047 outb(crtc_addr+1,address&0x00ff);
1051 // --------------------------------------------------------------------------------------------
1052 static void biosfn_get_cursor_pos (page,shape, pos)
1053 Bit8u page;Bit16u *shape;Bit16u *pos;
1055 Bit16u ss=get_SS();
1057 // Default
1058 write_word(ss, shape, 0);
1059 write_word(ss, pos, 0);
1061 if(page>7)return;
1062 // FIXME should handle VGA 14/16 lines
1063 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1064 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1067 // --------------------------------------------------------------------------------------------
1068 static void biosfn_set_active_page (page)
1069 Bit8u page;
1071 Bit16u cursor,dummy,crtc_addr;
1072 Bit16u nbcols,nbrows,address;
1073 Bit8u mode,line;
1075 if(page>7)return;
1077 // Get the mode
1078 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1079 line=find_vga_entry(mode);
1080 if(line==0xFF)return;
1082 // Get pos curs pos for the right page
1083 biosfn_get_cursor_pos(page,&dummy,&cursor);
1085 if(vga_modes[line].class==TEXT)
1087 // Get the dimensions
1088 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1089 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1091 // Calculate the address knowing nbcols nbrows and page num
1092 address=SCREEN_MEM_START(nbcols,nbrows,page);
1093 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1095 // Start address
1096 address=SCREEN_IO_START(nbcols,nbrows,page);
1098 else
1100 address = page*vga_modes[line].slength;
1103 // CRTC regs 0x0c and 0x0d
1104 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1105 outb(crtc_addr,0x0c);
1106 outb(crtc_addr+1,(address&0xff00)>>8);
1107 outb(crtc_addr,0x0d);
1108 outb(crtc_addr+1,address&0x00ff);
1110 // And change the BIOS page
1111 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1113 #ifdef DEBUG
1114 printf("Set active page %02x address %04x\n",page,address);
1115 #endif
1117 // Display the cursor, now the page is active
1118 biosfn_set_cursor_pos(page,cursor);
1121 // --------------------------------------------------------------------------------------------
1122 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1123 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1125 // page == 0xFF if current
1127 Bit8u mode,line;
1128 Bit16u nbcols,nbrows,i;
1129 Bit16u address;
1131 if(rul>rlr)return;
1132 if(cul>clr)return;
1134 // Get the mode
1135 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1136 line=find_vga_entry(mode);
1137 if(line==0xFF)return;
1139 // Get the dimensions
1140 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1141 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1143 // Get the current page
1144 if(page==0xFF)
1145 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1147 if(vga_modes[line].class==TEXT)
1149 // Compute the address
1150 address=SCREEN_MEM_START(nbcols,nbrows,page);
1151 #ifdef DEBUG
1152 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1153 #endif
1155 if(rlr>=nbrows)rlr=nbrows-1;
1156 if(clr>=nbcols)clr=nbcols-1;
1157 if(nblines>nbrows)nblines=0;
1159 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1161 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1163 else
1164 {// if Scroll up
1165 if(dir==SCROLL_UP)
1166 {for(i=rul;i<=rlr;i++)
1168 if((i+nblines>rlr)||(nblines==0))
1169 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1170 else
1171 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,clr-cul+1);
1174 else
1175 {for(i=rlr;i>=rul;i--)
1177 if((i<rul+nblines)||(nblines==0))
1178 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1179 else
1180 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,clr-cul+1);
1185 else
1187 // FIXME gfx mode
1188 #ifdef DEBUG
1189 printf("Scroll in graphics mode ");
1190 unimplemented();
1191 #endif
1195 // --------------------------------------------------------------------------------------------
1196 static void biosfn_read_char_attr (page,car)
1197 Bit8u page;Bit16u *car;
1198 {Bit16u ss=get_SS();
1199 Bit8u xcurs,ycurs,mode,line;
1200 Bit16u nbcols,nbrows,address;
1201 Bit16u cursor,dummy;
1203 // Get the mode
1204 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1205 line=find_vga_entry(mode);
1206 if(line==0xFF)return;
1208 // Get the cursor pos for the page
1209 biosfn_get_cursor_pos(page,&dummy,&cursor);
1210 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1212 // Get the dimensions
1213 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1214 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1216 if(vga_modes[line].class==TEXT)
1218 // Compute the address
1219 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1221 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1223 else
1225 // FIXME gfx mode
1226 #ifdef DEBUG
1227 unimplemented();
1228 #endif
1232 // --------------------------------------------------------------------------------------------
1233 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1234 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1236 Bit8u i,mmask;
1237 Bit8u *fdata;
1238 Bit16u addr,dest,src;
1240 switch(cheight)
1241 {case 14:
1242 fdata = &vgafont14;
1243 break;
1244 case 16:
1245 fdata = &vgafont16;
1246 break;
1247 default:
1248 fdata = &vgafont8;
1250 addr=xcurs+ycurs*cheight*nbcols;
1251 src = car * cheight;
1252 outb( VGAREG_SEQU_ADDRESS, 0x02 );
1253 mmask = inb( VGAREG_SEQU_DATA );
1254 for(i=0;i<cheight;i++)
1256 dest=addr+i*nbcols;
1257 outb( VGAREG_SEQU_DATA, 0x0f );
1258 write_byte(0xa000,dest,0x00);
1259 outb( VGAREG_SEQU_DATA, attr & 0x0f );
1260 write_byte(0xa000,dest,fdata[src+i]);
1262 outb( VGAREG_SEQU_DATA, mmask );
1265 // --------------------------------------------------------------------------------------------
1266 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1267 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1269 Bit8u i,j,mask,data;
1270 Bit8u *fdata;
1271 Bit16u addr,dest,src;
1273 fdata = &vgafont8;
1274 addr=(xcurs*bpp)+ycurs*320;
1275 src = car * 8;
1276 for(i=0;i<8;i++)
1278 dest=addr+(i>>1)*80;
1279 if (i & 1) dest += 0x2000;
1280 mask = 0x80;
1281 if (bpp == 1)
1283 if (attr & 0x80)
1285 data = read_byte(0xb800,dest);
1287 else
1289 data = 0x00;
1291 for(j=0;j<8;j++)
1293 if (fdata[src+i] & mask)
1295 if (attr & 0x80)
1297 data ^= (attr & 0x01) << (7-j);
1299 else
1301 data |= (attr & 0x01) << (7-j);
1304 mask >>= 1;
1306 write_byte(0xb800,dest,data);
1308 else
1310 while (mask > 0)
1312 if (attr & 0x80)
1314 data = read_byte(0xb800,dest);
1316 else
1318 data = 0x00;
1320 for(j=0;j<4;j++)
1322 if (fdata[src+i] & mask)
1324 if (attr & 0x80)
1326 data ^= (attr & 0x03) << ((3-j)*2);
1328 else
1330 data |= (attr & 0x03) << ((3-j)*2);
1333 mask >>= 1;
1335 write_byte(0xb800,dest,data);
1336 dest += 1;
1342 // --------------------------------------------------------------------------------------------
1343 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1344 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1346 Bit8u i,j,mask,data;
1347 Bit8u *fdata;
1348 Bit16u addr,dest,src;
1350 fdata = &vgafont8;
1351 addr=xcurs*8+ycurs*nbcols*64;
1352 src = car * 8;
1353 for(i=0;i<8;i++)
1355 dest=addr+i*nbcols*8;
1356 mask = 0x80;
1357 for(j=0;j<8;j++)
1359 data = 0x00;
1360 if (fdata[src+i] & mask)
1362 data = attr;
1364 write_byte(0xa000,dest+j,data);
1365 mask >>= 1;
1370 // --------------------------------------------------------------------------------------------
1371 static void biosfn_write_char_attr (car,page,attr,count)
1372 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1374 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1375 Bit16u nbcols,nbrows,address;
1376 Bit16u cursor,dummy;
1378 // Get the mode
1379 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1380 line=find_vga_entry(mode);
1381 if(line==0xFF)return;
1383 // Get the cursor pos for the page
1384 biosfn_get_cursor_pos(page,&dummy,&cursor);
1385 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1387 // Get the dimensions
1388 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1389 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1391 if(vga_modes[line].class==TEXT)
1393 // Compute the address
1394 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1396 dummy=((Bit16u)attr<<8)+car;
1397 memsetw(vga_modes[line].sstart,address,dummy,count);
1399 else
1401 // FIXME gfx mode not complete
1402 cheight=vga_modes[line].cheight;
1403 bpp=vga_modes[line].pixbits;
1404 while((count-->0) && (xcurs<nbcols))
1406 if(vga_modes[line].memmodel==PLANAR4)
1408 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1410 else if(vga_modes[line].memmodel==CGA)
1412 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1414 else if(vga_modes[line].memmodel==LINEAR8)
1416 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1418 else
1420 #ifdef DEBUG
1421 unimplemented();
1422 #endif
1424 xcurs++;
1429 // --------------------------------------------------------------------------------------------
1430 static void biosfn_write_char_only (car,page,attr,count)
1431 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1433 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1434 Bit16u nbcols,nbrows,address;
1435 Bit16u cursor,dummy;
1437 // Get the mode
1438 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1439 line=find_vga_entry(mode);
1440 if(line==0xFF)return;
1442 // Get the cursor pos for the page
1443 biosfn_get_cursor_pos(page,&dummy,&cursor);
1444 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1446 // Get the dimensions
1447 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1448 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1450 if(vga_modes[line].class==TEXT)
1452 // Compute the address
1453 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1455 while(count-->0)
1456 {write_byte(vga_modes[line].sstart,address,car);
1457 address+=2;
1460 else
1462 // FIXME gfx mode not complete
1463 cheight=vga_modes[line].cheight;
1464 bpp=vga_modes[line].pixbits;
1465 while((count-->0) && (xcurs<nbcols))
1467 if(vga_modes[line].memmodel==PLANAR4)
1469 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1471 else if(vga_modes[line].memmodel==CGA)
1473 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1475 else if(vga_modes[line].memmodel==LINEAR8)
1477 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1479 else
1481 #ifdef DEBUG
1482 unimplemented();
1483 #endif
1485 xcurs++;
1490 // --------------------------------------------------------------------------------------------
1491 static void biosfn_set_border_color (BL) Bit8u BL;
1492 // FIXME anybody using this function ?
1494 #ifdef DEBUG
1495 unimplemented();
1496 #endif
1499 // --------------------------------------------------------------------------------------------
1500 static void biosfn_set_palette (BL) Bit8u BL;
1501 // FIXME anybody using this function ?
1503 #ifdef DEBUG
1504 unimplemented();
1505 #endif
1508 // --------------------------------------------------------------------------------------------
1509 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1511 Bit8u mode,line,mask,attr;
1512 Bit16u addr,data;
1514 // Get the mode
1515 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1516 line=find_vga_entry(mode);
1517 if(line==0xFF)return;
1518 if(vga_modes[line].class==TEXT)return;
1520 if(vga_modes[line].memmodel==CGA)
1522 if(vga_modes[line].pixbits==2)
1524 addr=(CX>>2)+(DX>>1)*80;
1526 else
1528 addr=(CX>>3)+(DX>>1)*80;
1530 if (DX & 1) addr += 0x2000;
1531 data = read_byte(0xb800,addr);
1532 if(vga_modes[line].pixbits==2)
1534 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1535 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1537 else
1539 attr = (AL & 0x01) << (7 - (CX & 0x07));
1540 mask = 0x01 << (7 - (CX & 0x07));
1542 if (AL & 0x80)
1544 data ^= attr;
1546 else
1548 data &= ~mask;
1549 data |= attr;
1551 write_byte(0xb800,addr,data);
1553 else if(vga_modes[line].memmodel==LINEAR8)
1555 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1556 write_byte(0xa000,addr,AL);
1558 else
1560 #ifdef DEBUG
1561 unimplemented();
1562 #endif
1566 // --------------------------------------------------------------------------------------------
1567 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1569 Bit8u mode,line,attr;
1570 Bit16u addr,data;
1571 Bit16u ss=get_SS();
1573 // Get the mode
1574 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1575 line=find_vga_entry(mode);
1576 if(line==0xFF)return;
1577 if(vga_modes[line].class==TEXT)return;
1579 if(vga_modes[line].memmodel==CGA)
1581 addr=(CX>>2)+(DX>>1)*80;
1582 if (DX & 1) addr += 0x2000;
1583 data = read_byte(0xb800,addr);
1584 if(vga_modes[line].pixbits==2)
1586 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1588 else
1590 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1593 else if(vga_modes[line].memmodel==LINEAR8)
1595 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1596 attr=read_byte(0xa000,addr);
1598 else
1600 #ifdef DEBUG
1601 unimplemented();
1602 #endif
1603 attr = 0;
1605 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1608 // --------------------------------------------------------------------------------------------
1609 static void biosfn_write_teletype (car, page, attr, flag)
1610 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1611 {// flag = WITH_ATTR / NO_ATTR
1613 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1614 Bit16u nbcols,nbrows,address;
1615 Bit16u cursor,dummy;
1617 // special case if page is 0xff, use current page
1618 if(page==0xff)
1619 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1621 // FIXME gfx mode
1623 // Get the mode
1624 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1625 line=find_vga_entry(mode);
1626 if(line==0xFF)return;
1628 // Get the cursor pos for the page
1629 biosfn_get_cursor_pos(page,&dummy,&cursor);
1630 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1632 // Get the dimensions
1633 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1634 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1636 switch(car)
1638 case 7:
1639 //FIXME should beep
1640 break;
1642 case 8:
1643 if(xcurs>0)xcurs--;
1644 break;
1646 case '\r':
1647 xcurs=0;
1648 break;
1650 case '\n':
1651 xcurs=0;
1652 ycurs++;
1653 break;
1655 case '\t':
1658 biosfn_write_teletype(' ',page,attr,flag);
1659 biosfn_get_cursor_pos(page,&dummy,&cursor);
1660 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1661 }while(xcurs%8==0);
1662 break;
1664 default:
1666 if(vga_modes[line].class==TEXT)
1668 // Compute the address
1669 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1671 // Write the char
1672 write_byte(vga_modes[line].sstart,address,car);
1674 if(flag==WITH_ATTR)
1675 write_byte(vga_modes[line].sstart,address+1,attr);
1677 else
1679 // FIXME gfx mode not complete
1680 cheight=vga_modes[line].cheight;
1681 bpp=vga_modes[line].pixbits;
1682 if(vga_modes[line].memmodel==PLANAR4)
1684 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1686 else if(vga_modes[line].memmodel==CGA)
1688 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1690 else if(vga_modes[line].memmodel==LINEAR8)
1692 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1694 else
1696 #ifdef DEBUG
1697 unimplemented();
1698 #endif
1702 xcurs++;
1705 // Do we need to wrap ?
1706 if(xcurs==nbcols)
1707 {xcurs=0;
1708 ycurs++;
1711 // Do we need to scroll ?
1712 if(ycurs==nbrows)
1713 {biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1714 ycurs-=1;
1717 // Set the cursor for the page
1718 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1719 biosfn_set_cursor_pos(page,cursor);
1722 // --------------------------------------------------------------------------------------------
1723 ASM_START
1724 biosfn_get_video_mode:
1725 push ds
1726 mov ax, #biosmem_seg
1727 mov ds, ax
1728 push bx
1729 mov bx, #biosmem_current_page
1730 mov al, [bx]
1731 pop bx
1732 mov bh, al
1733 push bx
1734 mov bx, #biosmem_video_ctl
1735 mov ah, [bx]
1736 and ah, #0x80
1737 mov bx, #biosmem_current_mode
1738 mov al, [bx]
1739 or al, ah
1740 mov bx, #biosmem_nb_cols
1741 mov ah, [bx]
1742 pop bx
1743 pop ds
1745 ASM_END
1747 // --------------------------------------------------------------------------------------------
1748 ASM_START
1749 biosfn_group_10:
1750 cmp al, #0x00
1751 jne int10_test_1001
1752 jmp biosfn_set_single_palette_reg
1753 int10_test_1001:
1754 cmp al, #0x01
1755 jne int10_test_1002
1756 jmp biosfn_set_overscan_border_color
1757 int10_test_1002:
1758 cmp al, #0x02
1759 jne int10_test_1003
1760 jmp biosfn_set_all_palette_reg
1761 int10_test_1003:
1762 cmp al, #0x03
1763 jne int10_test_1007
1764 jmp biosfn_toggle_intensity
1765 int10_test_1007:
1766 cmp al, #0x07
1767 jne int10_test_1008
1768 jmp biosfn_get_single_palette_reg
1769 int10_test_1008:
1770 cmp al, #0x08
1771 jne int10_test_1009
1772 jmp biosfn_read_overscan_border_color
1773 int10_test_1009:
1774 cmp al, #0x09
1775 jne int10_test_1010
1776 jmp biosfn_get_all_palette_reg
1777 int10_test_1010:
1778 cmp al, #0x10
1779 jne int10_test_1012
1780 jmp biosfn_set_single_dac_reg
1781 int10_test_1012:
1782 cmp al, #0x12
1783 jne int10_test_1013
1784 jmp biosfn_set_all_dac_reg
1785 int10_test_1013:
1786 cmp al, #0x13
1787 jne int10_test_1015
1788 jmp biosfn_select_video_dac_color_page
1789 int10_test_1015:
1790 cmp al, #0x15
1791 jne int10_test_1017
1792 jmp biosfn_read_single_dac_reg
1793 int10_test_1017:
1794 cmp al, #0x17
1795 jne int10_test_1018
1796 jmp biosfn_read_all_dac_reg
1797 int10_test_1018:
1798 cmp al, #0x18
1799 jne int10_test_1019
1800 jmp biosfn_set_pel_mask
1801 int10_test_1019:
1802 cmp al, #0x19
1803 jne int10_test_101A
1804 jmp biosfn_read_pel_mask
1805 int10_test_101A:
1806 cmp al, #0x1a
1807 jne int10_group_10_unknown
1808 jmp biosfn_read_video_dac_state
1809 int10_group_10_unknown:
1810 #ifdef DEBUG
1811 call _unknown
1812 #endif
1815 biosfn_set_single_palette_reg:
1816 cmp bl, #0x14
1817 ja no_actl_reg1
1818 push ax
1819 push dx
1820 mov dx, #vgareg_actl_reset
1821 in al, dx
1822 mov dx, #vgareg_actl_address
1823 mov al, bl
1824 out dx, al
1825 mov al, bh
1826 out dx, al
1827 mov al, #0x20
1828 out dx, al
1829 pop dx
1830 pop ax
1831 no_actl_reg1:
1833 ASM_END
1835 // --------------------------------------------------------------------------------------------
1836 ASM_START
1837 biosfn_set_overscan_border_color:
1838 push bx
1839 mov bl, #0x11
1840 call biosfn_set_single_palette_reg
1841 pop bx
1843 ASM_END
1845 // --------------------------------------------------------------------------------------------
1846 ASM_START
1847 biosfn_set_all_palette_reg:
1848 push ax
1849 push bx
1850 push cx
1851 push dx
1852 mov bx, dx
1853 mov dx, #vgareg_actl_reset
1854 in al, dx
1855 mov cl, #0x00
1856 mov dx, #vgareg_actl_address
1857 set_palette_loop:
1858 mov al, cl
1859 out dx, al
1860 seg es
1861 mov al, [bx]
1862 out dx, al
1863 inc bx
1864 inc cl
1865 cmp cl, #0x10
1866 jne set_palette_loop
1867 mov al, #0x11
1868 out dx, al
1869 seg es
1870 mov al, [bx]
1871 out dx, al
1872 mov al, #0x20
1873 out dx, al
1874 pop dx
1875 pop cx
1876 pop bx
1877 pop ax
1879 ASM_END
1881 // --------------------------------------------------------------------------------------------
1882 ASM_START
1883 biosfn_toggle_intensity:
1884 push ax
1885 push bx
1886 push dx
1887 mov dx, #vgareg_actl_reset
1888 in al, dx
1889 mov dx, #vgareg_actl_address
1890 mov al, #0x10
1891 out dx, al
1892 mov dx, #vgareg_actl_read_data
1893 in al, dx
1894 and al, #0xf7
1895 and bl, #0x01
1896 shl bl, 3
1897 or al, bl
1898 mov dx, #vgareg_actl_address
1899 out dx, al
1900 mov al, #0x20
1901 out dx, al
1902 pop dx
1903 pop bx
1904 pop ax
1906 ASM_END
1908 // --------------------------------------------------------------------------------------------
1909 ASM_START
1910 biosfn_get_single_palette_reg:
1911 cmp bl, #0x14
1912 ja no_actl_reg2
1913 push ax
1914 push dx
1915 mov dx, #vgareg_actl_reset
1916 in al, dx
1917 mov dx, #vgareg_actl_address
1918 mov al, bl
1919 out dx, al
1920 mov dx, #vgareg_actl_read_data
1921 in al, dx
1922 mov bh, al
1923 mov dx, #vgareg_actl_reset
1924 in al, dx
1925 mov dx, #vgareg_actl_address
1926 mov al, #0x20
1927 out dx, al
1928 pop dx
1929 pop ax
1930 no_actl_reg2:
1932 ASM_END
1934 // --------------------------------------------------------------------------------------------
1935 ASM_START
1936 biosfn_read_overscan_border_color:
1937 push ax
1938 push bx
1939 mov bl, #0x11
1940 call biosfn_get_single_palette_reg
1941 mov al, bh
1942 pop bx
1943 mov bh, al
1944 pop ax
1946 ASM_END
1948 // --------------------------------------------------------------------------------------------
1949 ASM_START
1950 biosfn_get_all_palette_reg:
1951 push ax
1952 push bx
1953 push cx
1954 push dx
1955 mov bx, dx
1956 mov cl, #0x00
1957 get_palette_loop:
1958 mov dx, #vgareg_actl_reset
1959 in al, dx
1960 mov dx, #vgareg_actl_address
1961 mov al, cl
1962 out dx, al
1963 mov dx, #vgareg_actl_read_data
1964 in al, dx
1965 seg es
1966 mov [bx], al
1967 inc bx
1968 inc cl
1969 cmp cl, #0x10
1970 jne get_palette_loop
1971 mov dx, #vgareg_actl_reset
1972 in al, dx
1973 mov dx, #vgareg_actl_address
1974 mov al, #0x11
1975 out dx, al
1976 mov dx, #vgareg_actl_read_data
1977 in al, dx
1978 seg es
1979 mov [bx], al
1980 mov dx, #vgareg_actl_reset
1981 in al, dx
1982 mov dx, #vgareg_actl_address
1983 mov al, #0x20
1984 out dx, al
1985 pop dx
1986 pop cx
1987 pop bx
1988 pop ax
1990 ASM_END
1992 // --------------------------------------------------------------------------------------------
1993 ASM_START
1994 biosfn_set_single_dac_reg:
1995 push ax
1996 push dx
1997 mov dx, #vgareg_dac_write_address
1998 mov al, bl
1999 out dx, al
2000 mov dx, #vgareg_dac_data
2001 pop ax
2002 push ax
2003 mov al, ah
2004 out dx, al
2005 mov al, ch
2006 out dx, al
2007 mov al, cl
2008 out dx, al
2009 pop dx
2010 pop ax
2012 ASM_END
2014 // --------------------------------------------------------------------------------------------
2015 ASM_START
2016 biosfn_set_all_dac_reg:
2017 push ax
2018 push bx
2019 push cx
2020 push dx
2021 mov dx, #vgareg_dac_write_address
2022 mov al, bl
2023 out dx, al
2024 pop dx
2025 push dx
2026 mov bx, dx
2027 mov dx, #vgareg_dac_data
2028 set_dac_loop:
2029 seg es
2030 mov al, [bx]
2031 out dx, al
2032 inc bx
2033 seg es
2034 mov al, [bx]
2035 out dx, al
2036 inc bx
2037 seg es
2038 mov al, [bx]
2039 out dx, al
2040 inc bx
2041 dec cx
2042 jnz set_dac_loop
2043 pop dx
2044 pop cx
2045 pop bx
2046 pop ax
2048 ASM_END
2050 // --------------------------------------------------------------------------------------------
2051 ASM_START
2052 biosfn_select_video_dac_color_page:
2053 push ax
2054 push bx
2055 push dx
2056 mov dx, #vgareg_actl_reset
2057 in al, dx
2058 mov dx, #vgareg_actl_address
2059 mov al, #0x10
2060 out dx, al
2061 mov dx, #vgareg_actl_read_data
2062 in al, dx
2063 and bl, #0x01
2064 jnz set_dac_page
2065 and al, #0x7f
2066 shl bh, 7
2067 or al, bh
2068 mov dx, #vgareg_actl_address
2069 out dx, al
2070 jmp set_actl_normal
2071 set_dac_page:
2072 push ax
2073 mov dx, #vgareg_actl_reset
2074 in al, dx
2075 mov dx, #vgareg_actl_address
2076 mov al, #0x14
2077 out dx, al
2078 pop ax
2079 and al, #0x80
2080 jnz set_dac_16_page
2081 shl bh, 2
2082 set_dac_16_page:
2083 and bh, #0x0f
2084 mov al, bh
2085 out dx, al
2086 set_actl_normal:
2087 mov al, #0x20
2088 out dx, al
2089 pop dx
2090 pop bx
2091 pop ax
2093 ASM_END
2095 // --------------------------------------------------------------------------------------------
2096 ASM_START
2097 biosfn_read_single_dac_reg:
2098 push ax
2099 push dx
2100 mov dx, #vgareg_dac_read_address
2101 mov al, bl
2102 out dx, al
2103 pop ax
2104 mov ah, al
2105 mov dx, #vgareg_dac_data
2106 in al, dx
2107 xchg al, ah
2108 push ax
2109 in al, dx
2110 mov ch, al
2111 in al, dx
2112 mov cl, al
2113 pop dx
2114 pop ax
2116 ASM_END
2118 // --------------------------------------------------------------------------------------------
2119 ASM_START
2120 biosfn_read_all_dac_reg:
2121 push ax
2122 push bx
2123 push cx
2124 push dx
2125 mov dx, #vgareg_dac_read_address
2126 mov al, bl
2127 out dx, al
2128 pop dx
2129 push dx
2130 mov bx, dx
2131 mov dx, #vgareg_dac_data
2132 read_dac_loop:
2133 in al, dx
2134 seg es
2135 mov [bx], al
2136 inc bx
2137 in al, dx
2138 seg es
2139 mov [bx], al
2140 inc bx
2141 in al, dx
2142 seg es
2143 mov [bx], al
2144 inc bx
2145 dec cx
2146 jnz read_dac_loop
2147 pop dx
2148 pop cx
2149 pop bx
2150 pop ax
2152 ASM_END
2154 // --------------------------------------------------------------------------------------------
2155 ASM_START
2156 biosfn_set_pel_mask:
2157 push ax
2158 push dx
2159 mov dx, #vgareg_pel_mask
2160 mov al, bl
2161 out dx, al
2162 pop dx
2163 pop ax
2165 ASM_END
2167 // --------------------------------------------------------------------------------------------
2168 ASM_START
2169 biosfn_read_pel_mask:
2170 push ax
2171 push dx
2172 mov dx, #vgareg_pel_mask
2173 in al, dx
2174 mov bl, al
2175 pop dx
2176 pop ax
2178 ASM_END
2180 // --------------------------------------------------------------------------------------------
2181 ASM_START
2182 biosfn_read_video_dac_state:
2183 push ax
2184 push dx
2185 mov dx, #vgareg_actl_reset
2186 in al, dx
2187 mov dx, #vgareg_actl_address
2188 mov al, #0x10
2189 out dx, al
2190 mov dx, #vgareg_actl_read_data
2191 in al, dx
2192 mov bl, al
2193 shr bl, 7
2194 mov dx, #vgareg_actl_reset
2195 in al, dx
2196 mov dx, #vgareg_actl_address
2197 mov al, #0x14
2198 out dx, al
2199 mov dx, #vgareg_actl_read_data
2200 in al, dx
2201 mov bh, al
2202 and bh, #0x0f
2203 test bl, #0x01
2204 jnz get_dac_16_page
2205 shr bh, 2
2206 get_dac_16_page:
2207 mov dx, #vgareg_actl_reset
2208 in al, dx
2209 mov dx, #vgareg_actl_address
2210 mov al, #0x20
2211 out dx, al
2212 pop dx
2213 pop ax
2215 ASM_END
2217 // --------------------------------------------------------------------------------------------
2218 static void biosfn_perform_gray_scale_summing (start,count)
2219 Bit16u start;Bit16u count;
2220 {Bit8u r,g,b;
2221 Bit16u i;
2222 Bit16u index;
2224 inb(VGAREG_ACTL_RESET);
2225 outb(VGAREG_ACTL_ADDRESS,0x00);
2227 for( index = 0; index < count; index++ )
2229 // set read address and switch to read mode
2230 outb(VGAREG_DAC_READ_ADDRESS,start);
2231 // get 6-bit wide RGB data values
2232 r=inb( VGAREG_DAC_DATA );
2233 g=inb( VGAREG_DAC_DATA );
2234 b=inb( VGAREG_DAC_DATA );
2236 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2237 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2239 if(i>0x3f)i=0x3f;
2241 // set write address and switch to write mode
2242 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2243 // write new intensity value
2244 outb( VGAREG_DAC_DATA, i&0xff );
2245 outb( VGAREG_DAC_DATA, i&0xff );
2246 outb( VGAREG_DAC_DATA, i&0xff );
2247 start++;
2249 inb(VGAREG_ACTL_RESET);
2250 outb(VGAREG_ACTL_ADDRESS,0x20);
2253 // --------------------------------------------------------------------------------------------
2254 static void get_font_access()
2256 ASM_START
2257 mov dx, #vgareg_sequ_address
2258 mov ax, #0x0100
2259 out dx, ax
2260 mov ax, #0x0402
2261 out dx, ax
2262 mov ax, #0x0704
2263 out dx, ax
2264 mov ax, #0x0300
2265 out dx, ax
2266 mov dx, #vgareg_grdc_address
2267 mov ax, #0x0204
2268 out dx, ax
2269 mov ax, #0x0005
2270 out dx, ax
2271 mov ax, #0x0406
2272 out dx, ax
2273 ASM_END
2276 static void release_font_access()
2278 ASM_START
2279 mov dx, #vgareg_sequ_address
2280 mov ax, #0x0100
2281 out dx, ax
2282 mov ax, #0x0302
2283 out dx, ax
2284 mov ax, #0x0304
2285 out dx, ax
2286 mov ax, #0x0300
2287 out dx, ax
2288 mov dx, #vgareg_grdc_address
2289 mov ax, #0x0004
2290 out dx, ax
2291 mov ax, #0x1005
2292 out dx, ax
2293 mov ax, #0x0e06
2294 out dx, ax
2295 ASM_END
2298 ASM_START
2299 idiv_u:
2300 xor dx,dx
2301 div bx
2303 ASM_END
2305 static void set_scan_lines(lines) Bit8u lines;
2307 Bit16u crtc_addr,cols,page,vde;
2308 Bit8u crtc_r9,ovl,rows;
2310 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2311 outb(crtc_addr, 0x09);
2312 crtc_r9 = inb(crtc_addr+1);
2313 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2314 outb(crtc_addr+1, crtc_r9);
2315 if(lines==8)
2317 biosfn_set_cursor_shape(0x06,0x07);
2319 else
2321 biosfn_set_cursor_shape(lines-4,lines-3);
2323 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2324 outb(crtc_addr, 0x12);
2325 vde = inb(crtc_addr+1);
2326 outb(crtc_addr, 0x07);
2327 ovl = inb(crtc_addr+1);
2328 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2329 rows = vde / lines;
2330 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2331 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2332 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2335 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;
2337 Bit16u blockaddr,dest,i,src;
2339 get_font_access();
2340 blockaddr = BL << 13;
2341 for(i=0;i<CX;i++)
2343 src = BP + i * BH;
2344 dest = blockaddr + (DX + i) * 32;
2345 memcpyb(0xA000, dest, ES, src, BH);
2347 release_font_access();
2348 if(AL>=0x10)
2350 set_scan_lines(BH);
2354 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2356 Bit16u blockaddr,dest,i,src;
2358 get_font_access();
2359 blockaddr = BL << 13;
2360 for(i=0;i<0x100;i++)
2362 src = i * 14;
2363 dest = blockaddr + i * 32;
2364 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2366 release_font_access();
2367 if(AL>=0x10)
2369 set_scan_lines(14);
2373 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2375 Bit16u blockaddr,dest,i,src;
2377 get_font_access();
2378 blockaddr = BL << 13;
2379 for(i=0;i<0x100;i++)
2381 src = i * 8;
2382 dest = blockaddr + i * 32;
2383 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2385 release_font_access();
2386 if(AL>=0x10)
2388 set_scan_lines(8);
2392 static void biosfn_set_text_block_specifier (BL) Bit8u BL;
2394 outb( VGAREG_SEQU_ADDRESS, 0x03 );
2395 outb( VGAREG_SEQU_DATA, BL );
2398 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2400 Bit16u blockaddr,dest,i,src;
2402 get_font_access();
2403 blockaddr = BL << 13;
2404 for(i=0;i<0x100;i++)
2406 src = i * 16;
2407 dest = blockaddr + i * 32;
2408 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2410 release_font_access();
2411 if(AL>=0x10)
2413 set_scan_lines(16);
2417 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2419 #ifdef DEBUG
2420 unimplemented();
2421 #endif
2423 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2425 #ifdef DEBUG
2426 unimplemented();
2427 #endif
2429 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2431 #ifdef DEBUG
2432 unimplemented();
2433 #endif
2435 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2437 #ifdef DEBUG
2438 unimplemented();
2439 #endif
2441 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2443 #ifdef DEBUG
2444 unimplemented();
2445 #endif
2447 // --------------------------------------------------------------------------------------------
2448 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2449 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2450 {Bit16u ss=get_SS();
2452 switch(BH)
2453 {case 0x00:
2454 write_word(ss,ES,read_word(0x00,0x1f*4));
2455 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2456 break;
2457 case 0x01:
2458 write_word(ss,ES,read_word(0x00,0x43*4));
2459 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2460 break;
2461 case 0x02:
2462 write_word(ss,ES,0xC000);
2463 write_word(ss,BP,vgafont14);
2464 break;
2465 case 0x03:
2466 write_word(ss,ES,0xC000);
2467 write_word(ss,BP,vgafont8);
2468 break;
2469 case 0x04:
2470 write_word(ss,ES,0xC000);
2471 write_word(ss,BP,vgafont8+128*8);
2472 break;
2473 case 0x05:
2474 write_word(ss,ES,0xC000);
2475 write_word(ss,BP,vgafont14alt);
2476 break;
2477 case 0x06:
2478 write_word(ss,ES,0xC000);
2479 write_word(ss,BP,vgafont16);
2480 break;
2481 case 0x07:
2482 write_word(ss,ES,0xC000);
2483 write_word(ss,BP,vgafont16alt);
2484 break;
2485 default:
2486 #ifdef DEBUG
2487 printf("Get font info BH(%02x) was discarded\n",BH);
2488 #endif
2489 return;
2491 // Set byte/char of on screen font
2492 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2494 // Set Highest char row
2495 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2498 // --------------------------------------------------------------------------------------------
2499 static void biosfn_get_ega_info (BX,CX)
2500 Bit16u *BX;Bit16u *CX;
2501 {Bit16u ss=get_SS();
2502 Bit16u crtc;
2503 Bit8u switches;
2505 crtc=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2506 if(crtc==VGAREG_MDA_CRTC_ADDRESS)
2507 write_word(ss,BX,(1<<8)+0x0003);
2508 else
2509 write_word(ss,BX,0x0003);
2511 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2512 write_word(ss,CX,(switches&0x0f));
2515 // --------------------------------------------------------------------------------------------
2516 static void biosfn_alternate_prtsc()
2518 #ifdef DEBUG
2519 unimplemented();
2520 #endif
2523 // --------------------------------------------------------------------------------------------
2524 static void biosfn_select_vert_res (res)
2525 Bit8u res;
2526 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2527 Bit8u modeset,switches;
2529 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2530 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2531 switch(res)
2532 {case 0x00:
2533 // set modeset ctl bit 7 and reset bit 4
2534 // set switches bit 3-0 to 0x08
2535 modeset|=0x80;modeset&=0xef;
2536 switches&=0xf0;switches|=0x08;
2537 break;
2538 case 0x01:
2539 // reset modeset ctl bit 7 and bit 4
2540 // set switches bit 3-0 to 0x09
2541 modeset&=0x6f;
2542 switches&=0xf0;switches|=0x09;
2543 break;
2544 case 0x02:
2545 // reset modeset ctl bit 7 and set bit 4
2546 // set switches bit 3-0 to 0x09
2547 modeset|=0x10;modeset&=0x7f;
2548 switches&=0xf0;switches|=0x09;
2549 break;
2550 default:
2551 #ifdef DEBUG
2552 printf("Select vert res (%02x) was discarded\n",res);
2553 #endif
2554 return;
2556 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2557 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2560 // --------------------------------------------------------------------------------------------
2561 static void biosfn_enable_default_palette_loading (disable)
2562 Bit8u disable;
2564 Bit8u modeset;
2566 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2568 // Bit 3
2569 if(disable!=0x00)modeset|=0x08;
2570 else modeset&=0xf7;
2572 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2575 // --------------------------------------------------------------------------------------------
2576 static void biosfn_enable_video_addressing (disable)
2577 Bit8u disable;
2579 Bit8u misc;
2581 misc=inb(VGAREG_READ_MISC_OUTPUT);
2582 // bit 1, 0 disable
2583 if(disable!=0x00) misc&=0xfd;
2584 else misc|=0x02;
2585 outb(VGAREG_WRITE_MISC_OUTPUT,misc);
2588 // --------------------------------------------------------------------------------------------
2589 static void biosfn_enable_grayscale_summing (disable)
2590 Bit8u disable;
2592 Bit8u modeset;
2594 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2596 // Bit 1 set if disable=0
2597 if(disable==0x00)modeset|=0x02;
2598 else modeset&=0xfd;
2600 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2603 // --------------------------------------------------------------------------------------------
2604 static void biosfn_enable_cursor_emulation (disable)
2605 Bit8u disable;
2607 Bit8u videoctl;
2609 videoctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
2611 // Bit 0 set if disable!=0
2612 if(disable!=0x00)videoctl|=0x01;
2613 else videoctl&=0xfe;
2615 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,videoctl);
2618 // --------------------------------------------------------------------------------------------
2619 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2621 #ifdef DEBUG
2622 unimplemented();
2623 #endif
2625 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2627 #ifdef DEBUG
2628 unimplemented();
2629 #endif
2632 // --------------------------------------------------------------------------------------------
2633 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2634 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2636 Bit16u newcurs,oldcurs,dummy;
2637 Bit8u car,carattr;
2639 // Read curs info for the page
2640 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2642 // if row=0xff special case : use current cursor position
2643 if(row==0xff)
2644 {col=oldcurs&0x00ff;
2645 row=(oldcurs&0xff00)>>8;
2648 newcurs=row; newcurs<<=8; newcurs+=col;
2649 biosfn_set_cursor_pos(page,newcurs);
2651 while(count--!=0)
2653 car=read_byte(seg,offset++);
2654 if((flag&0x02)!=0)
2655 attr=read_byte(seg,offset++);
2657 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2660 // Set back curs pos
2661 if((flag&0x01)==0)
2662 biosfn_set_cursor_pos(page,oldcurs);
2665 // --------------------------------------------------------------------------------------------
2666 ASM_START
2667 biosfn_group_1A:
2668 cmp al, #0x00
2669 je biosfn_read_display_code
2670 cmp al, #0x01
2671 je biosfn_set_display_code
2672 #ifdef DEBUG
2673 call _unknown
2674 #endif
2676 biosfn_read_display_code:
2677 push ds
2678 push ax
2679 mov ax, #biosmem_seg
2680 mov ds, ax
2681 mov bx, #biosmem_dcc_index
2682 mov al, [bx]
2683 mov bl, al
2684 xor bh, bh
2685 pop ax
2686 mov al, ah
2687 pop ds
2689 biosfn_set_display_code:
2690 push ds
2691 push ax
2692 push bx
2693 mov ax, #biosmem_seg
2694 mov ds, ax
2695 mov ax, bx
2696 mov bx, #biosmem_dcc_index
2697 mov [bx], al
2698 #ifdef DEBUG
2699 mov al, ah
2700 xor ah, ah
2701 push ax
2702 mov bx, #msg_alt_dcc
2703 push bx
2704 call _printf
2705 add sp, #4
2706 #endif
2707 pop bx
2708 pop ax
2709 mov al, ah
2710 pop ds
2713 #ifdef DEBUG
2714 msg_alt_dcc:
2715 .ascii "Alternate Display code (%02x) was discarded"
2716 .byte 0x0d,0x0a,0x00
2717 #endif
2718 ASM_END
2720 // --------------------------------------------------------------------------------------------
2721 static void biosfn_read_state_info (BX,ES,DI)
2722 Bit16u BX;Bit16u ES;Bit16u DI;
2724 // Address of static functionality table
2725 write_word(ES,DI+0x00,&static_functionality);
2726 write_word(ES,DI+0x02,0xC000);
2728 // Hard coded copy from BIOS area. Should it be cleaner ?
2729 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2730 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2732 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2733 write_byte(ES,DI+0x26,0);
2734 write_byte(ES,DI+0x27,16);
2735 write_byte(ES,DI+0x28,0);
2736 write_byte(ES,DI+0x29,8);
2737 write_byte(ES,DI+0x2a,2);
2738 write_byte(ES,DI+0x2b,0);
2739 write_byte(ES,DI+0x2c,0);
2740 write_byte(ES,DI+0x31,3);
2741 write_byte(ES,DI+0x32,0);
2743 memsetb(ES,DI+0x33,0,13);
2746 // --------------------------------------------------------------------------------------------
2747 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2749 #ifdef DEBUG
2750 unimplemented();
2751 #endif
2753 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2755 #ifdef DEBUG
2756 unimplemented();
2757 #endif
2759 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2761 #ifdef DEBUG
2762 unimplemented();
2763 #endif
2766 // ============================================================================================
2768 // Video Utils
2770 // ============================================================================================
2772 // --------------------------------------------------------------------------------------------
2773 static Bit8u find_vga_entry(mode)
2774 Bit8u mode;
2776 Bit8u i,line=0xFF;
2777 for(i=0;i<=MODE_MAX;i++)
2778 if(vga_modes[i].svgamode==mode)
2779 {line=i;
2780 break;
2782 return line;
2785 /* =========================================================== */
2787 * Misc Utils
2789 /* =========================================================== */
2791 // --------------------------------------------------------------------------------------------
2792 static void memsetb(seg,offset,value,count)
2793 Bit16u seg;
2794 Bit16u offset;
2795 Bit16u value;
2796 Bit16u count;
2798 ASM_START
2799 push bp
2800 mov bp, sp
2802 push ax
2803 push cx
2804 push es
2805 push di
2807 mov cx, 10[bp] ; count
2808 cmp cx, #0x00
2809 je memsetb_end
2810 mov ax, 4[bp] ; segment
2811 mov es, ax
2812 mov ax, 6[bp] ; offset
2813 mov di, ax
2814 mov al, 8[bp] ; value
2817 stosb
2819 memsetb_end:
2820 pop di
2821 pop es
2822 pop cx
2823 pop ax
2825 pop bp
2826 ASM_END
2829 // --------------------------------------------------------------------------------------------
2830 static void memsetw(seg,offset,value,count)
2831 Bit16u seg;
2832 Bit16u offset;
2833 Bit16u value;
2834 Bit16u count;
2836 ASM_START
2837 push bp
2838 mov bp, sp
2840 push ax
2841 push cx
2842 push es
2843 push di
2845 mov cx, 10[bp] ; count
2846 cmp cx, #0x00
2847 je memsetw_end
2848 mov ax, 4[bp] ; segment
2849 mov es, ax
2850 mov ax, 6[bp] ; offset
2851 mov di, ax
2852 mov ax, 8[bp] ; value
2855 stosw
2857 memsetw_end:
2858 pop di
2859 pop es
2860 pop cx
2861 pop ax
2863 pop bp
2864 ASM_END
2867 // --------------------------------------------------------------------------------------------
2868 static void memcpyb(dseg,doffset,sseg,soffset,count)
2869 Bit16u dseg;
2870 Bit16u doffset;
2871 Bit16u sseg;
2872 Bit16u soffset;
2873 Bit16u count;
2875 ASM_START
2876 push bp
2877 mov bp, sp
2879 push ax
2880 push cx
2881 push es
2882 push di
2883 push ds
2884 push si
2886 mov cx, 12[bp] ; count
2887 cmp cx, #0x0000
2888 je memcpyb_end
2889 mov ax, 4[bp] ; dsegment
2890 mov es, ax
2891 mov ax, 6[bp] ; doffset
2892 mov di, ax
2893 mov ax, 8[bp] ; ssegment
2894 mov ds, ax
2895 mov ax, 10[bp] ; soffset
2896 mov si, ax
2899 movsb
2901 memcpyb_end:
2902 pop si
2903 pop ds
2904 pop di
2905 pop es
2906 pop cx
2907 pop ax
2909 pop bp
2910 ASM_END
2913 // --------------------------------------------------------------------------------------------
2914 static void memcpyw(dseg,doffset,sseg,soffset,count)
2915 Bit16u dseg;
2916 Bit16u doffset;
2917 Bit16u sseg;
2918 Bit16u soffset;
2919 Bit16u count;
2921 ASM_START
2922 push bp
2923 mov bp, sp
2925 push ax
2926 push cx
2927 push es
2928 push di
2929 push ds
2930 push si
2932 mov cx, 12[bp] ; count
2933 cmp cx, #0x0000
2934 je memcpyw_end
2935 mov ax, 4[bp] ; dsegment
2936 mov es, ax
2937 mov ax, 6[bp] ; doffset
2938 mov di, ax
2939 mov ax, 8[bp] ; ssegment
2940 mov ds, ax
2941 mov ax, 10[bp] ; soffset
2942 mov si, ax
2945 movsw
2947 memcpyw_end:
2948 pop si
2949 pop ds
2950 pop di
2951 pop es
2952 pop cx
2953 pop ax
2955 pop bp
2956 ASM_END
2959 /* =========================================================== */
2961 * These functions where ripped from Kevin's rombios.c
2963 /* =========================================================== */
2965 // --------------------------------------------------------------------------------------------
2966 static Bit8u
2967 read_byte(seg, offset)
2968 Bit16u seg;
2969 Bit16u offset;
2971 ASM_START
2972 push bp
2973 mov bp, sp
2975 push bx
2976 push ds
2977 mov ax, 4[bp] ; segment
2978 mov ds, ax
2979 mov bx, 6[bp] ; offset
2980 mov al, [bx]
2981 ;; al = return value (byte)
2982 pop ds
2983 pop bx
2985 pop bp
2986 ASM_END
2989 // --------------------------------------------------------------------------------------------
2990 static Bit16u
2991 read_word(seg, offset)
2992 Bit16u seg;
2993 Bit16u offset;
2995 ASM_START
2996 push bp
2997 mov bp, sp
2999 push bx
3000 push ds
3001 mov ax, 4[bp] ; segment
3002 mov ds, ax
3003 mov bx, 6[bp] ; offset
3004 mov ax, [bx]
3005 ;; ax = return value (word)
3006 pop ds
3007 pop bx
3009 pop bp
3010 ASM_END
3013 // --------------------------------------------------------------------------------------------
3014 static void
3015 write_byte(seg, offset, data)
3016 Bit16u seg;
3017 Bit16u offset;
3018 Bit8u data;
3020 ASM_START
3021 push bp
3022 mov bp, sp
3024 push ax
3025 push bx
3026 push ds
3027 mov ax, 4[bp] ; segment
3028 mov ds, ax
3029 mov bx, 6[bp] ; offset
3030 mov al, 8[bp] ; data byte
3031 mov [bx], al ; write data byte
3032 pop ds
3033 pop bx
3034 pop ax
3036 pop bp
3037 ASM_END
3040 // --------------------------------------------------------------------------------------------
3041 static void
3042 write_word(seg, offset, data)
3043 Bit16u seg;
3044 Bit16u offset;
3045 Bit16u data;
3047 ASM_START
3048 push bp
3049 mov bp, sp
3051 push ax
3052 push bx
3053 push ds
3054 mov ax, 4[bp] ; segment
3055 mov ds, ax
3056 mov bx, 6[bp] ; offset
3057 mov ax, 8[bp] ; data word
3058 mov [bx], ax ; write data word
3059 pop ds
3060 pop bx
3061 pop ax
3063 pop bp
3064 ASM_END
3067 // --------------------------------------------------------------------------------------------
3068 Bit8u
3069 inb(port)
3070 Bit16u port;
3072 ASM_START
3073 push bp
3074 mov bp, sp
3076 push dx
3077 mov dx, 4[bp]
3078 in al, dx
3079 pop dx
3081 pop bp
3082 ASM_END
3085 Bit16u
3086 inw(port)
3087 Bit16u port;
3089 ASM_START
3090 push bp
3091 mov bp, sp
3093 push dx
3094 mov dx, 4[bp]
3095 in ax, dx
3096 pop dx
3098 pop bp
3099 ASM_END
3102 // --------------------------------------------------------------------------------------------
3103 void
3104 outb(port, val)
3105 Bit16u port;
3106 Bit8u val;
3108 ASM_START
3109 push bp
3110 mov bp, sp
3112 push ax
3113 push dx
3114 mov dx, 4[bp]
3115 mov al, 6[bp]
3116 out dx, al
3117 pop dx
3118 pop ax
3120 pop bp
3121 ASM_END
3124 // --------------------------------------------------------------------------------------------
3125 void
3126 outw(port, val)
3127 Bit16u port;
3128 Bit16u val;
3130 ASM_START
3131 push bp
3132 mov bp, sp
3134 push ax
3135 push dx
3136 mov dx, 4[bp]
3137 mov ax, 6[bp]
3138 out dx, ax
3139 pop dx
3140 pop ax
3142 pop bp
3143 ASM_END
3146 Bit16u get_SS()
3148 ASM_START
3149 mov ax, ss
3150 ASM_END
3153 #ifdef DEBUG
3154 void unimplemented()
3156 printf("--> Unimplemented\n");
3159 void unknown()
3161 printf("--> Unknown int10\n");
3163 #endif
3165 // --------------------------------------------------------------------------------------------
3166 void printf(s)
3167 Bit8u *s;
3169 Bit8u c, format_char;
3170 Boolean in_format;
3171 unsigned format_width, i;
3172 Bit16u *arg_ptr;
3173 Bit16u arg_seg, arg, digit, nibble, shift_count;
3175 arg_ptr = &s;
3176 arg_seg = get_SS();
3178 in_format = 0;
3179 format_width = 0;
3181 while (c = read_byte(0xc000, s)) {
3182 if ( c == '%' ) {
3183 in_format = 1;
3184 format_width = 0;
3186 else if (in_format) {
3187 if ( (c>='0') && (c<='9') ) {
3188 format_width = (format_width * 10) + (c - '0');
3190 else if (c == 'x') {
3191 arg_ptr++; // increment to next arg
3192 arg = read_word(arg_seg, arg_ptr);
3193 if (format_width == 0)
3194 format_width = 4;
3195 i = 0;
3196 digit = format_width - 1;
3197 for (i=0; i<format_width; i++) {
3198 nibble = (arg >> (4 * digit)) & 0x000f;
3199 if (nibble <= 9)
3200 outb(0x0500, nibble + '0');
3201 else
3202 outb(0x0500, (nibble - 10) + 'A');
3203 digit--;
3205 in_format = 0;
3207 //else if (c == 'd') {
3208 // in_format = 0;
3209 // }
3211 else {
3212 outb(0x0500, c);
3214 s ++;
3218 #ifdef VBE
3219 #include "vbe.c"
3220 #endif
3222 // --------------------------------------------------------------------------------------------
3224 ASM_START
3225 ;; DATA_SEG_DEFS_HERE
3226 ASM_END
3228 ASM_START
3229 .ascii "vgabios ends here"
3230 .byte 0x00
3231 vgabios_end:
3232 .byte 0xCB
3233 ;; BLOCK_STRINGS_BEGIN
3234 ASM_END