|
|
1.1 root 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: // - [email protected]
48: //
49: // ============================================================================================
50:
51: #include "vgabios.h"
52:
53: #ifdef VBE
54: #include "vbe.h"
55: #endif
56:
57: #define USE_BX_INFO
58:
59: /* Declares */
60: static Bit8u read_byte();
61: static Bit16u read_word();
62: static void write_byte();
63: static void write_word();
64: static Bit8u inb();
65: static Bit16u inw();
66: static void outb();
67: static void outw();
68:
69: static Bit16u get_SS();
70:
71: // Output
72: static void printf();
73: static void unimplemented();
74: static void unknown();
75:
76: static Bit8u find_vga_entry();
77:
78: static void memsetb();
79: static void memsetw();
80: static void memcpyb();
81: static void memcpyw();
82:
83: static void biosfn_set_video_mode();
84: static void biosfn_set_cursor_shape();
85: static void biosfn_set_cursor_pos();
86: static void biosfn_get_cursor_pos();
87: static void biosfn_set_active_page();
88: static void biosfn_scroll();
89: static void biosfn_read_char_attr();
90: static void biosfn_write_char_attr();
91: static void biosfn_write_char_only();
92: static void biosfn_write_pixel();
93: static void biosfn_read_pixel();
94: static void biosfn_write_teletype();
95: static void biosfn_perform_gray_scale_summing();
96: static void biosfn_load_text_user_pat();
97: static void biosfn_load_text_8_14_pat();
98: static void biosfn_load_text_8_8_pat();
99: static void biosfn_load_text_8_16_pat();
100: static void biosfn_load_gfx_8_8_chars();
101: static void biosfn_load_gfx_user_chars();
102: static void biosfn_load_gfx_8_14_chars();
103: static void biosfn_load_gfx_8_8_dd_chars();
104: static void biosfn_load_gfx_8_16_chars();
105: static void biosfn_get_font_info();
106: static void biosfn_alternate_prtsc();
107: static void biosfn_switch_video_interface();
108: static void biosfn_enable_video_refresh_control();
109: static void biosfn_write_string();
110: static void biosfn_read_state_info();
111: static void biosfn_read_video_state_size();
112: static Bit16u biosfn_save_video_state();
113: static Bit16u biosfn_restore_video_state();
114: extern Bit8u video_save_pointer_table[];
115:
116: // This is for compiling with gcc2 and gcc3
117: #define ASM_START #asm
118: #define ASM_END #endasm
119:
120: ASM_START
121:
122: MACRO SET_INT_VECTOR
123: push ds
124: xor ax, ax
125: mov ds, ax
126: mov ax, ?3
127: mov ?1*4, ax
128: mov ax, ?2
129: mov ?1*4+2, ax
130: pop ds
131: MEND
132:
133: ASM_END
134:
135: ASM_START
136: .text
137: .rom
138: .org 0
139:
140: use16 386
141:
142: vgabios_start:
143: .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */
144:
145: .byte 0x40 /* BIOS extension length in units of 512 bytes */
146:
147:
148: vgabios_entry_point:
149:
150: jmp vgabios_init_func
151:
152: #ifdef PCIBIOS
153: .org 0x18
154: .word vgabios_pci_data
155: #endif
156:
157: // Info from Bart Oldeman
158: .org 0x1e
159: .ascii "IBM"
160: .byte 0x00
161:
162: vgabios_name:
163: .ascii "Plex86/Bochs VGABios"
164: #ifdef PCIBIOS
165: .ascii " (PCI)"
166: #endif
167: .ascii " "
168: .byte 0x00
169:
170: vgabios_version:
171: #ifndef VGABIOS_VERS
172: .ascii "current-cvs"
173: #else
174: .ascii VGABIOS_VERS
175: #endif
176: .ascii " "
177:
178: vgabios_date:
179: .ascii VGABIOS_DATE
180: .byte 0x0a,0x0d
181: .byte 0x00
182:
183: vgabios_copyright:
184: .ascii "(C) 2008 the LGPL VGABios developers Team"
185: .byte 0x0a,0x0d
186: .byte 0x00
187:
188: vgabios_license:
189: .ascii "This VGA/VBE Bios is released under the GNU LGPL"
190: .byte 0x0a,0x0d
191: .byte 0x0a,0x0d
192: .byte 0x00
193:
194: vgabios_website:
195: .ascii "Please visit :"
196: .byte 0x0a,0x0d
197: ;;.ascii " . http://www.plex86.org"
198: ;;.byte 0x0a,0x0d
199: .ascii " . http://bochs.sourceforge.net"
200: .byte 0x0a,0x0d
201: .ascii " . http://www.nongnu.org/vgabios"
202: .byte 0x0a,0x0d
203: .byte 0x0a,0x0d
204: .byte 0x00
205:
206: #ifdef PCIBIOS
207: vgabios_pci_data:
208: .ascii "PCIR"
209: #ifdef CIRRUS
210: .word 0x1013
211: .word 0x00b8 // CLGD5446
212: #else
213: #error "Unknown PCI vendor and device id"
214: #endif
215: .word 0 // reserved
216: .word 0x18 // dlen
217: .byte 0 // revision
218: .byte 0x0 // class,hi: vga display
219: .word 0x300 // class,lo: vga display
220: .word 0x40 // bios size
221: .word 1 // revision
222: .byte 0 // intel x86 data
223: .byte 0x80 // last image
224: .word 0 // reserved
225: #endif
226:
227:
228: ;; ============================================================================================
229: ;;
230: ;; Init Entry point
231: ;;
232: ;; ============================================================================================
233: vgabios_init_func:
234:
235: ;; init vga card
236: call init_vga_card
237:
238: ;; init basic bios vars
239: call init_bios_area
240:
241: #ifdef VBE
242: ;; init vbe functions
243: call vbe_init
244: #endif
245:
246: ;; set int10 vect
247: SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler)
248:
249: #ifdef CIRRUS
250: call cirrus_init
251: #endif
252:
253: ;; display splash screen
254: call _display_splash_screen
255:
256: ;; init video mode and clear the screen
257: mov ax,#0x0003
258: int #0x10
259:
260: ;; show info
261: call _display_info
262:
263: #ifdef VBE
264: ;; show vbe info
265: call vbe_display_info
266: #endif
267:
268: #ifdef CIRRUS
269: ;; show cirrus info
270: call cirrus_display_info
271: #endif
272:
273: retf
274: ASM_END
275:
276: /*
277: * int10 handled here
278: */
279: ASM_START
280: vgabios_int10_handler:
281: pushf
282: #ifdef DEBUG
283: push es
284: push ds
285: pusha
286: mov bx, #0xc000
287: mov ds, bx
288: call _int10_debugmsg
289: popa
290: pop ds
291: pop es
292: #endif
293: cmp ah, #0x0f
294: jne int10_test_1A
295: call biosfn_get_video_mode
296: jmp int10_end
297: int10_test_1A:
298: cmp ah, #0x1a
299: jne int10_test_0B
300: call biosfn_group_1A
301: jmp int10_end
302: int10_test_0B:
303: cmp ah, #0x0b
304: jne int10_test_1103
305: call biosfn_group_0B
306: jmp int10_end
307: int10_test_1103:
308: cmp ax, #0x1103
309: jne int10_test_12
310: call biosfn_set_text_block_specifier
311: jmp int10_end
312: int10_test_12:
313: cmp ah, #0x12
314: jne int10_test_101B
315: cmp bl, #0x10
316: jne int10_test_BL30
317: call biosfn_get_ega_info
318: jmp int10_end
319: int10_test_BL30:
320: cmp bl, #0x30
321: jne int10_test_BL31
322: call biosfn_select_vert_res
323: jmp int10_end
324: int10_test_BL31:
325: cmp bl, #0x31
326: jne int10_test_BL32
327: call biosfn_enable_default_palette_loading
328: jmp int10_end
329: int10_test_BL32:
330: cmp bl, #0x32
331: jne int10_test_BL33
332: call biosfn_enable_video_addressing
333: jmp int10_end
334: int10_test_BL33:
335: cmp bl, #0x33
336: jne int10_test_BL34
337: call biosfn_enable_grayscale_summing
338: jmp int10_end
339: int10_test_BL34:
340: cmp bl, #0x34
341: jne int10_normal
342: call biosfn_enable_cursor_emulation
343: jmp int10_end
344: int10_test_101B:
345: cmp ax, #0x101b
346: je int10_normal
347: cmp ah, #0x10
348: #ifndef VBE
349: jne int10_normal
350: #else
351: jne int10_test_4F
352: #endif
353: call biosfn_group_10
354: jmp int10_end
355: #ifdef VBE
356: int10_test_4F:
357: cmp ah, #0x4f
358: jne int10_normal
359: cmp al, #0x03
360: jne int10_test_vbe_05
361: call vbe_biosfn_return_current_mode
362: jmp int10_end
363: int10_test_vbe_05:
364: cmp al, #0x05
365: jne int10_test_vbe_06
366: call vbe_biosfn_display_window_control
367: jmp int10_end
368: int10_test_vbe_06:
369: cmp al, #0x06
370: jne int10_test_vbe_07
371: call vbe_biosfn_set_get_logical_scan_line_length
372: jmp int10_end
373: int10_test_vbe_07:
374: cmp al, #0x07
375: jne int10_test_vbe_08
376: call vbe_biosfn_set_get_display_start
377: jmp int10_end
378: int10_test_vbe_08:
379: cmp al, #0x08
380: jne int10_test_vbe_0A
381: call vbe_biosfn_set_get_dac_palette_format
382: jmp int10_end
383: int10_test_vbe_0A:
384: cmp al, #0x0A
385: jne int10_normal
386: call vbe_biosfn_return_protected_mode_interface
387: jmp int10_end
388: #endif
389:
390: int10_normal:
391: push es
392: push ds
393: pusha
394:
395: ;; We have to set ds to access the right data segment
396: mov bx, #0xc000
397: mov ds, bx
398: call _int10_func
399:
400: popa
401: pop ds
402: pop es
403: int10_end:
404: popf
405: iret
406: ASM_END
407:
408: #include "vgatables.h"
409: #include "vgafonts.h"
410:
411: /*
412: * Boot time harware inits
413: */
414: ASM_START
415: init_vga_card:
416: ;; switch to color mode and enable CPU access 480 lines
417: mov dx, #0x3C2
418: mov al, #0xC3
419: outb dx,al
420:
421: ;; more than 64k 3C4/04
422: mov dx, #0x3C4
423: mov al, #0x04
424: outb dx,al
425: mov dx, #0x3C5
426: mov al, #0x02
427: outb dx,al
428:
429: #if defined(USE_BX_INFO) || defined(DEBUG)
430: mov bx, #msg_vga_init
431: push bx
432: call _printf
433: #endif
434: inc sp
435: inc sp
436: ret
437:
438: #if defined(USE_BX_INFO) || defined(DEBUG)
439: msg_vga_init:
440: .ascii "VGABios $Id$"
441: .byte 0x0d,0x0a,0x00
442: #endif
443: ASM_END
444:
445: // --------------------------------------------------------------------------------------------
446: /*
447: * Boot time bios area inits
448: */
449: ASM_START
450: init_bios_area:
451: push ds
452: mov ax, # BIOSMEM_SEG
453: mov ds, ax
454:
455: ;; init detected hardware BIOS Area
456: mov bx, # BIOSMEM_INITIAL_MODE
457: mov ax, [bx]
458: and ax, #0xffcf
459: ;; set 80x25 color (not clear from RBIL but usual)
460: or ax, #0x0020
461: mov [bx], ax
462:
463: ;; Just for the first int10 find its children
464:
465: ;; the default char height
466: mov bx, # BIOSMEM_CHAR_HEIGHT
467: mov al, #0x10
468: mov [bx], al
469:
470: ;; Clear the screen
471: mov bx, # BIOSMEM_VIDEO_CTL
472: mov al, #0x60
473: mov [bx], al
474:
475: ;; Set the basic screen we have
476: mov bx, # BIOSMEM_SWITCHES
477: mov al, #0xf9
478: mov [bx], al
479:
480: ;; Set the basic modeset options
481: mov bx, # BIOSMEM_MODESET_CTL
482: mov al, #0x51
483: mov [bx], al
484:
485: ;; Set the default MSR
486: mov bx, # BIOSMEM_CURRENT_MSR
487: mov al, #0x09
488: mov [bx], al
489:
490: pop ds
491: ret
492:
493: _video_save_pointer_table:
494: .word _video_param_table
495: .word 0xc000
496:
497: .word 0 /* XXX: fill it */
498: .word 0
499:
500: .word 0 /* XXX: fill it */
501: .word 0
502:
503: .word 0 /* XXX: fill it */
504: .word 0
505:
506: .word 0 /* XXX: fill it */
507: .word 0
508:
509: .word 0 /* XXX: fill it */
510: .word 0
511:
512: .word 0 /* XXX: fill it */
513: .word 0
514:
515: ASM_END
516:
517: // --------------------------------------------------------------------------------------------
518: /*
519: * Boot time Splash screen
520: */
521: static void display_splash_screen()
522: {
523: }
524:
525: // --------------------------------------------------------------------------------------------
526: /*
527: * Tell who we are
528: */
529:
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:
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
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: */
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:
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
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: // --------------------------------------------------------------------------------------------
1940: static void biosfn_write_teletype (car, page, attr, flag)
1941: Bit8u car;Bit8u page;Bit8u attr;Bit8u flag;
1942: {// flag = WITH_ATTR / NO_ATTR
1943:
1944: Bit8u cheight,xcurs,ycurs,mode,line,bpp;
1945: Bit16u nbcols,nbrows,address;
1946: Bit16u cursor,dummy;
1947:
1948: // special case if page is 0xff, use current page
1949: if(page==0xff)
1950: page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
1951:
1952: // Get the mode
1953: mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
1954: line=find_vga_entry(mode);
1955: if(line==0xFF)return;
1956:
1957: // Get the cursor pos for the page
1958: biosfn_get_cursor_pos(page,&dummy,&cursor);
1959: xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1960:
1961: // Get the dimensions
1962: nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1;
1963: nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
1964:
1965: switch(car)
1966: {
1967: case 7:
1968: //FIXME should beep
1969: break;
1970:
1971: case 8:
1972: if(xcurs>0)xcurs--;
1973: break;
1974:
1975: case '\r':
1976: xcurs=0;
1977: break;
1978:
1979: case '\n':
1980: ycurs++;
1981: break;
1982:
1983: case '\t':
1984: do
1985: {
1986: biosfn_write_teletype(' ',page,attr,flag);
1987: biosfn_get_cursor_pos(page,&dummy,&cursor);
1988: xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8;
1989: }while(xcurs%8==0);
1990: break;
1991:
1992: default:
1993:
1994: if(vga_modes[line].class==TEXT)
1995: {
1996: // Compute the address
1997: address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2;
1998:
1999: // Write the char
2000: write_byte(vga_modes[line].sstart,address,car);
2001:
2002: if(flag==WITH_ATTR)
2003: write_byte(vga_modes[line].sstart,address+1,attr);
2004: }
2005: else
2006: {
2007: // FIXME gfx mode not complete
2008: cheight=video_param_table[line_to_vpti[line]].cheight;
2009: bpp=vga_modes[line].pixbits;
2010: switch(vga_modes[line].memmodel)
2011: {
2012: case PLANAR4:
2013: case PLANAR1:
2014: write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight);
2015: break;
2016: case CGA:
2017: write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp);
2018: break;
2019: case LINEAR8:
2020: write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols);
2021: break;
2022: #ifdef DEBUG
2023: default:
2024: unimplemented();
2025: #endif
2026: }
2027: }
2028: xcurs++;
2029: }
2030:
2031: // Do we need to wrap ?
2032: if(xcurs==nbcols)
2033: {xcurs=0;
2034: ycurs++;
2035: }
2036:
2037: // Do we need to scroll ?
2038: if(ycurs==nbrows)
2039: {
2040: if(vga_modes[line].class==TEXT)
2041: {
2042: biosfn_scroll(0x01,0x07,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2043: }
2044: else
2045: {
2046: biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP);
2047: }
2048: ycurs-=1;
2049: }
2050:
2051: // Set the cursor for the page
2052: cursor=ycurs; cursor<<=8; cursor+=xcurs;
2053: biosfn_set_cursor_pos(page,cursor);
2054: }
2055:
2056: // --------------------------------------------------------------------------------------------
2057: ASM_START
2058: biosfn_get_video_mode:
2059: push ds
2060: mov ax, # BIOSMEM_SEG
2061: mov ds, ax
2062: push bx
2063: mov bx, # BIOSMEM_CURRENT_PAGE
2064: mov al, [bx]
2065: pop bx
2066: mov bh, al
2067: push bx
2068: mov bx, # BIOSMEM_VIDEO_CTL
2069: mov ah, [bx]
2070: and ah, #0x80
2071: mov bx, # BIOSMEM_CURRENT_MODE
2072: mov al, [bx]
2073: or al, ah
2074: mov bx, # BIOSMEM_NB_COLS
2075: mov ah, [bx]
2076: pop bx
2077: pop ds
2078: ret
2079: ASM_END
2080:
2081: // --------------------------------------------------------------------------------------------
2082: ASM_START
2083: biosfn_group_10:
2084: cmp al, #0x00
2085: jne int10_test_1001
2086: jmp biosfn_set_single_palette_reg
2087: int10_test_1001:
2088: cmp al, #0x01
2089: jne int10_test_1002
2090: jmp biosfn_set_overscan_border_color
2091: int10_test_1002:
2092: cmp al, #0x02
2093: jne int10_test_1003
2094: jmp biosfn_set_all_palette_reg
2095: int10_test_1003:
2096: cmp al, #0x03
2097: jne int10_test_1007
2098: jmp biosfn_toggle_intensity
2099: int10_test_1007:
2100: cmp al, #0x07
2101: jne int10_test_1008
2102: jmp biosfn_get_single_palette_reg
2103: int10_test_1008:
2104: cmp al, #0x08
2105: jne int10_test_1009
2106: jmp biosfn_read_overscan_border_color
2107: int10_test_1009:
2108: cmp al, #0x09
2109: jne int10_test_1010
2110: jmp biosfn_get_all_palette_reg
2111: int10_test_1010:
2112: cmp al, #0x10
2113: jne int10_test_1012
2114: jmp biosfn_set_single_dac_reg
2115: int10_test_1012:
2116: cmp al, #0x12
2117: jne int10_test_1013
2118: jmp biosfn_set_all_dac_reg
2119: int10_test_1013:
2120: cmp al, #0x13
2121: jne int10_test_1015
2122: jmp biosfn_select_video_dac_color_page
2123: int10_test_1015:
2124: cmp al, #0x15
2125: jne int10_test_1017
2126: jmp biosfn_read_single_dac_reg
2127: int10_test_1017:
2128: cmp al, #0x17
2129: jne int10_test_1018
2130: jmp biosfn_read_all_dac_reg
2131: int10_test_1018:
2132: cmp al, #0x18
2133: jne int10_test_1019
2134: jmp biosfn_set_pel_mask
2135: int10_test_1019:
2136: cmp al, #0x19
2137: jne int10_test_101A
2138: jmp biosfn_read_pel_mask
2139: int10_test_101A:
2140: cmp al, #0x1a
2141: jne int10_group_10_unknown
2142: jmp biosfn_read_video_dac_state
2143: int10_group_10_unknown:
2144: #ifdef DEBUG
2145: call _unknown
2146: #endif
2147: ret
2148:
2149: biosfn_set_single_palette_reg:
2150: cmp bl, #0x14
2151: ja no_actl_reg1
2152: push ax
2153: push dx
2154: mov dx, # VGAREG_ACTL_RESET
2155: in al, dx
2156: mov dx, # VGAREG_ACTL_ADDRESS
2157: mov al, bl
2158: out dx, al
2159: mov al, bh
2160: out dx, al
2161: mov al, #0x20
2162: out dx, al
2163: pop dx
2164: pop ax
2165: no_actl_reg1:
2166: ret
2167: ASM_END
2168:
2169: // --------------------------------------------------------------------------------------------
2170: ASM_START
2171: biosfn_set_overscan_border_color:
2172: push bx
2173: mov bl, #0x11
2174: call biosfn_set_single_palette_reg
2175: pop bx
2176: ret
2177: ASM_END
2178:
2179: // --------------------------------------------------------------------------------------------
2180: ASM_START
2181: biosfn_set_all_palette_reg:
2182: push ax
2183: push bx
2184: push cx
2185: push dx
2186: mov bx, dx
2187: mov dx, # VGAREG_ACTL_RESET
2188: in al, dx
2189: mov cl, #0x00
2190: mov dx, # VGAREG_ACTL_ADDRESS
2191: set_palette_loop:
2192: mov al, cl
2193: out dx, al
2194: seg es
2195: mov al, [bx]
2196: out dx, al
2197: inc bx
2198: inc cl
2199: cmp cl, #0x10
2200: jne set_palette_loop
2201: mov al, #0x11
2202: out dx, al
2203: seg es
2204: mov al, [bx]
2205: out dx, al
2206: mov al, #0x20
2207: out dx, al
2208: pop dx
2209: pop cx
2210: pop bx
2211: pop ax
2212: ret
2213: ASM_END
2214:
2215: // --------------------------------------------------------------------------------------------
2216: ASM_START
2217: biosfn_toggle_intensity:
2218: push ax
2219: push bx
2220: push dx
2221: mov dx, # VGAREG_ACTL_RESET
2222: in al, dx
2223: mov dx, # VGAREG_ACTL_ADDRESS
2224: mov al, #0x10
2225: out dx, al
2226: mov dx, # VGAREG_ACTL_READ_DATA
2227: in al, dx
2228: and al, #0xf7
2229: and bl, #0x01
2230: shl bl, 3
2231: or al, bl
2232: mov dx, # VGAREG_ACTL_ADDRESS
2233: out dx, al
2234: mov al, #0x20
2235: out dx, al
2236: pop dx
2237: pop bx
2238: pop ax
2239: ret
2240: ASM_END
2241:
2242: // --------------------------------------------------------------------------------------------
2243: ASM_START
2244: biosfn_get_single_palette_reg:
2245: cmp bl, #0x14
2246: ja no_actl_reg2
2247: push ax
2248: push dx
2249: mov dx, # VGAREG_ACTL_RESET
2250: in al, dx
2251: mov dx, # VGAREG_ACTL_ADDRESS
2252: mov al, bl
2253: out dx, al
2254: mov dx, # VGAREG_ACTL_READ_DATA
2255: in al, dx
2256: mov bh, al
2257: mov dx, # VGAREG_ACTL_RESET
2258: in al, dx
2259: mov dx, # VGAREG_ACTL_ADDRESS
2260: mov al, #0x20
2261: out dx, al
2262: pop dx
2263: pop ax
2264: no_actl_reg2:
2265: ret
2266: ASM_END
2267:
2268: // --------------------------------------------------------------------------------------------
2269: ASM_START
2270: biosfn_read_overscan_border_color:
2271: push ax
2272: push bx
2273: mov bl, #0x11
2274: call biosfn_get_single_palette_reg
2275: mov al, bh
2276: pop bx
2277: mov bh, al
2278: pop ax
2279: ret
2280: ASM_END
2281:
2282: // --------------------------------------------------------------------------------------------
2283: ASM_START
2284: biosfn_get_all_palette_reg:
2285: push ax
2286: push bx
2287: push cx
2288: push dx
2289: mov bx, dx
2290: mov cl, #0x00
2291: get_palette_loop:
2292: mov dx, # VGAREG_ACTL_RESET
2293: in al, dx
2294: mov dx, # VGAREG_ACTL_ADDRESS
2295: mov al, cl
2296: out dx, al
2297: mov dx, # VGAREG_ACTL_READ_DATA
2298: in al, dx
2299: seg es
2300: mov [bx], al
2301: inc bx
2302: inc cl
2303: cmp cl, #0x10
2304: jne get_palette_loop
2305: mov dx, # VGAREG_ACTL_RESET
2306: in al, dx
2307: mov dx, # VGAREG_ACTL_ADDRESS
2308: mov al, #0x11
2309: out dx, al
2310: mov dx, # VGAREG_ACTL_READ_DATA
2311: in al, dx
2312: seg es
2313: mov [bx], al
2314: mov dx, # VGAREG_ACTL_RESET
2315: in al, dx
2316: mov dx, # VGAREG_ACTL_ADDRESS
2317: mov al, #0x20
2318: out dx, al
2319: pop dx
2320: pop cx
2321: pop bx
2322: pop ax
2323: ret
2324: ASM_END
2325:
2326: // --------------------------------------------------------------------------------------------
2327: ASM_START
2328: biosfn_set_single_dac_reg:
2329: push ax
2330: push dx
2331: mov dx, # VGAREG_DAC_WRITE_ADDRESS
2332: mov al, bl
2333: out dx, al
2334: mov dx, # VGAREG_DAC_DATA
2335: pop ax
2336: push ax
2337: mov al, ah
2338: out dx, al
2339: mov al, ch
2340: out dx, al
2341: mov al, cl
2342: out dx, al
2343: pop dx
2344: pop ax
2345: ret
2346: ASM_END
2347:
2348: // --------------------------------------------------------------------------------------------
2349: ASM_START
2350: biosfn_set_all_dac_reg:
2351: push ax
2352: push bx
2353: push cx
2354: push dx
2355: mov dx, # VGAREG_DAC_WRITE_ADDRESS
2356: mov al, bl
2357: out dx, al
2358: pop dx
2359: push dx
2360: mov bx, dx
2361: mov dx, # VGAREG_DAC_DATA
2362: set_dac_loop:
2363: seg es
2364: mov al, [bx]
2365: out dx, al
2366: inc bx
2367: seg es
2368: mov al, [bx]
2369: out dx, al
2370: inc bx
2371: seg es
2372: mov al, [bx]
2373: out dx, al
2374: inc bx
2375: dec cx
2376: jnz set_dac_loop
2377: pop dx
2378: pop cx
2379: pop bx
2380: pop ax
2381: ret
2382: ASM_END
2383:
2384: // --------------------------------------------------------------------------------------------
2385: ASM_START
2386: biosfn_select_video_dac_color_page:
2387: push ax
2388: push bx
2389: push dx
2390: mov dx, # VGAREG_ACTL_RESET
2391: in al, dx
2392: mov dx, # VGAREG_ACTL_ADDRESS
2393: mov al, #0x10
2394: out dx, al
2395: mov dx, # VGAREG_ACTL_READ_DATA
2396: in al, dx
2397: and bl, #0x01
2398: jnz set_dac_page
2399: and al, #0x7f
2400: shl bh, 7
2401: or al, bh
2402: mov dx, # VGAREG_ACTL_ADDRESS
2403: out dx, al
2404: jmp set_actl_normal
2405: set_dac_page:
2406: push ax
2407: mov dx, # VGAREG_ACTL_RESET
2408: in al, dx
2409: mov dx, # VGAREG_ACTL_ADDRESS
2410: mov al, #0x14
2411: out dx, al
2412: pop ax
2413: and al, #0x80
2414: jnz set_dac_16_page
2415: shl bh, 2
2416: set_dac_16_page:
2417: and bh, #0x0f
2418: mov al, bh
2419: out dx, al
2420: set_actl_normal:
2421: mov al, #0x20
2422: out dx, al
2423: pop dx
2424: pop bx
2425: pop ax
2426: ret
2427: ASM_END
2428:
2429: // --------------------------------------------------------------------------------------------
2430: ASM_START
2431: biosfn_read_single_dac_reg:
2432: push ax
2433: push dx
2434: mov dx, # VGAREG_DAC_READ_ADDRESS
2435: mov al, bl
2436: out dx, al
2437: pop ax
2438: mov ah, al
2439: mov dx, # VGAREG_DAC_DATA
2440: in al, dx
2441: xchg al, ah
2442: push ax
2443: in al, dx
2444: mov ch, al
2445: in al, dx
2446: mov cl, al
2447: pop dx
2448: pop ax
2449: ret
2450: ASM_END
2451:
2452: // --------------------------------------------------------------------------------------------
2453: ASM_START
2454: biosfn_read_all_dac_reg:
2455: push ax
2456: push bx
2457: push cx
2458: push dx
2459: mov dx, # VGAREG_DAC_READ_ADDRESS
2460: mov al, bl
2461: out dx, al
2462: pop dx
2463: push dx
2464: mov bx, dx
2465: mov dx, # VGAREG_DAC_DATA
2466: read_dac_loop:
2467: in al, dx
2468: seg es
2469: mov [bx], al
2470: inc bx
2471: in al, dx
2472: seg es
2473: mov [bx], al
2474: inc bx
2475: in al, dx
2476: seg es
2477: mov [bx], al
2478: inc bx
2479: dec cx
2480: jnz read_dac_loop
2481: pop dx
2482: pop cx
2483: pop bx
2484: pop ax
2485: ret
2486: ASM_END
2487:
2488: // --------------------------------------------------------------------------------------------
2489: ASM_START
2490: biosfn_set_pel_mask:
2491: push ax
2492: push dx
2493: mov dx, # VGAREG_PEL_MASK
2494: mov al, bl
2495: out dx, al
2496: pop dx
2497: pop ax
2498: ret
2499: ASM_END
2500:
2501: // --------------------------------------------------------------------------------------------
2502: ASM_START
2503: biosfn_read_pel_mask:
2504: push ax
2505: push dx
2506: mov dx, # VGAREG_PEL_MASK
2507: in al, dx
2508: mov bl, al
2509: pop dx
2510: pop ax
2511: ret
2512: ASM_END
2513:
2514: // --------------------------------------------------------------------------------------------
2515: ASM_START
2516: biosfn_read_video_dac_state:
2517: push ax
2518: push dx
2519: mov dx, # VGAREG_ACTL_RESET
2520: in al, dx
2521: mov dx, # VGAREG_ACTL_ADDRESS
2522: mov al, #0x10
2523: out dx, al
2524: mov dx, # VGAREG_ACTL_READ_DATA
2525: in al, dx
2526: mov bl, al
2527: shr bl, 7
2528: mov dx, # VGAREG_ACTL_RESET
2529: in al, dx
2530: mov dx, # VGAREG_ACTL_ADDRESS
2531: mov al, #0x14
2532: out dx, al
2533: mov dx, # VGAREG_ACTL_READ_DATA
2534: in al, dx
2535: mov bh, al
2536: and bh, #0x0f
2537: test bl, #0x01
2538: jnz get_dac_16_page
2539: shr bh, 2
2540: get_dac_16_page:
2541: mov dx, # VGAREG_ACTL_RESET
2542: in al, dx
2543: mov dx, # VGAREG_ACTL_ADDRESS
2544: mov al, #0x20
2545: out dx, al
2546: pop dx
2547: pop ax
2548: ret
2549: ASM_END
2550:
2551: // --------------------------------------------------------------------------------------------
2552: static void biosfn_perform_gray_scale_summing (start,count)
2553: Bit16u start;Bit16u count;
2554: {Bit8u r,g,b;
2555: Bit16u i;
2556: Bit16u index;
2557:
2558: inb(VGAREG_ACTL_RESET);
2559: outb(VGAREG_ACTL_ADDRESS,0x00);
2560:
2561: for( index = 0; index < count; index++ )
2562: {
2563: // set read address and switch to read mode
2564: outb(VGAREG_DAC_READ_ADDRESS,start);
2565: // get 6-bit wide RGB data values
2566: r=inb( VGAREG_DAC_DATA );
2567: g=inb( VGAREG_DAC_DATA );
2568: b=inb( VGAREG_DAC_DATA );
2569:
2570: // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
2571: i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8;
2572:
2573: if(i>0x3f)i=0x3f;
2574:
2575: // set write address and switch to write mode
2576: outb(VGAREG_DAC_WRITE_ADDRESS,start);
2577: // write new intensity value
2578: outb( VGAREG_DAC_DATA, i&0xff );
2579: outb( VGAREG_DAC_DATA, i&0xff );
2580: outb( VGAREG_DAC_DATA, i&0xff );
2581: start++;
2582: }
2583: inb(VGAREG_ACTL_RESET);
2584: outb(VGAREG_ACTL_ADDRESS,0x20);
2585: }
2586:
2587: // --------------------------------------------------------------------------------------------
2588: static void get_font_access()
2589: {
2590: ASM_START
2591: mov dx, # VGAREG_SEQU_ADDRESS
2592: mov ax, #0x0100
2593: out dx, ax
2594: mov ax, #0x0402
2595: out dx, ax
2596: mov ax, #0x0704
2597: out dx, ax
2598: mov ax, #0x0300
2599: out dx, ax
2600: mov dx, # VGAREG_GRDC_ADDRESS
2601: mov ax, #0x0204
2602: out dx, ax
2603: mov ax, #0x0005
2604: out dx, ax
2605: mov ax, #0x0406
2606: out dx, ax
2607: ASM_END
2608: }
2609:
2610: static void release_font_access()
2611: {
2612: ASM_START
2613: mov dx, # VGAREG_SEQU_ADDRESS
2614: mov ax, #0x0100
2615: out dx, ax
2616: mov ax, #0x0302
2617: out dx, ax
2618: mov ax, #0x0304
2619: out dx, ax
2620: mov ax, #0x0300
2621: out dx, ax
2622: mov dx, # VGAREG_READ_MISC_OUTPUT
2623: in al, dx
2624: and al, #0x01
2625: shl al, 2
2626: or al, #0x0a
2627: mov ah, al
2628: mov al, #0x06
2629: mov dx, # VGAREG_GRDC_ADDRESS
2630: out dx, ax
2631: mov ax, #0x0004
2632: out dx, ax
2633: mov ax, #0x1005
2634: out dx, ax
2635: ASM_END
2636: }
2637:
2638: ASM_START
2639: idiv_u:
2640: xor dx,dx
2641: div bx
2642: ret
2643: ASM_END
2644:
2645: static void set_scan_lines(lines) Bit8u lines;
2646: {
2647: Bit16u crtc_addr,cols,page,vde;
2648: Bit8u crtc_r9,ovl,rows;
2649:
2650: crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
2651: outb(crtc_addr, 0x09);
2652: crtc_r9 = inb(crtc_addr+1);
2653: crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
2654: outb(crtc_addr+1, crtc_r9);
2655: if(lines==8)
2656: {
2657: biosfn_set_cursor_shape(0x06,0x07);
2658: }
2659: else
2660: {
2661: biosfn_set_cursor_shape(lines-4,lines-3);
2662: }
2663: write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines);
2664: outb(crtc_addr, 0x12);
2665: vde = inb(crtc_addr+1);
2666: outb(crtc_addr, 0x07);
2667: ovl = inb(crtc_addr+1);
2668: vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
2669: rows = vde / lines;
2670: write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1);
2671: cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS);
2672: write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2);
2673: }
2674:
2675: static void biosfn_load_text_user_pat (AL,ES,BP,CX,DX,BL,BH) Bit8u AL;Bit16u ES;Bit16u BP;Bit16u CX;Bit16u DX;Bit8u BL;Bit8u BH;
2676: {
2677: Bit16u blockaddr,dest,i,src;
2678:
2679: get_font_access();
2680: blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2681: for(i=0;i<CX;i++)
2682: {
2683: src = BP + i * BH;
2684: dest = blockaddr + (DX + i) * 32;
2685: memcpyb(0xA000, dest, ES, src, BH);
2686: }
2687: release_font_access();
2688: if(AL>=0x10)
2689: {
2690: set_scan_lines(BH);
2691: }
2692: }
2693:
2694: static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL;
2695: {
2696: Bit16u blockaddr,dest,i,src;
2697:
2698: get_font_access();
2699: blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2700: for(i=0;i<0x100;i++)
2701: {
2702: src = i * 14;
2703: dest = blockaddr + i * 32;
2704: memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14);
2705: }
2706: release_font_access();
2707: if(AL>=0x10)
2708: {
2709: set_scan_lines(14);
2710: }
2711: }
2712:
2713: static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL;
2714: {
2715: Bit16u blockaddr,dest,i,src;
2716:
2717: get_font_access();
2718: blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2719: for(i=0;i<0x100;i++)
2720: {
2721: src = i * 8;
2722: dest = blockaddr + i * 32;
2723: memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8);
2724: }
2725: release_font_access();
2726: if(AL>=0x10)
2727: {
2728: set_scan_lines(8);
2729: }
2730: }
2731:
2732: // --------------------------------------------------------------------------------------------
2733: ASM_START
2734: biosfn_set_text_block_specifier:
2735: push ax
2736: push dx
2737: mov dx, # VGAREG_SEQU_ADDRESS
2738: mov ah, bl
2739: mov al, #0x03
2740: out dx, ax
2741: pop dx
2742: pop ax
2743: ret
2744: ASM_END
2745:
2746: // --------------------------------------------------------------------------------------------
2747: static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL;
2748: {
2749: Bit16u blockaddr,dest,i,src;
2750:
2751: get_font_access();
2752: blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11);
2753: for(i=0;i<0x100;i++)
2754: {
2755: src = i * 16;
2756: dest = blockaddr + i * 32;
2757: memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16);
2758: }
2759: release_font_access();
2760: if(AL>=0x10)
2761: {
2762: set_scan_lines(16);
2763: }
2764: }
2765:
2766: static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP;
2767: {
2768: #ifdef DEBUG
2769: unimplemented();
2770: #endif
2771: }
2772: static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL;
2773: {
2774: #ifdef DEBUG
2775: unimplemented();
2776: #endif
2777: }
2778: static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL;
2779: {
2780: #ifdef DEBUG
2781: unimplemented();
2782: #endif
2783: }
2784: static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL;
2785: {
2786: #ifdef DEBUG
2787: unimplemented();
2788: #endif
2789: }
2790: static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL;
2791: {
2792: #ifdef DEBUG
2793: unimplemented();
2794: #endif
2795: }
2796: // --------------------------------------------------------------------------------------------
2797: static void biosfn_get_font_info (BH,ES,BP,CX,DX)
2798: Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX;
2799: {Bit16u ss=get_SS();
2800:
2801: switch(BH)
2802: {case 0x00:
2803: write_word(ss,ES,read_word(0x00,0x1f*4));
2804: write_word(ss,BP,read_word(0x00,(0x1f*4)+2));
2805: break;
2806: case 0x01:
2807: write_word(ss,ES,read_word(0x00,0x43*4));
2808: write_word(ss,BP,read_word(0x00,(0x43*4)+2));
2809: break;
2810: case 0x02:
2811: write_word(ss,ES,0xC000);
2812: write_word(ss,BP,vgafont14);
2813: break;
2814: case 0x03:
2815: write_word(ss,ES,0xC000);
2816: write_word(ss,BP,vgafont8);
2817: break;
2818: case 0x04:
2819: write_word(ss,ES,0xC000);
2820: write_word(ss,BP,vgafont8+128*8);
2821: break;
2822: case 0x05:
2823: write_word(ss,ES,0xC000);
2824: write_word(ss,BP,vgafont14alt);
2825: break;
2826: case 0x06:
2827: write_word(ss,ES,0xC000);
2828: write_word(ss,BP,vgafont16);
2829: break;
2830: case 0x07:
2831: write_word(ss,ES,0xC000);
2832: write_word(ss,BP,vgafont16alt);
2833: break;
2834: default:
2835: #ifdef DEBUG
2836: printf("Get font info BH(%02x) was discarded\n",BH);
2837: #endif
2838: return;
2839: }
2840: // Set byte/char of on screen font
2841: write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT));
2842:
2843: // Set Highest char row
2844: write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS));
2845: }
2846:
2847: // --------------------------------------------------------------------------------------------
2848: ASM_START
2849: biosfn_get_ega_info:
2850: push ds
2851: push ax
2852: mov ax, # BIOSMEM_SEG
2853: mov ds, ax
2854: xor ch, ch
2855: mov bx, # BIOSMEM_SWITCHES
2856: mov cl, [bx]
2857: and cl, #0x0f
2858: mov bx, # BIOSMEM_CRTC_ADDRESS
2859: mov ax, [bx]
2860: mov bx, #0x0003
2861: cmp ax, # VGAREG_MDA_CRTC_ADDRESS
2862: jne mode_ega_color
2863: mov bh, #0x01
2864: mode_ega_color:
2865: pop ax
2866: pop ds
2867: ret
2868: ASM_END
2869:
2870: // --------------------------------------------------------------------------------------------
2871: static void biosfn_alternate_prtsc()
2872: {
2873: #ifdef DEBUG
2874: unimplemented();
2875: #endif
2876: }
2877:
2878: // --------------------------------------------------------------------------------------------
2879: ASM_START
2880: biosfn_select_vert_res:
2881:
2882: ; res : 00 200 lines, 01 350 lines, 02 400 lines
2883:
2884: push ds
2885: push bx
2886: push dx
2887: mov dl, al
2888: mov ax, # BIOSMEM_SEG
2889: mov ds, ax
2890: mov bx, # BIOSMEM_MODESET_CTL
2891: mov al, [bx]
2892: mov bx, # BIOSMEM_SWITCHES
2893: mov ah, [bx]
2894: cmp dl, #0x01
2895: je vert_res_350
2896: jb vert_res_200
2897: cmp dl, #0x02
2898: je vert_res_400
2899: #ifdef DEBUG
2900: mov al, dl
2901: xor ah, ah
2902: push ax
2903: mov bx, #msg_vert_res
2904: push bx
2905: call _printf
2906: add sp, #4
2907: #endif
2908: jmp set_retcode
2909: vert_res_400:
2910:
2911: ; reset modeset ctl bit 7 and set bit 4
2912: ; set switches bit 3-0 to 0x09
2913:
2914: and al, #0x7f
2915: or al, #0x10
2916: and ah, #0xf0
2917: or ah, #0x09
2918: jnz set_vert_res
2919: vert_res_350:
2920:
2921: ; reset modeset ctl bit 7 and bit 4
2922: ; set switches bit 3-0 to 0x09
2923:
2924: and al, #0x6f
2925: and ah, #0xf0
2926: or ah, #0x09
2927: jnz set_vert_res
2928: vert_res_200:
2929:
2930: ; set modeset ctl bit 7 and reset bit 4
2931: ; set switches bit 3-0 to 0x08
2932:
2933: and al, #0xef
2934: or al, #0x80
2935: and ah, #0xf0
2936: or ah, #0x08
2937: set_vert_res:
2938: mov bx, # BIOSMEM_MODESET_CTL
2939: mov [bx], al
2940: mov bx, # BIOSMEM_SWITCHES
2941: mov [bx], ah
2942: set_retcode:
2943: mov ax, #0x1212
2944: pop dx
2945: pop bx
2946: pop ds
2947: ret
2948:
2949: #ifdef DEBUG
2950: msg_vert_res:
2951: .ascii "Select vert res (%02x) was discarded"
2952: .byte 0x0d,0x0a,0x00
2953: #endif
2954:
2955:
2956: biosfn_enable_default_palette_loading:
2957: push ds
2958: push bx
2959: push dx
2960: mov dl, al
2961: and dl, #0x01
2962: shl dl, 3
2963: mov ax, # BIOSMEM_SEG
2964: mov ds, ax
2965: mov bx, # BIOSMEM_MODESET_CTL
2966: mov al, [bx]
2967: and al, #0xf7
2968: or al, dl
2969: mov [bx], al
2970: mov ax, #0x1212
2971: pop dx
2972: pop bx
2973: pop ds
2974: ret
2975:
2976:
2977: biosfn_enable_video_addressing:
2978: push bx
2979: push dx
2980: mov bl, al
2981: and bl, #0x01
2982: xor bl, #0x01
2983: shl bl, 1
2984: mov dx, # VGAREG_READ_MISC_OUTPUT
2985: in al, dx
2986: and al, #0xfd
2987: or al, bl
2988: mov dx, # VGAREG_WRITE_MISC_OUTPUT
2989: out dx, al
2990: mov ax, #0x1212
2991: pop dx
2992: pop bx
2993: ret
2994:
2995:
2996: biosfn_enable_grayscale_summing:
2997: push ds
2998: push bx
2999: push dx
3000: mov dl, al
3001: and dl, #0x01
3002: xor dl, #0x01
3003: shl dl, 1
3004: mov ax, # BIOSMEM_SEG
3005: mov ds, ax
3006: mov bx, # BIOSMEM_MODESET_CTL
3007: mov al, [bx]
3008: and al, #0xfd
3009: or al, dl
3010: mov [bx], al
3011: mov ax, #0x1212
3012: pop dx
3013: pop bx
3014: pop ds
3015: ret
3016:
3017:
3018: biosfn_enable_cursor_emulation:
3019: push ds
3020: push bx
3021: push dx
3022: mov dl, al
3023: and dl, #0x01
3024: xor dl, #0x01
3025: mov ax, # BIOSMEM_SEG
3026: mov ds, ax
3027: mov bx, # BIOSMEM_MODESET_CTL
3028: mov al, [bx]
3029: and al, #0xfe
3030: or al, dl
3031: mov [bx], al
3032: mov ax, #0x1212
3033: pop dx
3034: pop bx
3035: pop ds
3036: ret
3037: ASM_END
3038:
3039: // --------------------------------------------------------------------------------------------
3040: static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX;
3041: {
3042: #ifdef DEBUG
3043: unimplemented();
3044: #endif
3045: }
3046: static void biosfn_enable_video_refresh_control (AL) Bit8u AL;
3047: {
3048: #ifdef DEBUG
3049: unimplemented();
3050: #endif
3051: }
3052:
3053: // --------------------------------------------------------------------------------------------
3054: static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset)
3055: Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset;
3056: {
3057: Bit16u newcurs,oldcurs,dummy;
3058: Bit8u car,carattr;
3059:
3060: // Read curs info for the page
3061: biosfn_get_cursor_pos(page,&dummy,&oldcurs);
3062:
3063: // if row=0xff special case : use current cursor position
3064: if(row==0xff)
3065: {col=oldcurs&0x00ff;
3066: row=(oldcurs&0xff00)>>8;
3067: }
3068:
3069: newcurs=row; newcurs<<=8; newcurs+=col;
3070: biosfn_set_cursor_pos(page,newcurs);
3071:
3072: while(count--!=0)
3073: {
3074: car=read_byte(seg,offset++);
3075: if((flag&0x02)!=0)
3076: attr=read_byte(seg,offset++);
3077:
3078: biosfn_write_teletype(car,page,attr,WITH_ATTR);
3079: }
3080:
3081: // Set back curs pos
3082: if((flag&0x01)==0)
3083: biosfn_set_cursor_pos(page,oldcurs);
3084: }
3085:
3086: // --------------------------------------------------------------------------------------------
3087: ASM_START
3088: biosfn_group_1A:
3089: cmp al, #0x00
3090: je biosfn_read_display_code
3091: cmp al, #0x01
3092: je biosfn_set_display_code
3093: #ifdef DEBUG
3094: call _unknown
3095: #endif
3096: ret
3097: biosfn_read_display_code:
3098: push ds
3099: push ax
3100: mov ax, # BIOSMEM_SEG
3101: mov ds, ax
3102: mov bx, # BIOSMEM_DCC_INDEX
3103: mov al, [bx]
3104: mov bl, al
3105: xor bh, bh
3106: pop ax
3107: mov al, ah
3108: pop ds
3109: ret
3110: biosfn_set_display_code:
3111: push ds
3112: push ax
3113: push bx
3114: mov ax, # BIOSMEM_SEG
3115: mov ds, ax
3116: mov ax, bx
3117: mov bx, # BIOSMEM_DCC_INDEX
3118: mov [bx], al
3119: #ifdef DEBUG
3120: mov al, ah
3121: xor ah, ah
3122: push ax
3123: mov bx, #msg_alt_dcc
3124: push bx
3125: call _printf
3126: add sp, #4
3127: #endif
3128: pop bx
3129: pop ax
3130: mov al, ah
3131: pop ds
3132: ret
3133:
3134: #ifdef DEBUG
3135: msg_alt_dcc:
3136: .ascii "Alternate Display code (%02x) was discarded"
3137: .byte 0x0d,0x0a,0x00
3138: #endif
3139: ASM_END
3140:
3141: // --------------------------------------------------------------------------------------------
3142: static void biosfn_read_state_info (BX,ES,DI)
3143: Bit16u BX;Bit16u ES;Bit16u DI;
3144: {
3145: // Address of static functionality table
3146: write_word(ES,DI+0x00,&static_functionality);
3147: write_word(ES,DI+0x02,0xC000);
3148:
3149: // Hard coded copy from BIOS area. Should it be cleaner ?
3150: memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30);
3151: memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3);
3152:
3153: write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX));
3154: write_byte(ES,DI+0x26,0);
3155: write_byte(ES,DI+0x27,16);
3156: write_byte(ES,DI+0x28,0);
3157: write_byte(ES,DI+0x29,8);
3158: write_byte(ES,DI+0x2a,2);
3159: write_byte(ES,DI+0x2b,0);
3160: write_byte(ES,DI+0x2c,0);
3161: write_byte(ES,DI+0x31,3);
3162: write_byte(ES,DI+0x32,0);
3163:
3164: memsetb(ES,DI+0x33,0,13);
3165: }
3166:
3167: // --------------------------------------------------------------------------------------------
3168: // --------------------------------------------------------------------------------------------
3169: static Bit16u biosfn_read_video_state_size2 (CX)
3170: Bit16u CX;
3171: {
3172: Bit16u size;
3173: size = 0;
3174: if (CX & 1) {
3175: size += 0x46;
3176: }
3177: if (CX & 2) {
3178: size += (5 + 8 + 5) * 2 + 6;
3179: }
3180: if (CX & 4) {
3181: size += 3 + 256 * 3 + 1;
3182: }
3183: return size;
3184: }
3185:
3186: static void biosfn_read_video_state_size (CX, BX)
3187: Bit16u CX; Bit16u *BX;
3188: {
3189: Bit16u ss=get_SS();
3190: write_word(ss, BX, biosfn_read_video_state_size2(CX));
3191: }
3192:
3193: static Bit16u biosfn_save_video_state (CX,ES,BX)
3194: Bit16u CX;Bit16u ES;Bit16u BX;
3195: {
3196: Bit16u i, v, crtc_addr, ar_index;
3197:
3198: crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
3199: if (CX & 1) {
3200: write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
3201: write_byte(ES, BX, inb(crtc_addr)); BX++;
3202: write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
3203: inb(VGAREG_ACTL_RESET);
3204: ar_index = inb(VGAREG_ACTL_ADDRESS);
3205: write_byte(ES, BX, ar_index); BX++;
3206: write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
3207:
3208: for(i=1;i<=4;i++){
3209: outb(VGAREG_SEQU_ADDRESS, i);
3210: write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3211: }
3212: outb(VGAREG_SEQU_ADDRESS, 0);
3213: write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
3214:
3215: for(i=0;i<=0x18;i++) {
3216: outb(crtc_addr,i);
3217: write_byte(ES, BX, inb(crtc_addr+1)); BX++;
3218: }
3219:
3220: for(i=0;i<=0x13;i++) {
3221: inb(VGAREG_ACTL_RESET);
3222: outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3223: write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
3224: }
3225: inb(VGAREG_ACTL_RESET);
3226:
3227: for(i=0;i<=8;i++) {
3228: outb(VGAREG_GRDC_ADDRESS,i);
3229: write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
3230: }
3231:
3232: write_word(ES, BX, crtc_addr); BX+= 2;
3233:
3234: /* XXX: read plane latches */
3235: write_byte(ES, BX, 0); BX++;
3236: write_byte(ES, BX, 0); BX++;
3237: write_byte(ES, BX, 0); BX++;
3238: write_byte(ES, BX, 0); BX++;
3239: }
3240: if (CX & 2) {
3241: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
3242: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
3243: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
3244: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
3245: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
3246: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
3247: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
3248: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
3249: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
3250: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
3251: for(i=0;i<8;i++) {
3252: write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
3253: BX += 2;
3254: }
3255: write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
3256: write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
3257: /* current font */
3258: write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
3259: write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
3260: write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
3261: write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
3262: }
3263: if (CX & 4) {
3264: /* XXX: check this */
3265: write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
3266: write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
3267: write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
3268: // Set the whole dac always, from 0
3269: outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3270: for(i=0;i<256*3;i++) {
3271: write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
3272: }
3273: write_byte(ES, BX, 0); BX++; /* color select register */
3274: }
3275: return BX;
3276: }
3277:
3278: static Bit16u biosfn_restore_video_state (CX,ES,BX)
3279: Bit16u CX;Bit16u ES;Bit16u BX;
3280: {
3281: Bit16u i, crtc_addr, v, addr1, ar_index;
3282:
3283: if (CX & 1) {
3284: // Reset Attribute Ctl flip-flop
3285: inb(VGAREG_ACTL_RESET);
3286:
3287: crtc_addr = read_word(ES, BX + 0x40);
3288: addr1 = BX;
3289: BX += 5;
3290:
3291: for(i=1;i<=4;i++){
3292: outb(VGAREG_SEQU_ADDRESS, i);
3293: outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3294: }
3295: outb(VGAREG_SEQU_ADDRESS, 0);
3296: outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
3297:
3298: // Disable CRTC write protection
3299: outw(crtc_addr,0x0011);
3300: // Set CRTC regs
3301: for(i=0;i<=0x18;i++) {
3302: if (i != 0x11) {
3303: outb(crtc_addr,i);
3304: outb(crtc_addr+1, read_byte(ES, BX));
3305: }
3306: BX++;
3307: }
3308: // select crtc base address
3309: v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
3310: if (crtc_addr = 0x3d4)
3311: v |= 0x01;
3312: outb(VGAREG_WRITE_MISC_OUTPUT, v);
3313:
3314: // enable write protection if needed
3315: outb(crtc_addr, 0x11);
3316: outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
3317:
3318: // Set Attribute Ctl
3319: ar_index = read_byte(ES, addr1 + 0x03);
3320: inb(VGAREG_ACTL_RESET);
3321: for(i=0;i<=0x13;i++) {
3322: outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
3323: outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
3324: }
3325: outb(VGAREG_ACTL_ADDRESS, ar_index);
3326: inb(VGAREG_ACTL_RESET);
3327:
3328: for(i=0;i<=8;i++) {
3329: outb(VGAREG_GRDC_ADDRESS,i);
3330: outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
3331: }
3332: BX += 2; /* crtc_addr */
3333: BX += 4; /* plane latches */
3334:
3335: outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
3336: outb(crtc_addr, read_byte(ES, addr1)); addr1++;
3337: outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
3338: addr1++;
3339: outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
3340: }
3341: if (CX & 2) {
3342: write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
3343: write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
3344: write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
3345: write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
3346: write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
3347: write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
3348: write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
3349: write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
3350: write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
3351: write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
3352: for(i=0;i<8;i++) {
3353: write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
3354: BX += 2;
3355: }
3356: write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
3357: write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
3358: /* current font */
3359: write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
3360: write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
3361: write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
3362: write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
3363: }
3364: if (CX & 4) {
3365: BX++;
3366: v = read_byte(ES, BX); BX++;
3367: outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
3368: // Set the whole dac always, from 0
3369: outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
3370: for(i=0;i<256*3;i++) {
3371: outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
3372: }
3373: BX++;
3374: outb(VGAREG_DAC_WRITE_ADDRESS, v);
3375: }
3376: return BX;
3377: }
3378:
3379: // ============================================================================================
3380: //
3381: // Video Utils
3382: //
3383: // ============================================================================================
3384:
3385: // --------------------------------------------------------------------------------------------
3386: static Bit8u find_vga_entry(mode)
3387: Bit8u mode;
3388: {
3389: Bit8u i,line=0xFF;
3390: for(i=0;i<=MODE_MAX;i++)
3391: if(vga_modes[i].svgamode==mode)
3392: {line=i;
3393: break;
3394: }
3395: return line;
3396: }
3397:
3398: /* =========================================================== */
3399: /*
3400: * Misc Utils
3401: */
3402: /* =========================================================== */
3403:
3404: // --------------------------------------------------------------------------------------------
3405: static void memsetb(seg,offset,value,count)
3406: Bit16u seg;
3407: Bit16u offset;
3408: Bit16u value;
3409: Bit16u count;
3410: {
3411: ASM_START
3412: push bp
3413: mov bp, sp
3414:
3415: push ax
3416: push cx
3417: push es
3418: push di
3419:
3420: mov cx, 10[bp] ; count
3421: cmp cx, #0x00
3422: je memsetb_end
3423: mov ax, 4[bp] ; segment
3424: mov es, ax
3425: mov ax, 6[bp] ; offset
3426: mov di, ax
3427: mov al, 8[bp] ; value
3428: cld
3429: rep
3430: stosb
3431:
3432: memsetb_end:
3433: pop di
3434: pop es
3435: pop cx
3436: pop ax
3437:
3438: pop bp
3439: ASM_END
3440: }
3441:
3442: // --------------------------------------------------------------------------------------------
3443: static void memsetw(seg,offset,value,count)
3444: Bit16u seg;
3445: Bit16u offset;
3446: Bit16u value;
3447: Bit16u count;
3448: {
3449: ASM_START
3450: push bp
3451: mov bp, sp
3452:
3453: push ax
3454: push cx
3455: push es
3456: push di
3457:
3458: mov cx, 10[bp] ; count
3459: cmp cx, #0x00
3460: je memsetw_end
3461: mov ax, 4[bp] ; segment
3462: mov es, ax
3463: mov ax, 6[bp] ; offset
3464: mov di, ax
3465: mov ax, 8[bp] ; value
3466: cld
3467: rep
3468: stosw
3469:
3470: memsetw_end:
3471: pop di
3472: pop es
3473: pop cx
3474: pop ax
3475:
3476: pop bp
3477: ASM_END
3478: }
3479:
3480: // --------------------------------------------------------------------------------------------
3481: static void memcpyb(dseg,doffset,sseg,soffset,count)
3482: Bit16u dseg;
3483: Bit16u doffset;
3484: Bit16u sseg;
3485: Bit16u soffset;
3486: Bit16u count;
3487: {
3488: ASM_START
3489: push bp
3490: mov bp, sp
3491:
3492: push ax
3493: push cx
3494: push es
3495: push di
3496: push ds
3497: push si
3498:
3499: mov cx, 12[bp] ; count
3500: cmp cx, #0x0000
3501: je memcpyb_end
3502: mov ax, 4[bp] ; dsegment
3503: mov es, ax
3504: mov ax, 6[bp] ; doffset
3505: mov di, ax
3506: mov ax, 8[bp] ; ssegment
3507: mov ds, ax
3508: mov ax, 10[bp] ; soffset
3509: mov si, ax
3510: cld
3511: rep
3512: movsb
3513:
3514: memcpyb_end:
3515: pop si
3516: pop ds
3517: pop di
3518: pop es
3519: pop cx
3520: pop ax
3521:
3522: pop bp
3523: ASM_END
3524: }
3525:
3526: // --------------------------------------------------------------------------------------------
3527: static void memcpyw(dseg,doffset,sseg,soffset,count)
3528: Bit16u dseg;
3529: Bit16u doffset;
3530: Bit16u sseg;
3531: Bit16u soffset;
3532: Bit16u count;
3533: {
3534: ASM_START
3535: push bp
3536: mov bp, sp
3537:
3538: push ax
3539: push cx
3540: push es
3541: push di
3542: push ds
3543: push si
3544:
3545: mov cx, 12[bp] ; count
3546: cmp cx, #0x0000
3547: je memcpyw_end
3548: mov ax, 4[bp] ; dsegment
3549: mov es, ax
3550: mov ax, 6[bp] ; doffset
3551: mov di, ax
3552: mov ax, 8[bp] ; ssegment
3553: mov ds, ax
3554: mov ax, 10[bp] ; soffset
3555: mov si, ax
3556: cld
3557: rep
3558: movsw
3559:
3560: memcpyw_end:
3561: pop si
3562: pop ds
3563: pop di
3564: pop es
3565: pop cx
3566: pop ax
3567:
3568: pop bp
3569: ASM_END
3570: }
3571:
3572: /* =========================================================== */
3573: /*
3574: * These functions where ripped from Kevin's rombios.c
3575: */
3576: /* =========================================================== */
3577:
3578: // --------------------------------------------------------------------------------------------
3579: static Bit8u
3580: read_byte(seg, offset)
3581: Bit16u seg;
3582: Bit16u offset;
3583: {
3584: ASM_START
3585: push bp
3586: mov bp, sp
3587:
3588: push bx
3589: push ds
3590: mov ax, 4[bp] ; segment
3591: mov ds, ax
3592: mov bx, 6[bp] ; offset
3593: mov al, [bx]
3594: ;; al = return value (byte)
3595: pop ds
3596: pop bx
3597:
3598: pop bp
3599: ASM_END
3600: }
3601:
3602: // --------------------------------------------------------------------------------------------
3603: static Bit16u
3604: read_word(seg, offset)
3605: Bit16u seg;
3606: Bit16u offset;
3607: {
3608: ASM_START
3609: push bp
3610: mov bp, sp
3611:
3612: push bx
3613: push ds
3614: mov ax, 4[bp] ; segment
3615: mov ds, ax
3616: mov bx, 6[bp] ; offset
3617: mov ax, [bx]
3618: ;; ax = return value (word)
3619: pop ds
3620: pop bx
3621:
3622: pop bp
3623: ASM_END
3624: }
3625:
3626: // --------------------------------------------------------------------------------------------
3627: static void
3628: write_byte(seg, offset, data)
3629: Bit16u seg;
3630: Bit16u offset;
3631: Bit8u data;
3632: {
3633: ASM_START
3634: push bp
3635: mov bp, sp
3636:
3637: push ax
3638: push bx
3639: push ds
3640: mov ax, 4[bp] ; segment
3641: mov ds, ax
3642: mov bx, 6[bp] ; offset
3643: mov al, 8[bp] ; data byte
3644: mov [bx], al ; write data byte
3645: pop ds
3646: pop bx
3647: pop ax
3648:
3649: pop bp
3650: ASM_END
3651: }
3652:
3653: // --------------------------------------------------------------------------------------------
3654: static void
3655: write_word(seg, offset, data)
3656: Bit16u seg;
3657: Bit16u offset;
3658: Bit16u data;
3659: {
3660: ASM_START
3661: push bp
3662: mov bp, sp
3663:
3664: push ax
3665: push bx
3666: push ds
3667: mov ax, 4[bp] ; segment
3668: mov ds, ax
3669: mov bx, 6[bp] ; offset
3670: mov ax, 8[bp] ; data word
3671: mov [bx], ax ; write data word
3672: pop ds
3673: pop bx
3674: pop ax
3675:
3676: pop bp
3677: ASM_END
3678: }
3679:
3680: // --------------------------------------------------------------------------------------------
3681: Bit8u
3682: inb(port)
3683: Bit16u port;
3684: {
3685: ASM_START
3686: push bp
3687: mov bp, sp
3688:
3689: push dx
3690: mov dx, 4[bp]
3691: in al, dx
3692: pop dx
3693:
3694: pop bp
3695: ASM_END
3696: }
3697:
3698: Bit16u
3699: inw(port)
3700: Bit16u port;
3701: {
3702: ASM_START
3703: push bp
3704: mov bp, sp
3705:
3706: push dx
3707: mov dx, 4[bp]
3708: in ax, dx
3709: pop dx
3710:
3711: pop bp
3712: ASM_END
3713: }
3714:
3715: // --------------------------------------------------------------------------------------------
3716: void
3717: outb(port, val)
3718: Bit16u port;
3719: Bit8u val;
3720: {
3721: ASM_START
3722: push bp
3723: mov bp, sp
3724:
3725: push ax
3726: push dx
3727: mov dx, 4[bp]
3728: mov al, 6[bp]
3729: out dx, al
3730: pop dx
3731: pop ax
3732:
3733: pop bp
3734: ASM_END
3735: }
3736:
3737: // --------------------------------------------------------------------------------------------
3738: void
3739: outw(port, val)
3740: Bit16u port;
3741: Bit16u val;
3742: {
3743: ASM_START
3744: push bp
3745: mov bp, sp
3746:
3747: push ax
3748: push dx
3749: mov dx, 4[bp]
3750: mov ax, 6[bp]
3751: out dx, ax
3752: pop dx
3753: pop ax
3754:
3755: pop bp
3756: ASM_END
3757: }
3758:
3759: Bit16u get_SS()
3760: {
3761: ASM_START
3762: mov ax, ss
3763: ASM_END
3764: }
3765:
3766: #ifdef DEBUG
3767: void unimplemented()
3768: {
3769: printf("--> Unimplemented\n");
3770: }
3771:
3772: void unknown()
3773: {
3774: printf("--> Unknown int10\n");
3775: }
3776: #endif
3777:
3778: // --------------------------------------------------------------------------------------------
3779: #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG)
3780: void printf(s)
3781: Bit8u *s;
3782: {
3783: Bit8u c, format_char;
3784: Boolean in_format;
3785: unsigned format_width, i;
3786: Bit16u *arg_ptr;
3787: Bit16u arg_seg, arg, digit, nibble, shift_count;
3788:
3789: arg_ptr = &s;
3790: arg_seg = get_SS();
3791:
3792: in_format = 0;
3793: format_width = 0;
3794:
3795: while (c = read_byte(0xc000, s)) {
3796: if ( c == '%' ) {
3797: in_format = 1;
3798: format_width = 0;
3799: }
3800: else if (in_format) {
3801: if ( (c>='0') && (c<='9') ) {
3802: format_width = (format_width * 10) + (c - '0');
3803: }
3804: else if (c == 'x') {
3805: arg_ptr++; // increment to next arg
3806: arg = read_word(arg_seg, arg_ptr);
3807: if (format_width == 0)
3808: format_width = 4;
3809: i = 0;
3810: digit = format_width - 1;
3811: for (i=0; i<format_width; i++) {
3812: nibble = (arg >> (4 * digit)) & 0x000f;
3813: if (nibble <= 9)
3814: outb(0x0500, nibble + '0');
3815: else
3816: outb(0x0500, (nibble - 10) + 'A');
3817: digit--;
3818: }
3819: in_format = 0;
3820: }
3821: //else if (c == 'd') {
3822: // in_format = 0;
3823: // }
3824: }
3825: else {
3826: outb(0x0500, c);
3827: }
3828: s ++;
3829: }
3830: }
3831: #endif
3832:
3833: #ifdef VBE
3834: #include "vbe.c"
3835: #endif
3836:
3837: #ifdef CIRRUS
3838: #include "clext.c"
3839: #endif
3840:
3841: // --------------------------------------------------------------------------------------------
3842:
3843: ASM_START
3844: ;; DATA_SEG_DEFS_HERE
3845: ASM_END
3846:
3847: ASM_START
3848: .ascii "vgabios ends here"
3849: .byte 0x00
3850: vgabios_end:
3851: .byte 0xCB
3852: ;; BLOCK_STRINGS_BEGIN
3853: ASM_END
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.