- table entries for vga mode 0x0f fixed (PLANAR2 exists on EGA only)
[vgabios.git] / vgabios.c
blobd589958d656a73874bf81656100890c4802af85d
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_write_pixel();
91 static void biosfn_read_pixel();
92 static void biosfn_write_teletype();
93 static void biosfn_perform_gray_scale_summing();
94 static void biosfn_load_text_user_pat();
95 static void biosfn_load_text_8_14_pat();
96 static void biosfn_load_text_8_8_pat();
97 static void biosfn_load_text_8_16_pat();
98 static void biosfn_load_gfx_8_8_chars();
99 static void biosfn_load_gfx_user_chars();
100 static void biosfn_load_gfx_8_14_chars();
101 static void biosfn_load_gfx_8_8_dd_chars();
102 static void biosfn_load_gfx_8_16_chars();
103 static void biosfn_get_font_info();
104 static void biosfn_get_ega_info();
105 static void biosfn_alternate_prtsc();
106 static void biosfn_select_vert_res();
107 static void biosfn_enable_cursor_emulation();
108 static void biosfn_switch_video_interface();
109 static void biosfn_enable_video_refresh_control();
110 static void biosfn_write_string();
111 static void biosfn_read_state_info();
112 static void biosfn_read_video_state_size();
113 static void biosfn_save_video_state();
114 static void biosfn_restore_video_state();
116 // This is for compiling with gcc2 and gcc3
117 #define ASM_START #asm
118 #define ASM_END #endasm
120 ASM_START
122 biosmem_seg = 0x40
123 biosmem_initial_mode = 0x10
124 biosmem_current_mode = 0x49
125 biosmem_nb_cols = 0x4a
126 biosmem_current_page = 0x62
127 biosmem_current_msr = 0x65
128 biosmem_char_height = 0x85
129 biosmem_video_ctl = 0x87
130 biosmem_switches = 0x88
131 biosmem_modeset_ctl = 0x89
132 biosmem_dcc_index = 0x8a
134 vgareg_actl_address = 0x03c0
135 vgareg_actl_read_data = 0x03c1
136 vgareg_write_misc_output = 0x03c2
137 vgareg_sequ_address = 0x03c4
138 vgareg_pel_mask = 0x03c6
139 vgareg_dac_read_address = 0x03c7
140 vgareg_dac_write_address = 0x03c8
141 vgareg_dac_data = 0x03c9
142 vgareg_read_misc_output = 0x03cc
143 vgareg_grdc_address = 0x03ce
144 vgareg_actl_reset = 0x03da
146 MACRO SET_INT_VECTOR
147 push ds
148 xor ax, ax
149 mov ds, ax
150 mov ax, ?3
151 mov ?1*4, ax
152 mov ax, ?2
153 mov ?1*4+2, ax
154 pop ds
155 MEND
157 ASM_END
159 ASM_START
160 .text
161 .rom
162 .org 0
164 use16 386
166 vgabios_start:
167 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
169 .byte 0x40 /* BIOS extension length in units of 512 bytes */
172 vgabios_entry_point:
174 jmp vgabios_init_func
176 vgabios_name:
177 .ascii "Plex86/Bochs VGABios"
178 .ascii " "
179 .byte 0x00
181 // Info from Bart Oldeman
182 .org 0x1e
183 .ascii "IBM"
184 .byte 0x00
186 vgabios_version:
187 #ifndef VGABIOS_VERS
188 .ascii "current-cvs"
189 #else
190 .ascii VGABIOS_VERS
191 #endif
192 .ascii " "
194 vgabios_date:
195 .ascii VGABIOS_DATE
196 .byte 0x0a,0x0d
197 .byte 0x00
199 vgabios_copyright:
200 .ascii "(C) 2003 the LGPL VGABios developers Team"
201 .byte 0x0a,0x0d
202 .byte 0x00
204 vgabios_license:
205 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
206 .byte 0x0a,0x0d
207 .byte 0x0a,0x0d
208 .byte 0x00
210 vgabios_website:
211 .ascii "Please visit :"
212 .byte 0x0a,0x0d
213 ;;.ascii " . http://www.plex86.org"
214 ;;.byte 0x0a,0x0d
215 .ascii " . http://bochs.sourceforge.net"
216 .byte 0x0a,0x0d
217 .ascii " . http://www.nongnu.org/vgabios"
218 .byte 0x0a,0x0d
219 .byte 0x0a,0x0d
220 .byte 0x00
223 ;; ============================================================================================
225 ;; Init Entry point
227 ;; ============================================================================================
228 vgabios_init_func:
230 ;; init vga card
231 call init_vga_card
233 ;; init basic bios vars
234 call init_bios_area
236 #ifdef VBE
237 ;; init vbe functions
238 call _vbe_init
239 #endif
241 ;; set int10 vect
242 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
244 ;; display splash screen
245 call _display_splash_screen
247 ;; init video mode and clear the screen
248 mov ax,#0x0003
249 int #0x10
251 ;; show info
252 call _display_info
254 #ifdef VBE
255 ;; show vbe info
256 call _vbe_display_info
257 #endif
260 retf
261 ASM_END
264 * int10 handled here
266 ASM_START
267 vgabios_int10_handler:
268 pushf
269 #ifdef DEBUG
270 push es
271 push ds
272 pusha
273 mov bx, #0xc000
274 mov ds, bx
275 call _int10_debugmsg
276 popa
277 pop ds
278 pop es
279 #endif
280 cmp ah, #0x0f
281 jne int10_test_1A
282 call biosfn_get_video_mode
283 jmp int10_end
284 int10_test_1A:
285 cmp ah, #0x1a
286 jne int10_test_0B
287 call biosfn_group_1A
288 jmp int10_end
289 int10_test_0B:
290 cmp ah, #0x0b
291 jne int10_test_1103
292 call biosfn_group_0B
293 jmp int10_end
294 int10_test_1103:
295 cmp ax, #0x1103
296 jne int10_test_12
297 call biosfn_set_text_block_specifier
298 jmp int10_end
299 int10_test_12:
300 cmp ah, #0x12
301 jne int10_test_101B
302 cmp bl, #0x31
303 jne int10_test_BL32
304 call biosfn_enable_default_palette_loading
305 jmp int10_end
306 int10_test_BL32:
307 cmp bl, #0x32
308 jne int10_test_BL33
309 call biosfn_enable_video_addressing
310 jmp int10_end
311 int10_test_BL33:
312 cmp bl, #0x33
313 jne int10_normal
314 call biosfn_enable_grayscale_summing
315 jmp int10_end
316 int10_test_101B:
317 cmp ax, #0x101b
318 je int10_normal
319 cmp ah, #0x10
320 jne int10_normal
321 call biosfn_group_10
322 jmp int10_end
324 int10_normal:
325 push es
326 push ds
327 pusha
329 ;; We have to set ds to access the right data segment
330 mov bx, #0xc000
331 mov ds, bx
332 call _int10_func
334 popa
335 pop ds
336 pop es
337 int10_end:
338 popf
339 iret
340 ASM_END
342 #include "vgatables.h"
343 #include "vgafonts.h"
346 * Boot time harware inits
348 ASM_START
349 init_vga_card:
350 ;; switch to color mode and enable CPU access 480 lines
351 mov dx, #0x3C2
352 mov al, #0xC3
353 outb dx,al
355 ;; more than 64k 3C4/04
356 mov dx, #0x3C4
357 mov al, #0x04
358 outb dx,al
359 mov dx, #0x3C5
360 mov al, #0x02
361 outb dx,al
363 mov bx, #msg_vga_init
364 push bx
365 call _printf
366 inc sp
367 inc sp
370 msg_vga_init:
371 .ascii "VGABios $Id$"
372 .byte 0x0d,0x0a,0x00
373 ASM_END
375 // --------------------------------------------------------------------------------------------
377 * Boot time bios area inits
379 ASM_START
380 init_bios_area:
381 push ds
382 mov ax, #biosmem_seg
383 mov ds, ax
385 ;; init detected hardware BIOS Area
386 mov bx, #biosmem_initial_mode
387 mov ax, [bx]
388 and ax, #0xffcf
389 mov [bx], ax
391 ;; Just for the first int10 find its children
393 ;; the default char height
394 mov bx, #biosmem_char_height
395 mov al, #0x10
396 mov [bx], al
398 ;; Clear the screen
399 mov bx, #biosmem_video_ctl
400 mov al, #0x60
401 mov [bx], al
403 ;; Set the basic screen we have
404 mov bx, #biosmem_switches
405 mov al, #0xf9
406 mov [bx], al
408 ;; Set the basic modeset options
409 mov bx, #biosmem_modeset_ctl
410 mov al, #0x51
411 mov [bx], al
413 ;; Set the default MSR
414 mov bx, #biosmem_current_msr
415 mov al, #0x09
416 mov [bx], al
418 pop ds
420 ASM_END
422 // --------------------------------------------------------------------------------------------
424 * Boot time Splash screen
426 static void display_splash_screen()
430 // --------------------------------------------------------------------------------------------
432 * Tell who we are
435 static void display_info()
437 ASM_START
438 mov ax,#0xc000
439 mov ds,ax
440 mov si,#vgabios_name
441 call _display_string
442 mov si,#vgabios_version
443 call _display_string
445 ;;mov si,#vgabios_copyright
446 ;;call _display_string
447 ;;mov si,#crlf
448 ;;call _display_string
450 mov si,#vgabios_license
451 call _display_string
452 mov si,#vgabios_website
453 call _display_string
454 ASM_END
457 static void display_string()
459 // Get length of string
460 ASM_START
461 mov ax,ds
462 mov es,ax
463 mov di,si
464 xor cx,cx
465 not cx
466 xor al,al
468 repne
469 scasb
470 not cx
471 dec cx
472 push cx
474 mov ax,#0x0300
475 mov bx,#0x0000
476 int #0x10
478 pop cx
479 mov ax,#0x1301
480 mov bx,#0x000b
481 mov bp,si
482 int #0x10
483 ASM_END
486 // --------------------------------------------------------------------------------------------
487 #ifdef DEBUG
488 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
489 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
491 // 0E is write char...
492 if(GET_AH()!=0x0E)
493 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
495 #endif
497 // --------------------------------------------------------------------------------------------
499 * int10 main dispatcher
501 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
502 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
505 // BIOS functions
506 switch(GET_AH())
508 case 0x00:
509 biosfn_set_video_mode(GET_AL());
510 switch(GET_AL()&0x7F)
511 {case 6:
512 SET_AL(0x3F);
513 break;
514 case 0:
515 case 1:
516 case 2:
517 case 3:
518 case 4:
519 case 5:
520 case 7:
521 SET_AL(0x30);
522 break;
523 default:
524 SET_AL(0x20);
526 break;
527 case 0x01:
528 biosfn_set_cursor_shape(GET_CH(),GET_CL());
529 break;
530 case 0x02:
531 biosfn_set_cursor_pos(GET_BH(),DX);
532 break;
533 case 0x03:
534 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
535 break;
536 case 0x04:
537 // Read light pen pos (unimplemented)
538 #ifdef DEBUG
539 unimplemented();
540 #endif
541 AX=0x00;
542 BX=0x00;
543 CX=0x00;
544 DX=0x00;
545 break;
546 case 0x05:
547 biosfn_set_active_page(GET_AL());
548 break;
549 case 0x06:
550 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
551 break;
552 case 0x07:
553 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
554 break;
555 case 0x08:
556 biosfn_read_char_attr(GET_BH(),&AX);
557 break;
558 case 0x09:
559 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
560 break;
561 case 0x0A:
562 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
563 break;
564 case 0x0C:
565 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
566 break;
567 case 0x0D:
568 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
569 break;
570 case 0x0E:
571 // Ralf Brown Interrupt list is WRONG on bh(page)
572 // We do output only on the current page !
573 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
574 break;
575 case 0x10:
576 // All other functions of group AH=0x10 rewritten in assembler
577 biosfn_perform_gray_scale_summing(BX,CX);
578 break;
579 case 0x11:
580 switch(GET_AL())
582 case 0x00:
583 case 0x10:
584 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
585 break;
586 case 0x01:
587 case 0x11:
588 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
589 break;
590 case 0x02:
591 case 0x12:
592 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
593 break;
594 case 0x04:
595 case 0x14:
596 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
597 break;
598 case 0x20:
599 biosfn_load_gfx_8_8_chars(ES,BP);
600 break;
601 case 0x21:
602 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
603 break;
604 case 0x22:
605 biosfn_load_gfx_8_14_chars(GET_BL());
606 break;
607 case 0x23:
608 biosfn_load_gfx_8_8_dd_chars(GET_BL());
609 break;
610 case 0x24:
611 biosfn_load_gfx_8_16_chars(GET_BL());
612 break;
613 case 0x30:
614 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
615 break;
616 #ifdef DEBUG
617 default:
618 unknown();
619 #endif
622 break;
623 case 0x12:
624 switch(GET_BL())
626 case 0x10:
627 biosfn_get_ega_info(&BX,&CX);
628 break;
629 case 0x20:
630 biosfn_alternate_prtsc();
631 break;
632 case 0x30:
633 biosfn_select_vert_res(GET_AL());
634 SET_AL(0x12);
635 break;
636 case 0x34:
637 biosfn_enable_cursor_emulation(GET_AL());
638 SET_AL(0x12);
639 break;
640 case 0x35:
641 biosfn_switch_video_interface(GET_AL(),ES,DX);
642 SET_AL(0x12);
643 break;
644 case 0x36:
645 biosfn_enable_video_refresh_control(GET_AL());
646 SET_AL(0x12);
647 break;
648 #ifdef DEBUG
649 default:
650 unknown();
651 #endif
653 break;
654 case 0x13:
655 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
656 break;
657 case 0x1B:
658 biosfn_read_state_info(BX,ES,DI);
659 SET_AL(0x1B);
660 break;
661 case 0x1C:
662 switch(GET_AL())
664 case 0x00:
665 biosfn_read_video_state_size(CX,&BX);
666 break;
667 case 0x01:
668 biosfn_save_video_state(CX,ES,BX);
669 break;
670 case 0x02:
671 biosfn_restore_video_state(CX,ES,BX);
672 break;
673 #ifdef DEBUG
674 default:
675 unknown();
676 #endif
678 SET_AL(0x1C);
679 break;
681 #ifdef VBE
682 case 0x4f:
683 if (vbe_has_vbe_display()) {
684 switch(GET_AL())
686 case 0x00:
687 vbe_biosfn_return_controller_information(&AX,ES,DI);
688 break;
689 case 0x01:
690 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
691 break;
692 case 0x02:
693 vbe_biosfn_set_mode(&AX,BX,ES,DI);
694 break;
695 case 0x03:
696 vbe_biosfn_return_current_mode(&AX,&BX);
697 break;
698 case 0x04:
699 //FIXME
700 #ifdef DEBUG
701 unimplemented();
702 #endif
703 // function failed
704 AX=0x100;
705 break;
706 case 0x05:
707 vbe_biosfn_display_window_control(&AX,BX,&DX);
708 break;
709 case 0x06:
710 vbe_biosfn_set_get_logical_scan_line_length(&AX,&BX,&CX,&DX);
711 break;
712 case 0x07:
713 vbe_biosfn_set_get_display_start(&AX,BX,CX,DX);
714 break;
715 case 0x08:
716 //FIXME
717 #ifdef DEBUG
718 unimplemented();
719 #endif
720 // function failed
721 AX=0x100;
722 break;
723 case 0x09:
724 //FIXME
725 #ifdef DEBUG
726 unimplemented();
727 #endif
728 // function failed
729 AX=0x100;
730 break;
731 case 0x0A:
732 //FIXME
733 #ifdef DEBUG
734 unimplemented();
735 #endif
736 // function failed
737 AX=0x100;
738 break;
739 #ifdef DEBUG
740 default:
741 unknown();
742 #endif
743 // function failed
744 AX=0x100;
747 else {
748 // No VBE display
749 AX=0x0100;
751 break;
752 #endif
754 #ifdef DEBUG
755 default:
756 unknown();
757 #endif
761 // ============================================================================================
763 // BIOS functions
765 // ============================================================================================
767 static void biosfn_set_video_mode(mode) Bit8u mode;
768 {// mode: Bit 7 is 1 if no clear screen
770 // Should we clear the screen ?
771 Bit8u noclearmem=mode&0x80;
772 Bit8u line,mmask,*palette;
773 Bit16u i,twidth,theight,cheight;
774 Bit8u modeset_ctl,video_ctl,vga_switches;
775 Bit16u crtc_addr;
777 #ifdef VBE
778 if (vbe_has_vbe_display()) {
779 dispi_set_enable(VBE_DISPI_DISABLED);
781 #endif // def VBE
783 // The real mode
784 mode=mode&0x7f;
786 // find the entry in the video modes
787 line=find_vga_entry(mode);
789 #ifdef DEBUG
790 printf("mode search %02x found line %02x\n",mode,line);
791 #endif
793 if(line==0xFF)
794 return;
796 twidth=vga_modes[line].twidth;
797 theight=vga_modes[line].theight;
798 cheight=vga_modes[line].cheight;
800 // Read the bios vga control
801 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
803 // Read the bios vga switches
804 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
806 // Read the bios mode set control
807 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
809 // Then we know the number of lines
810 // FIXME
812 // if palette loading (bit 3 of modeset ctl = 0)
813 if((modeset_ctl&0x08)==0)
814 {// Set the PEL mask
815 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
817 // Set the whole dac always, from 0
818 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
820 // From which palette
821 switch(vga_modes[line].dacmodel)
822 {case 0:
823 palette=&palette0;
824 break;
825 case 1:
826 palette=&palette1;
827 break;
828 case 2:
829 palette=&palette2;
830 break;
831 case 3:
832 palette=&palette3;
833 break;
835 // Always 256*3 values
836 for(i=0;i<0x0100;i++)
837 {if(i<=dac_regs[vga_modes[line].dacmodel])
838 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
839 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
840 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
842 else
843 {outb(VGAREG_DAC_DATA,0);
844 outb(VGAREG_DAC_DATA,0);
845 outb(VGAREG_DAC_DATA,0);
848 if((modeset_ctl&0x02)==0x02)
850 biosfn_perform_gray_scale_summing(0x00, 0x100);
854 // Reset Attribute Ctl flip-flop
855 inb(VGAREG_ACTL_RESET);
857 // Set Attribute Ctl
858 for(i=0;i<=ACTL_MAX_REG;i++)
859 {outb(VGAREG_ACTL_ADDRESS,i);
860 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
863 // Set Sequencer Ctl
864 for(i=0;i<=SEQU_MAX_REG;i++)
865 {outb(VGAREG_SEQU_ADDRESS,i);
866 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
869 // Set Grafx Ctl
870 for(i=0;i<=GRDC_MAX_REG;i++)
871 {outb(VGAREG_GRDC_ADDRESS,i);
872 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
875 // Set CRTC address VGA or MDA
876 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
878 // Set CRTC regs
879 for(i=0;i<=CRTC_MAX_REG;i++)
880 {outb(crtc_addr,i);
881 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
884 // Set the misc register
885 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
887 // Enable video
888 outb(VGAREG_ACTL_ADDRESS,0x20);
889 inb(VGAREG_ACTL_RESET);
891 if(noclearmem==0x00)
893 if(vga_modes[line].class==TEXT)
895 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
897 else
899 if(mode<0x0d)
901 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
903 else
905 outb( VGAREG_SEQU_ADDRESS, 0x02 );
906 mmask = inb( VGAREG_SEQU_DATA );
907 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
908 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
909 outb( VGAREG_SEQU_DATA, mmask );
914 // Set the BIOS mem
915 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
916 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
917 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
918 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
919 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
920 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
921 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
922 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
923 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
925 // FIXME We nearly have the good tables. to be reworked
926 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
927 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
928 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
930 // FIXME
931 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
932 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
934 // Set cursor shape
935 if(vga_modes[line].class==TEXT)
937 biosfn_set_cursor_shape(0x06,0x07);
940 // Set cursor pos for page 0..7
941 for(i=0;i<8;i++)
942 biosfn_set_cursor_pos(i,0x0000);
944 // Set active page 0
945 biosfn_set_active_page(0x00);
947 // Write the fonts in memory
948 if(vga_modes[line].class==TEXT)
950 ASM_START
951 ;; copy and activate 8x16 font
952 mov ax, #0x1104
953 mov bl, #0x00
954 int #0x10
955 mov ax, #0x1103
956 mov bl, #0x00
957 int #0x10
958 ASM_END
961 // Set the ints 0x1F and 0x43
962 ASM_START
963 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
964 ASM_END
966 switch(cheight)
967 {case 8:
968 ASM_START
969 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
970 ASM_END
971 break;
972 case 14:
973 ASM_START
974 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
975 ASM_END
976 break;
977 case 16:
978 ASM_START
979 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
980 ASM_END
981 break;
985 // --------------------------------------------------------------------------------------------
986 static void biosfn_set_cursor_shape (CH,CL)
987 Bit8u CH;Bit8u CL;
988 {Bit16u cheight,curs,crtc_addr;
990 CH&=0x3f;
991 CL&=0x1f;
993 curs=(CH<<8)+CL;
994 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
996 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
997 if((cheight>8) && (CL<8) && (CH<0x20))
999 if(CL!=(CH+1))
1001 CH = ((CH+1) * cheight / 8) -1;
1003 else
1005 CH = ((CL+1) * cheight / 8) - 2;
1007 CL = ((CL+1) * cheight / 8) - 1;
1010 // CTRC regs 0x0a and 0x0b
1011 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1012 outb(crtc_addr,0x0a);
1013 outb(crtc_addr+1,CH);
1014 outb(crtc_addr,0x0b);
1015 outb(crtc_addr+1,CL);
1018 // --------------------------------------------------------------------------------------------
1019 static void biosfn_set_cursor_pos (page, cursor)
1020 Bit8u page;Bit16u cursor;
1022 Bit8u xcurs,ycurs,current;
1023 Bit16u nbcols,nbrows,address,crtc_addr;
1025 // Should not happen...
1026 if(page>7)return;
1028 // Bios cursor pos
1029 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1031 // Set the hardware cursor
1032 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1033 if(page==current)
1035 // Get the dimensions
1036 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1037 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1039 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1041 // Calculate the address knowing nbcols nbrows and page num
1042 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1044 // CRTC regs 0x0e and 0x0f
1045 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1046 outb(crtc_addr,0x0e);
1047 outb(crtc_addr+1,(address&0xff00)>>8);
1048 outb(crtc_addr,0x0f);
1049 outb(crtc_addr+1,address&0x00ff);
1053 // --------------------------------------------------------------------------------------------
1054 static void biosfn_get_cursor_pos (page,shape, pos)
1055 Bit8u page;Bit16u *shape;Bit16u *pos;
1057 Bit16u ss=get_SS();
1059 // Default
1060 write_word(ss, shape, 0);
1061 write_word(ss, pos, 0);
1063 if(page>7)return;
1064 // FIXME should handle VGA 14/16 lines
1065 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1066 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1069 // --------------------------------------------------------------------------------------------
1070 static void biosfn_set_active_page (page)
1071 Bit8u page;
1073 Bit16u cursor,dummy,crtc_addr;
1074 Bit16u nbcols,nbrows,address;
1075 Bit8u mode,line;
1077 if(page>7)return;
1079 // Get the mode
1080 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1081 line=find_vga_entry(mode);
1082 if(line==0xFF)return;
1084 // Get pos curs pos for the right page
1085 biosfn_get_cursor_pos(page,&dummy,&cursor);
1087 if(vga_modes[line].class==TEXT)
1089 // Get the dimensions
1090 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1091 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1093 // Calculate the address knowing nbcols nbrows and page num
1094 address=SCREEN_MEM_START(nbcols,nbrows,page);
1095 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1097 // Start address
1098 address=SCREEN_IO_START(nbcols,nbrows,page);
1100 else
1102 address = page*vga_modes[line].slength;
1105 // CRTC regs 0x0c and 0x0d
1106 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1107 outb(crtc_addr,0x0c);
1108 outb(crtc_addr+1,(address&0xff00)>>8);
1109 outb(crtc_addr,0x0d);
1110 outb(crtc_addr+1,address&0x00ff);
1112 // And change the BIOS page
1113 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1115 #ifdef DEBUG
1116 printf("Set active page %02x address %04x\n",page,address);
1117 #endif
1119 // Display the cursor, now the page is active
1120 biosfn_set_cursor_pos(page,cursor);
1123 // --------------------------------------------------------------------------------------------
1124 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1125 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1127 // page == 0xFF if current
1129 Bit8u mode,line;
1130 Bit16u nbcols,nbrows,i;
1131 Bit16u address;
1133 if(rul>rlr)return;
1134 if(cul>clr)return;
1136 // Get the mode
1137 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1138 line=find_vga_entry(mode);
1139 if(line==0xFF)return;
1141 // Get the dimensions
1142 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1143 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1145 // Get the current page
1146 if(page==0xFF)
1147 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1149 if(vga_modes[line].class==TEXT)
1151 // Compute the address
1152 address=SCREEN_MEM_START(nbcols,nbrows,page);
1153 #ifdef DEBUG
1154 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1155 #endif
1157 if(rlr>=nbrows)rlr=nbrows-1;
1158 if(clr>=nbcols)clr=nbcols-1;
1159 if(nblines>nbrows)nblines=0;
1161 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1163 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1165 else
1166 {// if Scroll up
1167 if(dir==SCROLL_UP)
1168 {for(i=rul;i<=rlr;i++)
1170 if((i+nblines>rlr)||(nblines==0))
1171 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1172 else
1173 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,clr-cul+1);
1176 else
1177 {for(i=rlr;i>=rul;i--)
1179 if((i<rul+nblines)||(nblines==0))
1180 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1181 else
1182 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,clr-cul+1);
1187 else
1189 // FIXME gfx mode
1190 #ifdef DEBUG
1191 printf("Scroll in graphics mode ");
1192 unimplemented();
1193 #endif
1197 // --------------------------------------------------------------------------------------------
1198 static void biosfn_read_char_attr (page,car)
1199 Bit8u page;Bit16u *car;
1200 {Bit16u ss=get_SS();
1201 Bit8u xcurs,ycurs,mode,line;
1202 Bit16u nbcols,nbrows,address;
1203 Bit16u cursor,dummy;
1205 // Get the mode
1206 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1207 line=find_vga_entry(mode);
1208 if(line==0xFF)return;
1210 // Get the cursor pos for the page
1211 biosfn_get_cursor_pos(page,&dummy,&cursor);
1212 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1214 // Get the dimensions
1215 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1216 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1218 if(vga_modes[line].class==TEXT)
1220 // Compute the address
1221 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1223 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1225 else
1227 // FIXME gfx mode
1228 #ifdef DEBUG
1229 unimplemented();
1230 #endif
1234 // --------------------------------------------------------------------------------------------
1235 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1236 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1238 Bit8u i,mmask;
1239 Bit8u *fdata;
1240 Bit16u addr,dest,src;
1242 switch(cheight)
1243 {case 14:
1244 fdata = &vgafont14;
1245 break;
1246 case 16:
1247 fdata = &vgafont16;
1248 break;
1249 default:
1250 fdata = &vgafont8;
1252 addr=xcurs+ycurs*cheight*nbcols;
1253 src = car * cheight;
1254 outb( VGAREG_SEQU_ADDRESS, 0x02 );
1255 mmask = inb( VGAREG_SEQU_DATA );
1256 for(i=0;i<cheight;i++)
1258 dest=addr+i*nbcols;
1259 outb( VGAREG_SEQU_DATA, 0x0f );
1260 write_byte(0xa000,dest,0x00);
1261 outb( VGAREG_SEQU_DATA, attr & 0x0f );
1262 write_byte(0xa000,dest,fdata[src+i]);
1264 outb( VGAREG_SEQU_DATA, mmask );
1267 // --------------------------------------------------------------------------------------------
1268 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1269 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1271 Bit8u i,j,mask,data;
1272 Bit8u *fdata;
1273 Bit16u addr,dest,src;
1275 fdata = &vgafont8;
1276 addr=(xcurs*bpp)+ycurs*320;
1277 src = car * 8;
1278 for(i=0;i<8;i++)
1280 dest=addr+(i>>1)*80;
1281 if (i & 1) dest += 0x2000;
1282 mask = 0x80;
1283 if (bpp == 1)
1285 if (attr & 0x80)
1287 data = read_byte(0xb800,dest);
1289 else
1291 data = 0x00;
1293 for(j=0;j<8;j++)
1295 if (fdata[src+i] & mask)
1297 if (attr & 0x80)
1299 data ^= (attr & 0x01) << (7-j);
1301 else
1303 data |= (attr & 0x01) << (7-j);
1306 mask >>= 1;
1308 write_byte(0xb800,dest,data);
1310 else
1312 while (mask > 0)
1314 if (attr & 0x80)
1316 data = read_byte(0xb800,dest);
1318 else
1320 data = 0x00;
1322 for(j=0;j<4;j++)
1324 if (fdata[src+i] & mask)
1326 if (attr & 0x80)
1328 data ^= (attr & 0x03) << ((3-j)*2);
1330 else
1332 data |= (attr & 0x03) << ((3-j)*2);
1335 mask >>= 1;
1337 write_byte(0xb800,dest,data);
1338 dest += 1;
1344 // --------------------------------------------------------------------------------------------
1345 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1346 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1348 Bit8u i,j,mask,data;
1349 Bit8u *fdata;
1350 Bit16u addr,dest,src;
1352 fdata = &vgafont8;
1353 addr=xcurs*8+ycurs*nbcols*64;
1354 src = car * 8;
1355 for(i=0;i<8;i++)
1357 dest=addr+i*nbcols*8;
1358 mask = 0x80;
1359 for(j=0;j<8;j++)
1361 data = 0x00;
1362 if (fdata[src+i] & mask)
1364 data = attr;
1366 write_byte(0xa000,dest+j,data);
1367 mask >>= 1;
1372 // --------------------------------------------------------------------------------------------
1373 static void biosfn_write_char_attr (car,page,attr,count)
1374 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1376 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1377 Bit16u nbcols,nbrows,address;
1378 Bit16u cursor,dummy;
1380 // Get the mode
1381 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1382 line=find_vga_entry(mode);
1383 if(line==0xFF)return;
1385 // Get the cursor pos for the page
1386 biosfn_get_cursor_pos(page,&dummy,&cursor);
1387 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1389 // Get the dimensions
1390 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1391 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1393 if(vga_modes[line].class==TEXT)
1395 // Compute the address
1396 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1398 dummy=((Bit16u)attr<<8)+car;
1399 memsetw(vga_modes[line].sstart,address,dummy,count);
1401 else
1403 // FIXME gfx mode not complete
1404 cheight=vga_modes[line].cheight;
1405 bpp=vga_modes[line].pixbits;
1406 while((count-->0) && (xcurs<nbcols))
1408 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1410 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1412 else if(vga_modes[line].memmodel==CGA)
1414 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1416 else if(vga_modes[line].memmodel==LINEAR8)
1418 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1420 else
1422 #ifdef DEBUG
1423 unimplemented();
1424 #endif
1426 xcurs++;
1431 // --------------------------------------------------------------------------------------------
1432 static void biosfn_write_char_only (car,page,attr,count)
1433 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1435 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1436 Bit16u nbcols,nbrows,address;
1437 Bit16u cursor,dummy;
1439 // Get the mode
1440 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1441 line=find_vga_entry(mode);
1442 if(line==0xFF)return;
1444 // Get the cursor pos for the page
1445 biosfn_get_cursor_pos(page,&dummy,&cursor);
1446 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1448 // Get the dimensions
1449 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1450 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1452 if(vga_modes[line].class==TEXT)
1454 // Compute the address
1455 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1457 while(count-->0)
1458 {write_byte(vga_modes[line].sstart,address,car);
1459 address+=2;
1462 else
1464 // FIXME gfx mode not complete
1465 cheight=vga_modes[line].cheight;
1466 bpp=vga_modes[line].pixbits;
1467 while((count-->0) && (xcurs<nbcols))
1469 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1471 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1473 else if(vga_modes[line].memmodel==CGA)
1475 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1477 else if(vga_modes[line].memmodel==LINEAR8)
1479 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1481 else
1483 #ifdef DEBUG
1484 unimplemented();
1485 #endif
1487 xcurs++;
1492 // --------------------------------------------------------------------------------------------
1493 ASM_START
1494 biosfn_group_0B:
1495 cmp bh, #0x00
1496 je biosfn_set_border_color
1497 cmp bh, #0x01
1498 je biosfn_set_palette
1499 #ifdef DEBUG
1500 call _unknown
1501 #endif
1503 biosfn_set_border_color:
1504 push ax
1505 push bx
1506 push cx
1507 push dx
1508 mov dx, #vgareg_actl_reset
1509 in al, dx
1510 mov dx, #vgareg_actl_address
1511 mov al, #0x00
1512 out dx, al
1513 mov al, bl
1514 and al, #0x0f
1515 test al, #0x08
1516 jz set_low_border
1517 add al, #0x08
1518 set_low_border:
1519 out dx, al
1520 mov cl, #0x01
1521 and bl, #0x10
1522 set_intensity_loop:
1523 mov dx, #vgareg_actl_address
1524 mov al, cl
1525 out dx, al
1526 mov dx, #vgareg_actl_read_data
1527 in al, dx
1528 and al, #0xef
1529 or al, bl
1530 mov dx, #vgareg_actl_address
1531 out dx, al
1532 inc cl
1533 cmp cl, #0x04
1534 jne set_intensity_loop
1535 mov al, #0x20
1536 out dx, al
1537 pop dx
1538 pop cx
1539 pop bx
1540 pop ax
1542 biosfn_set_palette:
1543 push ax
1544 push bx
1545 push cx
1546 push dx
1547 mov dx, #vgareg_actl_reset
1548 in al, dx
1549 mov cl, #0x01
1550 and bl, #0x01
1551 set_cga_palette_loop:
1552 mov dx, #vgareg_actl_address
1553 mov al, cl
1554 out dx, al
1555 mov dx, #vgareg_actl_read_data
1556 in al, dx
1557 and al, #0xfe
1558 or al, bl
1559 mov dx, #vgareg_actl_address
1560 out dx, al
1561 inc cl
1562 cmp cl, #0x04
1563 jne set_cga_palette_loop
1564 mov al, #0x20
1565 out dx, al
1566 pop dx
1567 pop cx
1568 pop bx
1569 pop ax
1571 ASM_END
1573 // --------------------------------------------------------------------------------------------
1574 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1576 Bit8u mode,line,mask,attr,data;
1577 Bit16u addr;
1579 // Get the mode
1580 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1581 line=find_vga_entry(mode);
1582 if(line==0xFF)return;
1583 if(vga_modes[line].class==TEXT)return;
1585 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1587 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1588 mask = 0x01 << (7 - (CX & 0x07));
1589 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1590 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1591 data = read_byte(0xa000,addr);
1592 if (AL & 0x80)
1594 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1596 write_byte(0xa000,addr,AL);
1597 outw(VGAREG_GRDC_ADDRESS, 0xff08);
1598 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1599 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1601 else if(vga_modes[line].memmodel==CGA)
1603 if(vga_modes[line].pixbits==2)
1605 addr=(CX>>2)+(DX>>1)*80;
1607 else
1609 addr=(CX>>3)+(DX>>1)*80;
1611 if (DX & 1) addr += 0x2000;
1612 data = read_byte(0xb800,addr);
1613 if(vga_modes[line].pixbits==2)
1615 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1616 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1618 else
1620 attr = (AL & 0x01) << (7 - (CX & 0x07));
1621 mask = 0x01 << (7 - (CX & 0x07));
1623 if (AL & 0x80)
1625 data ^= attr;
1627 else
1629 data &= ~mask;
1630 data |= attr;
1632 write_byte(0xb800,addr,data);
1634 else if(vga_modes[line].memmodel==LINEAR8)
1636 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1637 write_byte(0xa000,addr,AL);
1639 else
1641 #ifdef DEBUG
1642 unimplemented();
1643 #endif
1647 // --------------------------------------------------------------------------------------------
1648 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1650 Bit8u mode,line,mask,attr,data,i;
1651 Bit16u addr;
1652 Bit16u ss=get_SS();
1654 // Get the mode
1655 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1656 line=find_vga_entry(mode);
1657 if(line==0xFF)return;
1658 if(vga_modes[line].class==TEXT)return;
1660 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1662 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1663 mask = 0x01 << (7 - (CX & 0x07));
1664 attr = 0x00;
1665 for(i=0;i<4;i++)
1667 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1668 data = read_byte(0xa000,addr) & mask;
1669 if (data > 0) attr |= (0x01 << i);
1672 else if(vga_modes[line].memmodel==CGA)
1674 addr=(CX>>2)+(DX>>1)*80;
1675 if (DX & 1) addr += 0x2000;
1676 data = read_byte(0xb800,addr);
1677 if(vga_modes[line].pixbits==2)
1679 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1681 else
1683 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1686 else if(vga_modes[line].memmodel==LINEAR8)
1688 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1689 attr=read_byte(0xa000,addr);
1691 else
1693 #ifdef DEBUG
1694 unimplemented();
1695 #endif
1696 attr = 0;
1698 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1701 // --------------------------------------------------------------------------------------------
1702 static void biosfn_write_teletype (car, page, attr, flag)
1703 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1704 {// flag = WITH_ATTR / NO_ATTR
1706 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1707 Bit16u nbcols,nbrows,address;
1708 Bit16u cursor,dummy;
1710 // special case if page is 0xff, use current page
1711 if(page==0xff)
1712 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1714 // FIXME gfx mode
1716 // Get the mode
1717 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1718 line=find_vga_entry(mode);
1719 if(line==0xFF)return;
1721 // Get the cursor pos for the page
1722 biosfn_get_cursor_pos(page,&dummy,&cursor);
1723 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1725 // Get the dimensions
1726 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1727 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1729 switch(car)
1731 case 7:
1732 //FIXME should beep
1733 break;
1735 case 8:
1736 if(xcurs>0)xcurs--;
1737 break;
1739 case '\r':
1740 xcurs=0;
1741 break;
1743 case '\n':
1744 xcurs=0;
1745 ycurs++;
1746 break;
1748 case '\t':
1751 biosfn_write_teletype(' ',page,attr,flag);
1752 biosfn_get_cursor_pos(page,&dummy,&cursor);
1753 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1754 }while(xcurs%8==0);
1755 break;
1757 default:
1759 if(vga_modes[line].class==TEXT)
1761 // Compute the address
1762 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1764 // Write the char
1765 write_byte(vga_modes[line].sstart,address,car);
1767 if(flag==WITH_ATTR)
1768 write_byte(vga_modes[line].sstart,address+1,attr);
1770 else
1772 // FIXME gfx mode not complete
1773 cheight=vga_modes[line].cheight;
1774 bpp=vga_modes[line].pixbits;
1775 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1777 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1779 else if(vga_modes[line].memmodel==CGA)
1781 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1783 else if(vga_modes[line].memmodel==LINEAR8)
1785 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1787 else
1789 #ifdef DEBUG
1790 unimplemented();
1791 #endif
1795 xcurs++;
1798 // Do we need to wrap ?
1799 if(xcurs==nbcols)
1800 {xcurs=0;
1801 ycurs++;
1804 // Do we need to scroll ?
1805 if(ycurs==nbrows)
1806 {biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1807 ycurs-=1;
1810 // Set the cursor for the page
1811 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1812 biosfn_set_cursor_pos(page,cursor);
1815 // --------------------------------------------------------------------------------------------
1816 ASM_START
1817 biosfn_get_video_mode:
1818 push ds
1819 mov ax, #biosmem_seg
1820 mov ds, ax
1821 push bx
1822 mov bx, #biosmem_current_page
1823 mov al, [bx]
1824 pop bx
1825 mov bh, al
1826 push bx
1827 mov bx, #biosmem_video_ctl
1828 mov ah, [bx]
1829 and ah, #0x80
1830 mov bx, #biosmem_current_mode
1831 mov al, [bx]
1832 or al, ah
1833 mov bx, #biosmem_nb_cols
1834 mov ah, [bx]
1835 pop bx
1836 pop ds
1838 ASM_END
1840 // --------------------------------------------------------------------------------------------
1841 ASM_START
1842 biosfn_group_10:
1843 cmp al, #0x00
1844 jne int10_test_1001
1845 jmp biosfn_set_single_palette_reg
1846 int10_test_1001:
1847 cmp al, #0x01
1848 jne int10_test_1002
1849 jmp biosfn_set_overscan_border_color
1850 int10_test_1002:
1851 cmp al, #0x02
1852 jne int10_test_1003
1853 jmp biosfn_set_all_palette_reg
1854 int10_test_1003:
1855 cmp al, #0x03
1856 jne int10_test_1007
1857 jmp biosfn_toggle_intensity
1858 int10_test_1007:
1859 cmp al, #0x07
1860 jne int10_test_1008
1861 jmp biosfn_get_single_palette_reg
1862 int10_test_1008:
1863 cmp al, #0x08
1864 jne int10_test_1009
1865 jmp biosfn_read_overscan_border_color
1866 int10_test_1009:
1867 cmp al, #0x09
1868 jne int10_test_1010
1869 jmp biosfn_get_all_palette_reg
1870 int10_test_1010:
1871 cmp al, #0x10
1872 jne int10_test_1012
1873 jmp biosfn_set_single_dac_reg
1874 int10_test_1012:
1875 cmp al, #0x12
1876 jne int10_test_1013
1877 jmp biosfn_set_all_dac_reg
1878 int10_test_1013:
1879 cmp al, #0x13
1880 jne int10_test_1015
1881 jmp biosfn_select_video_dac_color_page
1882 int10_test_1015:
1883 cmp al, #0x15
1884 jne int10_test_1017
1885 jmp biosfn_read_single_dac_reg
1886 int10_test_1017:
1887 cmp al, #0x17
1888 jne int10_test_1018
1889 jmp biosfn_read_all_dac_reg
1890 int10_test_1018:
1891 cmp al, #0x18
1892 jne int10_test_1019
1893 jmp biosfn_set_pel_mask
1894 int10_test_1019:
1895 cmp al, #0x19
1896 jne int10_test_101A
1897 jmp biosfn_read_pel_mask
1898 int10_test_101A:
1899 cmp al, #0x1a
1900 jne int10_group_10_unknown
1901 jmp biosfn_read_video_dac_state
1902 int10_group_10_unknown:
1903 #ifdef DEBUG
1904 call _unknown
1905 #endif
1908 biosfn_set_single_palette_reg:
1909 cmp bl, #0x14
1910 ja no_actl_reg1
1911 push ax
1912 push dx
1913 mov dx, #vgareg_actl_reset
1914 in al, dx
1915 mov dx, #vgareg_actl_address
1916 mov al, bl
1917 out dx, al
1918 mov al, bh
1919 out dx, al
1920 mov al, #0x20
1921 out dx, al
1922 pop dx
1923 pop ax
1924 no_actl_reg1:
1926 ASM_END
1928 // --------------------------------------------------------------------------------------------
1929 ASM_START
1930 biosfn_set_overscan_border_color:
1931 push bx
1932 mov bl, #0x11
1933 call biosfn_set_single_palette_reg
1934 pop bx
1936 ASM_END
1938 // --------------------------------------------------------------------------------------------
1939 ASM_START
1940 biosfn_set_all_palette_reg:
1941 push ax
1942 push bx
1943 push cx
1944 push dx
1945 mov bx, dx
1946 mov dx, #vgareg_actl_reset
1947 in al, dx
1948 mov cl, #0x00
1949 mov dx, #vgareg_actl_address
1950 set_palette_loop:
1951 mov al, cl
1952 out dx, al
1953 seg es
1954 mov al, [bx]
1955 out dx, al
1956 inc bx
1957 inc cl
1958 cmp cl, #0x10
1959 jne set_palette_loop
1960 mov al, #0x11
1961 out dx, al
1962 seg es
1963 mov al, [bx]
1964 out dx, al
1965 mov al, #0x20
1966 out dx, al
1967 pop dx
1968 pop cx
1969 pop bx
1970 pop ax
1972 ASM_END
1974 // --------------------------------------------------------------------------------------------
1975 ASM_START
1976 biosfn_toggle_intensity:
1977 push ax
1978 push bx
1979 push dx
1980 mov dx, #vgareg_actl_reset
1981 in al, dx
1982 mov dx, #vgareg_actl_address
1983 mov al, #0x10
1984 out dx, al
1985 mov dx, #vgareg_actl_read_data
1986 in al, dx
1987 and al, #0xf7
1988 and bl, #0x01
1989 shl bl, 3
1990 or al, bl
1991 mov dx, #vgareg_actl_address
1992 out dx, al
1993 mov al, #0x20
1994 out dx, al
1995 pop dx
1996 pop bx
1997 pop ax
1999 ASM_END
2001 // --------------------------------------------------------------------------------------------
2002 ASM_START
2003 biosfn_get_single_palette_reg:
2004 cmp bl, #0x14
2005 ja no_actl_reg2
2006 push ax
2007 push dx
2008 mov dx, #vgareg_actl_reset
2009 in al, dx
2010 mov dx, #vgareg_actl_address
2011 mov al, bl
2012 out dx, al
2013 mov dx, #vgareg_actl_read_data
2014 in al, dx
2015 mov bh, al
2016 mov dx, #vgareg_actl_reset
2017 in al, dx
2018 mov dx, #vgareg_actl_address
2019 mov al, #0x20
2020 out dx, al
2021 pop dx
2022 pop ax
2023 no_actl_reg2:
2025 ASM_END
2027 // --------------------------------------------------------------------------------------------
2028 ASM_START
2029 biosfn_read_overscan_border_color:
2030 push ax
2031 push bx
2032 mov bl, #0x11
2033 call biosfn_get_single_palette_reg
2034 mov al, bh
2035 pop bx
2036 mov bh, al
2037 pop ax
2039 ASM_END
2041 // --------------------------------------------------------------------------------------------
2042 ASM_START
2043 biosfn_get_all_palette_reg:
2044 push ax
2045 push bx
2046 push cx
2047 push dx
2048 mov bx, dx
2049 mov cl, #0x00
2050 get_palette_loop:
2051 mov dx, #vgareg_actl_reset
2052 in al, dx
2053 mov dx, #vgareg_actl_address
2054 mov al, cl
2055 out dx, al
2056 mov dx, #vgareg_actl_read_data
2057 in al, dx
2058 seg es
2059 mov [bx], al
2060 inc bx
2061 inc cl
2062 cmp cl, #0x10
2063 jne get_palette_loop
2064 mov dx, #vgareg_actl_reset
2065 in al, dx
2066 mov dx, #vgareg_actl_address
2067 mov al, #0x11
2068 out dx, al
2069 mov dx, #vgareg_actl_read_data
2070 in al, dx
2071 seg es
2072 mov [bx], al
2073 mov dx, #vgareg_actl_reset
2074 in al, dx
2075 mov dx, #vgareg_actl_address
2076 mov al, #0x20
2077 out dx, al
2078 pop dx
2079 pop cx
2080 pop bx
2081 pop ax
2083 ASM_END
2085 // --------------------------------------------------------------------------------------------
2086 ASM_START
2087 biosfn_set_single_dac_reg:
2088 push ax
2089 push dx
2090 mov dx, #vgareg_dac_write_address
2091 mov al, bl
2092 out dx, al
2093 mov dx, #vgareg_dac_data
2094 pop ax
2095 push ax
2096 mov al, ah
2097 out dx, al
2098 mov al, ch
2099 out dx, al
2100 mov al, cl
2101 out dx, al
2102 pop dx
2103 pop ax
2105 ASM_END
2107 // --------------------------------------------------------------------------------------------
2108 ASM_START
2109 biosfn_set_all_dac_reg:
2110 push ax
2111 push bx
2112 push cx
2113 push dx
2114 mov dx, #vgareg_dac_write_address
2115 mov al, bl
2116 out dx, al
2117 pop dx
2118 push dx
2119 mov bx, dx
2120 mov dx, #vgareg_dac_data
2121 set_dac_loop:
2122 seg es
2123 mov al, [bx]
2124 out dx, al
2125 inc bx
2126 seg es
2127 mov al, [bx]
2128 out dx, al
2129 inc bx
2130 seg es
2131 mov al, [bx]
2132 out dx, al
2133 inc bx
2134 dec cx
2135 jnz set_dac_loop
2136 pop dx
2137 pop cx
2138 pop bx
2139 pop ax
2141 ASM_END
2143 // --------------------------------------------------------------------------------------------
2144 ASM_START
2145 biosfn_select_video_dac_color_page:
2146 push ax
2147 push bx
2148 push dx
2149 mov dx, #vgareg_actl_reset
2150 in al, dx
2151 mov dx, #vgareg_actl_address
2152 mov al, #0x10
2153 out dx, al
2154 mov dx, #vgareg_actl_read_data
2155 in al, dx
2156 and bl, #0x01
2157 jnz set_dac_page
2158 and al, #0x7f
2159 shl bh, 7
2160 or al, bh
2161 mov dx, #vgareg_actl_address
2162 out dx, al
2163 jmp set_actl_normal
2164 set_dac_page:
2165 push ax
2166 mov dx, #vgareg_actl_reset
2167 in al, dx
2168 mov dx, #vgareg_actl_address
2169 mov al, #0x14
2170 out dx, al
2171 pop ax
2172 and al, #0x80
2173 jnz set_dac_16_page
2174 shl bh, 2
2175 set_dac_16_page:
2176 and bh, #0x0f
2177 mov al, bh
2178 out dx, al
2179 set_actl_normal:
2180 mov al, #0x20
2181 out dx, al
2182 pop dx
2183 pop bx
2184 pop ax
2186 ASM_END
2188 // --------------------------------------------------------------------------------------------
2189 ASM_START
2190 biosfn_read_single_dac_reg:
2191 push ax
2192 push dx
2193 mov dx, #vgareg_dac_read_address
2194 mov al, bl
2195 out dx, al
2196 pop ax
2197 mov ah, al
2198 mov dx, #vgareg_dac_data
2199 in al, dx
2200 xchg al, ah
2201 push ax
2202 in al, dx
2203 mov ch, al
2204 in al, dx
2205 mov cl, al
2206 pop dx
2207 pop ax
2209 ASM_END
2211 // --------------------------------------------------------------------------------------------
2212 ASM_START
2213 biosfn_read_all_dac_reg:
2214 push ax
2215 push bx
2216 push cx
2217 push dx
2218 mov dx, #vgareg_dac_read_address
2219 mov al, bl
2220 out dx, al
2221 pop dx
2222 push dx
2223 mov bx, dx
2224 mov dx, #vgareg_dac_data
2225 read_dac_loop:
2226 in al, dx
2227 seg es
2228 mov [bx], al
2229 inc bx
2230 in al, dx
2231 seg es
2232 mov [bx], al
2233 inc bx
2234 in al, dx
2235 seg es
2236 mov [bx], al
2237 inc bx
2238 dec cx
2239 jnz read_dac_loop
2240 pop dx
2241 pop cx
2242 pop bx
2243 pop ax
2245 ASM_END
2247 // --------------------------------------------------------------------------------------------
2248 ASM_START
2249 biosfn_set_pel_mask:
2250 push ax
2251 push dx
2252 mov dx, #vgareg_pel_mask
2253 mov al, bl
2254 out dx, al
2255 pop dx
2256 pop ax
2258 ASM_END
2260 // --------------------------------------------------------------------------------------------
2261 ASM_START
2262 biosfn_read_pel_mask:
2263 push ax
2264 push dx
2265 mov dx, #vgareg_pel_mask
2266 in al, dx
2267 mov bl, al
2268 pop dx
2269 pop ax
2271 ASM_END
2273 // --------------------------------------------------------------------------------------------
2274 ASM_START
2275 biosfn_read_video_dac_state:
2276 push ax
2277 push dx
2278 mov dx, #vgareg_actl_reset
2279 in al, dx
2280 mov dx, #vgareg_actl_address
2281 mov al, #0x10
2282 out dx, al
2283 mov dx, #vgareg_actl_read_data
2284 in al, dx
2285 mov bl, al
2286 shr bl, 7
2287 mov dx, #vgareg_actl_reset
2288 in al, dx
2289 mov dx, #vgareg_actl_address
2290 mov al, #0x14
2291 out dx, al
2292 mov dx, #vgareg_actl_read_data
2293 in al, dx
2294 mov bh, al
2295 and bh, #0x0f
2296 test bl, #0x01
2297 jnz get_dac_16_page
2298 shr bh, 2
2299 get_dac_16_page:
2300 mov dx, #vgareg_actl_reset
2301 in al, dx
2302 mov dx, #vgareg_actl_address
2303 mov al, #0x20
2304 out dx, al
2305 pop dx
2306 pop ax
2308 ASM_END
2310 // --------------------------------------------------------------------------------------------
2311 static void biosfn_perform_gray_scale_summing (start,count)
2312 Bit16u start;Bit16u count;
2313 {Bit8u r,g,b;
2314 Bit16u i;
2315 Bit16u index;
2317 inb(VGAREG_ACTL_RESET);
2318 outb(VGAREG_ACTL_ADDRESS,0x00);
2320 for( index = 0; index < count; index++ )
2322 // set read address and switch to read mode
2323 outb(VGAREG_DAC_READ_ADDRESS,start);
2324 // get 6-bit wide RGB data values
2325 r=inb( VGAREG_DAC_DATA );
2326 g=inb( VGAREG_DAC_DATA );
2327 b=inb( VGAREG_DAC_DATA );
2329 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2330 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2332 if(i>0x3f)i=0x3f;
2334 // set write address and switch to write mode
2335 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2336 // write new intensity value
2337 outb( VGAREG_DAC_DATA, i&0xff );
2338 outb( VGAREG_DAC_DATA, i&0xff );
2339 outb( VGAREG_DAC_DATA, i&0xff );
2340 start++;
2342 inb(VGAREG_ACTL_RESET);
2343 outb(VGAREG_ACTL_ADDRESS,0x20);
2346 // --------------------------------------------------------------------------------------------
2347 static void get_font_access()
2349 ASM_START
2350 mov dx, #vgareg_sequ_address
2351 mov ax, #0x0100
2352 out dx, ax
2353 mov ax, #0x0402
2354 out dx, ax
2355 mov ax, #0x0704
2356 out dx, ax
2357 mov ax, #0x0300
2358 out dx, ax
2359 mov dx, #vgareg_grdc_address
2360 mov ax, #0x0204
2361 out dx, ax
2362 mov ax, #0x0005
2363 out dx, ax
2364 mov ax, #0x0406
2365 out dx, ax
2366 ASM_END
2369 static void release_font_access()
2371 ASM_START
2372 mov dx, #vgareg_sequ_address
2373 mov ax, #0x0100
2374 out dx, ax
2375 mov ax, #0x0302
2376 out dx, ax
2377 mov ax, #0x0304
2378 out dx, ax
2379 mov ax, #0x0300
2380 out dx, ax
2381 mov dx, #vgareg_read_misc_output
2382 in al, dx
2383 and al, #0x01
2384 shl al, 2
2385 or al, #0x0a
2386 mov ah, al
2387 mov al, #0x06
2388 mov dx, #vgareg_grdc_address
2389 out dx, ax
2390 mov ax, #0x0004
2391 out dx, ax
2392 mov ax, #0x1005
2393 out dx, ax
2394 ASM_END
2397 ASM_START
2398 idiv_u:
2399 xor dx,dx
2400 div bx
2402 ASM_END
2404 static void set_scan_lines(lines) Bit8u lines;
2406 Bit16u crtc_addr,cols,page,vde;
2407 Bit8u crtc_r9,ovl,rows;
2409 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2410 outb(crtc_addr, 0x09);
2411 crtc_r9 = inb(crtc_addr+1);
2412 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2413 outb(crtc_addr+1, crtc_r9);
2414 if(lines==8)
2416 biosfn_set_cursor_shape(0x06,0x07);
2418 else
2420 biosfn_set_cursor_shape(lines-4,lines-3);
2422 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2423 outb(crtc_addr, 0x12);
2424 vde = inb(crtc_addr+1);
2425 outb(crtc_addr, 0x07);
2426 ovl = inb(crtc_addr+1);
2427 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2428 rows = vde / lines;
2429 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2430 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2431 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2434 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;
2436 Bit16u blockaddr,dest,i,src;
2438 get_font_access();
2439 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2440 for(i=0;i<CX;i++)
2442 src = BP + i * BH;
2443 dest = blockaddr + (DX + i) * 32;
2444 memcpyb(0xA000, dest, ES, src, BH);
2446 release_font_access();
2447 if(AL>=0x10)
2449 set_scan_lines(BH);
2453 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2455 Bit16u blockaddr,dest,i,src;
2457 get_font_access();
2458 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2459 for(i=0;i<0x100;i++)
2461 src = i * 14;
2462 dest = blockaddr + i * 32;
2463 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2465 release_font_access();
2466 if(AL>=0x10)
2468 set_scan_lines(14);
2472 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2474 Bit16u blockaddr,dest,i,src;
2476 get_font_access();
2477 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2478 for(i=0;i<0x100;i++)
2480 src = i * 8;
2481 dest = blockaddr + i * 32;
2482 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2484 release_font_access();
2485 if(AL>=0x10)
2487 set_scan_lines(8);
2491 // --------------------------------------------------------------------------------------------
2492 ASM_START
2493 biosfn_set_text_block_specifier:
2494 push ax
2495 push dx
2496 mov dx, #vgareg_sequ_address
2497 mov ah, bl
2498 mov al, #0x03
2499 out dx, ax
2500 pop dx
2501 pop ax
2503 ASM_END
2505 // --------------------------------------------------------------------------------------------
2506 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2508 Bit16u blockaddr,dest,i,src;
2510 get_font_access();
2511 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2512 for(i=0;i<0x100;i++)
2514 src = i * 16;
2515 dest = blockaddr + i * 32;
2516 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2518 release_font_access();
2519 if(AL>=0x10)
2521 set_scan_lines(16);
2525 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2527 #ifdef DEBUG
2528 unimplemented();
2529 #endif
2531 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2533 #ifdef DEBUG
2534 unimplemented();
2535 #endif
2537 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2539 #ifdef DEBUG
2540 unimplemented();
2541 #endif
2543 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2545 #ifdef DEBUG
2546 unimplemented();
2547 #endif
2549 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2551 #ifdef DEBUG
2552 unimplemented();
2553 #endif
2555 // --------------------------------------------------------------------------------------------
2556 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2557 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2558 {Bit16u ss=get_SS();
2560 switch(BH)
2561 {case 0x00:
2562 write_word(ss,ES,read_word(0x00,0x1f*4));
2563 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2564 break;
2565 case 0x01:
2566 write_word(ss,ES,read_word(0x00,0x43*4));
2567 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2568 break;
2569 case 0x02:
2570 write_word(ss,ES,0xC000);
2571 write_word(ss,BP,vgafont14);
2572 break;
2573 case 0x03:
2574 write_word(ss,ES,0xC000);
2575 write_word(ss,BP,vgafont8);
2576 break;
2577 case 0x04:
2578 write_word(ss,ES,0xC000);
2579 write_word(ss,BP,vgafont8+128*8);
2580 break;
2581 case 0x05:
2582 write_word(ss,ES,0xC000);
2583 write_word(ss,BP,vgafont14alt);
2584 break;
2585 case 0x06:
2586 write_word(ss,ES,0xC000);
2587 write_word(ss,BP,vgafont16);
2588 break;
2589 case 0x07:
2590 write_word(ss,ES,0xC000);
2591 write_word(ss,BP,vgafont16alt);
2592 break;
2593 default:
2594 #ifdef DEBUG
2595 printf("Get font info BH(%02x) was discarded\n",BH);
2596 #endif
2597 return;
2599 // Set byte/char of on screen font
2600 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2602 // Set Highest char row
2603 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2606 // --------------------------------------------------------------------------------------------
2607 static void biosfn_get_ega_info (BX,CX)
2608 Bit16u *BX;Bit16u *CX;
2609 {Bit16u ss=get_SS();
2610 Bit16u crtc;
2611 Bit8u switches;
2613 crtc=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2614 if(crtc==VGAREG_MDA_CRTC_ADDRESS)
2615 write_word(ss,BX,(1<<8)+0x0003);
2616 else
2617 write_word(ss,BX,0x0003);
2619 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2620 write_word(ss,CX,(switches&0x0f));
2623 // --------------------------------------------------------------------------------------------
2624 static void biosfn_alternate_prtsc()
2626 #ifdef DEBUG
2627 unimplemented();
2628 #endif
2631 // --------------------------------------------------------------------------------------------
2632 static void biosfn_select_vert_res (res)
2633 Bit8u res;
2634 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2635 Bit8u modeset,switches;
2637 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2638 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2639 switch(res)
2640 {case 0x00:
2641 // set modeset ctl bit 7 and reset bit 4
2642 // set switches bit 3-0 to 0x08
2643 modeset|=0x80;modeset&=0xef;
2644 switches&=0xf0;switches|=0x08;
2645 break;
2646 case 0x01:
2647 // reset modeset ctl bit 7 and bit 4
2648 // set switches bit 3-0 to 0x09
2649 modeset&=0x6f;
2650 switches&=0xf0;switches|=0x09;
2651 break;
2652 case 0x02:
2653 // reset modeset ctl bit 7 and set bit 4
2654 // set switches bit 3-0 to 0x09
2655 modeset|=0x10;modeset&=0x7f;
2656 switches&=0xf0;switches|=0x09;
2657 break;
2658 default:
2659 #ifdef DEBUG
2660 printf("Select vert res (%02x) was discarded\n",res);
2661 #endif
2662 return;
2664 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2665 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2668 // --------------------------------------------------------------------------------------------
2669 ASM_START
2670 biosfn_enable_default_palette_loading:
2671 push ds
2672 push bx
2673 push dx
2674 mov dl, al
2675 and dl, #0x01
2676 shl dl, 3
2677 mov ax, #biosmem_seg
2678 mov ds, ax
2679 mov bx, #biosmem_modeset_ctl
2680 mov al, [bx]
2681 and al, #0xf7
2682 or al, dl
2683 mov [bx], al
2684 mov ax, #0x1212
2685 pop dx
2686 pop bx
2687 pop ds
2689 ASM_END
2691 // --------------------------------------------------------------------------------------------
2692 ASM_START
2693 biosfn_enable_video_addressing:
2694 push bx
2695 push dx
2696 mov bl, al
2697 and bl, #0x01
2698 xor bl, #0x01
2699 shl bl, 1
2700 mov dx, #vgareg_read_misc_output
2701 in al, dx
2702 and al, #0xfd
2703 or al, bl
2704 mov dx, #vgareg_write_misc_output
2705 out dx, al
2706 mov ax, #0x1212
2707 pop dx
2708 pop bx
2710 ASM_END
2712 // --------------------------------------------------------------------------------------------
2713 ASM_START
2714 biosfn_enable_grayscale_summing:
2715 push ds
2716 push bx
2717 push dx
2718 mov dl, al
2719 and dl, #0x01
2720 xor dl, #0x01
2721 shl dl, 1
2722 mov ax, #biosmem_seg
2723 mov ds, ax
2724 mov bx, #biosmem_modeset_ctl
2725 mov al, [bx]
2726 and al, #0xfd
2727 or al, dl
2728 mov [bx], al
2729 mov ax, #0x1212
2730 pop dx
2731 pop bx
2732 pop ds
2734 ASM_END
2736 // --------------------------------------------------------------------------------------------
2737 static void biosfn_enable_cursor_emulation (disable)
2738 Bit8u disable;
2740 Bit8u videoctl;
2742 videoctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
2744 // Bit 0 set if disable!=0
2745 if(disable!=0x00)videoctl|=0x01;
2746 else videoctl&=0xfe;
2748 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,videoctl);
2751 // --------------------------------------------------------------------------------------------
2752 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2754 #ifdef DEBUG
2755 unimplemented();
2756 #endif
2758 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2760 #ifdef DEBUG
2761 unimplemented();
2762 #endif
2765 // --------------------------------------------------------------------------------------------
2766 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2767 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2769 Bit16u newcurs,oldcurs,dummy;
2770 Bit8u car,carattr;
2772 // Read curs info for the page
2773 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2775 // if row=0xff special case : use current cursor position
2776 if(row==0xff)
2777 {col=oldcurs&0x00ff;
2778 row=(oldcurs&0xff00)>>8;
2781 newcurs=row; newcurs<<=8; newcurs+=col;
2782 biosfn_set_cursor_pos(page,newcurs);
2784 while(count--!=0)
2786 car=read_byte(seg,offset++);
2787 if((flag&0x02)!=0)
2788 attr=read_byte(seg,offset++);
2790 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2793 // Set back curs pos
2794 if((flag&0x01)==0)
2795 biosfn_set_cursor_pos(page,oldcurs);
2798 // --------------------------------------------------------------------------------------------
2799 ASM_START
2800 biosfn_group_1A:
2801 cmp al, #0x00
2802 je biosfn_read_display_code
2803 cmp al, #0x01
2804 je biosfn_set_display_code
2805 #ifdef DEBUG
2806 call _unknown
2807 #endif
2809 biosfn_read_display_code:
2810 push ds
2811 push ax
2812 mov ax, #biosmem_seg
2813 mov ds, ax
2814 mov bx, #biosmem_dcc_index
2815 mov al, [bx]
2816 mov bl, al
2817 xor bh, bh
2818 pop ax
2819 mov al, ah
2820 pop ds
2822 biosfn_set_display_code:
2823 push ds
2824 push ax
2825 push bx
2826 mov ax, #biosmem_seg
2827 mov ds, ax
2828 mov ax, bx
2829 mov bx, #biosmem_dcc_index
2830 mov [bx], al
2831 #ifdef DEBUG
2832 mov al, ah
2833 xor ah, ah
2834 push ax
2835 mov bx, #msg_alt_dcc
2836 push bx
2837 call _printf
2838 add sp, #4
2839 #endif
2840 pop bx
2841 pop ax
2842 mov al, ah
2843 pop ds
2846 #ifdef DEBUG
2847 msg_alt_dcc:
2848 .ascii "Alternate Display code (%02x) was discarded"
2849 .byte 0x0d,0x0a,0x00
2850 #endif
2851 ASM_END
2853 // --------------------------------------------------------------------------------------------
2854 static void biosfn_read_state_info (BX,ES,DI)
2855 Bit16u BX;Bit16u ES;Bit16u DI;
2857 // Address of static functionality table
2858 write_word(ES,DI+0x00,&static_functionality);
2859 write_word(ES,DI+0x02,0xC000);
2861 // Hard coded copy from BIOS area. Should it be cleaner ?
2862 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2863 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2865 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2866 write_byte(ES,DI+0x26,0);
2867 write_byte(ES,DI+0x27,16);
2868 write_byte(ES,DI+0x28,0);
2869 write_byte(ES,DI+0x29,8);
2870 write_byte(ES,DI+0x2a,2);
2871 write_byte(ES,DI+0x2b,0);
2872 write_byte(ES,DI+0x2c,0);
2873 write_byte(ES,DI+0x31,3);
2874 write_byte(ES,DI+0x32,0);
2876 memsetb(ES,DI+0x33,0,13);
2879 // --------------------------------------------------------------------------------------------
2880 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2882 #ifdef DEBUG
2883 unimplemented();
2884 #endif
2886 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2888 #ifdef DEBUG
2889 unimplemented();
2890 #endif
2892 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2894 #ifdef DEBUG
2895 unimplemented();
2896 #endif
2899 // ============================================================================================
2901 // Video Utils
2903 // ============================================================================================
2905 // --------------------------------------------------------------------------------------------
2906 static Bit8u find_vga_entry(mode)
2907 Bit8u mode;
2909 Bit8u i,line=0xFF;
2910 for(i=0;i<=MODE_MAX;i++)
2911 if(vga_modes[i].svgamode==mode)
2912 {line=i;
2913 break;
2915 return line;
2918 /* =========================================================== */
2920 * Misc Utils
2922 /* =========================================================== */
2924 // --------------------------------------------------------------------------------------------
2925 static void memsetb(seg,offset,value,count)
2926 Bit16u seg;
2927 Bit16u offset;
2928 Bit16u value;
2929 Bit16u count;
2931 ASM_START
2932 push bp
2933 mov bp, sp
2935 push ax
2936 push cx
2937 push es
2938 push di
2940 mov cx, 10[bp] ; count
2941 cmp cx, #0x00
2942 je memsetb_end
2943 mov ax, 4[bp] ; segment
2944 mov es, ax
2945 mov ax, 6[bp] ; offset
2946 mov di, ax
2947 mov al, 8[bp] ; value
2950 stosb
2952 memsetb_end:
2953 pop di
2954 pop es
2955 pop cx
2956 pop ax
2958 pop bp
2959 ASM_END
2962 // --------------------------------------------------------------------------------------------
2963 static void memsetw(seg,offset,value,count)
2964 Bit16u seg;
2965 Bit16u offset;
2966 Bit16u value;
2967 Bit16u count;
2969 ASM_START
2970 push bp
2971 mov bp, sp
2973 push ax
2974 push cx
2975 push es
2976 push di
2978 mov cx, 10[bp] ; count
2979 cmp cx, #0x00
2980 je memsetw_end
2981 mov ax, 4[bp] ; segment
2982 mov es, ax
2983 mov ax, 6[bp] ; offset
2984 mov di, ax
2985 mov ax, 8[bp] ; value
2988 stosw
2990 memsetw_end:
2991 pop di
2992 pop es
2993 pop cx
2994 pop ax
2996 pop bp
2997 ASM_END
3000 // --------------------------------------------------------------------------------------------
3001 static void memcpyb(dseg,doffset,sseg,soffset,count)
3002 Bit16u dseg;
3003 Bit16u doffset;
3004 Bit16u sseg;
3005 Bit16u soffset;
3006 Bit16u count;
3008 ASM_START
3009 push bp
3010 mov bp, sp
3012 push ax
3013 push cx
3014 push es
3015 push di
3016 push ds
3017 push si
3019 mov cx, 12[bp] ; count
3020 cmp cx, #0x0000
3021 je memcpyb_end
3022 mov ax, 4[bp] ; dsegment
3023 mov es, ax
3024 mov ax, 6[bp] ; doffset
3025 mov di, ax
3026 mov ax, 8[bp] ; ssegment
3027 mov ds, ax
3028 mov ax, 10[bp] ; soffset
3029 mov si, ax
3032 movsb
3034 memcpyb_end:
3035 pop si
3036 pop ds
3037 pop di
3038 pop es
3039 pop cx
3040 pop ax
3042 pop bp
3043 ASM_END
3046 // --------------------------------------------------------------------------------------------
3047 static void memcpyw(dseg,doffset,sseg,soffset,count)
3048 Bit16u dseg;
3049 Bit16u doffset;
3050 Bit16u sseg;
3051 Bit16u soffset;
3052 Bit16u count;
3054 ASM_START
3055 push bp
3056 mov bp, sp
3058 push ax
3059 push cx
3060 push es
3061 push di
3062 push ds
3063 push si
3065 mov cx, 12[bp] ; count
3066 cmp cx, #0x0000
3067 je memcpyw_end
3068 mov ax, 4[bp] ; dsegment
3069 mov es, ax
3070 mov ax, 6[bp] ; doffset
3071 mov di, ax
3072 mov ax, 8[bp] ; ssegment
3073 mov ds, ax
3074 mov ax, 10[bp] ; soffset
3075 mov si, ax
3078 movsw
3080 memcpyw_end:
3081 pop si
3082 pop ds
3083 pop di
3084 pop es
3085 pop cx
3086 pop ax
3088 pop bp
3089 ASM_END
3092 /* =========================================================== */
3094 * These functions where ripped from Kevin's rombios.c
3096 /* =========================================================== */
3098 // --------------------------------------------------------------------------------------------
3099 static Bit8u
3100 read_byte(seg, offset)
3101 Bit16u seg;
3102 Bit16u offset;
3104 ASM_START
3105 push bp
3106 mov bp, sp
3108 push bx
3109 push ds
3110 mov ax, 4[bp] ; segment
3111 mov ds, ax
3112 mov bx, 6[bp] ; offset
3113 mov al, [bx]
3114 ;; al = return value (byte)
3115 pop ds
3116 pop bx
3118 pop bp
3119 ASM_END
3122 // --------------------------------------------------------------------------------------------
3123 static Bit16u
3124 read_word(seg, offset)
3125 Bit16u seg;
3126 Bit16u offset;
3128 ASM_START
3129 push bp
3130 mov bp, sp
3132 push bx
3133 push ds
3134 mov ax, 4[bp] ; segment
3135 mov ds, ax
3136 mov bx, 6[bp] ; offset
3137 mov ax, [bx]
3138 ;; ax = return value (word)
3139 pop ds
3140 pop bx
3142 pop bp
3143 ASM_END
3146 // --------------------------------------------------------------------------------------------
3147 static void
3148 write_byte(seg, offset, data)
3149 Bit16u seg;
3150 Bit16u offset;
3151 Bit8u data;
3153 ASM_START
3154 push bp
3155 mov bp, sp
3157 push ax
3158 push bx
3159 push ds
3160 mov ax, 4[bp] ; segment
3161 mov ds, ax
3162 mov bx, 6[bp] ; offset
3163 mov al, 8[bp] ; data byte
3164 mov [bx], al ; write data byte
3165 pop ds
3166 pop bx
3167 pop ax
3169 pop bp
3170 ASM_END
3173 // --------------------------------------------------------------------------------------------
3174 static void
3175 write_word(seg, offset, data)
3176 Bit16u seg;
3177 Bit16u offset;
3178 Bit16u data;
3180 ASM_START
3181 push bp
3182 mov bp, sp
3184 push ax
3185 push bx
3186 push ds
3187 mov ax, 4[bp] ; segment
3188 mov ds, ax
3189 mov bx, 6[bp] ; offset
3190 mov ax, 8[bp] ; data word
3191 mov [bx], ax ; write data word
3192 pop ds
3193 pop bx
3194 pop ax
3196 pop bp
3197 ASM_END
3200 // --------------------------------------------------------------------------------------------
3201 Bit8u
3202 inb(port)
3203 Bit16u port;
3205 ASM_START
3206 push bp
3207 mov bp, sp
3209 push dx
3210 mov dx, 4[bp]
3211 in al, dx
3212 pop dx
3214 pop bp
3215 ASM_END
3218 Bit16u
3219 inw(port)
3220 Bit16u port;
3222 ASM_START
3223 push bp
3224 mov bp, sp
3226 push dx
3227 mov dx, 4[bp]
3228 in ax, dx
3229 pop dx
3231 pop bp
3232 ASM_END
3235 // --------------------------------------------------------------------------------------------
3236 void
3237 outb(port, val)
3238 Bit16u port;
3239 Bit8u val;
3241 ASM_START
3242 push bp
3243 mov bp, sp
3245 push ax
3246 push dx
3247 mov dx, 4[bp]
3248 mov al, 6[bp]
3249 out dx, al
3250 pop dx
3251 pop ax
3253 pop bp
3254 ASM_END
3257 // --------------------------------------------------------------------------------------------
3258 void
3259 outw(port, val)
3260 Bit16u port;
3261 Bit16u val;
3263 ASM_START
3264 push bp
3265 mov bp, sp
3267 push ax
3268 push dx
3269 mov dx, 4[bp]
3270 mov ax, 6[bp]
3271 out dx, ax
3272 pop dx
3273 pop ax
3275 pop bp
3276 ASM_END
3279 Bit16u get_SS()
3281 ASM_START
3282 mov ax, ss
3283 ASM_END
3286 #ifdef DEBUG
3287 void unimplemented()
3289 printf("--> Unimplemented\n");
3292 void unknown()
3294 printf("--> Unknown int10\n");
3296 #endif
3298 // --------------------------------------------------------------------------------------------
3299 void printf(s)
3300 Bit8u *s;
3302 Bit8u c, format_char;
3303 Boolean in_format;
3304 unsigned format_width, i;
3305 Bit16u *arg_ptr;
3306 Bit16u arg_seg, arg, digit, nibble, shift_count;
3308 arg_ptr = &s;
3309 arg_seg = get_SS();
3311 in_format = 0;
3312 format_width = 0;
3314 while (c = read_byte(0xc000, s)) {
3315 if ( c == '%' ) {
3316 in_format = 1;
3317 format_width = 0;
3319 else if (in_format) {
3320 if ( (c>='0') && (c<='9') ) {
3321 format_width = (format_width * 10) + (c - '0');
3323 else if (c == 'x') {
3324 arg_ptr++; // increment to next arg
3325 arg = read_word(arg_seg, arg_ptr);
3326 if (format_width == 0)
3327 format_width = 4;
3328 i = 0;
3329 digit = format_width - 1;
3330 for (i=0; i<format_width; i++) {
3331 nibble = (arg >> (4 * digit)) & 0x000f;
3332 if (nibble <= 9)
3333 outb(0x0500, nibble + '0');
3334 else
3335 outb(0x0500, (nibble - 10) + 'A');
3336 digit--;
3338 in_format = 0;
3340 //else if (c == 'd') {
3341 // in_format = 0;
3342 // }
3344 else {
3345 outb(0x0500, c);
3347 s ++;
3351 #ifdef VBE
3352 #include "vbe.c"
3353 #endif
3355 // --------------------------------------------------------------------------------------------
3357 ASM_START
3358 ;; DATA_SEG_DEFS_HERE
3359 ASM_END
3361 ASM_START
3362 .ascii "vgabios ends here"
3363 .byte 0x00
3364 vgabios_end:
3365 .byte 0xCB
3366 ;; BLOCK_STRINGS_BEGIN
3367 ASM_END