• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   inc  sp
434   inc  sp
435 #endif
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      address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2;
2043      attr=read_byte(vga_modes[line].sstart,address+1);
2044      biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2045     }
2046    else
2047     {
2048      biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2049     }
2050    ycurs-=1;
2051   }
2052 
2053  // Set the cursor for the page
2054  cursor=ycurs; cursor<<=8; cursor+=xcurs;
2055  biosfn_set_cursor_pos(page,cursor);
2056 }
2057 
2058 // --------------------------------------------------------------------------------------------
2059 ASM_START
2060 biosfn_get_video_mode:
2061   push  ds
2062   mov   ax, # BIOSMEM_SEG
2063   mov   ds, ax
2064   push  bx
2065   mov   bx, # BIOSMEM_CURRENT_PAGE
2066   mov   al, [bx]
2067   pop   bx
2068   mov   bh, al
2069   push  bx
2070   mov   bx, # BIOSMEM_VIDEO_CTL
2071   mov   ah, [bx]
2072   and   ah, #0x80
2073   mov   bx, # BIOSMEM_CURRENT_MODE
2074   mov   al, [bx]
2075   or    al, ah
2076   mov   bx, # BIOSMEM_NB_COLS
2077   mov   ah, [bx]
2078   pop   bx
2079   pop   ds
2080   ret
2081 ASM_END
2082 
2083 // --------------------------------------------------------------------------------------------
2084 ASM_START
2085 biosfn_group_10:
2086   cmp   al, #0x00
2087   jne   int10_test_1001
2088   jmp   biosfn_set_single_palette_reg
2089 int10_test_1001:
2090   cmp   al, #0x01
2091   jne   int10_test_1002
2092   jmp   biosfn_set_overscan_border_color
2093 int10_test_1002:
2094   cmp   al, #0x02
2095   jne   int10_test_1003
2096   jmp   biosfn_set_all_palette_reg
2097 int10_test_1003:
2098   cmp   al, #0x03
2099   jne   int10_test_1007
2100   jmp   biosfn_toggle_intensity
2101 int10_test_1007:
2102   cmp   al, #0x07
2103   jne   int10_test_1008
2104   jmp   biosfn_get_single_palette_reg
2105 int10_test_1008:
2106   cmp   al, #0x08
2107   jne   int10_test_1009
2108   jmp   biosfn_read_overscan_border_color
2109 int10_test_1009:
2110   cmp   al, #0x09
2111   jne   int10_test_1010
2112   jmp   biosfn_get_all_palette_reg
2113 int10_test_1010:
2114   cmp   al, #0x10
2115   jne   int10_test_1012
2116   jmp  biosfn_set_single_dac_reg
2117 int10_test_1012:
2118   cmp   al, #0x12
2119   jne   int10_test_1013
2120   jmp   biosfn_set_all_dac_reg
2121 int10_test_1013:
2122   cmp   al, #0x13
2123   jne   int10_test_1015
2124   jmp   biosfn_select_video_dac_color_page
2125 int10_test_1015:
2126   cmp   al, #0x15
2127   jne   int10_test_1017
2128   jmp   biosfn_read_single_dac_reg
2129 int10_test_1017:
2130   cmp   al, #0x17
2131   jne   int10_test_1018
2132   jmp   biosfn_read_all_dac_reg
2133 int10_test_1018:
2134   cmp   al, #0x18
2135   jne   int10_test_1019
2136   jmp   biosfn_set_pel_mask
2137 int10_test_1019:
2138   cmp   al, #0x19
2139   jne   int10_test_101A
2140   jmp   biosfn_read_pel_mask
2141 int10_test_101A:
2142   cmp   al, #0x1a
2143   jne   int10_group_10_unknown
2144   jmp   biosfn_read_video_dac_state
2145 int10_group_10_unknown:
2146 #ifdef DEBUG
2147   call  _unknown
2148 #endif
2149   ret
2150 
2151 biosfn_set_single_palette_reg:
2152   cmp   bl, #0x14
2153   ja    no_actl_reg1
2154   push  ax
2155   push  dx
2156   mov   dx, # VGAREG_ACTL_RESET
2157   in    al, dx
2158   mov   dx, # VGAREG_ACTL_ADDRESS
2159   mov   al, bl
2160   out   dx, al
2161   mov   al, bh
2162   out   dx, al
2163   mov   al, #0x20
2164   out   dx, al
2165   pop   dx
2166   pop   ax
2167 no_actl_reg1:
2168   ret
2169 ASM_END
2170 
2171 // --------------------------------------------------------------------------------------------
2172 ASM_START
2173 biosfn_set_overscan_border_color:
2174   push  bx
2175   mov   bl, #0x11
2176   call  biosfn_set_single_palette_reg
2177   pop   bx
2178   ret
2179 ASM_END
2180 
2181 // --------------------------------------------------------------------------------------------
2182 ASM_START
2183 biosfn_set_all_palette_reg:
2184   push  ax
2185   push  bx
2186   push  cx
2187   push  dx
2188   mov   bx, dx
2189   mov   dx, # VGAREG_ACTL_RESET
2190   in    al, dx
2191   mov   cl, #0x00
2192   mov   dx, # VGAREG_ACTL_ADDRESS
2193 set_palette_loop:
2194   mov   al, cl
2195   out   dx, al
2196   seg   es
2197   mov   al, [bx]
2198   out   dx, al
2199   inc   bx
2200   inc   cl
2201   cmp   cl, #0x10
2202   jne   set_palette_loop
2203   mov   al, #0x11
2204   out   dx, al
2205   seg   es
2206   mov   al, [bx]
2207   out   dx, al
2208   mov   al, #0x20
2209   out   dx, al
2210   pop   dx
2211   pop   cx
2212   pop   bx
2213   pop   ax
2214   ret
2215 ASM_END
2216 
2217 // --------------------------------------------------------------------------------------------
2218 ASM_START
2219 biosfn_toggle_intensity:
2220   push  ax
2221   push  bx
2222   push  dx
2223   mov   dx, # VGAREG_ACTL_RESET
2224   in    al, dx
2225   mov   dx, # VGAREG_ACTL_ADDRESS
2226   mov   al, #0x10
2227   out   dx, al
2228   mov   dx, # VGAREG_ACTL_READ_DATA
2229   in    al, dx
2230   and   al, #0xf7
2231   and   bl, #0x01
2232   shl   bl, 3
2233   or    al, bl
2234   mov   dx, # VGAREG_ACTL_ADDRESS
2235   out   dx, al
2236   mov   al, #0x20
2237   out   dx, al
2238   pop   dx
2239   pop   bx
2240   pop   ax
2241   ret
2242 ASM_END
2243 
2244 // --------------------------------------------------------------------------------------------
2245 ASM_START
2246 biosfn_get_single_palette_reg:
2247   cmp   bl, #0x14
2248   ja    no_actl_reg2
2249   push  ax
2250   push  dx
2251   mov   dx, # VGAREG_ACTL_RESET
2252   in    al, dx
2253   mov   dx, # VGAREG_ACTL_ADDRESS
2254   mov   al, bl
2255   out   dx, al
2256   mov   dx, # VGAREG_ACTL_READ_DATA
2257   in    al, dx
2258   mov   bh, al
2259   mov   dx, # VGAREG_ACTL_RESET
2260   in    al, dx
2261   mov   dx, # VGAREG_ACTL_ADDRESS
2262   mov   al, #0x20
2263   out   dx, al
2264   pop   dx
2265   pop   ax
2266 no_actl_reg2:
2267   ret
2268 ASM_END
2269 
2270 // --------------------------------------------------------------------------------------------
2271 ASM_START
2272 biosfn_read_overscan_border_color:
2273   push  ax
2274   push  bx
2275   mov   bl, #0x11
2276   call  biosfn_get_single_palette_reg
2277   mov   al, bh
2278   pop   bx
2279   mov   bh, al
2280   pop   ax
2281   ret
2282 ASM_END
2283 
2284 // --------------------------------------------------------------------------------------------
2285 ASM_START
2286 biosfn_get_all_palette_reg:
2287   push  ax
2288   push  bx
2289   push  cx
2290   push  dx
2291   mov   bx, dx
2292   mov   cl, #0x00
2293 get_palette_loop:
2294   mov   dx, # VGAREG_ACTL_RESET
2295   in    al, dx
2296   mov   dx, # VGAREG_ACTL_ADDRESS
2297   mov   al, cl
2298   out   dx, al
2299   mov   dx, # VGAREG_ACTL_READ_DATA
2300   in    al, dx
2301   seg   es
2302   mov   [bx], al
2303   inc   bx
2304   inc   cl
2305   cmp   cl, #0x10
2306   jne   get_palette_loop
2307   mov   dx, # VGAREG_ACTL_RESET
2308   in    al, dx
2309   mov   dx, # VGAREG_ACTL_ADDRESS
2310   mov   al, #0x11
2311   out   dx, al
2312   mov   dx, # VGAREG_ACTL_READ_DATA
2313   in    al, dx
2314   seg   es
2315   mov   [bx], al
2316   mov   dx, # VGAREG_ACTL_RESET
2317   in    al, dx
2318   mov   dx, # VGAREG_ACTL_ADDRESS
2319   mov   al, #0x20
2320   out   dx, al
2321   pop   dx
2322   pop   cx
2323   pop   bx
2324   pop   ax
2325   ret
2326 ASM_END
2327 
2328 // --------------------------------------------------------------------------------------------
2329 ASM_START
2330 biosfn_set_single_dac_reg:
2331   push  ax
2332   push  dx
2333   mov   dx, # VGAREG_DAC_WRITE_ADDRESS
2334   mov   al, bl
2335   out   dx, al
2336   mov   dx, # VGAREG_DAC_DATA
2337   pop   ax
2338   push  ax
2339   mov   al, ah
2340   out   dx, al
2341   mov   al, ch
2342   out   dx, al
2343   mov   al, cl
2344   out   dx, al
2345   pop   dx
2346   pop   ax
2347   ret
2348 ASM_END
2349 
2350 // --------------------------------------------------------------------------------------------
2351 ASM_START
2352 biosfn_set_all_dac_reg:
2353   push  ax
2354   push  bx
2355   push  cx
2356   push  dx
2357   mov   dx, # VGAREG_DAC_WRITE_ADDRESS
2358   mov   al, bl
2359   out   dx, al
2360   pop   dx
2361   push  dx
2362   mov   bx, dx
2363   mov   dx, # VGAREG_DAC_DATA
2364 set_dac_loop:
2365   seg   es
2366   mov   al, [bx]
2367   out   dx, al
2368   inc   bx
2369   seg   es
2370   mov   al, [bx]
2371   out   dx, al
2372   inc   bx
2373   seg   es
2374   mov   al, [bx]
2375   out   dx, al
2376   inc   bx
2377   dec   cx
2378   jnz   set_dac_loop
2379   pop   dx
2380   pop   cx
2381   pop   bx
2382   pop   ax
2383   ret
2384 ASM_END
2385 
2386 // --------------------------------------------------------------------------------------------
2387 ASM_START
2388 biosfn_select_video_dac_color_page:
2389   push  ax
2390   push  bx
2391   push  dx
2392   mov   dx, # VGAREG_ACTL_RESET
2393   in    al, dx
2394   mov   dx, # VGAREG_ACTL_ADDRESS
2395   mov   al, #0x10
2396   out   dx, al
2397   mov   dx, # VGAREG_ACTL_READ_DATA
2398   in    al, dx
2399   and   bl, #0x01
2400   jnz   set_dac_page
2401   and   al, #0x7f
2402   shl   bh, 7
2403   or    al, bh
2404   mov   dx, # VGAREG_ACTL_ADDRESS
2405   out   dx, al
2406   jmp   set_actl_normal
2407 set_dac_page:
2408   push  ax
2409   mov   dx, # VGAREG_ACTL_RESET
2410   in    al, dx
2411   mov   dx, # VGAREG_ACTL_ADDRESS
2412   mov   al, #0x14
2413   out   dx, al
2414   pop   ax
2415   and   al, #0x80
2416   jnz   set_dac_16_page
2417   shl   bh, 2
2418 set_dac_16_page:
2419   and   bh, #0x0f
2420   mov   al, bh
2421   out   dx, al
2422 set_actl_normal:
2423   mov   al, #0x20
2424   out   dx, al
2425   pop   dx
2426   pop   bx
2427   pop   ax
2428   ret
2429 ASM_END
2430 
2431 // --------------------------------------------------------------------------------------------
2432 ASM_START
2433 biosfn_read_single_dac_reg:
2434   push  ax
2435   push  dx
2436   mov   dx, # VGAREG_DAC_READ_ADDRESS
2437   mov   al, bl
2438   out   dx, al
2439   pop   ax
2440   mov   ah, al
2441   mov   dx, # VGAREG_DAC_DATA
2442   in    al, dx
2443   xchg  al, ah
2444   push  ax
2445   in    al, dx
2446   mov   ch, al
2447   in    al, dx
2448   mov   cl, al
2449   pop   dx
2450   pop   ax
2451   ret
2452 ASM_END
2453 
2454 // --------------------------------------------------------------------------------------------
2455 ASM_START
2456 biosfn_read_all_dac_reg:
2457   push  ax
2458   push  bx
2459   push  cx
2460   push  dx
2461   mov   dx, # VGAREG_DAC_READ_ADDRESS
2462   mov   al, bl
2463   out   dx, al
2464   pop   dx
2465   push  dx
2466   mov   bx, dx
2467   mov   dx, # VGAREG_DAC_DATA
2468 read_dac_loop:
2469   in    al, dx
2470   seg   es
2471   mov   [bx], al
2472   inc   bx
2473   in    al, dx
2474   seg   es
2475   mov   [bx], al
2476   inc   bx
2477   in    al, dx
2478   seg   es
2479   mov   [bx], al
2480   inc   bx
2481   dec   cx
2482   jnz   read_dac_loop
2483   pop   dx
2484   pop   cx
2485   pop   bx
2486   pop   ax
2487   ret
2488 ASM_END
2489 
2490 // --------------------------------------------------------------------------------------------
2491 ASM_START
2492 biosfn_set_pel_mask:
2493   push  ax
2494   push  dx
2495   mov   dx, # VGAREG_PEL_MASK
2496   mov   al, bl
2497   out   dx, al
2498   pop   dx
2499   pop   ax
2500   ret
2501 ASM_END
2502 
2503 // --------------------------------------------------------------------------------------------
2504 ASM_START
2505 biosfn_read_pel_mask:
2506   push  ax
2507   push  dx
2508   mov   dx, # VGAREG_PEL_MASK
2509   in    al, dx
2510   mov   bl, al
2511   pop   dx
2512   pop   ax
2513   ret
2514 ASM_END
2515 
2516 // --------------------------------------------------------------------------------------------
2517 ASM_START
2518 biosfn_read_video_dac_state:
2519   push  ax
2520   push  dx
2521   mov   dx, # VGAREG_ACTL_RESET
2522   in    al, dx
2523   mov   dx, # VGAREG_ACTL_ADDRESS
2524   mov   al, #0x10
2525   out   dx, al
2526   mov   dx, # VGAREG_ACTL_READ_DATA
2527   in    al, dx
2528   mov   bl, al
2529   shr   bl, 7
2530   mov   dx, # VGAREG_ACTL_RESET
2531   in    al, dx
2532   mov   dx, # VGAREG_ACTL_ADDRESS
2533   mov   al, #0x14
2534   out   dx, al
2535   mov   dx, # VGAREG_ACTL_READ_DATA
2536   in    al, dx
2537   mov   bh, al
2538   and   bh, #0x0f
2539   test  bl, #0x01
2540   jnz   get_dac_16_page
2541   shr   bh, 2
2542 get_dac_16_page:
2543   mov   dx, # VGAREG_ACTL_RESET
2544   in    al, dx
2545   mov   dx, # VGAREG_ACTL_ADDRESS
2546   mov   al, #0x20
2547   out   dx, al
2548   pop   dx
2549   pop   ax
2550   ret
2551 ASM_END
2552 
2553 // --------------------------------------------------------------------------------------------
biosfn_perform_gray_scale_summing(start,count)2554 static void biosfn_perform_gray_scale_summing (start,count)
2555 Bit16u start;Bit16u count;
2556 {Bit8u r,g,b;
2557  Bit16u i;
2558  Bit16u index;
2559 
2560  inb(VGAREG_ACTL_RESET);
2561  outb(VGAREG_ACTL_ADDRESS,0x00);
2562 
2563  for( index = 0; index < count; index++ )
2564   {
2565    // set read address and switch to read mode
2566    outb(VGAREG_DAC_READ_ADDRESS,start);
2567    // get 6-bit wide RGB data values
2568    r=inb( VGAREG_DAC_DATA );
2569    g=inb( VGAREG_DAC_DATA );
2570    b=inb( VGAREG_DAC_DATA );
2571 
2572    // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2573    i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2574 
2575    if(i>0x3f)i=0x3f;
2576 
2577    // set write address and switch to write mode
2578    outb(VGAREG_DAC_WRITE_ADDRESS,start);
2579    // write new intensity value
2580    outb( VGAREG_DAC_DATA, i&0xff );
2581    outb( VGAREG_DAC_DATA, i&0xff );
2582    outb( VGAREG_DAC_DATA, i&0xff );
2583    start++;
2584   }
2585  inb(VGAREG_ACTL_RESET);
2586  outb(VGAREG_ACTL_ADDRESS,0x20);
2587 }
2588 
2589 // --------------------------------------------------------------------------------------------
get_font_access()2590 static void get_font_access()
2591 {
2592 ASM_START
2593  mov dx, # VGAREG_SEQU_ADDRESS
2594  mov ax, #0x0100
2595  out dx, ax
2596  mov ax, #0x0402
2597  out dx, ax
2598  mov ax, #0x0704
2599  out dx, ax
2600  mov ax, #0x0300
2601  out dx, ax
2602  mov dx, # VGAREG_GRDC_ADDRESS
2603  mov ax, #0x0204
2604  out dx, ax
2605  mov ax, #0x0005
2606  out dx, ax
2607  mov ax, #0x0406
2608  out dx, ax
2609 ASM_END
2610 }
2611 
release_font_access()2612 static void release_font_access()
2613 {
2614 ASM_START
2615  mov dx, # VGAREG_SEQU_ADDRESS
2616  mov ax, #0x0100
2617  out dx, ax
2618  mov ax, #0x0302
2619  out dx, ax
2620  mov ax, #0x0304
2621  out dx, ax
2622  mov ax, #0x0300
2623  out dx, ax
2624  mov dx, # VGAREG_READ_MISC_OUTPUT
2625  in  al, dx
2626  and al, #0x01
2627  shl al, 2
2628  or  al, #0x0a
2629  mov ah, al
2630  mov al, #0x06
2631  mov dx, # VGAREG_GRDC_ADDRESS
2632  out dx, ax
2633  mov ax, #0x0004
2634  out dx, ax
2635  mov ax, #0x1005
2636  out dx, ax
2637 ASM_END
2638 }
2639 
2640 ASM_START
2641 idiv_u:
2642   xor dx,dx
2643   div bx
2644   ret
2645 ASM_END
2646 
set_scan_lines(lines)2647 static void set_scan_lines(lines) Bit8u lines;
2648 {
2649  Bit16u crtc_addr,cols,page,vde;
2650  Bit8u crtc_r9,ovl,rows;
2651 
2652  crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2653  outb(crtc_addr, 0x09);
2654  crtc_r9 = inb(crtc_addr+1);
2655  crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2656  outb(crtc_addr+1, crtc_r9);
2657  if(lines==8)
2658   {
2659    biosfn_set_cursor_shape(0x06,0x07);
2660   }
2661  else
2662   {
2663    biosfn_set_cursor_shape(lines-4,lines-3);
2664   }
2665  write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2666  outb(crtc_addr, 0x12);
2667  vde = inb(crtc_addr+1);
2668  outb(crtc_addr, 0x07);
2669  ovl = inb(crtc_addr+1);
2670  vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2671  rows = vde / lines;
2672  write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2673  cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2674  write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2675 }
2676 
biosfn_load_text_user_pat(AL,ES,BP,CX,DX,BL,BH)2677 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;
2678 {
2679  Bit16u blockaddr,dest,i,src;
2680 
2681  get_font_access();
2682  blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2683  for(i=0;i<CX;i++)
2684   {
2685    src = BP + i * BH;
2686    dest = blockaddr + (DX + i) * 32;
2687    memcpyb(0xA000, dest, ES, src, BH);
2688   }
2689  release_font_access();
2690  if(AL>=0x10)
2691   {
2692    set_scan_lines(BH);
2693   }
2694 }
2695 
biosfn_load_text_8_14_pat(AL,BL)2696 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2697 {
2698  Bit16u blockaddr,dest,i,src;
2699 
2700  get_font_access();
2701  blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2702  for(i=0;i<0x100;i++)
2703   {
2704    src = i * 14;
2705    dest = blockaddr + i * 32;
2706    memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2707   }
2708  release_font_access();
2709  if(AL>=0x10)
2710   {
2711    set_scan_lines(14);
2712   }
2713 }
2714 
biosfn_load_text_8_8_pat(AL,BL)2715 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2716 {
2717  Bit16u blockaddr,dest,i,src;
2718 
2719  get_font_access();
2720  blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2721  for(i=0;i<0x100;i++)
2722   {
2723    src = i * 8;
2724    dest = blockaddr + i * 32;
2725    memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2726   }
2727  release_font_access();
2728  if(AL>=0x10)
2729   {
2730    set_scan_lines(8);
2731   }
2732 }
2733 
2734 // --------------------------------------------------------------------------------------------
2735 ASM_START
2736 biosfn_set_text_block_specifier:
2737   push  ax
2738   push  dx
2739   mov   dx, # VGAREG_SEQU_ADDRESS
2740   mov   ah, bl
2741   mov   al, #0x03
2742   out   dx, ax
2743   pop   dx
2744   pop   ax
2745   ret
2746 ASM_END
2747 
2748 // --------------------------------------------------------------------------------------------
biosfn_load_text_8_16_pat(AL,BL)2749 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2750 {
2751  Bit16u blockaddr,dest,i,src;
2752 
2753  get_font_access();
2754  blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2755  for(i=0;i<0x100;i++)
2756   {
2757    src = i * 16;
2758    dest = blockaddr + i * 32;
2759    memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2760   }
2761  release_font_access();
2762  if(AL>=0x10)
2763   {
2764    set_scan_lines(16);
2765   }
2766 }
2767 
biosfn_load_gfx_8_8_chars(ES,BP)2768 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2769 {
2770 #ifdef DEBUG
2771  unimplemented();
2772 #endif
2773 }
biosfn_load_gfx_user_chars(ES,BP,CX,BL,DL)2774 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2775 {
2776 #ifdef DEBUG
2777  unimplemented();
2778 #endif
2779 }
biosfn_load_gfx_8_14_chars(BL)2780 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2781 {
2782 #ifdef DEBUG
2783  unimplemented();
2784 #endif
2785 }
biosfn_load_gfx_8_8_dd_chars(BL)2786 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2787 {
2788 #ifdef DEBUG
2789  unimplemented();
2790 #endif
2791 }
biosfn_load_gfx_8_16_chars(BL)2792 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2793 {
2794 #ifdef DEBUG
2795  unimplemented();
2796 #endif
2797 }
2798 // --------------------------------------------------------------------------------------------
biosfn_get_font_info(BH,ES,BP,CX,DX)2799 static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2800 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2801 {Bit16u ss=get_SS();
2802 
2803  switch(BH)
2804   {case 0x00:
2805     write_word(ss,ES,read_word(0x00,0x1f*4));
2806     write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2807     break;
2808    case 0x01:
2809     write_word(ss,ES,read_word(0x00,0x43*4));
2810     write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2811     break;
2812    case 0x02:
2813     write_word(ss,ES,0xC000);
2814     write_word(ss,BP,vgafont14);
2815     break;
2816    case 0x03:
2817     write_word(ss,ES,0xC000);
2818     write_word(ss,BP,vgafont8);
2819     break;
2820    case 0x04:
2821     write_word(ss,ES,0xC000);
2822     write_word(ss,BP,vgafont8+128*8);
2823     break;
2824    case 0x05:
2825     write_word(ss,ES,0xC000);
2826     write_word(ss,BP,vgafont14alt);
2827     break;
2828    case 0x06:
2829     write_word(ss,ES,0xC000);
2830     write_word(ss,BP,vgafont16);
2831     break;
2832    case 0x07:
2833     write_word(ss,ES,0xC000);
2834     write_word(ss,BP,vgafont16alt);
2835     break;
2836    default:
2837     #ifdef DEBUG
2838      printf("Get font info BH(%02x) was discarded\n",BH);
2839     #endif
2840     return;
2841   }
2842  // Set byte/char of on screen font
2843  write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2844 
2845  // Set Highest char row
2846  write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2847 }
2848 
2849 // --------------------------------------------------------------------------------------------
2850 ASM_START
2851 biosfn_get_ega_info:
2852   push  ds
2853   push  ax
2854   mov   ax, # BIOSMEM_SEG
2855   mov   ds, ax
2856   xor   ch, ch
2857   mov   bx, # BIOSMEM_SWITCHES
2858   mov   cl, [bx]
2859   and   cl, #0x0f
2860   mov   bx, # BIOSMEM_CRTC_ADDRESS
2861   mov   ax, [bx]
2862   mov   bx, #0x0003
2863   cmp   ax, # VGAREG_MDA_CRTC_ADDRESS
2864   jne   mode_ega_color
2865   mov   bh, #0x01
2866 mode_ega_color:
2867   pop   ax
2868   pop   ds
2869   ret
2870 ASM_END
2871 
2872 // --------------------------------------------------------------------------------------------
2873 static void biosfn_alternate_prtsc()
2874 {
2875 #ifdef DEBUG
2876  unimplemented();
2877 #endif
2878 }
2879 
2880 // --------------------------------------------------------------------------------------------
2881 ASM_START
2882 biosfn_select_vert_res:
2883 
2884 ; res : 00 200 lines, 01 350 lines, 02 400 lines
2885 
2886   push  ds
2887   push  bx
2888   push  dx
2889   mov   dl, al
2890   mov   ax, # BIOSMEM_SEG
2891   mov   ds, ax
2892   mov   bx, # BIOSMEM_MODESET_CTL
2893   mov   al, [bx]
2894   mov   bx, # BIOSMEM_SWITCHES
2895   mov   ah, [bx]
2896   cmp   dl, #0x01
2897   je    vert_res_350
2898   jb    vert_res_200
2899   cmp   dl, #0x02
2900   je    vert_res_400
2901 #ifdef DEBUG
2902   mov   al, dl
2903   xor   ah, ah
2904   push  ax
2905   mov   bx, #msg_vert_res
2906   push  bx
2907   call  _printf
2908   add   sp, #4
2909 #endif
2910   jmp   set_retcode
2911 vert_res_400:
2912 
2913   ; reset modeset ctl bit 7 and set bit 4
2914   ; set switches bit 3-0 to 0x09
2915 
2916   and   al, #0x7f
2917   or    al, #0x10
2918   and   ah, #0xf0
2919   or    ah, #0x09
2920   jnz   set_vert_res
2921 vert_res_350:
2922 
2923   ; reset modeset ctl bit 7 and bit 4
2924   ; set switches bit 3-0 to 0x09
2925 
2926   and   al, #0x6f
2927   and   ah, #0xf0
2928   or    ah, #0x09
2929   jnz   set_vert_res
2930 vert_res_200:
2931 
2932   ; set modeset ctl bit 7 and reset bit 4
2933   ; set switches bit 3-0 to 0x08
2934 
2935   and   al, #0xef
2936   or    al, #0x80
2937   and   ah, #0xf0
2938   or    ah, #0x08
2939 set_vert_res:
2940   mov   bx, # BIOSMEM_MODESET_CTL
2941   mov   [bx], al
2942   mov   bx, # BIOSMEM_SWITCHES
2943   mov   [bx], ah
2944 set_retcode:
2945   mov   ax, #0x1212
2946   pop   dx
2947   pop   bx
2948   pop   ds
2949   ret
2950 
2951 #ifdef DEBUG
2952 msg_vert_res:
2953 .ascii "Select vert res (%02x) was discarded"
2954 .byte 0x0d,0x0a,0x00
2955 #endif
2956 
2957 
2958 biosfn_enable_default_palette_loading:
2959   push  ds
2960   push  bx
2961   push  dx
2962   mov   dl, al
2963   and   dl, #0x01
2964   shl   dl, 3
2965   mov   ax, # BIOSMEM_SEG
2966   mov   ds, ax
2967   mov   bx, # BIOSMEM_MODESET_CTL
2968   mov   al, [bx]
2969   and   al, #0xf7
2970   or    al, dl
2971   mov   [bx], al
2972   mov   ax, #0x1212
2973   pop   dx
2974   pop   bx
2975   pop   ds
2976   ret
2977 
2978 
2979 biosfn_enable_video_addressing:
2980   push  bx
2981   push  dx
2982   mov   bl, al
2983   and   bl, #0x01
2984   xor   bl, #0x01
2985   shl   bl, 1
2986   mov   dx, # VGAREG_READ_MISC_OUTPUT
2987   in    al, dx
2988   and   al, #0xfd
2989   or    al, bl
2990   mov   dx, # VGAREG_WRITE_MISC_OUTPUT
2991   out   dx, al
2992   mov   ax, #0x1212
2993   pop   dx
2994   pop   bx
2995   ret
2996 
2997 
2998 biosfn_enable_grayscale_summing:
2999   push  ds
3000   push  bx
3001   push  dx
3002   mov   dl, al
3003   and   dl, #0x01
3004   xor   dl, #0x01
3005   shl   dl, 1
3006   mov   ax, # BIOSMEM_SEG
3007   mov   ds, ax
3008   mov   bx, # BIOSMEM_MODESET_CTL
3009   mov   al, [bx]
3010   and   al, #0xfd
3011   or    al, dl
3012   mov   [bx], al
3013   mov   ax, #0x1212
3014   pop   dx
3015   pop   bx
3016   pop   ds
3017   ret
3018 
3019 
3020 biosfn_enable_cursor_emulation:
3021   push  ds
3022   push  bx
3023   push  dx
3024   mov   dl, al
3025   and   dl, #0x01
3026   xor   dl, #0x01
3027   mov   ax, # BIOSMEM_SEG
3028   mov   ds, ax
3029   mov   bx, # BIOSMEM_MODESET_CTL
3030   mov   al, [bx]
3031   and   al, #0xfe
3032   or    al, dl
3033   mov   [bx], al
3034   mov   ax, #0x1212
3035   pop   dx
3036   pop   bx
3037   pop   ds
3038   ret
3039 ASM_END
3040 
3041 // --------------------------------------------------------------------------------------------
biosfn_switch_video_interface(AL,ES,DX)3042 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
3043 {
3044 #ifdef DEBUG
3045  unimplemented();
3046 #endif
3047 }
biosfn_enable_video_refresh_control(AL)3048 static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3049 {
3050 #ifdef DEBUG
3051  unimplemented();
3052 #endif
3053 }
3054 
3055 // --------------------------------------------------------------------------------------------
biosfn_write_string(flag,page,attr,count,row,col,seg,offset)3056 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3057 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3058 {
3059  Bit16u newcurs,oldcurs,dummy;
3060  Bit8u car,carattr;
3061 
3062  // Read curs info for the page
3063  biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3064 
3065  // if row=0xff special case : use current cursor position
3066  if(row==0xff)
3067   {col=oldcurs&0x00ff;
3068    row=(oldcurs&0xff00)>>8;
3069   }
3070 
3071  newcurs=row; newcurs<<=8; newcurs+=col;
3072  biosfn_set_cursor_pos(page,newcurs);
3073 
3074  while(count--!=0)
3075   {
3076    car=read_byte(seg,offset++);
3077    if((flag&0x02)!=0)
3078     attr=read_byte(seg,offset++);
3079 
3080    biosfn_write_teletype(car,page,attr,WITH_ATTR);
3081   }
3082 
3083  // Set back curs pos
3084  if((flag&0x01)==0)
3085   biosfn_set_cursor_pos(page,oldcurs);
3086 }
3087 
3088 // --------------------------------------------------------------------------------------------
3089 ASM_START
3090 biosfn_group_1A:
3091   cmp   al, #0x00
3092   je    biosfn_read_display_code
3093   cmp   al, #0x01
3094   je    biosfn_set_display_code
3095 #ifdef DEBUG
3096   call  _unknown
3097 #endif
3098   ret
3099 biosfn_read_display_code:
3100   push  ds
3101   push  ax
3102   mov   ax, # BIOSMEM_SEG
3103   mov   ds, ax
3104   mov   bx, # BIOSMEM_DCC_INDEX
3105   mov   al, [bx]
3106   mov   bl, al
3107   xor   bh, bh
3108   pop   ax
3109   mov   al, ah
3110   pop   ds
3111   ret
3112 biosfn_set_display_code:
3113   push  ds
3114   push  ax
3115   push  bx
3116   mov   ax, # BIOSMEM_SEG
3117   mov   ds, ax
3118   mov   ax, bx
3119   mov   bx, # BIOSMEM_DCC_INDEX
3120   mov   [bx], al
3121 #ifdef DEBUG
3122   mov   al, ah
3123   xor   ah, ah
3124   push  ax
3125   mov   bx, #msg_alt_dcc
3126   push  bx
3127   call  _printf
3128   add   sp, #4
3129 #endif
3130   pop   bx
3131   pop   ax
3132   mov   al, ah
3133   pop   ds
3134   ret
3135 
3136 #ifdef DEBUG
3137 msg_alt_dcc:
3138 .ascii "Alternate Display code (%02x) was discarded"
3139 .byte 0x0d,0x0a,0x00
3140 #endif
3141 ASM_END
3142 
3143 // --------------------------------------------------------------------------------------------
biosfn_read_state_info(BX,ES,DI)3144 static void biosfn_read_state_info (BX,ES,DI)
3145 Bit16u BX;Bit16u ES;Bit16u DI;
3146 {
3147  // Address of static functionality table
3148  write_word(ES,DI+0x00,&static_functionality);
3149  write_word(ES,DI+0x02,0xC000);
3150 
3151  // Hard coded copy from BIOS area. Should it be cleaner ?
3152  memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3153  memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3154 
3155  write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3156  write_byte(ES,DI+0x26,0);
3157  write_byte(ES,DI+0x27,16);
3158  write_byte(ES,DI+0x28,0);
3159  write_byte(ES,DI+0x29,8);
3160  write_byte(ES,DI+0x2a,2);
3161  write_byte(ES,DI+0x2b,0);
3162  write_byte(ES,DI+0x2c,0);
3163  write_byte(ES,DI+0x31,3);
3164  write_byte(ES,DI+0x32,0);
3165 
3166  memsetb(ES,DI+0x33,0,13);
3167 }
3168 
3169 // --------------------------------------------------------------------------------------------
3170 // --------------------------------------------------------------------------------------------
biosfn_read_video_state_size2(CX)3171 static Bit16u biosfn_read_video_state_size2 (CX)
3172      Bit16u CX;
3173 {
3174     Bit16u size;
3175     size = 0;
3176     if (CX & 1) {
3177         size += 0x46;
3178     }
3179     if (CX & 2) {
3180         size += (5 + 8 + 5) * 2 + 6;
3181     }
3182     if (CX & 4) {
3183         size += 3 + 256 * 3 + 1;
3184 }
3185     return size;
3186 }
3187 
biosfn_read_video_state_size(CX,BX)3188 static void biosfn_read_video_state_size (CX, BX)
3189      Bit16u CX; Bit16u *BX;
3190 {
3191     Bit16u ss=get_SS();
3192     write_word(ss, BX, biosfn_read_video_state_size2(CX));
3193 }
3194 
biosfn_save_video_state(CX,ES,BX)3195 static Bit16u biosfn_save_video_state (CX,ES,BX)
3196      Bit16u CX;Bit16u ES;Bit16u BX;
3197 {
3198     Bit16u i, v, crtc_addr, ar_index;
3199 
3200     crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
3201     if (CX & 1) {
3202         write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
3203         write_byte(ES, BX, inb(crtc_addr)); BX++;
3204         write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
3205         inb(VGAREG_ACTL_RESET);
3206         ar_index = inb(VGAREG_ACTL_ADDRESS);
3207         write_byte(ES, BX, ar_index); BX++;
3208         write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
3209 
3210         for(i=1;i<=4;i++){
3211             outb(VGAREG_SEQU_ADDRESS, i);
3212             write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3213         }
3214         outb(VGAREG_SEQU_ADDRESS, 0);
3215         write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3216 
3217         for(i=0;i<=0x18;i++) {
3218             outb(crtc_addr,i);
3219             write_byte(ES, BX, inb(crtc_addr+1)); BX++;
3220         }
3221 
3222         for(i=0;i<=0x13;i++) {
3223             inb(VGAREG_ACTL_RESET);
3224             outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3225             write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
3226         }
3227         inb(VGAREG_ACTL_RESET);
3228 
3229         for(i=0;i<=8;i++) {
3230             outb(VGAREG_GRDC_ADDRESS,i);
3231             write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
3232         }
3233 
3234         write_word(ES, BX, crtc_addr); BX+= 2;
3235 
3236         /* XXX: read plane latches */
3237         write_byte(ES, BX, 0); BX++;
3238         write_byte(ES, BX, 0); BX++;
3239         write_byte(ES, BX, 0); BX++;
3240         write_byte(ES, BX, 0); BX++;
3241     }
3242     if (CX & 2) {
3243         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
3244         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
3245         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
3246         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
3247         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
3248         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
3249         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
3250         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
3251         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
3252         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
3253         for(i=0;i<8;i++) {
3254             write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
3255             BX += 2;
3256         }
3257         write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
3258         write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
3259         /* current font */
3260         write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
3261         write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
3262         write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
3263         write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
3264     }
3265     if (CX & 4) {
3266         /* XXX: check this */
3267         write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
3268         write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
3269         write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
3270         // Set the whole dac always, from 0
3271         outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3272         for(i=0;i<256*3;i++) {
3273             write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
3274         }
3275         write_byte(ES, BX, 0); BX++; /* color select register */
3276     }
3277     return BX;
3278 }
3279 
biosfn_restore_video_state(CX,ES,BX)3280 static Bit16u biosfn_restore_video_state (CX,ES,BX)
3281      Bit16u CX;Bit16u ES;Bit16u BX;
3282 {
3283     Bit16u i, crtc_addr, v, addr1, ar_index;
3284 
3285     if (CX & 1) {
3286         // Reset Attribute Ctl flip-flop
3287         inb(VGAREG_ACTL_RESET);
3288 
3289         crtc_addr = read_word(ES, BX + 0x40);
3290         addr1 = BX;
3291         BX += 5;
3292 
3293         for(i=1;i<=4;i++){
3294             outb(VGAREG_SEQU_ADDRESS, i);
3295             outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3296         }
3297         outb(VGAREG_SEQU_ADDRESS, 0);
3298         outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3299 
3300         // Disable CRTC write protection
3301         outw(crtc_addr,0x0011);
3302         // Set CRTC regs
3303         for(i=0;i<=0x18;i++) {
3304             if (i != 0x11) {
3305                 outb(crtc_addr,i);
3306                 outb(crtc_addr+1, read_byte(ES, BX));
3307             }
3308             BX++;
3309         }
3310         // select crtc base address
3311         v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
3312         if (crtc_addr = 0x3d4)
3313             v |= 0x01;
3314         outb(VGAREG_WRITE_MISC_OUTPUT, v);
3315 
3316         // enable write protection if needed
3317         outb(crtc_addr, 0x11);
3318         outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
3319 
3320         // Set Attribute Ctl
3321         ar_index = read_byte(ES, addr1 + 0x03);
3322         inb(VGAREG_ACTL_RESET);
3323         for(i=0;i<=0x13;i++) {
3324             outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3325             outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
3326         }
3327         outb(VGAREG_ACTL_ADDRESS, ar_index);
3328         inb(VGAREG_ACTL_RESET);
3329 
3330         for(i=0;i<=8;i++) {
3331             outb(VGAREG_GRDC_ADDRESS,i);
3332             outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
3333         }
3334         BX += 2; /* crtc_addr */
3335         BX += 4; /* plane latches */
3336 
3337         outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
3338         outb(crtc_addr, read_byte(ES, addr1)); addr1++;
3339         outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
3340         addr1++;
3341         outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
3342     }
3343     if (CX & 2) {
3344         write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
3345         write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
3346         write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
3347         write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
3348         write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
3349         write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
3350         write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
3351         write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
3352         write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
3353         write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
3354         for(i=0;i<8;i++) {
3355             write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
3356             BX += 2;
3357         }
3358         write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
3359         write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
3360         /* current font */
3361         write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
3362         write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
3363         write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
3364         write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
3365     }
3366     if (CX & 4) {
3367         BX++;
3368         v = read_byte(ES, BX); BX++;
3369         outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
3370         // Set the whole dac always, from 0
3371         outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3372         for(i=0;i<256*3;i++) {
3373             outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
3374         }
3375         BX++;
3376         outb(VGAREG_DAC_WRITE_ADDRESS, v);
3377     }
3378     return BX;
3379 }
3380 
3381 // ============================================================================================
3382 //
3383 // Video Utils
3384 //
3385 // ============================================================================================
3386 
3387 // --------------------------------------------------------------------------------------------
find_vga_entry(mode)3388 static Bit8u find_vga_entry(mode)
3389 Bit8u mode;
3390 {
3391  Bit8u i,line=0xFF;
3392  for(i=0;i<=MODE_MAX;i++)
3393   if(vga_modes[i].svgamode==mode)
3394    {line=i;
3395     break;
3396    }
3397  return line;
3398 }
3399 
3400 /* =========================================================== */
3401 /*
3402  * Misc Utils
3403 */
3404 /* =========================================================== */
3405 
3406 // --------------------------------------------------------------------------------------------
memsetb(seg,offset,value,count)3407 static void memsetb(seg,offset,value,count)
3408   Bit16u seg;
3409   Bit16u offset;
3410   Bit16u value;
3411   Bit16u count;
3412 {
3413 ASM_START
3414   push bp
3415   mov  bp, sp
3416 
3417     push ax
3418     push cx
3419     push es
3420     push di
3421 
3422     mov  cx, 10[bp] ; count
3423     cmp  cx, #0x00
3424     je   memsetb_end
3425     mov  ax, 4[bp] ; segment
3426     mov  es, ax
3427     mov  ax, 6[bp] ; offset
3428     mov  di, ax
3429     mov  al, 8[bp] ; value
3430     cld
3431     rep
3432      stosb
3433 
3434 memsetb_end:
3435     pop di
3436     pop es
3437     pop cx
3438     pop ax
3439 
3440   pop bp
3441 ASM_END
3442 }
3443 
3444 // --------------------------------------------------------------------------------------------
memsetw(seg,offset,value,count)3445 static void memsetw(seg,offset,value,count)
3446   Bit16u seg;
3447   Bit16u offset;
3448   Bit16u value;
3449   Bit16u count;
3450 {
3451 ASM_START
3452   push bp
3453   mov  bp, sp
3454 
3455     push ax
3456     push cx
3457     push es
3458     push di
3459 
3460     mov  cx, 10[bp] ; count
3461     cmp  cx, #0x00
3462     je   memsetw_end
3463     mov  ax, 4[bp] ; segment
3464     mov  es, ax
3465     mov  ax, 6[bp] ; offset
3466     mov  di, ax
3467     mov  ax, 8[bp] ; value
3468     cld
3469     rep
3470      stosw
3471 
3472 memsetw_end:
3473     pop di
3474     pop es
3475     pop cx
3476     pop ax
3477 
3478   pop bp
3479 ASM_END
3480 }
3481 
3482 // --------------------------------------------------------------------------------------------
memcpyb(dseg,doffset,sseg,soffset,count)3483 static void memcpyb(dseg,doffset,sseg,soffset,count)
3484   Bit16u dseg;
3485   Bit16u doffset;
3486   Bit16u sseg;
3487   Bit16u soffset;
3488   Bit16u count;
3489 {
3490 ASM_START
3491   push bp
3492   mov  bp, sp
3493 
3494     push ax
3495     push cx
3496     push es
3497     push di
3498     push ds
3499     push si
3500 
3501     mov  cx, 12[bp] ; count
3502     cmp  cx, #0x0000
3503     je   memcpyb_end
3504     mov  ax, 4[bp] ; dsegment
3505     mov  es, ax
3506     mov  ax, 6[bp] ; doffset
3507     mov  di, ax
3508     mov  ax, 8[bp] ; ssegment
3509     mov  ds, ax
3510     mov  ax, 10[bp] ; soffset
3511     mov  si, ax
3512     cld
3513     rep
3514      movsb
3515 
3516 memcpyb_end:
3517     pop si
3518     pop ds
3519     pop di
3520     pop es
3521     pop cx
3522     pop ax
3523 
3524   pop bp
3525 ASM_END
3526 }
3527 
3528 // --------------------------------------------------------------------------------------------
memcpyw(dseg,doffset,sseg,soffset,count)3529 static void memcpyw(dseg,doffset,sseg,soffset,count)
3530   Bit16u dseg;
3531   Bit16u doffset;
3532   Bit16u sseg;
3533   Bit16u soffset;
3534   Bit16u count;
3535 {
3536 ASM_START
3537   push bp
3538   mov  bp, sp
3539 
3540     push ax
3541     push cx
3542     push es
3543     push di
3544     push ds
3545     push si
3546 
3547     mov  cx, 12[bp] ; count
3548     cmp  cx, #0x0000
3549     je   memcpyw_end
3550     mov  ax, 4[bp] ; dsegment
3551     mov  es, ax
3552     mov  ax, 6[bp] ; doffset
3553     mov  di, ax
3554     mov  ax, 8[bp] ; ssegment
3555     mov  ds, ax
3556     mov  ax, 10[bp] ; soffset
3557     mov  si, ax
3558     cld
3559     rep
3560      movsw
3561 
3562 memcpyw_end:
3563     pop si
3564     pop ds
3565     pop di
3566     pop es
3567     pop cx
3568     pop ax
3569 
3570   pop bp
3571 ASM_END
3572 }
3573 
3574 /* =========================================================== */
3575 /*
3576  * These functions where ripped from Kevin's rombios.c
3577 */
3578 /* =========================================================== */
3579 
3580 // --------------------------------------------------------------------------------------------
3581 static Bit8u
read_byte(seg,offset)3582 read_byte(seg, offset)
3583   Bit16u seg;
3584   Bit16u offset;
3585 {
3586 ASM_START
3587   push bp
3588   mov  bp, sp
3589 
3590     push bx
3591     push ds
3592     mov  ax, 4[bp] ; segment
3593     mov  ds, ax
3594     mov  bx, 6[bp] ; offset
3595     mov  al, [bx]
3596     ;; al = return value (byte)
3597     pop  ds
3598     pop  bx
3599 
3600   pop  bp
3601 ASM_END
3602 }
3603 
3604 // --------------------------------------------------------------------------------------------
3605 static Bit16u
3606 read_word(seg, offset)
3607   Bit16u seg;
3608   Bit16u offset;
3609 {
3610 ASM_START
3611   push bp
3612   mov  bp, sp
3613 
3614     push bx
3615     push ds
3616     mov  ax, 4[bp] ; segment
3617     mov  ds, ax
3618     mov  bx, 6[bp] ; offset
3619     mov  ax, [bx]
3620     ;; ax = return value (word)
3621     pop  ds
3622     pop  bx
3623 
3624   pop  bp
3625 ASM_END
3626 }
3627 
3628 // --------------------------------------------------------------------------------------------
3629 static void
3630 write_byte(seg, offset, data)
3631   Bit16u seg;
3632   Bit16u offset;
3633   Bit8u  data;
3634 {
3635 ASM_START
3636   push bp
3637   mov  bp, sp
3638 
3639     push ax
3640     push bx
3641     push ds
3642     mov  ax, 4[bp] ; segment
3643     mov  ds, ax
3644     mov  bx, 6[bp] ; offset
3645     mov  al, 8[bp] ; data byte
3646     mov  [bx], al  ; write data byte
3647     pop  ds
3648     pop  bx
3649     pop  ax
3650 
3651   pop  bp
3652 ASM_END
3653 }
3654 
3655 // --------------------------------------------------------------------------------------------
3656 static void
3657 write_word(seg, offset, data)
3658   Bit16u seg;
3659   Bit16u offset;
3660   Bit16u data;
3661 {
3662 ASM_START
3663   push bp
3664   mov  bp, sp
3665 
3666     push ax
3667     push bx
3668     push ds
3669     mov  ax, 4[bp] ; segment
3670     mov  ds, ax
3671     mov  bx, 6[bp] ; offset
3672     mov  ax, 8[bp] ; data word
3673     mov  [bx], ax  ; write data word
3674     pop  ds
3675     pop  bx
3676     pop  ax
3677 
3678   pop  bp
3679 ASM_END
3680 }
3681 
3682 // --------------------------------------------------------------------------------------------
3683  Bit8u
3684 inb(port)
3685   Bit16u port;
3686 {
3687 ASM_START
3688   push bp
3689   mov  bp, sp
3690 
3691     push dx
3692     mov  dx, 4[bp]
3693     in   al, dx
3694     pop  dx
3695 
3696   pop  bp
3697 ASM_END
3698 }
3699 
3700   Bit16u
3701 inw(port)
3702   Bit16u port;
3703 {
3704 ASM_START
3705   push bp
3706   mov  bp, sp
3707 
3708     push dx
3709     mov  dx, 4[bp]
3710     in   ax, dx
3711     pop  dx
3712 
3713   pop  bp
3714 ASM_END
3715 }
3716 
3717 // --------------------------------------------------------------------------------------------
3718   void
3719 outb(port, val)
3720   Bit16u port;
3721   Bit8u  val;
3722 {
3723 ASM_START
3724   push bp
3725   mov  bp, sp
3726 
3727     push ax
3728     push dx
3729     mov  dx, 4[bp]
3730     mov  al, 6[bp]
3731     out  dx, al
3732     pop  dx
3733     pop  ax
3734 
3735   pop  bp
3736 ASM_END
3737 }
3738 
3739 // --------------------------------------------------------------------------------------------
3740   void
3741 outw(port, val)
3742   Bit16u port;
3743   Bit16u  val;
3744 {
3745 ASM_START
3746   push bp
3747   mov  bp, sp
3748 
3749     push ax
3750     push dx
3751     mov  dx, 4[bp]
3752     mov  ax, 6[bp]
3753     out  dx, ax
3754     pop  dx
3755     pop  ax
3756 
3757   pop  bp
3758 ASM_END
3759 }
3760 
3761 Bit16u get_SS()
3762 {
3763 ASM_START
3764   mov  ax, ss
3765 ASM_END
3766 }
3767 
3768 #ifdef DEBUG
3769 void unimplemented()
3770 {
3771  printf("--> Unimplemented\n");
3772 }
3773 
3774 void unknown()
3775 {
3776  printf("--> Unknown int10\n");
3777 }
3778 #endif
3779 
3780 // --------------------------------------------------------------------------------------------
3781 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3782 void printf(s)
3783   Bit8u *s;
3784 {
3785   Bit8u c, format_char;
3786   Boolean  in_format;
3787   unsigned format_width, i;
3788   Bit16u  *arg_ptr;
3789   Bit16u   arg_seg, arg, digit, nibble, shift_count;
3790 
3791   arg_ptr = &s;
3792   arg_seg = get_SS();
3793 
3794   in_format = 0;
3795   format_width = 0;
3796 
3797   while (c = read_byte(0xc000, s)) {
3798     if ( c == '%' ) {
3799       in_format = 1;
3800       format_width = 0;
3801       }
3802     else if (in_format) {
3803       if ( (c>='0') && (c<='9') ) {
3804         format_width = (format_width * 10) + (c - '0');
3805         }
3806       else if (c == 'x') {
3807         arg_ptr++; // increment to next arg
3808         arg = read_word(arg_seg, arg_ptr);
3809         if (format_width == 0)
3810           format_width = 4;
3811         i = 0;
3812         digit = format_width - 1;
3813         for (i=0; i<format_width; i++) {
3814           nibble = (arg >> (4 * digit)) & 0x000f;
3815           if (nibble <= 9)
3816             outb(0x0500, nibble + '0');
3817           else
3818             outb(0x0500, (nibble - 10) + 'A');
3819           digit--;
3820           }
3821         in_format = 0;
3822         }
3823       //else if (c == 'd') {
3824       //  in_format = 0;
3825       //  }
3826       }
3827     else {
3828       outb(0x0500, c);
3829       }
3830     s ++;
3831     }
3832 }
3833 #endif
3834 
3835 ASM_START
3836   ; get LFB address from PCI
3837   ; in - ax: PCI device vendor
3838   ; out - ax: LFB address (high 16 bit)
3839   ;; NOTE - may be called in protected mode
3840 _pci_get_lfb_addr:
3841   push bx
3842   push cx
3843   push dx
3844   push eax
3845     mov bx, ax
3846     xor cx, cx
3847     mov dl, #0x00
3848     call pci_read_reg
3849     cmp ax, #0xffff
3850     jz pci_get_lfb_addr_5
3851  pci_get_lfb_addr_3:
3852     mov dl, #0x00
3853     call pci_read_reg
3854     cmp ax, bx ;; check vendor
3855     jz pci_get_lfb_addr_4
3856     add cx, #0x8
3857     cmp cx, #0x200 ;; search bus #0 and #1
3858     jb pci_get_lfb_addr_3
3859  pci_get_lfb_addr_5:
3860     xor dx, dx ;; no LFB
3861     jmp pci_get_lfb_addr_6
3862  pci_get_lfb_addr_4:
3863     mov dl, #0x10 ;; I/O space #0
3864     call pci_read_reg
3865     test ax, #0xfff1
3866     jnz pci_get_lfb_addr_5
3867     shr eax, #16
3868     mov dx, ax ;; LFB address
3869  pci_get_lfb_addr_6:
3870   pop eax
3871   mov ax, dx
3872   pop dx
3873   pop cx
3874   pop bx
3875   ret
3876 
3877   ; read PCI register
3878   ; in - cx: device/function
3879   ; in - dl: register
3880   ; out - eax: value
3881 pci_read_reg:
3882   mov eax, #0x00800000
3883   mov ax, cx
3884   shl eax, #8
3885   mov al, dl
3886   mov dx, #0xcf8
3887   out dx, eax
3888   add dl, #4
3889   in  eax, dx
3890   ret
3891 ASM_END
3892 
3893 #ifdef VBE
3894 #include "vbe.c"
3895 #endif
3896 
3897 #ifdef CIRRUS
3898 #include "clext.c"
3899 #endif
3900 
3901 // --------------------------------------------------------------------------------------------
3902 
3903 ASM_START
3904 ;; DATA_SEG_DEFS_HERE
3905 ASM_END
3906 
3907 ASM_START
3908 .ascii "vgabios ends here"
3909 .byte  0x00
3910 vgabios_end:
3911 .byte 0xCB
3912 ;; BLOCK_STRINGS_BEGIN
3913 ASM_END
3914