VirtualBox

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

最後變更 在這個檔案從20261是 18265,由 vboxsync 提交於 16 年 前

config file cleanup + small copyright year update

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

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