- biossums utility now supports VGABIOS sizes up to 64 kBytes
[vgabios.git] / vgabios.c
blobbef3b77917e49e579bf22b41b065c35aa250d613
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 #define USE_BX_INFO
59 /* Declares */
60 static Bit8u read_byte();
61 static Bit16u read_word();
62 static void write_byte();
63 static void write_word();
64 static Bit8u inb();
65 static Bit16u inw();
66 static void outb();
67 static void outw();
69 static Bit16u get_SS();
71 // Output
72 static void printf();
73 static void unimplemented();
74 static void unknown();
76 static Bit8u find_vga_entry();
78 static void memsetb();
79 static void memsetw();
80 static void memcpyb();
81 static void memcpyw();
83 static void biosfn_set_video_mode();
84 static void biosfn_set_cursor_shape();
85 static void biosfn_set_cursor_pos();
86 static void biosfn_get_cursor_pos();
87 static void biosfn_set_active_page();
88 static void biosfn_scroll();
89 static void biosfn_read_char_attr();
90 static void biosfn_write_char_attr();
91 static void biosfn_write_char_only();
92 static void biosfn_write_pixel();
93 static void biosfn_read_pixel();
94 static void biosfn_write_teletype();
95 static void biosfn_perform_gray_scale_summing();
96 static void biosfn_load_text_user_pat();
97 static void biosfn_load_text_8_14_pat();
98 static void biosfn_load_text_8_8_pat();
99 static void biosfn_load_text_8_16_pat();
100 static void biosfn_load_gfx_8_8_chars();
101 static void biosfn_load_gfx_user_chars();
102 static void biosfn_load_gfx_8_14_chars();
103 static void biosfn_load_gfx_8_8_dd_chars();
104 static void biosfn_load_gfx_8_16_chars();
105 static void biosfn_get_font_info();
106 static void biosfn_alternate_prtsc();
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 MACRO SET_INT_VECTOR
122 push ds
123 xor ax, ax
124 mov ds, ax
125 mov ax, ?3
126 mov ?1*4, ax
127 mov ax, ?2
128 mov ?1*4+2, ax
129 pop ds
130 MEND
132 ASM_END
134 ASM_START
135 .text
136 .rom
137 .org 0
139 use16 386
141 vgabios_start:
142 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
144 .byte 0x40 /* BIOS extension length in units of 512 bytes */
147 vgabios_entry_point:
149 jmp vgabios_init_func
151 vgabios_name:
152 .ascii "Plex86/Bochs VGABios"
153 .ascii " "
154 .byte 0x00
156 // Info from Bart Oldeman
157 .org 0x1e
158 .ascii "IBM"
159 .byte 0x00
161 vgabios_version:
162 #ifndef VGABIOS_VERS
163 .ascii "current-cvs"
164 #else
165 .ascii VGABIOS_VERS
166 #endif
167 .ascii " "
169 vgabios_date:
170 .ascii VGABIOS_DATE
171 .byte 0x0a,0x0d
172 .byte 0x00
174 vgabios_copyright:
175 .ascii "(C) 2003 the LGPL VGABios developers Team"
176 .byte 0x0a,0x0d
177 .byte 0x00
179 vgabios_license:
180 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
181 .byte 0x0a,0x0d
182 .byte 0x0a,0x0d
183 .byte 0x00
185 vgabios_website:
186 .ascii "Please visit :"
187 .byte 0x0a,0x0d
188 ;;.ascii " . http://www.plex86.org"
189 ;;.byte 0x0a,0x0d
190 .ascii " . http://bochs.sourceforge.net"
191 .byte 0x0a,0x0d
192 .ascii " . http://www.nongnu.org/vgabios"
193 .byte 0x0a,0x0d
194 .byte 0x0a,0x0d
195 .byte 0x00
198 ;; ============================================================================================
200 ;; Init Entry point
202 ;; ============================================================================================
203 vgabios_init_func:
205 ;; init vga card
206 call init_vga_card
208 ;; init basic bios vars
209 call init_bios_area
211 #ifdef VBE
212 ;; init vbe functions
213 call vbe_init
214 #endif
216 ;; set int10 vect
217 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
219 #ifdef CIRRUS
220 call cirrus_init
221 #endif
223 ;; display splash screen
224 call _display_splash_screen
226 ;; init video mode and clear the screen
227 mov ax,#0x0003
228 int #0x10
230 ;; show info
231 call _display_info
233 #ifdef VBE
234 ;; show vbe info
235 call vbe_display_info
236 #endif
238 #ifdef CIRRUS
239 ;; show cirrus info
240 call cirrus_display_info
241 #endif
243 retf
244 ASM_END
247 * int10 handled here
249 ASM_START
250 vgabios_int10_handler:
251 pushf
252 #ifdef DEBUG
253 push es
254 push ds
255 pusha
256 mov bx, #0xc000
257 mov ds, bx
258 call _int10_debugmsg
259 popa
260 pop ds
261 pop es
262 #endif
263 cmp ah, #0x0f
264 jne int10_test_1A
265 call biosfn_get_video_mode
266 jmp int10_end
267 int10_test_1A:
268 cmp ah, #0x1a
269 jne int10_test_0B
270 call biosfn_group_1A
271 jmp int10_end
272 int10_test_0B:
273 cmp ah, #0x0b
274 jne int10_test_1103
275 call biosfn_group_0B
276 jmp int10_end
277 int10_test_1103:
278 cmp ax, #0x1103
279 jne int10_test_12
280 call biosfn_set_text_block_specifier
281 jmp int10_end
282 int10_test_12:
283 cmp ah, #0x12
284 jne int10_test_101B
285 cmp bl, #0x10
286 jne int10_test_BL30
287 call biosfn_get_ega_info
288 jmp int10_end
289 int10_test_BL30:
290 cmp bl, #0x30
291 jne int10_test_BL31
292 call biosfn_select_vert_res
293 jmp int10_end
294 int10_test_BL31:
295 cmp bl, #0x31
296 jne int10_test_BL32
297 call biosfn_enable_default_palette_loading
298 jmp int10_end
299 int10_test_BL32:
300 cmp bl, #0x32
301 jne int10_test_BL33
302 call biosfn_enable_video_addressing
303 jmp int10_end
304 int10_test_BL33:
305 cmp bl, #0x33
306 jne int10_test_BL34
307 call biosfn_enable_grayscale_summing
308 jmp int10_end
309 int10_test_BL34:
310 cmp bl, #0x34
311 jne int10_normal
312 call biosfn_enable_cursor_emulation
313 jmp int10_end
314 int10_test_101B:
315 cmp ax, #0x101b
316 je int10_normal
317 cmp ah, #0x10
318 #ifndef VBE
319 jne int10_normal
320 #else
321 jne int10_test_4F
322 #endif
323 call biosfn_group_10
324 jmp int10_end
325 #ifdef VBE
326 int10_test_4F:
327 cmp ah, #0x4f
328 jne int10_normal
329 cmp al, #0x03
330 jne int10_test_vbe_05
331 call vbe_biosfn_return_current_mode
332 jmp int10_end
333 int10_test_vbe_05:
334 cmp al, #0x05
335 jne int10_test_vbe_06
336 call vbe_biosfn_display_window_control
337 jmp int10_end
338 int10_test_vbe_06:
339 cmp al, #0x06
340 jne int10_test_vbe_07
341 call vbe_biosfn_set_get_logical_scan_line_length
342 jmp int10_end
343 int10_test_vbe_07:
344 cmp al, #0x07
345 jne int10_test_vbe_08
346 call vbe_biosfn_set_get_display_start
347 jmp int10_end
348 int10_test_vbe_08:
349 cmp al, #0x08
350 jne int10_test_vbe_0A
351 call vbe_biosfn_set_get_dac_palette_format
352 jmp int10_end
353 int10_test_vbe_0A:
354 cmp al, #0x0A
355 jne int10_normal
356 call vbe_biosfn_return_protected_mode_interface
357 jmp int10_end
358 #endif
360 int10_normal:
361 push es
362 push ds
363 pusha
365 ;; We have to set ds to access the right data segment
366 mov bx, #0xc000
367 mov ds, bx
368 call _int10_func
370 popa
371 pop ds
372 pop es
373 int10_end:
374 popf
375 iret
376 ASM_END
378 #include "vgatables.h"
379 #include "vgafonts.h"
382 * Boot time harware inits
384 ASM_START
385 init_vga_card:
386 ;; switch to color mode and enable CPU access 480 lines
387 mov dx, #0x3C2
388 mov al, #0xC3
389 outb dx,al
391 ;; more than 64k 3C4/04
392 mov dx, #0x3C4
393 mov al, #0x04
394 outb dx,al
395 mov dx, #0x3C5
396 mov al, #0x02
397 outb dx,al
399 #if defined(USE_BX_INFO) || defined(DEBUG)
400 mov bx, #msg_vga_init
401 push bx
402 call _printf
403 #endif
404 inc sp
405 inc sp
408 #if defined(USE_BX_INFO) || defined(DEBUG)
409 msg_vga_init:
410 .ascii "VGABios $Id$"
411 .byte 0x0d,0x0a,0x00
412 #endif
413 ASM_END
415 // --------------------------------------------------------------------------------------------
417 * Boot time bios area inits
419 ASM_START
420 init_bios_area:
421 push ds
422 mov ax, # BIOSMEM_SEG
423 mov ds, ax
425 ;; init detected hardware BIOS Area
426 mov bx, # BIOSMEM_INITIAL_MODE
427 mov ax, [bx]
428 and ax, #0xffcf
429 ;; set 80x25 color (not clear from RBIL but usual)
430 or ax, #0x0020
431 mov [bx], ax
433 ;; Just for the first int10 find its children
435 ;; the default char height
436 mov bx, # BIOSMEM_CHAR_HEIGHT
437 mov al, #0x10
438 mov [bx], al
440 ;; Clear the screen
441 mov bx, # BIOSMEM_VIDEO_CTL
442 mov al, #0x60
443 mov [bx], al
445 ;; Set the basic screen we have
446 mov bx, # BIOSMEM_SWITCHES
447 mov al, #0xf9
448 mov [bx], al
450 ;; Set the basic modeset options
451 mov bx, # BIOSMEM_MODESET_CTL
452 mov al, #0x51
453 mov [bx], al
455 ;; Set the default MSR
456 mov bx, # BIOSMEM_CURRENT_MSR
457 mov al, #0x09
458 mov [bx], al
460 pop ds
462 ASM_END
464 // --------------------------------------------------------------------------------------------
466 * Boot time Splash screen
468 static void display_splash_screen()
472 // --------------------------------------------------------------------------------------------
474 * Tell who we are
477 static void display_info()
479 ASM_START
480 mov ax,#0xc000
481 mov ds,ax
482 mov si,#vgabios_name
483 call _display_string
484 mov si,#vgabios_version
485 call _display_string
487 ;;mov si,#vgabios_copyright
488 ;;call _display_string
489 ;;mov si,#crlf
490 ;;call _display_string
492 mov si,#vgabios_license
493 call _display_string
494 mov si,#vgabios_website
495 call _display_string
496 ASM_END
499 static void display_string()
501 // Get length of string
502 ASM_START
503 mov ax,ds
504 mov es,ax
505 mov di,si
506 xor cx,cx
507 not cx
508 xor al,al
510 repne
511 scasb
512 not cx
513 dec cx
514 push cx
516 mov ax,#0x0300
517 mov bx,#0x0000
518 int #0x10
520 pop cx
521 mov ax,#0x1301
522 mov bx,#0x000b
523 mov bp,si
524 int #0x10
525 ASM_END
528 // --------------------------------------------------------------------------------------------
529 #ifdef DEBUG
530 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
531 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
533 // 0E is write char...
534 if(GET_AH()!=0x0E)
535 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
537 #endif
539 // --------------------------------------------------------------------------------------------
541 * int10 main dispatcher
543 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
544 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
547 // BIOS functions
548 switch(GET_AH())
550 case 0x00:
551 biosfn_set_video_mode(GET_AL());
552 switch(GET_AL()&0x7F)
553 {case 6:
554 SET_AL(0x3F);
555 break;
556 case 0:
557 case 1:
558 case 2:
559 case 3:
560 case 4:
561 case 5:
562 case 7:
563 SET_AL(0x30);
564 break;
565 default:
566 SET_AL(0x20);
568 break;
569 case 0x01:
570 biosfn_set_cursor_shape(GET_CH(),GET_CL());
571 break;
572 case 0x02:
573 biosfn_set_cursor_pos(GET_BH(),DX);
574 break;
575 case 0x03:
576 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
577 break;
578 case 0x04:
579 // Read light pen pos (unimplemented)
580 #ifdef DEBUG
581 unimplemented();
582 #endif
583 AX=0x00;
584 BX=0x00;
585 CX=0x00;
586 DX=0x00;
587 break;
588 case 0x05:
589 biosfn_set_active_page(GET_AL());
590 break;
591 case 0x06:
592 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
593 break;
594 case 0x07:
595 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
596 break;
597 case 0x08:
598 biosfn_read_char_attr(GET_BH(),&AX);
599 break;
600 case 0x09:
601 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
602 break;
603 case 0x0A:
604 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
605 break;
606 case 0x0C:
607 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
608 break;
609 case 0x0D:
610 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
611 break;
612 case 0x0E:
613 // Ralf Brown Interrupt list is WRONG on bh(page)
614 // We do output only on the current page !
615 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
616 break;
617 case 0x10:
618 // All other functions of group AH=0x10 rewritten in assembler
619 biosfn_perform_gray_scale_summing(BX,CX);
620 break;
621 case 0x11:
622 switch(GET_AL())
624 case 0x00:
625 case 0x10:
626 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
627 break;
628 case 0x01:
629 case 0x11:
630 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
631 break;
632 case 0x02:
633 case 0x12:
634 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
635 break;
636 case 0x04:
637 case 0x14:
638 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
639 break;
640 case 0x20:
641 biosfn_load_gfx_8_8_chars(ES,BP);
642 break;
643 case 0x21:
644 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
645 break;
646 case 0x22:
647 biosfn_load_gfx_8_14_chars(GET_BL());
648 break;
649 case 0x23:
650 biosfn_load_gfx_8_8_dd_chars(GET_BL());
651 break;
652 case 0x24:
653 biosfn_load_gfx_8_16_chars(GET_BL());
654 break;
655 case 0x30:
656 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
657 break;
658 #ifdef DEBUG
659 default:
660 unknown();
661 #endif
664 break;
665 case 0x12:
666 switch(GET_BL())
668 case 0x20:
669 biosfn_alternate_prtsc();
670 break;
671 case 0x35:
672 biosfn_switch_video_interface(GET_AL(),ES,DX);
673 SET_AL(0x12);
674 break;
675 case 0x36:
676 biosfn_enable_video_refresh_control(GET_AL());
677 SET_AL(0x12);
678 break;
679 #ifdef DEBUG
680 default:
681 unknown();
682 #endif
684 break;
685 case 0x13:
686 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
687 break;
688 case 0x1B:
689 biosfn_read_state_info(BX,ES,DI);
690 SET_AL(0x1B);
691 break;
692 case 0x1C:
693 switch(GET_AL())
695 case 0x00:
696 biosfn_read_video_state_size(CX,&BX);
697 break;
698 case 0x01:
699 biosfn_save_video_state(CX,ES,BX);
700 break;
701 case 0x02:
702 biosfn_restore_video_state(CX,ES,BX);
703 break;
704 #ifdef DEBUG
705 default:
706 unknown();
707 #endif
709 SET_AL(0x1C);
710 break;
712 #ifdef VBE
713 case 0x4f:
714 if (vbe_has_vbe_display()) {
715 switch(GET_AL())
717 case 0x00:
718 vbe_biosfn_return_controller_information(&AX,ES,DI);
719 break;
720 case 0x01:
721 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
722 break;
723 case 0x02:
724 vbe_biosfn_set_mode(&AX,BX,ES,DI);
725 break;
726 case 0x04:
727 //FIXME
728 #ifdef DEBUG
729 unimplemented();
730 #endif
731 // function failed
732 AX=0x100;
733 break;
734 case 0x09:
735 //FIXME
736 #ifdef DEBUG
737 unimplemented();
738 #endif
739 // function failed
740 AX=0x100;
741 break;
742 case 0x0A:
743 //FIXME
744 #ifdef DEBUG
745 unimplemented();
746 #endif
747 // function failed
748 AX=0x100;
749 break;
750 default:
751 #ifdef DEBUG
752 unknown();
753 #endif
754 // function failed
755 AX=0x100;
758 else {
759 // No VBE display
760 AX=0x0100;
762 break;
763 #endif
765 #ifdef DEBUG
766 default:
767 unknown();
768 #endif
772 // ============================================================================================
774 // BIOS functions
776 // ============================================================================================
778 static void biosfn_set_video_mode(mode) Bit8u mode;
779 {// mode: Bit 7 is 1 if no clear screen
781 // Should we clear the screen ?
782 Bit8u noclearmem=mode&0x80;
783 Bit8u line,mmask,*palette;
784 Bit16u i,twidth,theight,cheight;
785 Bit8u modeset_ctl,video_ctl,vga_switches;
786 Bit16u crtc_addr;
788 #ifdef VBE
789 if (vbe_has_vbe_display()) {
790 dispi_set_enable(VBE_DISPI_DISABLED);
792 #endif // def VBE
794 // The real mode
795 mode=mode&0x7f;
797 // find the entry in the video modes
798 line=find_vga_entry(mode);
800 #ifdef DEBUG
801 printf("mode search %02x found line %02x\n",mode,line);
802 #endif
804 if(line==0xFF)
805 return;
807 twidth=vga_modes[line].twidth;
808 theight=vga_modes[line].theight;
809 cheight=vga_modes[line].cheight;
811 // Read the bios vga control
812 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
814 // Read the bios vga switches
815 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
817 // Read the bios mode set control
818 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
820 // Then we know the number of lines
821 // FIXME
823 // if palette loading (bit 3 of modeset ctl = 0)
824 if((modeset_ctl&0x08)==0)
825 {// Set the PEL mask
826 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
828 // Set the whole dac always, from 0
829 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
831 // From which palette
832 switch(vga_modes[line].dacmodel)
833 {case 0:
834 palette=&palette0;
835 break;
836 case 1:
837 palette=&palette1;
838 break;
839 case 2:
840 palette=&palette2;
841 break;
842 case 3:
843 palette=&palette3;
844 break;
846 // Always 256*3 values
847 for(i=0;i<0x0100;i++)
848 {if(i<=dac_regs[vga_modes[line].dacmodel])
849 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
850 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
851 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
853 else
854 {outb(VGAREG_DAC_DATA,0);
855 outb(VGAREG_DAC_DATA,0);
856 outb(VGAREG_DAC_DATA,0);
859 if((modeset_ctl&0x02)==0x02)
861 biosfn_perform_gray_scale_summing(0x00, 0x100);
865 // Reset Attribute Ctl flip-flop
866 inb(VGAREG_ACTL_RESET);
868 // Set Attribute Ctl
869 for(i=0;i<=ACTL_MAX_REG;i++)
870 {outb(VGAREG_ACTL_ADDRESS,i);
871 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
874 // Set Sequencer Ctl
875 for(i=0;i<=SEQU_MAX_REG;i++)
876 {outb(VGAREG_SEQU_ADDRESS,i);
877 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
880 // Set Grafx Ctl
881 for(i=0;i<=GRDC_MAX_REG;i++)
882 {outb(VGAREG_GRDC_ADDRESS,i);
883 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
886 // Set CRTC address VGA or MDA
887 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
889 // Disable CRTC write protection
890 outw(crtc_addr,0x0011);
891 // Set CRTC regs
892 for(i=0;i<=CRTC_MAX_REG;i++)
893 {outb(crtc_addr,i);
894 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
897 // Set the misc register
898 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
900 // Enable video
901 outb(VGAREG_ACTL_ADDRESS,0x20);
902 inb(VGAREG_ACTL_RESET);
904 if(noclearmem==0x00)
906 if(vga_modes[line].class==TEXT)
908 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
910 else
912 if(mode<0x0d)
914 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
916 else
918 outb( VGAREG_SEQU_ADDRESS, 0x02 );
919 mmask = inb( VGAREG_SEQU_DATA );
920 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
921 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
922 outb( VGAREG_SEQU_DATA, mmask );
927 // Set the BIOS mem
928 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
929 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
930 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
931 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
932 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
933 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
934 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
935 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
936 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
938 // FIXME We nearly have the good tables. to be reworked
939 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
940 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
941 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
943 // FIXME
944 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
945 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
947 // Set cursor shape
948 if(vga_modes[line].class==TEXT)
950 biosfn_set_cursor_shape(0x06,0x07);
953 // Set cursor pos for page 0..7
954 for(i=0;i<8;i++)
955 biosfn_set_cursor_pos(i,0x0000);
957 // Set active page 0
958 biosfn_set_active_page(0x00);
960 // Write the fonts in memory
961 if(vga_modes[line].class==TEXT)
963 ASM_START
964 ;; copy and activate 8x16 font
965 mov ax, #0x1104
966 mov bl, #0x00
967 int #0x10
968 mov ax, #0x1103
969 mov bl, #0x00
970 int #0x10
971 ASM_END
974 // Set the ints 0x1F and 0x43
975 ASM_START
976 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
977 ASM_END
979 switch(cheight)
980 {case 8:
981 ASM_START
982 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
983 ASM_END
984 break;
985 case 14:
986 ASM_START
987 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
988 ASM_END
989 break;
990 case 16:
991 ASM_START
992 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
993 ASM_END
994 break;
998 // --------------------------------------------------------------------------------------------
999 static void biosfn_set_cursor_shape (CH,CL)
1000 Bit8u CH;Bit8u CL;
1001 {Bit16u cheight,curs,crtc_addr;
1002 Bit8u modeset_ctl;
1004 CH&=0x3f;
1005 CL&=0x1f;
1007 curs=(CH<<8)+CL;
1008 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
1010 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
1011 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
1012 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1014 if(CL!=(CH+1))
1016 CH = ((CH+1) * cheight / 8) -1;
1018 else
1020 CH = ((CL+1) * cheight / 8) - 2;
1022 CL = ((CL+1) * cheight / 8) - 1;
1025 // CTRC regs 0x0a and 0x0b
1026 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1027 outb(crtc_addr,0x0a);
1028 outb(crtc_addr+1,CH);
1029 outb(crtc_addr,0x0b);
1030 outb(crtc_addr+1,CL);
1033 // --------------------------------------------------------------------------------------------
1034 static void biosfn_set_cursor_pos (page, cursor)
1035 Bit8u page;Bit16u cursor;
1037 Bit8u xcurs,ycurs,current;
1038 Bit16u nbcols,nbrows,address,crtc_addr;
1040 // Should not happen...
1041 if(page>7)return;
1043 // Bios cursor pos
1044 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1046 // Set the hardware cursor
1047 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1048 if(page==current)
1050 // Get the dimensions
1051 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1052 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1054 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1056 // Calculate the address knowing nbcols nbrows and page num
1057 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1059 // CRTC regs 0x0e and 0x0f
1060 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1061 outb(crtc_addr,0x0e);
1062 outb(crtc_addr+1,(address&0xff00)>>8);
1063 outb(crtc_addr,0x0f);
1064 outb(crtc_addr+1,address&0x00ff);
1068 // --------------------------------------------------------------------------------------------
1069 static void biosfn_get_cursor_pos (page,shape, pos)
1070 Bit8u page;Bit16u *shape;Bit16u *pos;
1072 Bit16u ss=get_SS();
1074 // Default
1075 write_word(ss, shape, 0);
1076 write_word(ss, pos, 0);
1078 if(page>7)return;
1079 // FIXME should handle VGA 14/16 lines
1080 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1081 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1084 // --------------------------------------------------------------------------------------------
1085 static void biosfn_set_active_page (page)
1086 Bit8u page;
1088 Bit16u cursor,dummy,crtc_addr;
1089 Bit16u nbcols,nbrows,address;
1090 Bit8u mode,line;
1092 if(page>7)return;
1094 // Get the mode
1095 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1096 line=find_vga_entry(mode);
1097 if(line==0xFF)return;
1099 // Get pos curs pos for the right page
1100 biosfn_get_cursor_pos(page,&dummy,&cursor);
1102 if(vga_modes[line].class==TEXT)
1104 // Get the dimensions
1105 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1106 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1108 // Calculate the address knowing nbcols nbrows and page num
1109 address=SCREEN_MEM_START(nbcols,nbrows,page);
1110 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1112 // Start address
1113 address=SCREEN_IO_START(nbcols,nbrows,page);
1115 else
1117 address = page*vga_modes[line].slength;
1120 // CRTC regs 0x0c and 0x0d
1121 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1122 outb(crtc_addr,0x0c);
1123 outb(crtc_addr+1,(address&0xff00)>>8);
1124 outb(crtc_addr,0x0d);
1125 outb(crtc_addr+1,address&0x00ff);
1127 // And change the BIOS page
1128 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1130 #ifdef DEBUG
1131 printf("Set active page %02x address %04x\n",page,address);
1132 #endif
1134 // Display the cursor, now the page is active
1135 biosfn_set_cursor_pos(page,cursor);
1138 // --------------------------------------------------------------------------------------------
1139 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1140 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1142 Bit16u src,dest;
1143 Bit8u i;
1145 src=ysrc*cheight*nbcols+xstart;
1146 dest=ydest*cheight*nbcols+xstart;
1147 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1148 for(i=0;i<cheight;i++)
1150 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1152 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1155 // --------------------------------------------------------------------------------------------
1156 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1157 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1159 Bit16u dest;
1160 Bit8u i;
1162 dest=ystart*cheight*nbcols+xstart;
1163 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1164 for(i=0;i<cheight;i++)
1166 memsetb(0xa000,dest+i*nbcols,attr,cols);
1168 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1171 // --------------------------------------------------------------------------------------------
1172 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1173 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1175 Bit16u src,dest;
1176 Bit8u i;
1178 src=((ysrc*cheight*nbcols)>>1)+xstart;
1179 dest=((ydest*cheight*nbcols)>>1)+xstart;
1180 for(i=0;i<cheight;i++)
1182 if (i & 1)
1183 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1184 else
1185 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1189 // --------------------------------------------------------------------------------------------
1190 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1191 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1193 Bit16u dest;
1194 Bit8u i;
1196 dest=((ystart*cheight*nbcols)>>1)+xstart;
1197 for(i=0;i<cheight;i++)
1199 if (i & 1)
1200 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1201 else
1202 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1206 // --------------------------------------------------------------------------------------------
1207 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1208 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1210 // page == 0xFF if current
1212 Bit8u mode,line,cheight,bpp,cols;
1213 Bit16u nbcols,nbrows,i;
1214 Bit16u address;
1216 if(rul>rlr)return;
1217 if(cul>clr)return;
1219 // Get the mode
1220 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1221 line=find_vga_entry(mode);
1222 if(line==0xFF)return;
1224 // Get the dimensions
1225 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1226 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1228 // Get the current page
1229 if(page==0xFF)
1230 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1232 if(rlr>=nbrows)rlr=nbrows-1;
1233 if(clr>=nbcols)clr=nbcols-1;
1234 if(nblines>nbrows)nblines=0;
1235 cols=clr-cul+1;
1237 if(vga_modes[line].class==TEXT)
1239 // Compute the address
1240 address=SCREEN_MEM_START(nbcols,nbrows,page);
1241 #ifdef DEBUG
1242 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1243 #endif
1245 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1247 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1249 else
1250 {// if Scroll up
1251 if(dir==SCROLL_UP)
1252 {for(i=rul;i<=rlr;i++)
1254 if((i+nblines>rlr)||(nblines==0))
1255 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1256 else
1257 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1260 else
1261 {for(i=rlr;i>=rul;i--)
1263 if((i<rul+nblines)||(nblines==0))
1264 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1265 else
1266 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1271 else
1273 // FIXME gfx mode not complete
1274 cheight=vga_modes[line].cheight;
1275 switch(vga_modes[line].memmodel)
1277 case PLANAR4:
1278 case PLANAR1:
1279 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1281 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1282 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1283 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1285 else
1286 {// if Scroll up
1287 if(dir==SCROLL_UP)
1288 {for(i=rul;i<=rlr;i++)
1290 if((i+nblines>rlr)||(nblines==0))
1291 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1292 else
1293 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1296 else
1297 {for(i=rlr;i>=rul;i--)
1299 if((i<rul+nblines)||(nblines==0))
1300 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1301 else
1302 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1306 break;
1307 case CGA:
1308 bpp=vga_modes[line].pixbits;
1309 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1311 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1313 else
1315 if(bpp==2)
1317 cul<<=1;
1318 cols<<=1;
1319 nbcols<<=1;
1321 // if Scroll up
1322 if(dir==SCROLL_UP)
1323 {for(i=rul;i<=rlr;i++)
1325 if((i+nblines>rlr)||(nblines==0))
1326 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1327 else
1328 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1331 else
1332 {for(i=rlr;i>=rul;i--)
1334 if((i<rul+nblines)||(nblines==0))
1335 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1336 else
1337 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1341 break;
1342 #ifdef DEBUG
1343 default:
1344 printf("Scroll in graphics mode ");
1345 unimplemented();
1346 #endif
1351 // --------------------------------------------------------------------------------------------
1352 static void biosfn_read_char_attr (page,car)
1353 Bit8u page;Bit16u *car;
1354 {Bit16u ss=get_SS();
1355 Bit8u xcurs,ycurs,mode,line;
1356 Bit16u nbcols,nbrows,address;
1357 Bit16u cursor,dummy;
1359 // Get the mode
1360 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1361 line=find_vga_entry(mode);
1362 if(line==0xFF)return;
1364 // Get the cursor pos for the page
1365 biosfn_get_cursor_pos(page,&dummy,&cursor);
1366 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1368 // Get the dimensions
1369 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1370 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1372 if(vga_modes[line].class==TEXT)
1374 // Compute the address
1375 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1377 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1379 else
1381 // FIXME gfx mode
1382 #ifdef DEBUG
1383 unimplemented();
1384 #endif
1388 // --------------------------------------------------------------------------------------------
1389 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1390 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1392 Bit8u i,j,mask;
1393 Bit8u *fdata;
1394 Bit16u addr,dest,src;
1396 switch(cheight)
1397 {case 14:
1398 fdata = &vgafont14;
1399 break;
1400 case 16:
1401 fdata = &vgafont16;
1402 break;
1403 default:
1404 fdata = &vgafont8;
1406 addr=xcurs+ycurs*cheight*nbcols;
1407 src = car * cheight;
1408 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1409 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1410 if(attr&0x80)
1412 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1414 else
1416 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1418 for(i=0;i<cheight;i++)
1420 dest=addr+i*nbcols;
1421 for(j=0;j<8;j++)
1423 mask=0x80>>j;
1424 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1425 read_byte(0xa000,dest);
1426 if(fdata[src+i]&mask)
1428 write_byte(0xa000,dest,attr&0x0f);
1430 else
1432 write_byte(0xa000,dest,0x00);
1436 ASM_START
1437 mov dx, # VGAREG_GRDC_ADDRESS
1438 mov ax, #0xff08
1439 out dx, ax
1440 mov ax, #0x0005
1441 out dx, ax
1442 mov ax, #0x0003
1443 out dx, ax
1444 ASM_END
1447 // --------------------------------------------------------------------------------------------
1448 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1449 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1451 Bit8u i,j,mask,data;
1452 Bit8u *fdata;
1453 Bit16u addr,dest,src;
1455 fdata = &vgafont8;
1456 addr=(xcurs*bpp)+ycurs*320;
1457 src = car * 8;
1458 for(i=0;i<8;i++)
1460 dest=addr+(i>>1)*80;
1461 if (i & 1) dest += 0x2000;
1462 mask = 0x80;
1463 if (bpp == 1)
1465 if (attr & 0x80)
1467 data = read_byte(0xb800,dest);
1469 else
1471 data = 0x00;
1473 for(j=0;j<8;j++)
1475 if (fdata[src+i] & mask)
1477 if (attr & 0x80)
1479 data ^= (attr & 0x01) << (7-j);
1481 else
1483 data |= (attr & 0x01) << (7-j);
1486 mask >>= 1;
1488 write_byte(0xb800,dest,data);
1490 else
1492 while (mask > 0)
1494 if (attr & 0x80)
1496 data = read_byte(0xb800,dest);
1498 else
1500 data = 0x00;
1502 for(j=0;j<4;j++)
1504 if (fdata[src+i] & mask)
1506 if (attr & 0x80)
1508 data ^= (attr & 0x03) << ((3-j)*2);
1510 else
1512 data |= (attr & 0x03) << ((3-j)*2);
1515 mask >>= 1;
1517 write_byte(0xb800,dest,data);
1518 dest += 1;
1524 // --------------------------------------------------------------------------------------------
1525 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1526 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1528 Bit8u i,j,mask,data;
1529 Bit8u *fdata;
1530 Bit16u addr,dest,src;
1532 fdata = &vgafont8;
1533 addr=xcurs*8+ycurs*nbcols*64;
1534 src = car * 8;
1535 for(i=0;i<8;i++)
1537 dest=addr+i*nbcols*8;
1538 mask = 0x80;
1539 for(j=0;j<8;j++)
1541 data = 0x00;
1542 if (fdata[src+i] & mask)
1544 data = attr;
1546 write_byte(0xa000,dest+j,data);
1547 mask >>= 1;
1552 // --------------------------------------------------------------------------------------------
1553 static void biosfn_write_char_attr (car,page,attr,count)
1554 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1556 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1557 Bit16u nbcols,nbrows,address;
1558 Bit16u cursor,dummy;
1560 // Get the mode
1561 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1562 line=find_vga_entry(mode);
1563 if(line==0xFF)return;
1565 // Get the cursor pos for the page
1566 biosfn_get_cursor_pos(page,&dummy,&cursor);
1567 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1569 // Get the dimensions
1570 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1571 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1573 if(vga_modes[line].class==TEXT)
1575 // Compute the address
1576 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1578 dummy=((Bit16u)attr<<8)+car;
1579 memsetw(vga_modes[line].sstart,address,dummy,count);
1581 else
1583 // FIXME gfx mode not complete
1584 cheight=vga_modes[line].cheight;
1585 bpp=vga_modes[line].pixbits;
1586 while((count-->0) && (xcurs<nbcols))
1588 switch(vga_modes[line].memmodel)
1590 case PLANAR4:
1591 case PLANAR1:
1592 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1593 break;
1594 case CGA:
1595 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1596 break;
1597 case LINEAR8:
1598 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1599 break;
1600 #ifdef DEBUG
1601 default:
1602 unimplemented();
1603 #endif
1605 xcurs++;
1610 // --------------------------------------------------------------------------------------------
1611 static void biosfn_write_char_only (car,page,attr,count)
1612 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1614 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1615 Bit16u nbcols,nbrows,address;
1616 Bit16u cursor,dummy;
1618 // Get the mode
1619 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1620 line=find_vga_entry(mode);
1621 if(line==0xFF)return;
1623 // Get the cursor pos for the page
1624 biosfn_get_cursor_pos(page,&dummy,&cursor);
1625 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1627 // Get the dimensions
1628 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1629 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1631 if(vga_modes[line].class==TEXT)
1633 // Compute the address
1634 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1636 while(count-->0)
1637 {write_byte(vga_modes[line].sstart,address,car);
1638 address+=2;
1641 else
1643 // FIXME gfx mode not complete
1644 cheight=vga_modes[line].cheight;
1645 bpp=vga_modes[line].pixbits;
1646 while((count-->0) && (xcurs<nbcols))
1648 switch(vga_modes[line].memmodel)
1650 case PLANAR4:
1651 case PLANAR1:
1652 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1653 break;
1654 case CGA:
1655 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1656 break;
1657 case LINEAR8:
1658 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1659 break;
1660 #ifdef DEBUG
1661 default:
1662 unimplemented();
1663 #endif
1665 xcurs++;
1670 // --------------------------------------------------------------------------------------------
1671 ASM_START
1672 biosfn_group_0B:
1673 cmp bh, #0x00
1674 je biosfn_set_border_color
1675 cmp bh, #0x01
1676 je biosfn_set_palette
1677 #ifdef DEBUG
1678 call _unknown
1679 #endif
1681 biosfn_set_border_color:
1682 push ax
1683 push bx
1684 push cx
1685 push dx
1686 mov dx, # VGAREG_ACTL_RESET
1687 in al, dx
1688 mov dx, # VGAREG_ACTL_ADDRESS
1689 mov al, #0x00
1690 out dx, al
1691 mov al, bl
1692 and al, #0x0f
1693 test al, #0x08
1694 jz set_low_border
1695 add al, #0x08
1696 set_low_border:
1697 out dx, al
1698 mov cl, #0x01
1699 and bl, #0x10
1700 set_intensity_loop:
1701 mov dx, # VGAREG_ACTL_ADDRESS
1702 mov al, cl
1703 out dx, al
1704 mov dx, # VGAREG_ACTL_READ_DATA
1705 in al, dx
1706 and al, #0xef
1707 or al, bl
1708 mov dx, # VGAREG_ACTL_ADDRESS
1709 out dx, al
1710 inc cl
1711 cmp cl, #0x04
1712 jne set_intensity_loop
1713 mov al, #0x20
1714 out dx, al
1715 pop dx
1716 pop cx
1717 pop bx
1718 pop ax
1720 biosfn_set_palette:
1721 push ax
1722 push bx
1723 push cx
1724 push dx
1725 mov dx, # VGAREG_ACTL_RESET
1726 in al, dx
1727 mov cl, #0x01
1728 and bl, #0x01
1729 set_cga_palette_loop:
1730 mov dx, # VGAREG_ACTL_ADDRESS
1731 mov al, cl
1732 out dx, al
1733 mov dx, # VGAREG_ACTL_READ_DATA
1734 in al, dx
1735 and al, #0xfe
1736 or al, bl
1737 mov dx, # VGAREG_ACTL_ADDRESS
1738 out dx, al
1739 inc cl
1740 cmp cl, #0x04
1741 jne set_cga_palette_loop
1742 mov al, #0x20
1743 out dx, al
1744 pop dx
1745 pop cx
1746 pop bx
1747 pop ax
1749 ASM_END
1751 // --------------------------------------------------------------------------------------------
1752 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1754 Bit8u mode,line,mask,attr,data;
1755 Bit16u addr;
1757 // Get the mode
1758 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1759 line=find_vga_entry(mode);
1760 if(line==0xFF)return;
1761 if(vga_modes[line].class==TEXT)return;
1763 switch(vga_modes[line].memmodel)
1765 case PLANAR4:
1766 case PLANAR1:
1767 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1768 mask = 0x80 >> (CX & 0x07);
1769 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1770 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1771 data = read_byte(0xa000,addr);
1772 if (AL & 0x80)
1774 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1776 write_byte(0xa000,addr,AL);
1777 ASM_START
1778 mov dx, # VGAREG_GRDC_ADDRESS
1779 mov ax, #0xff08
1780 out dx, ax
1781 mov ax, #0x0005
1782 out dx, ax
1783 mov ax, #0x0003
1784 out dx, ax
1785 ASM_END
1786 break;
1787 case CGA:
1788 if(vga_modes[line].pixbits==2)
1790 addr=(CX>>2)+(DX>>1)*80;
1792 else
1794 addr=(CX>>3)+(DX>>1)*80;
1796 if (DX & 1) addr += 0x2000;
1797 data = read_byte(0xb800,addr);
1798 if(vga_modes[line].pixbits==2)
1800 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1801 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1803 else
1805 attr = (AL & 0x01) << (7 - (CX & 0x07));
1806 mask = 0x01 << (7 - (CX & 0x07));
1808 if (AL & 0x80)
1810 data ^= attr;
1812 else
1814 data &= ~mask;
1815 data |= attr;
1817 write_byte(0xb800,addr,data);
1818 break;
1819 case LINEAR8:
1820 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1821 write_byte(0xa000,addr,AL);
1822 break;
1823 #ifdef DEBUG
1824 default:
1825 unimplemented();
1826 #endif
1830 // --------------------------------------------------------------------------------------------
1831 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1833 Bit8u mode,line,mask,attr,data,i;
1834 Bit16u addr;
1835 Bit16u ss=get_SS();
1837 // Get the mode
1838 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1839 line=find_vga_entry(mode);
1840 if(line==0xFF)return;
1841 if(vga_modes[line].class==TEXT)return;
1843 switch(vga_modes[line].memmodel)
1845 case PLANAR4:
1846 case PLANAR1:
1847 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1848 mask = 0x80 >> (CX & 0x07);
1849 attr = 0x00;
1850 for(i=0;i<4;i++)
1852 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1853 data = read_byte(0xa000,addr) & mask;
1854 if (data > 0) attr |= (0x01 << i);
1856 break;
1857 case CGA:
1858 addr=(CX>>2)+(DX>>1)*80;
1859 if (DX & 1) addr += 0x2000;
1860 data = read_byte(0xb800,addr);
1861 if(vga_modes[line].pixbits==2)
1863 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1865 else
1867 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1869 break;
1870 case LINEAR8:
1871 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1872 attr=read_byte(0xa000,addr);
1873 break;
1874 default:
1875 #ifdef DEBUG
1876 unimplemented();
1877 #endif
1878 attr = 0;
1880 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1883 // --------------------------------------------------------------------------------------------
1884 static void biosfn_write_teletype (car, page, attr, flag)
1885 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1886 {// flag = WITH_ATTR / NO_ATTR
1888 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1889 Bit16u nbcols,nbrows,address;
1890 Bit16u cursor,dummy;
1892 // special case if page is 0xff, use current page
1893 if(page==0xff)
1894 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1896 // Get the mode
1897 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1898 line=find_vga_entry(mode);
1899 if(line==0xFF)return;
1901 // Get the cursor pos for the page
1902 biosfn_get_cursor_pos(page,&dummy,&cursor);
1903 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1905 // Get the dimensions
1906 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1907 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1909 switch(car)
1911 case 7:
1912 //FIXME should beep
1913 break;
1915 case 8:
1916 if(xcurs>0)xcurs--;
1917 break;
1919 case '\r':
1920 xcurs=0;
1921 break;
1923 case '\n':
1924 ycurs++;
1925 break;
1927 case '\t':
1930 biosfn_write_teletype(' ',page,attr,flag);
1931 biosfn_get_cursor_pos(page,&dummy,&cursor);
1932 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1933 }while(xcurs%8==0);
1934 break;
1936 default:
1938 if(vga_modes[line].class==TEXT)
1940 // Compute the address
1941 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1943 // Write the char
1944 write_byte(vga_modes[line].sstart,address,car);
1946 if(flag==WITH_ATTR)
1947 write_byte(vga_modes[line].sstart,address+1,attr);
1949 else
1951 // FIXME gfx mode not complete
1952 cheight=vga_modes[line].cheight;
1953 bpp=vga_modes[line].pixbits;
1954 switch(vga_modes[line].memmodel)
1956 case PLANAR4:
1957 case PLANAR1:
1958 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1959 break;
1960 case CGA:
1961 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1962 break;
1963 case LINEAR8:
1964 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1965 break;
1966 #ifdef DEBUG
1967 default:
1968 unimplemented();
1969 #endif
1972 xcurs++;
1975 // Do we need to wrap ?
1976 if(xcurs==nbcols)
1977 {xcurs=0;
1978 ycurs++;
1981 // Do we need to scroll ?
1982 if(ycurs==nbrows)
1984 if(vga_modes[line].class==TEXT)
1986 biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1988 else
1990 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1992 ycurs-=1;
1995 // Set the cursor for the page
1996 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1997 biosfn_set_cursor_pos(page,cursor);
2000 // --------------------------------------------------------------------------------------------
2001 ASM_START
2002 biosfn_get_video_mode:
2003 push ds
2004 mov ax, # BIOSMEM_SEG
2005 mov ds, ax
2006 push bx
2007 mov bx, # BIOSMEM_CURRENT_PAGE
2008 mov al, [bx]
2009 pop bx
2010 mov bh, al
2011 push bx
2012 mov bx, # BIOSMEM_VIDEO_CTL
2013 mov ah, [bx]
2014 and ah, #0x80
2015 mov bx, # BIOSMEM_CURRENT_MODE
2016 mov al, [bx]
2017 or al, ah
2018 mov bx, # BIOSMEM_NB_COLS
2019 mov ah, [bx]
2020 pop bx
2021 pop ds
2023 ASM_END
2025 // --------------------------------------------------------------------------------------------
2026 ASM_START
2027 biosfn_group_10:
2028 cmp al, #0x00
2029 jne int10_test_1001
2030 jmp biosfn_set_single_palette_reg
2031 int10_test_1001:
2032 cmp al, #0x01
2033 jne int10_test_1002
2034 jmp biosfn_set_overscan_border_color
2035 int10_test_1002:
2036 cmp al, #0x02
2037 jne int10_test_1003
2038 jmp biosfn_set_all_palette_reg
2039 int10_test_1003:
2040 cmp al, #0x03
2041 jne int10_test_1007
2042 jmp biosfn_toggle_intensity
2043 int10_test_1007:
2044 cmp al, #0x07
2045 jne int10_test_1008
2046 jmp biosfn_get_single_palette_reg
2047 int10_test_1008:
2048 cmp al, #0x08
2049 jne int10_test_1009
2050 jmp biosfn_read_overscan_border_color
2051 int10_test_1009:
2052 cmp al, #0x09
2053 jne int10_test_1010
2054 jmp biosfn_get_all_palette_reg
2055 int10_test_1010:
2056 cmp al, #0x10
2057 jne int10_test_1012
2058 jmp biosfn_set_single_dac_reg
2059 int10_test_1012:
2060 cmp al, #0x12
2061 jne int10_test_1013
2062 jmp biosfn_set_all_dac_reg
2063 int10_test_1013:
2064 cmp al, #0x13
2065 jne int10_test_1015
2066 jmp biosfn_select_video_dac_color_page
2067 int10_test_1015:
2068 cmp al, #0x15
2069 jne int10_test_1017
2070 jmp biosfn_read_single_dac_reg
2071 int10_test_1017:
2072 cmp al, #0x17
2073 jne int10_test_1018
2074 jmp biosfn_read_all_dac_reg
2075 int10_test_1018:
2076 cmp al, #0x18
2077 jne int10_test_1019
2078 jmp biosfn_set_pel_mask
2079 int10_test_1019:
2080 cmp al, #0x19
2081 jne int10_test_101A
2082 jmp biosfn_read_pel_mask
2083 int10_test_101A:
2084 cmp al, #0x1a
2085 jne int10_group_10_unknown
2086 jmp biosfn_read_video_dac_state
2087 int10_group_10_unknown:
2088 #ifdef DEBUG
2089 call _unknown
2090 #endif
2093 biosfn_set_single_palette_reg:
2094 cmp bl, #0x14
2095 ja no_actl_reg1
2096 push ax
2097 push dx
2098 mov dx, # VGAREG_ACTL_RESET
2099 in al, dx
2100 mov dx, # VGAREG_ACTL_ADDRESS
2101 mov al, bl
2102 out dx, al
2103 mov al, bh
2104 out dx, al
2105 mov al, #0x20
2106 out dx, al
2107 pop dx
2108 pop ax
2109 no_actl_reg1:
2111 ASM_END
2113 // --------------------------------------------------------------------------------------------
2114 ASM_START
2115 biosfn_set_overscan_border_color:
2116 push bx
2117 mov bl, #0x11
2118 call biosfn_set_single_palette_reg
2119 pop bx
2121 ASM_END
2123 // --------------------------------------------------------------------------------------------
2124 ASM_START
2125 biosfn_set_all_palette_reg:
2126 push ax
2127 push bx
2128 push cx
2129 push dx
2130 mov bx, dx
2131 mov dx, # VGAREG_ACTL_RESET
2132 in al, dx
2133 mov cl, #0x00
2134 mov dx, # VGAREG_ACTL_ADDRESS
2135 set_palette_loop:
2136 mov al, cl
2137 out dx, al
2138 seg es
2139 mov al, [bx]
2140 out dx, al
2141 inc bx
2142 inc cl
2143 cmp cl, #0x10
2144 jne set_palette_loop
2145 mov al, #0x11
2146 out dx, al
2147 seg es
2148 mov al, [bx]
2149 out dx, al
2150 mov al, #0x20
2151 out dx, al
2152 pop dx
2153 pop cx
2154 pop bx
2155 pop ax
2157 ASM_END
2159 // --------------------------------------------------------------------------------------------
2160 ASM_START
2161 biosfn_toggle_intensity:
2162 push ax
2163 push bx
2164 push dx
2165 mov dx, # VGAREG_ACTL_RESET
2166 in al, dx
2167 mov dx, # VGAREG_ACTL_ADDRESS
2168 mov al, #0x10
2169 out dx, al
2170 mov dx, # VGAREG_ACTL_READ_DATA
2171 in al, dx
2172 and al, #0xf7
2173 and bl, #0x01
2174 shl bl, 3
2175 or al, bl
2176 mov dx, # VGAREG_ACTL_ADDRESS
2177 out dx, al
2178 mov al, #0x20
2179 out dx, al
2180 pop dx
2181 pop bx
2182 pop ax
2184 ASM_END
2186 // --------------------------------------------------------------------------------------------
2187 ASM_START
2188 biosfn_get_single_palette_reg:
2189 cmp bl, #0x14
2190 ja no_actl_reg2
2191 push ax
2192 push dx
2193 mov dx, # VGAREG_ACTL_RESET
2194 in al, dx
2195 mov dx, # VGAREG_ACTL_ADDRESS
2196 mov al, bl
2197 out dx, al
2198 mov dx, # VGAREG_ACTL_READ_DATA
2199 in al, dx
2200 mov bh, al
2201 mov dx, # VGAREG_ACTL_RESET
2202 in al, dx
2203 mov dx, # VGAREG_ACTL_ADDRESS
2204 mov al, #0x20
2205 out dx, al
2206 pop dx
2207 pop ax
2208 no_actl_reg2:
2210 ASM_END
2212 // --------------------------------------------------------------------------------------------
2213 ASM_START
2214 biosfn_read_overscan_border_color:
2215 push ax
2216 push bx
2217 mov bl, #0x11
2218 call biosfn_get_single_palette_reg
2219 mov al, bh
2220 pop bx
2221 mov bh, al
2222 pop ax
2224 ASM_END
2226 // --------------------------------------------------------------------------------------------
2227 ASM_START
2228 biosfn_get_all_palette_reg:
2229 push ax
2230 push bx
2231 push cx
2232 push dx
2233 mov bx, dx
2234 mov cl, #0x00
2235 get_palette_loop:
2236 mov dx, # VGAREG_ACTL_RESET
2237 in al, dx
2238 mov dx, # VGAREG_ACTL_ADDRESS
2239 mov al, cl
2240 out dx, al
2241 mov dx, # VGAREG_ACTL_READ_DATA
2242 in al, dx
2243 seg es
2244 mov [bx], al
2245 inc bx
2246 inc cl
2247 cmp cl, #0x10
2248 jne get_palette_loop
2249 mov dx, # VGAREG_ACTL_RESET
2250 in al, dx
2251 mov dx, # VGAREG_ACTL_ADDRESS
2252 mov al, #0x11
2253 out dx, al
2254 mov dx, # VGAREG_ACTL_READ_DATA
2255 in al, dx
2256 seg es
2257 mov [bx], al
2258 mov dx, # VGAREG_ACTL_RESET
2259 in al, dx
2260 mov dx, # VGAREG_ACTL_ADDRESS
2261 mov al, #0x20
2262 out dx, al
2263 pop dx
2264 pop cx
2265 pop bx
2266 pop ax
2268 ASM_END
2270 // --------------------------------------------------------------------------------------------
2271 ASM_START
2272 biosfn_set_single_dac_reg:
2273 push ax
2274 push dx
2275 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2276 mov al, bl
2277 out dx, al
2278 mov dx, # VGAREG_DAC_DATA
2279 pop ax
2280 push ax
2281 mov al, ah
2282 out dx, al
2283 mov al, ch
2284 out dx, al
2285 mov al, cl
2286 out dx, al
2287 pop dx
2288 pop ax
2290 ASM_END
2292 // --------------------------------------------------------------------------------------------
2293 ASM_START
2294 biosfn_set_all_dac_reg:
2295 push ax
2296 push bx
2297 push cx
2298 push dx
2299 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2300 mov al, bl
2301 out dx, al
2302 pop dx
2303 push dx
2304 mov bx, dx
2305 mov dx, # VGAREG_DAC_DATA
2306 set_dac_loop:
2307 seg es
2308 mov al, [bx]
2309 out dx, al
2310 inc bx
2311 seg es
2312 mov al, [bx]
2313 out dx, al
2314 inc bx
2315 seg es
2316 mov al, [bx]
2317 out dx, al
2318 inc bx
2319 dec cx
2320 jnz set_dac_loop
2321 pop dx
2322 pop cx
2323 pop bx
2324 pop ax
2326 ASM_END
2328 // --------------------------------------------------------------------------------------------
2329 ASM_START
2330 biosfn_select_video_dac_color_page:
2331 push ax
2332 push bx
2333 push dx
2334 mov dx, # VGAREG_ACTL_RESET
2335 in al, dx
2336 mov dx, # VGAREG_ACTL_ADDRESS
2337 mov al, #0x10
2338 out dx, al
2339 mov dx, # VGAREG_ACTL_READ_DATA
2340 in al, dx
2341 and bl, #0x01
2342 jnz set_dac_page
2343 and al, #0x7f
2344 shl bh, 7
2345 or al, bh
2346 mov dx, # VGAREG_ACTL_ADDRESS
2347 out dx, al
2348 jmp set_actl_normal
2349 set_dac_page:
2350 push ax
2351 mov dx, # VGAREG_ACTL_RESET
2352 in al, dx
2353 mov dx, # VGAREG_ACTL_ADDRESS
2354 mov al, #0x14
2355 out dx, al
2356 pop ax
2357 and al, #0x80
2358 jnz set_dac_16_page
2359 shl bh, 2
2360 set_dac_16_page:
2361 and bh, #0x0f
2362 mov al, bh
2363 out dx, al
2364 set_actl_normal:
2365 mov al, #0x20
2366 out dx, al
2367 pop dx
2368 pop bx
2369 pop ax
2371 ASM_END
2373 // --------------------------------------------------------------------------------------------
2374 ASM_START
2375 biosfn_read_single_dac_reg:
2376 push ax
2377 push dx
2378 mov dx, # VGAREG_DAC_READ_ADDRESS
2379 mov al, bl
2380 out dx, al
2381 pop ax
2382 mov ah, al
2383 mov dx, # VGAREG_DAC_DATA
2384 in al, dx
2385 xchg al, ah
2386 push ax
2387 in al, dx
2388 mov ch, al
2389 in al, dx
2390 mov cl, al
2391 pop dx
2392 pop ax
2394 ASM_END
2396 // --------------------------------------------------------------------------------------------
2397 ASM_START
2398 biosfn_read_all_dac_reg:
2399 push ax
2400 push bx
2401 push cx
2402 push dx
2403 mov dx, # VGAREG_DAC_READ_ADDRESS
2404 mov al, bl
2405 out dx, al
2406 pop dx
2407 push dx
2408 mov bx, dx
2409 mov dx, # VGAREG_DAC_DATA
2410 read_dac_loop:
2411 in al, dx
2412 seg es
2413 mov [bx], al
2414 inc bx
2415 in al, dx
2416 seg es
2417 mov [bx], al
2418 inc bx
2419 in al, dx
2420 seg es
2421 mov [bx], al
2422 inc bx
2423 dec cx
2424 jnz read_dac_loop
2425 pop dx
2426 pop cx
2427 pop bx
2428 pop ax
2430 ASM_END
2432 // --------------------------------------------------------------------------------------------
2433 ASM_START
2434 biosfn_set_pel_mask:
2435 push ax
2436 push dx
2437 mov dx, # VGAREG_PEL_MASK
2438 mov al, bl
2439 out dx, al
2440 pop dx
2441 pop ax
2443 ASM_END
2445 // --------------------------------------------------------------------------------------------
2446 ASM_START
2447 biosfn_read_pel_mask:
2448 push ax
2449 push dx
2450 mov dx, # VGAREG_PEL_MASK
2451 in al, dx
2452 mov bl, al
2453 pop dx
2454 pop ax
2456 ASM_END
2458 // --------------------------------------------------------------------------------------------
2459 ASM_START
2460 biosfn_read_video_dac_state:
2461 push ax
2462 push dx
2463 mov dx, # VGAREG_ACTL_RESET
2464 in al, dx
2465 mov dx, # VGAREG_ACTL_ADDRESS
2466 mov al, #0x10
2467 out dx, al
2468 mov dx, # VGAREG_ACTL_READ_DATA
2469 in al, dx
2470 mov bl, al
2471 shr bl, 7
2472 mov dx, # VGAREG_ACTL_RESET
2473 in al, dx
2474 mov dx, # VGAREG_ACTL_ADDRESS
2475 mov al, #0x14
2476 out dx, al
2477 mov dx, # VGAREG_ACTL_READ_DATA
2478 in al, dx
2479 mov bh, al
2480 and bh, #0x0f
2481 test bl, #0x01
2482 jnz get_dac_16_page
2483 shr bh, 2
2484 get_dac_16_page:
2485 mov dx, # VGAREG_ACTL_RESET
2486 in al, dx
2487 mov dx, # VGAREG_ACTL_ADDRESS
2488 mov al, #0x20
2489 out dx, al
2490 pop dx
2491 pop ax
2493 ASM_END
2495 // --------------------------------------------------------------------------------------------
2496 static void biosfn_perform_gray_scale_summing (start,count)
2497 Bit16u start;Bit16u count;
2498 {Bit8u r,g,b;
2499 Bit16u i;
2500 Bit16u index;
2502 inb(VGAREG_ACTL_RESET);
2503 outb(VGAREG_ACTL_ADDRESS,0x00);
2505 for( index = 0; index < count; index++ )
2507 // set read address and switch to read mode
2508 outb(VGAREG_DAC_READ_ADDRESS,start);
2509 // get 6-bit wide RGB data values
2510 r=inb( VGAREG_DAC_DATA );
2511 g=inb( VGAREG_DAC_DATA );
2512 b=inb( VGAREG_DAC_DATA );
2514 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2515 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2517 if(i>0x3f)i=0x3f;
2519 // set write address and switch to write mode
2520 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2521 // write new intensity value
2522 outb( VGAREG_DAC_DATA, i&0xff );
2523 outb( VGAREG_DAC_DATA, i&0xff );
2524 outb( VGAREG_DAC_DATA, i&0xff );
2525 start++;
2527 inb(VGAREG_ACTL_RESET);
2528 outb(VGAREG_ACTL_ADDRESS,0x20);
2531 // --------------------------------------------------------------------------------------------
2532 static void get_font_access()
2534 ASM_START
2535 mov dx, # VGAREG_SEQU_ADDRESS
2536 mov ax, #0x0100
2537 out dx, ax
2538 mov ax, #0x0402
2539 out dx, ax
2540 mov ax, #0x0704
2541 out dx, ax
2542 mov ax, #0x0300
2543 out dx, ax
2544 mov dx, # VGAREG_GRDC_ADDRESS
2545 mov ax, #0x0204
2546 out dx, ax
2547 mov ax, #0x0005
2548 out dx, ax
2549 mov ax, #0x0406
2550 out dx, ax
2551 ASM_END
2554 static void release_font_access()
2556 ASM_START
2557 mov dx, # VGAREG_SEQU_ADDRESS
2558 mov ax, #0x0100
2559 out dx, ax
2560 mov ax, #0x0302
2561 out dx, ax
2562 mov ax, #0x0304
2563 out dx, ax
2564 mov ax, #0x0300
2565 out dx, ax
2566 mov dx, # VGAREG_READ_MISC_OUTPUT
2567 in al, dx
2568 and al, #0x01
2569 shl al, 2
2570 or al, #0x0a
2571 mov ah, al
2572 mov al, #0x06
2573 mov dx, # VGAREG_GRDC_ADDRESS
2574 out dx, ax
2575 mov ax, #0x0004
2576 out dx, ax
2577 mov ax, #0x1005
2578 out dx, ax
2579 ASM_END
2582 ASM_START
2583 idiv_u:
2584 xor dx,dx
2585 div bx
2587 ASM_END
2589 static void set_scan_lines(lines) Bit8u lines;
2591 Bit16u crtc_addr,cols,page,vde;
2592 Bit8u crtc_r9,ovl,rows;
2594 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2595 outb(crtc_addr, 0x09);
2596 crtc_r9 = inb(crtc_addr+1);
2597 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2598 outb(crtc_addr+1, crtc_r9);
2599 if(lines==8)
2601 biosfn_set_cursor_shape(0x06,0x07);
2603 else
2605 biosfn_set_cursor_shape(lines-4,lines-3);
2607 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2608 outb(crtc_addr, 0x12);
2609 vde = inb(crtc_addr+1);
2610 outb(crtc_addr, 0x07);
2611 ovl = inb(crtc_addr+1);
2612 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2613 rows = vde / lines;
2614 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2615 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2616 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2619 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;
2621 Bit16u blockaddr,dest,i,src;
2623 get_font_access();
2624 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2625 for(i=0;i<CX;i++)
2627 src = BP + i * BH;
2628 dest = blockaddr + (DX + i) * 32;
2629 memcpyb(0xA000, dest, ES, src, BH);
2631 release_font_access();
2632 if(AL>=0x10)
2634 set_scan_lines(BH);
2638 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2640 Bit16u blockaddr,dest,i,src;
2642 get_font_access();
2643 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2644 for(i=0;i<0x100;i++)
2646 src = i * 14;
2647 dest = blockaddr + i * 32;
2648 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2650 release_font_access();
2651 if(AL>=0x10)
2653 set_scan_lines(14);
2657 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2659 Bit16u blockaddr,dest,i,src;
2661 get_font_access();
2662 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2663 for(i=0;i<0x100;i++)
2665 src = i * 8;
2666 dest = blockaddr + i * 32;
2667 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2669 release_font_access();
2670 if(AL>=0x10)
2672 set_scan_lines(8);
2676 // --------------------------------------------------------------------------------------------
2677 ASM_START
2678 biosfn_set_text_block_specifier:
2679 push ax
2680 push dx
2681 mov dx, # VGAREG_SEQU_ADDRESS
2682 mov ah, bl
2683 mov al, #0x03
2684 out dx, ax
2685 pop dx
2686 pop ax
2688 ASM_END
2690 // --------------------------------------------------------------------------------------------
2691 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2693 Bit16u blockaddr,dest,i,src;
2695 get_font_access();
2696 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2697 for(i=0;i<0x100;i++)
2699 src = i * 16;
2700 dest = blockaddr + i * 32;
2701 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2703 release_font_access();
2704 if(AL>=0x10)
2706 set_scan_lines(16);
2710 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2712 #ifdef DEBUG
2713 unimplemented();
2714 #endif
2716 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2718 #ifdef DEBUG
2719 unimplemented();
2720 #endif
2722 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2724 #ifdef DEBUG
2725 unimplemented();
2726 #endif
2728 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2730 #ifdef DEBUG
2731 unimplemented();
2732 #endif
2734 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2736 #ifdef DEBUG
2737 unimplemented();
2738 #endif
2740 // --------------------------------------------------------------------------------------------
2741 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2742 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2743 {Bit16u ss=get_SS();
2745 switch(BH)
2746 {case 0x00:
2747 write_word(ss,ES,read_word(0x00,0x1f*4));
2748 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2749 break;
2750 case 0x01:
2751 write_word(ss,ES,read_word(0x00,0x43*4));
2752 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2753 break;
2754 case 0x02:
2755 write_word(ss,ES,0xC000);
2756 write_word(ss,BP,vgafont14);
2757 break;
2758 case 0x03:
2759 write_word(ss,ES,0xC000);
2760 write_word(ss,BP,vgafont8);
2761 break;
2762 case 0x04:
2763 write_word(ss,ES,0xC000);
2764 write_word(ss,BP,vgafont8+128*8);
2765 break;
2766 case 0x05:
2767 write_word(ss,ES,0xC000);
2768 write_word(ss,BP,vgafont14alt);
2769 break;
2770 case 0x06:
2771 write_word(ss,ES,0xC000);
2772 write_word(ss,BP,vgafont16);
2773 break;
2774 case 0x07:
2775 write_word(ss,ES,0xC000);
2776 write_word(ss,BP,vgafont16alt);
2777 break;
2778 default:
2779 #ifdef DEBUG
2780 printf("Get font info BH(%02x) was discarded\n",BH);
2781 #endif
2782 return;
2784 // Set byte/char of on screen font
2785 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2787 // Set Highest char row
2788 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2791 // --------------------------------------------------------------------------------------------
2792 ASM_START
2793 biosfn_get_ega_info:
2794 push ds
2795 push ax
2796 mov ax, # BIOSMEM_SEG
2797 mov ds, ax
2798 xor ch, ch
2799 mov bx, # BIOSMEM_SWITCHES
2800 mov cl, [bx]
2801 and cl, #0x0f
2802 mov bx, # BIOSMEM_CRTC_ADDRESS
2803 mov ax, [bx]
2804 mov bx, #0x0003
2805 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2806 jne mode_ega_color
2807 mov bh, #0x01
2808 mode_ega_color:
2809 pop ax
2810 pop ds
2812 ASM_END
2814 // --------------------------------------------------------------------------------------------
2815 static void biosfn_alternate_prtsc()
2817 #ifdef DEBUG
2818 unimplemented();
2819 #endif
2822 // --------------------------------------------------------------------------------------------
2823 ASM_START
2824 biosfn_select_vert_res:
2826 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2828 push ds
2829 push bx
2830 push dx
2831 mov dl, al
2832 mov ax, # BIOSMEM_SEG
2833 mov ds, ax
2834 mov bx, # BIOSMEM_MODESET_CTL
2835 mov al, [bx]
2836 mov bx, # BIOSMEM_SWITCHES
2837 mov ah, [bx]
2838 cmp dl, #0x01
2839 je vert_res_350
2840 jb vert_res_200
2841 cmp dl, #0x02
2842 je vert_res_400
2843 #ifdef DEBUG
2844 mov al, dl
2845 xor ah, ah
2846 push ax
2847 mov bx, #msg_vert_res
2848 push bx
2849 call _printf
2850 add sp, #4
2851 #endif
2852 jmp set_retcode
2853 vert_res_400:
2855 ; reset modeset ctl bit 7 and set bit 4
2856 ; set switches bit 3-0 to 0x09
2858 and al, #0x7f
2859 or al, #0x10
2860 and ah, #0xf0
2861 or ah, #0x09
2862 jnz set_vert_res
2863 vert_res_350:
2865 ; reset modeset ctl bit 7 and bit 4
2866 ; set switches bit 3-0 to 0x09
2868 and al, #0x6f
2869 and ah, #0xf0
2870 or ah, #0x09
2871 jnz set_vert_res
2872 vert_res_200:
2874 ; set modeset ctl bit 7 and reset bit 4
2875 ; set switches bit 3-0 to 0x08
2877 and al, #0xef
2878 or al, #0x80
2879 and ah, #0xf0
2880 or ah, #0x08
2881 set_vert_res:
2882 mov bx, # BIOSMEM_MODESET_CTL
2883 mov [bx], al
2884 mov bx, # BIOSMEM_SWITCHES
2885 mov [bx], ah
2886 set_retcode:
2887 mov ax, #0x1212
2888 pop dx
2889 pop bx
2890 pop ds
2893 #ifdef DEBUG
2894 msg_vert_res:
2895 .ascii "Select vert res (%02x) was discarded"
2896 .byte 0x0d,0x0a,0x00
2897 #endif
2900 biosfn_enable_default_palette_loading:
2901 push ds
2902 push bx
2903 push dx
2904 mov dl, al
2905 and dl, #0x01
2906 shl dl, 3
2907 mov ax, # BIOSMEM_SEG
2908 mov ds, ax
2909 mov bx, # BIOSMEM_MODESET_CTL
2910 mov al, [bx]
2911 and al, #0xf7
2912 or al, dl
2913 mov [bx], al
2914 mov ax, #0x1212
2915 pop dx
2916 pop bx
2917 pop ds
2921 biosfn_enable_video_addressing:
2922 push bx
2923 push dx
2924 mov bl, al
2925 and bl, #0x01
2926 xor bl, #0x01
2927 shl bl, 1
2928 mov dx, # VGAREG_READ_MISC_OUTPUT
2929 in al, dx
2930 and al, #0xfd
2931 or al, bl
2932 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2933 out dx, al
2934 mov ax, #0x1212
2935 pop dx
2936 pop bx
2940 biosfn_enable_grayscale_summing:
2941 push ds
2942 push bx
2943 push dx
2944 mov dl, al
2945 and dl, #0x01
2946 xor dl, #0x01
2947 shl dl, 1
2948 mov ax, # BIOSMEM_SEG
2949 mov ds, ax
2950 mov bx, # BIOSMEM_MODESET_CTL
2951 mov al, [bx]
2952 and al, #0xfd
2953 or al, dl
2954 mov [bx], al
2955 mov ax, #0x1212
2956 pop dx
2957 pop bx
2958 pop ds
2962 biosfn_enable_cursor_emulation:
2963 push ds
2964 push bx
2965 push dx
2966 mov dl, al
2967 and dl, #0x01
2968 xor dl, #0x01
2969 mov ax, # BIOSMEM_SEG
2970 mov ds, ax
2971 mov bx, # BIOSMEM_MODESET_CTL
2972 mov al, [bx]
2973 and al, #0xfe
2974 or al, dl
2975 mov [bx], al
2976 mov ax, #0x1212
2977 pop dx
2978 pop bx
2979 pop ds
2981 ASM_END
2983 // --------------------------------------------------------------------------------------------
2984 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2986 #ifdef DEBUG
2987 unimplemented();
2988 #endif
2990 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2992 #ifdef DEBUG
2993 unimplemented();
2994 #endif
2997 // --------------------------------------------------------------------------------------------
2998 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2999 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3001 Bit16u newcurs,oldcurs,dummy;
3002 Bit8u car,carattr;
3004 // Read curs info for the page
3005 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3007 // if row=0xff special case : use current cursor position
3008 if(row==0xff)
3009 {col=oldcurs&0x00ff;
3010 row=(oldcurs&0xff00)>>8;
3013 newcurs=row; newcurs<<=8; newcurs+=col;
3014 biosfn_set_cursor_pos(page,newcurs);
3016 while(count--!=0)
3018 car=read_byte(seg,offset++);
3019 if((flag&0x02)!=0)
3020 attr=read_byte(seg,offset++);
3022 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3025 // Set back curs pos
3026 if((flag&0x01)==0)
3027 biosfn_set_cursor_pos(page,oldcurs);
3030 // --------------------------------------------------------------------------------------------
3031 ASM_START
3032 biosfn_group_1A:
3033 cmp al, #0x00
3034 je biosfn_read_display_code
3035 cmp al, #0x01
3036 je biosfn_set_display_code
3037 #ifdef DEBUG
3038 call _unknown
3039 #endif
3041 biosfn_read_display_code:
3042 push ds
3043 push ax
3044 mov ax, # BIOSMEM_SEG
3045 mov ds, ax
3046 mov bx, # BIOSMEM_DCC_INDEX
3047 mov al, [bx]
3048 mov bl, al
3049 xor bh, bh
3050 pop ax
3051 mov al, ah
3052 pop ds
3054 biosfn_set_display_code:
3055 push ds
3056 push ax
3057 push bx
3058 mov ax, # BIOSMEM_SEG
3059 mov ds, ax
3060 mov ax, bx
3061 mov bx, # BIOSMEM_DCC_INDEX
3062 mov [bx], al
3063 #ifdef DEBUG
3064 mov al, ah
3065 xor ah, ah
3066 push ax
3067 mov bx, #msg_alt_dcc
3068 push bx
3069 call _printf
3070 add sp, #4
3071 #endif
3072 pop bx
3073 pop ax
3074 mov al, ah
3075 pop ds
3078 #ifdef DEBUG
3079 msg_alt_dcc:
3080 .ascii "Alternate Display code (%02x) was discarded"
3081 .byte 0x0d,0x0a,0x00
3082 #endif
3083 ASM_END
3085 // --------------------------------------------------------------------------------------------
3086 static void biosfn_read_state_info (BX,ES,DI)
3087 Bit16u BX;Bit16u ES;Bit16u DI;
3089 // Address of static functionality table
3090 write_word(ES,DI+0x00,&static_functionality);
3091 write_word(ES,DI+0x02,0xC000);
3093 // Hard coded copy from BIOS area. Should it be cleaner ?
3094 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3095 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3097 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3098 write_byte(ES,DI+0x26,0);
3099 write_byte(ES,DI+0x27,16);
3100 write_byte(ES,DI+0x28,0);
3101 write_byte(ES,DI+0x29,8);
3102 write_byte(ES,DI+0x2a,2);
3103 write_byte(ES,DI+0x2b,0);
3104 write_byte(ES,DI+0x2c,0);
3105 write_byte(ES,DI+0x31,3);
3106 write_byte(ES,DI+0x32,0);
3108 memsetb(ES,DI+0x33,0,13);
3111 // --------------------------------------------------------------------------------------------
3112 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3114 #ifdef DEBUG
3115 unimplemented();
3116 #endif
3118 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3120 #ifdef DEBUG
3121 unimplemented();
3122 #endif
3124 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3126 #ifdef DEBUG
3127 unimplemented();
3128 #endif
3131 // ============================================================================================
3133 // Video Utils
3135 // ============================================================================================
3137 // --------------------------------------------------------------------------------------------
3138 static Bit8u find_vga_entry(mode)
3139 Bit8u mode;
3141 Bit8u i,line=0xFF;
3142 for(i=0;i<=MODE_MAX;i++)
3143 if(vga_modes[i].svgamode==mode)
3144 {line=i;
3145 break;
3147 return line;
3150 /* =========================================================== */
3152 * Misc Utils
3154 /* =========================================================== */
3156 // --------------------------------------------------------------------------------------------
3157 static void memsetb(seg,offset,value,count)
3158 Bit16u seg;
3159 Bit16u offset;
3160 Bit16u value;
3161 Bit16u count;
3163 ASM_START
3164 push bp
3165 mov bp, sp
3167 push ax
3168 push cx
3169 push es
3170 push di
3172 mov cx, 10[bp] ; count
3173 cmp cx, #0x00
3174 je memsetb_end
3175 mov ax, 4[bp] ; segment
3176 mov es, ax
3177 mov ax, 6[bp] ; offset
3178 mov di, ax
3179 mov al, 8[bp] ; value
3182 stosb
3184 memsetb_end:
3185 pop di
3186 pop es
3187 pop cx
3188 pop ax
3190 pop bp
3191 ASM_END
3194 // --------------------------------------------------------------------------------------------
3195 static void memsetw(seg,offset,value,count)
3196 Bit16u seg;
3197 Bit16u offset;
3198 Bit16u value;
3199 Bit16u count;
3201 ASM_START
3202 push bp
3203 mov bp, sp
3205 push ax
3206 push cx
3207 push es
3208 push di
3210 mov cx, 10[bp] ; count
3211 cmp cx, #0x00
3212 je memsetw_end
3213 mov ax, 4[bp] ; segment
3214 mov es, ax
3215 mov ax, 6[bp] ; offset
3216 mov di, ax
3217 mov ax, 8[bp] ; value
3220 stosw
3222 memsetw_end:
3223 pop di
3224 pop es
3225 pop cx
3226 pop ax
3228 pop bp
3229 ASM_END
3232 // --------------------------------------------------------------------------------------------
3233 static void memcpyb(dseg,doffset,sseg,soffset,count)
3234 Bit16u dseg;
3235 Bit16u doffset;
3236 Bit16u sseg;
3237 Bit16u soffset;
3238 Bit16u count;
3240 ASM_START
3241 push bp
3242 mov bp, sp
3244 push ax
3245 push cx
3246 push es
3247 push di
3248 push ds
3249 push si
3251 mov cx, 12[bp] ; count
3252 cmp cx, #0x0000
3253 je memcpyb_end
3254 mov ax, 4[bp] ; dsegment
3255 mov es, ax
3256 mov ax, 6[bp] ; doffset
3257 mov di, ax
3258 mov ax, 8[bp] ; ssegment
3259 mov ds, ax
3260 mov ax, 10[bp] ; soffset
3261 mov si, ax
3264 movsb
3266 memcpyb_end:
3267 pop si
3268 pop ds
3269 pop di
3270 pop es
3271 pop cx
3272 pop ax
3274 pop bp
3275 ASM_END
3278 // --------------------------------------------------------------------------------------------
3279 static void memcpyw(dseg,doffset,sseg,soffset,count)
3280 Bit16u dseg;
3281 Bit16u doffset;
3282 Bit16u sseg;
3283 Bit16u soffset;
3284 Bit16u count;
3286 ASM_START
3287 push bp
3288 mov bp, sp
3290 push ax
3291 push cx
3292 push es
3293 push di
3294 push ds
3295 push si
3297 mov cx, 12[bp] ; count
3298 cmp cx, #0x0000
3299 je memcpyw_end
3300 mov ax, 4[bp] ; dsegment
3301 mov es, ax
3302 mov ax, 6[bp] ; doffset
3303 mov di, ax
3304 mov ax, 8[bp] ; ssegment
3305 mov ds, ax
3306 mov ax, 10[bp] ; soffset
3307 mov si, ax
3310 movsw
3312 memcpyw_end:
3313 pop si
3314 pop ds
3315 pop di
3316 pop es
3317 pop cx
3318 pop ax
3320 pop bp
3321 ASM_END
3324 /* =========================================================== */
3326 * These functions where ripped from Kevin's rombios.c
3328 /* =========================================================== */
3330 // --------------------------------------------------------------------------------------------
3331 static Bit8u
3332 read_byte(seg, offset)
3333 Bit16u seg;
3334 Bit16u offset;
3336 ASM_START
3337 push bp
3338 mov bp, sp
3340 push bx
3341 push ds
3342 mov ax, 4[bp] ; segment
3343 mov ds, ax
3344 mov bx, 6[bp] ; offset
3345 mov al, [bx]
3346 ;; al = return value (byte)
3347 pop ds
3348 pop bx
3350 pop bp
3351 ASM_END
3354 // --------------------------------------------------------------------------------------------
3355 static Bit16u
3356 read_word(seg, offset)
3357 Bit16u seg;
3358 Bit16u offset;
3360 ASM_START
3361 push bp
3362 mov bp, sp
3364 push bx
3365 push ds
3366 mov ax, 4[bp] ; segment
3367 mov ds, ax
3368 mov bx, 6[bp] ; offset
3369 mov ax, [bx]
3370 ;; ax = return value (word)
3371 pop ds
3372 pop bx
3374 pop bp
3375 ASM_END
3378 // --------------------------------------------------------------------------------------------
3379 static void
3380 write_byte(seg, offset, data)
3381 Bit16u seg;
3382 Bit16u offset;
3383 Bit8u data;
3385 ASM_START
3386 push bp
3387 mov bp, sp
3389 push ax
3390 push bx
3391 push ds
3392 mov ax, 4[bp] ; segment
3393 mov ds, ax
3394 mov bx, 6[bp] ; offset
3395 mov al, 8[bp] ; data byte
3396 mov [bx], al ; write data byte
3397 pop ds
3398 pop bx
3399 pop ax
3401 pop bp
3402 ASM_END
3405 // --------------------------------------------------------------------------------------------
3406 static void
3407 write_word(seg, offset, data)
3408 Bit16u seg;
3409 Bit16u offset;
3410 Bit16u data;
3412 ASM_START
3413 push bp
3414 mov bp, sp
3416 push ax
3417 push bx
3418 push ds
3419 mov ax, 4[bp] ; segment
3420 mov ds, ax
3421 mov bx, 6[bp] ; offset
3422 mov ax, 8[bp] ; data word
3423 mov [bx], ax ; write data word
3424 pop ds
3425 pop bx
3426 pop ax
3428 pop bp
3429 ASM_END
3432 // --------------------------------------------------------------------------------------------
3433 Bit8u
3434 inb(port)
3435 Bit16u port;
3437 ASM_START
3438 push bp
3439 mov bp, sp
3441 push dx
3442 mov dx, 4[bp]
3443 in al, dx
3444 pop dx
3446 pop bp
3447 ASM_END
3450 Bit16u
3451 inw(port)
3452 Bit16u port;
3454 ASM_START
3455 push bp
3456 mov bp, sp
3458 push dx
3459 mov dx, 4[bp]
3460 in ax, dx
3461 pop dx
3463 pop bp
3464 ASM_END
3467 // --------------------------------------------------------------------------------------------
3468 void
3469 outb(port, val)
3470 Bit16u port;
3471 Bit8u val;
3473 ASM_START
3474 push bp
3475 mov bp, sp
3477 push ax
3478 push dx
3479 mov dx, 4[bp]
3480 mov al, 6[bp]
3481 out dx, al
3482 pop dx
3483 pop ax
3485 pop bp
3486 ASM_END
3489 // --------------------------------------------------------------------------------------------
3490 void
3491 outw(port, val)
3492 Bit16u port;
3493 Bit16u val;
3495 ASM_START
3496 push bp
3497 mov bp, sp
3499 push ax
3500 push dx
3501 mov dx, 4[bp]
3502 mov ax, 6[bp]
3503 out dx, ax
3504 pop dx
3505 pop ax
3507 pop bp
3508 ASM_END
3511 Bit16u get_SS()
3513 ASM_START
3514 mov ax, ss
3515 ASM_END
3518 #ifdef DEBUG
3519 void unimplemented()
3521 printf("--> Unimplemented\n");
3524 void unknown()
3526 printf("--> Unknown int10\n");
3528 #endif
3530 // --------------------------------------------------------------------------------------------
3531 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3532 void printf(s)
3533 Bit8u *s;
3535 Bit8u c, format_char;
3536 Boolean in_format;
3537 unsigned format_width, i;
3538 Bit16u *arg_ptr;
3539 Bit16u arg_seg, arg, digit, nibble, shift_count;
3541 arg_ptr = &s;
3542 arg_seg = get_SS();
3544 in_format = 0;
3545 format_width = 0;
3547 while (c = read_byte(0xc000, s)) {
3548 if ( c == '%' ) {
3549 in_format = 1;
3550 format_width = 0;
3552 else if (in_format) {
3553 if ( (c>='0') && (c<='9') ) {
3554 format_width = (format_width * 10) + (c - '0');
3556 else if (c == 'x') {
3557 arg_ptr++; // increment to next arg
3558 arg = read_word(arg_seg, arg_ptr);
3559 if (format_width == 0)
3560 format_width = 4;
3561 i = 0;
3562 digit = format_width - 1;
3563 for (i=0; i<format_width; i++) {
3564 nibble = (arg >> (4 * digit)) & 0x000f;
3565 if (nibble <= 9)
3566 outb(0x0500, nibble + '0');
3567 else
3568 outb(0x0500, (nibble - 10) + 'A');
3569 digit--;
3571 in_format = 0;
3573 //else if (c == 'd') {
3574 // in_format = 0;
3575 // }
3577 else {
3578 outb(0x0500, c);
3580 s ++;
3583 #endif
3585 #ifdef VBE
3586 #include "vbe.c"
3587 #endif
3589 #ifdef CIRRUS
3590 #include "clext.c"
3591 #endif
3593 // --------------------------------------------------------------------------------------------
3595 ASM_START
3596 ;; DATA_SEG_DEFS_HERE
3597 ASM_END
3599 ASM_START
3600 .ascii "vgabios ends here"
3601 .byte 0x00
3602 vgabios_end:
3603 .byte 0xCB
3604 ;; BLOCK_STRINGS_BEGIN
3605 ASM_END