VirtualBox

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

Last change on this file since 7554 was 5454, checked in by vboxsync, 17 years ago

The generated VBE mode list MUST NOT include the terminator, else custom modes
will be missing. Plus misc. minor fixes.

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

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