VirtualBox

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

Last change on this file since 26506 was 26506, checked in by vboxsync, 15 years ago

Devices: tabs -> spaces.

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