- biosfn_enable_cursor_emulation rewritten in assembler
[vgabios.git] / vgabios.c
blob82de891ca22de529fee3cc1a01116e31f992918a
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_switch_video_interface();
108 static void biosfn_enable_video_refresh_control();
109 static void biosfn_write_string();
110 static void biosfn_read_state_info();
111 static void biosfn_read_video_state_size();
112 static void biosfn_save_video_state();
113 static void biosfn_restore_video_state();
115 // This is for compiling with gcc2 and gcc3
116 #define ASM_START #asm
117 #define ASM_END #endasm
119 ASM_START
121 biosmem_seg = 0x40
122 biosmem_initial_mode = 0x10
123 biosmem_current_mode = 0x49
124 biosmem_nb_cols = 0x4a
125 biosmem_current_page = 0x62
126 biosmem_current_msr = 0x65
127 biosmem_char_height = 0x85
128 biosmem_video_ctl = 0x87
129 biosmem_switches = 0x88
130 biosmem_modeset_ctl = 0x89
131 biosmem_dcc_index = 0x8a
133 vgareg_actl_address = 0x03c0
134 vgareg_actl_read_data = 0x03c1
135 vgareg_write_misc_output = 0x03c2
136 vgareg_sequ_address = 0x03c4
137 vgareg_pel_mask = 0x03c6
138 vgareg_dac_read_address = 0x03c7
139 vgareg_dac_write_address = 0x03c8
140 vgareg_dac_data = 0x03c9
141 vgareg_read_misc_output = 0x03cc
142 vgareg_grdc_address = 0x03ce
143 vgareg_actl_reset = 0x03da
145 MACRO SET_INT_VECTOR
146 push ds
147 xor ax, ax
148 mov ds, ax
149 mov ax, ?3
150 mov ?1*4, ax
151 mov ax, ?2
152 mov ?1*4+2, ax
153 pop ds
154 MEND
156 ASM_END
158 ASM_START
159 .text
160 .rom
161 .org 0
163 use16 386
165 vgabios_start:
166 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
168 .byte 0x40 /* BIOS extension length in units of 512 bytes */
171 vgabios_entry_point:
173 jmp vgabios_init_func
175 vgabios_name:
176 .ascii "Plex86/Bochs VGABios"
177 .ascii " "
178 .byte 0x00
180 // Info from Bart Oldeman
181 .org 0x1e
182 .ascii "IBM"
183 .byte 0x00
185 vgabios_version:
186 #ifndef VGABIOS_VERS
187 .ascii "current-cvs"
188 #else
189 .ascii VGABIOS_VERS
190 #endif
191 .ascii " "
193 vgabios_date:
194 .ascii VGABIOS_DATE
195 .byte 0x0a,0x0d
196 .byte 0x00
198 vgabios_copyright:
199 .ascii "(C) 2003 the LGPL VGABios developers Team"
200 .byte 0x0a,0x0d
201 .byte 0x00
203 vgabios_license:
204 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
205 .byte 0x0a,0x0d
206 .byte 0x0a,0x0d
207 .byte 0x00
209 vgabios_website:
210 .ascii "Please visit :"
211 .byte 0x0a,0x0d
212 ;;.ascii " . http://www.plex86.org"
213 ;;.byte 0x0a,0x0d
214 .ascii " . http://bochs.sourceforge.net"
215 .byte 0x0a,0x0d
216 .ascii " . http://www.nongnu.org/vgabios"
217 .byte 0x0a,0x0d
218 .byte 0x0a,0x0d
219 .byte 0x00
222 ;; ============================================================================================
224 ;; Init Entry point
226 ;; ============================================================================================
227 vgabios_init_func:
229 ;; init vga card
230 call init_vga_card
232 ;; init basic bios vars
233 call init_bios_area
235 #ifdef VBE
236 ;; init vbe functions
237 call _vbe_init
238 #endif
240 ;; set int10 vect
241 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
243 ;; display splash screen
244 call _display_splash_screen
246 ;; init video mode and clear the screen
247 mov ax,#0x0003
248 int #0x10
250 ;; show info
251 call _display_info
253 #ifdef VBE
254 ;; show vbe info
255 call _vbe_display_info
256 #endif
259 retf
260 ASM_END
263 * int10 handled here
265 ASM_START
266 vgabios_int10_handler:
267 pushf
268 #ifdef DEBUG
269 push es
270 push ds
271 pusha
272 mov bx, #0xc000
273 mov ds, bx
274 call _int10_debugmsg
275 popa
276 pop ds
277 pop es
278 #endif
279 cmp ah, #0x0f
280 jne int10_test_1A
281 call biosfn_get_video_mode
282 jmp int10_end
283 int10_test_1A:
284 cmp ah, #0x1a
285 jne int10_test_0B
286 call biosfn_group_1A
287 jmp int10_end
288 int10_test_0B:
289 cmp ah, #0x0b
290 jne int10_test_1103
291 call biosfn_group_0B
292 jmp int10_end
293 int10_test_1103:
294 cmp ax, #0x1103
295 jne int10_test_12
296 call biosfn_set_text_block_specifier
297 jmp int10_end
298 int10_test_12:
299 cmp ah, #0x12
300 jne int10_test_101B
301 cmp bl, #0x31
302 jne int10_test_BL32
303 call biosfn_enable_default_palette_loading
304 jmp int10_end
305 int10_test_BL32:
306 cmp bl, #0x32
307 jne int10_test_BL33
308 call biosfn_enable_video_addressing
309 jmp int10_end
310 int10_test_BL33:
311 cmp bl, #0x33
312 jne int10_test_BL34
313 call biosfn_enable_grayscale_summing
314 jmp int10_end
315 int10_test_BL34:
316 cmp bl, #0x34
317 jne int10_normal
318 call biosfn_enable_cursor_emulation
319 jmp int10_end
320 int10_test_101B:
321 cmp ax, #0x101b
322 je int10_normal
323 cmp ah, #0x10
324 jne int10_normal
325 call biosfn_group_10
326 jmp int10_end
328 int10_normal:
329 push es
330 push ds
331 pusha
333 ;; We have to set ds to access the right data segment
334 mov bx, #0xc000
335 mov ds, bx
336 call _int10_func
338 popa
339 pop ds
340 pop es
341 int10_end:
342 popf
343 iret
344 ASM_END
346 #include "vgatables.h"
347 #include "vgafonts.h"
350 * Boot time harware inits
352 ASM_START
353 init_vga_card:
354 ;; switch to color mode and enable CPU access 480 lines
355 mov dx, #0x3C2
356 mov al, #0xC3
357 outb dx,al
359 ;; more than 64k 3C4/04
360 mov dx, #0x3C4
361 mov al, #0x04
362 outb dx,al
363 mov dx, #0x3C5
364 mov al, #0x02
365 outb dx,al
367 mov bx, #msg_vga_init
368 push bx
369 call _printf
370 inc sp
371 inc sp
374 msg_vga_init:
375 .ascii "VGABios $Id$"
376 .byte 0x0d,0x0a,0x00
377 ASM_END
379 // --------------------------------------------------------------------------------------------
381 * Boot time bios area inits
383 ASM_START
384 init_bios_area:
385 push ds
386 mov ax, #biosmem_seg
387 mov ds, ax
389 ;; init detected hardware BIOS Area
390 mov bx, #biosmem_initial_mode
391 mov ax, [bx]
392 and ax, #0xffcf
393 mov [bx], ax
395 ;; Just for the first int10 find its children
397 ;; the default char height
398 mov bx, #biosmem_char_height
399 mov al, #0x10
400 mov [bx], al
402 ;; Clear the screen
403 mov bx, #biosmem_video_ctl
404 mov al, #0x60
405 mov [bx], al
407 ;; Set the basic screen we have
408 mov bx, #biosmem_switches
409 mov al, #0xf9
410 mov [bx], al
412 ;; Set the basic modeset options
413 mov bx, #biosmem_modeset_ctl
414 mov al, #0x51
415 mov [bx], al
417 ;; Set the default MSR
418 mov bx, #biosmem_current_msr
419 mov al, #0x09
420 mov [bx], al
422 pop ds
424 ASM_END
426 // --------------------------------------------------------------------------------------------
428 * Boot time Splash screen
430 static void display_splash_screen()
434 // --------------------------------------------------------------------------------------------
436 * Tell who we are
439 static void display_info()
441 ASM_START
442 mov ax,#0xc000
443 mov ds,ax
444 mov si,#vgabios_name
445 call _display_string
446 mov si,#vgabios_version
447 call _display_string
449 ;;mov si,#vgabios_copyright
450 ;;call _display_string
451 ;;mov si,#crlf
452 ;;call _display_string
454 mov si,#vgabios_license
455 call _display_string
456 mov si,#vgabios_website
457 call _display_string
458 ASM_END
461 static void display_string()
463 // Get length of string
464 ASM_START
465 mov ax,ds
466 mov es,ax
467 mov di,si
468 xor cx,cx
469 not cx
470 xor al,al
472 repne
473 scasb
474 not cx
475 dec cx
476 push cx
478 mov ax,#0x0300
479 mov bx,#0x0000
480 int #0x10
482 pop cx
483 mov ax,#0x1301
484 mov bx,#0x000b
485 mov bp,si
486 int #0x10
487 ASM_END
490 // --------------------------------------------------------------------------------------------
491 #ifdef DEBUG
492 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
493 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
495 // 0E is write char...
496 if(GET_AH()!=0x0E)
497 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
499 #endif
501 // --------------------------------------------------------------------------------------------
503 * int10 main dispatcher
505 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
506 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
509 // BIOS functions
510 switch(GET_AH())
512 case 0x00:
513 biosfn_set_video_mode(GET_AL());
514 switch(GET_AL()&0x7F)
515 {case 6:
516 SET_AL(0x3F);
517 break;
518 case 0:
519 case 1:
520 case 2:
521 case 3:
522 case 4:
523 case 5:
524 case 7:
525 SET_AL(0x30);
526 break;
527 default:
528 SET_AL(0x20);
530 break;
531 case 0x01:
532 biosfn_set_cursor_shape(GET_CH(),GET_CL());
533 break;
534 case 0x02:
535 biosfn_set_cursor_pos(GET_BH(),DX);
536 break;
537 case 0x03:
538 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
539 break;
540 case 0x04:
541 // Read light pen pos (unimplemented)
542 #ifdef DEBUG
543 unimplemented();
544 #endif
545 AX=0x00;
546 BX=0x00;
547 CX=0x00;
548 DX=0x00;
549 break;
550 case 0x05:
551 biosfn_set_active_page(GET_AL());
552 break;
553 case 0x06:
554 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
555 break;
556 case 0x07:
557 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
558 break;
559 case 0x08:
560 biosfn_read_char_attr(GET_BH(),&AX);
561 break;
562 case 0x09:
563 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
564 break;
565 case 0x0A:
566 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
567 break;
568 case 0x0C:
569 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
570 break;
571 case 0x0D:
572 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
573 break;
574 case 0x0E:
575 // Ralf Brown Interrupt list is WRONG on bh(page)
576 // We do output only on the current page !
577 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
578 break;
579 case 0x10:
580 // All other functions of group AH=0x10 rewritten in assembler
581 biosfn_perform_gray_scale_summing(BX,CX);
582 break;
583 case 0x11:
584 switch(GET_AL())
586 case 0x00:
587 case 0x10:
588 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
589 break;
590 case 0x01:
591 case 0x11:
592 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
593 break;
594 case 0x02:
595 case 0x12:
596 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
597 break;
598 case 0x04:
599 case 0x14:
600 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
601 break;
602 case 0x20:
603 biosfn_load_gfx_8_8_chars(ES,BP);
604 break;
605 case 0x21:
606 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
607 break;
608 case 0x22:
609 biosfn_load_gfx_8_14_chars(GET_BL());
610 break;
611 case 0x23:
612 biosfn_load_gfx_8_8_dd_chars(GET_BL());
613 break;
614 case 0x24:
615 biosfn_load_gfx_8_16_chars(GET_BL());
616 break;
617 case 0x30:
618 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
619 break;
620 #ifdef DEBUG
621 default:
622 unknown();
623 #endif
626 break;
627 case 0x12:
628 switch(GET_BL())
630 case 0x10:
631 biosfn_get_ega_info(&BX,&CX);
632 break;
633 case 0x20:
634 biosfn_alternate_prtsc();
635 break;
636 case 0x30:
637 biosfn_select_vert_res(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;
989 Bit8u modeset_ctl;
991 CH&=0x3f;
992 CL&=0x1f;
994 curs=(CH<<8)+CL;
995 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
997 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
998 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
999 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1001 if(CL!=(CH+1))
1003 CH = ((CH+1) * cheight / 8) -1;
1005 else
1007 CH = ((CL+1) * cheight / 8) - 2;
1009 CL = ((CL+1) * cheight / 8) - 1;
1012 // CTRC regs 0x0a and 0x0b
1013 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1014 outb(crtc_addr,0x0a);
1015 outb(crtc_addr+1,CH);
1016 outb(crtc_addr,0x0b);
1017 outb(crtc_addr+1,CL);
1020 // --------------------------------------------------------------------------------------------
1021 static void biosfn_set_cursor_pos (page, cursor)
1022 Bit8u page;Bit16u cursor;
1024 Bit8u xcurs,ycurs,current;
1025 Bit16u nbcols,nbrows,address,crtc_addr;
1027 // Should not happen...
1028 if(page>7)return;
1030 // Bios cursor pos
1031 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1033 // Set the hardware cursor
1034 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1035 if(page==current)
1037 // Get the dimensions
1038 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1039 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1041 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1043 // Calculate the address knowing nbcols nbrows and page num
1044 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1046 // CRTC regs 0x0e and 0x0f
1047 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1048 outb(crtc_addr,0x0e);
1049 outb(crtc_addr+1,(address&0xff00)>>8);
1050 outb(crtc_addr,0x0f);
1051 outb(crtc_addr+1,address&0x00ff);
1055 // --------------------------------------------------------------------------------------------
1056 static void biosfn_get_cursor_pos (page,shape, pos)
1057 Bit8u page;Bit16u *shape;Bit16u *pos;
1059 Bit16u ss=get_SS();
1061 // Default
1062 write_word(ss, shape, 0);
1063 write_word(ss, pos, 0);
1065 if(page>7)return;
1066 // FIXME should handle VGA 14/16 lines
1067 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1068 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1071 // --------------------------------------------------------------------------------------------
1072 static void biosfn_set_active_page (page)
1073 Bit8u page;
1075 Bit16u cursor,dummy,crtc_addr;
1076 Bit16u nbcols,nbrows,address;
1077 Bit8u mode,line;
1079 if(page>7)return;
1081 // Get the mode
1082 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1083 line=find_vga_entry(mode);
1084 if(line==0xFF)return;
1086 // Get pos curs pos for the right page
1087 biosfn_get_cursor_pos(page,&dummy,&cursor);
1089 if(vga_modes[line].class==TEXT)
1091 // Get the dimensions
1092 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1093 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1095 // Calculate the address knowing nbcols nbrows and page num
1096 address=SCREEN_MEM_START(nbcols,nbrows,page);
1097 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1099 // Start address
1100 address=SCREEN_IO_START(nbcols,nbrows,page);
1102 else
1104 address = page*vga_modes[line].slength;
1107 // CRTC regs 0x0c and 0x0d
1108 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1109 outb(crtc_addr,0x0c);
1110 outb(crtc_addr+1,(address&0xff00)>>8);
1111 outb(crtc_addr,0x0d);
1112 outb(crtc_addr+1,address&0x00ff);
1114 // And change the BIOS page
1115 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1117 #ifdef DEBUG
1118 printf("Set active page %02x address %04x\n",page,address);
1119 #endif
1121 // Display the cursor, now the page is active
1122 biosfn_set_cursor_pos(page,cursor);
1125 // --------------------------------------------------------------------------------------------
1126 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1127 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1129 // page == 0xFF if current
1131 Bit8u mode,line;
1132 Bit16u nbcols,nbrows,i;
1133 Bit16u address;
1135 if(rul>rlr)return;
1136 if(cul>clr)return;
1138 // Get the mode
1139 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1140 line=find_vga_entry(mode);
1141 if(line==0xFF)return;
1143 // Get the dimensions
1144 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1145 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1147 // Get the current page
1148 if(page==0xFF)
1149 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1151 if(vga_modes[line].class==TEXT)
1153 // Compute the address
1154 address=SCREEN_MEM_START(nbcols,nbrows,page);
1155 #ifdef DEBUG
1156 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1157 #endif
1159 if(rlr>=nbrows)rlr=nbrows-1;
1160 if(clr>=nbcols)clr=nbcols-1;
1161 if(nblines>nbrows)nblines=0;
1163 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1165 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1167 else
1168 {// if Scroll up
1169 if(dir==SCROLL_UP)
1170 {for(i=rul;i<=rlr;i++)
1172 if((i+nblines>rlr)||(nblines==0))
1173 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1174 else
1175 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,clr-cul+1);
1178 else
1179 {for(i=rlr;i>=rul;i--)
1181 if((i<rul+nblines)||(nblines==0))
1182 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1183 else
1184 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,clr-cul+1);
1189 else
1191 // FIXME gfx mode
1192 #ifdef DEBUG
1193 printf("Scroll in graphics mode ");
1194 unimplemented();
1195 #endif
1199 // --------------------------------------------------------------------------------------------
1200 static void biosfn_read_char_attr (page,car)
1201 Bit8u page;Bit16u *car;
1202 {Bit16u ss=get_SS();
1203 Bit8u xcurs,ycurs,mode,line;
1204 Bit16u nbcols,nbrows,address;
1205 Bit16u cursor,dummy;
1207 // Get the mode
1208 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1209 line=find_vga_entry(mode);
1210 if(line==0xFF)return;
1212 // Get the cursor pos for the page
1213 biosfn_get_cursor_pos(page,&dummy,&cursor);
1214 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1216 // Get the dimensions
1217 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1218 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1220 if(vga_modes[line].class==TEXT)
1222 // Compute the address
1223 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1225 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1227 else
1229 // FIXME gfx mode
1230 #ifdef DEBUG
1231 unimplemented();
1232 #endif
1236 // --------------------------------------------------------------------------------------------
1237 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1238 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1240 Bit8u i,j,mask;
1241 Bit8u *fdata;
1242 Bit16u addr,dest,src;
1244 switch(cheight)
1245 {case 14:
1246 fdata = &vgafont14;
1247 break;
1248 case 16:
1249 fdata = &vgafont16;
1250 break;
1251 default:
1252 fdata = &vgafont8;
1254 addr=xcurs+ycurs*cheight*nbcols;
1255 src = car * cheight;
1256 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1257 if(attr&0x80)
1259 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1261 for(i=0;i<cheight;i++)
1263 dest=addr+i*nbcols;
1264 for(j=0;j<8;j++)
1266 mask=0x80>>j;
1267 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1268 read_byte(0xa000,dest);
1269 if(fdata[src+i]&mask)
1271 write_byte(0xa000,dest,attr&0x0f);
1273 else
1275 write_byte(0xa000,dest,0x00);
1279 ASM_START
1280 mov dx, #vgareg_grdc_address
1281 mov ax, 0xff08
1282 out dx, ax
1283 mov ax, 0x0005
1284 out dx, ax
1285 mov ax, 0x0003
1286 out dx, ax
1287 ASM_END
1290 // --------------------------------------------------------------------------------------------
1291 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1292 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1294 Bit8u i,j,mask,data;
1295 Bit8u *fdata;
1296 Bit16u addr,dest,src;
1298 fdata = &vgafont8;
1299 addr=(xcurs*bpp)+ycurs*320;
1300 src = car * 8;
1301 for(i=0;i<8;i++)
1303 dest=addr+(i>>1)*80;
1304 if (i & 1) dest += 0x2000;
1305 mask = 0x80;
1306 if (bpp == 1)
1308 if (attr & 0x80)
1310 data = read_byte(0xb800,dest);
1312 else
1314 data = 0x00;
1316 for(j=0;j<8;j++)
1318 if (fdata[src+i] & mask)
1320 if (attr & 0x80)
1322 data ^= (attr & 0x01) << (7-j);
1324 else
1326 data |= (attr & 0x01) << (7-j);
1329 mask >>= 1;
1331 write_byte(0xb800,dest,data);
1333 else
1335 while (mask > 0)
1337 if (attr & 0x80)
1339 data = read_byte(0xb800,dest);
1341 else
1343 data = 0x00;
1345 for(j=0;j<4;j++)
1347 if (fdata[src+i] & mask)
1349 if (attr & 0x80)
1351 data ^= (attr & 0x03) << ((3-j)*2);
1353 else
1355 data |= (attr & 0x03) << ((3-j)*2);
1358 mask >>= 1;
1360 write_byte(0xb800,dest,data);
1361 dest += 1;
1367 // --------------------------------------------------------------------------------------------
1368 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1369 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1371 Bit8u i,j,mask,data;
1372 Bit8u *fdata;
1373 Bit16u addr,dest,src;
1375 fdata = &vgafont8;
1376 addr=xcurs*8+ycurs*nbcols*64;
1377 src = car * 8;
1378 for(i=0;i<8;i++)
1380 dest=addr+i*nbcols*8;
1381 mask = 0x80;
1382 for(j=0;j<8;j++)
1384 data = 0x00;
1385 if (fdata[src+i] & mask)
1387 data = attr;
1389 write_byte(0xa000,dest+j,data);
1390 mask >>= 1;
1395 // --------------------------------------------------------------------------------------------
1396 static void biosfn_write_char_attr (car,page,attr,count)
1397 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1399 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1400 Bit16u nbcols,nbrows,address;
1401 Bit16u cursor,dummy;
1403 // Get the mode
1404 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1405 line=find_vga_entry(mode);
1406 if(line==0xFF)return;
1408 // Get the cursor pos for the page
1409 biosfn_get_cursor_pos(page,&dummy,&cursor);
1410 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1412 // Get the dimensions
1413 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1414 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1416 if(vga_modes[line].class==TEXT)
1418 // Compute the address
1419 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1421 dummy=((Bit16u)attr<<8)+car;
1422 memsetw(vga_modes[line].sstart,address,dummy,count);
1424 else
1426 // FIXME gfx mode not complete
1427 cheight=vga_modes[line].cheight;
1428 bpp=vga_modes[line].pixbits;
1429 while((count-->0) && (xcurs<nbcols))
1431 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1433 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1435 else if(vga_modes[line].memmodel==CGA)
1437 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1439 else if(vga_modes[line].memmodel==LINEAR8)
1441 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1443 else
1445 #ifdef DEBUG
1446 unimplemented();
1447 #endif
1449 xcurs++;
1454 // --------------------------------------------------------------------------------------------
1455 static void biosfn_write_char_only (car,page,attr,count)
1456 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1458 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1459 Bit16u nbcols,nbrows,address;
1460 Bit16u cursor,dummy;
1462 // Get the mode
1463 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1464 line=find_vga_entry(mode);
1465 if(line==0xFF)return;
1467 // Get the cursor pos for the page
1468 biosfn_get_cursor_pos(page,&dummy,&cursor);
1469 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1471 // Get the dimensions
1472 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1473 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1475 if(vga_modes[line].class==TEXT)
1477 // Compute the address
1478 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1480 while(count-->0)
1481 {write_byte(vga_modes[line].sstart,address,car);
1482 address+=2;
1485 else
1487 // FIXME gfx mode not complete
1488 cheight=vga_modes[line].cheight;
1489 bpp=vga_modes[line].pixbits;
1490 while((count-->0) && (xcurs<nbcols))
1492 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1494 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1496 else if(vga_modes[line].memmodel==CGA)
1498 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1500 else if(vga_modes[line].memmodel==LINEAR8)
1502 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1504 else
1506 #ifdef DEBUG
1507 unimplemented();
1508 #endif
1510 xcurs++;
1515 // --------------------------------------------------------------------------------------------
1516 ASM_START
1517 biosfn_group_0B:
1518 cmp bh, #0x00
1519 je biosfn_set_border_color
1520 cmp bh, #0x01
1521 je biosfn_set_palette
1522 #ifdef DEBUG
1523 call _unknown
1524 #endif
1526 biosfn_set_border_color:
1527 push ax
1528 push bx
1529 push cx
1530 push dx
1531 mov dx, #vgareg_actl_reset
1532 in al, dx
1533 mov dx, #vgareg_actl_address
1534 mov al, #0x00
1535 out dx, al
1536 mov al, bl
1537 and al, #0x0f
1538 test al, #0x08
1539 jz set_low_border
1540 add al, #0x08
1541 set_low_border:
1542 out dx, al
1543 mov cl, #0x01
1544 and bl, #0x10
1545 set_intensity_loop:
1546 mov dx, #vgareg_actl_address
1547 mov al, cl
1548 out dx, al
1549 mov dx, #vgareg_actl_read_data
1550 in al, dx
1551 and al, #0xef
1552 or al, bl
1553 mov dx, #vgareg_actl_address
1554 out dx, al
1555 inc cl
1556 cmp cl, #0x04
1557 jne set_intensity_loop
1558 mov al, #0x20
1559 out dx, al
1560 pop dx
1561 pop cx
1562 pop bx
1563 pop ax
1565 biosfn_set_palette:
1566 push ax
1567 push bx
1568 push cx
1569 push dx
1570 mov dx, #vgareg_actl_reset
1571 in al, dx
1572 mov cl, #0x01
1573 and bl, #0x01
1574 set_cga_palette_loop:
1575 mov dx, #vgareg_actl_address
1576 mov al, cl
1577 out dx, al
1578 mov dx, #vgareg_actl_read_data
1579 in al, dx
1580 and al, #0xfe
1581 or al, bl
1582 mov dx, #vgareg_actl_address
1583 out dx, al
1584 inc cl
1585 cmp cl, #0x04
1586 jne set_cga_palette_loop
1587 mov al, #0x20
1588 out dx, al
1589 pop dx
1590 pop cx
1591 pop bx
1592 pop ax
1594 ASM_END
1596 // --------------------------------------------------------------------------------------------
1597 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1599 Bit8u mode,line,mask,attr,data;
1600 Bit16u addr;
1602 // Get the mode
1603 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1604 line=find_vga_entry(mode);
1605 if(line==0xFF)return;
1606 if(vga_modes[line].class==TEXT)return;
1608 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1610 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1611 mask = 0x01 << (7 - (CX & 0x07));
1612 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1613 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1614 data = read_byte(0xa000,addr);
1615 if (AL & 0x80)
1617 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1619 write_byte(0xa000,addr,AL);
1620 outw(VGAREG_GRDC_ADDRESS, 0xff08);
1621 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1622 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1624 else if(vga_modes[line].memmodel==CGA)
1626 if(vga_modes[line].pixbits==2)
1628 addr=(CX>>2)+(DX>>1)*80;
1630 else
1632 addr=(CX>>3)+(DX>>1)*80;
1634 if (DX & 1) addr += 0x2000;
1635 data = read_byte(0xb800,addr);
1636 if(vga_modes[line].pixbits==2)
1638 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1639 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1641 else
1643 attr = (AL & 0x01) << (7 - (CX & 0x07));
1644 mask = 0x01 << (7 - (CX & 0x07));
1646 if (AL & 0x80)
1648 data ^= attr;
1650 else
1652 data &= ~mask;
1653 data |= attr;
1655 write_byte(0xb800,addr,data);
1657 else if(vga_modes[line].memmodel==LINEAR8)
1659 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1660 write_byte(0xa000,addr,AL);
1662 else
1664 #ifdef DEBUG
1665 unimplemented();
1666 #endif
1670 // --------------------------------------------------------------------------------------------
1671 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1673 Bit8u mode,line,mask,attr,data,i;
1674 Bit16u addr;
1675 Bit16u ss=get_SS();
1677 // Get the mode
1678 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1679 line=find_vga_entry(mode);
1680 if(line==0xFF)return;
1681 if(vga_modes[line].class==TEXT)return;
1683 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1685 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1686 mask = 0x01 << (7 - (CX & 0x07));
1687 attr = 0x00;
1688 for(i=0;i<4;i++)
1690 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1691 data = read_byte(0xa000,addr) & mask;
1692 if (data > 0) attr |= (0x01 << i);
1695 else if(vga_modes[line].memmodel==CGA)
1697 addr=(CX>>2)+(DX>>1)*80;
1698 if (DX & 1) addr += 0x2000;
1699 data = read_byte(0xb800,addr);
1700 if(vga_modes[line].pixbits==2)
1702 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1704 else
1706 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1709 else if(vga_modes[line].memmodel==LINEAR8)
1711 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1712 attr=read_byte(0xa000,addr);
1714 else
1716 #ifdef DEBUG
1717 unimplemented();
1718 #endif
1719 attr = 0;
1721 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1724 // --------------------------------------------------------------------------------------------
1725 static void biosfn_write_teletype (car, page, attr, flag)
1726 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1727 {// flag = WITH_ATTR / NO_ATTR
1729 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1730 Bit16u nbcols,nbrows,address;
1731 Bit16u cursor,dummy;
1733 // special case if page is 0xff, use current page
1734 if(page==0xff)
1735 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1737 // FIXME gfx mode
1739 // Get the mode
1740 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1741 line=find_vga_entry(mode);
1742 if(line==0xFF)return;
1744 // Get the cursor pos for the page
1745 biosfn_get_cursor_pos(page,&dummy,&cursor);
1746 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1748 // Get the dimensions
1749 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1750 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1752 switch(car)
1754 case 7:
1755 //FIXME should beep
1756 break;
1758 case 8:
1759 if(xcurs>0)xcurs--;
1760 break;
1762 case '\r':
1763 xcurs=0;
1764 break;
1766 case '\n':
1767 xcurs=0;
1768 ycurs++;
1769 break;
1771 case '\t':
1774 biosfn_write_teletype(' ',page,attr,flag);
1775 biosfn_get_cursor_pos(page,&dummy,&cursor);
1776 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1777 }while(xcurs%8==0);
1778 break;
1780 default:
1782 if(vga_modes[line].class==TEXT)
1784 // Compute the address
1785 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1787 // Write the char
1788 write_byte(vga_modes[line].sstart,address,car);
1790 if(flag==WITH_ATTR)
1791 write_byte(vga_modes[line].sstart,address+1,attr);
1793 else
1795 // FIXME gfx mode not complete
1796 cheight=vga_modes[line].cheight;
1797 bpp=vga_modes[line].pixbits;
1798 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1800 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1802 else if(vga_modes[line].memmodel==CGA)
1804 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1806 else if(vga_modes[line].memmodel==LINEAR8)
1808 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1810 else
1812 #ifdef DEBUG
1813 unimplemented();
1814 #endif
1818 xcurs++;
1821 // Do we need to wrap ?
1822 if(xcurs==nbcols)
1823 {xcurs=0;
1824 ycurs++;
1827 // Do we need to scroll ?
1828 if(ycurs==nbrows)
1829 {biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1830 ycurs-=1;
1833 // Set the cursor for the page
1834 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1835 biosfn_set_cursor_pos(page,cursor);
1838 // --------------------------------------------------------------------------------------------
1839 ASM_START
1840 biosfn_get_video_mode:
1841 push ds
1842 mov ax, #biosmem_seg
1843 mov ds, ax
1844 push bx
1845 mov bx, #biosmem_current_page
1846 mov al, [bx]
1847 pop bx
1848 mov bh, al
1849 push bx
1850 mov bx, #biosmem_video_ctl
1851 mov ah, [bx]
1852 and ah, #0x80
1853 mov bx, #biosmem_current_mode
1854 mov al, [bx]
1855 or al, ah
1856 mov bx, #biosmem_nb_cols
1857 mov ah, [bx]
1858 pop bx
1859 pop ds
1861 ASM_END
1863 // --------------------------------------------------------------------------------------------
1864 ASM_START
1865 biosfn_group_10:
1866 cmp al, #0x00
1867 jne int10_test_1001
1868 jmp biosfn_set_single_palette_reg
1869 int10_test_1001:
1870 cmp al, #0x01
1871 jne int10_test_1002
1872 jmp biosfn_set_overscan_border_color
1873 int10_test_1002:
1874 cmp al, #0x02
1875 jne int10_test_1003
1876 jmp biosfn_set_all_palette_reg
1877 int10_test_1003:
1878 cmp al, #0x03
1879 jne int10_test_1007
1880 jmp biosfn_toggle_intensity
1881 int10_test_1007:
1882 cmp al, #0x07
1883 jne int10_test_1008
1884 jmp biosfn_get_single_palette_reg
1885 int10_test_1008:
1886 cmp al, #0x08
1887 jne int10_test_1009
1888 jmp biosfn_read_overscan_border_color
1889 int10_test_1009:
1890 cmp al, #0x09
1891 jne int10_test_1010
1892 jmp biosfn_get_all_palette_reg
1893 int10_test_1010:
1894 cmp al, #0x10
1895 jne int10_test_1012
1896 jmp biosfn_set_single_dac_reg
1897 int10_test_1012:
1898 cmp al, #0x12
1899 jne int10_test_1013
1900 jmp biosfn_set_all_dac_reg
1901 int10_test_1013:
1902 cmp al, #0x13
1903 jne int10_test_1015
1904 jmp biosfn_select_video_dac_color_page
1905 int10_test_1015:
1906 cmp al, #0x15
1907 jne int10_test_1017
1908 jmp biosfn_read_single_dac_reg
1909 int10_test_1017:
1910 cmp al, #0x17
1911 jne int10_test_1018
1912 jmp biosfn_read_all_dac_reg
1913 int10_test_1018:
1914 cmp al, #0x18
1915 jne int10_test_1019
1916 jmp biosfn_set_pel_mask
1917 int10_test_1019:
1918 cmp al, #0x19
1919 jne int10_test_101A
1920 jmp biosfn_read_pel_mask
1921 int10_test_101A:
1922 cmp al, #0x1a
1923 jne int10_group_10_unknown
1924 jmp biosfn_read_video_dac_state
1925 int10_group_10_unknown:
1926 #ifdef DEBUG
1927 call _unknown
1928 #endif
1931 biosfn_set_single_palette_reg:
1932 cmp bl, #0x14
1933 ja no_actl_reg1
1934 push ax
1935 push dx
1936 mov dx, #vgareg_actl_reset
1937 in al, dx
1938 mov dx, #vgareg_actl_address
1939 mov al, bl
1940 out dx, al
1941 mov al, bh
1942 out dx, al
1943 mov al, #0x20
1944 out dx, al
1945 pop dx
1946 pop ax
1947 no_actl_reg1:
1949 ASM_END
1951 // --------------------------------------------------------------------------------------------
1952 ASM_START
1953 biosfn_set_overscan_border_color:
1954 push bx
1955 mov bl, #0x11
1956 call biosfn_set_single_palette_reg
1957 pop bx
1959 ASM_END
1961 // --------------------------------------------------------------------------------------------
1962 ASM_START
1963 biosfn_set_all_palette_reg:
1964 push ax
1965 push bx
1966 push cx
1967 push dx
1968 mov bx, dx
1969 mov dx, #vgareg_actl_reset
1970 in al, dx
1971 mov cl, #0x00
1972 mov dx, #vgareg_actl_address
1973 set_palette_loop:
1974 mov al, cl
1975 out dx, al
1976 seg es
1977 mov al, [bx]
1978 out dx, al
1979 inc bx
1980 inc cl
1981 cmp cl, #0x10
1982 jne set_palette_loop
1983 mov al, #0x11
1984 out dx, al
1985 seg es
1986 mov al, [bx]
1987 out dx, al
1988 mov al, #0x20
1989 out dx, al
1990 pop dx
1991 pop cx
1992 pop bx
1993 pop ax
1995 ASM_END
1997 // --------------------------------------------------------------------------------------------
1998 ASM_START
1999 biosfn_toggle_intensity:
2000 push ax
2001 push bx
2002 push dx
2003 mov dx, #vgareg_actl_reset
2004 in al, dx
2005 mov dx, #vgareg_actl_address
2006 mov al, #0x10
2007 out dx, al
2008 mov dx, #vgareg_actl_read_data
2009 in al, dx
2010 and al, #0xf7
2011 and bl, #0x01
2012 shl bl, 3
2013 or al, bl
2014 mov dx, #vgareg_actl_address
2015 out dx, al
2016 mov al, #0x20
2017 out dx, al
2018 pop dx
2019 pop bx
2020 pop ax
2022 ASM_END
2024 // --------------------------------------------------------------------------------------------
2025 ASM_START
2026 biosfn_get_single_palette_reg:
2027 cmp bl, #0x14
2028 ja no_actl_reg2
2029 push ax
2030 push dx
2031 mov dx, #vgareg_actl_reset
2032 in al, dx
2033 mov dx, #vgareg_actl_address
2034 mov al, bl
2035 out dx, al
2036 mov dx, #vgareg_actl_read_data
2037 in al, dx
2038 mov bh, al
2039 mov dx, #vgareg_actl_reset
2040 in al, dx
2041 mov dx, #vgareg_actl_address
2042 mov al, #0x20
2043 out dx, al
2044 pop dx
2045 pop ax
2046 no_actl_reg2:
2048 ASM_END
2050 // --------------------------------------------------------------------------------------------
2051 ASM_START
2052 biosfn_read_overscan_border_color:
2053 push ax
2054 push bx
2055 mov bl, #0x11
2056 call biosfn_get_single_palette_reg
2057 mov al, bh
2058 pop bx
2059 mov bh, al
2060 pop ax
2062 ASM_END
2064 // --------------------------------------------------------------------------------------------
2065 ASM_START
2066 biosfn_get_all_palette_reg:
2067 push ax
2068 push bx
2069 push cx
2070 push dx
2071 mov bx, dx
2072 mov cl, #0x00
2073 get_palette_loop:
2074 mov dx, #vgareg_actl_reset
2075 in al, dx
2076 mov dx, #vgareg_actl_address
2077 mov al, cl
2078 out dx, al
2079 mov dx, #vgareg_actl_read_data
2080 in al, dx
2081 seg es
2082 mov [bx], al
2083 inc bx
2084 inc cl
2085 cmp cl, #0x10
2086 jne get_palette_loop
2087 mov dx, #vgareg_actl_reset
2088 in al, dx
2089 mov dx, #vgareg_actl_address
2090 mov al, #0x11
2091 out dx, al
2092 mov dx, #vgareg_actl_read_data
2093 in al, dx
2094 seg es
2095 mov [bx], al
2096 mov dx, #vgareg_actl_reset
2097 in al, dx
2098 mov dx, #vgareg_actl_address
2099 mov al, #0x20
2100 out dx, al
2101 pop dx
2102 pop cx
2103 pop bx
2104 pop ax
2106 ASM_END
2108 // --------------------------------------------------------------------------------------------
2109 ASM_START
2110 biosfn_set_single_dac_reg:
2111 push ax
2112 push dx
2113 mov dx, #vgareg_dac_write_address
2114 mov al, bl
2115 out dx, al
2116 mov dx, #vgareg_dac_data
2117 pop ax
2118 push ax
2119 mov al, ah
2120 out dx, al
2121 mov al, ch
2122 out dx, al
2123 mov al, cl
2124 out dx, al
2125 pop dx
2126 pop ax
2128 ASM_END
2130 // --------------------------------------------------------------------------------------------
2131 ASM_START
2132 biosfn_set_all_dac_reg:
2133 push ax
2134 push bx
2135 push cx
2136 push dx
2137 mov dx, #vgareg_dac_write_address
2138 mov al, bl
2139 out dx, al
2140 pop dx
2141 push dx
2142 mov bx, dx
2143 mov dx, #vgareg_dac_data
2144 set_dac_loop:
2145 seg es
2146 mov al, [bx]
2147 out dx, al
2148 inc bx
2149 seg es
2150 mov al, [bx]
2151 out dx, al
2152 inc bx
2153 seg es
2154 mov al, [bx]
2155 out dx, al
2156 inc bx
2157 dec cx
2158 jnz set_dac_loop
2159 pop dx
2160 pop cx
2161 pop bx
2162 pop ax
2164 ASM_END
2166 // --------------------------------------------------------------------------------------------
2167 ASM_START
2168 biosfn_select_video_dac_color_page:
2169 push ax
2170 push bx
2171 push dx
2172 mov dx, #vgareg_actl_reset
2173 in al, dx
2174 mov dx, #vgareg_actl_address
2175 mov al, #0x10
2176 out dx, al
2177 mov dx, #vgareg_actl_read_data
2178 in al, dx
2179 and bl, #0x01
2180 jnz set_dac_page
2181 and al, #0x7f
2182 shl bh, 7
2183 or al, bh
2184 mov dx, #vgareg_actl_address
2185 out dx, al
2186 jmp set_actl_normal
2187 set_dac_page:
2188 push ax
2189 mov dx, #vgareg_actl_reset
2190 in al, dx
2191 mov dx, #vgareg_actl_address
2192 mov al, #0x14
2193 out dx, al
2194 pop ax
2195 and al, #0x80
2196 jnz set_dac_16_page
2197 shl bh, 2
2198 set_dac_16_page:
2199 and bh, #0x0f
2200 mov al, bh
2201 out dx, al
2202 set_actl_normal:
2203 mov al, #0x20
2204 out dx, al
2205 pop dx
2206 pop bx
2207 pop ax
2209 ASM_END
2211 // --------------------------------------------------------------------------------------------
2212 ASM_START
2213 biosfn_read_single_dac_reg:
2214 push ax
2215 push dx
2216 mov dx, #vgareg_dac_read_address
2217 mov al, bl
2218 out dx, al
2219 pop ax
2220 mov ah, al
2221 mov dx, #vgareg_dac_data
2222 in al, dx
2223 xchg al, ah
2224 push ax
2225 in al, dx
2226 mov ch, al
2227 in al, dx
2228 mov cl, al
2229 pop dx
2230 pop ax
2232 ASM_END
2234 // --------------------------------------------------------------------------------------------
2235 ASM_START
2236 biosfn_read_all_dac_reg:
2237 push ax
2238 push bx
2239 push cx
2240 push dx
2241 mov dx, #vgareg_dac_read_address
2242 mov al, bl
2243 out dx, al
2244 pop dx
2245 push dx
2246 mov bx, dx
2247 mov dx, #vgareg_dac_data
2248 read_dac_loop:
2249 in al, dx
2250 seg es
2251 mov [bx], al
2252 inc bx
2253 in al, dx
2254 seg es
2255 mov [bx], al
2256 inc bx
2257 in al, dx
2258 seg es
2259 mov [bx], al
2260 inc bx
2261 dec cx
2262 jnz read_dac_loop
2263 pop dx
2264 pop cx
2265 pop bx
2266 pop ax
2268 ASM_END
2270 // --------------------------------------------------------------------------------------------
2271 ASM_START
2272 biosfn_set_pel_mask:
2273 push ax
2274 push dx
2275 mov dx, #vgareg_pel_mask
2276 mov al, bl
2277 out dx, al
2278 pop dx
2279 pop ax
2281 ASM_END
2283 // --------------------------------------------------------------------------------------------
2284 ASM_START
2285 biosfn_read_pel_mask:
2286 push ax
2287 push dx
2288 mov dx, #vgareg_pel_mask
2289 in al, dx
2290 mov bl, al
2291 pop dx
2292 pop ax
2294 ASM_END
2296 // --------------------------------------------------------------------------------------------
2297 ASM_START
2298 biosfn_read_video_dac_state:
2299 push ax
2300 push dx
2301 mov dx, #vgareg_actl_reset
2302 in al, dx
2303 mov dx, #vgareg_actl_address
2304 mov al, #0x10
2305 out dx, al
2306 mov dx, #vgareg_actl_read_data
2307 in al, dx
2308 mov bl, al
2309 shr bl, 7
2310 mov dx, #vgareg_actl_reset
2311 in al, dx
2312 mov dx, #vgareg_actl_address
2313 mov al, #0x14
2314 out dx, al
2315 mov dx, #vgareg_actl_read_data
2316 in al, dx
2317 mov bh, al
2318 and bh, #0x0f
2319 test bl, #0x01
2320 jnz get_dac_16_page
2321 shr bh, 2
2322 get_dac_16_page:
2323 mov dx, #vgareg_actl_reset
2324 in al, dx
2325 mov dx, #vgareg_actl_address
2326 mov al, #0x20
2327 out dx, al
2328 pop dx
2329 pop ax
2331 ASM_END
2333 // --------------------------------------------------------------------------------------------
2334 static void biosfn_perform_gray_scale_summing (start,count)
2335 Bit16u start;Bit16u count;
2336 {Bit8u r,g,b;
2337 Bit16u i;
2338 Bit16u index;
2340 inb(VGAREG_ACTL_RESET);
2341 outb(VGAREG_ACTL_ADDRESS,0x00);
2343 for( index = 0; index < count; index++ )
2345 // set read address and switch to read mode
2346 outb(VGAREG_DAC_READ_ADDRESS,start);
2347 // get 6-bit wide RGB data values
2348 r=inb( VGAREG_DAC_DATA );
2349 g=inb( VGAREG_DAC_DATA );
2350 b=inb( VGAREG_DAC_DATA );
2352 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2353 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2355 if(i>0x3f)i=0x3f;
2357 // set write address and switch to write mode
2358 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2359 // write new intensity value
2360 outb( VGAREG_DAC_DATA, i&0xff );
2361 outb( VGAREG_DAC_DATA, i&0xff );
2362 outb( VGAREG_DAC_DATA, i&0xff );
2363 start++;
2365 inb(VGAREG_ACTL_RESET);
2366 outb(VGAREG_ACTL_ADDRESS,0x20);
2369 // --------------------------------------------------------------------------------------------
2370 static void get_font_access()
2372 ASM_START
2373 mov dx, #vgareg_sequ_address
2374 mov ax, #0x0100
2375 out dx, ax
2376 mov ax, #0x0402
2377 out dx, ax
2378 mov ax, #0x0704
2379 out dx, ax
2380 mov ax, #0x0300
2381 out dx, ax
2382 mov dx, #vgareg_grdc_address
2383 mov ax, #0x0204
2384 out dx, ax
2385 mov ax, #0x0005
2386 out dx, ax
2387 mov ax, #0x0406
2388 out dx, ax
2389 ASM_END
2392 static void release_font_access()
2394 ASM_START
2395 mov dx, #vgareg_sequ_address
2396 mov ax, #0x0100
2397 out dx, ax
2398 mov ax, #0x0302
2399 out dx, ax
2400 mov ax, #0x0304
2401 out dx, ax
2402 mov ax, #0x0300
2403 out dx, ax
2404 mov dx, #vgareg_read_misc_output
2405 in al, dx
2406 and al, #0x01
2407 shl al, 2
2408 or al, #0x0a
2409 mov ah, al
2410 mov al, #0x06
2411 mov dx, #vgareg_grdc_address
2412 out dx, ax
2413 mov ax, #0x0004
2414 out dx, ax
2415 mov ax, #0x1005
2416 out dx, ax
2417 ASM_END
2420 ASM_START
2421 idiv_u:
2422 xor dx,dx
2423 div bx
2425 ASM_END
2427 static void set_scan_lines(lines) Bit8u lines;
2429 Bit16u crtc_addr,cols,page,vde;
2430 Bit8u crtc_r9,ovl,rows;
2432 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2433 outb(crtc_addr, 0x09);
2434 crtc_r9 = inb(crtc_addr+1);
2435 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2436 outb(crtc_addr+1, crtc_r9);
2437 if(lines==8)
2439 biosfn_set_cursor_shape(0x06,0x07);
2441 else
2443 biosfn_set_cursor_shape(lines-4,lines-3);
2445 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2446 outb(crtc_addr, 0x12);
2447 vde = inb(crtc_addr+1);
2448 outb(crtc_addr, 0x07);
2449 ovl = inb(crtc_addr+1);
2450 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2451 rows = vde / lines;
2452 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2453 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2454 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2457 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;
2459 Bit16u blockaddr,dest,i,src;
2461 get_font_access();
2462 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2463 for(i=0;i<CX;i++)
2465 src = BP + i * BH;
2466 dest = blockaddr + (DX + i) * 32;
2467 memcpyb(0xA000, dest, ES, src, BH);
2469 release_font_access();
2470 if(AL>=0x10)
2472 set_scan_lines(BH);
2476 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2478 Bit16u blockaddr,dest,i,src;
2480 get_font_access();
2481 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2482 for(i=0;i<0x100;i++)
2484 src = i * 14;
2485 dest = blockaddr + i * 32;
2486 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2488 release_font_access();
2489 if(AL>=0x10)
2491 set_scan_lines(14);
2495 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2497 Bit16u blockaddr,dest,i,src;
2499 get_font_access();
2500 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2501 for(i=0;i<0x100;i++)
2503 src = i * 8;
2504 dest = blockaddr + i * 32;
2505 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2507 release_font_access();
2508 if(AL>=0x10)
2510 set_scan_lines(8);
2514 // --------------------------------------------------------------------------------------------
2515 ASM_START
2516 biosfn_set_text_block_specifier:
2517 push ax
2518 push dx
2519 mov dx, #vgareg_sequ_address
2520 mov ah, bl
2521 mov al, #0x03
2522 out dx, ax
2523 pop dx
2524 pop ax
2526 ASM_END
2528 // --------------------------------------------------------------------------------------------
2529 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2531 Bit16u blockaddr,dest,i,src;
2533 get_font_access();
2534 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2535 for(i=0;i<0x100;i++)
2537 src = i * 16;
2538 dest = blockaddr + i * 32;
2539 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2541 release_font_access();
2542 if(AL>=0x10)
2544 set_scan_lines(16);
2548 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2550 #ifdef DEBUG
2551 unimplemented();
2552 #endif
2554 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2556 #ifdef DEBUG
2557 unimplemented();
2558 #endif
2560 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2562 #ifdef DEBUG
2563 unimplemented();
2564 #endif
2566 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2568 #ifdef DEBUG
2569 unimplemented();
2570 #endif
2572 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2574 #ifdef DEBUG
2575 unimplemented();
2576 #endif
2578 // --------------------------------------------------------------------------------------------
2579 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2580 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2581 {Bit16u ss=get_SS();
2583 switch(BH)
2584 {case 0x00:
2585 write_word(ss,ES,read_word(0x00,0x1f*4));
2586 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2587 break;
2588 case 0x01:
2589 write_word(ss,ES,read_word(0x00,0x43*4));
2590 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2591 break;
2592 case 0x02:
2593 write_word(ss,ES,0xC000);
2594 write_word(ss,BP,vgafont14);
2595 break;
2596 case 0x03:
2597 write_word(ss,ES,0xC000);
2598 write_word(ss,BP,vgafont8);
2599 break;
2600 case 0x04:
2601 write_word(ss,ES,0xC000);
2602 write_word(ss,BP,vgafont8+128*8);
2603 break;
2604 case 0x05:
2605 write_word(ss,ES,0xC000);
2606 write_word(ss,BP,vgafont14alt);
2607 break;
2608 case 0x06:
2609 write_word(ss,ES,0xC000);
2610 write_word(ss,BP,vgafont16);
2611 break;
2612 case 0x07:
2613 write_word(ss,ES,0xC000);
2614 write_word(ss,BP,vgafont16alt);
2615 break;
2616 default:
2617 #ifdef DEBUG
2618 printf("Get font info BH(%02x) was discarded\n",BH);
2619 #endif
2620 return;
2622 // Set byte/char of on screen font
2623 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2625 // Set Highest char row
2626 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2629 // --------------------------------------------------------------------------------------------
2630 static void biosfn_get_ega_info (BX,CX)
2631 Bit16u *BX;Bit16u *CX;
2632 {Bit16u ss=get_SS();
2633 Bit16u crtc;
2634 Bit8u switches;
2636 crtc=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2637 if(crtc==VGAREG_MDA_CRTC_ADDRESS)
2638 write_word(ss,BX,(1<<8)+0x0003);
2639 else
2640 write_word(ss,BX,0x0003);
2642 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2643 write_word(ss,CX,(switches&0x0f));
2646 // --------------------------------------------------------------------------------------------
2647 static void biosfn_alternate_prtsc()
2649 #ifdef DEBUG
2650 unimplemented();
2651 #endif
2654 // --------------------------------------------------------------------------------------------
2655 static void biosfn_select_vert_res (res)
2656 Bit8u res;
2657 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2658 Bit8u modeset,switches;
2660 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2661 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2662 switch(res)
2663 {case 0x00:
2664 // set modeset ctl bit 7 and reset bit 4
2665 // set switches bit 3-0 to 0x08
2666 modeset|=0x80;modeset&=0xef;
2667 switches&=0xf0;switches|=0x08;
2668 break;
2669 case 0x01:
2670 // reset modeset ctl bit 7 and bit 4
2671 // set switches bit 3-0 to 0x09
2672 modeset&=0x6f;
2673 switches&=0xf0;switches|=0x09;
2674 break;
2675 case 0x02:
2676 // reset modeset ctl bit 7 and set bit 4
2677 // set switches bit 3-0 to 0x09
2678 modeset|=0x10;modeset&=0x7f;
2679 switches&=0xf0;switches|=0x09;
2680 break;
2681 default:
2682 #ifdef DEBUG
2683 printf("Select vert res (%02x) was discarded\n",res);
2684 #endif
2685 return;
2687 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2688 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2691 // --------------------------------------------------------------------------------------------
2692 ASM_START
2693 biosfn_enable_default_palette_loading:
2694 push ds
2695 push bx
2696 push dx
2697 mov dl, al
2698 and dl, #0x01
2699 shl dl, 3
2700 mov ax, #biosmem_seg
2701 mov ds, ax
2702 mov bx, #biosmem_modeset_ctl
2703 mov al, [bx]
2704 and al, #0xf7
2705 or al, dl
2706 mov [bx], al
2707 mov ax, #0x1212
2708 pop dx
2709 pop bx
2710 pop ds
2712 ASM_END
2714 // --------------------------------------------------------------------------------------------
2715 ASM_START
2716 biosfn_enable_video_addressing:
2717 push bx
2718 push dx
2719 mov bl, al
2720 and bl, #0x01
2721 xor bl, #0x01
2722 shl bl, 1
2723 mov dx, #vgareg_read_misc_output
2724 in al, dx
2725 and al, #0xfd
2726 or al, bl
2727 mov dx, #vgareg_write_misc_output
2728 out dx, al
2729 mov ax, #0x1212
2730 pop dx
2731 pop bx
2733 ASM_END
2735 // --------------------------------------------------------------------------------------------
2736 ASM_START
2737 biosfn_enable_grayscale_summing:
2738 push ds
2739 push bx
2740 push dx
2741 mov dl, al
2742 and dl, #0x01
2743 xor dl, #0x01
2744 shl dl, 1
2745 mov ax, #biosmem_seg
2746 mov ds, ax
2747 mov bx, #biosmem_modeset_ctl
2748 mov al, [bx]
2749 and al, #0xfd
2750 or al, dl
2751 mov [bx], al
2752 mov ax, #0x1212
2753 pop dx
2754 pop bx
2755 pop ds
2757 ASM_END
2759 // --------------------------------------------------------------------------------------------
2760 ASM_START
2761 biosfn_enable_cursor_emulation:
2762 push ds
2763 push bx
2764 push dx
2765 mov dl, al
2766 and dl, #0x01
2767 xor dl, #0x01
2768 mov ax, #biosmem_seg
2769 mov ds, ax
2770 mov bx, #biosmem_modeset_ctl
2771 mov al, [bx]
2772 and al, #0xfe
2773 or al, dl
2774 mov [bx], al
2775 mov ax, #0x1212
2776 pop dx
2777 pop bx
2778 pop ds
2780 ASM_END
2782 // --------------------------------------------------------------------------------------------
2783 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2785 #ifdef DEBUG
2786 unimplemented();
2787 #endif
2789 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2791 #ifdef DEBUG
2792 unimplemented();
2793 #endif
2796 // --------------------------------------------------------------------------------------------
2797 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2798 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2800 Bit16u newcurs,oldcurs,dummy;
2801 Bit8u car,carattr;
2803 // Read curs info for the page
2804 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2806 // if row=0xff special case : use current cursor position
2807 if(row==0xff)
2808 {col=oldcurs&0x00ff;
2809 row=(oldcurs&0xff00)>>8;
2812 newcurs=row; newcurs<<=8; newcurs+=col;
2813 biosfn_set_cursor_pos(page,newcurs);
2815 while(count--!=0)
2817 car=read_byte(seg,offset++);
2818 if((flag&0x02)!=0)
2819 attr=read_byte(seg,offset++);
2821 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2824 // Set back curs pos
2825 if((flag&0x01)==0)
2826 biosfn_set_cursor_pos(page,oldcurs);
2829 // --------------------------------------------------------------------------------------------
2830 ASM_START
2831 biosfn_group_1A:
2832 cmp al, #0x00
2833 je biosfn_read_display_code
2834 cmp al, #0x01
2835 je biosfn_set_display_code
2836 #ifdef DEBUG
2837 call _unknown
2838 #endif
2840 biosfn_read_display_code:
2841 push ds
2842 push ax
2843 mov ax, #biosmem_seg
2844 mov ds, ax
2845 mov bx, #biosmem_dcc_index
2846 mov al, [bx]
2847 mov bl, al
2848 xor bh, bh
2849 pop ax
2850 mov al, ah
2851 pop ds
2853 biosfn_set_display_code:
2854 push ds
2855 push ax
2856 push bx
2857 mov ax, #biosmem_seg
2858 mov ds, ax
2859 mov ax, bx
2860 mov bx, #biosmem_dcc_index
2861 mov [bx], al
2862 #ifdef DEBUG
2863 mov al, ah
2864 xor ah, ah
2865 push ax
2866 mov bx, #msg_alt_dcc
2867 push bx
2868 call _printf
2869 add sp, #4
2870 #endif
2871 pop bx
2872 pop ax
2873 mov al, ah
2874 pop ds
2877 #ifdef DEBUG
2878 msg_alt_dcc:
2879 .ascii "Alternate Display code (%02x) was discarded"
2880 .byte 0x0d,0x0a,0x00
2881 #endif
2882 ASM_END
2884 // --------------------------------------------------------------------------------------------
2885 static void biosfn_read_state_info (BX,ES,DI)
2886 Bit16u BX;Bit16u ES;Bit16u DI;
2888 // Address of static functionality table
2889 write_word(ES,DI+0x00,&static_functionality);
2890 write_word(ES,DI+0x02,0xC000);
2892 // Hard coded copy from BIOS area. Should it be cleaner ?
2893 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2894 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2896 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2897 write_byte(ES,DI+0x26,0);
2898 write_byte(ES,DI+0x27,16);
2899 write_byte(ES,DI+0x28,0);
2900 write_byte(ES,DI+0x29,8);
2901 write_byte(ES,DI+0x2a,2);
2902 write_byte(ES,DI+0x2b,0);
2903 write_byte(ES,DI+0x2c,0);
2904 write_byte(ES,DI+0x31,3);
2905 write_byte(ES,DI+0x32,0);
2907 memsetb(ES,DI+0x33,0,13);
2910 // --------------------------------------------------------------------------------------------
2911 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2913 #ifdef DEBUG
2914 unimplemented();
2915 #endif
2917 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2919 #ifdef DEBUG
2920 unimplemented();
2921 #endif
2923 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2925 #ifdef DEBUG
2926 unimplemented();
2927 #endif
2930 // ============================================================================================
2932 // Video Utils
2934 // ============================================================================================
2936 // --------------------------------------------------------------------------------------------
2937 static Bit8u find_vga_entry(mode)
2938 Bit8u mode;
2940 Bit8u i,line=0xFF;
2941 for(i=0;i<=MODE_MAX;i++)
2942 if(vga_modes[i].svgamode==mode)
2943 {line=i;
2944 break;
2946 return line;
2949 /* =========================================================== */
2951 * Misc Utils
2953 /* =========================================================== */
2955 // --------------------------------------------------------------------------------------------
2956 static void memsetb(seg,offset,value,count)
2957 Bit16u seg;
2958 Bit16u offset;
2959 Bit16u value;
2960 Bit16u count;
2962 ASM_START
2963 push bp
2964 mov bp, sp
2966 push ax
2967 push cx
2968 push es
2969 push di
2971 mov cx, 10[bp] ; count
2972 cmp cx, #0x00
2973 je memsetb_end
2974 mov ax, 4[bp] ; segment
2975 mov es, ax
2976 mov ax, 6[bp] ; offset
2977 mov di, ax
2978 mov al, 8[bp] ; value
2981 stosb
2983 memsetb_end:
2984 pop di
2985 pop es
2986 pop cx
2987 pop ax
2989 pop bp
2990 ASM_END
2993 // --------------------------------------------------------------------------------------------
2994 static void memsetw(seg,offset,value,count)
2995 Bit16u seg;
2996 Bit16u offset;
2997 Bit16u value;
2998 Bit16u count;
3000 ASM_START
3001 push bp
3002 mov bp, sp
3004 push ax
3005 push cx
3006 push es
3007 push di
3009 mov cx, 10[bp] ; count
3010 cmp cx, #0x00
3011 je memsetw_end
3012 mov ax, 4[bp] ; segment
3013 mov es, ax
3014 mov ax, 6[bp] ; offset
3015 mov di, ax
3016 mov ax, 8[bp] ; value
3019 stosw
3021 memsetw_end:
3022 pop di
3023 pop es
3024 pop cx
3025 pop ax
3027 pop bp
3028 ASM_END
3031 // --------------------------------------------------------------------------------------------
3032 static void memcpyb(dseg,doffset,sseg,soffset,count)
3033 Bit16u dseg;
3034 Bit16u doffset;
3035 Bit16u sseg;
3036 Bit16u soffset;
3037 Bit16u count;
3039 ASM_START
3040 push bp
3041 mov bp, sp
3043 push ax
3044 push cx
3045 push es
3046 push di
3047 push ds
3048 push si
3050 mov cx, 12[bp] ; count
3051 cmp cx, #0x0000
3052 je memcpyb_end
3053 mov ax, 4[bp] ; dsegment
3054 mov es, ax
3055 mov ax, 6[bp] ; doffset
3056 mov di, ax
3057 mov ax, 8[bp] ; ssegment
3058 mov ds, ax
3059 mov ax, 10[bp] ; soffset
3060 mov si, ax
3063 movsb
3065 memcpyb_end:
3066 pop si
3067 pop ds
3068 pop di
3069 pop es
3070 pop cx
3071 pop ax
3073 pop bp
3074 ASM_END
3077 // --------------------------------------------------------------------------------------------
3078 static void memcpyw(dseg,doffset,sseg,soffset,count)
3079 Bit16u dseg;
3080 Bit16u doffset;
3081 Bit16u sseg;
3082 Bit16u soffset;
3083 Bit16u count;
3085 ASM_START
3086 push bp
3087 mov bp, sp
3089 push ax
3090 push cx
3091 push es
3092 push di
3093 push ds
3094 push si
3096 mov cx, 12[bp] ; count
3097 cmp cx, #0x0000
3098 je memcpyw_end
3099 mov ax, 4[bp] ; dsegment
3100 mov es, ax
3101 mov ax, 6[bp] ; doffset
3102 mov di, ax
3103 mov ax, 8[bp] ; ssegment
3104 mov ds, ax
3105 mov ax, 10[bp] ; soffset
3106 mov si, ax
3109 movsw
3111 memcpyw_end:
3112 pop si
3113 pop ds
3114 pop di
3115 pop es
3116 pop cx
3117 pop ax
3119 pop bp
3120 ASM_END
3123 /* =========================================================== */
3125 * These functions where ripped from Kevin's rombios.c
3127 /* =========================================================== */
3129 // --------------------------------------------------------------------------------------------
3130 static Bit8u
3131 read_byte(seg, offset)
3132 Bit16u seg;
3133 Bit16u offset;
3135 ASM_START
3136 push bp
3137 mov bp, sp
3139 push bx
3140 push ds
3141 mov ax, 4[bp] ; segment
3142 mov ds, ax
3143 mov bx, 6[bp] ; offset
3144 mov al, [bx]
3145 ;; al = return value (byte)
3146 pop ds
3147 pop bx
3149 pop bp
3150 ASM_END
3153 // --------------------------------------------------------------------------------------------
3154 static Bit16u
3155 read_word(seg, offset)
3156 Bit16u seg;
3157 Bit16u offset;
3159 ASM_START
3160 push bp
3161 mov bp, sp
3163 push bx
3164 push ds
3165 mov ax, 4[bp] ; segment
3166 mov ds, ax
3167 mov bx, 6[bp] ; offset
3168 mov ax, [bx]
3169 ;; ax = return value (word)
3170 pop ds
3171 pop bx
3173 pop bp
3174 ASM_END
3177 // --------------------------------------------------------------------------------------------
3178 static void
3179 write_byte(seg, offset, data)
3180 Bit16u seg;
3181 Bit16u offset;
3182 Bit8u data;
3184 ASM_START
3185 push bp
3186 mov bp, sp
3188 push ax
3189 push bx
3190 push ds
3191 mov ax, 4[bp] ; segment
3192 mov ds, ax
3193 mov bx, 6[bp] ; offset
3194 mov al, 8[bp] ; data byte
3195 mov [bx], al ; write data byte
3196 pop ds
3197 pop bx
3198 pop ax
3200 pop bp
3201 ASM_END
3204 // --------------------------------------------------------------------------------------------
3205 static void
3206 write_word(seg, offset, data)
3207 Bit16u seg;
3208 Bit16u offset;
3209 Bit16u data;
3211 ASM_START
3212 push bp
3213 mov bp, sp
3215 push ax
3216 push bx
3217 push ds
3218 mov ax, 4[bp] ; segment
3219 mov ds, ax
3220 mov bx, 6[bp] ; offset
3221 mov ax, 8[bp] ; data word
3222 mov [bx], ax ; write data word
3223 pop ds
3224 pop bx
3225 pop ax
3227 pop bp
3228 ASM_END
3231 // --------------------------------------------------------------------------------------------
3232 Bit8u
3233 inb(port)
3234 Bit16u port;
3236 ASM_START
3237 push bp
3238 mov bp, sp
3240 push dx
3241 mov dx, 4[bp]
3242 in al, dx
3243 pop dx
3245 pop bp
3246 ASM_END
3249 Bit16u
3250 inw(port)
3251 Bit16u port;
3253 ASM_START
3254 push bp
3255 mov bp, sp
3257 push dx
3258 mov dx, 4[bp]
3259 in ax, dx
3260 pop dx
3262 pop bp
3263 ASM_END
3266 // --------------------------------------------------------------------------------------------
3267 void
3268 outb(port, val)
3269 Bit16u port;
3270 Bit8u val;
3272 ASM_START
3273 push bp
3274 mov bp, sp
3276 push ax
3277 push dx
3278 mov dx, 4[bp]
3279 mov al, 6[bp]
3280 out dx, al
3281 pop dx
3282 pop ax
3284 pop bp
3285 ASM_END
3288 // --------------------------------------------------------------------------------------------
3289 void
3290 outw(port, val)
3291 Bit16u port;
3292 Bit16u val;
3294 ASM_START
3295 push bp
3296 mov bp, sp
3298 push ax
3299 push dx
3300 mov dx, 4[bp]
3301 mov ax, 6[bp]
3302 out dx, ax
3303 pop dx
3304 pop ax
3306 pop bp
3307 ASM_END
3310 Bit16u get_SS()
3312 ASM_START
3313 mov ax, ss
3314 ASM_END
3317 #ifdef DEBUG
3318 void unimplemented()
3320 printf("--> Unimplemented\n");
3323 void unknown()
3325 printf("--> Unknown int10\n");
3327 #endif
3329 // --------------------------------------------------------------------------------------------
3330 void printf(s)
3331 Bit8u *s;
3333 Bit8u c, format_char;
3334 Boolean in_format;
3335 unsigned format_width, i;
3336 Bit16u *arg_ptr;
3337 Bit16u arg_seg, arg, digit, nibble, shift_count;
3339 arg_ptr = &s;
3340 arg_seg = get_SS();
3342 in_format = 0;
3343 format_width = 0;
3345 while (c = read_byte(0xc000, s)) {
3346 if ( c == '%' ) {
3347 in_format = 1;
3348 format_width = 0;
3350 else if (in_format) {
3351 if ( (c>='0') && (c<='9') ) {
3352 format_width = (format_width * 10) + (c - '0');
3354 else if (c == 'x') {
3355 arg_ptr++; // increment to next arg
3356 arg = read_word(arg_seg, arg_ptr);
3357 if (format_width == 0)
3358 format_width = 4;
3359 i = 0;
3360 digit = format_width - 1;
3361 for (i=0; i<format_width; i++) {
3362 nibble = (arg >> (4 * digit)) & 0x000f;
3363 if (nibble <= 9)
3364 outb(0x0500, nibble + '0');
3365 else
3366 outb(0x0500, (nibble - 10) + 'A');
3367 digit--;
3369 in_format = 0;
3371 //else if (c == 'd') {
3372 // in_format = 0;
3373 // }
3375 else {
3376 outb(0x0500, c);
3378 s ++;
3382 #ifdef VBE
3383 #include "vbe.c"
3384 #endif
3386 // --------------------------------------------------------------------------------------------
3388 ASM_START
3389 ;; DATA_SEG_DEFS_HERE
3390 ASM_END
3392 ASM_START
3393 .ascii "vgabios ends here"
3394 .byte 0x00
3395 vgabios_end:
3396 .byte 0xCB
3397 ;; BLOCK_STRINGS_BEGIN
3398 ASM_END