VirtualBox

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

Last change on this file since 82781 was 82278, checked in by vboxsync, 5 years ago

VGABIOS: Use inlines instead of calls for far memory access. Saves over 700 bytes of code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 72.9 KB
Line 
1// ============================================================================================
2/*
3 * vgabios.c
4 */
5// ============================================================================================
6//
7// Copyright (C) 2001,2002 the LGPL VGABios developers Team
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22//
23// ============================================================================================
24//
25// This VGA Bios is specific to the plex86/bochs Emulated VGA card.
26// You can NOT drive any physical vga card with it.
27//
28// ============================================================================================
29//
30// This file contains code ripped from :
31// - rombios.c of plex86
32//
33// This VGA Bios contains fonts from :
34// - fntcol16.zip (c) by Joseph Gil avalable at :
35// ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
36// These fonts are public domain
37//
38// This VGA Bios is based on information taken from :
39// - Kevin Lawton's vga card emulation for bochs/plex86
40// - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
41// - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
42// - Michael Abrash's Graphics Programming Black Book
43// - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex
44// - DOSEMU 1.0.1 source code for several tables values and formulas
45//
46// Thanks for patches, comments and ideas to :
47// - techt@pikeonline.net
48//
49// ============================================================================================
50
51
52/*
53 * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
54 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
55 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
56 * a choice of LGPL license versions is made available with the language indicating
57 * that LGPLv2 or any later version may be used, or where a choice of which version
58 * of the LGPL is applied is otherwise unspecified.
59 */
60
61#include <inttypes.h>
62#include "vgabios.h"
63
64#ifdef VBE
65#include "vbe.h"
66#endif
67
68#include "inlines.h"
69
70/* Declares */
71extern void vgabios_int10_handler(void);
72#pragma aux vgabios_int10_handler "*";
73
74// Output
75void __cdecl unimplemented(void);
76void __cdecl unknown(void);
77
78static uint8_t find_vga_entry();
79
80extern uint8_t xread_byte(uint16_t seg, uint16_t offset);
81
82#ifdef VBE
83extern uint16_t __cdecl vbe_has_vbe_display(void);
84extern void vbe_init(void);
85#endif
86
87void set_int_vector(uint8_t int_vec, void *offset)
88{
89 void __far * __far *ivt = 0;
90
91 ivt[int_vec] = 0xC000 :> offset;
92}
93
94//@todo!!
95#if 0
96
97vgabios_name:
98#ifdef VBOX
99.ascii "VirtualBox VGA BIOS"
100#else
101.ascii "Plex86/Bochs VGABios"
102#endif
103.ascii " "
104.byte 0x00
105
106#ifndef VBOX
107vgabios_version:
108#ifndef VGABIOS_VERS
109.ascii "current-cvs"
110#else
111.ascii VGABIOS_VERS
112#endif
113.ascii " "
114
115vgabios_date:
116.ascii VGABIOS_DATE
117.byte 0x0a,0x0d
118.byte 0x00
119#endif
120
121#ifndef VBOX
122char vgabios_copyright[] = "(C) 2003 the LGPL VGABios developers Team\r\n";
123char vgabios_license[] = "This VGA/VBE Bios is released under the GNU LGPL\r\n\r\n";
124char vgabios_website[] = "Please visit :\r\n" \
125 " . http://www.plex86.org\r\n" \
126 " . http://bochs.sourceforge.net\r\n" \
127 " . http://www.nongnu.org/vgabios\r\n\r\n"
128#endif
129
130#endif
131
132extern void set_mode(int mode);
133#pragma aux set_mode = \
134 "xor ah, ah" \
135 "int 10h" \
136 parm [ax];
137
138char msg_vga_init[] = "Oracle VM VirtualBox Version " VBOX_VERSION_STRING " VGA BIOS\r\n";
139
140/*
141 * Boot time harware inits
142 */
143void init_vga_card(void)
144{
145 /* Switch to color mode and enable CPU access 480 lines. */
146 outb(0x3C2, 0xC3);
147 /* More than 64k 3C4/04. */
148 /// @todo 16-bit write
149 outb(0x3C4, 0x04);
150 outb(0x3C5, 0x02);
151
152#ifdef DEBUG_VGA
153 printf(msg_vga_init);
154#endif
155}
156
157#include "vgatables.h"
158#include "vgadefs.h"
159
160// --------------------------------------------------------------------------------------------
161/*
162 * Boot time bios area inits
163 */
164void init_bios_area(void)
165{
166 uint8_t __far *bda;
167
168 bda = 0x40 :> 0;
169
170 /* Indicate 80x25 color was detected. */
171 bda[BIOSMEM_INITIAL_MODE] = (bda[BIOSMEM_INITIAL_MODE] & 0xcf) | 0x20;
172 /* Just for the first int10 find its children. */
173
174 /* The default char height. */
175 bda[BIOSMEM_CHAR_HEIGHT] = 16;
176 /* Clear the screen. */
177 bda[BIOSMEM_VIDEO_CTL] = 0x60;
178 /* Set the basic screen we have. */
179 bda[BIOSMEM_SWITCHES] = 0xf9;
180 /* Set the basic mode set options. */
181 bda[BIOSMEM_MODESET_CTL] = 0x51;
182 /* Set the default MSR. */
183 bda[BIOSMEM_CURRENT_MSR] = 0x09;
184}
185
186struct dcc {
187 uint8_t n_ent;
188 uint8_t version;
189 uint8_t max_code;
190 uint8_t reserved;
191 uint16_t dccs[16];
192} dcc_table = {
193 16,
194 1,
195 7,
196 0
197};
198
199struct ssa {
200 uint16_t size;
201 void __far *dcc;
202 void __far *sacs;
203 void __far *pal;
204 void __far *resvd[3];
205
206} secondary_save_area = {
207 sizeof(struct ssa),
208 &dcc_table
209};
210
211void __far *video_save_pointer_table[7] = {
212 &video_param_table,
213 0,
214 0,
215 0,
216 &secondary_save_area
217};
218
219// ============================================================================================
220//
221// Init Entry point
222//
223// ============================================================================================
224void __far __cdecl vgabios_init_func(void)
225{
226 init_vga_card();
227 init_bios_area();
228#ifdef VBE
229 vbe_init();
230#endif
231 set_int_vector(0x10, vgabios_int10_handler);
232#ifdef CIRRUS
233 cirrus_init();
234#endif
235
236#ifndef VBOX
237 display_splash_screen();
238
239 // init video mode and clear the screen
240 // @@AS: Do not remove this init, because it will break VESA graphics
241 set_mode(3);
242
243 display_info();
244
245#ifdef VBE
246 vbe_display_info();
247#endif
248
249#ifdef CIRRUS
250 cirrus_display_info();
251#endif
252
253#else /* VBOX */
254
255//#ifdef DEBUG_bird
256 /* Init video mode and clear the screen */
257 set_mode(3);
258//#endif
259#endif /* VBOX */
260}
261
262#include "vgafonts.h"
263
264#ifndef VBOX
265// --------------------------------------------------------------------------------------------
266/*
267 * Boot time Splash screen
268 */
269static void display_splash_screen()
270{
271}
272
273// --------------------------------------------------------------------------------------------
274/*
275 * Tell who we are
276 */
277
278static void display_string(void)
279{
280 // Get length of string
281ASM_START
282 mov ax,ds
283 mov es,ax
284 mov di,si
285 xor cx,cx
286 not cx
287 xor al,al
288 cld
289 repne
290 scasb
291 not cx
292 dec cx
293 push cx
294
295 mov ax,#0x0300
296 mov bx,#0x0000
297 int #0x10
298
299 pop cx
300 mov ax,#0x1301
301 mov bx,#0x000b
302 mov bp,si
303 int #0x10
304ASM_END
305}
306
307static void display_info(void)
308{
309 display_string(vgabios_name);
310 display_string(vgabios_version);
311 display_string(vgabios_copyright);
312 display_string(vgabios_license);
313 display_string(vgabios_website);
314}
315
316#endif
317
318// --------------------------------------------------------------------------------------------
319#ifdef VGA_DEBUG
320void __cdecl int10_debugmsg(uint16_t DI, uint16_t SI, uint16_t BP, uint16_t SP, uint16_t BX,
321 uint16_t DX, uint16_t CX, uint16_t AX, uint16_t DS, uint16_t ES, uint16_t FLAGS)
322{
323 /* Function 0Eh is write char and would generate way too much output. */
324 if (GET_AH() != 0x0E)
325 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n", GET_AH(), GET_AL(), BX, CX, DX);
326}
327#endif
328
329static void vga_get_cursor_pos(uint8_t page, uint16_t STACK_BASED *scans, uint16_t STACK_BASED *loc)
330{
331 if (page > 7) {
332 *scans = 0;
333 *loc = 0;
334 } else {
335 // FIXME should handle VGA 14/16 lines
336 *scans = read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE);
337 *loc = read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS + page * 2);
338 }
339}
340
341/* Look for a glyph bitmap in a given font. */
342static uint16_t vga_find_glyph(uint8_t __far *font, uint8_t STACK_BASED *glyph, uint8_t cp, uint16_t n_glyphs, uint8_t cheight)
343{
344 uint16_t codepoint = 0; /* Zero returned when glyph not found. */
345
346 while (n_glyphs--) {
347 if (!repe_cmpsb(font, glyph, cheight)) {
348 codepoint = cp | 0x8000; /* Found matching glyph! */
349 break;
350 }
351 font += cheight;
352 ++cp; /* Increment code point number. */
353 }
354 return codepoint;
355}
356
357static void vga_read_glyph_planar(uint8_t __far *vptr, uint16_t stride, uint8_t STACK_BASED *glyph, uint8_t cheight)
358{
359 /* Set Mode Register (GR5) to Read Mode 1. Assuming default register
360 * state from our mode set, this does all the hard work for us such that
361 * reading a byte from video memory gives us a bit mask for all eight
362 * pixels, for both 16-color and monochrome modes.
363 */
364 outw(VGAREG_GRDC_ADDRESS, 0x0805);
365
366 while (cheight--) {
367 *glyph++ = ~*vptr;
368 vptr += stride;
369 }
370
371 /* Put GR5 back to Read Mode 0. */
372 outw(VGAREG_GRDC_ADDRESS, 0x0005);
373}
374
375static uint16_t vga_char_ofs_planar(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols, uint8_t page, uint8_t cheight)
376{
377 uint16_t ofs;
378
379 ofs = ycurs * nbcols * cheight + xcurs;
380 ofs += page * read_word(BIOSMEM_SEG, BIOSMEM_PAGE_SIZE);
381
382 return ofs;
383}
384
385static uint8_t vga_read_char_planar(uint16_t nbcols, uint16_t ofs, uint8_t cheight)
386{
387 uint8_t glyph[16]; /* NB: Don't try taller characters! */
388
389 vga_read_glyph_planar(0xA000 :> (uint8_t *)ofs, nbcols, &glyph, cheight);
390
391 /* Look through font pointed to by INT 43h. */
392 return vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 256, cheight);
393}
394
395static uint16_t vga_char_ofs_linear(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols, uint8_t page, uint8_t cheight)
396{
397 uint16_t ofs;
398
399 ofs = ycurs * nbcols * cheight + xcurs;
400 ofs *= 8;
401 return ofs;
402}
403
404static void vga_read_glyph_linear(uint8_t __far *vptr, uint16_t stride, uint8_t STACK_BASED *glyph, uint8_t cheight)
405{
406 uint8_t bmap, cbit;
407 int i;
408
409 /* Zero pixels are background, everything else foreground. */
410 while (cheight--) {
411 bmap = 0;
412 cbit = 0x80;
413 for (i = 0; i < 8; ++i) {
414 if (vptr[i])
415 bmap |= cbit;
416 cbit >>= 1;
417 }
418 *glyph++ = bmap;
419 vptr += stride;
420 }
421}
422
423static uint8_t vga_read_char_linear(uint16_t nbcols, uint16_t ofs, uint8_t cheight)
424{
425 uint8_t glyph[16]; /* NB: Don't try taller characters! */
426
427 vga_read_glyph_linear(0xA000 :> (uint8_t *)ofs, nbcols * 8, &glyph, cheight);
428
429 /* Look through font pointed to by INT 43h. */
430 return vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 256, cheight);
431}
432
433static uint8_t vga_read_2bpp_char(uint8_t __far *vptr)
434{
435 uint16_t mask, pixb;
436 uint8_t bmap, cbit;
437 int i;
438
439 mask = 0xC000; /* Check two bits at a time to see if they're zero. */
440 cbit = 0x80; /* Go from left to right. */
441 bmap = 0;
442 pixb = swap_16(*((uint16_t __far *)vptr));
443 /* Go through 8 lines/words. */
444 for (i = 0; i < 8; ++i) {
445 if (pixb & mask)
446 bmap |= cbit;
447 cbit >>= 1;
448 mask >>= 2;
449 }
450 return bmap;
451}
452
453static void vga_read_glyph_cga(uint16_t ofs, uint8_t STACK_BASED *glyph, uint8_t mode)
454{
455 int i;
456 uint8_t __far *vptr;
457
458 /* The font size is fixed at 8x8. Stride is always 80 bytes because the
459 * mode is either 80 characters wide at 1bpp or 40 characters at 2bpp.
460 */
461 if (mode != 6) {
462 /* Adjust offset for 2bpp. */
463 vptr = 0xB800 :> (uint8_t *)(ofs * 2);
464 /* For 2bpp modes, we have to extract the bits by hand. */
465 for (i = 0; i < 4; ++i) {
466 *glyph++ = vga_read_2bpp_char(vptr);
467 *glyph++ = vga_read_2bpp_char(vptr + 0x2000);
468 vptr += 80;
469 }
470 } else {
471 vptr = 0xB800 :> (uint8_t *)ofs;
472 for (i = 0; i < 4; ++i) {
473 *glyph++ = vptr[0];
474 *glyph++ = vptr[0x2000];
475 vptr += 80;
476 }
477 }
478}
479
480static uint16_t vga_char_ofs_cga(uint8_t xcurs, uint8_t ycurs, uint16_t nbcols)
481{
482 /* Multiply ony by 8 due to line interleaving. NB: Caller
483 * has to multiply the result for two for 2bpp mode.
484 */
485 return ycurs * nbcols * 4 + xcurs;
486}
487
488static uint8_t vga_read_char_cga(uint16_t ofs, uint8_t mode)
489{
490 uint8_t glyph[8]; /* Char height is hardcoded to 8. */
491 uint16_t found;
492
493 /* Segment would be B000h for mono modes; we don't do those. */
494 vga_read_glyph_cga(ofs, &glyph, mode);
495
496 /* Look through the first half of the font pointed to by INT 43h. */
497 found = vga_find_glyph((void __far *)read_dword(0, 0x43 * 4), &glyph, 0, 128, 8);
498 /* If not found, look for the second half pointed to by INT 1Fh */
499 if (!(found & 0x8000)) {
500 void __far *int1f;
501
502 int1f = (void __far *)read_dword(0, 0x1f * 4);
503 if (int1f) /* If null pointer, skip. */
504 found = vga_find_glyph(int1f, &glyph, 128, 128, 8);
505 }
506 return found;
507}
508
509static void vga_read_char_attr(uint8_t page, uint16_t STACK_BASED *chr_atr)
510{
511 uint8_t xcurs, ycurs, mode, line, cheight;
512 uint16_t nbcols, nbrows, address;
513 uint16_t cursor, dummy, ofs;
514
515 // Get the mode
516 mode = read_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE);
517 line = find_vga_entry(mode);
518 if (line == 0xFF)
519 return;
520
521 // Get the cursor pos for the page
522 vga_get_cursor_pos(page, &dummy, &cursor);
523 xcurs = cursor & 0x00ff;
524 ycurs = (cursor & 0xff00) >> 8;
525
526 // Get the dimensions
527 nbrows = read_byte(BIOSMEM_SEG, BIOSMEM_NB_ROWS) + 1;
528 nbcols = read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS);
529
530 if (vga_modes[line].class == TEXT) {
531 // Compute the address
532 address = SCREEN_MEM_START(nbcols, nbrows, page) + (xcurs + ycurs * nbcols) * 2;
533 *chr_atr = read_word(vga_modes[line].sstart, address);
534 } else {
535 switch (vga_modes[line].memmodel) {
536 case CGA:
537 /* For CGA graphics, font size is hardcoded at 8x8. */
538 ofs = vga_char_ofs_cga(xcurs, ycurs, nbcols);
539 *chr_atr = vga_read_char_cga(ofs, mode);
540 break;
541 case PLANAR1:
542 case PLANAR4:
543 cheight = read_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT);
544 ofs = vga_char_ofs_planar(xcurs, ycurs, nbcols, page, cheight);
545 *chr_atr = vga_read_char_planar(nbcols, ofs, cheight);
546 break;
547 case LINEAR8:
548 cheight = read_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT);
549 ofs = vga_char_ofs_linear(xcurs, ycurs, nbcols, page, cheight);
550 *chr_atr = vga_read_char_linear(nbcols, ofs, cheight);
551 break;
552 default:
553#ifdef VGA_DEBUG
554 unimplemented();
555#endif
556 break;
557 }
558 }
559}
560
561static void vga_get_font_info (uint16_t func, uint16_t STACK_BASED *u_seg, uint16_t STACK_BASED *u_ofs,
562 uint16_t STACK_BASED *c_height, uint16_t STACK_BASED *max_row)
563{
564 void __far *ptr;
565
566 switch (func) {
567 case 0x00:
568 ptr = (void __far *)read_dword(0x00, 0x1f * 4);
569 break;
570 case 0x01:
571 ptr = (void __far *)read_dword(0x00, 0x43 * 4);
572 break;
573 case 0x02:
574 ptr = 0xC000 :> vgafont14;
575 break;
576 case 0x03:
577 ptr = 0xC000 :> vgafont8;
578 break;
579 case 0x04:
580 ptr = 0xC000 :> (vgafont8 + 128 * 8);
581 break;
582 case 0x05:
583 ptr = 0xC000 :> vgafont14alt;
584 break;
585 case 0x06:
586 ptr = 0xC000 :> vgafont16;
587 break;
588 case 0x07:
589 ptr = 0xC000 :> vgafont16alt;
590 break;
591 default:
592#ifdef VGA_DEBUG
593 printf("Get font info subfn(%02x) not implemented\n", func);
594#endif
595 return;
596 }
597 /* Split the far pointer and write it back. */
598 *u_ofs = (uint16_t)ptr;
599 *u_seg = (uint32_t)ptr >> 16;
600
601 /* The character height (effectively bytes per glyph). */
602 *c_height = read_byte(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT);
603
604 /* The highest row number. */
605 *max_row = read_byte(BIOSMEM_SEG, BIOSMEM_NB_ROWS);
606}
607
608static void vga_read_pixel(uint8_t page, uint16_t col, uint16_t row, uint16_t STACK_BASED *pixel)
609{
610 uint8_t mode, line, mask, attr, data, i;
611 uint16_t addr;
612
613 /* Determine current mode characteristics. */
614 mode = read_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_MODE);
615 line = find_vga_entry(mode);
616 if (line == 0xFF)
617 return;
618 if (vga_modes[line].class == TEXT)
619 return;
620
621 /* Read data depending on memory model. */
622 switch (vga_modes[line].memmodel) {
623 case PLANAR4:
624 case PLANAR1:
625 addr = col / 8 + row * read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS);
626 addr += read_word(BIOSMEM_SEG, BIOSMEM_PAGE_SIZE) * page;
627 mask = 0x80 >> (col & 0x07);
628 attr = 0x00;
629 for (i = 0; i < 4; i++) {
630 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
631 data = read_byte(0xa000,addr) & mask;
632 if (data > 0)
633 attr |= (0x01 << i);
634 }
635 break;
636 case CGA:
637 addr = (col >> (4 - vga_modes[line].pixbits)) + (row >> 1) * 80;
638 if (row & 1)
639 addr += 0x2000;
640 data = read_byte(0xb800, addr);
641 if (vga_modes[line].pixbits == 2)
642 attr = (data >> ((3 - (col & 0x03)) * 2)) & 0x03;
643 else
644 attr = (data >> (7 - (col & 0x07))) & 0x01;
645 break;
646 case LINEAR8:
647 addr = col + row * (read_word(BIOSMEM_SEG, BIOSMEM_NB_COLS) * 8);
648 attr = read_byte(0xa000, addr);
649 break;
650 default:
651#ifdef VGA_DEBUG
652 unimplemented();
653#endif
654 attr = 0;
655 }
656 *(uint8_t STACK_BASED *)pixel = attr;
657}
658
659
660
661// --------------------------------------------------------------------------------------------
662/*static*/ void biosfn_perform_gray_scale_summing(uint16_t start, uint16_t count)
663{uint8_t r,g,b;
664 uint16_t i;
665 uint16_t index;
666
667 inb(VGAREG_ACTL_RESET);
668 outb(VGAREG_ACTL_ADDRESS,0x00);
669
670 for( index = 0; index < count; index++ )
671 {
672 // set read address and switch to read mode
673 outb(VGAREG_DAC_READ_ADDRESS,start);
674 // get 6-bit wide RGB data values
675 r=inb( VGAREG_DAC_DATA );
676 g=inb( VGAREG_DAC_DATA );
677 b=inb( VGAREG_DAC_DATA );
678
679 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
680 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
681
682 if(i>0x3f)i=0x3f;
683
684 // set write address and switch to write mode
685 outb(VGAREG_DAC_WRITE_ADDRESS,start);
686 // write new intensity value
687 outb( VGAREG_DAC_DATA, i&0xff );
688 outb( VGAREG_DAC_DATA, i&0xff );
689 outb( VGAREG_DAC_DATA, i&0xff );
690 start++;
691 }
692 inb(VGAREG_ACTL_RESET);
693 outb(VGAREG_ACTL_ADDRESS,0x20);
694#ifdef VBOX
695 inb(VGAREG_ACTL_RESET);
696#endif /* VBOX */
697}
698
699// --------------------------------------------------------------------------------------------
700static void biosfn_set_cursor_shape(uint8_t CH, uint8_t CL)
701{
702 uint16_t cheight, curs, crtc_addr;
703 int cga_emu;
704
705 /* Unmodified input is stored in the BDA. */
706 curs = (CH << 8) + CL;
707 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_TYPE, curs);
708
709 /* Check if VGA is active. If not, just write the input to the CRTC. */
710 if (!(read_byte(BIOSMEM_SEG, BIOSMEM_VIDEO_CTL) & 8)) {
711 /* Trying to disable the cursor? */
712 if ((CH & 0x60) == 0x20) {
713 /* Special IBM-compatible value to turn off cursor. */
714 CH = 0x1E;
715 CL = 0;
716 } else {
717 cga_emu = !(read_byte(BIOSMEM_SEG, BIOSMEM_VIDEO_CTL) & 1);
718
719 /* If CGA cursor emulation is on and this is a text mode, adjust.
720 * But if cursor star or end is bigger than 31, don't adjust.
721 */
722 /// @todo Figure out if this is a text mode
723 if (cga_emu /* && text mode*/ && (CH < 32) && (CL < 32)) {
724 cheight = read_word(BIOSMEM_SEG, BIOSMEM_CHAR_HEIGHT);
725
726 /* Is the end lower than start? VGA does not wrap around.*/
727 if (CL < CH) {
728 /* For zero CL (end), leave values unchanged. */
729 if (CL) {
730 CH = 0;
731 CL = cheight - 1;
732 }
733 } else {
734 if (((CL | CH) >= cheight) || ((CL != cheight - 1) && (CH != cheight - 2))) {
735 /* If it's an overbar cursor, don't adjust. */
736 if (CL > 3) {
737 if (CL <= CH + 2) {
738 /* It's it a normal underline style cursor. */
739 CH = CH - CL + cheight - 1;
740 CL = cheight - 1;
741 if (cheight >= 14) {
742 /* Shift up one pixel for normal EGA/VGA fonts. */
743 CL--;
744 CH--;
745 }
746 } else if (CH <= 2) {
747 /* It's a full block cursor. */
748 CL = cheight - 1;
749 } else {
750 /* It's a half block cursor. */
751 CH = cheight / 2;
752 CL = cheight - 1;
753 }
754 }
755 }
756 }
757 }
758 }
759 }
760
761 // CTRC regs 0x0a and 0x0b
762 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
763 outb(crtc_addr, 0x0a);
764 outb(crtc_addr + 1, CH);
765 outb(crtc_addr, 0x0b);
766 outb(crtc_addr + 1 ,CL);
767}
768
769// --------------------------------------------------------------------------------------------
770static void biosfn_set_cursor_pos (uint8_t page, uint16_t cursor)
771{
772 uint8_t xcurs,ycurs,current;
773 uint16_t nbcols,nbrows,address,crtc_addr;
774
775 // Should not happen...
776 if(page>7)return;
777
778 // Bios cursor pos
779 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor);
780
781 // Set the hardware cursor
782 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
783 if(page==current)
784 {
785 // Get the dimensions
786 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
787 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
788
789 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
790
791 // Calculate the address knowing nbcols nbrows and page num
792 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols;
793
794 // CRTC regs 0x0e and 0x0f
795 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
796 outb(crtc_addr,0x0e);
797 outb(crtc_addr+1,(address&0xff00)>>8);
798 outb(crtc_addr,0x0f);
799 outb(crtc_addr+1,address&0x00ff);
800 }
801}
802
803// --------------------------------------------------------------------------------------------
804static void biosfn_set_active_page(uint8_t page)
805{
806 uint16_t cursor,dummy,crtc_addr;
807 uint16_t nbcols,nbrows,address;
808 uint8_t mode,line;
809
810 if(page>7)return;
811
812 // Get the mode
813 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
814 line=find_vga_entry(mode);
815 if(line==0xFF)return;
816
817 // Get pos curs pos for the right page
818 vga_get_cursor_pos(page,&dummy,&cursor);
819
820 if(vga_modes[line].class==TEXT)
821 {
822 // Get the dimensions
823 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
824 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
825
826 // Calculate the address knowing nbcols nbrows and page num
827 address=SCREEN_MEM_START(nbcols,nbrows,page);
828 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address);
829
830 // Start address
831 address=SCREEN_IO_START(nbcols,nbrows,page);
832 }
833 else
834 {
835 address = page * video_param_table[line_to_vpti[line]].slength;
836 }
837
838 // CRTC regs 0x0c and 0x0d
839 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
840 outb(crtc_addr,0x0c);
841 outb(crtc_addr+1,(address&0xff00)>>8);
842 outb(crtc_addr,0x0d);
843 outb(crtc_addr+1,address&0x00ff);
844
845 // And change the BIOS page
846 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
847
848#ifdef VGA_DEBUG
849 printf("Set active page %02x address %04x\n",page,address);
850#endif
851
852 // Display the cursor, now the page is active
853 biosfn_set_cursor_pos(page,cursor);
854}
855
856/// @todo Evaluate whether executing INT 10h is the right thing here
857extern void vga_font_set(uint8_t function, uint8_t data);
858#pragma aux vga_font_set = \
859 "mov ah, 11h" \
860 "int 10h" \
861 parm [al] [bl];
862
863// ============================================================================================
864//
865// BIOS functions
866//
867// ============================================================================================
868
869/* CGA-compatible MSR (0x3D8) register values for first modes 0-7. */
870uint8_t cga_msr[8] = {
871 0x2C, 0x28, 0x2D, 0x29, 0x2A, 0x2E, 0x1E, 0x29
872};
873
874void biosfn_set_video_mode(uint8_t mode)
875{// mode: Bit 7 is 1 if no clear screen
876
877 // Should we clear the screen ?
878 uint8_t noclearmem=mode&0x80;
879 uint8_t line,mmask,*palette,vpti;
880 uint16_t i,twidth,theightm1,cheight;
881 uint8_t modeset_ctl,video_ctl,vga_switches;
882 uint16_t crtc_addr;
883
884#ifdef VBE
885 if (vbe_has_vbe_display()) {
886 // Force controller into VGA mode
887 outb(VGAREG_SEQU_ADDRESS,7);
888 outb(VGAREG_SEQU_DATA,0x00);
889 }
890#endif // def VBE
891
892 // The real mode
893 mode=mode&0x7f;
894
895 // Display switching is not supported, and mono monitors aren't either.
896 // Requests to set mode 7 (mono) must set mode 0 instead (color).
897 if (mode == 7)
898 mode = 0;
899
900 // find the entry in the video modes
901 line=find_vga_entry(mode);
902
903#ifdef VGA_DEBUG
904 printf("mode search %02x found line %02x\n",mode,line);
905#endif
906
907 if(line==0xFF)
908 return;
909
910 vpti=line_to_vpti[line];
911 twidth=video_param_table[vpti].twidth;
912 theightm1=video_param_table[vpti].theightm1;
913 cheight=video_param_table[vpti].cheight;
914
915 // Read the bios vga control
916 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
917
918 // Read the bios vga switches
919 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES);
920
921 // Read the bios mode set control
922 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
923
924 // Then we know the number of lines
925// FIXME
926
927 // if palette loading (bit 3 of modeset ctl = 0)
928 if((modeset_ctl&0x08)==0)
929 {// Set the PEL mask
930 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask);
931
932 // Set the whole dac always, from 0
933 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
934
935 // From which palette
936 switch(vga_modes[line].dacmodel)
937 {case 0:
938 palette=&palette0[0];
939 break;
940 case 1:
941 palette=&palette1[0];
942 break;
943 case 2:
944 palette=&palette2[0];
945 break;
946 case 3:
947 palette=&palette3[0];
948 break;
949 }
950 // Always 256*3 values
951 for(i=0;i<0x0100;i++)
952 {if(i<=dac_regs[vga_modes[line].dacmodel])
953 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]);
954 outb(VGAREG_DAC_DATA,palette[(i*3)+1]);
955 outb(VGAREG_DAC_DATA,palette[(i*3)+2]);
956 }
957 else
958 {outb(VGAREG_DAC_DATA,0);
959 outb(VGAREG_DAC_DATA,0);
960 outb(VGAREG_DAC_DATA,0);
961 }
962 }
963 if((modeset_ctl&0x02)==0x02)
964 {
965 biosfn_perform_gray_scale_summing(0x00, 0x100);
966 }
967 }
968
969 // Reset Attribute Ctl flip-flop
970 inb(VGAREG_ACTL_RESET);
971
972 // Set Attribute Ctl
973 for(i=0;i<=0x13;i++)
974 {outb(VGAREG_ACTL_ADDRESS,i);
975 outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]);
976 }
977 outb(VGAREG_ACTL_ADDRESS,0x14);
978 outb(VGAREG_ACTL_WRITE_DATA,0x00);
979
980 // Set Sequencer Ctl
981 outb(VGAREG_SEQU_ADDRESS,0);
982 outb(VGAREG_SEQU_DATA,0x03);
983 for(i=1;i<=4;i++)
984 {outb(VGAREG_SEQU_ADDRESS,i);
985 outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]);
986 }
987
988 // Set Grafx Ctl
989 for(i=0;i<=8;i++)
990 {outb(VGAREG_GRDC_ADDRESS,i);
991 outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]);
992 }
993
994 // Set CRTC address VGA or MDA
995 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
996
997 // Disable CRTC write protection
998 outw(crtc_addr,0x0011);
999 // Set CRTC regs
1000 for(i=0;i<=0x18;i++)
1001 {outb(crtc_addr,i);
1002 outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]);
1003 }
1004
1005 // Set the misc register
1006 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg);
1007
1008 // Enable video
1009 outb(VGAREG_ACTL_ADDRESS,0x20);
1010 inb(VGAREG_ACTL_RESET);
1011
1012 if(noclearmem==0x00)
1013 {
1014 if(vga_modes[line].class==TEXT)
1015 {
1016 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k
1017 }
1018 else
1019 {
1020 if(mode<0x0d)
1021 {
1022 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k
1023 }
1024 else
1025 {
1026 outb( VGAREG_SEQU_ADDRESS, 0x02 );
1027 mmask = inb( VGAREG_SEQU_DATA );
1028 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes
1029 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k
1030 outb( VGAREG_SEQU_DATA, mmask );
1031 }
1032 }
1033 }
1034
1035 // Set the BIOS mem
1036 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode);
1037 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth);
1038 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,video_param_table[vpti].slength);
1039 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr);
1040 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1);
1041 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
1042 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem));
1043 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
1044 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
1045
1046 // FIXME We nearly have the good tables. to be reworked
1047 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now
1048 write_dword(BIOSMEM_SEG,BIOSMEM_VS_POINTER, (uint32_t)(void __far *)video_save_pointer_table);
1049
1050 if (mode <= 7)
1051 {
1052 write_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_MSR, cga_msr[mode]); /* Like CGA reg. 0x3D8 */
1053 write_byte(BIOSMEM_SEG, BIOSMEM_CURRENT_PAL, mode == 6 ? 0x3F : 0x30); /* Like CGA reg. 0x3D9*/
1054 }
1055
1056 // Set cursor shape
1057 if(vga_modes[line].class==TEXT)
1058 {
1059 biosfn_set_cursor_shape(0x06,0x07);
1060 }
1061
1062 // Set cursor pos for page 0..7
1063 for(i=0;i<8;i++)
1064 biosfn_set_cursor_pos(i,0x0000);
1065
1066 // Set active page 0
1067 biosfn_set_active_page(0x00);
1068
1069 // Write the fonts in memory
1070 if(vga_modes[line].class==TEXT)
1071 {
1072 vga_font_set(0x04, 0); /* Load 8x16 font into page 0. */
1073 vga_font_set(0x03, 0); /* Select font page mode 0. */
1074 }
1075
1076 // Set the ints 0x1F and 0x43
1077 set_int_vector(0x1f, vgafont8+128*8);
1078
1079 switch(cheight)
1080 {case 8:
1081 set_int_vector(0x43, vgafont8);
1082 break;
1083 case 14:
1084 set_int_vector(0x43, vgafont14);
1085 break;
1086 case 16:
1087 set_int_vector(0x43, vgafont16);
1088 break;
1089 }
1090}
1091
1092// --------------------------------------------------------------------------------------------
1093static void vgamem_copy_pl4(uint8_t xstart, uint8_t ysrc, uint8_t ydest,
1094 uint8_t cols, uint8_t nbcols, uint8_t cheight)
1095{
1096 uint16_t src,dest;
1097 uint8_t i;
1098
1099 src=ysrc*cheight*nbcols+xstart;
1100 dest=ydest*cheight*nbcols+xstart;
1101 outw(VGAREG_GRDC_ADDRESS, 0x0105);
1102 for(i=0;i<cheight;i++)
1103 {
1104 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1105 }
1106 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1107}
1108
1109// --------------------------------------------------------------------------------------------
1110static void vgamem_fill_pl4(uint8_t xstart, uint8_t ystart, uint8_t cols,
1111 uint8_t nbcols, uint8_t cheight, uint8_t attr)
1112{
1113 uint16_t dest;
1114 uint8_t i;
1115
1116 dest=ystart*cheight*nbcols+xstart;
1117 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1118 for(i=0;i<cheight;i++)
1119 {
1120 memsetb(0xa000,dest+i*nbcols,attr,cols);
1121 }
1122 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1123}
1124
1125// --------------------------------------------------------------------------------------------
1126static void vgamem_copy_cga(uint8_t xstart, uint8_t ysrc, uint8_t ydest,
1127 uint8_t cols, uint8_t nbcols, uint8_t cheight)
1128{
1129 uint16_t src,dest;
1130 uint8_t i;
1131
1132 src=((ysrc*cheight*nbcols)>>1)+xstart;
1133 dest=((ydest*cheight*nbcols)>>1)+xstart;
1134 for(i=0;i<cheight/2;i++)
1135 {
1136 memcpyb(0xb800,dest+i*nbcols,0xb800,src+i*nbcols,cols);
1137 memcpyb(0xb800,0x2000+dest+i*nbcols,0xb800,0x2000+src+i*nbcols,cols);
1138 }
1139}
1140
1141// --------------------------------------------------------------------------------------------
1142static void vgamem_fill_cga(uint8_t xstart, uint8_t ystart, uint8_t cols,
1143 uint8_t nbcols, uint8_t cheight, uint8_t attr)
1144{
1145 uint16_t dest;
1146 uint8_t i;
1147
1148 dest=((ystart*cheight*nbcols)>>1)+xstart;
1149 for(i=0;i<cheight/2;i++)
1150 {
1151 memsetb(0xb800,dest+i*nbcols,attr,cols);
1152 memsetb(0xb800,0x2000+dest+i*nbcols,attr,cols);
1153 }
1154}
1155
1156// --------------------------------------------------------------------------------------------
1157static void vgamem_copy_linear(uint8_t xstart, uint8_t ysrc, uint8_t ydest,
1158 uint16_t cols, uint16_t nbcols, uint8_t cheight)
1159{
1160 uint16_t src,dest;
1161 uint8_t i;
1162
1163 src=((ysrc*cheight*nbcols)+xstart)*8;
1164 dest=((ydest*cheight*nbcols)+xstart)*8;
1165 cols*=8;
1166 nbcols*=8;
1167 for(i=0;i<cheight;i++)
1168 {
1169 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
1170 }
1171}
1172
1173// --------------------------------------------------------------------------------------------
1174static void vgamem_fill_linear(uint8_t xstart, uint8_t ystart, uint16_t cols,
1175 uint16_t nbcols, uint8_t cheight, uint8_t attr)
1176{
1177 uint16_t dest;
1178 uint8_t i;
1179
1180 dest=((ystart*cheight*nbcols)+xstart)*8;
1181 cols*=8;
1182 nbcols*=8;
1183 for(i=0;i<cheight;i++)
1184 {
1185 memsetb(0xa000,dest+i*nbcols,attr,cols);
1186 }
1187}
1188
1189// --------------------------------------------------------------------------------------------
1190static void biosfn_scroll(uint8_t nblines, uint8_t attr, uint8_t rul, uint8_t cul,
1191 uint8_t rlr, uint8_t clr, uint8_t page, uint8_t dir)
1192{
1193 // page == 0xFF if current
1194
1195 uint8_t mode,line,cheight,bpp,cols;
1196 uint16_t nbcols,nbrows,i;
1197 uint16_t address;
1198
1199 if(rul>rlr)return;
1200 if(cul>clr)return;
1201
1202 // Get the mode
1203 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1204 line=find_vga_entry(mode);
1205 if(line==0xFF)return;
1206
1207 // Get the dimensions
1208 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1209 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1210
1211 // Get the current page
1212 if(page==0xFF)
1213 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1214
1215 if(rlr>=nbrows)rlr=nbrows-1;
1216 if(clr>=nbcols)clr=nbcols-1;
1217 if(nblines>nbrows)nblines=0;
1218 cols=clr-cul+1;
1219
1220 if(vga_modes[line].class==TEXT)
1221 {
1222 // Compute the address
1223 address=SCREEN_MEM_START(nbcols,nbrows,page);
1224#ifdef VGA_DEBUG
1225 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page);
1226#endif
1227
1228 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1229 {
1230 memsetw(vga_modes[line].sstart,address,(uint16_t)attr*0x100+' ',nbrows*nbcols);
1231 }
1232 else
1233 {// if Scroll up
1234 if(dir==SCROLL_UP)
1235 {for(i=rul;i<=rlr;i++)
1236 {
1237 if((i+nblines>rlr)||(nblines==0))
1238 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(uint16_t)attr*0x100+' ',cols);
1239 else
1240 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols);
1241 }
1242 }
1243 else
1244 {for(i=rlr;i>=rul;i--)
1245 {
1246 if((i<rul+nblines)||(nblines==0))
1247 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(uint16_t)attr*0x100+' ',cols);
1248 else
1249 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols);
1250 if (i>rlr) break;
1251 }
1252 }
1253 }
1254 }
1255 else
1256 {
1257 cheight=video_param_table[line_to_vpti[line]].cheight;
1258 switch(vga_modes[line].memmodel)
1259 {
1260 case PLANAR4:
1261 case PLANAR1:
1262 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1263 {
1264 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1265 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight);
1266 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1267 }
1268 else
1269 {// if Scroll up
1270 if(dir==SCROLL_UP)
1271 {for(i=rul;i<=rlr;i++)
1272 {
1273 if((i+nblines>rlr)||(nblines==0))
1274 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1275 else
1276 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight);
1277 }
1278 }
1279 else
1280 {for(i=rlr;i>=rul;i--)
1281 {
1282 if((i<rul+nblines)||(nblines==0))
1283 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr);
1284 else
1285 vgamem_copy_pl4(cul,i-nblines,i,cols,nbcols,cheight);
1286 if (i>rlr) break;
1287 }
1288 }
1289 }
1290 break;
1291 case CGA:
1292 bpp=vga_modes[line].pixbits;
1293 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1294 {
1295 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp);
1296 }
1297 else
1298 {
1299 if(bpp==2)
1300 {
1301 cul<<=1;
1302 cols<<=1;
1303 nbcols<<=1;
1304 }
1305 // if Scroll up
1306 if(dir==SCROLL_UP)
1307 {for(i=rul;i<=rlr;i++)
1308 {
1309 if((i+nblines>rlr)||(nblines==0))
1310 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1311 else
1312 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight);
1313 }
1314 }
1315 else
1316 {for(i=rlr;i>=rul;i--)
1317 {
1318 if((i<rul+nblines)||(nblines==0))
1319 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr);
1320 else
1321 vgamem_copy_cga(cul,i-nblines,i,cols,nbcols,cheight);
1322 if (i>rlr) break;
1323 }
1324 }
1325 }
1326 break;
1327 case LINEAR8:
1328 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
1329 {
1330 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*8);
1331 }
1332 else
1333 {
1334 // if Scroll up
1335 if(dir==SCROLL_UP)
1336 {for(i=rul;i<=rlr;i++)
1337 {
1338 if((i+nblines>rlr)||(nblines==0))
1339 vgamem_fill_linear(cul,i,cols,nbcols,cheight,attr);
1340 else
1341 vgamem_copy_linear(cul,i+nblines,i,cols,nbcols,cheight);
1342 }
1343 }
1344 else
1345 {for(i=rlr;i>=rul;i--)
1346 {
1347 if((i<rul+nblines)||(nblines==0))
1348 vgamem_fill_linear(cul,i,cols,nbcols,cheight,attr);
1349 else
1350 vgamem_copy_linear(cul,i-nblines,i,cols,nbcols,cheight);
1351 if (i>rlr) break;
1352 }
1353 }
1354 }
1355 break;
1356#ifdef VGA_DEBUG
1357 default:
1358 printf("Scroll in graphics mode ");
1359 unimplemented();
1360#endif
1361 }
1362 }
1363}
1364
1365// --------------------------------------------------------------------------------------------
1366static void write_gfx_char_pl4(uint8_t car, uint8_t attr, uint8_t xcurs,
1367 uint8_t ycurs, uint8_t nbcols, uint8_t cheight, uint8_t page)
1368{
1369 uint8_t i,j,mask;
1370 uint8_t __far *fdata;
1371 uint16_t addr,dest,src;
1372
1373 fdata = (void __far *)read_dword(0x00, 0x43 * 4);
1374
1375 addr=xcurs+ycurs*cheight*nbcols;
1376 addr+=read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)*page;
1377 src = car * cheight;
1378 outw(VGAREG_SEQU_ADDRESS, 0x0f02);
1379 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1380 if(attr&0x80)
1381 {
1382 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1383 }
1384 else
1385 {
1386 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1387 }
1388 for(i=0;i<cheight;i++)
1389 {
1390 dest=addr+i*nbcols;
1391 for(j=0;j<8;j++)
1392 {
1393 mask=0x80>>j;
1394 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1395 xread_byte(0xa000,dest);
1396 if(fdata[src+i]&mask)
1397 {
1398 write_byte(0xa000,dest,attr&0x0f);
1399 }
1400 else
1401 {
1402 write_byte(0xa000,dest,0x00);
1403 }
1404 }
1405 }
1406 outw(VGAREG_GRDC_ADDRESS, 0xff08);
1407 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1408 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1409}
1410
1411// --------------------------------------------------------------------------------------------
1412static void write_gfx_char_cga(uint8_t car, uint8_t attr, uint8_t xcurs,
1413 uint8_t ycurs, uint8_t nbcols, uint8_t bpp)
1414{
1415 uint8_t i,j,mask,data;
1416 uint8_t *fdata;
1417 uint16_t addr,dest,src;
1418
1419 fdata = &vgafont8;
1420 addr=(xcurs*bpp)+ycurs*320;
1421 src = car * 8;
1422 for(i=0;i<8;i++)
1423 {
1424 dest=addr+(i>>1)*80;
1425 if (i & 1) dest += 0x2000;
1426 mask = 0x80;
1427 /* NB: In 1bpp modes, the attribute is ignored, only the XOR flag has meaning. */
1428 if (bpp == 1)
1429 {
1430 if (attr & 0x80)
1431 {
1432 data = read_byte(0xb800,dest);
1433 data ^= fdata[src+i];
1434 }
1435 else
1436 {
1437 data = fdata[src+i];
1438 }
1439 write_byte(0xb800,dest,data);
1440 }
1441 else
1442 {
1443 while (mask > 0)
1444 {
1445 if (attr & 0x80)
1446 {
1447 data = read_byte(0xb800,dest);
1448 }
1449 else
1450 {
1451 data = 0x00;
1452 }
1453 for(j=0;j<4;j++)
1454 {
1455 if (fdata[src+i] & mask)
1456 {
1457 if (attr & 0x80)
1458 {
1459 data ^= (attr & 0x03) << ((3-j)*2);
1460 }
1461 else
1462 {
1463 data |= (attr & 0x03) << ((3-j)*2);
1464 }
1465 }
1466 mask >>= 1;
1467 }
1468 write_byte(0xb800,dest,data);
1469 dest += 1;
1470 }
1471 }
1472 }
1473}
1474
1475// --------------------------------------------------------------------------------------------
1476static void write_gfx_char_lin(uint8_t car, uint8_t attr, uint8_t xcurs,
1477 uint8_t ycurs, uint8_t nbcols)
1478{
1479 uint8_t i,j,mask,data;
1480 uint8_t *fdata;
1481 uint16_t addr,dest,src;
1482
1483 fdata = &vgafont8;
1484 addr=xcurs*8+ycurs*nbcols*64;
1485 src = car * 8;
1486 for(i=0;i<8;i++)
1487 {
1488 dest=addr+i*nbcols*8;
1489 mask = 0x80;
1490 for(j=0;j<8;j++)
1491 {
1492 data = 0x00;
1493 if (fdata[src+i] & mask)
1494 {
1495 data = attr;
1496 }
1497 write_byte(0xa000,dest+j,data);
1498 mask >>= 1;
1499 }
1500 }
1501}
1502
1503// --------------------------------------------------------------------------------------------
1504static void biosfn_write_char_attr(uint8_t car, uint8_t page, uint8_t attr, uint16_t count)
1505{
1506 uint8_t cheight,xcurs,ycurs,mode,line,bpp;
1507 uint16_t nbcols,nbrows,address;
1508 uint16_t cursor,dummy;
1509
1510 // Get the mode
1511 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1512 line=find_vga_entry(mode);
1513 if(line==0xFF)return;
1514
1515 // Get the cursor pos for the page
1516 vga_get_cursor_pos(page,&dummy,&cursor);
1517 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1518
1519 // Get the dimensions
1520 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1521 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1522
1523 if(vga_modes[line].class==TEXT)
1524 {
1525 // Compute the address
1526 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1527
1528 dummy=((uint16_t)attr<<8)+car;
1529 memsetw(vga_modes[line].sstart,address,dummy,count);
1530 }
1531 else
1532 {
1533 // FIXME gfx mode not complete
1534 cheight=video_param_table[line_to_vpti[line]].cheight;
1535 bpp=vga_modes[line].pixbits;
1536 while(count-->0)
1537 {
1538 switch(vga_modes[line].memmodel)
1539 {
1540 case PLANAR1:
1541 attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */
1542 case PLANAR4:
1543 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page);
1544 break;
1545 case CGA:
1546 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1547 break;
1548 case LINEAR8:
1549 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1550 break;
1551#ifdef VGA_DEBUG
1552 default:
1553 unimplemented();
1554#endif
1555 }
1556 xcurs++;
1557 }
1558 }
1559}
1560
1561// --------------------------------------------------------------------------------------------
1562static void biosfn_write_char_only(uint8_t car, uint8_t page, uint8_t attr, uint16_t count)
1563{
1564 uint8_t cheight,xcurs,ycurs,mode,line,bpp;
1565 uint16_t nbcols,nbrows,address;
1566 uint16_t cursor,dummy;
1567
1568 // Get the mode
1569 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1570 line=find_vga_entry(mode);
1571 if(line==0xFF)return;
1572
1573 // Get the cursor pos for the page
1574 vga_get_cursor_pos(page,&dummy,&cursor);
1575 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1576
1577 // Get the dimensions
1578 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1579 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1580
1581 if(vga_modes[line].class==TEXT)
1582 {
1583 // Compute the address
1584 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1585
1586 while(count-->0)
1587 {write_byte(vga_modes[line].sstart,address,car);
1588 address+=2;
1589 }
1590 }
1591 else
1592 {
1593 // FIXME gfx mode not complete
1594 cheight=video_param_table[line_to_vpti[line]].cheight;
1595 bpp=vga_modes[line].pixbits;
1596 while(count-->0)
1597 {
1598 switch(vga_modes[line].memmodel)
1599 {
1600 case PLANAR1:
1601 attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */
1602 case PLANAR4:
1603 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page);
1604 break;
1605 case CGA:
1606 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1607 break;
1608 case LINEAR8:
1609 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1610 break;
1611#ifdef VGA_DEBUG
1612 default:
1613 unimplemented();
1614#endif
1615 }
1616 xcurs++;
1617 }
1618 }
1619}
1620
1621// --------------------------------------------------------------------------------------------
1622static void biosfn_write_pixel(uint8_t BH, uint8_t AL, uint16_t CX, uint16_t DX)
1623{
1624 uint8_t mode,line,mask,attr,data;
1625 uint16_t addr;
1626
1627 // Get the mode
1628 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1629 line=find_vga_entry(mode);
1630 if(line==0xFF)return;
1631 if(vga_modes[line].class==TEXT)return;
1632
1633 switch(vga_modes[line].memmodel)
1634 {
1635 case PLANAR4:
1636 case PLANAR1:
1637 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1638 addr += read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE) * BH;
1639 mask = 0x80 >> (CX & 0x07);
1640 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
1641 outw(VGAREG_GRDC_ADDRESS, 0x0205);
1642 data = xread_byte(0xa000,addr);
1643 if (AL & 0x80)
1644 {
1645 outw(VGAREG_GRDC_ADDRESS, 0x1803);
1646 }
1647 write_byte(0xa000,addr,AL);
1648 outw(VGAREG_GRDC_ADDRESS, 0xff08);
1649 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1650 outw(VGAREG_GRDC_ADDRESS, 0x0003);
1651 break;
1652 case CGA:
1653 if(vga_modes[line].pixbits==2)
1654 {
1655 addr=(CX>>2)+(DX>>1)*80;
1656 }
1657 else
1658 {
1659 addr=(CX>>3)+(DX>>1)*80;
1660 }
1661 if (DX & 1) addr += 0x2000;
1662 data = read_byte(0xb800,addr);
1663 if(vga_modes[line].pixbits==2)
1664 {
1665 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2);
1666 mask = 0x03 << ((3 - (CX & 0x03)) * 2);
1667 }
1668 else
1669 {
1670 attr = (AL & 0x01) << (7 - (CX & 0x07));
1671 mask = 0x01 << (7 - (CX & 0x07));
1672 }
1673 if (AL & 0x80)
1674 {
1675 data ^= attr;
1676 }
1677 else
1678 {
1679 data &= ~mask;
1680 data |= attr;
1681 }
1682 write_byte(0xb800,addr,data);
1683 break;
1684 case LINEAR8:
1685 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8);
1686 write_byte(0xa000,addr,AL);
1687 break;
1688#ifdef VGA_DEBUG
1689 default:
1690 unimplemented();
1691#endif
1692 }
1693}
1694
1695// --------------------------------------------------------------------------------------------
1696static void biosfn_write_teletype(uint8_t car, uint8_t page, uint8_t attr, uint8_t flag)
1697{// flag = WITH_ATTR / NO_ATTR
1698
1699 uint8_t cheight,xcurs,ycurs,mode,line,bpp;
1700 uint16_t nbcols,nbrows,address;
1701 uint16_t cursor,dummy;
1702
1703 // special case if page is 0xff, use current page
1704 if(page==0xff)
1705 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1706
1707 // Get the mode
1708 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1709 line=find_vga_entry(mode);
1710 if(line==0xFF)return;
1711
1712 // Get the cursor pos for the page
1713 vga_get_cursor_pos(page,&dummy,&cursor);
1714 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1715
1716 // Get the dimensions
1717 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1718 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1719
1720 switch(car)
1721 {
1722 case '\a': // ASCII 0x07, BEL
1723 //FIXME should beep
1724 break;
1725
1726 case '\b': // ASCII 0x08, BS
1727 if(xcurs>0)xcurs--;
1728 break;
1729
1730 case '\n': // ASCII 0x0A, LF
1731 ycurs++;
1732 break;
1733
1734 case '\r': // ASCII 0x0D, CR
1735 xcurs=0;
1736 break;
1737
1738 default:
1739
1740 if(vga_modes[line].class==TEXT)
1741 {
1742 // Compute the address
1743 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1744
1745 // Write the char
1746 write_byte(vga_modes[line].sstart,address,car);
1747
1748 if(flag==WITH_ATTR)
1749 write_byte(vga_modes[line].sstart,address+1,attr);
1750 }
1751 else
1752 {
1753 // FIXME gfx mode not complete
1754 cheight=video_param_table[line_to_vpti[line]].cheight;
1755 bpp=vga_modes[line].pixbits;
1756 switch(vga_modes[line].memmodel)
1757 {
1758 case PLANAR1:
1759 attr |= 0x01; /* Color is ignored in 1bpp modes, always foreground. */
1760 case PLANAR4:
1761 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight,page);
1762 break;
1763 case CGA:
1764 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
1765 break;
1766 case LINEAR8:
1767 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
1768 break;
1769#ifdef VGA_DEBUG
1770 default:
1771 unimplemented();
1772#endif
1773 }
1774 }
1775 xcurs++;
1776 // Do we need to wrap ?
1777 if(xcurs==nbcols)
1778 {xcurs=0;
1779 ycurs++;
1780 }
1781 }
1782
1783 // Do we need to scroll ?
1784 if(ycurs==nbrows)
1785 {
1786 if(vga_modes[line].class==TEXT)
1787 {
1788 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2;
1789 attr=read_byte(vga_modes[line].sstart,address+1);
1790 biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1791 }
1792 else
1793 {
1794 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
1795 }
1796 ycurs-=1;
1797 }
1798
1799 // Set the cursor for the page
1800 cursor=ycurs; cursor<<=8; cursor+=xcurs;
1801 biosfn_set_cursor_pos(page,cursor);
1802}
1803
1804// --------------------------------------------------------------------------------------------
1805static void get_font_access(void)
1806{
1807 outw(VGAREG_SEQU_ADDRESS, 0x0100);
1808 outw(VGAREG_SEQU_ADDRESS, 0x0402);
1809 outw(VGAREG_SEQU_ADDRESS, 0x0704);
1810 outw(VGAREG_SEQU_ADDRESS, 0x0300);
1811 outw(VGAREG_GRDC_ADDRESS, 0x0204);
1812 outw(VGAREG_GRDC_ADDRESS, 0x0005);
1813 outw(VGAREG_GRDC_ADDRESS, 0x0406);
1814}
1815
1816static void release_font_access(void)
1817{
1818 outw(VGAREG_SEQU_ADDRESS, 0x0100);
1819 outw(VGAREG_SEQU_ADDRESS, 0x0302);
1820 outw(VGAREG_SEQU_ADDRESS, 0x0304);
1821 outw(VGAREG_SEQU_ADDRESS, 0x0300);
1822 outw(VGAREG_GRDC_ADDRESS, (((0x0a | ((inb(VGAREG_READ_MISC_OUTPUT) & 0x01) << 2)) << 8) | 0x06));
1823 outw(VGAREG_GRDC_ADDRESS, 0x0004);
1824 outw(VGAREG_GRDC_ADDRESS, 0x1005);
1825}
1826
1827static void set_scan_lines(uint8_t lines)
1828{
1829 uint16_t crtc_addr,cols,vde;
1830 uint8_t crtc_r9,ovl,rows;
1831
1832 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
1833 outb(crtc_addr, 0x09);
1834 crtc_r9 = inb(crtc_addr+1);
1835 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
1836 outb(crtc_addr+1, crtc_r9);
1837 if(lines==8)
1838 {
1839 biosfn_set_cursor_shape(0x06,0x07);
1840 }
1841 else
1842 {
1843 biosfn_set_cursor_shape(lines-4,lines-3);
1844 }
1845 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
1846 outb(crtc_addr, 0x12);
1847 vde = inb(crtc_addr+1);
1848 outb(crtc_addr, 0x07);
1849 ovl = inb(crtc_addr+1);
1850 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
1851 rows = vde / lines;
1852 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
1853 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1854 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
1855}
1856
1857static void biosfn_load_text_user_pat(uint8_t AL, uint16_t ES, uint16_t BP, uint16_t CX,
1858 uint16_t DX, uint8_t BL, uint8_t BH)
1859{
1860 uint16_t blockaddr,dest,i,src;
1861
1862 get_font_access();
1863 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1864 for(i=0;i<CX;i++)
1865 {
1866 src = BP + i * BH;
1867 dest = blockaddr + (DX + i) * 32;
1868 memcpyb(0xA000, dest, ES, src, BH);
1869 }
1870 release_font_access();
1871 if(AL>=0x10)
1872 {
1873 set_scan_lines(BH);
1874 }
1875}
1876
1877static void biosfn_load_text_8_14_pat(uint8_t AL, uint8_t BL)
1878{
1879 uint16_t blockaddr,dest,i,src;
1880
1881 get_font_access();
1882 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1883 for(i=0;i<0x100;i++)
1884 {
1885 src = i * 14;
1886 dest = blockaddr + i * 32;
1887 memcpyb(0xA000, dest, 0xC000, (uint16_t)vgafont14+src, 14);
1888 }
1889 release_font_access();
1890 if(AL>=0x10)
1891 {
1892 set_scan_lines(14);
1893 }
1894}
1895
1896static void biosfn_load_text_8_8_pat(uint8_t AL, uint8_t BL)
1897{
1898 uint16_t blockaddr,dest,i,src;
1899
1900 get_font_access();
1901 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1902 for(i=0;i<0x100;i++)
1903 {
1904 src = i * 8;
1905 dest = blockaddr + i * 32;
1906 memcpyb(0xA000, dest, 0xC000, (uint16_t)vgafont8+src, 8);
1907 }
1908 release_font_access();
1909 if(AL>=0x10)
1910 {
1911 set_scan_lines(8);
1912 }
1913}
1914
1915// --------------------------------------------------------------------------------------------
1916static void biosfn_load_text_8_16_pat(uint8_t AL, uint8_t BL)
1917{
1918 uint16_t blockaddr,dest,i,src;
1919
1920 get_font_access();
1921 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
1922 for(i=0;i<0x100;i++)
1923 {
1924 src = i * 16;
1925 dest = blockaddr + i * 32;
1926 memcpyb(0xA000, dest, 0xC000, (uint16_t)vgafont16+src, 16);
1927 }
1928 release_font_access();
1929 if(AL>=0x10)
1930 {
1931 set_scan_lines(16);
1932 }
1933}
1934
1935static void biosfn_load_gfx_8_8_chars(uint16_t ES, uint16_t BP)
1936{
1937#ifdef VGA_DEBUG
1938 unimplemented();
1939#endif
1940}
1941static void biosfn_load_gfx_user_chars(uint16_t ES, uint16_t BP, uint16_t CX,
1942 uint8_t BL, uint8_t DL)
1943{
1944#ifdef VGA_DEBUG
1945 unimplemented();
1946#endif
1947}
1948static void biosfn_load_gfx_8_14_chars(uint8_t BL)
1949{
1950#ifdef VGA_DEBUG
1951 unimplemented();
1952#endif
1953}
1954static void biosfn_load_gfx_8_8_dd_chars(uint8_t BL)
1955{
1956#ifdef VGA_DEBUG
1957 unimplemented();
1958#endif
1959}
1960static void biosfn_load_gfx_8_16_chars(uint8_t BL)
1961{
1962#ifdef VGA_DEBUG
1963 unimplemented();
1964#endif
1965}
1966// --------------------------------------------------------------------------------------------
1967static void biosfn_alternate_prtsc(void)
1968{
1969#ifdef VGA_DEBUG
1970 unimplemented();
1971#endif
1972}
1973
1974// --------------------------------------------------------------------------------------------
1975static void biosfn_switch_video_interface (AL,ES,DX) uint8_t AL;uint16_t ES;uint16_t DX;
1976{
1977#ifdef VGA_DEBUG
1978 unimplemented();
1979#endif
1980}
1981static void biosfn_enable_video_refresh_control(uint8_t AL)
1982{
1983#ifdef VGA_DEBUG
1984 unimplemented();
1985#endif
1986}
1987
1988// --------------------------------------------------------------------------------------------
1989static void biosfn_write_string(uint8_t flag, uint8_t page, uint8_t attr, uint16_t count,
1990 uint8_t row, uint8_t col, uint16_t seg, uint16_t offset)
1991{
1992 uint16_t newcurs,oldcurs,dummy;
1993 uint8_t car;
1994
1995 // Read curs info for the page
1996 vga_get_cursor_pos(page,&dummy,&oldcurs);
1997
1998 // if row=0xff special case : use current cursor position
1999 if(row==0xff)
2000 {col=oldcurs&0x00ff;
2001 row=(oldcurs&0xff00)>>8;
2002 }
2003
2004 newcurs=row; newcurs<<=8; newcurs+=col;
2005 biosfn_set_cursor_pos(page,newcurs);
2006
2007 while(count--!=0)
2008 {
2009 car=read_byte(seg,offset++);
2010 if((flag&0x02)!=0)
2011 attr=read_byte(seg,offset++);
2012
2013 biosfn_write_teletype(car,page,attr,WITH_ATTR);
2014 }
2015
2016 // Set back curs pos
2017 if((flag&0x01)==0)
2018 biosfn_set_cursor_pos(page,oldcurs);
2019}
2020
2021// --------------------------------------------------------------------------------------------
2022static void biosfn_read_state_info(uint16_t BX, uint16_t ES, uint16_t DI)
2023{
2024 uint16_t pg_sz;
2025 uint16_t scans;
2026 uint8_t mode;
2027 uint8_t mctl;
2028 uint8_t temp;
2029
2030 mode = read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
2031 pg_sz = read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE);
2032 // Address of static functionality table
2033 write_dword(ES,DI+0x00, (uint32_t)(void __far *)static_functionality);
2034
2035 // A lot is a straight copy from the BDA. Note that the number
2036 // of character rows in the BDA is zero-based but one-based in
2037 // the dynamic state area
2038 memcpyb(ES,DI+0x04,BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,30);
2039 write_byte(ES,DI+0x22,read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1);
2040 memcpyb(ES,DI+0x23,BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,2);
2041
2042 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
2043 write_byte(ES,DI+0x26,0); // Alternate display code
2044 write_word(ES,DI+0x27,16); // Number of colors
2045 write_byte(ES,DI+0x29,8); // Number of pages
2046 write_byte(ES,DI+0x2a,2); // Vertical resolution specifier
2047 write_byte(ES,DI+0x2b,0); // Primary font block
2048 write_byte(ES,DI+0x2c,0); // Secondary font block
2049 write_byte(ES,DI+0x2d,0x21);
2050 write_byte(ES,DI+0x31,3); // 256K video RAM
2051 write_byte(ES,DI+0x32,0); // Save pointer state information
2052
2053 mctl = read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
2054
2055 /* Extract and write the vertical resolution specifier bits. */
2056 scans = ((mctl & 0x80) >> 6) | ((mctl & 0x10) >> 4);
2057 switch (scans) {
2058 case 0: temp = 1; break; /* 350 lines */
2059 case 1: temp = 2; break; /* 400 lines */
2060 default:
2061 case 2: temp = 0; break; /* 200 lines */
2062 }
2063 write_byte(ES,DI+0x2a,temp);
2064
2065 /* Patch up the data for graphics modes. */
2066 if (mode >= 0x0E && mode <= 0x12) {
2067 if (pg_sz)
2068 write_byte(ES,DI+0x29,16384/(pg_sz >> 2));
2069 } else if (mode == 0x13) {
2070 write_byte(ES,DI+0x29,1); /* Just one page due to chaining */
2071 write_word(ES,DI+0x27,256); /* But 256!! colors!!! */
2072 } else if (mode >= 4 && mode <= 6) {
2073 /* CGA modes. */
2074 if (pg_sz)
2075 write_byte(ES,DI+0x29,16384/pg_sz);
2076 write_word(ES,DI+0x27,4);
2077 }
2078 if (mode == 6 || mode == 0x11)
2079 write_word(ES,DI+0x27,2); /* 2-color modes. */
2080
2081 if ((mode >= 4) && (mode != 7)) {
2082 write_byte(ES,DI+0x2d,0x01);
2083 scans = (read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1) * read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
2084 switch (scans) {
2085 case 200: temp = 0; break;
2086 case 350: temp = 1; break;
2087 case 400: temp = 2; break;
2088 default:
2089 case 480: temp = 3; break;
2090 }
2091 write_byte(ES,DI+0x2a,temp);
2092 }
2093
2094 memsetb(ES,DI+0x33,0,13);
2095}
2096
2097// --------------------------------------------------------------------------------------------
2098uint16_t biosfn_read_video_state_size2(uint16_t state)
2099{
2100 uint16_t size;
2101
2102 size = 0;
2103 if (state & 1)
2104 size += 0x46;
2105
2106 if (state & 2)
2107 size += (5 + 8 + 5) * 2 + 6;
2108
2109 if (state & 4)
2110 size += 3 + 256 * 3 + 1;
2111
2112 return size;
2113}
2114
2115static void vga_get_video_state_size(uint16_t state, uint16_t STACK_BASED *size)
2116{
2117 /* The size is the number of 64-byte blocks required to save the state. */
2118 *size = (biosfn_read_video_state_size2(state) + 63) / 64;
2119}
2120
2121uint16_t biosfn_save_video_state(uint16_t CX, uint16_t ES, uint16_t BX)
2122{
2123 uint16_t i, crtc_addr, ar_index;
2124
2125 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
2126 if (CX & 1) {
2127 write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
2128 write_byte(ES, BX, inb(crtc_addr)); BX++;
2129 write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
2130 inb(VGAREG_ACTL_RESET);
2131 ar_index = inb(VGAREG_ACTL_ADDRESS);
2132 write_byte(ES, BX, ar_index); BX++;
2133 write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
2134
2135 for(i=1;i<=4;i++){
2136 outb(VGAREG_SEQU_ADDRESS, i);
2137 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
2138 }
2139 outb(VGAREG_SEQU_ADDRESS, 0);
2140 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
2141
2142 for(i=0;i<=0x18;i++) {
2143 outb(crtc_addr,i);
2144 write_byte(ES, BX, inb(crtc_addr+1)); BX++;
2145 }
2146
2147 for(i=0;i<=0x13;i++) {
2148 inb(VGAREG_ACTL_RESET);
2149 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
2150 write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
2151 }
2152 inb(VGAREG_ACTL_RESET);
2153
2154 for(i=0;i<=8;i++) {
2155 outb(VGAREG_GRDC_ADDRESS,i);
2156 write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
2157 }
2158
2159 write_word(ES, BX, crtc_addr); BX+= 2;
2160
2161 /* XXX: read plane latches */
2162 write_byte(ES, BX, 0); BX++;
2163 write_byte(ES, BX, 0); BX++;
2164 write_byte(ES, BX, 0); BX++;
2165 write_byte(ES, BX, 0); BX++;
2166 }
2167 if (CX & 2) {
2168 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
2169 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
2170 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
2171 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
2172 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
2173 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
2174 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
2175 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
2176 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
2177 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
2178 for(i=0;i<8;i++) {
2179 write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
2180 BX += 2;
2181 }
2182 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
2183 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
2184 /* current font */
2185 write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
2186 write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
2187 write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
2188 write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
2189 }
2190 if (CX & 4) {
2191 /* XXX: check this */
2192 write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
2193 write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
2194 write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
2195 // Set the whole dac always, from 0
2196 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
2197 for(i=0;i<256*3;i++) {
2198 write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
2199 }
2200 write_byte(ES, BX, 0); BX++; /* color select register */
2201 }
2202 return BX;
2203}
2204
2205uint16_t biosfn_restore_video_state(uint16_t CX, uint16_t ES, uint16_t BX)
2206{
2207 uint16_t i, crtc_addr, v, addr1, ar_index;
2208
2209 if (CX & 1) {
2210 // Reset Attribute Ctl flip-flop
2211 inb(VGAREG_ACTL_RESET);
2212
2213 crtc_addr = read_word(ES, BX + 0x40);
2214 addr1 = BX;
2215 BX += 5;
2216
2217 for(i=1;i<=4;i++){
2218 outb(VGAREG_SEQU_ADDRESS, i);
2219 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
2220 }
2221 outb(VGAREG_SEQU_ADDRESS, 0);
2222 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
2223
2224 // Disable CRTC write protection
2225 outw(crtc_addr,0x0011);
2226 // Set CRTC regs
2227 for(i=0;i<=0x18;i++) {
2228 if (i != 0x11) {
2229 outb(crtc_addr,i);
2230 outb(crtc_addr+1, read_byte(ES, BX));
2231 }
2232 BX++;
2233 }
2234 // select crtc base address
2235 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
2236 if (crtc_addr == 0x3d4)
2237 v |= 0x01;
2238 outb(VGAREG_WRITE_MISC_OUTPUT, v);
2239
2240 // enable write protection if needed
2241 outb(crtc_addr, 0x11);
2242 outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
2243
2244 // Set Attribute Ctl
2245 ar_index = read_byte(ES, addr1 + 0x03);
2246 inb(VGAREG_ACTL_RESET);
2247 for(i=0;i<=0x13;i++) {
2248 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
2249 outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
2250 }
2251 outb(VGAREG_ACTL_ADDRESS, ar_index);
2252 inb(VGAREG_ACTL_RESET);
2253
2254 for(i=0;i<=8;i++) {
2255 outb(VGAREG_GRDC_ADDRESS,i);
2256 outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
2257 }
2258 BX += 2; /* crtc_addr */
2259 BX += 4; /* plane latches */
2260
2261 outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
2262 outb(crtc_addr, read_byte(ES, addr1)); addr1++;
2263 outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
2264 addr1++;
2265 outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
2266 }
2267 if (CX & 2) {
2268 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
2269 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
2270 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
2271 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
2272 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
2273 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
2274 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
2275 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
2276 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
2277 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
2278 for(i=0;i<8;i++) {
2279 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
2280 BX += 2;
2281 }
2282 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
2283 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
2284 /* current font */
2285 write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
2286 write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
2287 write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
2288 write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
2289 }
2290 if (CX & 4) {
2291 BX++;
2292 v = read_byte(ES, BX); BX++;
2293 outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
2294 // Set the whole dac always, from 0
2295 outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
2296 for(i=0;i<256*3;i++) {
2297 outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
2298 }
2299 BX++;
2300 outb(VGAREG_DAC_WRITE_ADDRESS, v);
2301 }
2302 return BX;
2303}
2304
2305// ============================================================================================
2306//
2307// Video Utils
2308//
2309// ============================================================================================
2310
2311// --------------------------------------------------------------------------------------------
2312static uint8_t find_vga_entry(uint8_t mode)
2313{
2314 uint8_t i,line=0xFF;
2315 for(i=0;i<=MODE_MAX;i++)
2316 if(vga_modes[i].svgamode==mode)
2317 {line=i;
2318 break;
2319 }
2320 return line;
2321}
2322
2323/* =========================================================== */
2324/*
2325 * Misc Utils
2326*/
2327/* =========================================================== */
2328
2329/* This function is used for planar VGA memory reads to defeat the
2330 * optimizer. We must read exactly one byte, otherwise the screen
2331 * may be corrupted.
2332 */
2333uint8_t xread_byte(uint16_t seg, uint16_t offset)
2334{
2335 return( *(seg:>(uint8_t *)offset) );
2336}
2337
2338#ifdef VGA_DEBUG
2339void __cdecl unimplemented()
2340{
2341 printf("--> Unimplemented\n");
2342}
2343
2344void __cdecl unknown()
2345{
2346 printf("--> Unknown int10\n");
2347}
2348
2349#undef VBE_PRINTF_PORT
2350#define VBE_PRINTF_PORT 0x504
2351
2352// --------------------------------------------------------------------------------------------
2353void __cdecl printf(char *s, ...)
2354{
2355 char c;
2356 Boolean in_format;
2357 unsigned format_width, i;
2358 uint16_t arg, digit, nibble;
2359 uint16_t STACK_BASED *arg_ptr;
2360
2361 arg_ptr = (uint16_t STACK_BASED *)&s;
2362
2363 in_format = 0;
2364 format_width = 0;
2365
2366 while (c = *s) {
2367 if (c == '%') {
2368 in_format = 1;
2369 format_width = 0;
2370 } else if (in_format) {
2371 if ((c >= '0') && (c <= '9')) {
2372 format_width = (format_width * 10) + (c - '0');
2373 } else if (c == 'x') {
2374 arg_ptr++; // increment to next arg
2375 arg = *arg_ptr;
2376 if (format_width == 0)
2377 format_width = 4;
2378 i = 0;
2379 digit = format_width - 1;
2380 for (i = 0; i < format_width; i++) {
2381 nibble = (arg >> (4 * digit)) & 0x000f;
2382 if (nibble <= 9)
2383 outb(VBE_PRINTF_PORT, nibble + '0');
2384 else
2385 outb(VBE_PRINTF_PORT, (nibble - 10) + 'A');
2386 digit--;
2387 }
2388 in_format = 0;
2389 }
2390 //else if (c == 'd') {
2391 // in_format = 0;
2392 // }
2393 } else {
2394 outb(VBE_PRINTF_PORT, c);
2395 }
2396 ++s;
2397 }
2398}
2399#endif
2400
2401/// @todo rearrange, call only from VBE module?
2402extern void vbe_biosfn_return_controller_information(uint16_t STACK_BASED *AX, uint16_t ES, uint16_t DI);
2403extern void vbe_biosfn_return_mode_information(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t ES, uint16_t DI);
2404extern void vbe_biosfn_set_mode(uint16_t STACK_BASED *AX, uint16_t BX, uint16_t ES, uint16_t DI);
2405extern void vbe_biosfn_save_restore_state(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t DX, uint16_t ES, uint16_t STACK_BASED *BX);
2406extern void vbe_biosfn_get_set_scanline_length(uint16_t STACK_BASED *AX, uint16_t STACK_BASED *BX, uint16_t STACK_BASED *CX, uint16_t STACK_BASED *DX);
2407extern void private_biosfn_custom_mode(uint16_t STACK_BASED *AX, uint16_t STACK_BASED *BX, uint16_t STACK_BASED *CX, uint16_t STACK_BASED *DX);
2408
2409
2410// --------------------------------------------------------------------------------------------
2411/*
2412 * int10 main dispatcher
2413 */
2414void __cdecl int10_func(uint16_t DI, uint16_t SI, uint16_t BP, uint16_t SP, uint16_t BX,
2415 uint16_t DX, uint16_t CX, uint16_t AX, uint16_t DS, uint16_t ES, uint16_t FLAGS)
2416{
2417
2418 // BIOS functions
2419 switch(GET_AH())
2420 {
2421 case 0x00:
2422 biosfn_set_video_mode(GET_AL());
2423 switch(GET_AL()&0x7F)
2424 {case 6:
2425 SET_AL(0x3F);
2426 break;
2427 case 0:
2428 case 1:
2429 case 2:
2430 case 3:
2431 case 4:
2432 case 5:
2433 case 7:
2434 SET_AL(0x30);
2435 break;
2436 default:
2437 SET_AL(0x20);
2438 }
2439 break;
2440 case 0x01:
2441 biosfn_set_cursor_shape(GET_CH(),GET_CL());
2442 break;
2443 case 0x02:
2444 biosfn_set_cursor_pos(GET_BH(),DX);
2445 break;
2446 case 0x03:
2447 vga_get_cursor_pos(GET_BH(), &CX, &DX);
2448 break;
2449 case 0x04:
2450 // Read light pen pos (unimplemented)
2451#ifdef VGA_DEBUG
2452 unimplemented();
2453#endif
2454 AX=0x00;
2455 BX=0x00;
2456 CX=0x00;
2457 DX=0x00;
2458 break;
2459 case 0x05:
2460 biosfn_set_active_page(GET_AL());
2461 break;
2462 case 0x06:
2463 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP);
2464 break;
2465 case 0x07:
2466 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN);
2467 break;
2468 case 0x08:
2469 vga_read_char_attr(GET_BH(), &AX);
2470 break;
2471 case 0x09:
2472 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX);
2473 break;
2474 case 0x0A:
2475 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX);
2476 break;
2477 case 0x0C:
2478 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX);
2479 break;
2480 case 0x0D:
2481 vga_read_pixel(GET_BH(), CX, DX, &AX);
2482 break;
2483 case 0x0E:
2484 // Ralf Brown Interrupt list is WRONG on bh(page)
2485 // We do output only on the current page !
2486#ifdef VGA_DEBUG
2487 printf("write_teletype %02x\n", GET_AL());
2488#endif
2489
2490 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR);
2491 break;
2492 case 0x10:
2493 // All other functions of group AH=0x10 rewritten in assembler
2494 biosfn_perform_gray_scale_summing(BX,CX);
2495 break;
2496 case 0x11:
2497 switch(GET_AL())
2498 {
2499 case 0x00:
2500 case 0x10:
2501 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH());
2502 break;
2503 case 0x01:
2504 case 0x11:
2505 biosfn_load_text_8_14_pat(GET_AL(),GET_BL());
2506 break;
2507 case 0x02:
2508 case 0x12:
2509 biosfn_load_text_8_8_pat(GET_AL(),GET_BL());
2510 break;
2511 case 0x04:
2512 case 0x14:
2513 biosfn_load_text_8_16_pat(GET_AL(),GET_BL());
2514 break;
2515 case 0x20:
2516 biosfn_load_gfx_8_8_chars(ES,BP);
2517 break;
2518 case 0x21:
2519 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL());
2520 break;
2521 case 0x22:
2522 biosfn_load_gfx_8_14_chars(GET_BL());
2523 break;
2524 case 0x23:
2525 biosfn_load_gfx_8_8_dd_chars(GET_BL());
2526 break;
2527 case 0x24:
2528 biosfn_load_gfx_8_16_chars(GET_BL());
2529 break;
2530 case 0x30:
2531 vga_get_font_info(GET_BH(), &ES, &BP, &CX, &DX);
2532 break;
2533#ifdef VGA_DEBUG
2534 default:
2535 unknown();
2536#endif
2537 }
2538
2539 break;
2540 case 0x12:
2541 switch(GET_BL())
2542 {
2543 case 0x20:
2544 biosfn_alternate_prtsc();
2545 break;
2546 case 0x34: /* CGA text cursor emulation control. */
2547 if (GET_AL() < 2) {
2548 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,
2549 (xread_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & ~1) | GET_AL());
2550 SET_AL(0x12);
2551 }
2552 else
2553 SET_AL(0); /* Invalid argument. */
2554 break;
2555 case 0x35:
2556 biosfn_switch_video_interface(GET_AL(),ES,DX);
2557 SET_AL(0x12);
2558 break;
2559 case 0x36:
2560 biosfn_enable_video_refresh_control(GET_AL());
2561 SET_AL(0x12);
2562 break;
2563#ifdef VGA_DEBUG
2564 default:
2565 unknown();
2566#endif
2567 }
2568 break;
2569 case 0x13:
2570 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP);
2571 break;
2572 case 0x1B:
2573 biosfn_read_state_info(BX,ES,DI);
2574 SET_AL(0x1B);
2575 break;
2576 case 0x1C:
2577 switch(GET_AL())
2578 {
2579 case 0x00:
2580 vga_get_video_state_size(CX,&BX);
2581 break;
2582 case 0x01:
2583 biosfn_save_video_state(CX,ES,BX);
2584 break;
2585 case 0x02:
2586 biosfn_restore_video_state(CX,ES,BX);
2587 break;
2588#ifdef VGA_DEBUG
2589 default:
2590 unknown();
2591#endif
2592 }
2593 SET_AL(0x1C);
2594 break;
2595
2596#ifdef VBE
2597 case 0x4f:
2598 if (vbe_has_vbe_display()) {
2599 switch(GET_AL())
2600 {
2601 case 0x00:
2602 vbe_biosfn_return_controller_information(&AX,ES,DI);
2603 break;
2604 case 0x01:
2605 vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
2606 break;
2607 case 0x02:
2608 vbe_biosfn_set_mode(&AX,BX,ES,DI);
2609 break;
2610 case 0x04:
2611 vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
2612 break;
2613 case 0x06:
2614 vbe_biosfn_get_set_scanline_length(&AX, &BX, &CX, &DX);
2615 break;
2616 case 0x09:
2617 //FIXME
2618#ifdef VGA_DEBUG
2619 unimplemented();
2620#endif
2621 // function failed
2622 AX=0x100;
2623 break;
2624 case 0x0A:
2625 //FIXME
2626#ifdef VGA_DEBUG
2627 unimplemented();
2628#endif
2629 // function failed
2630 AX=0x100;
2631 break;
2632 default:
2633#ifdef VGA_DEBUG
2634 unknown();
2635#endif
2636 // function failed
2637 AX=0x100;
2638 }
2639 }
2640 else {
2641 // No VBE display
2642 AX=0x0100;
2643 }
2644 break;
2645 case 0x56:
2646 if (vbe_has_vbe_display()) {
2647 switch(GET_AL())
2648 {
2649 case 0x42:
2650 private_biosfn_custom_mode(&AX,&BX,&CX,&DX);
2651 break;
2652 default:
2653 AX=0x0100;
2654 break;
2655 }
2656 } else {
2657 // No VBE display
2658 AX=0x0100;
2659 }
2660 break;
2661#endif
2662
2663#ifdef VGA_DEBUG
2664 default:
2665 unknown();
2666#endif
2667 }
2668}
2669
2670#ifdef VBE
2671//#include "vbe.c"
2672#endif
2673
2674#ifdef CIRRUS
2675#include "clext.c"
2676#endif
2677
2678// --------------------------------------------------------------------------------------------
2679
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use