- 4MB memory probe added (patch from Fabrice Bellard)
[vgabios.git] / vgabios.c
blobf54d20d80bfd6f611e2e993099cf9b2848b73ed0
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_switch_video_interface();
106 static void biosfn_enable_video_refresh_control();
107 static void biosfn_write_string();
108 static void biosfn_read_state_info();
109 static void biosfn_read_video_state_size();
110 static void biosfn_save_video_state();
111 static void biosfn_restore_video_state();
113 // This is for compiling with gcc2 and gcc3
114 #define ASM_START #asm
115 #define ASM_END #endasm
117 ASM_START
119 MACRO SET_INT_VECTOR
120 push ds
121 xor ax, ax
122 mov ds, ax
123 mov ax, ?3
124 mov ?1*4, ax
125 mov ax, ?2
126 mov ?1*4+2, ax
127 pop ds
128 MEND
130 ASM_END
132 ASM_START
133 .text
134 .rom
135 .org 0
137 use16 386
139 vgabios_start:
140 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
142 .byte 0x40 /* BIOS extension length in units of 512 bytes */
145 vgabios_entry_point:
147 jmp vgabios_init_func
149 vgabios_name:
150 .ascii "Plex86/Bochs VGABios"
151 .ascii " "
152 .byte 0x00
154 // Info from Bart Oldeman
155 .org 0x1e
156 .ascii "IBM"
157 .byte 0x00
159 vgabios_version:
160 #ifndef VGABIOS_VERS
161 .ascii "current-cvs"
162 #else
163 .ascii VGABIOS_VERS
164 #endif
165 .ascii " "
167 vgabios_date:
168 .ascii VGABIOS_DATE
169 .byte 0x0a,0x0d
170 .byte 0x00
172 vgabios_copyright:
173 .ascii "(C) 2003 the LGPL VGABios developers Team"
174 .byte 0x0a,0x0d
175 .byte 0x00
177 vgabios_license:
178 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
179 .byte 0x0a,0x0d
180 .byte 0x0a,0x0d
181 .byte 0x00
183 vgabios_website:
184 .ascii "Please visit :"
185 .byte 0x0a,0x0d
186 ;;.ascii " . http://www.plex86.org"
187 ;;.byte 0x0a,0x0d
188 .ascii " . http://bochs.sourceforge.net"
189 .byte 0x0a,0x0d
190 .ascii " . http://www.nongnu.org/vgabios"
191 .byte 0x0a,0x0d
192 .byte 0x0a,0x0d
193 .byte 0x00
196 ;; ============================================================================================
198 ;; Init Entry point
200 ;; ============================================================================================
201 vgabios_init_func:
203 ;; init vga card
204 call init_vga_card
206 ;; init basic bios vars
207 call init_bios_area
209 #ifdef VBE
210 ;; init vbe functions
211 call vbe_init
212 #endif
214 ;; set int10 vect
215 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
217 #ifdef CIRRUS
218 call cirrus_init
219 #endif
221 ;; display splash screen
222 call _display_splash_screen
224 ;; init video mode and clear the screen
225 mov ax,#0x0003
226 int #0x10
228 ;; show info
229 call _display_info
231 #ifdef VBE
232 ;; show vbe info
233 call vbe_display_info
234 #endif
236 #ifdef CIRRUS
237 ;; show cirrus info
238 call cirrus_display_info
239 #endif
241 retf
242 ASM_END
245 * int10 handled here
247 ASM_START
248 vgabios_int10_handler:
249 pushf
250 #ifdef DEBUG
251 push es
252 push ds
253 pusha
254 mov bx, #0xc000
255 mov ds, bx
256 call _int10_debugmsg
257 popa
258 pop ds
259 pop es
260 #endif
261 cmp ah, #0x0f
262 jne int10_test_1A
263 call biosfn_get_video_mode
264 jmp int10_end
265 int10_test_1A:
266 cmp ah, #0x1a
267 jne int10_test_0B
268 call biosfn_group_1A
269 jmp int10_end
270 int10_test_0B:
271 cmp ah, #0x0b
272 jne int10_test_1103
273 call biosfn_group_0B
274 jmp int10_end
275 int10_test_1103:
276 cmp ax, #0x1103
277 jne int10_test_12
278 call biosfn_set_text_block_specifier
279 jmp int10_end
280 int10_test_12:
281 cmp ah, #0x12
282 jne int10_test_101B
283 cmp bl, #0x10
284 jne int10_test_BL30
285 call biosfn_get_ega_info
286 jmp int10_end
287 int10_test_BL30:
288 cmp bl, #0x30
289 jne int10_test_BL31
290 call biosfn_select_vert_res
291 jmp int10_end
292 int10_test_BL31:
293 cmp bl, #0x31
294 jne int10_test_BL32
295 call biosfn_enable_default_palette_loading
296 jmp int10_end
297 int10_test_BL32:
298 cmp bl, #0x32
299 jne int10_test_BL33
300 call biosfn_enable_video_addressing
301 jmp int10_end
302 int10_test_BL33:
303 cmp bl, #0x33
304 jne int10_test_BL34
305 call biosfn_enable_grayscale_summing
306 jmp int10_end
307 int10_test_BL34:
308 cmp bl, #0x34
309 jne int10_normal
310 call biosfn_enable_cursor_emulation
311 jmp int10_end
312 int10_test_101B:
313 cmp ax, #0x101b
314 je int10_normal
315 cmp ah, #0x10
316 #ifndef VBE
317 jne int10_normal
318 #else
319 jne int10_test_4F
320 #endif
321 call biosfn_group_10
322 jmp int10_end
323 #ifdef VBE
324 int10_test_4F:
325 cmp ah, #0x4f
326 jne int10_normal
327 cmp al, #0x03
328 jne int10_test_vbe_05
329 call vbe_biosfn_return_current_mode
330 jmp int10_end
331 int10_test_vbe_05:
332 cmp al, #0x05
333 jne int10_test_vbe_06
334 call vbe_biosfn_display_window_control
335 jmp int10_end
336 int10_test_vbe_06:
337 cmp al, #0x06
338 jne int10_test_vbe_07
339 call vbe_biosfn_set_get_logical_scan_line_length
340 jmp int10_end
341 int10_test_vbe_07:
342 cmp al, #0x07
343 jne int10_test_vbe_08
344 call vbe_biosfn_set_get_display_start
345 jmp int10_end
346 int10_test_vbe_08:
347 cmp al, #0x08
348 jne int10_normal
349 call vbe_biosfn_set_get_dac_palette_format
350 jmp int10_end
351 #endif
353 int10_normal:
354 push es
355 push ds
356 pusha
358 ;; We have to set ds to access the right data segment
359 mov bx, #0xc000
360 mov ds, bx
361 call _int10_func
363 popa
364 pop ds
365 pop es
366 int10_end:
367 popf
368 iret
369 ASM_END
371 #include "vgatables.h"
372 #include "vgafonts.h"
375 * Boot time harware inits
377 ASM_START
378 init_vga_card:
379 ;; switch to color mode and enable CPU access 480 lines
380 mov dx, #0x3C2
381 mov al, #0xC3
382 outb dx,al
384 ;; more than 64k 3C4/04
385 mov dx, #0x3C4
386 mov al, #0x04
387 outb dx,al
388 mov dx, #0x3C5
389 mov al, #0x02
390 outb dx,al
392 mov bx, #msg_vga_init
393 push bx
394 call _printf
395 inc sp
396 inc sp
399 msg_vga_init:
400 .ascii "VGABios $Id$"
401 .byte 0x0d,0x0a,0x00
402 ASM_END
404 // --------------------------------------------------------------------------------------------
406 * Boot time bios area inits
408 ASM_START
409 init_bios_area:
410 push ds
411 mov ax, # BIOSMEM_SEG
412 mov ds, ax
414 ;; init detected hardware BIOS Area
415 mov bx, # BIOSMEM_INITIAL_MODE
416 mov ax, [bx]
417 and ax, #0xffcf
418 mov [bx], ax
420 ;; Just for the first int10 find its children
422 ;; the default char height
423 mov bx, # BIOSMEM_CHAR_HEIGHT
424 mov al, #0x10
425 mov [bx], al
427 ;; Clear the screen
428 mov bx, # BIOSMEM_VIDEO_CTL
429 mov al, #0x60
430 mov [bx], al
432 ;; Set the basic screen we have
433 mov bx, # BIOSMEM_SWITCHES
434 mov al, #0xf9
435 mov [bx], al
437 ;; Set the basic modeset options
438 mov bx, # BIOSMEM_MODESET_CTL
439 mov al, #0x51
440 mov [bx], al
442 ;; Set the default MSR
443 mov bx, # BIOSMEM_CURRENT_MSR
444 mov al, #0x09
445 mov [bx], al
447 pop ds
449 ASM_END
451 // --------------------------------------------------------------------------------------------
453 * Boot time Splash screen
455 static void display_splash_screen()
459 // --------------------------------------------------------------------------------------------
461 * Tell who we are
464 static void display_info()
466 ASM_START
467 mov ax,#0xc000
468 mov ds,ax
469 mov si,#vgabios_name
470 call _display_string
471 mov si,#vgabios_version
472 call _display_string
474 ;;mov si,#vgabios_copyright
475 ;;call _display_string
476 ;;mov si,#crlf
477 ;;call _display_string
479 mov si,#vgabios_license
480 call _display_string
481 mov si,#vgabios_website
482 call _display_string
483 ASM_END
486 static void display_string()
488 // Get length of string
489 ASM_START
490 mov ax,ds
491 mov es,ax
492 mov di,si
493 xor cx,cx
494 not cx
495 xor al,al
497 repne
498 scasb
499 not cx
500 dec cx
501 push cx
503 mov ax,#0x0300
504 mov bx,#0x0000
505 int #0x10
507 pop cx
508 mov ax,#0x1301
509 mov bx,#0x000b
510 mov bp,si
511 int #0x10
512 ASM_END
515 // --------------------------------------------------------------------------------------------
516 #ifdef DEBUG
517 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
518 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
520 // 0E is write char...
521 if(GET_AH()!=0x0E)
522 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
524 #endif
526 // --------------------------------------------------------------------------------------------
528 * int10 main dispatcher
530 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
531 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
534 // BIOS functions
535 switch(GET_AH())
537 case 0x00:
538 biosfn_set_video_mode(GET_AL());
539 switch(GET_AL()&0x7F)
540 {case 6:
541 SET_AL(0x3F);
542 break;
543 case 0:
544 case 1:
545 case 2:
546 case 3:
547 case 4:
548 case 5:
549 case 7:
550 SET_AL(0x30);
551 break;
552 default:
553 SET_AL(0x20);
555 break;
556 case 0x01:
557 biosfn_set_cursor_shape(GET_CH(),GET_CL());
558 break;
559 case 0x02:
560 biosfn_set_cursor_pos(GET_BH(),DX);
561 break;
562 case 0x03:
563 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
564 break;
565 case 0x04:
566 // Read light pen pos (unimplemented)
567 #ifdef DEBUG
568 unimplemented();
569 #endif
570 AX=0x00;
571 BX=0x00;
572 CX=0x00;
573 DX=0x00;
574 break;
575 case 0x05:
576 biosfn_set_active_page(GET_AL());
577 break;
578 case 0x06:
579 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
580 break;
581 case 0x07:
582 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
583 break;
584 case 0x08:
585 biosfn_read_char_attr(GET_BH(),&AX);
586 break;
587 case 0x09:
588 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
589 break;
590 case 0x0A:
591 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
592 break;
593 case 0x0C:
594 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
595 break;
596 case 0x0D:
597 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
598 break;
599 case 0x0E:
600 // Ralf Brown Interrupt list is WRONG on bh(page)
601 // We do output only on the current page !
602 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
603 break;
604 case 0x10:
605 // All other functions of group AH=0x10 rewritten in assembler
606 biosfn_perform_gray_scale_summing(BX,CX);
607 break;
608 case 0x11:
609 switch(GET_AL())
611 case 0x00:
612 case 0x10:
613 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
614 break;
615 case 0x01:
616 case 0x11:
617 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
618 break;
619 case 0x02:
620 case 0x12:
621 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
622 break;
623 case 0x04:
624 case 0x14:
625 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
626 break;
627 case 0x20:
628 biosfn_load_gfx_8_8_chars(ES,BP);
629 break;
630 case 0x21:
631 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
632 break;
633 case 0x22:
634 biosfn_load_gfx_8_14_chars(GET_BL());
635 break;
636 case 0x23:
637 biosfn_load_gfx_8_8_dd_chars(GET_BL());
638 break;
639 case 0x24:
640 biosfn_load_gfx_8_16_chars(GET_BL());
641 break;
642 case 0x30:
643 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
644 break;
645 #ifdef DEBUG
646 default:
647 unknown();
648 #endif
651 break;
652 case 0x12:
653 switch(GET_BL())
655 case 0x20:
656 biosfn_alternate_prtsc();
657 break;
658 case 0x35:
659 biosfn_switch_video_interface(GET_AL(),ES,DX);
660 SET_AL(0x12);
661 break;
662 case 0x36:
663 biosfn_enable_video_refresh_control(GET_AL());
664 SET_AL(0x12);
665 break;
666 #ifdef DEBUG
667 default:
668 unknown();
669 #endif
671 break;
672 case 0x13:
673 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
674 break;
675 case 0x1B:
676 biosfn_read_state_info(BX,ES,DI);
677 SET_AL(0x1B);
678 break;
679 case 0x1C:
680 switch(GET_AL())
682 case 0x00:
683 biosfn_read_video_state_size(CX,&BX);
684 break;
685 case 0x01:
686 biosfn_save_video_state(CX,ES,BX);
687 break;
688 case 0x02:
689 biosfn_restore_video_state(CX,ES,BX);
690 break;
691 #ifdef DEBUG
692 default:
693 unknown();
694 #endif
696 SET_AL(0x1C);
697 break;
699 #ifdef VBE
700 case 0x4f:
701 if (vbe_has_vbe_display()) {
702 switch(GET_AL())
704 case 0x00:
705 vbe_biosfn_return_controller_information(&AX,ES,DI);
706 break;
707 case 0x01:
708 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
709 break;
710 case 0x02:
711 vbe_biosfn_set_mode(&AX,BX,ES,DI);
712 break;
713 case 0x04:
714 //FIXME
715 #ifdef DEBUG
716 unimplemented();
717 #endif
718 // function failed
719 AX=0x100;
720 break;
721 case 0x09:
722 //FIXME
723 #ifdef DEBUG
724 unimplemented();
725 #endif
726 // function failed
727 AX=0x100;
728 break;
729 case 0x0A:
730 //FIXME
731 #ifdef DEBUG
732 unimplemented();
733 #endif
734 // function failed
735 AX=0x100;
736 break;
737 #ifdef DEBUG
738 default:
739 unknown();
740 #endif
741 // function failed
742 AX=0x100;
745 else {
746 // No VBE display
747 AX=0x0100;
749 break;
750 #endif
752 #ifdef DEBUG
753 default:
754 unknown();
755 #endif
759 // ============================================================================================
761 // BIOS functions
763 // ============================================================================================
765 static void biosfn_set_video_mode(mode) Bit8u mode;
766 {// mode: Bit 7 is 1 if no clear screen
768 // Should we clear the screen ?
769 Bit8u noclearmem=mode&0x80;
770 Bit8u line,mmask,*palette;
771 Bit16u i,twidth,theight,cheight;
772 Bit8u modeset_ctl,video_ctl,vga_switches;
773 Bit16u crtc_addr;
775 #ifdef VBE
776 if (vbe_has_vbe_display()) {
777 dispi_set_enable(VBE_DISPI_DISABLED);
779 #endif // def VBE
781 // The real mode
782 mode=mode&0x7f;
784 // find the entry in the video modes
785 line=find_vga_entry(mode);
787 #ifdef DEBUG
788 printf("mode search %02x found line %02x\n",mode,line);
789 #endif
791 if(line==0xFF)
792 return;
794 twidth=vga_modes[line].twidth;
795 theight=vga_modes[line].theight;
796 cheight=vga_modes[line].cheight;
798 // Read the bios vga control
799 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
801 // Read the bios vga switches
802 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
804 // Read the bios mode set control
805 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
807 // Then we know the number of lines
808 // FIXME
810 // if palette loading (bit 3 of modeset ctl = 0)
811 if((modeset_ctl&0x08)==0)
812 {// Set the PEL mask
813 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
815 // Set the whole dac always, from 0
816 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
818 // From which palette
819 switch(vga_modes[line].dacmodel)
820 {case 0:
821 palette=&palette0;
822 break;
823 case 1:
824 palette=&palette1;
825 break;
826 case 2:
827 palette=&palette2;
828 break;
829 case 3:
830 palette=&palette3;
831 break;
833 // Always 256*3 values
834 for(i=0;i<0x0100;i++)
835 {if(i<=dac_regs[vga_modes[line].dacmodel])
836 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
837 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
838 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
840 else
841 {outb(VGAREG_DAC_DATA,0);
842 outb(VGAREG_DAC_DATA,0);
843 outb(VGAREG_DAC_DATA,0);
846 if((modeset_ctl&0x02)==0x02)
848 biosfn_perform_gray_scale_summing(0x00, 0x100);
852 // Reset Attribute Ctl flip-flop
853 inb(VGAREG_ACTL_RESET);
855 // Set Attribute Ctl
856 for(i=0;i<=ACTL_MAX_REG;i++)
857 {outb(VGAREG_ACTL_ADDRESS,i);
858 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
861 // Set Sequencer Ctl
862 for(i=0;i<=SEQU_MAX_REG;i++)
863 {outb(VGAREG_SEQU_ADDRESS,i);
864 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
867 // Set Grafx Ctl
868 for(i=0;i<=GRDC_MAX_REG;i++)
869 {outb(VGAREG_GRDC_ADDRESS,i);
870 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
873 // Set CRTC address VGA or MDA
874 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
876 // Set CRTC regs
877 for(i=0;i<=CRTC_MAX_REG;i++)
878 {outb(crtc_addr,i);
879 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
882 // Set the misc register
883 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
885 // Enable video
886 outb(VGAREG_ACTL_ADDRESS,0x20);
887 inb(VGAREG_ACTL_RESET);
889 if(noclearmem==0x00)
891 if(vga_modes[line].class==TEXT)
893 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
895 else
897 if(mode<0x0d)
899 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
901 else
903 outb( VGAREG_SEQU_ADDRESS, 0x02 );
904 mmask = inb( VGAREG_SEQU_DATA );
905 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
906 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
907 outb( VGAREG_SEQU_DATA, mmask );
912 // Set the BIOS mem
913 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
914 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
915 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
916 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
917 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
918 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
919 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
920 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
921 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
923 // FIXME We nearly have the good tables. to be reworked
924 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
925 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
926 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
928 // FIXME
929 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
930 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
932 // Set cursor shape
933 if(vga_modes[line].class==TEXT)
935 biosfn_set_cursor_shape(0x06,0x07);
938 // Set cursor pos for page 0..7
939 for(i=0;i<8;i++)
940 biosfn_set_cursor_pos(i,0x0000);
942 // Set active page 0
943 biosfn_set_active_page(0x00);
945 // Write the fonts in memory
946 if(vga_modes[line].class==TEXT)
948 ASM_START
949 ;; copy and activate 8x16 font
950 mov ax, #0x1104
951 mov bl, #0x00
952 int #0x10
953 mov ax, #0x1103
954 mov bl, #0x00
955 int #0x10
956 ASM_END
959 // Set the ints 0x1F and 0x43
960 ASM_START
961 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
962 ASM_END
964 switch(cheight)
965 {case 8:
966 ASM_START
967 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
968 ASM_END
969 break;
970 case 14:
971 ASM_START
972 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
973 ASM_END
974 break;
975 case 16:
976 ASM_START
977 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
978 ASM_END
979 break;
983 // --------------------------------------------------------------------------------------------
984 static void biosfn_set_cursor_shape (CH,CL)
985 Bit8u CH;Bit8u CL;
986 {Bit16u cheight,curs,crtc_addr;
987 Bit8u modeset_ctl;
989 CH&=0x3f;
990 CL&=0x1f;
992 curs=(CH<<8)+CL;
993 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
995 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
996 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
997 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
999 if(CL!=(CH+1))
1001 CH = ((CH+1) * cheight / 8) -1;
1003 else
1005 CH = ((CL+1) * cheight / 8) - 2;
1007 CL = ((CL+1) * cheight / 8) - 1;
1010 // CTRC regs 0x0a and 0x0b
1011 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1012 outb(crtc_addr,0x0a);
1013 outb(crtc_addr+1,CH);
1014 outb(crtc_addr,0x0b);
1015 outb(crtc_addr+1,CL);
1018 // --------------------------------------------------------------------------------------------
1019 static void biosfn_set_cursor_pos (page, cursor)
1020 Bit8u page;Bit16u cursor;
1022 Bit8u xcurs,ycurs,current;
1023 Bit16u nbcols,nbrows,address,crtc_addr;
1025 // Should not happen...
1026 if(page>7)return;
1028 // Bios cursor pos
1029 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1031 // Set the hardware cursor
1032 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1033 if(page==current)
1035 // Get the dimensions
1036 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1037 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1039 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1041 // Calculate the address knowing nbcols nbrows and page num
1042 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1044 // CRTC regs 0x0e and 0x0f
1045 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1046 outb(crtc_addr,0x0e);
1047 outb(crtc_addr+1,(address&0xff00)>>8);
1048 outb(crtc_addr,0x0f);
1049 outb(crtc_addr+1,address&0x00ff);
1053 // --------------------------------------------------------------------------------------------
1054 static void biosfn_get_cursor_pos (page,shape, pos)
1055 Bit8u page;Bit16u *shape;Bit16u *pos;
1057 Bit16u ss=get_SS();
1059 // Default
1060 write_word(ss, shape, 0);
1061 write_word(ss, pos, 0);
1063 if(page>7)return;
1064 // FIXME should handle VGA 14/16 lines
1065 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1066 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1069 // --------------------------------------------------------------------------------------------
1070 static void biosfn_set_active_page (page)
1071 Bit8u page;
1073 Bit16u cursor,dummy,crtc_addr;
1074 Bit16u nbcols,nbrows,address;
1075 Bit8u mode,line;
1077 if(page>7)return;
1079 // Get the mode
1080 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1081 line=find_vga_entry(mode);
1082 if(line==0xFF)return;
1084 // Get pos curs pos for the right page
1085 biosfn_get_cursor_pos(page,&dummy,&cursor);
1087 if(vga_modes[line].class==TEXT)
1089 // Get the dimensions
1090 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1091 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1093 // Calculate the address knowing nbcols nbrows and page num
1094 address=SCREEN_MEM_START(nbcols,nbrows,page);
1095 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1097 // Start address
1098 address=SCREEN_IO_START(nbcols,nbrows,page);
1100 else
1102 address = page*vga_modes[line].slength;
1105 // CRTC regs 0x0c and 0x0d
1106 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1107 outb(crtc_addr,0x0c);
1108 outb(crtc_addr+1,(address&0xff00)>>8);
1109 outb(crtc_addr,0x0d);
1110 outb(crtc_addr+1,address&0x00ff);
1112 // And change the BIOS page
1113 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1115 #ifdef DEBUG
1116 printf("Set active page %02x address %04x\n",page,address);
1117 #endif
1119 // Display the cursor, now the page is active
1120 biosfn_set_cursor_pos(page,cursor);
1123 // --------------------------------------------------------------------------------------------
1124 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1125 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1127 Bit16u src,dest;
1128 Bit8u i;
1130 src=ysrc*cheight*nbcols+xstart;
1131 dest=ydest*cheight*nbcols+xstart;
1132 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1133 for(i=0;i<cheight;i++)
1135 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1137 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1140 // --------------------------------------------------------------------------------------------
1141 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1142 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1144 Bit16u dest;
1145 Bit8u i;
1147 dest=ystart*cheight*nbcols+xstart;
1148 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1149 for(i=0;i<cheight;i++)
1151 memsetb(0xa000,dest+i*nbcols,attr,cols);
1153 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1156 // --------------------------------------------------------------------------------------------
1157 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1158 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1160 Bit16u src,dest;
1161 Bit8u i;
1163 src=((ysrc*cheight*nbcols)>>1)+xstart;
1164 dest=((ydest*cheight*nbcols)>>1)+xstart;
1165 for(i=0;i<cheight;i++)
1167 if (i & 1)
1168 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1169 else
1170 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1174 // --------------------------------------------------------------------------------------------
1175 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1176 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1178 Bit16u dest;
1179 Bit8u i;
1181 dest=((ystart*cheight*nbcols)>>1)+xstart;
1182 for(i=0;i<cheight;i++)
1184 if (i & 1)
1185 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1186 else
1187 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1191 // --------------------------------------------------------------------------------------------
1192 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1193 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1195 // page == 0xFF if current
1197 Bit8u mode,line,cheight,bpp,cols;
1198 Bit16u nbcols,nbrows,i;
1199 Bit16u address;
1201 if(rul>rlr)return;
1202 if(cul>clr)return;
1204 // Get the mode
1205 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1206 line=find_vga_entry(mode);
1207 if(line==0xFF)return;
1209 // Get the dimensions
1210 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1211 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1213 // Get the current page
1214 if(page==0xFF)
1215 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1217 if(rlr>=nbrows)rlr=nbrows-1;
1218 if(clr>=nbcols)clr=nbcols-1;
1219 if(nblines>nbrows)nblines=0;
1220 cols=clr-cul+1;
1222 if(vga_modes[line].class==TEXT)
1224 // Compute the address
1225 address=SCREEN_MEM_START(nbcols,nbrows,page);
1226 #ifdef DEBUG
1227 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1228 #endif
1230 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1232 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1234 else
1235 {// if Scroll up
1236 if(dir==SCROLL_UP)
1237 {for(i=rul;i<=rlr;i++)
1239 if((i+nblines>rlr)||(nblines==0))
1240 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1241 else
1242 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1245 else
1246 {for(i=rlr;i>=rul;i--)
1248 if((i<rul+nblines)||(nblines==0))
1249 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1250 else
1251 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1256 else
1258 // FIXME gfx mode not complete
1259 cheight=vga_modes[line].cheight;
1260 switch(vga_modes[line].memmodel)
1262 case PLANAR4:
1263 case PLANAR1:
1264 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1266 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1267 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1268 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1270 else
1271 {// if Scroll up
1272 if(dir==SCROLL_UP)
1273 {for(i=rul;i<=rlr;i++)
1275 if((i+nblines>rlr)||(nblines==0))
1276 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1277 else
1278 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1281 else
1282 {for(i=rlr;i>=rul;i--)
1284 if((i<rul+nblines)||(nblines==0))
1285 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1286 else
1287 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1291 break;
1292 case CGA:
1293 bpp=vga_modes[line].pixbits;
1294 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1296 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1298 else
1300 if(bpp==2)
1302 cul<<=1;
1303 cols<<=1;
1304 nbcols<<=1;
1306 // if Scroll up
1307 if(dir==SCROLL_UP)
1308 {for(i=rul;i<=rlr;i++)
1310 if((i+nblines>rlr)||(nblines==0))
1311 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1312 else
1313 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1316 else
1317 {for(i=rlr;i>=rul;i--)
1319 if((i<rul+nblines)||(nblines==0))
1320 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1321 else
1322 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1326 break;
1327 #ifdef DEBUG
1328 default:
1329 printf("Scroll in graphics mode ");
1330 unimplemented();
1331 #endif
1336 // --------------------------------------------------------------------------------------------
1337 static void biosfn_read_char_attr (page,car)
1338 Bit8u page;Bit16u *car;
1339 {Bit16u ss=get_SS();
1340 Bit8u xcurs,ycurs,mode,line;
1341 Bit16u nbcols,nbrows,address;
1342 Bit16u cursor,dummy;
1344 // Get the mode
1345 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1346 line=find_vga_entry(mode);
1347 if(line==0xFF)return;
1349 // Get the cursor pos for the page
1350 biosfn_get_cursor_pos(page,&dummy,&cursor);
1351 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1353 // Get the dimensions
1354 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1355 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1357 if(vga_modes[line].class==TEXT)
1359 // Compute the address
1360 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1362 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1364 else
1366 // FIXME gfx mode
1367 #ifdef DEBUG
1368 unimplemented();
1369 #endif
1373 // --------------------------------------------------------------------------------------------
1374 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1375 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1377 Bit8u i,j,mask;
1378 Bit8u *fdata;
1379 Bit16u addr,dest,src;
1381 switch(cheight)
1382 {case 14:
1383 fdata = &vgafont14;
1384 break;
1385 case 16:
1386 fdata = &vgafont16;
1387 break;
1388 default:
1389 fdata = &vgafont8;
1391 addr=xcurs+ycurs*cheight*nbcols;
1392 src = car * cheight;
1393 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1394 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1395 if(attr&0x80)
1397 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1399 else
1401 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1403 for(i=0;i<cheight;i++)
1405 dest=addr+i*nbcols;
1406 for(j=0;j<8;j++)
1408 mask=0x80>>j;
1409 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1410 read_byte(0xa000,dest);
1411 if(fdata[src+i]&mask)
1413 write_byte(0xa000,dest,attr&0x0f);
1415 else
1417 write_byte(0xa000,dest,0x00);
1421 ASM_START
1422 mov dx, # VGAREG_GRDC_ADDRESS
1423 mov ax, #0xff08
1424 out dx, ax
1425 mov ax, #0x0005
1426 out dx, ax
1427 mov ax, #0x0003
1428 out dx, ax
1429 ASM_END
1432 // --------------------------------------------------------------------------------------------
1433 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1434 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1436 Bit8u i,j,mask,data;
1437 Bit8u *fdata;
1438 Bit16u addr,dest,src;
1440 fdata = &vgafont8;
1441 addr=(xcurs*bpp)+ycurs*320;
1442 src = car * 8;
1443 for(i=0;i<8;i++)
1445 dest=addr+(i>>1)*80;
1446 if (i & 1) dest += 0x2000;
1447 mask = 0x80;
1448 if (bpp == 1)
1450 if (attr & 0x80)
1452 data = read_byte(0xb800,dest);
1454 else
1456 data = 0x00;
1458 for(j=0;j<8;j++)
1460 if (fdata[src+i] & mask)
1462 if (attr & 0x80)
1464 data ^= (attr & 0x01) << (7-j);
1466 else
1468 data |= (attr & 0x01) << (7-j);
1471 mask >>= 1;
1473 write_byte(0xb800,dest,data);
1475 else
1477 while (mask > 0)
1479 if (attr & 0x80)
1481 data = read_byte(0xb800,dest);
1483 else
1485 data = 0x00;
1487 for(j=0;j<4;j++)
1489 if (fdata[src+i] & mask)
1491 if (attr & 0x80)
1493 data ^= (attr & 0x03) << ((3-j)*2);
1495 else
1497 data |= (attr & 0x03) << ((3-j)*2);
1500 mask >>= 1;
1502 write_byte(0xb800,dest,data);
1503 dest += 1;
1509 // --------------------------------------------------------------------------------------------
1510 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1511 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1513 Bit8u i,j,mask,data;
1514 Bit8u *fdata;
1515 Bit16u addr,dest,src;
1517 fdata = &vgafont8;
1518 addr=xcurs*8+ycurs*nbcols*64;
1519 src = car * 8;
1520 for(i=0;i<8;i++)
1522 dest=addr+i*nbcols*8;
1523 mask = 0x80;
1524 for(j=0;j<8;j++)
1526 data = 0x00;
1527 if (fdata[src+i] & mask)
1529 data = attr;
1531 write_byte(0xa000,dest+j,data);
1532 mask >>= 1;
1537 // --------------------------------------------------------------------------------------------
1538 static void biosfn_write_char_attr (car,page,attr,count)
1539 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1541 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1542 Bit16u nbcols,nbrows,address;
1543 Bit16u cursor,dummy;
1545 // Get the mode
1546 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1547 line=find_vga_entry(mode);
1548 if(line==0xFF)return;
1550 // Get the cursor pos for the page
1551 biosfn_get_cursor_pos(page,&dummy,&cursor);
1552 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1554 // Get the dimensions
1555 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1556 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1558 if(vga_modes[line].class==TEXT)
1560 // Compute the address
1561 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1563 dummy=((Bit16u)attr<<8)+car;
1564 memsetw(vga_modes[line].sstart,address,dummy,count);
1566 else
1568 // FIXME gfx mode not complete
1569 cheight=vga_modes[line].cheight;
1570 bpp=vga_modes[line].pixbits;
1571 while((count-->0) && (xcurs<nbcols))
1573 switch(vga_modes[line].memmodel)
1575 case PLANAR4:
1576 case PLANAR1:
1577 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1578 break;
1579 case CGA:
1580 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1581 break;
1582 case LINEAR8:
1583 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1584 break;
1585 #ifdef DEBUG
1586 default:
1587 unimplemented();
1588 #endif
1590 xcurs++;
1595 // --------------------------------------------------------------------------------------------
1596 static void biosfn_write_char_only (car,page,attr,count)
1597 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1599 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1600 Bit16u nbcols,nbrows,address;
1601 Bit16u cursor,dummy;
1603 // Get the mode
1604 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1605 line=find_vga_entry(mode);
1606 if(line==0xFF)return;
1608 // Get the cursor pos for the page
1609 biosfn_get_cursor_pos(page,&dummy,&cursor);
1610 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1612 // Get the dimensions
1613 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1614 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1616 if(vga_modes[line].class==TEXT)
1618 // Compute the address
1619 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1621 while(count-->0)
1622 {write_byte(vga_modes[line].sstart,address,car);
1623 address+=2;
1626 else
1628 // FIXME gfx mode not complete
1629 cheight=vga_modes[line].cheight;
1630 bpp=vga_modes[line].pixbits;
1631 while((count-->0) && (xcurs<nbcols))
1633 switch(vga_modes[line].memmodel)
1635 case PLANAR4:
1636 case PLANAR1:
1637 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1638 break;
1639 case CGA:
1640 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1641 break;
1642 case LINEAR8:
1643 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1644 break;
1645 #ifdef DEBUG
1646 default:
1647 unimplemented();
1648 #endif
1650 xcurs++;
1655 // --------------------------------------------------------------------------------------------
1656 ASM_START
1657 biosfn_group_0B:
1658 cmp bh, #0x00
1659 je biosfn_set_border_color
1660 cmp bh, #0x01
1661 je biosfn_set_palette
1662 #ifdef DEBUG
1663 call _unknown
1664 #endif
1666 biosfn_set_border_color:
1667 push ax
1668 push bx
1669 push cx
1670 push dx
1671 mov dx, # VGAREG_ACTL_RESET
1672 in al, dx
1673 mov dx, # VGAREG_ACTL_ADDRESS
1674 mov al, #0x00
1675 out dx, al
1676 mov al, bl
1677 and al, #0x0f
1678 test al, #0x08
1679 jz set_low_border
1680 add al, #0x08
1681 set_low_border:
1682 out dx, al
1683 mov cl, #0x01
1684 and bl, #0x10
1685 set_intensity_loop:
1686 mov dx, # VGAREG_ACTL_ADDRESS
1687 mov al, cl
1688 out dx, al
1689 mov dx, # VGAREG_ACTL_READ_DATA
1690 in al, dx
1691 and al, #0xef
1692 or al, bl
1693 mov dx, # VGAREG_ACTL_ADDRESS
1694 out dx, al
1695 inc cl
1696 cmp cl, #0x04
1697 jne set_intensity_loop
1698 mov al, #0x20
1699 out dx, al
1700 pop dx
1701 pop cx
1702 pop bx
1703 pop ax
1705 biosfn_set_palette:
1706 push ax
1707 push bx
1708 push cx
1709 push dx
1710 mov dx, # VGAREG_ACTL_RESET
1711 in al, dx
1712 mov cl, #0x01
1713 and bl, #0x01
1714 set_cga_palette_loop:
1715 mov dx, # VGAREG_ACTL_ADDRESS
1716 mov al, cl
1717 out dx, al
1718 mov dx, # VGAREG_ACTL_READ_DATA
1719 in al, dx
1720 and al, #0xfe
1721 or al, bl
1722 mov dx, # VGAREG_ACTL_ADDRESS
1723 out dx, al
1724 inc cl
1725 cmp cl, #0x04
1726 jne set_cga_palette_loop
1727 mov al, #0x20
1728 out dx, al
1729 pop dx
1730 pop cx
1731 pop bx
1732 pop ax
1734 ASM_END
1736 // --------------------------------------------------------------------------------------------
1737 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1739 Bit8u mode,line,mask,attr,data;
1740 Bit16u addr;
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 = 0x80 >> (CX & 0x07);
1754 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1755 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1756 data = read_byte(0xa000,addr);
1757 if (AL & 0x80)
1759 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1761 write_byte(0xa000,addr,AL);
1762 ASM_START
1763 mov dx, # VGAREG_GRDC_ADDRESS
1764 mov ax, #0xff08
1765 out dx, ax
1766 mov ax, #0x0005
1767 out dx, ax
1768 mov ax, #0x0003
1769 out dx, ax
1770 ASM_END
1771 break;
1772 case CGA:
1773 if(vga_modes[line].pixbits==2)
1775 addr=(CX>>2)+(DX>>1)*80;
1777 else
1779 addr=(CX>>3)+(DX>>1)*80;
1781 if (DX & 1) addr += 0x2000;
1782 data = read_byte(0xb800,addr);
1783 if(vga_modes[line].pixbits==2)
1785 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1786 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1788 else
1790 attr = (AL & 0x01) << (7 - (CX & 0x07));
1791 mask = 0x01 << (7 - (CX & 0x07));
1793 if (AL & 0x80)
1795 data ^= attr;
1797 else
1799 data &= ~mask;
1800 data |= attr;
1802 write_byte(0xb800,addr,data);
1803 break;
1804 case LINEAR8:
1805 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1806 write_byte(0xa000,addr,AL);
1807 break;
1808 #ifdef DEBUG
1809 default:
1810 unimplemented();
1811 #endif
1815 // --------------------------------------------------------------------------------------------
1816 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1818 Bit8u mode,line,mask,attr,data,i;
1819 Bit16u addr;
1820 Bit16u ss=get_SS();
1822 // Get the mode
1823 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1824 line=find_vga_entry(mode);
1825 if(line==0xFF)return;
1826 if(vga_modes[line].class==TEXT)return;
1828 switch(vga_modes[line].memmodel)
1830 case PLANAR4:
1831 case PLANAR1:
1832 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1833 mask = 0x80 >> (CX & 0x07);
1834 attr = 0x00;
1835 for(i=0;i<4;i++)
1837 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1838 data = read_byte(0xa000,addr) & mask;
1839 if (data > 0) attr |= (0x01 << i);
1841 break;
1842 case CGA:
1843 addr=(CX>>2)+(DX>>1)*80;
1844 if (DX & 1) addr += 0x2000;
1845 data = read_byte(0xb800,addr);
1846 if(vga_modes[line].pixbits==2)
1848 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1850 else
1852 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1854 break;
1855 case LINEAR8:
1856 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1857 attr=read_byte(0xa000,addr);
1858 break;
1859 default:
1860 #ifdef DEBUG
1861 unimplemented();
1862 #endif
1863 attr = 0;
1865 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1868 // --------------------------------------------------------------------------------------------
1869 static void biosfn_write_teletype (car, page, attr, flag)
1870 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1871 {// flag = WITH_ATTR / NO_ATTR
1873 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1874 Bit16u nbcols,nbrows,address;
1875 Bit16u cursor,dummy;
1877 // special case if page is 0xff, use current page
1878 if(page==0xff)
1879 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1881 // Get the mode
1882 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1883 line=find_vga_entry(mode);
1884 if(line==0xFF)return;
1886 // Get the cursor pos for the page
1887 biosfn_get_cursor_pos(page,&dummy,&cursor);
1888 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1890 // Get the dimensions
1891 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1892 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1894 switch(car)
1896 case 7:
1897 //FIXME should beep
1898 break;
1900 case 8:
1901 if(xcurs>0)xcurs--;
1902 break;
1904 case '\r':
1905 xcurs=0;
1906 break;
1908 case '\n':
1909 xcurs=0;
1910 ycurs++;
1911 break;
1913 case '\t':
1916 biosfn_write_teletype(' ',page,attr,flag);
1917 biosfn_get_cursor_pos(page,&dummy,&cursor);
1918 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1919 }while(xcurs%8==0);
1920 break;
1922 default:
1924 if(vga_modes[line].class==TEXT)
1926 // Compute the address
1927 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1929 // Write the char
1930 write_byte(vga_modes[line].sstart,address,car);
1932 if(flag==WITH_ATTR)
1933 write_byte(vga_modes[line].sstart,address+1,attr);
1935 else
1937 // FIXME gfx mode not complete
1938 cheight=vga_modes[line].cheight;
1939 bpp=vga_modes[line].pixbits;
1940 switch(vga_modes[line].memmodel)
1942 case PLANAR4:
1943 case PLANAR1:
1944 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1945 break;
1946 case CGA:
1947 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1948 break;
1949 case LINEAR8:
1950 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1951 break;
1952 #ifdef DEBUG
1953 default:
1954 unimplemented();
1955 #endif
1958 xcurs++;
1961 // Do we need to wrap ?
1962 if(xcurs==nbcols)
1963 {xcurs=0;
1964 ycurs++;
1967 // Do we need to scroll ?
1968 if(ycurs==nbrows)
1970 if(vga_modes[line].class==TEXT)
1972 biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1974 else
1976 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1978 ycurs-=1;
1981 // Set the cursor for the page
1982 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1983 biosfn_set_cursor_pos(page,cursor);
1986 // --------------------------------------------------------------------------------------------
1987 ASM_START
1988 biosfn_get_video_mode:
1989 push ds
1990 mov ax, # BIOSMEM_SEG
1991 mov ds, ax
1992 push bx
1993 mov bx, # BIOSMEM_CURRENT_PAGE
1994 mov al, [bx]
1995 pop bx
1996 mov bh, al
1997 push bx
1998 mov bx, # BIOSMEM_VIDEO_CTL
1999 mov ah, [bx]
2000 and ah, #0x80
2001 mov bx, # BIOSMEM_CURRENT_MODE
2002 mov al, [bx]
2003 or al, ah
2004 mov bx, # BIOSMEM_NB_COLS
2005 mov ah, [bx]
2006 pop bx
2007 pop ds
2009 ASM_END
2011 // --------------------------------------------------------------------------------------------
2012 ASM_START
2013 biosfn_group_10:
2014 cmp al, #0x00
2015 jne int10_test_1001
2016 jmp biosfn_set_single_palette_reg
2017 int10_test_1001:
2018 cmp al, #0x01
2019 jne int10_test_1002
2020 jmp biosfn_set_overscan_border_color
2021 int10_test_1002:
2022 cmp al, #0x02
2023 jne int10_test_1003
2024 jmp biosfn_set_all_palette_reg
2025 int10_test_1003:
2026 cmp al, #0x03
2027 jne int10_test_1007
2028 jmp biosfn_toggle_intensity
2029 int10_test_1007:
2030 cmp al, #0x07
2031 jne int10_test_1008
2032 jmp biosfn_get_single_palette_reg
2033 int10_test_1008:
2034 cmp al, #0x08
2035 jne int10_test_1009
2036 jmp biosfn_read_overscan_border_color
2037 int10_test_1009:
2038 cmp al, #0x09
2039 jne int10_test_1010
2040 jmp biosfn_get_all_palette_reg
2041 int10_test_1010:
2042 cmp al, #0x10
2043 jne int10_test_1012
2044 jmp biosfn_set_single_dac_reg
2045 int10_test_1012:
2046 cmp al, #0x12
2047 jne int10_test_1013
2048 jmp biosfn_set_all_dac_reg
2049 int10_test_1013:
2050 cmp al, #0x13
2051 jne int10_test_1015
2052 jmp biosfn_select_video_dac_color_page
2053 int10_test_1015:
2054 cmp al, #0x15
2055 jne int10_test_1017
2056 jmp biosfn_read_single_dac_reg
2057 int10_test_1017:
2058 cmp al, #0x17
2059 jne int10_test_1018
2060 jmp biosfn_read_all_dac_reg
2061 int10_test_1018:
2062 cmp al, #0x18
2063 jne int10_test_1019
2064 jmp biosfn_set_pel_mask
2065 int10_test_1019:
2066 cmp al, #0x19
2067 jne int10_test_101A
2068 jmp biosfn_read_pel_mask
2069 int10_test_101A:
2070 cmp al, #0x1a
2071 jne int10_group_10_unknown
2072 jmp biosfn_read_video_dac_state
2073 int10_group_10_unknown:
2074 #ifdef DEBUG
2075 call _unknown
2076 #endif
2079 biosfn_set_single_palette_reg:
2080 cmp bl, #0x14
2081 ja no_actl_reg1
2082 push ax
2083 push dx
2084 mov dx, # VGAREG_ACTL_RESET
2085 in al, dx
2086 mov dx, # VGAREG_ACTL_ADDRESS
2087 mov al, bl
2088 out dx, al
2089 mov al, bh
2090 out dx, al
2091 mov al, #0x20
2092 out dx, al
2093 pop dx
2094 pop ax
2095 no_actl_reg1:
2097 ASM_END
2099 // --------------------------------------------------------------------------------------------
2100 ASM_START
2101 biosfn_set_overscan_border_color:
2102 push bx
2103 mov bl, #0x11
2104 call biosfn_set_single_palette_reg
2105 pop bx
2107 ASM_END
2109 // --------------------------------------------------------------------------------------------
2110 ASM_START
2111 biosfn_set_all_palette_reg:
2112 push ax
2113 push bx
2114 push cx
2115 push dx
2116 mov bx, dx
2117 mov dx, # VGAREG_ACTL_RESET
2118 in al, dx
2119 mov cl, #0x00
2120 mov dx, # VGAREG_ACTL_ADDRESS
2121 set_palette_loop:
2122 mov al, cl
2123 out dx, al
2124 seg es
2125 mov al, [bx]
2126 out dx, al
2127 inc bx
2128 inc cl
2129 cmp cl, #0x10
2130 jne set_palette_loop
2131 mov al, #0x11
2132 out dx, al
2133 seg es
2134 mov al, [bx]
2135 out dx, al
2136 mov al, #0x20
2137 out dx, al
2138 pop dx
2139 pop cx
2140 pop bx
2141 pop ax
2143 ASM_END
2145 // --------------------------------------------------------------------------------------------
2146 ASM_START
2147 biosfn_toggle_intensity:
2148 push ax
2149 push bx
2150 push dx
2151 mov dx, # VGAREG_ACTL_RESET
2152 in al, dx
2153 mov dx, # VGAREG_ACTL_ADDRESS
2154 mov al, #0x10
2155 out dx, al
2156 mov dx, # VGAREG_ACTL_READ_DATA
2157 in al, dx
2158 and al, #0xf7
2159 and bl, #0x01
2160 shl bl, 3
2161 or al, bl
2162 mov dx, # VGAREG_ACTL_ADDRESS
2163 out dx, al
2164 mov al, #0x20
2165 out dx, al
2166 pop dx
2167 pop bx
2168 pop ax
2170 ASM_END
2172 // --------------------------------------------------------------------------------------------
2173 ASM_START
2174 biosfn_get_single_palette_reg:
2175 cmp bl, #0x14
2176 ja no_actl_reg2
2177 push ax
2178 push dx
2179 mov dx, # VGAREG_ACTL_RESET
2180 in al, dx
2181 mov dx, # VGAREG_ACTL_ADDRESS
2182 mov al, bl
2183 out dx, al
2184 mov dx, # VGAREG_ACTL_READ_DATA
2185 in al, dx
2186 mov bh, al
2187 mov dx, # VGAREG_ACTL_RESET
2188 in al, dx
2189 mov dx, # VGAREG_ACTL_ADDRESS
2190 mov al, #0x20
2191 out dx, al
2192 pop dx
2193 pop ax
2194 no_actl_reg2:
2196 ASM_END
2198 // --------------------------------------------------------------------------------------------
2199 ASM_START
2200 biosfn_read_overscan_border_color:
2201 push ax
2202 push bx
2203 mov bl, #0x11
2204 call biosfn_get_single_palette_reg
2205 mov al, bh
2206 pop bx
2207 mov bh, al
2208 pop ax
2210 ASM_END
2212 // --------------------------------------------------------------------------------------------
2213 ASM_START
2214 biosfn_get_all_palette_reg:
2215 push ax
2216 push bx
2217 push cx
2218 push dx
2219 mov bx, dx
2220 mov cl, #0x00
2221 get_palette_loop:
2222 mov dx, # VGAREG_ACTL_RESET
2223 in al, dx
2224 mov dx, # VGAREG_ACTL_ADDRESS
2225 mov al, cl
2226 out dx, al
2227 mov dx, # VGAREG_ACTL_READ_DATA
2228 in al, dx
2229 seg es
2230 mov [bx], al
2231 inc bx
2232 inc cl
2233 cmp cl, #0x10
2234 jne get_palette_loop
2235 mov dx, # VGAREG_ACTL_RESET
2236 in al, dx
2237 mov dx, # VGAREG_ACTL_ADDRESS
2238 mov al, #0x11
2239 out dx, al
2240 mov dx, # VGAREG_ACTL_READ_DATA
2241 in al, dx
2242 seg es
2243 mov [bx], al
2244 mov dx, # VGAREG_ACTL_RESET
2245 in al, dx
2246 mov dx, # VGAREG_ACTL_ADDRESS
2247 mov al, #0x20
2248 out dx, al
2249 pop dx
2250 pop cx
2251 pop bx
2252 pop ax
2254 ASM_END
2256 // --------------------------------------------------------------------------------------------
2257 ASM_START
2258 biosfn_set_single_dac_reg:
2259 push ax
2260 push dx
2261 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2262 mov al, bl
2263 out dx, al
2264 mov dx, # VGAREG_DAC_DATA
2265 pop ax
2266 push ax
2267 mov al, ah
2268 out dx, al
2269 mov al, ch
2270 out dx, al
2271 mov al, cl
2272 out dx, al
2273 pop dx
2274 pop ax
2276 ASM_END
2278 // --------------------------------------------------------------------------------------------
2279 ASM_START
2280 biosfn_set_all_dac_reg:
2281 push ax
2282 push bx
2283 push cx
2284 push dx
2285 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2286 mov al, bl
2287 out dx, al
2288 pop dx
2289 push dx
2290 mov bx, dx
2291 mov dx, # VGAREG_DAC_DATA
2292 set_dac_loop:
2293 seg es
2294 mov al, [bx]
2295 out dx, al
2296 inc bx
2297 seg es
2298 mov al, [bx]
2299 out dx, al
2300 inc bx
2301 seg es
2302 mov al, [bx]
2303 out dx, al
2304 inc bx
2305 dec cx
2306 jnz set_dac_loop
2307 pop dx
2308 pop cx
2309 pop bx
2310 pop ax
2312 ASM_END
2314 // --------------------------------------------------------------------------------------------
2315 ASM_START
2316 biosfn_select_video_dac_color_page:
2317 push ax
2318 push bx
2319 push dx
2320 mov dx, # VGAREG_ACTL_RESET
2321 in al, dx
2322 mov dx, # VGAREG_ACTL_ADDRESS
2323 mov al, #0x10
2324 out dx, al
2325 mov dx, # VGAREG_ACTL_READ_DATA
2326 in al, dx
2327 and bl, #0x01
2328 jnz set_dac_page
2329 and al, #0x7f
2330 shl bh, 7
2331 or al, bh
2332 mov dx, # VGAREG_ACTL_ADDRESS
2333 out dx, al
2334 jmp set_actl_normal
2335 set_dac_page:
2336 push ax
2337 mov dx, # VGAREG_ACTL_RESET
2338 in al, dx
2339 mov dx, # VGAREG_ACTL_ADDRESS
2340 mov al, #0x14
2341 out dx, al
2342 pop ax
2343 and al, #0x80
2344 jnz set_dac_16_page
2345 shl bh, 2
2346 set_dac_16_page:
2347 and bh, #0x0f
2348 mov al, bh
2349 out dx, al
2350 set_actl_normal:
2351 mov al, #0x20
2352 out dx, al
2353 pop dx
2354 pop bx
2355 pop ax
2357 ASM_END
2359 // --------------------------------------------------------------------------------------------
2360 ASM_START
2361 biosfn_read_single_dac_reg:
2362 push ax
2363 push dx
2364 mov dx, # VGAREG_DAC_READ_ADDRESS
2365 mov al, bl
2366 out dx, al
2367 pop ax
2368 mov ah, al
2369 mov dx, # VGAREG_DAC_DATA
2370 in al, dx
2371 xchg al, ah
2372 push ax
2373 in al, dx
2374 mov ch, al
2375 in al, dx
2376 mov cl, al
2377 pop dx
2378 pop ax
2380 ASM_END
2382 // --------------------------------------------------------------------------------------------
2383 ASM_START
2384 biosfn_read_all_dac_reg:
2385 push ax
2386 push bx
2387 push cx
2388 push dx
2389 mov dx, # VGAREG_DAC_READ_ADDRESS
2390 mov al, bl
2391 out dx, al
2392 pop dx
2393 push dx
2394 mov bx, dx
2395 mov dx, # VGAREG_DAC_DATA
2396 read_dac_loop:
2397 in al, dx
2398 seg es
2399 mov [bx], al
2400 inc bx
2401 in al, dx
2402 seg es
2403 mov [bx], al
2404 inc bx
2405 in al, dx
2406 seg es
2407 mov [bx], al
2408 inc bx
2409 dec cx
2410 jnz read_dac_loop
2411 pop dx
2412 pop cx
2413 pop bx
2414 pop ax
2416 ASM_END
2418 // --------------------------------------------------------------------------------------------
2419 ASM_START
2420 biosfn_set_pel_mask:
2421 push ax
2422 push dx
2423 mov dx, # VGAREG_PEL_MASK
2424 mov al, bl
2425 out dx, al
2426 pop dx
2427 pop ax
2429 ASM_END
2431 // --------------------------------------------------------------------------------------------
2432 ASM_START
2433 biosfn_read_pel_mask:
2434 push ax
2435 push dx
2436 mov dx, # VGAREG_PEL_MASK
2437 in al, dx
2438 mov bl, al
2439 pop dx
2440 pop ax
2442 ASM_END
2444 // --------------------------------------------------------------------------------------------
2445 ASM_START
2446 biosfn_read_video_dac_state:
2447 push ax
2448 push dx
2449 mov dx, # VGAREG_ACTL_RESET
2450 in al, dx
2451 mov dx, # VGAREG_ACTL_ADDRESS
2452 mov al, #0x10
2453 out dx, al
2454 mov dx, # VGAREG_ACTL_READ_DATA
2455 in al, dx
2456 mov bl, al
2457 shr bl, 7
2458 mov dx, # VGAREG_ACTL_RESET
2459 in al, dx
2460 mov dx, # VGAREG_ACTL_ADDRESS
2461 mov al, #0x14
2462 out dx, al
2463 mov dx, # VGAREG_ACTL_READ_DATA
2464 in al, dx
2465 mov bh, al
2466 and bh, #0x0f
2467 test bl, #0x01
2468 jnz get_dac_16_page
2469 shr bh, 2
2470 get_dac_16_page:
2471 mov dx, # VGAREG_ACTL_RESET
2472 in al, dx
2473 mov dx, # VGAREG_ACTL_ADDRESS
2474 mov al, #0x20
2475 out dx, al
2476 pop dx
2477 pop ax
2479 ASM_END
2481 // --------------------------------------------------------------------------------------------
2482 static void biosfn_perform_gray_scale_summing (start,count)
2483 Bit16u start;Bit16u count;
2484 {Bit8u r,g,b;
2485 Bit16u i;
2486 Bit16u index;
2488 inb(VGAREG_ACTL_RESET);
2489 outb(VGAREG_ACTL_ADDRESS,0x00);
2491 for( index = 0; index < count; index++ )
2493 // set read address and switch to read mode
2494 outb(VGAREG_DAC_READ_ADDRESS,start);
2495 // get 6-bit wide RGB data values
2496 r=inb( VGAREG_DAC_DATA );
2497 g=inb( VGAREG_DAC_DATA );
2498 b=inb( VGAREG_DAC_DATA );
2500 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2501 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2503 if(i>0x3f)i=0x3f;
2505 // set write address and switch to write mode
2506 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2507 // write new intensity value
2508 outb( VGAREG_DAC_DATA, i&0xff );
2509 outb( VGAREG_DAC_DATA, i&0xff );
2510 outb( VGAREG_DAC_DATA, i&0xff );
2511 start++;
2513 inb(VGAREG_ACTL_RESET);
2514 outb(VGAREG_ACTL_ADDRESS,0x20);
2517 // --------------------------------------------------------------------------------------------
2518 static void get_font_access()
2520 ASM_START
2521 mov dx, # VGAREG_SEQU_ADDRESS
2522 mov ax, #0x0100
2523 out dx, ax
2524 mov ax, #0x0402
2525 out dx, ax
2526 mov ax, #0x0704
2527 out dx, ax
2528 mov ax, #0x0300
2529 out dx, ax
2530 mov dx, # VGAREG_GRDC_ADDRESS
2531 mov ax, #0x0204
2532 out dx, ax
2533 mov ax, #0x0005
2534 out dx, ax
2535 mov ax, #0x0406
2536 out dx, ax
2537 ASM_END
2540 static void release_font_access()
2542 ASM_START
2543 mov dx, # VGAREG_SEQU_ADDRESS
2544 mov ax, #0x0100
2545 out dx, ax
2546 mov ax, #0x0302
2547 out dx, ax
2548 mov ax, #0x0304
2549 out dx, ax
2550 mov ax, #0x0300
2551 out dx, ax
2552 mov dx, # VGAREG_READ_MISC_OUTPUT
2553 in al, dx
2554 and al, #0x01
2555 shl al, 2
2556 or al, #0x0a
2557 mov ah, al
2558 mov al, #0x06
2559 mov dx, # VGAREG_GRDC_ADDRESS
2560 out dx, ax
2561 mov ax, #0x0004
2562 out dx, ax
2563 mov ax, #0x1005
2564 out dx, ax
2565 ASM_END
2568 ASM_START
2569 idiv_u:
2570 xor dx,dx
2571 div bx
2573 ASM_END
2575 static void set_scan_lines(lines) Bit8u lines;
2577 Bit16u crtc_addr,cols,page,vde;
2578 Bit8u crtc_r9,ovl,rows;
2580 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2581 outb(crtc_addr, 0x09);
2582 crtc_r9 = inb(crtc_addr+1);
2583 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2584 outb(crtc_addr+1, crtc_r9);
2585 if(lines==8)
2587 biosfn_set_cursor_shape(0x06,0x07);
2589 else
2591 biosfn_set_cursor_shape(lines-4,lines-3);
2593 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2594 outb(crtc_addr, 0x12);
2595 vde = inb(crtc_addr+1);
2596 outb(crtc_addr, 0x07);
2597 ovl = inb(crtc_addr+1);
2598 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2599 rows = vde / lines;
2600 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2601 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2602 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2605 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;
2607 Bit16u blockaddr,dest,i,src;
2609 get_font_access();
2610 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2611 for(i=0;i<CX;i++)
2613 src = BP + i * BH;
2614 dest = blockaddr + (DX + i) * 32;
2615 memcpyb(0xA000, dest, ES, src, BH);
2617 release_font_access();
2618 if(AL>=0x10)
2620 set_scan_lines(BH);
2624 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2626 Bit16u blockaddr,dest,i,src;
2628 get_font_access();
2629 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2630 for(i=0;i<0x100;i++)
2632 src = i * 14;
2633 dest = blockaddr + i * 32;
2634 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2636 release_font_access();
2637 if(AL>=0x10)
2639 set_scan_lines(14);
2643 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2645 Bit16u blockaddr,dest,i,src;
2647 get_font_access();
2648 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2649 for(i=0;i<0x100;i++)
2651 src = i * 8;
2652 dest = blockaddr + i * 32;
2653 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2655 release_font_access();
2656 if(AL>=0x10)
2658 set_scan_lines(8);
2662 // --------------------------------------------------------------------------------------------
2663 ASM_START
2664 biosfn_set_text_block_specifier:
2665 push ax
2666 push dx
2667 mov dx, # VGAREG_SEQU_ADDRESS
2668 mov ah, bl
2669 mov al, #0x03
2670 out dx, ax
2671 pop dx
2672 pop ax
2674 ASM_END
2676 // --------------------------------------------------------------------------------------------
2677 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2679 Bit16u blockaddr,dest,i,src;
2681 get_font_access();
2682 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2683 for(i=0;i<0x100;i++)
2685 src = i * 16;
2686 dest = blockaddr + i * 32;
2687 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2689 release_font_access();
2690 if(AL>=0x10)
2692 set_scan_lines(16);
2696 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2698 #ifdef DEBUG
2699 unimplemented();
2700 #endif
2702 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2704 #ifdef DEBUG
2705 unimplemented();
2706 #endif
2708 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2710 #ifdef DEBUG
2711 unimplemented();
2712 #endif
2714 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2716 #ifdef DEBUG
2717 unimplemented();
2718 #endif
2720 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2722 #ifdef DEBUG
2723 unimplemented();
2724 #endif
2726 // --------------------------------------------------------------------------------------------
2727 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2728 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2729 {Bit16u ss=get_SS();
2731 switch(BH)
2732 {case 0x00:
2733 write_word(ss,ES,read_word(0x00,0x1f*4));
2734 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2735 break;
2736 case 0x01:
2737 write_word(ss,ES,read_word(0x00,0x43*4));
2738 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2739 break;
2740 case 0x02:
2741 write_word(ss,ES,0xC000);
2742 write_word(ss,BP,vgafont14);
2743 break;
2744 case 0x03:
2745 write_word(ss,ES,0xC000);
2746 write_word(ss,BP,vgafont8);
2747 break;
2748 case 0x04:
2749 write_word(ss,ES,0xC000);
2750 write_word(ss,BP,vgafont8+128*8);
2751 break;
2752 case 0x05:
2753 write_word(ss,ES,0xC000);
2754 write_word(ss,BP,vgafont14alt);
2755 break;
2756 case 0x06:
2757 write_word(ss,ES,0xC000);
2758 write_word(ss,BP,vgafont16);
2759 break;
2760 case 0x07:
2761 write_word(ss,ES,0xC000);
2762 write_word(ss,BP,vgafont16alt);
2763 break;
2764 default:
2765 #ifdef DEBUG
2766 printf("Get font info BH(%02x) was discarded\n",BH);
2767 #endif
2768 return;
2770 // Set byte/char of on screen font
2771 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2773 // Set Highest char row
2774 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2777 // --------------------------------------------------------------------------------------------
2778 ASM_START
2779 biosfn_get_ega_info:
2780 push ds
2781 push ax
2782 mov ax, # BIOSMEM_SEG
2783 mov ds, ax
2784 xor ch, ch
2785 mov bx, # BIOSMEM_SWITCHES
2786 mov cl, [bx]
2787 and cl, #0x0f
2788 mov bx, # BIOSMEM_CRTC_ADDRESS
2789 mov ax, [bx]
2790 mov bx, #0x0003
2791 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2792 jne mode_ega_color
2793 mov bh, #0x01
2794 mode_ega_color:
2795 pop ax
2796 pop ds
2798 ASM_END
2800 // --------------------------------------------------------------------------------------------
2801 static void biosfn_alternate_prtsc()
2803 #ifdef DEBUG
2804 unimplemented();
2805 #endif
2808 // --------------------------------------------------------------------------------------------
2809 ASM_START
2810 biosfn_select_vert_res:
2812 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2814 push ds
2815 push bx
2816 push dx
2817 mov dl, al
2818 mov ax, # BIOSMEM_SEG
2819 mov ds, ax
2820 mov bx, # BIOSMEM_MODESET_CTL
2821 mov al, [bx]
2822 mov bx, # BIOSMEM_SWITCHES
2823 mov ah, [bx]
2824 cmp dl, #0x01
2825 je vert_res_350
2826 jb vert_res_200
2827 cmp dl, #0x02
2828 je vert_res_400
2829 #ifdef DEBUG
2830 mov al, dl
2831 xor ah, ah
2832 push ax
2833 mov bx, #msg_vert_res
2834 push bx
2835 call _printf
2836 add sp, #4
2837 #endif
2838 jmp set_retcode
2839 vert_res_400:
2841 ; reset modeset ctl bit 7 and set bit 4
2842 ; set switches bit 3-0 to 0x09
2844 and al, #0x7f
2845 or al, #0x10
2846 and ah, #0xf0
2847 or ah, #0x09
2848 jnz set_vert_res
2849 vert_res_350:
2851 ; reset modeset ctl bit 7 and bit 4
2852 ; set switches bit 3-0 to 0x09
2854 and al, #0x6f
2855 and ah, #0xf0
2856 or ah, #0x09
2857 jnz set_vert_res
2858 vert_res_200:
2860 ; set modeset ctl bit 7 and reset bit 4
2861 ; set switches bit 3-0 to 0x08
2863 and al, #0xef
2864 or al, #0x80
2865 and ah, #0xf0
2866 or ah, #0x08
2867 set_vert_res:
2868 mov bx, # BIOSMEM_MODESET_CTL
2869 mov [bx], al
2870 mov bx, # BIOSMEM_SWITCHES
2871 mov [bx], ah
2872 set_retcode:
2873 mov ax, #0x1212
2874 pop dx
2875 pop bx
2876 pop ds
2879 #ifdef DEBUG
2880 msg_vert_res:
2881 .ascii "Select vert res (%02x) was discarded"
2882 .byte 0x0d,0x0a,0x00
2883 #endif
2886 biosfn_enable_default_palette_loading:
2887 push ds
2888 push bx
2889 push dx
2890 mov dl, al
2891 and dl, #0x01
2892 shl dl, 3
2893 mov ax, # BIOSMEM_SEG
2894 mov ds, ax
2895 mov bx, # BIOSMEM_MODESET_CTL
2896 mov al, [bx]
2897 and al, #0xf7
2898 or al, dl
2899 mov [bx], al
2900 mov ax, #0x1212
2901 pop dx
2902 pop bx
2903 pop ds
2907 biosfn_enable_video_addressing:
2908 push bx
2909 push dx
2910 mov bl, al
2911 and bl, #0x01
2912 xor bl, #0x01
2913 shl bl, 1
2914 mov dx, # VGAREG_READ_MISC_OUTPUT
2915 in al, dx
2916 and al, #0xfd
2917 or al, bl
2918 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2919 out dx, al
2920 mov ax, #0x1212
2921 pop dx
2922 pop bx
2926 biosfn_enable_grayscale_summing:
2927 push ds
2928 push bx
2929 push dx
2930 mov dl, al
2931 and dl, #0x01
2932 xor dl, #0x01
2933 shl dl, 1
2934 mov ax, # BIOSMEM_SEG
2935 mov ds, ax
2936 mov bx, # BIOSMEM_MODESET_CTL
2937 mov al, [bx]
2938 and al, #0xfd
2939 or al, dl
2940 mov [bx], al
2941 mov ax, #0x1212
2942 pop dx
2943 pop bx
2944 pop ds
2948 biosfn_enable_cursor_emulation:
2949 push ds
2950 push bx
2951 push dx
2952 mov dl, al
2953 and dl, #0x01
2954 xor dl, #0x01
2955 mov ax, # BIOSMEM_SEG
2956 mov ds, ax
2957 mov bx, # BIOSMEM_MODESET_CTL
2958 mov al, [bx]
2959 and al, #0xfe
2960 or al, dl
2961 mov [bx], al
2962 mov ax, #0x1212
2963 pop dx
2964 pop bx
2965 pop ds
2967 ASM_END
2969 // --------------------------------------------------------------------------------------------
2970 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2972 #ifdef DEBUG
2973 unimplemented();
2974 #endif
2976 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2978 #ifdef DEBUG
2979 unimplemented();
2980 #endif
2983 // --------------------------------------------------------------------------------------------
2984 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2985 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2987 Bit16u newcurs,oldcurs,dummy;
2988 Bit8u car,carattr;
2990 // Read curs info for the page
2991 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2993 // if row=0xff special case : use current cursor position
2994 if(row==0xff)
2995 {col=oldcurs&0x00ff;
2996 row=(oldcurs&0xff00)>>8;
2999 newcurs=row; newcurs<<=8; newcurs+=col;
3000 biosfn_set_cursor_pos(page,newcurs);
3002 while(count--!=0)
3004 car=read_byte(seg,offset++);
3005 if((flag&0x02)!=0)
3006 attr=read_byte(seg,offset++);
3008 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3011 // Set back curs pos
3012 if((flag&0x01)==0)
3013 biosfn_set_cursor_pos(page,oldcurs);
3016 // --------------------------------------------------------------------------------------------
3017 ASM_START
3018 biosfn_group_1A:
3019 cmp al, #0x00
3020 je biosfn_read_display_code
3021 cmp al, #0x01
3022 je biosfn_set_display_code
3023 #ifdef DEBUG
3024 call _unknown
3025 #endif
3027 biosfn_read_display_code:
3028 push ds
3029 push ax
3030 mov ax, # BIOSMEM_SEG
3031 mov ds, ax
3032 mov bx, # BIOSMEM_DCC_INDEX
3033 mov al, [bx]
3034 mov bl, al
3035 xor bh, bh
3036 pop ax
3037 mov al, ah
3038 pop ds
3040 biosfn_set_display_code:
3041 push ds
3042 push ax
3043 push bx
3044 mov ax, # BIOSMEM_SEG
3045 mov ds, ax
3046 mov ax, bx
3047 mov bx, # BIOSMEM_DCC_INDEX
3048 mov [bx], al
3049 #ifdef DEBUG
3050 mov al, ah
3051 xor ah, ah
3052 push ax
3053 mov bx, #msg_alt_dcc
3054 push bx
3055 call _printf
3056 add sp, #4
3057 #endif
3058 pop bx
3059 pop ax
3060 mov al, ah
3061 pop ds
3064 #ifdef DEBUG
3065 msg_alt_dcc:
3066 .ascii "Alternate Display code (%02x) was discarded"
3067 .byte 0x0d,0x0a,0x00
3068 #endif
3069 ASM_END
3071 // --------------------------------------------------------------------------------------------
3072 static void biosfn_read_state_info (BX,ES,DI)
3073 Bit16u BX;Bit16u ES;Bit16u DI;
3075 // Address of static functionality table
3076 write_word(ES,DI+0x00,&static_functionality);
3077 write_word(ES,DI+0x02,0xC000);
3079 // Hard coded copy from BIOS area. Should it be cleaner ?
3080 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3081 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3083 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3084 write_byte(ES,DI+0x26,0);
3085 write_byte(ES,DI+0x27,16);
3086 write_byte(ES,DI+0x28,0);
3087 write_byte(ES,DI+0x29,8);
3088 write_byte(ES,DI+0x2a,2);
3089 write_byte(ES,DI+0x2b,0);
3090 write_byte(ES,DI+0x2c,0);
3091 write_byte(ES,DI+0x31,3);
3092 write_byte(ES,DI+0x32,0);
3094 memsetb(ES,DI+0x33,0,13);
3097 // --------------------------------------------------------------------------------------------
3098 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3100 #ifdef DEBUG
3101 unimplemented();
3102 #endif
3104 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3106 #ifdef DEBUG
3107 unimplemented();
3108 #endif
3110 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3112 #ifdef DEBUG
3113 unimplemented();
3114 #endif
3117 // ============================================================================================
3119 // Video Utils
3121 // ============================================================================================
3123 // --------------------------------------------------------------------------------------------
3124 static Bit8u find_vga_entry(mode)
3125 Bit8u mode;
3127 Bit8u i,line=0xFF;
3128 for(i=0;i<=MODE_MAX;i++)
3129 if(vga_modes[i].svgamode==mode)
3130 {line=i;
3131 break;
3133 return line;
3136 /* =========================================================== */
3138 * Misc Utils
3140 /* =========================================================== */
3142 // --------------------------------------------------------------------------------------------
3143 static void memsetb(seg,offset,value,count)
3144 Bit16u seg;
3145 Bit16u offset;
3146 Bit16u value;
3147 Bit16u count;
3149 ASM_START
3150 push bp
3151 mov bp, sp
3153 push ax
3154 push cx
3155 push es
3156 push di
3158 mov cx, 10[bp] ; count
3159 cmp cx, #0x00
3160 je memsetb_end
3161 mov ax, 4[bp] ; segment
3162 mov es, ax
3163 mov ax, 6[bp] ; offset
3164 mov di, ax
3165 mov al, 8[bp] ; value
3168 stosb
3170 memsetb_end:
3171 pop di
3172 pop es
3173 pop cx
3174 pop ax
3176 pop bp
3177 ASM_END
3180 // --------------------------------------------------------------------------------------------
3181 static void memsetw(seg,offset,value,count)
3182 Bit16u seg;
3183 Bit16u offset;
3184 Bit16u value;
3185 Bit16u count;
3187 ASM_START
3188 push bp
3189 mov bp, sp
3191 push ax
3192 push cx
3193 push es
3194 push di
3196 mov cx, 10[bp] ; count
3197 cmp cx, #0x00
3198 je memsetw_end
3199 mov ax, 4[bp] ; segment
3200 mov es, ax
3201 mov ax, 6[bp] ; offset
3202 mov di, ax
3203 mov ax, 8[bp] ; value
3206 stosw
3208 memsetw_end:
3209 pop di
3210 pop es
3211 pop cx
3212 pop ax
3214 pop bp
3215 ASM_END
3218 // --------------------------------------------------------------------------------------------
3219 static void memcpyb(dseg,doffset,sseg,soffset,count)
3220 Bit16u dseg;
3221 Bit16u doffset;
3222 Bit16u sseg;
3223 Bit16u soffset;
3224 Bit16u count;
3226 ASM_START
3227 push bp
3228 mov bp, sp
3230 push ax
3231 push cx
3232 push es
3233 push di
3234 push ds
3235 push si
3237 mov cx, 12[bp] ; count
3238 cmp cx, #0x0000
3239 je memcpyb_end
3240 mov ax, 4[bp] ; dsegment
3241 mov es, ax
3242 mov ax, 6[bp] ; doffset
3243 mov di, ax
3244 mov ax, 8[bp] ; ssegment
3245 mov ds, ax
3246 mov ax, 10[bp] ; soffset
3247 mov si, ax
3250 movsb
3252 memcpyb_end:
3253 pop si
3254 pop ds
3255 pop di
3256 pop es
3257 pop cx
3258 pop ax
3260 pop bp
3261 ASM_END
3264 // --------------------------------------------------------------------------------------------
3265 static void memcpyw(dseg,doffset,sseg,soffset,count)
3266 Bit16u dseg;
3267 Bit16u doffset;
3268 Bit16u sseg;
3269 Bit16u soffset;
3270 Bit16u count;
3272 ASM_START
3273 push bp
3274 mov bp, sp
3276 push ax
3277 push cx
3278 push es
3279 push di
3280 push ds
3281 push si
3283 mov cx, 12[bp] ; count
3284 cmp cx, #0x0000
3285 je memcpyw_end
3286 mov ax, 4[bp] ; dsegment
3287 mov es, ax
3288 mov ax, 6[bp] ; doffset
3289 mov di, ax
3290 mov ax, 8[bp] ; ssegment
3291 mov ds, ax
3292 mov ax, 10[bp] ; soffset
3293 mov si, ax
3296 movsw
3298 memcpyw_end:
3299 pop si
3300 pop ds
3301 pop di
3302 pop es
3303 pop cx
3304 pop ax
3306 pop bp
3307 ASM_END
3310 /* =========================================================== */
3312 * These functions where ripped from Kevin's rombios.c
3314 /* =========================================================== */
3316 // --------------------------------------------------------------------------------------------
3317 static Bit8u
3318 read_byte(seg, offset)
3319 Bit16u seg;
3320 Bit16u offset;
3322 ASM_START
3323 push bp
3324 mov bp, sp
3326 push bx
3327 push ds
3328 mov ax, 4[bp] ; segment
3329 mov ds, ax
3330 mov bx, 6[bp] ; offset
3331 mov al, [bx]
3332 ;; al = return value (byte)
3333 pop ds
3334 pop bx
3336 pop bp
3337 ASM_END
3340 // --------------------------------------------------------------------------------------------
3341 static Bit16u
3342 read_word(seg, offset)
3343 Bit16u seg;
3344 Bit16u offset;
3346 ASM_START
3347 push bp
3348 mov bp, sp
3350 push bx
3351 push ds
3352 mov ax, 4[bp] ; segment
3353 mov ds, ax
3354 mov bx, 6[bp] ; offset
3355 mov ax, [bx]
3356 ;; ax = return value (word)
3357 pop ds
3358 pop bx
3360 pop bp
3361 ASM_END
3364 // --------------------------------------------------------------------------------------------
3365 static void
3366 write_byte(seg, offset, data)
3367 Bit16u seg;
3368 Bit16u offset;
3369 Bit8u data;
3371 ASM_START
3372 push bp
3373 mov bp, sp
3375 push ax
3376 push bx
3377 push ds
3378 mov ax, 4[bp] ; segment
3379 mov ds, ax
3380 mov bx, 6[bp] ; offset
3381 mov al, 8[bp] ; data byte
3382 mov [bx], al ; write data byte
3383 pop ds
3384 pop bx
3385 pop ax
3387 pop bp
3388 ASM_END
3391 // --------------------------------------------------------------------------------------------
3392 static void
3393 write_word(seg, offset, data)
3394 Bit16u seg;
3395 Bit16u offset;
3396 Bit16u data;
3398 ASM_START
3399 push bp
3400 mov bp, sp
3402 push ax
3403 push bx
3404 push ds
3405 mov ax, 4[bp] ; segment
3406 mov ds, ax
3407 mov bx, 6[bp] ; offset
3408 mov ax, 8[bp] ; data word
3409 mov [bx], ax ; write data word
3410 pop ds
3411 pop bx
3412 pop ax
3414 pop bp
3415 ASM_END
3418 // --------------------------------------------------------------------------------------------
3419 Bit8u
3420 inb(port)
3421 Bit16u port;
3423 ASM_START
3424 push bp
3425 mov bp, sp
3427 push dx
3428 mov dx, 4[bp]
3429 in al, dx
3430 pop dx
3432 pop bp
3433 ASM_END
3436 Bit16u
3437 inw(port)
3438 Bit16u port;
3440 ASM_START
3441 push bp
3442 mov bp, sp
3444 push dx
3445 mov dx, 4[bp]
3446 in ax, dx
3447 pop dx
3449 pop bp
3450 ASM_END
3453 // --------------------------------------------------------------------------------------------
3454 void
3455 outb(port, val)
3456 Bit16u port;
3457 Bit8u val;
3459 ASM_START
3460 push bp
3461 mov bp, sp
3463 push ax
3464 push dx
3465 mov dx, 4[bp]
3466 mov al, 6[bp]
3467 out dx, al
3468 pop dx
3469 pop ax
3471 pop bp
3472 ASM_END
3475 // --------------------------------------------------------------------------------------------
3476 void
3477 outw(port, val)
3478 Bit16u port;
3479 Bit16u val;
3481 ASM_START
3482 push bp
3483 mov bp, sp
3485 push ax
3486 push dx
3487 mov dx, 4[bp]
3488 mov ax, 6[bp]
3489 out dx, ax
3490 pop dx
3491 pop ax
3493 pop bp
3494 ASM_END
3497 Bit16u get_SS()
3499 ASM_START
3500 mov ax, ss
3501 ASM_END
3504 #ifdef DEBUG
3505 void unimplemented()
3507 printf("--> Unimplemented\n");
3510 void unknown()
3512 printf("--> Unknown int10\n");
3514 #endif
3516 // --------------------------------------------------------------------------------------------
3517 void printf(s)
3518 Bit8u *s;
3520 Bit8u c, format_char;
3521 Boolean in_format;
3522 unsigned format_width, i;
3523 Bit16u *arg_ptr;
3524 Bit16u arg_seg, arg, digit, nibble, shift_count;
3526 arg_ptr = &s;
3527 arg_seg = get_SS();
3529 in_format = 0;
3530 format_width = 0;
3532 while (c = read_byte(0xc000, s)) {
3533 if ( c == '%' ) {
3534 in_format = 1;
3535 format_width = 0;
3537 else if (in_format) {
3538 if ( (c>='0') && (c<='9') ) {
3539 format_width = (format_width * 10) + (c - '0');
3541 else if (c == 'x') {
3542 arg_ptr++; // increment to next arg
3543 arg = read_word(arg_seg, arg_ptr);
3544 if (format_width == 0)
3545 format_width = 4;
3546 i = 0;
3547 digit = format_width - 1;
3548 for (i=0; i<format_width; i++) {
3549 nibble = (arg >> (4 * digit)) & 0x000f;
3550 if (nibble <= 9)
3551 outb(0x0500, nibble + '0');
3552 else
3553 outb(0x0500, (nibble - 10) + 'A');
3554 digit--;
3556 in_format = 0;
3558 //else if (c == 'd') {
3559 // in_format = 0;
3560 // }
3562 else {
3563 outb(0x0500, c);
3565 s ++;
3569 #ifdef VBE
3570 #include "vbe.c"
3571 #endif
3573 #ifdef CIRRUS
3574 #include "clext.c"
3575 #endif
3577 // --------------------------------------------------------------------------------------------
3579 ASM_START
3580 ;; DATA_SEG_DEFS_HERE
3581 ASM_END
3583 ASM_START
3584 .ascii "vgabios ends here"
3585 .byte 0x00
3586 vgabios_end:
3587 .byte 0xCB
3588 ;; BLOCK_STRINGS_BEGIN
3589 ASM_END