- text scroll functions for PLANAR1/PLANAR4 graphics modes added
[vgabios.git] / vgabios.c
blob1d0822a541514e842eae509ac2950190bab77d20
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_alternate_prtsc();
105 static void biosfn_select_vert_res();
106 static void biosfn_switch_video_interface();
107 static void biosfn_enable_video_refresh_control();
108 static void biosfn_write_string();
109 static void biosfn_read_state_info();
110 static void biosfn_read_video_state_size();
111 static void biosfn_save_video_state();
112 static void biosfn_restore_video_state();
114 // This is for compiling with gcc2 and gcc3
115 #define ASM_START #asm
116 #define ASM_END #endasm
118 ASM_START
120 biosmem_seg = 0x40
121 biosmem_initial_mode = 0x10
122 biosmem_current_mode = 0x49
123 biosmem_nb_cols = 0x4a
124 biosmem_current_page = 0x62
125 biosmem_crtc_address = 0x63
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_mda_crtc_address = 0x03b4
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, #0x10
303 jne int10_test_BL31
304 call biosfn_get_ega_info
305 jmp int10_end
306 int10_test_BL31:
307 cmp bl, #0x31
308 jne int10_test_BL32
309 call biosfn_enable_default_palette_loading
310 jmp int10_end
311 int10_test_BL32:
312 cmp bl, #0x32
313 jne int10_test_BL33
314 call biosfn_enable_video_addressing
315 jmp int10_end
316 int10_test_BL33:
317 cmp bl, #0x33
318 jne int10_test_BL34
319 call biosfn_enable_grayscale_summing
320 jmp int10_end
321 int10_test_BL34:
322 cmp bl, #0x34
323 jne int10_normal
324 call biosfn_enable_cursor_emulation
325 jmp int10_end
326 int10_test_101B:
327 cmp ax, #0x101b
328 je int10_normal
329 cmp ah, #0x10
330 jne int10_normal
331 call biosfn_group_10
332 jmp int10_end
334 int10_normal:
335 push es
336 push ds
337 pusha
339 ;; We have to set ds to access the right data segment
340 mov bx, #0xc000
341 mov ds, bx
342 call _int10_func
344 popa
345 pop ds
346 pop es
347 int10_end:
348 popf
349 iret
350 ASM_END
352 #include "vgatables.h"
353 #include "vgafonts.h"
356 * Boot time harware inits
358 ASM_START
359 init_vga_card:
360 ;; switch to color mode and enable CPU access 480 lines
361 mov dx, #0x3C2
362 mov al, #0xC3
363 outb dx,al
365 ;; more than 64k 3C4/04
366 mov dx, #0x3C4
367 mov al, #0x04
368 outb dx,al
369 mov dx, #0x3C5
370 mov al, #0x02
371 outb dx,al
373 mov bx, #msg_vga_init
374 push bx
375 call _printf
376 inc sp
377 inc sp
380 msg_vga_init:
381 .ascii "VGABios $Id$"
382 .byte 0x0d,0x0a,0x00
383 ASM_END
385 // --------------------------------------------------------------------------------------------
387 * Boot time bios area inits
389 ASM_START
390 init_bios_area:
391 push ds
392 mov ax, #biosmem_seg
393 mov ds, ax
395 ;; init detected hardware BIOS Area
396 mov bx, #biosmem_initial_mode
397 mov ax, [bx]
398 and ax, #0xffcf
399 mov [bx], ax
401 ;; Just for the first int10 find its children
403 ;; the default char height
404 mov bx, #biosmem_char_height
405 mov al, #0x10
406 mov [bx], al
408 ;; Clear the screen
409 mov bx, #biosmem_video_ctl
410 mov al, #0x60
411 mov [bx], al
413 ;; Set the basic screen we have
414 mov bx, #biosmem_switches
415 mov al, #0xf9
416 mov [bx], al
418 ;; Set the basic modeset options
419 mov bx, #biosmem_modeset_ctl
420 mov al, #0x51
421 mov [bx], al
423 ;; Set the default MSR
424 mov bx, #biosmem_current_msr
425 mov al, #0x09
426 mov [bx], al
428 pop ds
430 ASM_END
432 // --------------------------------------------------------------------------------------------
434 * Boot time Splash screen
436 static void display_splash_screen()
440 // --------------------------------------------------------------------------------------------
442 * Tell who we are
445 static void display_info()
447 ASM_START
448 mov ax,#0xc000
449 mov ds,ax
450 mov si,#vgabios_name
451 call _display_string
452 mov si,#vgabios_version
453 call _display_string
455 ;;mov si,#vgabios_copyright
456 ;;call _display_string
457 ;;mov si,#crlf
458 ;;call _display_string
460 mov si,#vgabios_license
461 call _display_string
462 mov si,#vgabios_website
463 call _display_string
464 ASM_END
467 static void display_string()
469 // Get length of string
470 ASM_START
471 mov ax,ds
472 mov es,ax
473 mov di,si
474 xor cx,cx
475 not cx
476 xor al,al
478 repne
479 scasb
480 not cx
481 dec cx
482 push cx
484 mov ax,#0x0300
485 mov bx,#0x0000
486 int #0x10
488 pop cx
489 mov ax,#0x1301
490 mov bx,#0x000b
491 mov bp,si
492 int #0x10
493 ASM_END
496 // --------------------------------------------------------------------------------------------
497 #ifdef DEBUG
498 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
499 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
501 // 0E is write char...
502 if(GET_AH()!=0x0E)
503 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
505 #endif
507 // --------------------------------------------------------------------------------------------
509 * int10 main dispatcher
511 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
512 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
515 // BIOS functions
516 switch(GET_AH())
518 case 0x00:
519 biosfn_set_video_mode(GET_AL());
520 switch(GET_AL()&0x7F)
521 {case 6:
522 SET_AL(0x3F);
523 break;
524 case 0:
525 case 1:
526 case 2:
527 case 3:
528 case 4:
529 case 5:
530 case 7:
531 SET_AL(0x30);
532 break;
533 default:
534 SET_AL(0x20);
536 break;
537 case 0x01:
538 biosfn_set_cursor_shape(GET_CH(),GET_CL());
539 break;
540 case 0x02:
541 biosfn_set_cursor_pos(GET_BH(),DX);
542 break;
543 case 0x03:
544 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
545 break;
546 case 0x04:
547 // Read light pen pos (unimplemented)
548 #ifdef DEBUG
549 unimplemented();
550 #endif
551 AX=0x00;
552 BX=0x00;
553 CX=0x00;
554 DX=0x00;
555 break;
556 case 0x05:
557 biosfn_set_active_page(GET_AL());
558 break;
559 case 0x06:
560 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
561 break;
562 case 0x07:
563 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
564 break;
565 case 0x08:
566 biosfn_read_char_attr(GET_BH(),&AX);
567 break;
568 case 0x09:
569 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
570 break;
571 case 0x0A:
572 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
573 break;
574 case 0x0C:
575 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
576 break;
577 case 0x0D:
578 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
579 break;
580 case 0x0E:
581 // Ralf Brown Interrupt list is WRONG on bh(page)
582 // We do output only on the current page !
583 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
584 break;
585 case 0x10:
586 // All other functions of group AH=0x10 rewritten in assembler
587 biosfn_perform_gray_scale_summing(BX,CX);
588 break;
589 case 0x11:
590 switch(GET_AL())
592 case 0x00:
593 case 0x10:
594 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
595 break;
596 case 0x01:
597 case 0x11:
598 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
599 break;
600 case 0x02:
601 case 0x12:
602 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
603 break;
604 case 0x04:
605 case 0x14:
606 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
607 break;
608 case 0x20:
609 biosfn_load_gfx_8_8_chars(ES,BP);
610 break;
611 case 0x21:
612 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
613 break;
614 case 0x22:
615 biosfn_load_gfx_8_14_chars(GET_BL());
616 break;
617 case 0x23:
618 biosfn_load_gfx_8_8_dd_chars(GET_BL());
619 break;
620 case 0x24:
621 biosfn_load_gfx_8_16_chars(GET_BL());
622 break;
623 case 0x30:
624 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
625 break;
626 #ifdef DEBUG
627 default:
628 unknown();
629 #endif
632 break;
633 case 0x12:
634 switch(GET_BL())
636 case 0x20:
637 biosfn_alternate_prtsc();
638 break;
639 case 0x30:
640 biosfn_select_vert_res(GET_AL());
641 SET_AL(0x12);
642 break;
643 case 0x35:
644 biosfn_switch_video_interface(GET_AL(),ES,DX);
645 SET_AL(0x12);
646 break;
647 case 0x36:
648 biosfn_enable_video_refresh_control(GET_AL());
649 SET_AL(0x12);
650 break;
651 #ifdef DEBUG
652 default:
653 unknown();
654 #endif
656 break;
657 case 0x13:
658 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
659 break;
660 case 0x1B:
661 biosfn_read_state_info(BX,ES,DI);
662 SET_AL(0x1B);
663 break;
664 case 0x1C:
665 switch(GET_AL())
667 case 0x00:
668 biosfn_read_video_state_size(CX,&BX);
669 break;
670 case 0x01:
671 biosfn_save_video_state(CX,ES,BX);
672 break;
673 case 0x02:
674 biosfn_restore_video_state(CX,ES,BX);
675 break;
676 #ifdef DEBUG
677 default:
678 unknown();
679 #endif
681 SET_AL(0x1C);
682 break;
684 #ifdef VBE
685 case 0x4f:
686 if (vbe_has_vbe_display()) {
687 switch(GET_AL())
689 case 0x00:
690 vbe_biosfn_return_controller_information(&AX,ES,DI);
691 break;
692 case 0x01:
693 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
694 break;
695 case 0x02:
696 vbe_biosfn_set_mode(&AX,BX,ES,DI);
697 break;
698 case 0x03:
699 vbe_biosfn_return_current_mode(&AX,&BX);
700 break;
701 case 0x04:
702 //FIXME
703 #ifdef DEBUG
704 unimplemented();
705 #endif
706 // function failed
707 AX=0x100;
708 break;
709 case 0x05:
710 vbe_biosfn_display_window_control(&AX,BX,&DX);
711 break;
712 case 0x06:
713 vbe_biosfn_set_get_logical_scan_line_length(&AX,&BX,&CX,&DX);
714 break;
715 case 0x07:
716 vbe_biosfn_set_get_display_start(&AX,BX,CX,DX);
717 break;
718 case 0x08:
719 //FIXME
720 #ifdef DEBUG
721 unimplemented();
722 #endif
723 // function failed
724 AX=0x100;
725 break;
726 case 0x09:
727 //FIXME
728 #ifdef DEBUG
729 unimplemented();
730 #endif
731 // function failed
732 AX=0x100;
733 break;
734 case 0x0A:
735 //FIXME
736 #ifdef DEBUG
737 unimplemented();
738 #endif
739 // function failed
740 AX=0x100;
741 break;
742 #ifdef DEBUG
743 default:
744 unknown();
745 #endif
746 // function failed
747 AX=0x100;
750 else {
751 // No VBE display
752 AX=0x0100;
754 break;
755 #endif
757 #ifdef DEBUG
758 default:
759 unknown();
760 #endif
764 // ============================================================================================
766 // BIOS functions
768 // ============================================================================================
770 static void biosfn_set_video_mode(mode) Bit8u mode;
771 {// mode: Bit 7 is 1 if no clear screen
773 // Should we clear the screen ?
774 Bit8u noclearmem=mode&0x80;
775 Bit8u line,mmask,*palette;
776 Bit16u i,twidth,theight,cheight;
777 Bit8u modeset_ctl,video_ctl,vga_switches;
778 Bit16u crtc_addr;
780 #ifdef VBE
781 if (vbe_has_vbe_display()) {
782 dispi_set_enable(VBE_DISPI_DISABLED);
784 #endif // def VBE
786 // The real mode
787 mode=mode&0x7f;
789 // find the entry in the video modes
790 line=find_vga_entry(mode);
792 #ifdef DEBUG
793 printf("mode search %02x found line %02x\n",mode,line);
794 #endif
796 if(line==0xFF)
797 return;
799 twidth=vga_modes[line].twidth;
800 theight=vga_modes[line].theight;
801 cheight=vga_modes[line].cheight;
803 // Read the bios vga control
804 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
806 // Read the bios vga switches
807 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
809 // Read the bios mode set control
810 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
812 // Then we know the number of lines
813 // FIXME
815 // if palette loading (bit 3 of modeset ctl = 0)
816 if((modeset_ctl&0x08)==0)
817 {// Set the PEL mask
818 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
820 // Set the whole dac always, from 0
821 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
823 // From which palette
824 switch(vga_modes[line].dacmodel)
825 {case 0:
826 palette=&palette0;
827 break;
828 case 1:
829 palette=&palette1;
830 break;
831 case 2:
832 palette=&palette2;
833 break;
834 case 3:
835 palette=&palette3;
836 break;
838 // Always 256*3 values
839 for(i=0;i<0x0100;i++)
840 {if(i<=dac_regs[vga_modes[line].dacmodel])
841 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
842 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
843 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
845 else
846 {outb(VGAREG_DAC_DATA,0);
847 outb(VGAREG_DAC_DATA,0);
848 outb(VGAREG_DAC_DATA,0);
851 if((modeset_ctl&0x02)==0x02)
853 biosfn_perform_gray_scale_summing(0x00, 0x100);
857 // Reset Attribute Ctl flip-flop
858 inb(VGAREG_ACTL_RESET);
860 // Set Attribute Ctl
861 for(i=0;i<=ACTL_MAX_REG;i++)
862 {outb(VGAREG_ACTL_ADDRESS,i);
863 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
866 // Set Sequencer Ctl
867 for(i=0;i<=SEQU_MAX_REG;i++)
868 {outb(VGAREG_SEQU_ADDRESS,i);
869 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
872 // Set Grafx Ctl
873 for(i=0;i<=GRDC_MAX_REG;i++)
874 {outb(VGAREG_GRDC_ADDRESS,i);
875 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
878 // Set CRTC address VGA or MDA
879 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
881 // Set CRTC regs
882 for(i=0;i<=CRTC_MAX_REG;i++)
883 {outb(crtc_addr,i);
884 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
887 // Set the misc register
888 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
890 // Enable video
891 outb(VGAREG_ACTL_ADDRESS,0x20);
892 inb(VGAREG_ACTL_RESET);
894 if(noclearmem==0x00)
896 if(vga_modes[line].class==TEXT)
898 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
900 else
902 if(mode<0x0d)
904 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
906 else
908 outb( VGAREG_SEQU_ADDRESS, 0x02 );
909 mmask = inb( VGAREG_SEQU_DATA );
910 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
911 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
912 outb( VGAREG_SEQU_DATA, mmask );
917 // Set the BIOS mem
918 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
919 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
920 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
921 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
922 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
923 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
924 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
925 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
926 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
928 // FIXME We nearly have the good tables. to be reworked
929 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
930 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
931 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
933 // FIXME
934 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
935 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
937 // Set cursor shape
938 if(vga_modes[line].class==TEXT)
940 biosfn_set_cursor_shape(0x06,0x07);
943 // Set cursor pos for page 0..7
944 for(i=0;i<8;i++)
945 biosfn_set_cursor_pos(i,0x0000);
947 // Set active page 0
948 biosfn_set_active_page(0x00);
950 // Write the fonts in memory
951 if(vga_modes[line].class==TEXT)
953 ASM_START
954 ;; copy and activate 8x16 font
955 mov ax, #0x1104
956 mov bl, #0x00
957 int #0x10
958 mov ax, #0x1103
959 mov bl, #0x00
960 int #0x10
961 ASM_END
964 // Set the ints 0x1F and 0x43
965 ASM_START
966 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
967 ASM_END
969 switch(cheight)
970 {case 8:
971 ASM_START
972 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
973 ASM_END
974 break;
975 case 14:
976 ASM_START
977 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
978 ASM_END
979 break;
980 case 16:
981 ASM_START
982 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
983 ASM_END
984 break;
988 // --------------------------------------------------------------------------------------------
989 static void biosfn_set_cursor_shape (CH,CL)
990 Bit8u CH;Bit8u CL;
991 {Bit16u cheight,curs,crtc_addr;
992 Bit8u modeset_ctl;
994 CH&=0x3f;
995 CL&=0x1f;
997 curs=(CH<<8)+CL;
998 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1000 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
1001 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1002 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1004 if(CL!=(CH+1))
1006 CH = ((CH+1) * cheight / 8) -1;
1008 else
1010 CH = ((CL+1) * cheight / 8) - 2;
1012 CL = ((CL+1) * cheight / 8) - 1;
1015 // CTRC regs 0x0a and 0x0b
1016 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1017 outb(crtc_addr,0x0a);
1018 outb(crtc_addr+1,CH);
1019 outb(crtc_addr,0x0b);
1020 outb(crtc_addr+1,CL);
1023 // --------------------------------------------------------------------------------------------
1024 static void biosfn_set_cursor_pos (page, cursor)
1025 Bit8u page;Bit16u cursor;
1027 Bit8u xcurs,ycurs,current;
1028 Bit16u nbcols,nbrows,address,crtc_addr;
1030 // Should not happen...
1031 if(page>7)return;
1033 // Bios cursor pos
1034 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1036 // Set the hardware cursor
1037 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1038 if(page==current)
1040 // Get the dimensions
1041 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1042 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1044 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1046 // Calculate the address knowing nbcols nbrows and page num
1047 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1049 // CRTC regs 0x0e and 0x0f
1050 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1051 outb(crtc_addr,0x0e);
1052 outb(crtc_addr+1,(address&0xff00)>>8);
1053 outb(crtc_addr,0x0f);
1054 outb(crtc_addr+1,address&0x00ff);
1058 // --------------------------------------------------------------------------------------------
1059 static void biosfn_get_cursor_pos (page,shape, pos)
1060 Bit8u page;Bit16u *shape;Bit16u *pos;
1062 Bit16u ss=get_SS();
1064 // Default
1065 write_word(ss, shape, 0);
1066 write_word(ss, pos, 0);
1068 if(page>7)return;
1069 // FIXME should handle VGA 14/16 lines
1070 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1071 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1074 // --------------------------------------------------------------------------------------------
1075 static void biosfn_set_active_page (page)
1076 Bit8u page;
1078 Bit16u cursor,dummy,crtc_addr;
1079 Bit16u nbcols,nbrows,address;
1080 Bit8u mode,line;
1082 if(page>7)return;
1084 // Get the mode
1085 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1086 line=find_vga_entry(mode);
1087 if(line==0xFF)return;
1089 // Get pos curs pos for the right page
1090 biosfn_get_cursor_pos(page,&dummy,&cursor);
1092 if(vga_modes[line].class==TEXT)
1094 // Get the dimensions
1095 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1096 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1098 // Calculate the address knowing nbcols nbrows and page num
1099 address=SCREEN_MEM_START(nbcols,nbrows,page);
1100 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1102 // Start address
1103 address=SCREEN_IO_START(nbcols,nbrows,page);
1105 else
1107 address = page*vga_modes[line].slength;
1110 // CRTC regs 0x0c and 0x0d
1111 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1112 outb(crtc_addr,0x0c);
1113 outb(crtc_addr+1,(address&0xff00)>>8);
1114 outb(crtc_addr,0x0d);
1115 outb(crtc_addr+1,address&0x00ff);
1117 // And change the BIOS page
1118 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1120 #ifdef DEBUG
1121 printf("Set active page %02x address %04x\n",page,address);
1122 #endif
1124 // Display the cursor, now the page is active
1125 biosfn_set_cursor_pos(page,cursor);
1128 // --------------------------------------------------------------------------------------------
1129 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1130 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1132 Bit16u src,dest;
1133 Bit8u i;
1135 src=ysrc*cheight*nbcols+xstart;
1136 dest=ydest*cheight*nbcols+xstart;
1137 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1138 for(i=0;i<cheight;i++)
1140 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1142 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1145 // --------------------------------------------------------------------------------------------
1146 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight)
1147 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1149 Bit16u dest;
1150 Bit8u i;
1152 dest=ystart*cheight*nbcols+xstart;
1153 for(i=0;i<cheight;i++)
1155 memsetb(0xa000,dest+i*nbcols,0x00,cols);
1159 // --------------------------------------------------------------------------------------------
1160 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1161 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1163 // page == 0xFF if current
1165 Bit8u mode,line,cheight;
1166 Bit16u nbcols,nbrows,i;
1167 Bit16u address;
1169 if(rul>rlr)return;
1170 if(cul>clr)return;
1172 // Get the mode
1173 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1174 line=find_vga_entry(mode);
1175 if(line==0xFF)return;
1177 // Get the dimensions
1178 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1179 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1181 // Get the current page
1182 if(page==0xFF)
1183 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1185 if(rlr>=nbrows)rlr=nbrows-1;
1186 if(clr>=nbcols)clr=nbcols-1;
1187 if(nblines>nbrows)nblines=0;
1189 if(vga_modes[line].class==TEXT)
1191 // Compute the address
1192 address=SCREEN_MEM_START(nbcols,nbrows,page);
1193 #ifdef DEBUG
1194 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1195 #endif
1197 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1199 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1201 else
1202 {// if Scroll up
1203 if(dir==SCROLL_UP)
1204 {for(i=rul;i<=rlr;i++)
1206 if((i+nblines>rlr)||(nblines==0))
1207 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1208 else
1209 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,clr-cul+1);
1212 else
1213 {for(i=rlr;i>=rul;i--)
1215 if((i<rul+nblines)||(nblines==0))
1216 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',clr-cul+1);
1217 else
1218 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,clr-cul+1);
1223 else
1225 // FIXME gfx mode not complete
1226 cheight=vga_modes[line].cheight;
1227 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1229 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1231 memsetb(vga_modes[line].sstart,0,0x00,nbrows*nbcols*cheight);
1233 else
1234 {// if Scroll up
1235 if(dir==SCROLL_UP)
1236 {for(i=rul;i<=rlr;i++)
1238 if((i+nblines>rlr)||(nblines==0))
1239 vgamem_fill_pl4(cul,i,clr-cul+1,nbcols,cheight);
1240 else
1241 vgamem_copy_pl4(cul,i+nblines,i,clr-cul+1,nbcols,cheight);
1244 else
1245 {for(i=rlr;i>=rul;i--)
1247 if((i<rul+nblines)||(nblines==0))
1248 vgamem_fill_pl4(cul,i,clr-cul+1,nbcols,cheight);
1249 else
1250 vgamem_copy_pl4(cul,i,i-nblines,clr-cul+1,nbcols,cheight);
1255 else
1257 #ifdef DEBUG
1258 printf("Scroll in graphics mode ");
1259 unimplemented();
1260 #endif
1265 // --------------------------------------------------------------------------------------------
1266 static void biosfn_read_char_attr (page,car)
1267 Bit8u page;Bit16u *car;
1268 {Bit16u ss=get_SS();
1269 Bit8u xcurs,ycurs,mode,line;
1270 Bit16u nbcols,nbrows,address;
1271 Bit16u cursor,dummy;
1273 // Get the mode
1274 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1275 line=find_vga_entry(mode);
1276 if(line==0xFF)return;
1278 // Get the cursor pos for the page
1279 biosfn_get_cursor_pos(page,&dummy,&cursor);
1280 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1282 // Get the dimensions
1283 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1284 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1286 if(vga_modes[line].class==TEXT)
1288 // Compute the address
1289 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1291 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1293 else
1295 // FIXME gfx mode
1296 #ifdef DEBUG
1297 unimplemented();
1298 #endif
1302 // --------------------------------------------------------------------------------------------
1303 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1304 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1306 Bit8u i,j,mask;
1307 Bit8u *fdata;
1308 Bit16u addr,dest,src;
1310 switch(cheight)
1311 {case 14:
1312 fdata = &vgafont14;
1313 break;
1314 case 16:
1315 fdata = &vgafont16;
1316 break;
1317 default:
1318 fdata = &vgafont8;
1320 addr=xcurs+ycurs*cheight*nbcols;
1321 src = car * cheight;
1322 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1323 if(attr&0x80)
1325 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1327 for(i=0;i<cheight;i++)
1329 dest=addr+i*nbcols;
1330 for(j=0;j<8;j++)
1332 mask=0x80>>j;
1333 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1334 read_byte(0xa000,dest);
1335 if(fdata[src+i]&mask)
1337 write_byte(0xa000,dest,attr&0x0f);
1339 else
1341 write_byte(0xa000,dest,0x00);
1345 ASM_START
1346 mov dx, #vgareg_grdc_address
1347 mov ax, 0xff08
1348 out dx, ax
1349 mov ax, 0x0005
1350 out dx, ax
1351 mov ax, 0x0003
1352 out dx, ax
1353 ASM_END
1356 // --------------------------------------------------------------------------------------------
1357 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1358 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1360 Bit8u i,j,mask,data;
1361 Bit8u *fdata;
1362 Bit16u addr,dest,src;
1364 fdata = &vgafont8;
1365 addr=(xcurs*bpp)+ycurs*320;
1366 src = car * 8;
1367 for(i=0;i<8;i++)
1369 dest=addr+(i>>1)*80;
1370 if (i & 1) dest += 0x2000;
1371 mask = 0x80;
1372 if (bpp == 1)
1374 if (attr & 0x80)
1376 data = read_byte(0xb800,dest);
1378 else
1380 data = 0x00;
1382 for(j=0;j<8;j++)
1384 if (fdata[src+i] & mask)
1386 if (attr & 0x80)
1388 data ^= (attr & 0x01) << (7-j);
1390 else
1392 data |= (attr & 0x01) << (7-j);
1395 mask >>= 1;
1397 write_byte(0xb800,dest,data);
1399 else
1401 while (mask > 0)
1403 if (attr & 0x80)
1405 data = read_byte(0xb800,dest);
1407 else
1409 data = 0x00;
1411 for(j=0;j<4;j++)
1413 if (fdata[src+i] & mask)
1415 if (attr & 0x80)
1417 data ^= (attr & 0x03) << ((3-j)*2);
1419 else
1421 data |= (attr & 0x03) << ((3-j)*2);
1424 mask >>= 1;
1426 write_byte(0xb800,dest,data);
1427 dest += 1;
1433 // --------------------------------------------------------------------------------------------
1434 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1435 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1437 Bit8u i,j,mask,data;
1438 Bit8u *fdata;
1439 Bit16u addr,dest,src;
1441 fdata = &vgafont8;
1442 addr=xcurs*8+ycurs*nbcols*64;
1443 src = car * 8;
1444 for(i=0;i<8;i++)
1446 dest=addr+i*nbcols*8;
1447 mask = 0x80;
1448 for(j=0;j<8;j++)
1450 data = 0x00;
1451 if (fdata[src+i] & mask)
1453 data = attr;
1455 write_byte(0xa000,dest+j,data);
1456 mask >>= 1;
1461 // --------------------------------------------------------------------------------------------
1462 static void biosfn_write_char_attr (car,page,attr,count)
1463 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1465 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1466 Bit16u nbcols,nbrows,address;
1467 Bit16u cursor,dummy;
1469 // Get the mode
1470 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1471 line=find_vga_entry(mode);
1472 if(line==0xFF)return;
1474 // Get the cursor pos for the page
1475 biosfn_get_cursor_pos(page,&dummy,&cursor);
1476 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1478 // Get the dimensions
1479 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1480 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1482 if(vga_modes[line].class==TEXT)
1484 // Compute the address
1485 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1487 dummy=((Bit16u)attr<<8)+car;
1488 memsetw(vga_modes[line].sstart,address,dummy,count);
1490 else
1492 // FIXME gfx mode not complete
1493 cheight=vga_modes[line].cheight;
1494 bpp=vga_modes[line].pixbits;
1495 while((count-->0) && (xcurs<nbcols))
1497 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1499 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1501 else if(vga_modes[line].memmodel==CGA)
1503 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1505 else if(vga_modes[line].memmodel==LINEAR8)
1507 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1509 else
1511 #ifdef DEBUG
1512 unimplemented();
1513 #endif
1515 xcurs++;
1520 // --------------------------------------------------------------------------------------------
1521 static void biosfn_write_char_only (car,page,attr,count)
1522 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1524 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1525 Bit16u nbcols,nbrows,address;
1526 Bit16u cursor,dummy;
1528 // Get the mode
1529 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1530 line=find_vga_entry(mode);
1531 if(line==0xFF)return;
1533 // Get the cursor pos for the page
1534 biosfn_get_cursor_pos(page,&dummy,&cursor);
1535 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1537 // Get the dimensions
1538 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1539 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1541 if(vga_modes[line].class==TEXT)
1543 // Compute the address
1544 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1546 while(count-->0)
1547 {write_byte(vga_modes[line].sstart,address,car);
1548 address+=2;
1551 else
1553 // FIXME gfx mode not complete
1554 cheight=vga_modes[line].cheight;
1555 bpp=vga_modes[line].pixbits;
1556 while((count-->0) && (xcurs<nbcols))
1558 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1560 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1562 else if(vga_modes[line].memmodel==CGA)
1564 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1566 else if(vga_modes[line].memmodel==LINEAR8)
1568 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1570 else
1572 #ifdef DEBUG
1573 unimplemented();
1574 #endif
1576 xcurs++;
1581 // --------------------------------------------------------------------------------------------
1582 ASM_START
1583 biosfn_group_0B:
1584 cmp bh, #0x00
1585 je biosfn_set_border_color
1586 cmp bh, #0x01
1587 je biosfn_set_palette
1588 #ifdef DEBUG
1589 call _unknown
1590 #endif
1592 biosfn_set_border_color:
1593 push ax
1594 push bx
1595 push cx
1596 push dx
1597 mov dx, #vgareg_actl_reset
1598 in al, dx
1599 mov dx, #vgareg_actl_address
1600 mov al, #0x00
1601 out dx, al
1602 mov al, bl
1603 and al, #0x0f
1604 test al, #0x08
1605 jz set_low_border
1606 add al, #0x08
1607 set_low_border:
1608 out dx, al
1609 mov cl, #0x01
1610 and bl, #0x10
1611 set_intensity_loop:
1612 mov dx, #vgareg_actl_address
1613 mov al, cl
1614 out dx, al
1615 mov dx, #vgareg_actl_read_data
1616 in al, dx
1617 and al, #0xef
1618 or al, bl
1619 mov dx, #vgareg_actl_address
1620 out dx, al
1621 inc cl
1622 cmp cl, #0x04
1623 jne set_intensity_loop
1624 mov al, #0x20
1625 out dx, al
1626 pop dx
1627 pop cx
1628 pop bx
1629 pop ax
1631 biosfn_set_palette:
1632 push ax
1633 push bx
1634 push cx
1635 push dx
1636 mov dx, #vgareg_actl_reset
1637 in al, dx
1638 mov cl, #0x01
1639 and bl, #0x01
1640 set_cga_palette_loop:
1641 mov dx, #vgareg_actl_address
1642 mov al, cl
1643 out dx, al
1644 mov dx, #vgareg_actl_read_data
1645 in al, dx
1646 and al, #0xfe
1647 or al, bl
1648 mov dx, #vgareg_actl_address
1649 out dx, al
1650 inc cl
1651 cmp cl, #0x04
1652 jne set_cga_palette_loop
1653 mov al, #0x20
1654 out dx, al
1655 pop dx
1656 pop cx
1657 pop bx
1658 pop ax
1660 ASM_END
1662 // --------------------------------------------------------------------------------------------
1663 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1665 Bit8u mode,line,mask,attr,data;
1666 Bit16u addr;
1668 // Get the mode
1669 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1670 line=find_vga_entry(mode);
1671 if(line==0xFF)return;
1672 if(vga_modes[line].class==TEXT)return;
1674 switch(vga_modes[line].memmodel)
1676 case PLANAR4:
1677 case PLANAR1:
1678 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1679 mask = 0x01 << (7 - (CX & 0x07));
1680 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1681 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1682 data = read_byte(0xa000,addr);
1683 if (AL & 0x80)
1685 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1687 write_byte(0xa000,addr,AL);
1688 outw(VGAREG_GRDC_ADDRESS, 0xff08);
1689 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1690 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1691 break;
1692 case CGA:
1693 if(vga_modes[line].pixbits==2)
1695 addr=(CX>>2)+(DX>>1)*80;
1697 else
1699 addr=(CX>>3)+(DX>>1)*80;
1701 if (DX & 1) addr += 0x2000;
1702 data = read_byte(0xb800,addr);
1703 if(vga_modes[line].pixbits==2)
1705 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1706 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1708 else
1710 attr = (AL & 0x01) << (7 - (CX & 0x07));
1711 mask = 0x01 << (7 - (CX & 0x07));
1713 if (AL & 0x80)
1715 data ^= attr;
1717 else
1719 data &= ~mask;
1720 data |= attr;
1722 write_byte(0xb800,addr,data);
1723 break;
1724 case LINEAR8:
1725 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1726 write_byte(0xa000,addr,AL);
1727 break;
1728 #ifdef DEBUG
1729 default:
1730 unimplemented();
1731 #endif
1735 // --------------------------------------------------------------------------------------------
1736 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1738 Bit8u mode,line,mask,attr,data,i;
1739 Bit16u addr;
1740 Bit16u ss=get_SS();
1742 // Get the mode
1743 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1744 line=find_vga_entry(mode);
1745 if(line==0xFF)return;
1746 if(vga_modes[line].class==TEXT)return;
1748 switch(vga_modes[line].memmodel)
1750 case PLANAR4:
1751 case PLANAR1:
1752 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1753 mask = 0x01 << (7 - (CX & 0x07));
1754 attr = 0x00;
1755 for(i=0;i<4;i++)
1757 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1758 data = read_byte(0xa000,addr) & mask;
1759 if (data > 0) attr |= (0x01 << i);
1761 break;
1762 case CGA:
1763 addr=(CX>>2)+(DX>>1)*80;
1764 if (DX & 1) addr += 0x2000;
1765 data = read_byte(0xb800,addr);
1766 if(vga_modes[line].pixbits==2)
1768 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1770 else
1772 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1774 break;
1775 case LINEAR8:
1776 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1777 attr=read_byte(0xa000,addr);
1778 break;
1779 default:
1780 #ifdef DEBUG
1781 unimplemented();
1782 #endif
1783 attr = 0;
1785 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1788 // --------------------------------------------------------------------------------------------
1789 static void biosfn_write_teletype (car, page, attr, flag)
1790 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1791 {// flag = WITH_ATTR / NO_ATTR
1793 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1794 Bit16u nbcols,nbrows,address;
1795 Bit16u cursor,dummy;
1797 // special case if page is 0xff, use current page
1798 if(page==0xff)
1799 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1801 // Get the mode
1802 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1803 line=find_vga_entry(mode);
1804 if(line==0xFF)return;
1806 // Get the cursor pos for the page
1807 biosfn_get_cursor_pos(page,&dummy,&cursor);
1808 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1810 // Get the dimensions
1811 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1812 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1814 switch(car)
1816 case 7:
1817 //FIXME should beep
1818 break;
1820 case 8:
1821 if(xcurs>0)xcurs--;
1822 break;
1824 case '\r':
1825 xcurs=0;
1826 break;
1828 case '\n':
1829 xcurs=0;
1830 ycurs++;
1831 break;
1833 case '\t':
1836 biosfn_write_teletype(' ',page,attr,flag);
1837 biosfn_get_cursor_pos(page,&dummy,&cursor);
1838 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1839 }while(xcurs%8==0);
1840 break;
1842 default:
1844 if(vga_modes[line].class==TEXT)
1846 // Compute the address
1847 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1849 // Write the char
1850 write_byte(vga_modes[line].sstart,address,car);
1852 if(flag==WITH_ATTR)
1853 write_byte(vga_modes[line].sstart,address+1,attr);
1855 else
1857 // FIXME gfx mode not complete
1858 cheight=vga_modes[line].cheight;
1859 bpp=vga_modes[line].pixbits;
1860 if((vga_modes[line].memmodel==PLANAR4)||(vga_modes[line].memmodel==PLANAR1))
1862 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1864 else if(vga_modes[line].memmodel==CGA)
1866 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1868 else if(vga_modes[line].memmodel==LINEAR8)
1870 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1872 else
1874 #ifdef DEBUG
1875 unimplemented();
1876 #endif
1880 xcurs++;
1883 // Do we need to wrap ?
1884 if(xcurs==nbcols)
1885 {xcurs=0;
1886 ycurs++;
1889 // Do we need to scroll ?
1890 if(ycurs==nbrows)
1891 {biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1892 ycurs-=1;
1895 // Set the cursor for the page
1896 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1897 biosfn_set_cursor_pos(page,cursor);
1900 // --------------------------------------------------------------------------------------------
1901 ASM_START
1902 biosfn_get_video_mode:
1903 push ds
1904 mov ax, #biosmem_seg
1905 mov ds, ax
1906 push bx
1907 mov bx, #biosmem_current_page
1908 mov al, [bx]
1909 pop bx
1910 mov bh, al
1911 push bx
1912 mov bx, #biosmem_video_ctl
1913 mov ah, [bx]
1914 and ah, #0x80
1915 mov bx, #biosmem_current_mode
1916 mov al, [bx]
1917 or al, ah
1918 mov bx, #biosmem_nb_cols
1919 mov ah, [bx]
1920 pop bx
1921 pop ds
1923 ASM_END
1925 // --------------------------------------------------------------------------------------------
1926 ASM_START
1927 biosfn_group_10:
1928 cmp al, #0x00
1929 jne int10_test_1001
1930 jmp biosfn_set_single_palette_reg
1931 int10_test_1001:
1932 cmp al, #0x01
1933 jne int10_test_1002
1934 jmp biosfn_set_overscan_border_color
1935 int10_test_1002:
1936 cmp al, #0x02
1937 jne int10_test_1003
1938 jmp biosfn_set_all_palette_reg
1939 int10_test_1003:
1940 cmp al, #0x03
1941 jne int10_test_1007
1942 jmp biosfn_toggle_intensity
1943 int10_test_1007:
1944 cmp al, #0x07
1945 jne int10_test_1008
1946 jmp biosfn_get_single_palette_reg
1947 int10_test_1008:
1948 cmp al, #0x08
1949 jne int10_test_1009
1950 jmp biosfn_read_overscan_border_color
1951 int10_test_1009:
1952 cmp al, #0x09
1953 jne int10_test_1010
1954 jmp biosfn_get_all_palette_reg
1955 int10_test_1010:
1956 cmp al, #0x10
1957 jne int10_test_1012
1958 jmp biosfn_set_single_dac_reg
1959 int10_test_1012:
1960 cmp al, #0x12
1961 jne int10_test_1013
1962 jmp biosfn_set_all_dac_reg
1963 int10_test_1013:
1964 cmp al, #0x13
1965 jne int10_test_1015
1966 jmp biosfn_select_video_dac_color_page
1967 int10_test_1015:
1968 cmp al, #0x15
1969 jne int10_test_1017
1970 jmp biosfn_read_single_dac_reg
1971 int10_test_1017:
1972 cmp al, #0x17
1973 jne int10_test_1018
1974 jmp biosfn_read_all_dac_reg
1975 int10_test_1018:
1976 cmp al, #0x18
1977 jne int10_test_1019
1978 jmp biosfn_set_pel_mask
1979 int10_test_1019:
1980 cmp al, #0x19
1981 jne int10_test_101A
1982 jmp biosfn_read_pel_mask
1983 int10_test_101A:
1984 cmp al, #0x1a
1985 jne int10_group_10_unknown
1986 jmp biosfn_read_video_dac_state
1987 int10_group_10_unknown:
1988 #ifdef DEBUG
1989 call _unknown
1990 #endif
1993 biosfn_set_single_palette_reg:
1994 cmp bl, #0x14
1995 ja no_actl_reg1
1996 push ax
1997 push dx
1998 mov dx, #vgareg_actl_reset
1999 in al, dx
2000 mov dx, #vgareg_actl_address
2001 mov al, bl
2002 out dx, al
2003 mov al, bh
2004 out dx, al
2005 mov al, #0x20
2006 out dx, al
2007 pop dx
2008 pop ax
2009 no_actl_reg1:
2011 ASM_END
2013 // --------------------------------------------------------------------------------------------
2014 ASM_START
2015 biosfn_set_overscan_border_color:
2016 push bx
2017 mov bl, #0x11
2018 call biosfn_set_single_palette_reg
2019 pop bx
2021 ASM_END
2023 // --------------------------------------------------------------------------------------------
2024 ASM_START
2025 biosfn_set_all_palette_reg:
2026 push ax
2027 push bx
2028 push cx
2029 push dx
2030 mov bx, dx
2031 mov dx, #vgareg_actl_reset
2032 in al, dx
2033 mov cl, #0x00
2034 mov dx, #vgareg_actl_address
2035 set_palette_loop:
2036 mov al, cl
2037 out dx, al
2038 seg es
2039 mov al, [bx]
2040 out dx, al
2041 inc bx
2042 inc cl
2043 cmp cl, #0x10
2044 jne set_palette_loop
2045 mov al, #0x11
2046 out dx, al
2047 seg es
2048 mov al, [bx]
2049 out dx, al
2050 mov al, #0x20
2051 out dx, al
2052 pop dx
2053 pop cx
2054 pop bx
2055 pop ax
2057 ASM_END
2059 // --------------------------------------------------------------------------------------------
2060 ASM_START
2061 biosfn_toggle_intensity:
2062 push ax
2063 push bx
2064 push dx
2065 mov dx, #vgareg_actl_reset
2066 in al, dx
2067 mov dx, #vgareg_actl_address
2068 mov al, #0x10
2069 out dx, al
2070 mov dx, #vgareg_actl_read_data
2071 in al, dx
2072 and al, #0xf7
2073 and bl, #0x01
2074 shl bl, 3
2075 or al, bl
2076 mov dx, #vgareg_actl_address
2077 out dx, al
2078 mov al, #0x20
2079 out dx, al
2080 pop dx
2081 pop bx
2082 pop ax
2084 ASM_END
2086 // --------------------------------------------------------------------------------------------
2087 ASM_START
2088 biosfn_get_single_palette_reg:
2089 cmp bl, #0x14
2090 ja no_actl_reg2
2091 push ax
2092 push dx
2093 mov dx, #vgareg_actl_reset
2094 in al, dx
2095 mov dx, #vgareg_actl_address
2096 mov al, bl
2097 out dx, al
2098 mov dx, #vgareg_actl_read_data
2099 in al, dx
2100 mov bh, al
2101 mov dx, #vgareg_actl_reset
2102 in al, dx
2103 mov dx, #vgareg_actl_address
2104 mov al, #0x20
2105 out dx, al
2106 pop dx
2107 pop ax
2108 no_actl_reg2:
2110 ASM_END
2112 // --------------------------------------------------------------------------------------------
2113 ASM_START
2114 biosfn_read_overscan_border_color:
2115 push ax
2116 push bx
2117 mov bl, #0x11
2118 call biosfn_get_single_palette_reg
2119 mov al, bh
2120 pop bx
2121 mov bh, al
2122 pop ax
2124 ASM_END
2126 // --------------------------------------------------------------------------------------------
2127 ASM_START
2128 biosfn_get_all_palette_reg:
2129 push ax
2130 push bx
2131 push cx
2132 push dx
2133 mov bx, dx
2134 mov cl, #0x00
2135 get_palette_loop:
2136 mov dx, #vgareg_actl_reset
2137 in al, dx
2138 mov dx, #vgareg_actl_address
2139 mov al, cl
2140 out dx, al
2141 mov dx, #vgareg_actl_read_data
2142 in al, dx
2143 seg es
2144 mov [bx], al
2145 inc bx
2146 inc cl
2147 cmp cl, #0x10
2148 jne get_palette_loop
2149 mov dx, #vgareg_actl_reset
2150 in al, dx
2151 mov dx, #vgareg_actl_address
2152 mov al, #0x11
2153 out dx, al
2154 mov dx, #vgareg_actl_read_data
2155 in al, dx
2156 seg es
2157 mov [bx], al
2158 mov dx, #vgareg_actl_reset
2159 in al, dx
2160 mov dx, #vgareg_actl_address
2161 mov al, #0x20
2162 out dx, al
2163 pop dx
2164 pop cx
2165 pop bx
2166 pop ax
2168 ASM_END
2170 // --------------------------------------------------------------------------------------------
2171 ASM_START
2172 biosfn_set_single_dac_reg:
2173 push ax
2174 push dx
2175 mov dx, #vgareg_dac_write_address
2176 mov al, bl
2177 out dx, al
2178 mov dx, #vgareg_dac_data
2179 pop ax
2180 push ax
2181 mov al, ah
2182 out dx, al
2183 mov al, ch
2184 out dx, al
2185 mov al, cl
2186 out dx, al
2187 pop dx
2188 pop ax
2190 ASM_END
2192 // --------------------------------------------------------------------------------------------
2193 ASM_START
2194 biosfn_set_all_dac_reg:
2195 push ax
2196 push bx
2197 push cx
2198 push dx
2199 mov dx, #vgareg_dac_write_address
2200 mov al, bl
2201 out dx, al
2202 pop dx
2203 push dx
2204 mov bx, dx
2205 mov dx, #vgareg_dac_data
2206 set_dac_loop:
2207 seg es
2208 mov al, [bx]
2209 out dx, al
2210 inc bx
2211 seg es
2212 mov al, [bx]
2213 out dx, al
2214 inc bx
2215 seg es
2216 mov al, [bx]
2217 out dx, al
2218 inc bx
2219 dec cx
2220 jnz set_dac_loop
2221 pop dx
2222 pop cx
2223 pop bx
2224 pop ax
2226 ASM_END
2228 // --------------------------------------------------------------------------------------------
2229 ASM_START
2230 biosfn_select_video_dac_color_page:
2231 push ax
2232 push bx
2233 push dx
2234 mov dx, #vgareg_actl_reset
2235 in al, dx
2236 mov dx, #vgareg_actl_address
2237 mov al, #0x10
2238 out dx, al
2239 mov dx, #vgareg_actl_read_data
2240 in al, dx
2241 and bl, #0x01
2242 jnz set_dac_page
2243 and al, #0x7f
2244 shl bh, 7
2245 or al, bh
2246 mov dx, #vgareg_actl_address
2247 out dx, al
2248 jmp set_actl_normal
2249 set_dac_page:
2250 push ax
2251 mov dx, #vgareg_actl_reset
2252 in al, dx
2253 mov dx, #vgareg_actl_address
2254 mov al, #0x14
2255 out dx, al
2256 pop ax
2257 and al, #0x80
2258 jnz set_dac_16_page
2259 shl bh, 2
2260 set_dac_16_page:
2261 and bh, #0x0f
2262 mov al, bh
2263 out dx, al
2264 set_actl_normal:
2265 mov al, #0x20
2266 out dx, al
2267 pop dx
2268 pop bx
2269 pop ax
2271 ASM_END
2273 // --------------------------------------------------------------------------------------------
2274 ASM_START
2275 biosfn_read_single_dac_reg:
2276 push ax
2277 push dx
2278 mov dx, #vgareg_dac_read_address
2279 mov al, bl
2280 out dx, al
2281 pop ax
2282 mov ah, al
2283 mov dx, #vgareg_dac_data
2284 in al, dx
2285 xchg al, ah
2286 push ax
2287 in al, dx
2288 mov ch, al
2289 in al, dx
2290 mov cl, al
2291 pop dx
2292 pop ax
2294 ASM_END
2296 // --------------------------------------------------------------------------------------------
2297 ASM_START
2298 biosfn_read_all_dac_reg:
2299 push ax
2300 push bx
2301 push cx
2302 push dx
2303 mov dx, #vgareg_dac_read_address
2304 mov al, bl
2305 out dx, al
2306 pop dx
2307 push dx
2308 mov bx, dx
2309 mov dx, #vgareg_dac_data
2310 read_dac_loop:
2311 in al, dx
2312 seg es
2313 mov [bx], al
2314 inc bx
2315 in al, dx
2316 seg es
2317 mov [bx], al
2318 inc bx
2319 in al, dx
2320 seg es
2321 mov [bx], al
2322 inc bx
2323 dec cx
2324 jnz read_dac_loop
2325 pop dx
2326 pop cx
2327 pop bx
2328 pop ax
2330 ASM_END
2332 // --------------------------------------------------------------------------------------------
2333 ASM_START
2334 biosfn_set_pel_mask:
2335 push ax
2336 push dx
2337 mov dx, #vgareg_pel_mask
2338 mov al, bl
2339 out dx, al
2340 pop dx
2341 pop ax
2343 ASM_END
2345 // --------------------------------------------------------------------------------------------
2346 ASM_START
2347 biosfn_read_pel_mask:
2348 push ax
2349 push dx
2350 mov dx, #vgareg_pel_mask
2351 in al, dx
2352 mov bl, al
2353 pop dx
2354 pop ax
2356 ASM_END
2358 // --------------------------------------------------------------------------------------------
2359 ASM_START
2360 biosfn_read_video_dac_state:
2361 push ax
2362 push dx
2363 mov dx, #vgareg_actl_reset
2364 in al, dx
2365 mov dx, #vgareg_actl_address
2366 mov al, #0x10
2367 out dx, al
2368 mov dx, #vgareg_actl_read_data
2369 in al, dx
2370 mov bl, al
2371 shr bl, 7
2372 mov dx, #vgareg_actl_reset
2373 in al, dx
2374 mov dx, #vgareg_actl_address
2375 mov al, #0x14
2376 out dx, al
2377 mov dx, #vgareg_actl_read_data
2378 in al, dx
2379 mov bh, al
2380 and bh, #0x0f
2381 test bl, #0x01
2382 jnz get_dac_16_page
2383 shr bh, 2
2384 get_dac_16_page:
2385 mov dx, #vgareg_actl_reset
2386 in al, dx
2387 mov dx, #vgareg_actl_address
2388 mov al, #0x20
2389 out dx, al
2390 pop dx
2391 pop ax
2393 ASM_END
2395 // --------------------------------------------------------------------------------------------
2396 static void biosfn_perform_gray_scale_summing (start,count)
2397 Bit16u start;Bit16u count;
2398 {Bit8u r,g,b;
2399 Bit16u i;
2400 Bit16u index;
2402 inb(VGAREG_ACTL_RESET);
2403 outb(VGAREG_ACTL_ADDRESS,0x00);
2405 for( index = 0; index < count; index++ )
2407 // set read address and switch to read mode
2408 outb(VGAREG_DAC_READ_ADDRESS,start);
2409 // get 6-bit wide RGB data values
2410 r=inb( VGAREG_DAC_DATA );
2411 g=inb( VGAREG_DAC_DATA );
2412 b=inb( VGAREG_DAC_DATA );
2414 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2415 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2417 if(i>0x3f)i=0x3f;
2419 // set write address and switch to write mode
2420 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2421 // write new intensity value
2422 outb( VGAREG_DAC_DATA, i&0xff );
2423 outb( VGAREG_DAC_DATA, i&0xff );
2424 outb( VGAREG_DAC_DATA, i&0xff );
2425 start++;
2427 inb(VGAREG_ACTL_RESET);
2428 outb(VGAREG_ACTL_ADDRESS,0x20);
2431 // --------------------------------------------------------------------------------------------
2432 static void get_font_access()
2434 ASM_START
2435 mov dx, #vgareg_sequ_address
2436 mov ax, #0x0100
2437 out dx, ax
2438 mov ax, #0x0402
2439 out dx, ax
2440 mov ax, #0x0704
2441 out dx, ax
2442 mov ax, #0x0300
2443 out dx, ax
2444 mov dx, #vgareg_grdc_address
2445 mov ax, #0x0204
2446 out dx, ax
2447 mov ax, #0x0005
2448 out dx, ax
2449 mov ax, #0x0406
2450 out dx, ax
2451 ASM_END
2454 static void release_font_access()
2456 ASM_START
2457 mov dx, #vgareg_sequ_address
2458 mov ax, #0x0100
2459 out dx, ax
2460 mov ax, #0x0302
2461 out dx, ax
2462 mov ax, #0x0304
2463 out dx, ax
2464 mov ax, #0x0300
2465 out dx, ax
2466 mov dx, #vgareg_read_misc_output
2467 in al, dx
2468 and al, #0x01
2469 shl al, 2
2470 or al, #0x0a
2471 mov ah, al
2472 mov al, #0x06
2473 mov dx, #vgareg_grdc_address
2474 out dx, ax
2475 mov ax, #0x0004
2476 out dx, ax
2477 mov ax, #0x1005
2478 out dx, ax
2479 ASM_END
2482 ASM_START
2483 idiv_u:
2484 xor dx,dx
2485 div bx
2487 ASM_END
2489 static void set_scan_lines(lines) Bit8u lines;
2491 Bit16u crtc_addr,cols,page,vde;
2492 Bit8u crtc_r9,ovl,rows;
2494 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2495 outb(crtc_addr, 0x09);
2496 crtc_r9 = inb(crtc_addr+1);
2497 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2498 outb(crtc_addr+1, crtc_r9);
2499 if(lines==8)
2501 biosfn_set_cursor_shape(0x06,0x07);
2503 else
2505 biosfn_set_cursor_shape(lines-4,lines-3);
2507 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2508 outb(crtc_addr, 0x12);
2509 vde = inb(crtc_addr+1);
2510 outb(crtc_addr, 0x07);
2511 ovl = inb(crtc_addr+1);
2512 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2513 rows = vde / lines;
2514 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2515 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2516 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2519 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;
2521 Bit16u blockaddr,dest,i,src;
2523 get_font_access();
2524 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2525 for(i=0;i<CX;i++)
2527 src = BP + i * BH;
2528 dest = blockaddr + (DX + i) * 32;
2529 memcpyb(0xA000, dest, ES, src, BH);
2531 release_font_access();
2532 if(AL>=0x10)
2534 set_scan_lines(BH);
2538 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2540 Bit16u blockaddr,dest,i,src;
2542 get_font_access();
2543 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2544 for(i=0;i<0x100;i++)
2546 src = i * 14;
2547 dest = blockaddr + i * 32;
2548 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2550 release_font_access();
2551 if(AL>=0x10)
2553 set_scan_lines(14);
2557 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2559 Bit16u blockaddr,dest,i,src;
2561 get_font_access();
2562 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2563 for(i=0;i<0x100;i++)
2565 src = i * 8;
2566 dest = blockaddr + i * 32;
2567 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2569 release_font_access();
2570 if(AL>=0x10)
2572 set_scan_lines(8);
2576 // --------------------------------------------------------------------------------------------
2577 ASM_START
2578 biosfn_set_text_block_specifier:
2579 push ax
2580 push dx
2581 mov dx, #vgareg_sequ_address
2582 mov ah, bl
2583 mov al, #0x03
2584 out dx, ax
2585 pop dx
2586 pop ax
2588 ASM_END
2590 // --------------------------------------------------------------------------------------------
2591 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2593 Bit16u blockaddr,dest,i,src;
2595 get_font_access();
2596 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2597 for(i=0;i<0x100;i++)
2599 src = i * 16;
2600 dest = blockaddr + i * 32;
2601 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2603 release_font_access();
2604 if(AL>=0x10)
2606 set_scan_lines(16);
2610 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2612 #ifdef DEBUG
2613 unimplemented();
2614 #endif
2616 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2618 #ifdef DEBUG
2619 unimplemented();
2620 #endif
2622 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2624 #ifdef DEBUG
2625 unimplemented();
2626 #endif
2628 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2630 #ifdef DEBUG
2631 unimplemented();
2632 #endif
2634 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2636 #ifdef DEBUG
2637 unimplemented();
2638 #endif
2640 // --------------------------------------------------------------------------------------------
2641 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2642 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2643 {Bit16u ss=get_SS();
2645 switch(BH)
2646 {case 0x00:
2647 write_word(ss,ES,read_word(0x00,0x1f*4));
2648 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2649 break;
2650 case 0x01:
2651 write_word(ss,ES,read_word(0x00,0x43*4));
2652 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2653 break;
2654 case 0x02:
2655 write_word(ss,ES,0xC000);
2656 write_word(ss,BP,vgafont14);
2657 break;
2658 case 0x03:
2659 write_word(ss,ES,0xC000);
2660 write_word(ss,BP,vgafont8);
2661 break;
2662 case 0x04:
2663 write_word(ss,ES,0xC000);
2664 write_word(ss,BP,vgafont8+128*8);
2665 break;
2666 case 0x05:
2667 write_word(ss,ES,0xC000);
2668 write_word(ss,BP,vgafont14alt);
2669 break;
2670 case 0x06:
2671 write_word(ss,ES,0xC000);
2672 write_word(ss,BP,vgafont16);
2673 break;
2674 case 0x07:
2675 write_word(ss,ES,0xC000);
2676 write_word(ss,BP,vgafont16alt);
2677 break;
2678 default:
2679 #ifdef DEBUG
2680 printf("Get font info BH(%02x) was discarded\n",BH);
2681 #endif
2682 return;
2684 // Set byte/char of on screen font
2685 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2687 // Set Highest char row
2688 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2691 // --------------------------------------------------------------------------------------------
2692 ASM_START
2693 biosfn_get_ega_info:
2694 push ds
2695 push ax
2696 mov ax, #biosmem_seg
2697 mov ds, ax
2698 xor ch, ch
2699 mov bx, #biosmem_switches
2700 mov cl, [bx]
2701 and cl, #0x0f
2702 mov bx, #biosmem_crtc_address
2703 mov ax, [bx]
2704 mov bx, #0x0003
2705 cmp ax, #vgareg_mda_crtc_address
2706 jne mode_ega_color
2707 mov bh, #0x01
2708 mode_ega_color:
2709 pop ax
2710 pop ds
2712 ASM_END
2714 // --------------------------------------------------------------------------------------------
2715 static void biosfn_alternate_prtsc()
2717 #ifdef DEBUG
2718 unimplemented();
2719 #endif
2722 // --------------------------------------------------------------------------------------------
2723 static void biosfn_select_vert_res (res)
2724 Bit8u res;
2725 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2726 Bit8u modeset,switches;
2728 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2729 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2730 switch(res)
2731 {case 0x00:
2732 // set modeset ctl bit 7 and reset bit 4
2733 // set switches bit 3-0 to 0x08
2734 modeset|=0x80;modeset&=0xef;
2735 switches&=0xf0;switches|=0x08;
2736 break;
2737 case 0x01:
2738 // reset modeset ctl bit 7 and bit 4
2739 // set switches bit 3-0 to 0x09
2740 modeset&=0x6f;
2741 switches&=0xf0;switches|=0x09;
2742 break;
2743 case 0x02:
2744 // reset modeset ctl bit 7 and set bit 4
2745 // set switches bit 3-0 to 0x09
2746 modeset|=0x10;modeset&=0x7f;
2747 switches&=0xf0;switches|=0x09;
2748 break;
2749 default:
2750 #ifdef DEBUG
2751 printf("Select vert res (%02x) was discarded\n",res);
2752 #endif
2753 return;
2755 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2756 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2759 // --------------------------------------------------------------------------------------------
2760 ASM_START
2761 biosfn_enable_default_palette_loading:
2762 push ds
2763 push bx
2764 push dx
2765 mov dl, al
2766 and dl, #0x01
2767 shl dl, 3
2768 mov ax, #biosmem_seg
2769 mov ds, ax
2770 mov bx, #biosmem_modeset_ctl
2771 mov al, [bx]
2772 and al, #0xf7
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 ASM_START
2784 biosfn_enable_video_addressing:
2785 push bx
2786 push dx
2787 mov bl, al
2788 and bl, #0x01
2789 xor bl, #0x01
2790 shl bl, 1
2791 mov dx, #vgareg_read_misc_output
2792 in al, dx
2793 and al, #0xfd
2794 or al, bl
2795 mov dx, #vgareg_write_misc_output
2796 out dx, al
2797 mov ax, #0x1212
2798 pop dx
2799 pop bx
2801 ASM_END
2803 // --------------------------------------------------------------------------------------------
2804 ASM_START
2805 biosfn_enable_grayscale_summing:
2806 push ds
2807 push bx
2808 push dx
2809 mov dl, al
2810 and dl, #0x01
2811 xor dl, #0x01
2812 shl dl, 1
2813 mov ax, #biosmem_seg
2814 mov ds, ax
2815 mov bx, #biosmem_modeset_ctl
2816 mov al, [bx]
2817 and al, #0xfd
2818 or al, dl
2819 mov [bx], al
2820 mov ax, #0x1212
2821 pop dx
2822 pop bx
2823 pop ds
2825 ASM_END
2827 // --------------------------------------------------------------------------------------------
2828 ASM_START
2829 biosfn_enable_cursor_emulation:
2830 push ds
2831 push bx
2832 push dx
2833 mov dl, al
2834 and dl, #0x01
2835 xor dl, #0x01
2836 mov ax, #biosmem_seg
2837 mov ds, ax
2838 mov bx, #biosmem_modeset_ctl
2839 mov al, [bx]
2840 and al, #0xfe
2841 or al, dl
2842 mov [bx], al
2843 mov ax, #0x1212
2844 pop dx
2845 pop bx
2846 pop ds
2848 ASM_END
2850 // --------------------------------------------------------------------------------------------
2851 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2853 #ifdef DEBUG
2854 unimplemented();
2855 #endif
2857 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2859 #ifdef DEBUG
2860 unimplemented();
2861 #endif
2864 // --------------------------------------------------------------------------------------------
2865 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2866 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2868 Bit16u newcurs,oldcurs,dummy;
2869 Bit8u car,carattr;
2871 // Read curs info for the page
2872 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2874 // if row=0xff special case : use current cursor position
2875 if(row==0xff)
2876 {col=oldcurs&0x00ff;
2877 row=(oldcurs&0xff00)>>8;
2880 newcurs=row; newcurs<<=8; newcurs+=col;
2881 biosfn_set_cursor_pos(page,newcurs);
2883 while(count--!=0)
2885 car=read_byte(seg,offset++);
2886 if((flag&0x02)!=0)
2887 attr=read_byte(seg,offset++);
2889 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2892 // Set back curs pos
2893 if((flag&0x01)==0)
2894 biosfn_set_cursor_pos(page,oldcurs);
2897 // --------------------------------------------------------------------------------------------
2898 ASM_START
2899 biosfn_group_1A:
2900 cmp al, #0x00
2901 je biosfn_read_display_code
2902 cmp al, #0x01
2903 je biosfn_set_display_code
2904 #ifdef DEBUG
2905 call _unknown
2906 #endif
2908 biosfn_read_display_code:
2909 push ds
2910 push ax
2911 mov ax, #biosmem_seg
2912 mov ds, ax
2913 mov bx, #biosmem_dcc_index
2914 mov al, [bx]
2915 mov bl, al
2916 xor bh, bh
2917 pop ax
2918 mov al, ah
2919 pop ds
2921 biosfn_set_display_code:
2922 push ds
2923 push ax
2924 push bx
2925 mov ax, #biosmem_seg
2926 mov ds, ax
2927 mov ax, bx
2928 mov bx, #biosmem_dcc_index
2929 mov [bx], al
2930 #ifdef DEBUG
2931 mov al, ah
2932 xor ah, ah
2933 push ax
2934 mov bx, #msg_alt_dcc
2935 push bx
2936 call _printf
2937 add sp, #4
2938 #endif
2939 pop bx
2940 pop ax
2941 mov al, ah
2942 pop ds
2945 #ifdef DEBUG
2946 msg_alt_dcc:
2947 .ascii "Alternate Display code (%02x) was discarded"
2948 .byte 0x0d,0x0a,0x00
2949 #endif
2950 ASM_END
2952 // --------------------------------------------------------------------------------------------
2953 static void biosfn_read_state_info (BX,ES,DI)
2954 Bit16u BX;Bit16u ES;Bit16u DI;
2956 // Address of static functionality table
2957 write_word(ES,DI+0x00,&static_functionality);
2958 write_word(ES,DI+0x02,0xC000);
2960 // Hard coded copy from BIOS area. Should it be cleaner ?
2961 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
2962 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
2964 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2965 write_byte(ES,DI+0x26,0);
2966 write_byte(ES,DI+0x27,16);
2967 write_byte(ES,DI+0x28,0);
2968 write_byte(ES,DI+0x29,8);
2969 write_byte(ES,DI+0x2a,2);
2970 write_byte(ES,DI+0x2b,0);
2971 write_byte(ES,DI+0x2c,0);
2972 write_byte(ES,DI+0x31,3);
2973 write_byte(ES,DI+0x32,0);
2975 memsetb(ES,DI+0x33,0,13);
2978 // --------------------------------------------------------------------------------------------
2979 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2981 #ifdef DEBUG
2982 unimplemented();
2983 #endif
2985 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2987 #ifdef DEBUG
2988 unimplemented();
2989 #endif
2991 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
2993 #ifdef DEBUG
2994 unimplemented();
2995 #endif
2998 // ============================================================================================
3000 // Video Utils
3002 // ============================================================================================
3004 // --------------------------------------------------------------------------------------------
3005 static Bit8u find_vga_entry(mode)
3006 Bit8u mode;
3008 Bit8u i,line=0xFF;
3009 for(i=0;i<=MODE_MAX;i++)
3010 if(vga_modes[i].svgamode==mode)
3011 {line=i;
3012 break;
3014 return line;
3017 /* =========================================================== */
3019 * Misc Utils
3021 /* =========================================================== */
3023 // --------------------------------------------------------------------------------------------
3024 static void memsetb(seg,offset,value,count)
3025 Bit16u seg;
3026 Bit16u offset;
3027 Bit16u value;
3028 Bit16u count;
3030 ASM_START
3031 push bp
3032 mov bp, sp
3034 push ax
3035 push cx
3036 push es
3037 push di
3039 mov cx, 10[bp] ; count
3040 cmp cx, #0x00
3041 je memsetb_end
3042 mov ax, 4[bp] ; segment
3043 mov es, ax
3044 mov ax, 6[bp] ; offset
3045 mov di, ax
3046 mov al, 8[bp] ; value
3049 stosb
3051 memsetb_end:
3052 pop di
3053 pop es
3054 pop cx
3055 pop ax
3057 pop bp
3058 ASM_END
3061 // --------------------------------------------------------------------------------------------
3062 static void memsetw(seg,offset,value,count)
3063 Bit16u seg;
3064 Bit16u offset;
3065 Bit16u value;
3066 Bit16u count;
3068 ASM_START
3069 push bp
3070 mov bp, sp
3072 push ax
3073 push cx
3074 push es
3075 push di
3077 mov cx, 10[bp] ; count
3078 cmp cx, #0x00
3079 je memsetw_end
3080 mov ax, 4[bp] ; segment
3081 mov es, ax
3082 mov ax, 6[bp] ; offset
3083 mov di, ax
3084 mov ax, 8[bp] ; value
3087 stosw
3089 memsetw_end:
3090 pop di
3091 pop es
3092 pop cx
3093 pop ax
3095 pop bp
3096 ASM_END
3099 // --------------------------------------------------------------------------------------------
3100 static void memcpyb(dseg,doffset,sseg,soffset,count)
3101 Bit16u dseg;
3102 Bit16u doffset;
3103 Bit16u sseg;
3104 Bit16u soffset;
3105 Bit16u count;
3107 ASM_START
3108 push bp
3109 mov bp, sp
3111 push ax
3112 push cx
3113 push es
3114 push di
3115 push ds
3116 push si
3118 mov cx, 12[bp] ; count
3119 cmp cx, #0x0000
3120 je memcpyb_end
3121 mov ax, 4[bp] ; dsegment
3122 mov es, ax
3123 mov ax, 6[bp] ; doffset
3124 mov di, ax
3125 mov ax, 8[bp] ; ssegment
3126 mov ds, ax
3127 mov ax, 10[bp] ; soffset
3128 mov si, ax
3131 movsb
3133 memcpyb_end:
3134 pop si
3135 pop ds
3136 pop di
3137 pop es
3138 pop cx
3139 pop ax
3141 pop bp
3142 ASM_END
3145 // --------------------------------------------------------------------------------------------
3146 static void memcpyw(dseg,doffset,sseg,soffset,count)
3147 Bit16u dseg;
3148 Bit16u doffset;
3149 Bit16u sseg;
3150 Bit16u soffset;
3151 Bit16u count;
3153 ASM_START
3154 push bp
3155 mov bp, sp
3157 push ax
3158 push cx
3159 push es
3160 push di
3161 push ds
3162 push si
3164 mov cx, 12[bp] ; count
3165 cmp cx, #0x0000
3166 je memcpyw_end
3167 mov ax, 4[bp] ; dsegment
3168 mov es, ax
3169 mov ax, 6[bp] ; doffset
3170 mov di, ax
3171 mov ax, 8[bp] ; ssegment
3172 mov ds, ax
3173 mov ax, 10[bp] ; soffset
3174 mov si, ax
3177 movsw
3179 memcpyw_end:
3180 pop si
3181 pop ds
3182 pop di
3183 pop es
3184 pop cx
3185 pop ax
3187 pop bp
3188 ASM_END
3191 /* =========================================================== */
3193 * These functions where ripped from Kevin's rombios.c
3195 /* =========================================================== */
3197 // --------------------------------------------------------------------------------------------
3198 static Bit8u
3199 read_byte(seg, offset)
3200 Bit16u seg;
3201 Bit16u offset;
3203 ASM_START
3204 push bp
3205 mov bp, sp
3207 push bx
3208 push ds
3209 mov ax, 4[bp] ; segment
3210 mov ds, ax
3211 mov bx, 6[bp] ; offset
3212 mov al, [bx]
3213 ;; al = return value (byte)
3214 pop ds
3215 pop bx
3217 pop bp
3218 ASM_END
3221 // --------------------------------------------------------------------------------------------
3222 static Bit16u
3223 read_word(seg, offset)
3224 Bit16u seg;
3225 Bit16u offset;
3227 ASM_START
3228 push bp
3229 mov bp, sp
3231 push bx
3232 push ds
3233 mov ax, 4[bp] ; segment
3234 mov ds, ax
3235 mov bx, 6[bp] ; offset
3236 mov ax, [bx]
3237 ;; ax = return value (word)
3238 pop ds
3239 pop bx
3241 pop bp
3242 ASM_END
3245 // --------------------------------------------------------------------------------------------
3246 static void
3247 write_byte(seg, offset, data)
3248 Bit16u seg;
3249 Bit16u offset;
3250 Bit8u data;
3252 ASM_START
3253 push bp
3254 mov bp, sp
3256 push ax
3257 push bx
3258 push ds
3259 mov ax, 4[bp] ; segment
3260 mov ds, ax
3261 mov bx, 6[bp] ; offset
3262 mov al, 8[bp] ; data byte
3263 mov [bx], al ; write data byte
3264 pop ds
3265 pop bx
3266 pop ax
3268 pop bp
3269 ASM_END
3272 // --------------------------------------------------------------------------------------------
3273 static void
3274 write_word(seg, offset, data)
3275 Bit16u seg;
3276 Bit16u offset;
3277 Bit16u data;
3279 ASM_START
3280 push bp
3281 mov bp, sp
3283 push ax
3284 push bx
3285 push ds
3286 mov ax, 4[bp] ; segment
3287 mov ds, ax
3288 mov bx, 6[bp] ; offset
3289 mov ax, 8[bp] ; data word
3290 mov [bx], ax ; write data word
3291 pop ds
3292 pop bx
3293 pop ax
3295 pop bp
3296 ASM_END
3299 // --------------------------------------------------------------------------------------------
3300 Bit8u
3301 inb(port)
3302 Bit16u port;
3304 ASM_START
3305 push bp
3306 mov bp, sp
3308 push dx
3309 mov dx, 4[bp]
3310 in al, dx
3311 pop dx
3313 pop bp
3314 ASM_END
3317 Bit16u
3318 inw(port)
3319 Bit16u port;
3321 ASM_START
3322 push bp
3323 mov bp, sp
3325 push dx
3326 mov dx, 4[bp]
3327 in ax, dx
3328 pop dx
3330 pop bp
3331 ASM_END
3334 // --------------------------------------------------------------------------------------------
3335 void
3336 outb(port, val)
3337 Bit16u port;
3338 Bit8u val;
3340 ASM_START
3341 push bp
3342 mov bp, sp
3344 push ax
3345 push dx
3346 mov dx, 4[bp]
3347 mov al, 6[bp]
3348 out dx, al
3349 pop dx
3350 pop ax
3352 pop bp
3353 ASM_END
3356 // --------------------------------------------------------------------------------------------
3357 void
3358 outw(port, val)
3359 Bit16u port;
3360 Bit16u val;
3362 ASM_START
3363 push bp
3364 mov bp, sp
3366 push ax
3367 push dx
3368 mov dx, 4[bp]
3369 mov ax, 6[bp]
3370 out dx, ax
3371 pop dx
3372 pop ax
3374 pop bp
3375 ASM_END
3378 Bit16u get_SS()
3380 ASM_START
3381 mov ax, ss
3382 ASM_END
3385 #ifdef DEBUG
3386 void unimplemented()
3388 printf("--> Unimplemented\n");
3391 void unknown()
3393 printf("--> Unknown int10\n");
3395 #endif
3397 // --------------------------------------------------------------------------------------------
3398 void printf(s)
3399 Bit8u *s;
3401 Bit8u c, format_char;
3402 Boolean in_format;
3403 unsigned format_width, i;
3404 Bit16u *arg_ptr;
3405 Bit16u arg_seg, arg, digit, nibble, shift_count;
3407 arg_ptr = &s;
3408 arg_seg = get_SS();
3410 in_format = 0;
3411 format_width = 0;
3413 while (c = read_byte(0xc000, s)) {
3414 if ( c == '%' ) {
3415 in_format = 1;
3416 format_width = 0;
3418 else if (in_format) {
3419 if ( (c>='0') && (c<='9') ) {
3420 format_width = (format_width * 10) + (c - '0');
3422 else if (c == 'x') {
3423 arg_ptr++; // increment to next arg
3424 arg = read_word(arg_seg, arg_ptr);
3425 if (format_width == 0)
3426 format_width = 4;
3427 i = 0;
3428 digit = format_width - 1;
3429 for (i=0; i<format_width; i++) {
3430 nibble = (arg >> (4 * digit)) & 0x000f;
3431 if (nibble <= 9)
3432 outb(0x0500, nibble + '0');
3433 else
3434 outb(0x0500, (nibble - 10) + 'A');
3435 digit--;
3437 in_format = 0;
3439 //else if (c == 'd') {
3440 // in_format = 0;
3441 // }
3443 else {
3444 outb(0x0500, c);
3446 s ++;
3450 #ifdef VBE
3451 #include "vbe.c"
3452 #endif
3454 // --------------------------------------------------------------------------------------------
3456 ASM_START
3457 ;; DATA_SEG_DEFS_HERE
3458 ASM_END
3460 ASM_START
3461 .ascii "vgabios ends here"
3462 .byte 0x00
3463 vgabios_end:
3464 .byte 0xCB
3465 ;; BLOCK_STRINGS_BEGIN
3466 ASM_END