source: trunk/packages/xen-3.1/xen-3.1/tools/firmware/vgabios/vgabios.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

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