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