- VBE init code and some dispi ioport functions rewritten in assembler
[vgabios.git] / vgabios.c
blob36c57b13cadc595a311373099045552941fd5dd9
1 // ============================================================================================
2 /*
3 * vgabios.c
4 */
5 // ============================================================================================
6 //
7 // Copyright (C) 2001,2002 the LGPL VGABios developers Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // ============================================================================================
24 //
25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26 // You can NOT drive any physical vga card with it.
27 //
28 // ============================================================================================
29 //
30 // This file contains code ripped from :
31 // - rombios.c of plex86
33 // This VGA Bios contains fonts from :
34 // - fntcol16.zip (c) by Joseph Gil avalable at :
35 // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
36 // These fonts are public domain
38 // This VGA Bios is based on information taken from :
39 // - Kevin Lawton's vga card emulation for bochs/plex86
40 // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
41 // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
42 // - Michael Abrash's Graphics Programming Black Book
43 // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
44 // - DOSEMU 1.0.1 source code for several tables values and formulas
46 // Thanks for patches, comments and ideas to :
47 // - techt@pikeonline.net
49 // ============================================================================================
51 #include "vgabios.h"
53 #ifdef VBE
54 #include "vbe.h"
55 #endif
57 /* Declares */
58 static Bit8u read_byte();
59 static Bit16u read_word();
60 static void write_byte();
61 static void write_word();
62 static Bit8u inb();
63 static Bit16u inw();
64 static void outb();
65 static void outw();
67 static Bit16u get_SS();
69 // Output
70 static void printf();
71 static void unimplemented();
72 static void unknown();
74 static Bit8u find_vga_entry();
76 static void memsetb();
77 static void memsetw();
78 static void memcpyb();
79 static void memcpyw();
81 static void biosfn_set_video_mode();
82 static void biosfn_set_cursor_shape();
83 static void biosfn_set_cursor_pos();
84 static void biosfn_get_cursor_pos();
85 static void biosfn_set_active_page();
86 static void biosfn_scroll();
87 static void biosfn_read_char_attr();
88 static void biosfn_write_char_attr();
89 static void biosfn_write_char_only();
90 static void biosfn_write_pixel();
91 static void biosfn_read_pixel();
92 static void biosfn_write_teletype();
93 static void biosfn_perform_gray_scale_summing();
94 static void biosfn_load_text_user_pat();
95 static void biosfn_load_text_8_14_pat();
96 static void biosfn_load_text_8_8_pat();
97 static void biosfn_load_text_8_16_pat();
98 static void biosfn_load_gfx_8_8_chars();
99 static void biosfn_load_gfx_user_chars();
100 static void biosfn_load_gfx_8_14_chars();
101 static void biosfn_load_gfx_8_8_dd_chars();
102 static void biosfn_load_gfx_8_16_chars();
103 static void biosfn_get_font_info();
104 static void biosfn_alternate_prtsc();
105 static void biosfn_select_vert_res();
106 static void biosfn_switch_video_interface();
107 static void biosfn_enable_video_refresh_control();
108 static void biosfn_write_string();
109 static void biosfn_read_state_info();
110 static void biosfn_read_video_state_size();
111 static void biosfn_save_video_state();
112 static void biosfn_restore_video_state();
114 // This is for compiling with gcc2 and gcc3
115 #define ASM_START #asm
116 #define ASM_END #endasm
118 ASM_START
120 MACRO SET_INT_VECTOR
121 push ds
122 xor ax, ax
123 mov ds, ax
124 mov ax, ?3
125 mov ?1*4, ax
126 mov ax, ?2
127 mov ?1*4+2, ax
128 pop ds
129 MEND
131 ASM_END
133 ASM_START
134 .text
135 .rom
136 .org 0
138 use16 386
140 vgabios_start:
141 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
143 .byte 0x40 /* BIOS extension length in units of 512 bytes */
146 vgabios_entry_point:
148 jmp vgabios_init_func
150 vgabios_name:
151 .ascii "Plex86/Bochs VGABios"
152 .ascii " "
153 .byte 0x00
155 // Info from Bart Oldeman
156 .org 0x1e
157 .ascii "IBM"
158 .byte 0x00
160 vgabios_version:
161 #ifndef VGABIOS_VERS
162 .ascii "current-cvs"
163 #else
164 .ascii VGABIOS_VERS
165 #endif
166 .ascii " "
168 vgabios_date:
169 .ascii VGABIOS_DATE
170 .byte 0x0a,0x0d
171 .byte 0x00
173 vgabios_copyright:
174 .ascii "(C) 2003 the LGPL VGABios developers Team"
175 .byte 0x0a,0x0d
176 .byte 0x00
178 vgabios_license:
179 .ascii "This VGA/VBE Bios is released under the GNU LGPL"
180 .byte 0x0a,0x0d
181 .byte 0x0a,0x0d
182 .byte 0x00
184 vgabios_website:
185 .ascii "Please visit :"
186 .byte 0x0a,0x0d
187 ;;.ascii " . http://www.plex86.org"
188 ;;.byte 0x0a,0x0d
189 .ascii " . http://bochs.sourceforge.net"
190 .byte 0x0a,0x0d
191 .ascii " . http://www.nongnu.org/vgabios"
192 .byte 0x0a,0x0d
193 .byte 0x0a,0x0d
194 .byte 0x00
197 ;; ============================================================================================
199 ;; Init Entry point
201 ;; ============================================================================================
202 vgabios_init_func:
204 ;; init vga card
205 call init_vga_card
207 ;; init basic bios vars
208 call init_bios_area
210 #ifdef VBE
211 ;; init vbe functions
212 call vbe_init
213 #endif
215 ;; set int10 vect
216 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
218 ;; display splash screen
219 call _display_splash_screen
221 ;; init video mode and clear the screen
222 mov ax,#0x0003
223 int #0x10
225 ;; show info
226 call _display_info
228 #ifdef VBE
229 ;; show vbe info
230 call vbe_display_info
231 #endif
234 retf
235 ASM_END
238 * int10 handled here
240 ASM_START
241 vgabios_int10_handler:
242 pushf
243 #ifdef DEBUG
244 push es
245 push ds
246 pusha
247 mov bx, #0xc000
248 mov ds, bx
249 call _int10_debugmsg
250 popa
251 pop ds
252 pop es
253 #endif
254 cmp ah, #0x0f
255 jne int10_test_1A
256 call biosfn_get_video_mode
257 jmp int10_end
258 int10_test_1A:
259 cmp ah, #0x1a
260 jne int10_test_0B
261 call biosfn_group_1A
262 jmp int10_end
263 int10_test_0B:
264 cmp ah, #0x0b
265 jne int10_test_1103
266 call biosfn_group_0B
267 jmp int10_end
268 int10_test_1103:
269 cmp ax, #0x1103
270 jne int10_test_12
271 call biosfn_set_text_block_specifier
272 jmp int10_end
273 int10_test_12:
274 cmp ah, #0x12
275 jne int10_test_101B
276 cmp bl, #0x10
277 jne int10_test_BL31
278 call biosfn_get_ega_info
279 jmp int10_end
280 int10_test_BL31:
281 cmp bl, #0x31
282 jne int10_test_BL32
283 call biosfn_enable_default_palette_loading
284 jmp int10_end
285 int10_test_BL32:
286 cmp bl, #0x32
287 jne int10_test_BL33
288 call biosfn_enable_video_addressing
289 jmp int10_end
290 int10_test_BL33:
291 cmp bl, #0x33
292 jne int10_test_BL34
293 call biosfn_enable_grayscale_summing
294 jmp int10_end
295 int10_test_BL34:
296 cmp bl, #0x34
297 jne int10_normal
298 call biosfn_enable_cursor_emulation
299 jmp int10_end
300 int10_test_101B:
301 cmp ax, #0x101b
302 je int10_normal
303 cmp ah, #0x10
304 #ifndef VBE
305 jne int10_normal
306 #else
307 jne int10_test_4F
308 #endif
309 call biosfn_group_10
310 jmp int10_end
311 #ifdef VBE
312 int10_test_4F:
313 cmp ah, #0x4f
314 jne int10_normal
315 cmp al, #0x03
316 jne int10_test_vbe_05
317 call vbe_biosfn_return_current_mode
318 jmp int10_end
319 int10_test_vbe_05:
320 cmp al, #0x05
321 jne int10_test_vbe_06
322 call vbe_biosfn_display_window_control
323 jmp int10_end
324 int10_test_vbe_06:
325 cmp al, #0x06
326 jne int10_test_vbe_07
327 call vbe_biosfn_set_get_logical_scan_line_length
328 jmp int10_end
329 int10_test_vbe_07:
330 cmp al, #0x07
331 jne int10_test_vbe_08
332 call vbe_biosfn_set_get_display_start
333 jmp int10_end
334 int10_test_vbe_08:
335 cmp al, #0x08
336 jne int10_normal
337 call vbe_biosfn_set_get_dac_palette_format
338 jmp int10_end
339 #endif
341 int10_normal:
342 push es
343 push ds
344 pusha
346 ;; We have to set ds to access the right data segment
347 mov bx, #0xc000
348 mov ds, bx
349 call _int10_func
351 popa
352 pop ds
353 pop es
354 int10_end:
355 popf
356 iret
357 ASM_END
359 #include "vgatables.h"
360 #include "vgafonts.h"
363 * Boot time harware inits
365 ASM_START
366 init_vga_card:
367 ;; switch to color mode and enable CPU access 480 lines
368 mov dx, #0x3C2
369 mov al, #0xC3
370 outb dx,al
372 ;; more than 64k 3C4/04
373 mov dx, #0x3C4
374 mov al, #0x04
375 outb dx,al
376 mov dx, #0x3C5
377 mov al, #0x02
378 outb dx,al
380 mov bx, #msg_vga_init
381 push bx
382 call _printf
383 inc sp
384 inc sp
387 msg_vga_init:
388 .ascii "VGABios $Id$"
389 .byte 0x0d,0x0a,0x00
390 ASM_END
392 // --------------------------------------------------------------------------------------------
394 * Boot time bios area inits
396 ASM_START
397 init_bios_area:
398 push ds
399 mov ax, # BIOSMEM_SEG
400 mov ds, ax
402 ;; init detected hardware BIOS Area
403 mov bx, # BIOSMEM_INITIAL_MODE
404 mov ax, [bx]
405 and ax, #0xffcf
406 mov [bx], ax
408 ;; Just for the first int10 find its children
410 ;; the default char height
411 mov bx, # BIOSMEM_CHAR_HEIGHT
412 mov al, #0x10
413 mov [bx], al
415 ;; Clear the screen
416 mov bx, # BIOSMEM_VIDEO_CTL
417 mov al, #0x60
418 mov [bx], al
420 ;; Set the basic screen we have
421 mov bx, # BIOSMEM_SWITCHES
422 mov al, #0xf9
423 mov [bx], al
425 ;; Set the basic modeset options
426 mov bx, # BIOSMEM_MODESET_CTL
427 mov al, #0x51
428 mov [bx], al
430 ;; Set the default MSR
431 mov bx, # BIOSMEM_CURRENT_MSR
432 mov al, #0x09
433 mov [bx], al
435 pop ds
437 ASM_END
439 // --------------------------------------------------------------------------------------------
441 * Boot time Splash screen
443 static void display_splash_screen()
447 // --------------------------------------------------------------------------------------------
449 * Tell who we are
452 static void display_info()
454 ASM_START
455 mov ax,#0xc000
456 mov ds,ax
457 mov si,#vgabios_name
458 call _display_string
459 mov si,#vgabios_version
460 call _display_string
462 ;;mov si,#vgabios_copyright
463 ;;call _display_string
464 ;;mov si,#crlf
465 ;;call _display_string
467 mov si,#vgabios_license
468 call _display_string
469 mov si,#vgabios_website
470 call _display_string
471 ASM_END
474 static void display_string()
476 // Get length of string
477 ASM_START
478 mov ax,ds
479 mov es,ax
480 mov di,si
481 xor cx,cx
482 not cx
483 xor al,al
485 repne
486 scasb
487 not cx
488 dec cx
489 push cx
491 mov ax,#0x0300
492 mov bx,#0x0000
493 int #0x10
495 pop cx
496 mov ax,#0x1301
497 mov bx,#0x000b
498 mov bp,si
499 int #0x10
500 ASM_END
503 // --------------------------------------------------------------------------------------------
504 #ifdef DEBUG
505 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
506 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
508 // 0E is write char...
509 if(GET_AH()!=0x0E)
510 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX);
512 #endif
514 // --------------------------------------------------------------------------------------------
516 * int10 main dispatcher
518 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
519 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS;
522 // BIOS functions
523 switch(GET_AH())
525 case 0x00:
526 biosfn_set_video_mode(GET_AL());
527 switch(GET_AL()&0x7F)
528 {case 6:
529 SET_AL(0x3F);
530 break;
531 case 0:
532 case 1:
533 case 2:
534 case 3:
535 case 4:
536 case 5:
537 case 7:
538 SET_AL(0x30);
539 break;
540 default:
541 SET_AL(0x20);
543 break;
544 case 0x01:
545 biosfn_set_cursor_shape(GET_CH(),GET_CL());
546 break;
547 case 0x02:
548 biosfn_set_cursor_pos(GET_BH(),DX);
549 break;
550 case 0x03:
551 biosfn_get_cursor_pos(GET_BH(),&CX,&DX);
552 break;
553 case 0x04:
554 // Read light pen pos (unimplemented)
555 #ifdef DEBUG
556 unimplemented();
557 #endif
558 AX=0x00;
559 BX=0x00;
560 CX=0x00;
561 DX=0x00;
562 break;
563 case 0x05:
564 biosfn_set_active_page(GET_AL());
565 break;
566 case 0x06:
567 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
568 break;
569 case 0x07:
570 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
571 break;
572 case 0x08:
573 biosfn_read_char_attr(GET_BH(),&AX);
574 break;
575 case 0x09:
576 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
577 break;
578 case 0x0A:
579 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
580 break;
581 case 0x0C:
582 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
583 break;
584 case 0x0D:
585 biosfn_read_pixel(GET_BH(),CX,DX,&AX);
586 break;
587 case 0x0E:
588 // Ralf Brown Interrupt list is WRONG on bh(page)
589 // We do output only on the current page !
590 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
591 break;
592 case 0x10:
593 // All other functions of group AH=0x10 rewritten in assembler
594 biosfn_perform_gray_scale_summing(BX,CX);
595 break;
596 case 0x11:
597 switch(GET_AL())
599 case 0x00:
600 case 0x10:
601 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
602 break;
603 case 0x01:
604 case 0x11:
605 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
606 break;
607 case 0x02:
608 case 0x12:
609 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
610 break;
611 case 0x04:
612 case 0x14:
613 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
614 break;
615 case 0x20:
616 biosfn_load_gfx_8_8_chars(ES,BP);
617 break;
618 case 0x21:
619 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
620 break;
621 case 0x22:
622 biosfn_load_gfx_8_14_chars(GET_BL());
623 break;
624 case 0x23:
625 biosfn_load_gfx_8_8_dd_chars(GET_BL());
626 break;
627 case 0x24:
628 biosfn_load_gfx_8_16_chars(GET_BL());
629 break;
630 case 0x30:
631 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX);
632 break;
633 #ifdef DEBUG
634 default:
635 unknown();
636 #endif
639 break;
640 case 0x12:
641 switch(GET_BL())
643 case 0x20:
644 biosfn_alternate_prtsc();
645 break;
646 case 0x30:
647 biosfn_select_vert_res(GET_AL());
648 SET_AL(0x12);
649 break;
650 case 0x35:
651 biosfn_switch_video_interface(GET_AL(),ES,DX);
652 SET_AL(0x12);
653 break;
654 case 0x36:
655 biosfn_enable_video_refresh_control(GET_AL());
656 SET_AL(0x12);
657 break;
658 #ifdef DEBUG
659 default:
660 unknown();
661 #endif
663 break;
664 case 0x13:
665 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
666 break;
667 case 0x1B:
668 biosfn_read_state_info(BX,ES,DI);
669 SET_AL(0x1B);
670 break;
671 case 0x1C:
672 switch(GET_AL())
674 case 0x00:
675 biosfn_read_video_state_size(CX,&BX);
676 break;
677 case 0x01:
678 biosfn_save_video_state(CX,ES,BX);
679 break;
680 case 0x02:
681 biosfn_restore_video_state(CX,ES,BX);
682 break;
683 #ifdef DEBUG
684 default:
685 unknown();
686 #endif
688 SET_AL(0x1C);
689 break;
691 #ifdef VBE
692 case 0x4f:
693 if (vbe_has_vbe_display()) {
694 switch(GET_AL())
696 case 0x00:
697 vbe_biosfn_return_controller_information(&AX,ES,DI);
698 break;
699 case 0x01:
700 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
701 break;
702 case 0x02:
703 vbe_biosfn_set_mode(&AX,BX,ES,DI);
704 break;
705 case 0x04:
706 //FIXME
707 #ifdef DEBUG
708 unimplemented();
709 #endif
710 // function failed
711 AX=0x100;
712 break;
713 case 0x09:
714 //FIXME
715 #ifdef DEBUG
716 unimplemented();
717 #endif
718 // function failed
719 AX=0x100;
720 break;
721 case 0x0A:
722 //FIXME
723 #ifdef DEBUG
724 unimplemented();
725 #endif
726 // function failed
727 AX=0x100;
728 break;
729 #ifdef DEBUG
730 default:
731 unknown();
732 #endif
733 // function failed
734 AX=0x100;
737 else {
738 // No VBE display
739 AX=0x0100;
741 break;
742 #endif
744 #ifdef DEBUG
745 default:
746 unknown();
747 #endif
751 // ============================================================================================
753 // BIOS functions
755 // ============================================================================================
757 static void biosfn_set_video_mode(mode) Bit8u mode;
758 {// mode: Bit 7 is 1 if no clear screen
760 // Should we clear the screen ?
761 Bit8u noclearmem=mode&0x80;
762 Bit8u line,mmask,*palette;
763 Bit16u i,twidth,theight,cheight;
764 Bit8u modeset_ctl,video_ctl,vga_switches;
765 Bit16u crtc_addr;
767 #ifdef VBE
768 if (vbe_has_vbe_display()) {
769 dispi_set_enable(VBE_DISPI_DISABLED);
771 #endif // def VBE
773 // The real mode
774 mode=mode&0x7f;
776 // find the entry in the video modes
777 line=find_vga_entry(mode);
779 #ifdef DEBUG
780 printf("mode search %02x found line %02x\n",mode,line);
781 #endif
783 if(line==0xFF)
784 return;
786 twidth=vga_modes[line].twidth;
787 theight=vga_modes[line].theight;
788 cheight=vga_modes[line].cheight;
790 // Read the bios vga control
791 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
793 // Read the bios vga switches
794 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
796 // Read the bios mode set control
797 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
799 // Then we know the number of lines
800 // FIXME
802 // if palette loading (bit 3 of modeset ctl = 0)
803 if((modeset_ctl&0x08)==0)
804 {// Set the PEL mask
805 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
807 // Set the whole dac always, from 0
808 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
810 // From which palette
811 switch(vga_modes[line].dacmodel)
812 {case 0:
813 palette=&palette0;
814 break;
815 case 1:
816 palette=&palette1;
817 break;
818 case 2:
819 palette=&palette2;
820 break;
821 case 3:
822 palette=&palette3;
823 break;
825 // Always 256*3 values
826 for(i=0;i<0x0100;i++)
827 {if(i<=dac_regs[vga_modes[line].dacmodel])
828 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
829 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
830 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
832 else
833 {outb(VGAREG_DAC_DATA,0);
834 outb(VGAREG_DAC_DATA,0);
835 outb(VGAREG_DAC_DATA,0);
838 if((modeset_ctl&0x02)==0x02)
840 biosfn_perform_gray_scale_summing(0x00, 0x100);
844 // Reset Attribute Ctl flip-flop
845 inb(VGAREG_ACTL_RESET);
847 // Set Attribute Ctl
848 for(i=0;i<=ACTL_MAX_REG;i++)
849 {outb(VGAREG_ACTL_ADDRESS,i);
850 outb(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
853 // Set Sequencer Ctl
854 for(i=0;i<=SEQU_MAX_REG;i++)
855 {outb(VGAREG_SEQU_ADDRESS,i);
856 outb(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
859 // Set Grafx Ctl
860 for(i=0;i<=GRDC_MAX_REG;i++)
861 {outb(VGAREG_GRDC_ADDRESS,i);
862 outb(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
865 // Set CRTC address VGA or MDA
866 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
868 // Set CRTC regs
869 for(i=0;i<=CRTC_MAX_REG;i++)
870 {outb(crtc_addr,i);
871 outb(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
874 // Set the misc register
875 outb(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
877 // Enable video
878 outb(VGAREG_ACTL_ADDRESS,0x20);
879 inb(VGAREG_ACTL_RESET);
881 if(noclearmem==0x00)
883 if(vga_modes[line].class==TEXT)
885 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
887 else
889 if(mode<0x0d)
891 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
893 else
895 outb( VGAREG_SEQU_ADDRESS, 0x02 );
896 mmask = inb( VGAREG_SEQU_DATA );
897 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
898 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
899 outb( VGAREG_SEQU_DATA, mmask );
904 // Set the BIOS mem
905 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
906 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
907 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength);
908 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
909 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1);
910 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
911 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
912 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
913 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
915 // FIXME We nearly have the good tables. to be reworked
916 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
917 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00);
918 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00);
920 // FIXME
921 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but...
922 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but...
924 // Set cursor shape
925 if(vga_modes[line].class==TEXT)
927 biosfn_set_cursor_shape(0x06,0x07);
930 // Set cursor pos for page 0..7
931 for(i=0;i<8;i++)
932 biosfn_set_cursor_pos(i,0x0000);
934 // Set active page 0
935 biosfn_set_active_page(0x00);
937 // Write the fonts in memory
938 if(vga_modes[line].class==TEXT)
940 ASM_START
941 ;; copy and activate 8x16 font
942 mov ax, #0x1104
943 mov bl, #0x00
944 int #0x10
945 mov ax, #0x1103
946 mov bl, #0x00
947 int #0x10
948 ASM_END
951 // Set the ints 0x1F and 0x43
952 ASM_START
953 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8)
954 ASM_END
956 switch(cheight)
957 {case 8:
958 ASM_START
959 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8)
960 ASM_END
961 break;
962 case 14:
963 ASM_START
964 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14)
965 ASM_END
966 break;
967 case 16:
968 ASM_START
969 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16)
970 ASM_END
971 break;
975 // --------------------------------------------------------------------------------------------
976 static void biosfn_set_cursor_shape (CH,CL)
977 Bit8u CH;Bit8u CL;
978 {Bit16u cheight,curs,crtc_addr;
979 Bit8u modeset_ctl;
981 CH&=0x3f;
982 CL&=0x1f;
984 curs=(CH<<8)+CL;
985 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs);
987 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
988 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
989 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20))
991 if(CL!=(CH+1))
993 CH = ((CH+1) * cheight / 8) -1;
995 else
997 CH = ((CL+1) * cheight / 8) - 2;
999 CL = ((CL+1) * cheight / 8) - 1;
1002 // CTRC regs 0x0a and 0x0b
1003 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1004 outb(crtc_addr,0x0a);
1005 outb(crtc_addr+1,CH);
1006 outb(crtc_addr,0x0b);
1007 outb(crtc_addr+1,CL);
1010 // --------------------------------------------------------------------------------------------
1011 static void biosfn_set_cursor_pos (page, cursor)
1012 Bit8u page;Bit16u cursor;
1014 Bit8u xcurs,ycurs,current;
1015 Bit16u nbcols,nbrows,address,crtc_addr;
1017 // Should not happen...
1018 if(page>7)return;
1020 // Bios cursor pos
1021 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
1023 // Set the hardware cursor
1024 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1025 if(page==current)
1027 // Get the dimensions
1028 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1029 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1031 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1033 // Calculate the address knowing nbcols nbrows and page num
1034 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
1036 // CRTC regs 0x0e and 0x0f
1037 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1038 outb(crtc_addr,0x0e);
1039 outb(crtc_addr+1,(address&0xff00)>>8);
1040 outb(crtc_addr,0x0f);
1041 outb(crtc_addr+1,address&0x00ff);
1045 // --------------------------------------------------------------------------------------------
1046 static void biosfn_get_cursor_pos (page,shape, pos)
1047 Bit8u page;Bit16u *shape;Bit16u *pos;
1049 Bit16u ss=get_SS();
1051 // Default
1052 write_word(ss, shape, 0);
1053 write_word(ss, pos, 0);
1055 if(page>7)return;
1056 // FIXME should handle VGA 14/16 lines
1057 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE));
1058 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2));
1061 // --------------------------------------------------------------------------------------------
1062 static void biosfn_set_active_page (page)
1063 Bit8u page;
1065 Bit16u cursor,dummy,crtc_addr;
1066 Bit16u nbcols,nbrows,address;
1067 Bit8u mode,line;
1069 if(page>7)return;
1071 // Get the mode
1072 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1073 line=find_vga_entry(mode);
1074 if(line==0xFF)return;
1076 // Get pos curs pos for the right page
1077 biosfn_get_cursor_pos(page,&dummy,&cursor);
1079 if(vga_modes[line].class==TEXT)
1081 // Get the dimensions
1082 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1083 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1085 // Calculate the address knowing nbcols nbrows and page num
1086 address=SCREEN_MEM_START(nbcols,nbrows,page);
1087 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
1089 // Start address
1090 address=SCREEN_IO_START(nbcols,nbrows,page);
1092 else
1094 address = page*vga_modes[line].slength;
1097 // CRTC regs 0x0c and 0x0d
1098 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1099 outb(crtc_addr,0x0c);
1100 outb(crtc_addr+1,(address&0xff00)>>8);
1101 outb(crtc_addr,0x0d);
1102 outb(crtc_addr+1,address&0x00ff);
1104 // And change the BIOS page
1105 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
1107 #ifdef DEBUG
1108 printf("Set active page %02x address %04x\n",page,address);
1109 #endif
1111 // Display the cursor, now the page is active
1112 biosfn_set_cursor_pos(page,cursor);
1115 // --------------------------------------------------------------------------------------------
1116 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight)
1117 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1119 Bit16u src,dest;
1120 Bit8u i;
1122 src=ysrc*cheight*nbcols+xstart;
1123 dest=ydest*cheight*nbcols+xstart;
1124 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1125 for(i=0;i<cheight;i++)
1127 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1129 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1132 // --------------------------------------------------------------------------------------------
1133 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight)
1134 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1136 Bit16u dest;
1137 Bit8u i;
1139 dest=ystart*cheight*nbcols+xstart;
1140 for(i=0;i<cheight;i++)
1142 memsetb(0xa000,dest+i*nbcols,0x00,cols);
1146 // --------------------------------------------------------------------------------------------
1147 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight)
1148 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight;
1150 Bit16u src,dest;
1151 Bit8u i;
1153 src=((ysrc*cheight*nbcols)>>1)+xstart;
1154 dest=((ydest*cheight*nbcols)>>1)+xstart;
1155 for(i=0;i<cheight;i++)
1157 if (i & 1)
1158 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols);
1159 else
1160 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols);
1164 // --------------------------------------------------------------------------------------------
1165 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr)
1166 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr;
1168 Bit16u dest;
1169 Bit8u i;
1171 dest=((ystart*cheight*nbcols)>>1)+xstart;
1172 for(i=0;i<cheight;i++)
1174 if (i & 1)
1175 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols);
1176 else
1177 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols);
1181 // --------------------------------------------------------------------------------------------
1182 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir)
1183 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir;
1185 // page == 0xFF if current
1187 Bit8u mode,line,cheight,bpp,cols;
1188 Bit16u nbcols,nbrows,i;
1189 Bit16u address;
1191 if(rul>rlr)return;
1192 if(cul>clr)return;
1194 // Get the mode
1195 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1196 line=find_vga_entry(mode);
1197 if(line==0xFF)return;
1199 // Get the dimensions
1200 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1201 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1203 // Get the current page
1204 if(page==0xFF)
1205 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1207 if(rlr>=nbrows)rlr=nbrows-1;
1208 if(clr>=nbcols)clr=nbcols-1;
1209 if(nblines>nbrows)nblines=0;
1210 cols=clr-cul+1;
1212 if(vga_modes[line].class==TEXT)
1214 // Compute the address
1215 address=SCREEN_MEM_START(nbcols,nbrows,page);
1216 #ifdef DEBUG
1217 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1218 #endif
1220 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1222 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols);
1224 else
1225 {// if Scroll up
1226 if(dir==SCROLL_UP)
1227 {for(i=rul;i<=rlr;i++)
1229 if((i+nblines>rlr)||(nblines==0))
1230 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1231 else
1232 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1235 else
1236 {for(i=rlr;i>=rul;i--)
1238 if((i<rul+nblines)||(nblines==0))
1239 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols);
1240 else
1241 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1246 else
1248 // FIXME gfx mode not complete
1249 cheight=vga_modes[line].cheight;
1250 switch(vga_modes[line].memmodel)
1252 case PLANAR4:
1253 case PLANAR1:
1254 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1256 memsetb(vga_modes[line].sstart,0,0x00,nbrows*nbcols*cheight);
1258 else
1259 {// if Scroll up
1260 if(dir==SCROLL_UP)
1261 {for(i=rul;i<=rlr;i++)
1263 if((i+nblines>rlr)||(nblines==0))
1264 vgamem_fill_pl4(cul,i,cols,nbcols,cheight);
1265 else
1266 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1269 else
1270 {for(i=rlr;i>=rul;i--)
1272 if((i<rul+nblines)||(nblines==0))
1273 vgamem_fill_pl4(cul,i,cols,nbcols,cheight);
1274 else
1275 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight);
1279 break;
1280 case CGA:
1281 bpp=vga_modes[line].pixbits;
1282 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1284 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1286 else
1288 if(bpp==2)
1290 cul<<=1;
1291 cols<<=1;
1292 nbcols<<=1;
1294 // if Scroll up
1295 if(dir==SCROLL_UP)
1296 {for(i=rul;i<=rlr;i++)
1298 if((i+nblines>rlr)||(nblines==0))
1299 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1300 else
1301 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1304 else
1305 {for(i=rlr;i>=rul;i--)
1307 if((i<rul+nblines)||(nblines==0))
1308 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1309 else
1310 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight);
1314 break;
1315 #ifdef DEBUG
1316 default:
1317 printf("Scroll in graphics mode ");
1318 unimplemented();
1319 #endif
1324 // --------------------------------------------------------------------------------------------
1325 static void biosfn_read_char_attr (page,car)
1326 Bit8u page;Bit16u *car;
1327 {Bit16u ss=get_SS();
1328 Bit8u xcurs,ycurs,mode,line;
1329 Bit16u nbcols,nbrows,address;
1330 Bit16u cursor,dummy;
1332 // Get the mode
1333 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1334 line=find_vga_entry(mode);
1335 if(line==0xFF)return;
1337 // Get the cursor pos for the page
1338 biosfn_get_cursor_pos(page,&dummy,&cursor);
1339 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1341 // Get the dimensions
1342 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1343 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1345 if(vga_modes[line].class==TEXT)
1347 // Compute the address
1348 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1350 write_word(ss,car,read_word(vga_modes[line].sstart,address));
1352 else
1354 // FIXME gfx mode
1355 #ifdef DEBUG
1356 unimplemented();
1357 #endif
1361 // --------------------------------------------------------------------------------------------
1362 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight)
1363 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight;
1365 Bit8u i,j,mask;
1366 Bit8u *fdata;
1367 Bit16u addr,dest,src;
1369 switch(cheight)
1370 {case 14:
1371 fdata = &vgafont14;
1372 break;
1373 case 16:
1374 fdata = &vgafont16;
1375 break;
1376 default:
1377 fdata = &vgafont8;
1379 addr=xcurs+ycurs*cheight*nbcols;
1380 src = car * cheight;
1381 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1382 if(attr&0x80)
1384 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1386 for(i=0;i<cheight;i++)
1388 dest=addr+i*nbcols;
1389 for(j=0;j<8;j++)
1391 mask=0x80>>j;
1392 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1393 read_byte(0xa000,dest);
1394 if(fdata[src+i]&mask)
1396 write_byte(0xa000,dest,attr&0x0f);
1398 else
1400 write_byte(0xa000,dest,0x00);
1404 ASM_START
1405 mov dx, # VGAREG_GRDC_ADDRESS
1406 mov ax, 0xff08
1407 out dx, ax
1408 mov ax, 0x0005
1409 out dx, ax
1410 mov ax, 0x0003
1411 out dx, ax
1412 ASM_END
1415 // --------------------------------------------------------------------------------------------
1416 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp)
1417 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp;
1419 Bit8u i,j,mask,data;
1420 Bit8u *fdata;
1421 Bit16u addr,dest,src;
1423 fdata = &vgafont8;
1424 addr=(xcurs*bpp)+ycurs*320;
1425 src = car * 8;
1426 for(i=0;i<8;i++)
1428 dest=addr+(i>>1)*80;
1429 if (i & 1) dest += 0x2000;
1430 mask = 0x80;
1431 if (bpp == 1)
1433 if (attr & 0x80)
1435 data = read_byte(0xb800,dest);
1437 else
1439 data = 0x00;
1441 for(j=0;j<8;j++)
1443 if (fdata[src+i] & mask)
1445 if (attr & 0x80)
1447 data ^= (attr & 0x01) << (7-j);
1449 else
1451 data |= (attr & 0x01) << (7-j);
1454 mask >>= 1;
1456 write_byte(0xb800,dest,data);
1458 else
1460 while (mask > 0)
1462 if (attr & 0x80)
1464 data = read_byte(0xb800,dest);
1466 else
1468 data = 0x00;
1470 for(j=0;j<4;j++)
1472 if (fdata[src+i] & mask)
1474 if (attr & 0x80)
1476 data ^= (attr & 0x03) << ((3-j)*2);
1478 else
1480 data |= (attr & 0x03) << ((3-j)*2);
1483 mask >>= 1;
1485 write_byte(0xb800,dest,data);
1486 dest += 1;
1492 // --------------------------------------------------------------------------------------------
1493 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols)
1494 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;
1496 Bit8u i,j,mask,data;
1497 Bit8u *fdata;
1498 Bit16u addr,dest,src;
1500 fdata = &vgafont8;
1501 addr=xcurs*8+ycurs*nbcols*64;
1502 src = car * 8;
1503 for(i=0;i<8;i++)
1505 dest=addr+i*nbcols*8;
1506 mask = 0x80;
1507 for(j=0;j<8;j++)
1509 data = 0x00;
1510 if (fdata[src+i] & mask)
1512 data = attr;
1514 write_byte(0xa000,dest+j,data);
1515 mask >>= 1;
1520 // --------------------------------------------------------------------------------------------
1521 static void biosfn_write_char_attr (car,page,attr,count)
1522 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1524 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1525 Bit16u nbcols,nbrows,address;
1526 Bit16u cursor,dummy;
1528 // Get the mode
1529 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1530 line=find_vga_entry(mode);
1531 if(line==0xFF)return;
1533 // Get the cursor pos for the page
1534 biosfn_get_cursor_pos(page,&dummy,&cursor);
1535 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1537 // Get the dimensions
1538 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1539 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1541 if(vga_modes[line].class==TEXT)
1543 // Compute the address
1544 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1546 dummy=((Bit16u)attr<<8)+car;
1547 memsetw(vga_modes[line].sstart,address,dummy,count);
1549 else
1551 // FIXME gfx mode not complete
1552 cheight=vga_modes[line].cheight;
1553 bpp=vga_modes[line].pixbits;
1554 while((count-->0) && (xcurs<nbcols))
1556 switch(vga_modes[line].memmodel)
1558 case PLANAR4:
1559 case PLANAR1:
1560 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1561 break;
1562 case CGA:
1563 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1564 break;
1565 case LINEAR8:
1566 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1567 break;
1568 #ifdef DEBUG
1569 default:
1570 unimplemented();
1571 #endif
1573 xcurs++;
1578 // --------------------------------------------------------------------------------------------
1579 static void biosfn_write_char_only (car,page,attr,count)
1580 Bit8u car;Bit8u page;Bit8u attr;Bit16u count;
1582 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1583 Bit16u nbcols,nbrows,address;
1584 Bit16u cursor,dummy;
1586 // Get the mode
1587 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1588 line=find_vga_entry(mode);
1589 if(line==0xFF)return;
1591 // Get the cursor pos for the page
1592 biosfn_get_cursor_pos(page,&dummy,&cursor);
1593 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1595 // Get the dimensions
1596 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1597 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1599 if(vga_modes[line].class==TEXT)
1601 // Compute the address
1602 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1604 while(count-->0)
1605 {write_byte(vga_modes[line].sstart,address,car);
1606 address+=2;
1609 else
1611 // FIXME gfx mode not complete
1612 cheight=vga_modes[line].cheight;
1613 bpp=vga_modes[line].pixbits;
1614 while((count-->0) && (xcurs<nbcols))
1616 switch(vga_modes[line].memmodel)
1618 case PLANAR4:
1619 case PLANAR1:
1620 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1621 break;
1622 case CGA:
1623 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1624 break;
1625 case LINEAR8:
1626 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1627 break;
1628 #ifdef DEBUG
1629 default:
1630 unimplemented();
1631 #endif
1633 xcurs++;
1638 // --------------------------------------------------------------------------------------------
1639 ASM_START
1640 biosfn_group_0B:
1641 cmp bh, #0x00
1642 je biosfn_set_border_color
1643 cmp bh, #0x01
1644 je biosfn_set_palette
1645 #ifdef DEBUG
1646 call _unknown
1647 #endif
1649 biosfn_set_border_color:
1650 push ax
1651 push bx
1652 push cx
1653 push dx
1654 mov dx, # VGAREG_ACTL_RESET
1655 in al, dx
1656 mov dx, # VGAREG_ACTL_ADDRESS
1657 mov al, #0x00
1658 out dx, al
1659 mov al, bl
1660 and al, #0x0f
1661 test al, #0x08
1662 jz set_low_border
1663 add al, #0x08
1664 set_low_border:
1665 out dx, al
1666 mov cl, #0x01
1667 and bl, #0x10
1668 set_intensity_loop:
1669 mov dx, # VGAREG_ACTL_ADDRESS
1670 mov al, cl
1671 out dx, al
1672 mov dx, # VGAREG_ACTL_READ_DATA
1673 in al, dx
1674 and al, #0xef
1675 or al, bl
1676 mov dx, # VGAREG_ACTL_ADDRESS
1677 out dx, al
1678 inc cl
1679 cmp cl, #0x04
1680 jne set_intensity_loop
1681 mov al, #0x20
1682 out dx, al
1683 pop dx
1684 pop cx
1685 pop bx
1686 pop ax
1688 biosfn_set_palette:
1689 push ax
1690 push bx
1691 push cx
1692 push dx
1693 mov dx, # VGAREG_ACTL_RESET
1694 in al, dx
1695 mov cl, #0x01
1696 and bl, #0x01
1697 set_cga_palette_loop:
1698 mov dx, # VGAREG_ACTL_ADDRESS
1699 mov al, cl
1700 out dx, al
1701 mov dx, # VGAREG_ACTL_READ_DATA
1702 in al, dx
1703 and al, #0xfe
1704 or al, bl
1705 mov dx, # VGAREG_ACTL_ADDRESS
1706 out dx, al
1707 inc cl
1708 cmp cl, #0x04
1709 jne set_cga_palette_loop
1710 mov al, #0x20
1711 out dx, al
1712 pop dx
1713 pop cx
1714 pop bx
1715 pop ax
1717 ASM_END
1719 // --------------------------------------------------------------------------------------------
1720 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX;
1722 Bit8u mode,line,mask,attr,data;
1723 Bit16u addr;
1725 // Get the mode
1726 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1727 line=find_vga_entry(mode);
1728 if(line==0xFF)return;
1729 if(vga_modes[line].class==TEXT)return;
1731 switch(vga_modes[line].memmodel)
1733 case PLANAR4:
1734 case PLANAR1:
1735 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1736 mask = 0x01 << (7 - (CX & 0x07));
1737 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1738 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1739 data = read_byte(0xa000,addr);
1740 if (AL & 0x80)
1742 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1744 write_byte(0xa000,addr,AL);
1745 outw(VGAREG_GRDC_ADDRESS, 0xff08);
1746 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1747 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1748 break;
1749 case CGA:
1750 if(vga_modes[line].pixbits==2)
1752 addr=(CX>>2)+(DX>>1)*80;
1754 else
1756 addr=(CX>>3)+(DX>>1)*80;
1758 if (DX & 1) addr += 0x2000;
1759 data = read_byte(0xb800,addr);
1760 if(vga_modes[line].pixbits==2)
1762 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1763 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1765 else
1767 attr = (AL & 0x01) << (7 - (CX & 0x07));
1768 mask = 0x01 << (7 - (CX & 0x07));
1770 if (AL & 0x80)
1772 data ^= attr;
1774 else
1776 data &= ~mask;
1777 data |= attr;
1779 write_byte(0xb800,addr,data);
1780 break;
1781 case LINEAR8:
1782 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1783 write_byte(0xa000,addr,AL);
1784 break;
1785 #ifdef DEBUG
1786 default:
1787 unimplemented();
1788 #endif
1792 // --------------------------------------------------------------------------------------------
1793 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX;
1795 Bit8u mode,line,mask,attr,data,i;
1796 Bit16u addr;
1797 Bit16u ss=get_SS();
1799 // Get the mode
1800 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1801 line=find_vga_entry(mode);
1802 if(line==0xFF)return;
1803 if(vga_modes[line].class==TEXT)return;
1805 switch(vga_modes[line].memmodel)
1807 case PLANAR4:
1808 case PLANAR1:
1809 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1810 mask = 0x01 << (7 - (CX & 0x07));
1811 attr = 0x00;
1812 for(i=0;i<4;i++)
1814 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
1815 data = read_byte(0xa000,addr) & mask;
1816 if (data > 0) attr |= (0x01 << i);
1818 break;
1819 case CGA:
1820 addr=(CX>>2)+(DX>>1)*80;
1821 if (DX & 1) addr += 0x2000;
1822 data = read_byte(0xb800,addr);
1823 if(vga_modes[line].pixbits==2)
1825 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03;
1827 else
1829 attr = (data >> (7 - (CX & 0x07))) & 0x01;
1831 break;
1832 case LINEAR8:
1833 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1834 attr=read_byte(0xa000,addr);
1835 break;
1836 default:
1837 #ifdef DEBUG
1838 unimplemented();
1839 #endif
1840 attr = 0;
1842 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr);
1845 // --------------------------------------------------------------------------------------------
1846 static void biosfn_write_teletype (car, page, attr, flag)
1847 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1848 {// flag = WITH_ATTR / NO_ATTR
1850 Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1851 Bit16u nbcols,nbrows,address;
1852 Bit16u cursor,dummy;
1854 // special case if page is 0xff, use current page
1855 if(page==0xff)
1856 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1858 // Get the mode
1859 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1860 line=find_vga_entry(mode);
1861 if(line==0xFF)return;
1863 // Get the cursor pos for the page
1864 biosfn_get_cursor_pos(page,&dummy,&cursor);
1865 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1867 // Get the dimensions
1868 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1869 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1871 switch(car)
1873 case 7:
1874 //FIXME should beep
1875 break;
1877 case 8:
1878 if(xcurs>0)xcurs--;
1879 break;
1881 case '\r':
1882 xcurs=0;
1883 break;
1885 case '\n':
1886 xcurs=0;
1887 ycurs++;
1888 break;
1890 case '\t':
1893 biosfn_write_teletype(' ',page,attr,flag);
1894 biosfn_get_cursor_pos(page,&dummy,&cursor);
1895 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1896 }while(xcurs%8==0);
1897 break;
1899 default:
1901 if(vga_modes[line].class==TEXT)
1903 // Compute the address
1904 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1906 // Write the char
1907 write_byte(vga_modes[line].sstart,address,car);
1909 if(flag==WITH_ATTR)
1910 write_byte(vga_modes[line].sstart,address+1,attr);
1912 else
1914 // FIXME gfx mode not complete
1915 cheight=vga_modes[line].cheight;
1916 bpp=vga_modes[line].pixbits;
1917 switch(vga_modes[line].memmodel)
1919 case PLANAR4:
1920 case PLANAR1:
1921 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
1922 break;
1923 case CGA:
1924 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1925 break;
1926 case LINEAR8:
1927 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1928 break;
1929 #ifdef DEBUG
1930 default:
1931 unimplemented();
1932 #endif
1935 xcurs++;
1938 // Do we need to wrap ?
1939 if(xcurs==nbcols)
1940 {xcurs=0;
1941 ycurs++;
1944 // Do we need to scroll ?
1945 if(ycurs==nbrows)
1947 if(vga_modes[line].class==TEXT)
1949 biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1951 else
1953 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1955 ycurs-=1;
1958 // Set the cursor for the page
1959 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1960 biosfn_set_cursor_pos(page,cursor);
1963 // --------------------------------------------------------------------------------------------
1964 ASM_START
1965 biosfn_get_video_mode:
1966 push ds
1967 mov ax, # BIOSMEM_SEG
1968 mov ds, ax
1969 push bx
1970 mov bx, # BIOSMEM_CURRENT_PAGE
1971 mov al, [bx]
1972 pop bx
1973 mov bh, al
1974 push bx
1975 mov bx, # BIOSMEM_VIDEO_CTL
1976 mov ah, [bx]
1977 and ah, #0x80
1978 mov bx, # BIOSMEM_CURRENT_MODE
1979 mov al, [bx]
1980 or al, ah
1981 mov bx, # BIOSMEM_NB_COLS
1982 mov ah, [bx]
1983 pop bx
1984 pop ds
1986 ASM_END
1988 // --------------------------------------------------------------------------------------------
1989 ASM_START
1990 biosfn_group_10:
1991 cmp al, #0x00
1992 jne int10_test_1001
1993 jmp biosfn_set_single_palette_reg
1994 int10_test_1001:
1995 cmp al, #0x01
1996 jne int10_test_1002
1997 jmp biosfn_set_overscan_border_color
1998 int10_test_1002:
1999 cmp al, #0x02
2000 jne int10_test_1003
2001 jmp biosfn_set_all_palette_reg
2002 int10_test_1003:
2003 cmp al, #0x03
2004 jne int10_test_1007
2005 jmp biosfn_toggle_intensity
2006 int10_test_1007:
2007 cmp al, #0x07
2008 jne int10_test_1008
2009 jmp biosfn_get_single_palette_reg
2010 int10_test_1008:
2011 cmp al, #0x08
2012 jne int10_test_1009
2013 jmp biosfn_read_overscan_border_color
2014 int10_test_1009:
2015 cmp al, #0x09
2016 jne int10_test_1010
2017 jmp biosfn_get_all_palette_reg
2018 int10_test_1010:
2019 cmp al, #0x10
2020 jne int10_test_1012
2021 jmp biosfn_set_single_dac_reg
2022 int10_test_1012:
2023 cmp al, #0x12
2024 jne int10_test_1013
2025 jmp biosfn_set_all_dac_reg
2026 int10_test_1013:
2027 cmp al, #0x13
2028 jne int10_test_1015
2029 jmp biosfn_select_video_dac_color_page
2030 int10_test_1015:
2031 cmp al, #0x15
2032 jne int10_test_1017
2033 jmp biosfn_read_single_dac_reg
2034 int10_test_1017:
2035 cmp al, #0x17
2036 jne int10_test_1018
2037 jmp biosfn_read_all_dac_reg
2038 int10_test_1018:
2039 cmp al, #0x18
2040 jne int10_test_1019
2041 jmp biosfn_set_pel_mask
2042 int10_test_1019:
2043 cmp al, #0x19
2044 jne int10_test_101A
2045 jmp biosfn_read_pel_mask
2046 int10_test_101A:
2047 cmp al, #0x1a
2048 jne int10_group_10_unknown
2049 jmp biosfn_read_video_dac_state
2050 int10_group_10_unknown:
2051 #ifdef DEBUG
2052 call _unknown
2053 #endif
2056 biosfn_set_single_palette_reg:
2057 cmp bl, #0x14
2058 ja no_actl_reg1
2059 push ax
2060 push dx
2061 mov dx, # VGAREG_ACTL_RESET
2062 in al, dx
2063 mov dx, # VGAREG_ACTL_ADDRESS
2064 mov al, bl
2065 out dx, al
2066 mov al, bh
2067 out dx, al
2068 mov al, #0x20
2069 out dx, al
2070 pop dx
2071 pop ax
2072 no_actl_reg1:
2074 ASM_END
2076 // --------------------------------------------------------------------------------------------
2077 ASM_START
2078 biosfn_set_overscan_border_color:
2079 push bx
2080 mov bl, #0x11
2081 call biosfn_set_single_palette_reg
2082 pop bx
2084 ASM_END
2086 // --------------------------------------------------------------------------------------------
2087 ASM_START
2088 biosfn_set_all_palette_reg:
2089 push ax
2090 push bx
2091 push cx
2092 push dx
2093 mov bx, dx
2094 mov dx, # VGAREG_ACTL_RESET
2095 in al, dx
2096 mov cl, #0x00
2097 mov dx, # VGAREG_ACTL_ADDRESS
2098 set_palette_loop:
2099 mov al, cl
2100 out dx, al
2101 seg es
2102 mov al, [bx]
2103 out dx, al
2104 inc bx
2105 inc cl
2106 cmp cl, #0x10
2107 jne set_palette_loop
2108 mov al, #0x11
2109 out dx, al
2110 seg es
2111 mov al, [bx]
2112 out dx, al
2113 mov al, #0x20
2114 out dx, al
2115 pop dx
2116 pop cx
2117 pop bx
2118 pop ax
2120 ASM_END
2122 // --------------------------------------------------------------------------------------------
2123 ASM_START
2124 biosfn_toggle_intensity:
2125 push ax
2126 push bx
2127 push dx
2128 mov dx, # VGAREG_ACTL_RESET
2129 in al, dx
2130 mov dx, # VGAREG_ACTL_ADDRESS
2131 mov al, #0x10
2132 out dx, al
2133 mov dx, # VGAREG_ACTL_READ_DATA
2134 in al, dx
2135 and al, #0xf7
2136 and bl, #0x01
2137 shl bl, 3
2138 or al, bl
2139 mov dx, # VGAREG_ACTL_ADDRESS
2140 out dx, al
2141 mov al, #0x20
2142 out dx, al
2143 pop dx
2144 pop bx
2145 pop ax
2147 ASM_END
2149 // --------------------------------------------------------------------------------------------
2150 ASM_START
2151 biosfn_get_single_palette_reg:
2152 cmp bl, #0x14
2153 ja no_actl_reg2
2154 push ax
2155 push dx
2156 mov dx, # VGAREG_ACTL_RESET
2157 in al, dx
2158 mov dx, # VGAREG_ACTL_ADDRESS
2159 mov al, bl
2160 out dx, al
2161 mov dx, # VGAREG_ACTL_READ_DATA
2162 in al, dx
2163 mov bh, al
2164 mov dx, # VGAREG_ACTL_RESET
2165 in al, dx
2166 mov dx, # VGAREG_ACTL_ADDRESS
2167 mov al, #0x20
2168 out dx, al
2169 pop dx
2170 pop ax
2171 no_actl_reg2:
2173 ASM_END
2175 // --------------------------------------------------------------------------------------------
2176 ASM_START
2177 biosfn_read_overscan_border_color:
2178 push ax
2179 push bx
2180 mov bl, #0x11
2181 call biosfn_get_single_palette_reg
2182 mov al, bh
2183 pop bx
2184 mov bh, al
2185 pop ax
2187 ASM_END
2189 // --------------------------------------------------------------------------------------------
2190 ASM_START
2191 biosfn_get_all_palette_reg:
2192 push ax
2193 push bx
2194 push cx
2195 push dx
2196 mov bx, dx
2197 mov cl, #0x00
2198 get_palette_loop:
2199 mov dx, # VGAREG_ACTL_RESET
2200 in al, dx
2201 mov dx, # VGAREG_ACTL_ADDRESS
2202 mov al, cl
2203 out dx, al
2204 mov dx, # VGAREG_ACTL_READ_DATA
2205 in al, dx
2206 seg es
2207 mov [bx], al
2208 inc bx
2209 inc cl
2210 cmp cl, #0x10
2211 jne get_palette_loop
2212 mov dx, # VGAREG_ACTL_RESET
2213 in al, dx
2214 mov dx, # VGAREG_ACTL_ADDRESS
2215 mov al, #0x11
2216 out dx, al
2217 mov dx, # VGAREG_ACTL_READ_DATA
2218 in al, dx
2219 seg es
2220 mov [bx], al
2221 mov dx, # VGAREG_ACTL_RESET
2222 in al, dx
2223 mov dx, # VGAREG_ACTL_ADDRESS
2224 mov al, #0x20
2225 out dx, al
2226 pop dx
2227 pop cx
2228 pop bx
2229 pop ax
2231 ASM_END
2233 // --------------------------------------------------------------------------------------------
2234 ASM_START
2235 biosfn_set_single_dac_reg:
2236 push ax
2237 push dx
2238 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2239 mov al, bl
2240 out dx, al
2241 mov dx, # VGAREG_DAC_DATA
2242 pop ax
2243 push ax
2244 mov al, ah
2245 out dx, al
2246 mov al, ch
2247 out dx, al
2248 mov al, cl
2249 out dx, al
2250 pop dx
2251 pop ax
2253 ASM_END
2255 // --------------------------------------------------------------------------------------------
2256 ASM_START
2257 biosfn_set_all_dac_reg:
2258 push ax
2259 push bx
2260 push cx
2261 push dx
2262 mov dx, # VGAREG_DAC_WRITE_ADDRESS
2263 mov al, bl
2264 out dx, al
2265 pop dx
2266 push dx
2267 mov bx, dx
2268 mov dx, # VGAREG_DAC_DATA
2269 set_dac_loop:
2270 seg es
2271 mov al, [bx]
2272 out dx, al
2273 inc bx
2274 seg es
2275 mov al, [bx]
2276 out dx, al
2277 inc bx
2278 seg es
2279 mov al, [bx]
2280 out dx, al
2281 inc bx
2282 dec cx
2283 jnz set_dac_loop
2284 pop dx
2285 pop cx
2286 pop bx
2287 pop ax
2289 ASM_END
2291 // --------------------------------------------------------------------------------------------
2292 ASM_START
2293 biosfn_select_video_dac_color_page:
2294 push ax
2295 push bx
2296 push dx
2297 mov dx, # VGAREG_ACTL_RESET
2298 in al, dx
2299 mov dx, # VGAREG_ACTL_ADDRESS
2300 mov al, #0x10
2301 out dx, al
2302 mov dx, # VGAREG_ACTL_READ_DATA
2303 in al, dx
2304 and bl, #0x01
2305 jnz set_dac_page
2306 and al, #0x7f
2307 shl bh, 7
2308 or al, bh
2309 mov dx, # VGAREG_ACTL_ADDRESS
2310 out dx, al
2311 jmp set_actl_normal
2312 set_dac_page:
2313 push ax
2314 mov dx, # VGAREG_ACTL_RESET
2315 in al, dx
2316 mov dx, # VGAREG_ACTL_ADDRESS
2317 mov al, #0x14
2318 out dx, al
2319 pop ax
2320 and al, #0x80
2321 jnz set_dac_16_page
2322 shl bh, 2
2323 set_dac_16_page:
2324 and bh, #0x0f
2325 mov al, bh
2326 out dx, al
2327 set_actl_normal:
2328 mov al, #0x20
2329 out dx, al
2330 pop dx
2331 pop bx
2332 pop ax
2334 ASM_END
2336 // --------------------------------------------------------------------------------------------
2337 ASM_START
2338 biosfn_read_single_dac_reg:
2339 push ax
2340 push dx
2341 mov dx, # VGAREG_DAC_READ_ADDRESS
2342 mov al, bl
2343 out dx, al
2344 pop ax
2345 mov ah, al
2346 mov dx, # VGAREG_DAC_DATA
2347 in al, dx
2348 xchg al, ah
2349 push ax
2350 in al, dx
2351 mov ch, al
2352 in al, dx
2353 mov cl, al
2354 pop dx
2355 pop ax
2357 ASM_END
2359 // --------------------------------------------------------------------------------------------
2360 ASM_START
2361 biosfn_read_all_dac_reg:
2362 push ax
2363 push bx
2364 push cx
2365 push dx
2366 mov dx, # VGAREG_DAC_READ_ADDRESS
2367 mov al, bl
2368 out dx, al
2369 pop dx
2370 push dx
2371 mov bx, dx
2372 mov dx, # VGAREG_DAC_DATA
2373 read_dac_loop:
2374 in al, dx
2375 seg es
2376 mov [bx], al
2377 inc bx
2378 in al, dx
2379 seg es
2380 mov [bx], al
2381 inc bx
2382 in al, dx
2383 seg es
2384 mov [bx], al
2385 inc bx
2386 dec cx
2387 jnz read_dac_loop
2388 pop dx
2389 pop cx
2390 pop bx
2391 pop ax
2393 ASM_END
2395 // --------------------------------------------------------------------------------------------
2396 ASM_START
2397 biosfn_set_pel_mask:
2398 push ax
2399 push dx
2400 mov dx, # VGAREG_PEL_MASK
2401 mov al, bl
2402 out dx, al
2403 pop dx
2404 pop ax
2406 ASM_END
2408 // --------------------------------------------------------------------------------------------
2409 ASM_START
2410 biosfn_read_pel_mask:
2411 push ax
2412 push dx
2413 mov dx, # VGAREG_PEL_MASK
2414 in al, dx
2415 mov bl, al
2416 pop dx
2417 pop ax
2419 ASM_END
2421 // --------------------------------------------------------------------------------------------
2422 ASM_START
2423 biosfn_read_video_dac_state:
2424 push ax
2425 push dx
2426 mov dx, # VGAREG_ACTL_RESET
2427 in al, dx
2428 mov dx, # VGAREG_ACTL_ADDRESS
2429 mov al, #0x10
2430 out dx, al
2431 mov dx, # VGAREG_ACTL_READ_DATA
2432 in al, dx
2433 mov bl, al
2434 shr bl, 7
2435 mov dx, # VGAREG_ACTL_RESET
2436 in al, dx
2437 mov dx, # VGAREG_ACTL_ADDRESS
2438 mov al, #0x14
2439 out dx, al
2440 mov dx, # VGAREG_ACTL_READ_DATA
2441 in al, dx
2442 mov bh, al
2443 and bh, #0x0f
2444 test bl, #0x01
2445 jnz get_dac_16_page
2446 shr bh, 2
2447 get_dac_16_page:
2448 mov dx, # VGAREG_ACTL_RESET
2449 in al, dx
2450 mov dx, # VGAREG_ACTL_ADDRESS
2451 mov al, #0x20
2452 out dx, al
2453 pop dx
2454 pop ax
2456 ASM_END
2458 // --------------------------------------------------------------------------------------------
2459 static void biosfn_perform_gray_scale_summing (start,count)
2460 Bit16u start;Bit16u count;
2461 {Bit8u r,g,b;
2462 Bit16u i;
2463 Bit16u index;
2465 inb(VGAREG_ACTL_RESET);
2466 outb(VGAREG_ACTL_ADDRESS,0x00);
2468 for( index = 0; index < count; index++ )
2470 // set read address and switch to read mode
2471 outb(VGAREG_DAC_READ_ADDRESS,start);
2472 // get 6-bit wide RGB data values
2473 r=inb( VGAREG_DAC_DATA );
2474 g=inb( VGAREG_DAC_DATA );
2475 b=inb( VGAREG_DAC_DATA );
2477 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2478 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2480 if(i>0x3f)i=0x3f;
2482 // set write address and switch to write mode
2483 outb(VGAREG_DAC_WRITE_ADDRESS,start);
2484 // write new intensity value
2485 outb( VGAREG_DAC_DATA, i&0xff );
2486 outb( VGAREG_DAC_DATA, i&0xff );
2487 outb( VGAREG_DAC_DATA, i&0xff );
2488 start++;
2490 inb(VGAREG_ACTL_RESET);
2491 outb(VGAREG_ACTL_ADDRESS,0x20);
2494 // --------------------------------------------------------------------------------------------
2495 static void get_font_access()
2497 ASM_START
2498 mov dx, # VGAREG_SEQU_ADDRESS
2499 mov ax, #0x0100
2500 out dx, ax
2501 mov ax, #0x0402
2502 out dx, ax
2503 mov ax, #0x0704
2504 out dx, ax
2505 mov ax, #0x0300
2506 out dx, ax
2507 mov dx, # VGAREG_GRDC_ADDRESS
2508 mov ax, #0x0204
2509 out dx, ax
2510 mov ax, #0x0005
2511 out dx, ax
2512 mov ax, #0x0406
2513 out dx, ax
2514 ASM_END
2517 static void release_font_access()
2519 ASM_START
2520 mov dx, # VGAREG_SEQU_ADDRESS
2521 mov ax, #0x0100
2522 out dx, ax
2523 mov ax, #0x0302
2524 out dx, ax
2525 mov ax, #0x0304
2526 out dx, ax
2527 mov ax, #0x0300
2528 out dx, ax
2529 mov dx, # VGAREG_READ_MISC_OUTPUT
2530 in al, dx
2531 and al, #0x01
2532 shl al, 2
2533 or al, #0x0a
2534 mov ah, al
2535 mov al, #0x06
2536 mov dx, # VGAREG_GRDC_ADDRESS
2537 out dx, ax
2538 mov ax, #0x0004
2539 out dx, ax
2540 mov ax, #0x1005
2541 out dx, ax
2542 ASM_END
2545 ASM_START
2546 idiv_u:
2547 xor dx,dx
2548 div bx
2550 ASM_END
2552 static void set_scan_lines(lines) Bit8u lines;
2554 Bit16u crtc_addr,cols,page,vde;
2555 Bit8u crtc_r9,ovl,rows;
2557 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2558 outb(crtc_addr, 0x09);
2559 crtc_r9 = inb(crtc_addr+1);
2560 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2561 outb(crtc_addr+1, crtc_r9);
2562 if(lines==8)
2564 biosfn_set_cursor_shape(0x06,0x07);
2566 else
2568 biosfn_set_cursor_shape(lines-4,lines-3);
2570 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2571 outb(crtc_addr, 0x12);
2572 vde = inb(crtc_addr+1);
2573 outb(crtc_addr, 0x07);
2574 ovl = inb(crtc_addr+1);
2575 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2576 rows = vde / lines;
2577 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2578 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2579 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2582 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;
2584 Bit16u blockaddr,dest,i,src;
2586 get_font_access();
2587 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2588 for(i=0;i<CX;i++)
2590 src = BP + i * BH;
2591 dest = blockaddr + (DX + i) * 32;
2592 memcpyb(0xA000, dest, ES, src, BH);
2594 release_font_access();
2595 if(AL>=0x10)
2597 set_scan_lines(BH);
2601 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2603 Bit16u blockaddr,dest,i,src;
2605 get_font_access();
2606 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2607 for(i=0;i<0x100;i++)
2609 src = i * 14;
2610 dest = blockaddr + i * 32;
2611 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2613 release_font_access();
2614 if(AL>=0x10)
2616 set_scan_lines(14);
2620 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2622 Bit16u blockaddr,dest,i,src;
2624 get_font_access();
2625 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2626 for(i=0;i<0x100;i++)
2628 src = i * 8;
2629 dest = blockaddr + i * 32;
2630 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2632 release_font_access();
2633 if(AL>=0x10)
2635 set_scan_lines(8);
2639 // --------------------------------------------------------------------------------------------
2640 ASM_START
2641 biosfn_set_text_block_specifier:
2642 push ax
2643 push dx
2644 mov dx, # VGAREG_SEQU_ADDRESS
2645 mov ah, bl
2646 mov al, #0x03
2647 out dx, ax
2648 pop dx
2649 pop ax
2651 ASM_END
2653 // --------------------------------------------------------------------------------------------
2654 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2656 Bit16u blockaddr,dest,i,src;
2658 get_font_access();
2659 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2660 for(i=0;i<0x100;i++)
2662 src = i * 16;
2663 dest = blockaddr + i * 32;
2664 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2666 release_font_access();
2667 if(AL>=0x10)
2669 set_scan_lines(16);
2673 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2675 #ifdef DEBUG
2676 unimplemented();
2677 #endif
2679 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2681 #ifdef DEBUG
2682 unimplemented();
2683 #endif
2685 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2687 #ifdef DEBUG
2688 unimplemented();
2689 #endif
2691 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2693 #ifdef DEBUG
2694 unimplemented();
2695 #endif
2697 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2699 #ifdef DEBUG
2700 unimplemented();
2701 #endif
2703 // --------------------------------------------------------------------------------------------
2704 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2705 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2706 {Bit16u ss=get_SS();
2708 switch(BH)
2709 {case 0x00:
2710 write_word(ss,ES,read_word(0x00,0x1f*4));
2711 write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2712 break;
2713 case 0x01:
2714 write_word(ss,ES,read_word(0x00,0x43*4));
2715 write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2716 break;
2717 case 0x02:
2718 write_word(ss,ES,0xC000);
2719 write_word(ss,BP,vgafont14);
2720 break;
2721 case 0x03:
2722 write_word(ss,ES,0xC000);
2723 write_word(ss,BP,vgafont8);
2724 break;
2725 case 0x04:
2726 write_word(ss,ES,0xC000);
2727 write_word(ss,BP,vgafont8+128*8);
2728 break;
2729 case 0x05:
2730 write_word(ss,ES,0xC000);
2731 write_word(ss,BP,vgafont14alt);
2732 break;
2733 case 0x06:
2734 write_word(ss,ES,0xC000);
2735 write_word(ss,BP,vgafont16);
2736 break;
2737 case 0x07:
2738 write_word(ss,ES,0xC000);
2739 write_word(ss,BP,vgafont16alt);
2740 break;
2741 default:
2742 #ifdef DEBUG
2743 printf("Get font info BH(%02x) was discarded\n",BH);
2744 #endif
2745 return;
2747 // Set byte/char of on screen font
2748 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2750 // Set Highest char row
2751 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2754 // --------------------------------------------------------------------------------------------
2755 ASM_START
2756 biosfn_get_ega_info:
2757 push ds
2758 push ax
2759 mov ax, # BIOSMEM_SEG
2760 mov ds, ax
2761 xor ch, ch
2762 mov bx, # BIOSMEM_SWITCHES
2763 mov cl, [bx]
2764 and cl, #0x0f
2765 mov bx, # BIOSMEM_CRTC_ADDRESS
2766 mov ax, [bx]
2767 mov bx, #0x0003
2768 cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2769 jne mode_ega_color
2770 mov bh, #0x01
2771 mode_ega_color:
2772 pop ax
2773 pop ds
2775 ASM_END
2777 // --------------------------------------------------------------------------------------------
2778 static void biosfn_alternate_prtsc()
2780 #ifdef DEBUG
2781 unimplemented();
2782 #endif
2785 // --------------------------------------------------------------------------------------------
2786 static void biosfn_select_vert_res (res)
2787 Bit8u res;
2788 {// res : 00 200 lines, 01 350 lines, 02 400 lines
2789 Bit8u modeset,switches;
2791 modeset=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2792 switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
2793 switch(res)
2794 {case 0x00:
2795 // set modeset ctl bit 7 and reset bit 4
2796 // set switches bit 3-0 to 0x08
2797 modeset|=0x80;modeset&=0xef;
2798 switches&=0xf0;switches|=0x08;
2799 break;
2800 case 0x01:
2801 // reset modeset ctl bit 7 and bit 4
2802 // set switches bit 3-0 to 0x09
2803 modeset&=0x6f;
2804 switches&=0xf0;switches|=0x09;
2805 break;
2806 case 0x02:
2807 // reset modeset ctl bit 7 and set bit 4
2808 // set switches bit 3-0 to 0x09
2809 modeset|=0x10;modeset&=0x7f;
2810 switches&=0xf0;switches|=0x09;
2811 break;
2812 default:
2813 #ifdef DEBUG
2814 printf("Select vert res (%02x) was discarded\n",res);
2815 #endif
2816 return;
2818 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,modeset);
2819 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,switches);
2822 // --------------------------------------------------------------------------------------------
2823 ASM_START
2824 biosfn_enable_default_palette_loading:
2825 push ds
2826 push bx
2827 push dx
2828 mov dl, al
2829 and dl, #0x01
2830 shl dl, 3
2831 mov ax, # BIOSMEM_SEG
2832 mov ds, ax
2833 mov bx, # BIOSMEM_MODESET_CTL
2834 mov al, [bx]
2835 and al, #0xf7
2836 or al, dl
2837 mov [bx], al
2838 mov ax, #0x1212
2839 pop dx
2840 pop bx
2841 pop ds
2843 ASM_END
2845 // --------------------------------------------------------------------------------------------
2846 ASM_START
2847 biosfn_enable_video_addressing:
2848 push bx
2849 push dx
2850 mov bl, al
2851 and bl, #0x01
2852 xor bl, #0x01
2853 shl bl, 1
2854 mov dx, # VGAREG_READ_MISC_OUTPUT
2855 in al, dx
2856 and al, #0xfd
2857 or al, bl
2858 mov dx, # VGAREG_WRITE_MISC_OUTPUT
2859 out dx, al
2860 mov ax, #0x1212
2861 pop dx
2862 pop bx
2864 ASM_END
2866 // --------------------------------------------------------------------------------------------
2867 ASM_START
2868 biosfn_enable_grayscale_summing:
2869 push ds
2870 push bx
2871 push dx
2872 mov dl, al
2873 and dl, #0x01
2874 xor dl, #0x01
2875 shl dl, 1
2876 mov ax, # BIOSMEM_SEG
2877 mov ds, ax
2878 mov bx, # BIOSMEM_MODESET_CTL
2879 mov al, [bx]
2880 and al, #0xfd
2881 or al, dl
2882 mov [bx], al
2883 mov ax, #0x1212
2884 pop dx
2885 pop bx
2886 pop ds
2888 ASM_END
2890 // --------------------------------------------------------------------------------------------
2891 ASM_START
2892 biosfn_enable_cursor_emulation:
2893 push ds
2894 push bx
2895 push dx
2896 mov dl, al
2897 and dl, #0x01
2898 xor dl, #0x01
2899 mov ax, # BIOSMEM_SEG
2900 mov ds, ax
2901 mov bx, # BIOSMEM_MODESET_CTL
2902 mov al, [bx]
2903 and al, #0xfe
2904 or al, dl
2905 mov [bx], al
2906 mov ax, #0x1212
2907 pop dx
2908 pop bx
2909 pop ds
2911 ASM_END
2913 // --------------------------------------------------------------------------------------------
2914 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
2916 #ifdef DEBUG
2917 unimplemented();
2918 #endif
2920 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
2922 #ifdef DEBUG
2923 unimplemented();
2924 #endif
2927 // --------------------------------------------------------------------------------------------
2928 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
2929 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
2931 Bit16u newcurs,oldcurs,dummy;
2932 Bit8u car,carattr;
2934 // Read curs info for the page
2935 biosfn_get_cursor_pos(page,&dummy,&oldcurs);
2937 // if row=0xff special case : use current cursor position
2938 if(row==0xff)
2939 {col=oldcurs&0x00ff;
2940 row=(oldcurs&0xff00)>>8;
2943 newcurs=row; newcurs<<=8; newcurs+=col;
2944 biosfn_set_cursor_pos(page,newcurs);
2946 while(count--!=0)
2948 car=read_byte(seg,offset++);
2949 if((flag&0x02)!=0)
2950 attr=read_byte(seg,offset++);
2952 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2955 // Set back curs pos
2956 if((flag&0x01)==0)
2957 biosfn_set_cursor_pos(page,oldcurs);
2960 // --------------------------------------------------------------------------------------------
2961 ASM_START
2962 biosfn_group_1A:
2963 cmp al, #0x00
2964 je biosfn_read_display_code
2965 cmp al, #0x01
2966 je biosfn_set_display_code
2967 #ifdef DEBUG
2968 call _unknown
2969 #endif
2971 biosfn_read_display_code:
2972 push ds
2973 push ax
2974 mov ax, # BIOSMEM_SEG
2975 mov ds, ax
2976 mov bx, # BIOSMEM_DCC_INDEX
2977 mov al, [bx]
2978 mov bl, al
2979 xor bh, bh
2980 pop ax
2981 mov al, ah
2982 pop ds
2984 biosfn_set_display_code:
2985 push ds
2986 push ax
2987 push bx
2988 mov ax, # BIOSMEM_SEG
2989 mov ds, ax
2990 mov ax, bx
2991 mov bx, # BIOSMEM_DCC_INDEX
2992 mov [bx], al
2993 #ifdef DEBUG
2994 mov al, ah
2995 xor ah, ah
2996 push ax
2997 mov bx, #msg_alt_dcc
2998 push bx
2999 call _printf
3000 add sp, #4
3001 #endif
3002 pop bx
3003 pop ax
3004 mov al, ah
3005 pop ds
3008 #ifdef DEBUG
3009 msg_alt_dcc:
3010 .ascii "Alternate Display code (%02x) was discarded"
3011 .byte 0x0d,0x0a,0x00
3012 #endif
3013 ASM_END
3015 // --------------------------------------------------------------------------------------------
3016 static void biosfn_read_state_info (BX,ES,DI)
3017 Bit16u BX;Bit16u ES;Bit16u DI;
3019 // Address of static functionality table
3020 write_word(ES,DI+0x00,&static_functionality);
3021 write_word(ES,DI+0x02,0xC000);
3023 // Hard coded copy from BIOS area. Should it be cleaner ?
3024 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3025 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3027 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3028 write_byte(ES,DI+0x26,0);
3029 write_byte(ES,DI+0x27,16);
3030 write_byte(ES,DI+0x28,0);
3031 write_byte(ES,DI+0x29,8);
3032 write_byte(ES,DI+0x2a,2);
3033 write_byte(ES,DI+0x2b,0);
3034 write_byte(ES,DI+0x2c,0);
3035 write_byte(ES,DI+0x31,3);
3036 write_byte(ES,DI+0x32,0);
3038 memsetb(ES,DI+0x33,0,13);
3041 // --------------------------------------------------------------------------------------------
3042 static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3044 #ifdef DEBUG
3045 unimplemented();
3046 #endif
3048 static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3050 #ifdef DEBUG
3051 unimplemented();
3052 #endif
3054 static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
3056 #ifdef DEBUG
3057 unimplemented();
3058 #endif
3061 // ============================================================================================
3063 // Video Utils
3065 // ============================================================================================
3067 // --------------------------------------------------------------------------------------------
3068 static Bit8u find_vga_entry(mode)
3069 Bit8u mode;
3071 Bit8u i,line=0xFF;
3072 for(i=0;i<=MODE_MAX;i++)
3073 if(vga_modes[i].svgamode==mode)
3074 {line=i;
3075 break;
3077 return line;
3080 /* =========================================================== */
3082 * Misc Utils
3084 /* =========================================================== */
3086 // --------------------------------------------------------------------------------------------
3087 static void memsetb(seg,offset,value,count)
3088 Bit16u seg;
3089 Bit16u offset;
3090 Bit16u value;
3091 Bit16u count;
3093 ASM_START
3094 push bp
3095 mov bp, sp
3097 push ax
3098 push cx
3099 push es
3100 push di
3102 mov cx, 10[bp] ; count
3103 cmp cx, #0x00
3104 je memsetb_end
3105 mov ax, 4[bp] ; segment
3106 mov es, ax
3107 mov ax, 6[bp] ; offset
3108 mov di, ax
3109 mov al, 8[bp] ; value
3112 stosb
3114 memsetb_end:
3115 pop di
3116 pop es
3117 pop cx
3118 pop ax
3120 pop bp
3121 ASM_END
3124 // --------------------------------------------------------------------------------------------
3125 static void memsetw(seg,offset,value,count)
3126 Bit16u seg;
3127 Bit16u offset;
3128 Bit16u value;
3129 Bit16u count;
3131 ASM_START
3132 push bp
3133 mov bp, sp
3135 push ax
3136 push cx
3137 push es
3138 push di
3140 mov cx, 10[bp] ; count
3141 cmp cx, #0x00
3142 je memsetw_end
3143 mov ax, 4[bp] ; segment
3144 mov es, ax
3145 mov ax, 6[bp] ; offset
3146 mov di, ax
3147 mov ax, 8[bp] ; value
3150 stosw
3152 memsetw_end:
3153 pop di
3154 pop es
3155 pop cx
3156 pop ax
3158 pop bp
3159 ASM_END
3162 // --------------------------------------------------------------------------------------------
3163 static void memcpyb(dseg,doffset,sseg,soffset,count)
3164 Bit16u dseg;
3165 Bit16u doffset;
3166 Bit16u sseg;
3167 Bit16u soffset;
3168 Bit16u count;
3170 ASM_START
3171 push bp
3172 mov bp, sp
3174 push ax
3175 push cx
3176 push es
3177 push di
3178 push ds
3179 push si
3181 mov cx, 12[bp] ; count
3182 cmp cx, #0x0000
3183 je memcpyb_end
3184 mov ax, 4[bp] ; dsegment
3185 mov es, ax
3186 mov ax, 6[bp] ; doffset
3187 mov di, ax
3188 mov ax, 8[bp] ; ssegment
3189 mov ds, ax
3190 mov ax, 10[bp] ; soffset
3191 mov si, ax
3194 movsb
3196 memcpyb_end:
3197 pop si
3198 pop ds
3199 pop di
3200 pop es
3201 pop cx
3202 pop ax
3204 pop bp
3205 ASM_END
3208 // --------------------------------------------------------------------------------------------
3209 static void memcpyw(dseg,doffset,sseg,soffset,count)
3210 Bit16u dseg;
3211 Bit16u doffset;
3212 Bit16u sseg;
3213 Bit16u soffset;
3214 Bit16u count;
3216 ASM_START
3217 push bp
3218 mov bp, sp
3220 push ax
3221 push cx
3222 push es
3223 push di
3224 push ds
3225 push si
3227 mov cx, 12[bp] ; count
3228 cmp cx, #0x0000
3229 je memcpyw_end
3230 mov ax, 4[bp] ; dsegment
3231 mov es, ax
3232 mov ax, 6[bp] ; doffset
3233 mov di, ax
3234 mov ax, 8[bp] ; ssegment
3235 mov ds, ax
3236 mov ax, 10[bp] ; soffset
3237 mov si, ax
3240 movsw
3242 memcpyw_end:
3243 pop si
3244 pop ds
3245 pop di
3246 pop es
3247 pop cx
3248 pop ax
3250 pop bp
3251 ASM_END
3254 /* =========================================================== */
3256 * These functions where ripped from Kevin's rombios.c
3258 /* =========================================================== */
3260 // --------------------------------------------------------------------------------------------
3261 static Bit8u
3262 read_byte(seg, offset)
3263 Bit16u seg;
3264 Bit16u offset;
3266 ASM_START
3267 push bp
3268 mov bp, sp
3270 push bx
3271 push ds
3272 mov ax, 4[bp] ; segment
3273 mov ds, ax
3274 mov bx, 6[bp] ; offset
3275 mov al, [bx]
3276 ;; al = return value (byte)
3277 pop ds
3278 pop bx
3280 pop bp
3281 ASM_END
3284 // --------------------------------------------------------------------------------------------
3285 static Bit16u
3286 read_word(seg, offset)
3287 Bit16u seg;
3288 Bit16u offset;
3290 ASM_START
3291 push bp
3292 mov bp, sp
3294 push bx
3295 push ds
3296 mov ax, 4[bp] ; segment
3297 mov ds, ax
3298 mov bx, 6[bp] ; offset
3299 mov ax, [bx]
3300 ;; ax = return value (word)
3301 pop ds
3302 pop bx
3304 pop bp
3305 ASM_END
3308 // --------------------------------------------------------------------------------------------
3309 static void
3310 write_byte(seg, offset, data)
3311 Bit16u seg;
3312 Bit16u offset;
3313 Bit8u data;
3315 ASM_START
3316 push bp
3317 mov bp, sp
3319 push ax
3320 push bx
3321 push ds
3322 mov ax, 4[bp] ; segment
3323 mov ds, ax
3324 mov bx, 6[bp] ; offset
3325 mov al, 8[bp] ; data byte
3326 mov [bx], al ; write data byte
3327 pop ds
3328 pop bx
3329 pop ax
3331 pop bp
3332 ASM_END
3335 // --------------------------------------------------------------------------------------------
3336 static void
3337 write_word(seg, offset, data)
3338 Bit16u seg;
3339 Bit16u offset;
3340 Bit16u data;
3342 ASM_START
3343 push bp
3344 mov bp, sp
3346 push ax
3347 push bx
3348 push ds
3349 mov ax, 4[bp] ; segment
3350 mov ds, ax
3351 mov bx, 6[bp] ; offset
3352 mov ax, 8[bp] ; data word
3353 mov [bx], ax ; write data word
3354 pop ds
3355 pop bx
3356 pop ax
3358 pop bp
3359 ASM_END
3362 // --------------------------------------------------------------------------------------------
3363 Bit8u
3364 inb(port)
3365 Bit16u port;
3367 ASM_START
3368 push bp
3369 mov bp, sp
3371 push dx
3372 mov dx, 4[bp]
3373 in al, dx
3374 pop dx
3376 pop bp
3377 ASM_END
3380 Bit16u
3381 inw(port)
3382 Bit16u port;
3384 ASM_START
3385 push bp
3386 mov bp, sp
3388 push dx
3389 mov dx, 4[bp]
3390 in ax, dx
3391 pop dx
3393 pop bp
3394 ASM_END
3397 // --------------------------------------------------------------------------------------------
3398 void
3399 outb(port, val)
3400 Bit16u port;
3401 Bit8u val;
3403 ASM_START
3404 push bp
3405 mov bp, sp
3407 push ax
3408 push dx
3409 mov dx, 4[bp]
3410 mov al, 6[bp]
3411 out dx, al
3412 pop dx
3413 pop ax
3415 pop bp
3416 ASM_END
3419 // --------------------------------------------------------------------------------------------
3420 void
3421 outw(port, val)
3422 Bit16u port;
3423 Bit16u val;
3425 ASM_START
3426 push bp
3427 mov bp, sp
3429 push ax
3430 push dx
3431 mov dx, 4[bp]
3432 mov ax, 6[bp]
3433 out dx, ax
3434 pop dx
3435 pop ax
3437 pop bp
3438 ASM_END
3441 Bit16u get_SS()
3443 ASM_START
3444 mov ax, ss
3445 ASM_END
3448 #ifdef DEBUG
3449 void unimplemented()
3451 printf("--> Unimplemented\n");
3454 void unknown()
3456 printf("--> Unknown int10\n");
3458 #endif
3460 // --------------------------------------------------------------------------------------------
3461 void printf(s)
3462 Bit8u *s;
3464 Bit8u c, format_char;
3465 Boolean in_format;
3466 unsigned format_width, i;
3467 Bit16u *arg_ptr;
3468 Bit16u arg_seg, arg, digit, nibble, shift_count;
3470 arg_ptr = &s;
3471 arg_seg = get_SS();
3473 in_format = 0;
3474 format_width = 0;
3476 while (c = read_byte(0xc000, s)) {
3477 if ( c == '%' ) {
3478 in_format = 1;
3479 format_width = 0;
3481 else if (in_format) {
3482 if ( (c>='0') && (c<='9') ) {
3483 format_width = (format_width * 10) + (c - '0');
3485 else if (c == 'x') {
3486 arg_ptr++; // increment to next arg
3487 arg = read_word(arg_seg, arg_ptr);
3488 if (format_width == 0)
3489 format_width = 4;
3490 i = 0;
3491 digit = format_width - 1;
3492 for (i=0; i<format_width; i++) {
3493 nibble = (arg >> (4 * digit)) & 0x000f;
3494 if (nibble <= 9)
3495 outb(0x0500, nibble + '0');
3496 else
3497 outb(0x0500, (nibble - 10) + 'A');
3498 digit--;
3500 in_format = 0;
3502 //else if (c == 'd') {
3503 // in_format = 0;
3504 // }
3506 else {
3507 outb(0x0500, c);
3509 s ++;
3513 #ifdef VBE
3514 #include "vbe.c"
3515 #endif
3517 // --------------------------------------------------------------------------------------------
3519 ASM_START
3520 ;; DATA_SEG_DEFS_HERE
3521 ASM_END
3523 ASM_START
3524 .ascii "vgabios ends here"
3525 .byte 0x00
3526 vgabios_end:
3527 .byte 0xCB
3528 ;; BLOCK_STRINGS_BEGIN
3529 ASM_END