- cross compilation support added (patch from Alex Beregszaszi)
[vgabios.git] / vgabios.c
blob0931bb73d33a0838333b153ad5b5b83218c479c8
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 // Disable CRTC write protection
877 outw(crtc_addr,0x0011);
878 // Set CRTC regs
879 for(i=0;i<=CRTC_MAX_REG;i++)
880 {outb(crtc_addr,i);
881 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
884 // Set the misc register
885 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
887 // Enable video
888 outb(VGAREG_ACTL_ADDRESS,0x20);
889 inb(VGAREG_ACTL_RESET);
891 if(noclearmem==0x00)
893 if(vga_modes[line].class==TEXT)
895 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
897 else
899 if(mode<0x0d)
901 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
903 else
905 outb( VGAREG_SEQU_ADDRESS, 0x02 );
906 mmask = inb( VGAREG_SEQU_DATA );
907 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
908 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
909 outb( VGAREG_SEQU_DATA, mmask );
914 // Set the BIOS mem
915 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
916 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
917 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
918 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
919 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
920 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
921 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
922 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
923 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
925 // FIXME We nearly have the good tables. to be reworked
926 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
927 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
928 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
930 // FIXME
931 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
932 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
934 // Set cursor shape
935 if(vga_modes[line].class==TEXT)
937 biosfn_set_cursor_shape(0x06,0x07);
940 // Set cursor pos for page 0..7
941 for(i=0;i<8;i++)
942 biosfn_set_cursor_pos(i,0x0000);
944 // Set active page 0
945 biosfn_set_active_page(0x00);
947 // Write the fonts in memory
948 if(vga_modes[line].class==TEXT)
950 ASM_START
951 ;; copy and activate 8x16 font
952 mov ax, #0x1104
953 mov bl, #0x00
954 int #0x10
955 mov ax, #0x1103
956 mov bl, #0x00
957 int #0x10
958 ASM_END
961 // Set the ints 0x1F and 0x43
962 ASM_START
963 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
964 ASM_END
966 switch(cheight)
967 {case 8:
968 ASM_START
969 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
970 ASM_END
971 break;
972 case 14:
973 ASM_START
974 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
975 ASM_END
976 break;
977 case 16:
978 ASM_START
979 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
980 ASM_END
981 break;
985 // --------------------------------------------------------------------------------------------
986 static void biosfn_set_cursor_shape (CH,CL)
987 Bit8u CH;Bit8u CL;
988 {Bit16u cheight,curs,crtc_addr;
989 Bit8u modeset_ctl;
991 CH&=0x3f;
992 CL&=0x1f;
994 curs=(CH<<8)+CL;
995 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
997 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
998 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
999 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
1001 if(CL!=(CH+1))
1003 CH = ((CH+1) * cheight / 8) -1;
1005 else
1007 CH = ((CL+1) * cheight / 8) - 2;
1009 CL = ((CL+1) * cheight / 8) - 1;
1012 // CTRC regs 0x0a and 0x0b
1013 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1014 outb(crtc_addr,0x0a);
1015 outb(crtc_addr+1,CH);
1016 outb(crtc_addr,0x0b);
1017 outb(crtc_addr+1,CL);
1020 // --------------------------------------------------------------------------------------------
1021 static void biosfn_set_cursor_pos (page, cursor)
1022 Bit8u page;Bit16u cursor;
1024 Bit8u xcurs,ycurs,current;
1025 Bit16u nbcols,nbrows,address,crtc_addr;
1027 // Should not happen...
1028 if(page>7)return;
1030 // Bios cursor pos
1031 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1033 // Set the hardware cursor
1034 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1035 if(page==current)
1037 // Get the dimensions
1038 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1039 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1041 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1043 // Calculate the address knowing nbcols nbrows and page num
1044 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1046 // CRTC regs 0x0e and 0x0f
1047 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1048 outb(crtc_addr,0x0e);
1049 outb(crtc_addr+1,(address&0xff00)>>8);
1050 outb(crtc_addr,0x0f);
1051 outb(crtc_addr+1,address&0x00ff);
1055 // --------------------------------------------------------------------------------------------
1056 static void biosfn_get_cursor_pos (page,shape, pos)
1057 Bit8u page;Bit16u *shape;Bit16u *pos;
1059 Bit16u ss=get_SS();
1061 // Default
1062 write_word(ss, shape, 0);
1063 write_word(ss, pos, 0);
1065 if(page>7)return;
1066 // FIXME should handle VGA 14/16 lines
1067 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1068 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1071 // --------------------------------------------------------------------------------------------
1072 static void biosfn_set_active_page (page)
1073 Bit8u page;
1075 Bit16u cursor,dummy,crtc_addr;
1076 Bit16u nbcols,nbrows,address;
1077 Bit8u mode,line;
1079 if(page>7)return;
1081 // Get the mode
1082 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1083 line=find_vga_entry(mode);
1084 if(line==0xFF)return;
1086 // Get pos curs pos for the right page
1087 biosfn_get_cursor_pos(page,&dummy,&cursor);
1089 if(vga_modes[line].class==TEXT)
1091 // Get the dimensions
1092 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1093 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1095 // Calculate the address knowing nbcols nbrows and page num
1096 address=SCREEN_MEM_START(nbcols,nbrows,page);
1097 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1099 // Start address
1100 address=SCREEN_IO_START(nbcols,nbrows,page);
1102 else
1104 address = page*vga_modes[line].slength;
1107 // CRTC regs 0x0c and 0x0d
1108 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1109 outb(crtc_addr,0x0c);
1110 outb(crtc_addr+1,(address&0xff00)>>8);
1111 outb(crtc_addr,0x0d);
1112 outb(crtc_addr+1,address&0x00ff);
1114 // And change the BIOS page
1115 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1117 #ifdef DEBUG
1118 printf("Set active page %02x address %04x\n",page,address);
1119 #endif
1121 // Display the cursor, now the page is active
1122 biosfn_set_cursor_pos(page,cursor);
1125 // --------------------------------------------------------------------------------------------
1126 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1127 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1129 Bit16u src,dest;
1130 Bit8u i;
1132 src=ysrc*cheight*nbcols+xstart;
1133 dest=ydest*cheight*nbcols+xstart;
1134 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1135 for(i=0;i<cheight;i++)
1137 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1139 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1142 // --------------------------------------------------------------------------------------------
1143 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr)
1144 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1146 Bit16u dest;
1147 Bit8u i;
1149 dest=ystart*cheight*nbcols+xstart;
1150 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1151 for(i=0;i<cheight;i++)
1153 memsetb(0xa000,dest+i*nbcols,attr,cols);
1155 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1158 // --------------------------------------------------------------------------------------------
1159 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1160 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1162 Bit16u src,dest;
1163 Bit8u i;
1165 src=((ysrc*cheight*nbcols)>>1)+xstart;
1166 dest=((ydest*cheight*nbcols)>>1)+xstart;
1167 for(i=0;i<cheight;i++)
1169 if (i & 1)
1170 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1171 else
1172 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1176 // --------------------------------------------------------------------------------------------
1177 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1178 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1180 Bit16u dest;
1181 Bit8u i;
1183 dest=((ystart*cheight*nbcols)>>1)+xstart;
1184 for(i=0;i<cheight;i++)
1186 if (i & 1)
1187 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1188 else
1189 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1193 // --------------------------------------------------------------------------------------------
1194 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1195 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1197 // page == 0xFF if current
1199 Bit8u mode,line,cheight,bpp,cols;
1200 Bit16u nbcols,nbrows,i;
1201 Bit16u address;
1203 if(rul>rlr)return;
1204 if(cul>clr)return;
1206 // Get the mode
1207 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1208 line=find_vga_entry(mode);
1209 if(line==0xFF)return;
1211 // Get the dimensions
1212 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1213 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1215 // Get the current page
1216 if(page==0xFF)
1217 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1219 if(rlr>=nbrows)rlr=nbrows-1;
1220 if(clr>=nbcols)clr=nbcols-1;
1221 if(nblines>nbrows)nblines=0;
1222 cols=clr-cul+1;
1224 if(vga_modes[line].class==TEXT)
1226 // Compute the address
1227 address=SCREEN_MEM_START(nbcols,nbrows,page);
1228 #ifdef DEBUG
1229 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1230 #endif
1232 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1234 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1236 else
1237 {// if Scroll up
1238 if(dir==SCROLL_UP)
1239 {for(i=rul;i<=rlr;i++)
1241 if((i+nblines>rlr)||(nblines==0))
1242 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1243 else
1244 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1247 else
1248 {for(i=rlr;i>=rul;i--)
1250 if((i<rul+nblines)||(nblines==0))
1251 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1252 else
1253 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1258 else
1260 // FIXME gfx mode not complete
1261 cheight=vga_modes[line].cheight;
1262 switch(vga_modes[line].memmodel)
1264 case PLANAR4:
1265 case PLANAR1:
1266 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1268 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1269 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1270 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1272 else
1273 {// if Scroll up
1274 if(dir==SCROLL_UP)
1275 {for(i=rul;i<=rlr;i++)
1277 if((i+nblines>rlr)||(nblines==0))
1278 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1279 else
1280 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1283 else
1284 {for(i=rlr;i>=rul;i--)
1286 if((i<rul+nblines)||(nblines==0))
1287 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1288 else
1289 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1293 break;
1294 case CGA:
1295 bpp=vga_modes[line].pixbits;
1296 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1298 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1300 else
1302 if(bpp==2)
1304 cul<<=1;
1305 cols<<=1;
1306 nbcols<<=1;
1308 // if Scroll up
1309 if(dir==SCROLL_UP)
1310 {for(i=rul;i<=rlr;i++)
1312 if((i+nblines>rlr)||(nblines==0))
1313 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1314 else
1315 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1318 else
1319 {for(i=rlr;i>=rul;i--)
1321 if((i<rul+nblines)||(nblines==0))
1322 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1323 else
1324 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1328 break;
1329 #ifdef DEBUG
1330 default:
1331 printf("Scroll in graphics mode ");
1332 unimplemented();
1333 #endif
1338 // --------------------------------------------------------------------------------------------
1339 static void biosfn_read_char_attr (page,car)
1340 Bit8u page;Bit16u *car;
1341 {Bit16u ss=get_SS();
1342 Bit8u xcurs,ycurs,mode,line;
1343 Bit16u nbcols,nbrows,address;
1344 Bit16u cursor,dummy;
1346 // Get the mode
1347 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1348 line=find_vga_entry(mode);
1349 if(line==0xFF)return;
1351 // Get the cursor pos for the page
1352 biosfn_get_cursor_pos(page,&dummy,&cursor);
1353 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1355 // Get the dimensions
1356 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1357 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1359 if(vga_modes[line].class==TEXT)
1361 // Compute the address
1362 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1364 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1366 else
1368 // FIXME gfx mode
1369 #ifdef DEBUG
1370 unimplemented();
1371 #endif
1375 // --------------------------------------------------------------------------------------------
1376 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1377 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1379 Bit8u i,j,mask;
1380 Bit8u *fdata;
1381 Bit16u addr,dest,src;
1383 switch(cheight)
1384 {case 14:
1385 fdata = &vgafont14;
1386 break;
1387 case 16:
1388 fdata = &vgafont16;
1389 break;
1390 default:
1391 fdata = &vgafont8;
1393 addr=xcurs+ycurs*cheight*nbcols;
1394 src = car * cheight;
1395 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1396 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1397 if(attr&0x80)
1399 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1401 else
1403 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1405 for(i=0;i<cheight;i++)
1407 dest=addr+i*nbcols;
1408 for(j=0;j<8;j++)
1410 mask=0x80>>j;
1411 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1412 read_byte(0xa000,dest);
1413 if(fdata[src+i]&mask)
1415 write_byte(0xa000,dest,attr&0x0f);
1417 else
1419 write_byte(0xa000,dest,0x00);
1423 ASM_START
1424 mov dx, # VGAREG_GRDC_ADDRESS
1425 mov ax, #0xff08
1426 out dx, ax
1427 mov ax, #0x0005
1428 out dx, ax
1429 mov ax, #0x0003
1430 out dx, ax
1431 ASM_END
1434 // --------------------------------------------------------------------------------------------
1435 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1436 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1438 Bit8u i,j,mask,data;
1439 Bit8u *fdata;
1440 Bit16u addr,dest,src;
1442 fdata = &vgafont8;
1443 addr=(xcurs*bpp)+ycurs*320;
1444 src = car * 8;
1445 for(i=0;i<8;i++)
1447 dest=addr+(i>>1)*80;
1448 if (i & 1) dest += 0x2000;
1449 mask = 0x80;
1450 if (bpp == 1)
1452 if (attr & 0x80)
1454 data = read_byte(0xb800,dest);
1456 else
1458 data = 0x00;
1460 for(j=0;j<8;j++)
1462 if (fdata[src+i] & mask)
1464 if (attr & 0x80)
1466 data ^= (attr & 0x01) << (7-j);
1468 else
1470 data |= (attr & 0x01) << (7-j);
1473 mask >>= 1;
1475 write_byte(0xb800,dest,data);
1477 else
1479 while (mask > 0)
1481 if (attr & 0x80)
1483 data = read_byte(0xb800,dest);
1485 else
1487 data = 0x00;
1489 for(j=0;j<4;j++)
1491 if (fdata[src+i] & mask)
1493 if (attr & 0x80)
1495 data ^= (attr & 0x03) << ((3-j)*2);
1497 else
1499 data |= (attr & 0x03) << ((3-j)*2);
1502 mask >>= 1;
1504 write_byte(0xb800,dest,data);
1505 dest += 1;
1511 // --------------------------------------------------------------------------------------------
1512 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1513 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1515 Bit8u i,j,mask,data;
1516 Bit8u *fdata;
1517 Bit16u addr,dest,src;
1519 fdata = &vgafont8;
1520 addr=xcurs*8+ycurs*nbcols*64;
1521 src = car * 8;
1522 for(i=0;i<8;i++)
1524 dest=addr+i*nbcols*8;
1525 mask = 0x80;
1526 for(j=0;j<8;j++)
1528 data = 0x00;
1529 if (fdata[src+i] & mask)
1531 data = attr;
1533 write_byte(0xa000,dest+j,data);
1534 mask >>= 1;
1539 // --------------------------------------------------------------------------------------------
1540 static void biosfn_write_char_attr (car,page,attr,count)
1541 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1543 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1544 Bit16u nbcols,nbrows,address;
1545 Bit16u cursor,dummy;
1547 // Get the mode
1548 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1549 line=find_vga_entry(mode);
1550 if(line==0xFF)return;
1552 // Get the cursor pos for the page
1553 biosfn_get_cursor_pos(page,&dummy,&cursor);
1554 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1556 // Get the dimensions
1557 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1558 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1560 if(vga_modes[line].class==TEXT)
1562 // Compute the address
1563 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1565 dummy=((Bit16u)attr<<8)+car;
1566 memsetw(vga_modes[line].sstart,address,dummy,count);
1568 else
1570 // FIXME gfx mode not complete
1571 cheight=vga_modes[line].cheight;
1572 bpp=vga_modes[line].pixbits;
1573 while((count-->0) && (xcurs<nbcols))
1575 switch(vga_modes[line].memmodel)
1577 case PLANAR4:
1578 case PLANAR1:
1579 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1580 break;
1581 case CGA:
1582 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1583 break;
1584 case LINEAR8:
1585 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1586 break;
1587 #ifdef DEBUG
1588 default:
1589 unimplemented();
1590 #endif
1592 xcurs++;
1597 // --------------------------------------------------------------------------------------------
1598 static void biosfn_write_char_only (car,page,attr,count)
1599 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1601 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1602 Bit16u nbcols,nbrows,address;
1603 Bit16u cursor,dummy;
1605 // Get the mode
1606 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1607 line=find_vga_entry(mode);
1608 if(line==0xFF)return;
1610 // Get the cursor pos for the page
1611 biosfn_get_cursor_pos(page,&dummy,&cursor);
1612 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1614 // Get the dimensions
1615 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1616 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1618 if(vga_modes[line].class==TEXT)
1620 // Compute the address
1621 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1623 while(count-->0)
1624 {write_byte(vga_modes[line].sstart,address,car);
1625 address+=2;
1628 else
1630 // FIXME gfx mode not complete
1631 cheight=vga_modes[line].cheight;
1632 bpp=vga_modes[line].pixbits;
1633 while((count-->0) && (xcurs<nbcols))
1635 switch(vga_modes[line].memmodel)
1637 case PLANAR4:
1638 case PLANAR1:
1639 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1640 break;
1641 case CGA:
1642 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1643 break;
1644 case LINEAR8:
1645 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1646 break;
1647 #ifdef DEBUG
1648 default:
1649 unimplemented();
1650 #endif
1652 xcurs++;
1657 // --------------------------------------------------------------------------------------------
1658 ASM_START
1659 biosfn_group_0B:
1660 cmp bh, #0x00
1661 je biosfn_set_border_color
1662 cmp bh, #0x01
1663 je biosfn_set_palette
1664 #ifdef DEBUG
1665 call _unknown
1666 #endif
1668 biosfn_set_border_color:
1669 push ax
1670 push bx
1671 push cx
1672 push dx
1673 mov dx, # VGAREG_ACTL_RESET
1674 in al, dx
1675 mov dx, # VGAREG_ACTL_ADDRESS
1676 mov al, #0x00
1677 out dx, al
1678 mov al, bl
1679 and al, #0x0f
1680 test al, #0x08
1681 jz set_low_border
1682 add al, #0x08
1683 set_low_border:
1684 out dx, al
1685 mov cl, #0x01
1686 and bl, #0x10
1687 set_intensity_loop:
1688 mov dx, # VGAREG_ACTL_ADDRESS
1689 mov al, cl
1690 out dx, al
1691 mov dx, # VGAREG_ACTL_READ_DATA
1692 in al, dx
1693 and al, #0xef
1694 or al, bl
1695 mov dx, # VGAREG_ACTL_ADDRESS
1696 out dx, al
1697 inc cl
1698 cmp cl, #0x04
1699 jne set_intensity_loop
1700 mov al, #0x20
1701 out dx, al
1702 pop dx
1703 pop cx
1704 pop bx
1705 pop ax
1707 biosfn_set_palette:
1708 push ax
1709 push bx
1710 push cx
1711 push dx
1712 mov dx, # VGAREG_ACTL_RESET
1713 in al, dx
1714 mov cl, #0x01
1715 and bl, #0x01
1716 set_cga_palette_loop:
1717 mov dx, # VGAREG_ACTL_ADDRESS
1718 mov al, cl
1719 out dx, al
1720 mov dx, # VGAREG_ACTL_READ_DATA
1721 in al, dx
1722 and al, #0xfe
1723 or al, bl
1724 mov dx, # VGAREG_ACTL_ADDRESS
1725 out dx, al
1726 inc cl
1727 cmp cl, #0x04
1728 jne set_cga_palette_loop
1729 mov al, #0x20
1730 out dx, al
1731 pop dx
1732 pop cx
1733 pop bx
1734 pop ax
1736 ASM_END
1738 // --------------------------------------------------------------------------------------------
1739 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1741 Bit8u mode,line,mask,attr,data;
1742 Bit16u addr;
1744 // Get the mode
1745 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1746 line=find_vga_entry(mode);
1747 if(line==0xFF)return;
1748 if(vga_modes[line].class==TEXT)return;
1750 switch(vga_modes[line].memmodel)
1752 case PLANAR4:
1753 case PLANAR1:
1754 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1755 mask = 0x80 >> (CX & 0x07);
1756 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1757 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1758 data = read_byte(0xa000,addr);
1759 if (AL & 0x80)
1761 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1763 write_byte(0xa000,addr,AL);
1764 ASM_START
1765 mov dx, # VGAREG_GRDC_ADDRESS
1766 mov ax, #0xff08
1767 out dx, ax
1768 mov ax, #0x0005
1769 out dx, ax
1770 mov ax, #0x0003
1771 out dx, ax
1772 ASM_END
1773 break;
1774 case CGA:
1775 if(vga_modes[line].pixbits==2)
1777 addr=(CX>>2)+(DX>>1)*80;
1779 else
1781 addr=(CX>>3)+(DX>>1)*80;
1783 if (DX & 1) addr += 0x2000;
1784 data = read_byte(0xb800,addr);
1785 if(vga_modes[line].pixbits==2)
1787 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1788 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1790 else
1792 attr = (AL & 0x01) << (7 - (CX & 0x07));
1793 mask = 0x01 << (7 - (CX & 0x07));
1795 if (AL & 0x80)
1797 data ^= attr;
1799 else
1801 data &= ~mask;
1802 data |= attr;
1804 write_byte(0xb800,addr,data);
1805 break;
1806 case LINEAR8:
1807 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1808 write_byte(0xa000,addr,AL);
1809 break;
1810 #ifdef DEBUG
1811 default:
1812 unimplemented();
1813 #endif
1817 // --------------------------------------------------------------------------------------------
1818 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1820 Bit8u mode,line,mask,attr,data,i;
1821 Bit16u addr;
1822 Bit16u ss=get_SS();
1824 // Get the mode
1825 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1826 line=find_vga_entry(mode);
1827 if(line==0xFF)return;
1828 if(vga_modes[line].class==TEXT)return;
1830 switch(vga_modes[line].memmodel)
1832 case PLANAR4:
1833 case PLANAR1:
1834 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1835 mask = 0x80 >> (CX & 0x07);
1836 attr = 0x00;
1837 for(i=0;i<4;i++)
1839 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1840 data = read_byte(0xa000,addr) & mask;
1841 if (data > 0) attr |= (0x01 << i);
1843 break;
1844 case CGA:
1845 addr=(CX>>2)+(DX>>1)*80;
1846 if (DX & 1) addr += 0x2000;
1847 data = read_byte(0xb800,addr);
1848 if(vga_modes[line].pixbits==2)
1850 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1852 else
1854 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1856 break;
1857 case LINEAR8:
1858 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1859 attr=read_byte(0xa000,addr);
1860 break;
1861 default:
1862 #ifdef DEBUG
1863 unimplemented();
1864 #endif
1865 attr = 0;
1867 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1870 // --------------------------------------------------------------------------------------------
1871 static void biosfn_write_teletype (car, page, attr, flag)
1872 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1873 {// flag = WITH_ATTR / NO_ATTR
1875 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1876 Bit16u nbcols,nbrows,address;
1877 Bit16u cursor,dummy;
1879 // special case if page is 0xff, use current page
1880 if(page==0xff)
1881 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1883 // Get the mode
1884 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1885 line=find_vga_entry(mode);
1886 if(line==0xFF)return;
1888 // Get the cursor pos for the page
1889 biosfn_get_cursor_pos(page,&dummy,&cursor);
1890 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1892 // Get the dimensions
1893 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1894 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1896 switch(car)
1898 case 7:
1899 //FIXME should beep
1900 break;
1902 case 8:
1903 if(xcurs>0)xcurs--;
1904 break;
1906 case '\r':
1907 xcurs=0;
1908 break;
1910 case '\n':
1911 xcurs=0;
1912 ycurs++;
1913 break;
1915 case '\t':
1918 biosfn_write_teletype(' ',page,attr,flag);
1919 biosfn_get_cursor_pos(page,&dummy,&cursor);
1920 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1921 }while(xcurs%8==0);
1922 break;
1924 default:
1926 if(vga_modes[line].class==TEXT)
1928 // Compute the address
1929 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1931 // Write the char
1932 write_byte(vga_modes[line].sstart,address,car);
1934 if(flag==WITH_ATTR)
1935 write_byte(vga_modes[line].sstart,address+1,attr);
1937 else
1939 // FIXME gfx mode not complete
1940 cheight=vga_modes[line].cheight;
1941 bpp=vga_modes[line].pixbits;
1942 switch(vga_modes[line].memmodel)
1944 case PLANAR4:
1945 case PLANAR1:
1946 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1947 break;
1948 case CGA:
1949 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1950 break;
1951 case LINEAR8:
1952 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1953 break;
1954 #ifdef DEBUG
1955 default:
1956 unimplemented();
1957 #endif
1960 xcurs++;
1963 // Do we need to wrap ?
1964 if(xcurs==nbcols)
1965 {xcurs=0;
1966 ycurs++;
1969 // Do we need to scroll ?
1970 if(ycurs==nbrows)
1972 if(vga_modes[line].class==TEXT)
1974 biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1976 else
1978 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1980 ycurs-=1;
1983 // Set the cursor for the page
1984 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1985 biosfn_set_cursor_pos(page,cursor);
1988 // --------------------------------------------------------------------------------------------
1989 ASM_START
1990 biosfn_get_video_mode:
1991 push ds
1992 mov ax, # BIOSMEM_SEG
1993 mov ds, ax
1994 push bx
1995 mov bx, # BIOSMEM_CURRENT_PAGE
1996 mov al, [bx]
1997 pop bx
1998 mov bh, al
1999 push bx
2000 mov bx, # BIOSMEM_VIDEO_CTL
2001 mov ah, [bx]
2002 and ah, #0x80
2003 mov bx, # BIOSMEM_CURRENT_MODE
2004 mov al, [bx]
2005 or al, ah
2006 mov bx, # BIOSMEM_NB_COLS
2007 mov ah, [bx]
2008 pop bx
2009 pop ds
2011 ASM_END
2013 // --------------------------------------------------------------------------------------------
2014 ASM_START
2015 biosfn_group_10:
2016 cmp al, #0x00
2017 jne int10_test_1001
2018 jmp biosfn_set_single_palette_reg
2019 int10_test_1001:
2020 cmp al, #0x01
2021 jne int10_test_1002
2022 jmp biosfn_set_overscan_border_color
2023 int10_test_1002:
2024 cmp al, #0x02
2025 jne int10_test_1003
2026 jmp biosfn_set_all_palette_reg
2027 int10_test_1003:
2028 cmp al, #0x03
2029 jne int10_test_1007
2030 jmp biosfn_toggle_intensity
2031 int10_test_1007:
2032 cmp al, #0x07
2033 jne int10_test_1008
2034 jmp biosfn_get_single_palette_reg
2035 int10_test_1008:
2036 cmp al, #0x08
2037 jne int10_test_1009
2038 jmp biosfn_read_overscan_border_color
2039 int10_test_1009:
2040 cmp al, #0x09
2041 jne int10_test_1010
2042 jmp biosfn_get_all_palette_reg
2043 int10_test_1010:
2044 cmp al, #0x10
2045 jne int10_test_1012
2046 jmp biosfn_set_single_dac_reg
2047 int10_test_1012:
2048 cmp al, #0x12
2049 jne int10_test_1013
2050 jmp biosfn_set_all_dac_reg
2051 int10_test_1013:
2052 cmp al, #0x13
2053 jne int10_test_1015
2054 jmp biosfn_select_video_dac_color_page
2055 int10_test_1015:
2056 cmp al, #0x15
2057 jne int10_test_1017
2058 jmp biosfn_read_single_dac_reg
2059 int10_test_1017:
2060 cmp al, #0x17
2061 jne int10_test_1018
2062 jmp biosfn_read_all_dac_reg
2063 int10_test_1018:
2064 cmp al, #0x18
2065 jne int10_test_1019
2066 jmp biosfn_set_pel_mask
2067 int10_test_1019:
2068 cmp al, #0x19
2069 jne int10_test_101A
2070 jmp biosfn_read_pel_mask
2071 int10_test_101A:
2072 cmp al, #0x1a
2073 jne int10_group_10_unknown
2074 jmp biosfn_read_video_dac_state
2075 int10_group_10_unknown:
2076 #ifdef DEBUG
2077 call _unknown
2078 #endif
2081 biosfn_set_single_palette_reg:
2082 cmp bl, #0x14
2083 ja no_actl_reg1
2084 push ax
2085 push dx
2086 mov dx, # VGAREG_ACTL_RESET
2087 in al, dx
2088 mov dx, # VGAREG_ACTL_ADDRESS
2089 mov al, bl
2090 out dx, al
2091 mov al, bh
2092 out dx, al
2093 mov al, #0x20
2094 out dx, al
2095 pop dx
2096 pop ax
2097 no_actl_reg1:
2099 ASM_END
2101 // --------------------------------------------------------------------------------------------
2102 ASM_START
2103 biosfn_set_overscan_border_color:
2104 push bx
2105 mov bl, #0x11
2106 call biosfn_set_single_palette_reg
2107 pop bx
2109 ASM_END
2111 // --------------------------------------------------------------------------------------------
2112 ASM_START
2113 biosfn_set_all_palette_reg:
2114 push ax
2115 push bx
2116 push cx
2117 push dx
2118 mov bx, dx
2119 mov dx, # VGAREG_ACTL_RESET
2120 in al, dx
2121 mov cl, #0x00
2122 mov dx, # VGAREG_ACTL_ADDRESS
2123 set_palette_loop:
2124 mov al, cl
2125 out dx, al
2126 seg es
2127 mov al, [bx]
2128 out dx, al
2129 inc bx
2130 inc cl
2131 cmp cl, #0x10
2132 jne set_palette_loop
2133 mov al, #0x11
2134 out dx, al
2135 seg es
2136 mov al, [bx]
2137 out dx, al
2138 mov al, #0x20
2139 out dx, al
2140 pop dx
2141 pop cx
2142 pop bx
2143 pop ax
2145 ASM_END
2147 // --------------------------------------------------------------------------------------------
2148 ASM_START
2149 biosfn_toggle_intensity:
2150 push ax
2151 push bx
2152 push dx
2153 mov dx, # VGAREG_ACTL_RESET
2154 in al, dx
2155 mov dx, # VGAREG_ACTL_ADDRESS
2156 mov al, #0x10
2157 out dx, al
2158 mov dx, # VGAREG_ACTL_READ_DATA
2159 in al, dx
2160 and al, #0xf7
2161 and bl, #0x01
2162 shl bl, 3
2163 or al, bl
2164 mov dx, # VGAREG_ACTL_ADDRESS
2165 out dx, al
2166 mov al, #0x20
2167 out dx, al
2168 pop dx
2169 pop bx
2170 pop ax
2172 ASM_END
2174 // --------------------------------------------------------------------------------------------
2175 ASM_START
2176 biosfn_get_single_palette_reg:
2177 cmp bl, #0x14
2178 ja no_actl_reg2
2179 push ax
2180 push dx
2181 mov dx, # VGAREG_ACTL_RESET
2182 in al, dx
2183 mov dx, # VGAREG_ACTL_ADDRESS
2184 mov al, bl
2185 out dx, al
2186 mov dx, # VGAREG_ACTL_READ_DATA
2187 in al, dx
2188 mov bh, al
2189 mov dx, # VGAREG_ACTL_RESET
2190 in al, dx
2191 mov dx, # VGAREG_ACTL_ADDRESS
2192 mov al, #0x20
2193 out dx, al
2194 pop dx
2195 pop ax
2196 no_actl_reg2:
2198 ASM_END
2200 // --------------------------------------------------------------------------------------------
2201 ASM_START
2202 biosfn_read_overscan_border_color:
2203 push ax
2204 push bx
2205 mov bl, #0x11
2206 call biosfn_get_single_palette_reg
2207 mov al, bh
2208 pop bx
2209 mov bh, al
2210 pop ax
2212 ASM_END
2214 // --------------------------------------------------------------------------------------------
2215 ASM_START
2216 biosfn_get_all_palette_reg:
2217 push ax
2218 push bx
2219 push cx
2220 push dx
2221 mov bx, dx
2222 mov cl, #0x00
2223 get_palette_loop:
2224 mov dx, # VGAREG_ACTL_RESET
2225 in al, dx
2226 mov dx, # VGAREG_ACTL_ADDRESS
2227 mov al, cl
2228 out dx, al
2229 mov dx, # VGAREG_ACTL_READ_DATA
2230 in al, dx
2231 seg es
2232 mov [bx], al
2233 inc bx
2234 inc cl
2235 cmp cl, #0x10
2236 jne get_palette_loop
2237 mov dx, # VGAREG_ACTL_RESET
2238 in al, dx
2239 mov dx, # VGAREG_ACTL_ADDRESS
2240 mov al, #0x11
2241 out dx, al
2242 mov dx, # VGAREG_ACTL_READ_DATA
2243 in al, dx
2244 seg es
2245 mov [bx], al
2246 mov dx, # VGAREG_ACTL_RESET
2247 in al, dx
2248 mov dx, # VGAREG_ACTL_ADDRESS
2249 mov al, #0x20
2250 out dx, al
2251 pop dx
2252 pop cx
2253 pop bx
2254 pop ax
2256 ASM_END
2258 // --------------------------------------------------------------------------------------------
2259 ASM_START
2260 biosfn_set_single_dac_reg:
2261 push ax
2262 push dx
2263 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2264 mov al, bl
2265 out dx, al
2266 mov dx, # VGAREG_DAC_DATA
2267 pop ax
2268 push ax
2269 mov al, ah
2270 out dx, al
2271 mov al, ch
2272 out dx, al
2273 mov al, cl
2274 out dx, al
2275 pop dx
2276 pop ax
2278 ASM_END
2280 // --------------------------------------------------------------------------------------------
2281 ASM_START
2282 biosfn_set_all_dac_reg:
2283 push ax
2284 push bx
2285 push cx
2286 push dx
2287 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2288 mov al, bl
2289 out dx, al
2290 pop dx
2291 push dx
2292 mov bx, dx
2293 mov dx, # VGAREG_DAC_DATA
2294 set_dac_loop:
2295 seg es
2296 mov al, [bx]
2297 out dx, al
2298 inc bx
2299 seg es
2300 mov al, [bx]
2301 out dx, al
2302 inc bx
2303 seg es
2304 mov al, [bx]
2305 out dx, al
2306 inc bx
2307 dec cx
2308 jnz set_dac_loop
2309 pop dx
2310 pop cx
2311 pop bx
2312 pop ax
2314 ASM_END
2316 // --------------------------------------------------------------------------------------------
2317 ASM_START
2318 biosfn_select_video_dac_color_page:
2319 push ax
2320 push bx
2321 push dx
2322 mov dx, # VGAREG_ACTL_RESET
2323 in al, dx
2324 mov dx, # VGAREG_ACTL_ADDRESS
2325 mov al, #0x10
2326 out dx, al
2327 mov dx, # VGAREG_ACTL_READ_DATA
2328 in al, dx
2329 and bl, #0x01
2330 jnz set_dac_page
2331 and al, #0x7f
2332 shl bh, 7
2333 or al, bh
2334 mov dx, # VGAREG_ACTL_ADDRESS
2335 out dx, al
2336 jmp set_actl_normal
2337 set_dac_page:
2338 push ax
2339 mov dx, # VGAREG_ACTL_RESET
2340 in al, dx
2341 mov dx, # VGAREG_ACTL_ADDRESS
2342 mov al, #0x14
2343 out dx, al
2344 pop ax
2345 and al, #0x80
2346 jnz set_dac_16_page
2347 shl bh, 2
2348 set_dac_16_page:
2349 and bh, #0x0f
2350 mov al, bh
2351 out dx, al
2352 set_actl_normal:
2353 mov al, #0x20
2354 out dx, al
2355 pop dx
2356 pop bx
2357 pop ax
2359 ASM_END
2361 // --------------------------------------------------------------------------------------------
2362 ASM_START
2363 biosfn_read_single_dac_reg:
2364 push ax
2365 push dx
2366 mov dx, # VGAREG_DAC_READ_ADDRESS
2367 mov al, bl
2368 out dx, al
2369 pop ax
2370 mov ah, al
2371 mov dx, # VGAREG_DAC_DATA
2372 in al, dx
2373 xchg al, ah
2374 push ax
2375 in al, dx
2376 mov ch, al
2377 in al, dx
2378 mov cl, al
2379 pop dx
2380 pop ax
2382 ASM_END
2384 // --------------------------------------------------------------------------------------------
2385 ASM_START
2386 biosfn_read_all_dac_reg:
2387 push ax
2388 push bx
2389 push cx
2390 push dx
2391 mov dx, # VGAREG_DAC_READ_ADDRESS
2392 mov al, bl
2393 out dx, al
2394 pop dx
2395 push dx
2396 mov bx, dx
2397 mov dx, # VGAREG_DAC_DATA
2398 read_dac_loop:
2399 in al, dx
2400 seg es
2401 mov [bx], al
2402 inc bx
2403 in al, dx
2404 seg es
2405 mov [bx], al
2406 inc bx
2407 in al, dx
2408 seg es
2409 mov [bx], al
2410 inc bx
2411 dec cx
2412 jnz read_dac_loop
2413 pop dx
2414 pop cx
2415 pop bx
2416 pop ax
2418 ASM_END
2420 // --------------------------------------------------------------------------------------------
2421 ASM_START
2422 biosfn_set_pel_mask:
2423 push ax
2424 push dx
2425 mov dx, # VGAREG_PEL_MASK
2426 mov al, bl
2427 out dx, al
2428 pop dx
2429 pop ax
2431 ASM_END
2433 // --------------------------------------------------------------------------------------------
2434 ASM_START
2435 biosfn_read_pel_mask:
2436 push ax
2437 push dx
2438 mov dx, # VGAREG_PEL_MASK
2439 in al, dx
2440 mov bl, al
2441 pop dx
2442 pop ax
2444 ASM_END
2446 // --------------------------------------------------------------------------------------------
2447 ASM_START
2448 biosfn_read_video_dac_state:
2449 push ax
2450 push dx
2451 mov dx, # VGAREG_ACTL_RESET
2452 in al, dx
2453 mov dx, # VGAREG_ACTL_ADDRESS
2454 mov al, #0x10
2455 out dx, al
2456 mov dx, # VGAREG_ACTL_READ_DATA
2457 in al, dx
2458 mov bl, al
2459 shr bl, 7
2460 mov dx, # VGAREG_ACTL_RESET
2461 in al, dx
2462 mov dx, # VGAREG_ACTL_ADDRESS
2463 mov al, #0x14
2464 out dx, al
2465 mov dx, # VGAREG_ACTL_READ_DATA
2466 in al, dx
2467 mov bh, al
2468 and bh, #0x0f
2469 test bl, #0x01
2470 jnz get_dac_16_page
2471 shr bh, 2
2472 get_dac_16_page:
2473 mov dx, # VGAREG_ACTL_RESET
2474 in al, dx
2475 mov dx, # VGAREG_ACTL_ADDRESS
2476 mov al, #0x20
2477 out dx, al
2478 pop dx
2479 pop ax
2481 ASM_END
2483 // --------------------------------------------------------------------------------------------
2484 static void biosfn_perform_gray_scale_summing (start,count)
2485 Bit16u start;Bit16u count;
2486 {Bit8u r,g,b;
2487 Bit16u i;
2488 Bit16u index;
2490 inb(VGAREG_ACTL_RESET);
2491 outb(VGAREG_ACTL_ADDRESS,0x00);
2493 for( index = 0; index < count; index++ )
2495 // set read address and switch to read mode
2496 outb(VGAREG_DAC_READ_ADDRESS,start);
2497 // get 6-bit wide RGB data values
2498 r=inb( VGAREG_DAC_DATA );
2499 g=inb( VGAREG_DAC_DATA );
2500 b=inb( VGAREG_DAC_DATA );
2502 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2503 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2505 if(i>0x3f)i=0x3f;
2507 // set write address and switch to write mode
2508 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2509 // write new intensity value
2510 outb( VGAREG_DAC_DATA, i&0xff );
2511 outb( VGAREG_DAC_DATA, i&0xff );
2512 outb( VGAREG_DAC_DATA, i&0xff );
2513 start++;
2515 inb(VGAREG_ACTL_RESET);
2516 outb(VGAREG_ACTL_ADDRESS,0x20);
2519 // --------------------------------------------------------------------------------------------
2520 static void get_font_access()
2522 ASM_START
2523 mov dx, # VGAREG_SEQU_ADDRESS
2524 mov ax, #0x0100
2525 out dx, ax
2526 mov ax, #0x0402
2527 out dx, ax
2528 mov ax, #0x0704
2529 out dx, ax
2530 mov ax, #0x0300
2531 out dx, ax
2532 mov dx, # VGAREG_GRDC_ADDRESS
2533 mov ax, #0x0204
2534 out dx, ax
2535 mov ax, #0x0005
2536 out dx, ax
2537 mov ax, #0x0406
2538 out dx, ax
2539 ASM_END
2542 static void release_font_access()
2544 ASM_START
2545 mov dx, # VGAREG_SEQU_ADDRESS
2546 mov ax, #0x0100
2547 out dx, ax
2548 mov ax, #0x0302
2549 out dx, ax
2550 mov ax, #0x0304
2551 out dx, ax
2552 mov ax, #0x0300
2553 out dx, ax
2554 mov dx, # VGAREG_READ_MISC_OUTPUT
2555 in al, dx
2556 and al, #0x01
2557 shl al, 2
2558 or al, #0x0a
2559 mov ah, al
2560 mov al, #0x06
2561 mov dx, # VGAREG_GRDC_ADDRESS
2562 out dx, ax
2563 mov ax, #0x0004
2564 out dx, ax
2565 mov ax, #0x1005
2566 out dx, ax
2567 ASM_END
2570 ASM_START
2571 idiv_u:
2572 xor dx,dx
2573 div bx
2575 ASM_END
2577 static void set_scan_lines(lines) Bit8u lines;
2579 Bit16u crtc_addr,cols,page,vde;
2580 Bit8u crtc_r9,ovl,rows;
2582 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2583 outb(crtc_addr, 0x09);
2584 crtc_r9 = inb(crtc_addr+1);
2585 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2586 outb(crtc_addr+1, crtc_r9);
2587 if(lines==8)
2589 biosfn_set_cursor_shape(0x06,0x07);
2591 else
2593 biosfn_set_cursor_shape(lines-4,lines-3);
2595 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2596 outb(crtc_addr, 0x12);
2597 vde = inb(crtc_addr+1);
2598 outb(crtc_addr, 0x07);
2599 ovl = inb(crtc_addr+1);
2600 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2601 rows = vde / lines;
2602 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2603 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2604 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2607 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;
2609 Bit16u blockaddr,dest,i,src;
2611 get_font_access();
2612 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2613 for(i=0;i<CX;i++)
2615 src = BP + i * BH;
2616 dest = blockaddr + (DX + i) * 32;
2617 memcpyb(0xA000, dest, ES, src, BH);
2619 release_font_access();
2620 if(AL>=0x10)
2622 set_scan_lines(BH);
2626 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2628 Bit16u blockaddr,dest,i,src;
2630 get_font_access();
2631 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2632 for(i=0;i<0x100;i++)
2634 src = i * 14;
2635 dest = blockaddr + i * 32;
2636 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2638 release_font_access();
2639 if(AL>=0x10)
2641 set_scan_lines(14);
2645 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2647 Bit16u blockaddr,dest,i,src;
2649 get_font_access();
2650 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2651 for(i=0;i<0x100;i++)
2653 src = i * 8;
2654 dest = blockaddr + i * 32;
2655 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2657 release_font_access();
2658 if(AL>=0x10)
2660 set_scan_lines(8);
2664 // --------------------------------------------------------------------------------------------
2665 ASM_START
2666 biosfn_set_text_block_specifier:
2667 push ax
2668 push dx
2669 mov dx, # VGAREG_SEQU_ADDRESS
2670 mov ah, bl
2671 mov al, #0x03
2672 out dx, ax
2673 pop dx
2674 pop ax
2676 ASM_END
2678 // --------------------------------------------------------------------------------------------
2679 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2681 Bit16u blockaddr,dest,i,src;
2683 get_font_access();
2684 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2685 for(i=0;i<0x100;i++)
2687 src = i * 16;
2688 dest = blockaddr + i * 32;
2689 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2691 release_font_access();
2692 if(AL>=0x10)
2694 set_scan_lines(16);
2698 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2700 #ifdef DEBUG
2701 unimplemented();
2702 #endif
2704 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2706 #ifdef DEBUG
2707 unimplemented();
2708 #endif
2710 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2712 #ifdef DEBUG
2713 unimplemented();
2714 #endif
2716 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2718 #ifdef DEBUG
2719 unimplemented();
2720 #endif
2722 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2724 #ifdef DEBUG
2725 unimplemented();
2726 #endif
2728 // --------------------------------------------------------------------------------------------
2729 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2730 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2731 {Bit16u ss=get_SS();
2733 switch(BH)
2734 {case 0x00:
2735 write_word(ss,ES,read_word(0x00,0x1f*4));
2736 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2737 break;
2738 case 0x01:
2739 write_word(ss,ES,read_word(0x00,0x43*4));
2740 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2741 break;
2742 case 0x02:
2743 write_word(ss,ES,0xC000);
2744 write_word(ss,BP,vgafont14);
2745 break;
2746 case 0x03:
2747 write_word(ss,ES,0xC000);
2748 write_word(ss,BP,vgafont8);
2749 break;
2750 case 0x04:
2751 write_word(ss,ES,0xC000);
2752 write_word(ss,BP,vgafont8+128*8);
2753 break;
2754 case 0x05:
2755 write_word(ss,ES,0xC000);
2756 write_word(ss,BP,vgafont14alt);
2757 break;
2758 case 0x06:
2759 write_word(ss,ES,0xC000);
2760 write_word(ss,BP,vgafont16);
2761 break;
2762 case 0x07:
2763 write_word(ss,ES,0xC000);
2764 write_word(ss,BP,vgafont16alt);
2765 break;
2766 default:
2767 #ifdef DEBUG
2768 printf("Get font info BH(%02x) was discarded\n",BH);
2769 #endif
2770 return;
2772 // Set byte/char of on screen font
2773 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2775 // Set Highest char row
2776 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2779 // --------------------------------------------------------------------------------------------
2780 ASM_START
2781 biosfn_get_ega_info:
2782 push ds
2783 push ax
2784 mov ax, # BIOSMEM_SEG
2785 mov ds, ax
2786 xor ch, ch
2787 mov bx, # BIOSMEM_SWITCHES
2788 mov cl, [bx]
2789 and cl, #0x0f
2790 mov bx, # BIOSMEM_CRTC_ADDRESS
2791 mov ax, [bx]
2792 mov bx, #0x0003
2793 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2794 jne mode_ega_color
2795 mov bh, #0x01
2796 mode_ega_color:
2797 pop ax
2798 pop ds
2800 ASM_END
2802 // --------------------------------------------------------------------------------------------
2803 static void biosfn_alternate_prtsc()
2805 #ifdef DEBUG
2806 unimplemented();
2807 #endif
2810 // --------------------------------------------------------------------------------------------
2811 ASM_START
2812 biosfn_select_vert_res:
2814 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2816 push ds
2817 push bx
2818 push dx
2819 mov dl, al
2820 mov ax, # BIOSMEM_SEG
2821 mov ds, ax
2822 mov bx, # BIOSMEM_MODESET_CTL
2823 mov al, [bx]
2824 mov bx, # BIOSMEM_SWITCHES
2825 mov ah, [bx]
2826 cmp dl, #0x01
2827 je vert_res_350
2828 jb vert_res_200
2829 cmp dl, #0x02
2830 je vert_res_400
2831 #ifdef DEBUG
2832 mov al, dl
2833 xor ah, ah
2834 push ax
2835 mov bx, #msg_vert_res
2836 push bx
2837 call _printf
2838 add sp, #4
2839 #endif
2840 jmp set_retcode
2841 vert_res_400:
2843 ; reset modeset ctl bit 7 and set bit 4
2844 ; set switches bit 3-0 to 0x09
2846 and al, #0x7f
2847 or al, #0x10
2848 and ah, #0xf0
2849 or ah, #0x09
2850 jnz set_vert_res
2851 vert_res_350:
2853 ; reset modeset ctl bit 7 and bit 4
2854 ; set switches bit 3-0 to 0x09
2856 and al, #0x6f
2857 and ah, #0xf0
2858 or ah, #0x09
2859 jnz set_vert_res
2860 vert_res_200:
2862 ; set modeset ctl bit 7 and reset bit 4
2863 ; set switches bit 3-0 to 0x08
2865 and al, #0xef
2866 or al, #0x80
2867 and ah, #0xf0
2868 or ah, #0x08
2869 set_vert_res:
2870 mov bx, # BIOSMEM_MODESET_CTL
2871 mov [bx], al
2872 mov bx, # BIOSMEM_SWITCHES
2873 mov [bx], ah
2874 set_retcode:
2875 mov ax, #0x1212
2876 pop dx
2877 pop bx
2878 pop ds
2881 #ifdef DEBUG
2882 msg_vert_res:
2883 .ascii "Select vert res (%02x) was discarded"
2884 .byte 0x0d,0x0a,0x00
2885 #endif
2888 biosfn_enable_default_palette_loading:
2889 push ds
2890 push bx
2891 push dx
2892 mov dl, al
2893 and dl, #0x01
2894 shl dl, 3
2895 mov ax, # BIOSMEM_SEG
2896 mov ds, ax
2897 mov bx, # BIOSMEM_MODESET_CTL
2898 mov al, [bx]
2899 and al, #0xf7
2900 or al, dl
2901 mov [bx], al
2902 mov ax, #0x1212
2903 pop dx
2904 pop bx
2905 pop ds
2909 biosfn_enable_video_addressing:
2910 push bx
2911 push dx
2912 mov bl, al
2913 and bl, #0x01
2914 xor bl, #0x01
2915 shl bl, 1
2916 mov dx, # VGAREG_READ_MISC_OUTPUT
2917 in al, dx
2918 and al, #0xfd
2919 or al, bl
2920 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2921 out dx, al
2922 mov ax, #0x1212
2923 pop dx
2924 pop bx
2928 biosfn_enable_grayscale_summing:
2929 push ds
2930 push bx
2931 push dx
2932 mov dl, al
2933 and dl, #0x01
2934 xor dl, #0x01
2935 shl dl, 1
2936 mov ax, # BIOSMEM_SEG
2937 mov ds, ax
2938 mov bx, # BIOSMEM_MODESET_CTL
2939 mov al, [bx]
2940 and al, #0xfd
2941 or al, dl
2942 mov [bx], al
2943 mov ax, #0x1212
2944 pop dx
2945 pop bx
2946 pop ds
2950 biosfn_enable_cursor_emulation:
2951 push ds
2952 push bx
2953 push dx
2954 mov dl, al
2955 and dl, #0x01
2956 xor dl, #0x01
2957 mov ax, # BIOSMEM_SEG
2958 mov ds, ax
2959 mov bx, # BIOSMEM_MODESET_CTL
2960 mov al, [bx]
2961 and al, #0xfe
2962 or al, dl
2963 mov [bx], al
2964 mov ax, #0x1212
2965 pop dx
2966 pop bx
2967 pop ds
2969 ASM_END
2971 // --------------------------------------------------------------------------------------------
2972 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2974 #ifdef DEBUG
2975 unimplemented();
2976 #endif
2978 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2980 #ifdef DEBUG
2981 unimplemented();
2982 #endif
2985 // --------------------------------------------------------------------------------------------
2986 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2987 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2989 Bit16u newcurs,oldcurs,dummy;
2990 Bit8u car,carattr;
2992 // Read curs info for the page
2993 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2995 // if row=0xff special case : use current cursor position
2996 if(row==0xff)
2997 {col=oldcurs&0x00ff;
2998 row=(oldcurs&0xff00)>>8;
3001 newcurs=row; newcurs<<=8; newcurs+=col;
3002 biosfn_set_cursor_pos(page,newcurs);
3004 while(count--!=0)
3006 car=read_byte(seg,offset++);
3007 if((flag&0x02)!=0)
3008 attr=read_byte(seg,offset++);
3010 biosfn_write_teletype(car,page,attr,WITH_ATTR);
3013 // Set back curs pos
3014 if((flag&0x01)==0)
3015 biosfn_set_cursor_pos(page,oldcurs);
3018 // --------------------------------------------------------------------------------------------
3019 ASM_START
3020 biosfn_group_1A:
3021 cmp al, #0x00
3022 je biosfn_read_display_code
3023 cmp al, #0x01
3024 je biosfn_set_display_code
3025 #ifdef DEBUG
3026 call _unknown
3027 #endif
3029 biosfn_read_display_code:
3030 push ds
3031 push ax
3032 mov ax, # BIOSMEM_SEG
3033 mov ds, ax
3034 mov bx, # BIOSMEM_DCC_INDEX
3035 mov al, [bx]
3036 mov bl, al
3037 xor bh, bh
3038 pop ax
3039 mov al, ah
3040 pop ds
3042 biosfn_set_display_code:
3043 push ds
3044 push ax
3045 push bx
3046 mov ax, # BIOSMEM_SEG
3047 mov ds, ax
3048 mov ax, bx
3049 mov bx, # BIOSMEM_DCC_INDEX
3050 mov [bx], al
3051 #ifdef DEBUG
3052 mov al, ah
3053 xor ah, ah
3054 push ax
3055 mov bx, #msg_alt_dcc
3056 push bx
3057 call _printf
3058 add sp, #4
3059 #endif
3060 pop bx
3061 pop ax
3062 mov al, ah
3063 pop ds
3066 #ifdef DEBUG
3067 msg_alt_dcc:
3068 .ascii "Alternate Display code (%02x) was discarded"
3069 .byte 0x0d,0x0a,0x00
3070 #endif
3071 ASM_END
3073 // --------------------------------------------------------------------------------------------
3074 static void biosfn_read_state_info (BX,ES,DI)
3075 Bit16u BX;Bit16u ES;Bit16u DI;
3077 // Address of static functionality table
3078 write_word(ES,DI+0x00,&static_functionality);
3079 write_word(ES,DI+0x02,0xC000);
3081 // Hard coded copy from BIOS area. Should it be cleaner ?
3082 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3083 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3085 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3086 write_byte(ES,DI+0x26,0);
3087 write_byte(ES,DI+0x27,16);
3088 write_byte(ES,DI+0x28,0);
3089 write_byte(ES,DI+0x29,8);
3090 write_byte(ES,DI+0x2a,2);
3091 write_byte(ES,DI+0x2b,0);
3092 write_byte(ES,DI+0x2c,0);
3093 write_byte(ES,DI+0x31,3);
3094 write_byte(ES,DI+0x32,0);
3096 memsetb(ES,DI+0x33,0,13);
3099 // --------------------------------------------------------------------------------------------
3100 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3102 #ifdef DEBUG
3103 unimplemented();
3104 #endif
3106 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3108 #ifdef DEBUG
3109 unimplemented();
3110 #endif
3112 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3114 #ifdef DEBUG
3115 unimplemented();
3116 #endif
3119 // ============================================================================================
3121 // Video Utils
3123 // ============================================================================================
3125 // --------------------------------------------------------------------------------------------
3126 static Bit8u find_vga_entry(mode)
3127 Bit8u mode;
3129 Bit8u i,line=0xFF;
3130 for(i=0;i<=MODE_MAX;i++)
3131 if(vga_modes[i].svgamode==mode)
3132 {line=i;
3133 break;
3135 return line;
3138 /* =========================================================== */
3140 * Misc Utils
3142 /* =========================================================== */
3144 // --------------------------------------------------------------------------------------------
3145 static void memsetb(seg,offset,value,count)
3146 Bit16u seg;
3147 Bit16u offset;
3148 Bit16u value;
3149 Bit16u count;
3151 ASM_START
3152 push bp
3153 mov bp, sp
3155 push ax
3156 push cx
3157 push es
3158 push di
3160 mov cx, 10[bp] ; count
3161 cmp cx, #0x00
3162 je memsetb_end
3163 mov ax, 4[bp] ; segment
3164 mov es, ax
3165 mov ax, 6[bp] ; offset
3166 mov di, ax
3167 mov al, 8[bp] ; value
3170 stosb
3172 memsetb_end:
3173 pop di
3174 pop es
3175 pop cx
3176 pop ax
3178 pop bp
3179 ASM_END
3182 // --------------------------------------------------------------------------------------------
3183 static void memsetw(seg,offset,value,count)
3184 Bit16u seg;
3185 Bit16u offset;
3186 Bit16u value;
3187 Bit16u count;
3189 ASM_START
3190 push bp
3191 mov bp, sp
3193 push ax
3194 push cx
3195 push es
3196 push di
3198 mov cx, 10[bp] ; count
3199 cmp cx, #0x00
3200 je memsetw_end
3201 mov ax, 4[bp] ; segment
3202 mov es, ax
3203 mov ax, 6[bp] ; offset
3204 mov di, ax
3205 mov ax, 8[bp] ; value
3208 stosw
3210 memsetw_end:
3211 pop di
3212 pop es
3213 pop cx
3214 pop ax
3216 pop bp
3217 ASM_END
3220 // --------------------------------------------------------------------------------------------
3221 static void memcpyb(dseg,doffset,sseg,soffset,count)
3222 Bit16u dseg;
3223 Bit16u doffset;
3224 Bit16u sseg;
3225 Bit16u soffset;
3226 Bit16u count;
3228 ASM_START
3229 push bp
3230 mov bp, sp
3232 push ax
3233 push cx
3234 push es
3235 push di
3236 push ds
3237 push si
3239 mov cx, 12[bp] ; count
3240 cmp cx, #0x0000
3241 je memcpyb_end
3242 mov ax, 4[bp] ; dsegment
3243 mov es, ax
3244 mov ax, 6[bp] ; doffset
3245 mov di, ax
3246 mov ax, 8[bp] ; ssegment
3247 mov ds, ax
3248 mov ax, 10[bp] ; soffset
3249 mov si, ax
3252 movsb
3254 memcpyb_end:
3255 pop si
3256 pop ds
3257 pop di
3258 pop es
3259 pop cx
3260 pop ax
3262 pop bp
3263 ASM_END
3266 // --------------------------------------------------------------------------------------------
3267 static void memcpyw(dseg,doffset,sseg,soffset,count)
3268 Bit16u dseg;
3269 Bit16u doffset;
3270 Bit16u sseg;
3271 Bit16u soffset;
3272 Bit16u count;
3274 ASM_START
3275 push bp
3276 mov bp, sp
3278 push ax
3279 push cx
3280 push es
3281 push di
3282 push ds
3283 push si
3285 mov cx, 12[bp] ; count
3286 cmp cx, #0x0000
3287 je memcpyw_end
3288 mov ax, 4[bp] ; dsegment
3289 mov es, ax
3290 mov ax, 6[bp] ; doffset
3291 mov di, ax
3292 mov ax, 8[bp] ; ssegment
3293 mov ds, ax
3294 mov ax, 10[bp] ; soffset
3295 mov si, ax
3298 movsw
3300 memcpyw_end:
3301 pop si
3302 pop ds
3303 pop di
3304 pop es
3305 pop cx
3306 pop ax
3308 pop bp
3309 ASM_END
3312 /* =========================================================== */
3314 * These functions where ripped from Kevin's rombios.c
3316 /* =========================================================== */
3318 // --------------------------------------------------------------------------------------------
3319 static Bit8u
3320 read_byte(seg, offset)
3321 Bit16u seg;
3322 Bit16u offset;
3324 ASM_START
3325 push bp
3326 mov bp, sp
3328 push bx
3329 push ds
3330 mov ax, 4[bp] ; segment
3331 mov ds, ax
3332 mov bx, 6[bp] ; offset
3333 mov al, [bx]
3334 ;; al = return value (byte)
3335 pop ds
3336 pop bx
3338 pop bp
3339 ASM_END
3342 // --------------------------------------------------------------------------------------------
3343 static Bit16u
3344 read_word(seg, offset)
3345 Bit16u seg;
3346 Bit16u offset;
3348 ASM_START
3349 push bp
3350 mov bp, sp
3352 push bx
3353 push ds
3354 mov ax, 4[bp] ; segment
3355 mov ds, ax
3356 mov bx, 6[bp] ; offset
3357 mov ax, [bx]
3358 ;; ax = return value (word)
3359 pop ds
3360 pop bx
3362 pop bp
3363 ASM_END
3366 // --------------------------------------------------------------------------------------------
3367 static void
3368 write_byte(seg, offset, data)
3369 Bit16u seg;
3370 Bit16u offset;
3371 Bit8u data;
3373 ASM_START
3374 push bp
3375 mov bp, sp
3377 push ax
3378 push bx
3379 push ds
3380 mov ax, 4[bp] ; segment
3381 mov ds, ax
3382 mov bx, 6[bp] ; offset
3383 mov al, 8[bp] ; data byte
3384 mov [bx], al ; write data byte
3385 pop ds
3386 pop bx
3387 pop ax
3389 pop bp
3390 ASM_END
3393 // --------------------------------------------------------------------------------------------
3394 static void
3395 write_word(seg, offset, data)
3396 Bit16u seg;
3397 Bit16u offset;
3398 Bit16u data;
3400 ASM_START
3401 push bp
3402 mov bp, sp
3404 push ax
3405 push bx
3406 push ds
3407 mov ax, 4[bp] ; segment
3408 mov ds, ax
3409 mov bx, 6[bp] ; offset
3410 mov ax, 8[bp] ; data word
3411 mov [bx], ax ; write data word
3412 pop ds
3413 pop bx
3414 pop ax
3416 pop bp
3417 ASM_END
3420 // --------------------------------------------------------------------------------------------
3421 Bit8u
3422 inb(port)
3423 Bit16u port;
3425 ASM_START
3426 push bp
3427 mov bp, sp
3429 push dx
3430 mov dx, 4[bp]
3431 in al, dx
3432 pop dx
3434 pop bp
3435 ASM_END
3438 Bit16u
3439 inw(port)
3440 Bit16u port;
3442 ASM_START
3443 push bp
3444 mov bp, sp
3446 push dx
3447 mov dx, 4[bp]
3448 in ax, dx
3449 pop dx
3451 pop bp
3452 ASM_END
3455 // --------------------------------------------------------------------------------------------
3456 void
3457 outb(port, val)
3458 Bit16u port;
3459 Bit8u val;
3461 ASM_START
3462 push bp
3463 mov bp, sp
3465 push ax
3466 push dx
3467 mov dx, 4[bp]
3468 mov al, 6[bp]
3469 out dx, al
3470 pop dx
3471 pop ax
3473 pop bp
3474 ASM_END
3477 // --------------------------------------------------------------------------------------------
3478 void
3479 outw(port, val)
3480 Bit16u port;
3481 Bit16u val;
3483 ASM_START
3484 push bp
3485 mov bp, sp
3487 push ax
3488 push dx
3489 mov dx, 4[bp]
3490 mov ax, 6[bp]
3491 out dx, ax
3492 pop dx
3493 pop ax
3495 pop bp
3496 ASM_END
3499 Bit16u get_SS()
3501 ASM_START
3502 mov ax, ss
3503 ASM_END
3506 #ifdef DEBUG
3507 void unimplemented()
3509 printf("--> Unimplemented\n");
3512 void unknown()
3514 printf("--> Unknown int10\n");
3516 #endif
3518 // --------------------------------------------------------------------------------------------
3519 void printf(s)
3520 Bit8u *s;
3522 Bit8u c, format_char;
3523 Boolean in_format;
3524 unsigned format_width, i;
3525 Bit16u *arg_ptr;
3526 Bit16u arg_seg, arg, digit, nibble, shift_count;
3528 arg_ptr = &s;
3529 arg_seg = get_SS();
3531 in_format = 0;
3532 format_width = 0;
3534 while (c = read_byte(0xc000, s)) {
3535 if ( c == '%' ) {
3536 in_format = 1;
3537 format_width = 0;
3539 else if (in_format) {
3540 if ( (c>='0') && (c<='9') ) {
3541 format_width = (format_width * 10) + (c - '0');
3543 else if (c == 'x') {
3544 arg_ptr++; // increment to next arg
3545 arg = read_word(arg_seg, arg_ptr);
3546 if (format_width == 0)
3547 format_width = 4;
3548 i = 0;
3549 digit = format_width - 1;
3550 for (i=0; i<format_width; i++) {
3551 nibble = (arg >> (4 * digit)) & 0x000f;
3552 if (nibble <= 9)
3553 outb(0x0500, nibble + '0');
3554 else
3555 outb(0x0500, (nibble - 10) + 'A');
3556 digit--;
3558 in_format = 0;
3560 //else if (c == 'd') {
3561 // in_format = 0;
3562 // }
3564 else {
3565 outb(0x0500, c);
3567 s ++;
3571 #ifdef VBE
3572 #include "vbe.c"
3573 #endif
3575 #ifdef CIRRUS
3576 #include "clext.c"
3577 #endif
3579 // --------------------------------------------------------------------------------------------
3581 ASM_START
3582 ;; DATA_SEG_DEFS_HERE
3583 ASM_END
3585 ASM_START
3586 .ascii "vgabios ends here"
3587 .byte 0x00
3588 vgabios_end:
3589 .byte 0xCB
3590 ;; BLOCK_STRINGS_BEGIN
3591 ASM_END