VirtualBox

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

Last change on this file since 41210 was 40148, checked in by vboxsync, 13 years ago

Let VGA BIOS get out of VBE mode only through VGA registers.

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

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