VirtualBox

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

Last change on this file since 12467 was 11982, checked in by vboxsync, 16 years ago

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

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