~ubuntu-branches/ubuntu/hardy/kvm/hardy-backports

« back to all changes in this revision

Viewing changes to vgabios/vgabios.c

  • Committer: Bazaar Package Importer
  • Author(s): Soren Hansen
  • Date: 2008-01-03 10:39:25 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20080103103925-8480u7sq2646hvbh
Tags: 1:59+dfsg-0ubuntu1
* New upstream release
* Build with alsa support (cherry pick from 57+dfsg-2)

Show diffs side-by-side

added added

removed removed

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