VirtualBox

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

Last change on this file since 1 was 1, checked in by vboxsync, 55 years ago

import

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