VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/BIOS/vgabios.c@ 3082

最後變更 在這個檔案從3082是 3082,由 vboxsync 提交於 18 年 前

Reset the attribute controller state in the VGA BIOS.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette