2 * VGA hardware emulation
4 * Copyright 1998 Ove Kåven (with some help from Marcus Meissner)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
34 static IDirectDraw
*lpddraw
= NULL
;
35 static IDirectDrawSurface
*lpddsurf
;
36 static IDirectDrawPalette
*lpddpal
;
37 static DDSURFACEDESC sdesc
;
38 static LONG vga_refresh
;
39 static HANDLE poll_timer
;
42 static int vga_height
;
44 static BYTE vga_text_attr
;
45 static char *textbuf_old
= NULL
;
47 static BOOL vga_mode_initialized
= FALSE
;
49 static CRITICAL_SECTION vga_lock
= CRITICAL_SECTION_INIT("VGA");
51 typedef HRESULT (WINAPI
*DirectDrawCreateProc
)(LPGUID
,LPDIRECTDRAW
*,LPUNKNOWN
);
52 static DirectDrawCreateProc pDirectDrawCreate
;
54 static void CALLBACK
VGA_Poll( LPVOID arg
, DWORD low
, DWORD high
);
56 static HWND vga_hwnd
= (HWND
) NULL
;
59 * For simplicity, I'm creating a second palette.
60 * 16 color accesses will use these pointers and insert
61 * entries from the 64-color palette into the default
62 * palette. --Robert 'Admiral' Coeyman
65 static char vga_16_palette
[17]={
71 0x05, /* 5 - Magenta */
73 0x07, /* 7 - Light gray */
74 0x38, /* 8 - Dark gray */
75 0x39, /* 9 - Light blue */
76 0x3a, /* A - Light green */
77 0x3b, /* B - Light cyan */
78 0x3c, /* C - Light red */
79 0x3d, /* D - Light magenta */
80 0x3e, /* E - Yellow */
82 0x00 /* Border Color */
85 static PALETTEENTRY vga_def_palette
[256]={
87 {0x00, 0x00, 0x00}, /* 0 - Black */
88 {0x00, 0x00, 0x80}, /* 1 - Blue */
89 {0x00, 0x80, 0x00}, /* 2 - Green */
90 {0x00, 0x80, 0x80}, /* 3 - Cyan */
91 {0x80, 0x00, 0x00}, /* 4 - Red */
92 {0x80, 0x00, 0x80}, /* 5 - Magenta */
93 {0x80, 0x80, 0x00}, /* 6 - Brown */
94 {0xC0, 0xC0, 0xC0}, /* 7 - Light gray */
95 {0x80, 0x80, 0x80}, /* 8 - Dark gray */
96 {0x00, 0x00, 0xFF}, /* 9 - Light blue */
97 {0x00, 0xFF, 0x00}, /* A - Light green */
98 {0x00, 0xFF, 0xFF}, /* B - Light cyan */
99 {0xFF, 0x00, 0x00}, /* C - Light red */
100 {0xFF, 0x00, 0xFF}, /* D - Light magenta */
101 {0xFF, 0xFF, 0x00}, /* E - Yellow */
102 {0xFF, 0xFF, 0xFF}, /* F - White */
103 {0,0,0} /* FIXME: a series of continuous rainbow hues should follow */
107 * This palette is the dos default, converted from 18 bit color to 24.
108 * It contains only 64 entries of colors--all others are zeros.
109 * --Robert 'Admiral' Coeyman
111 static PALETTEENTRY vga_def64_palette
[256]={
113 {0x00, 0x00, 0x00}, /* 0x00 Black */
114 {0x00, 0x00, 0xaa}, /* 0x01 Blue */
115 {0x00, 0xaa, 0x00}, /* 0x02 Green */
116 {0x00, 0xaa, 0xaa}, /* 0x03 Cyan */
117 {0xaa, 0x00, 0x00}, /* 0x04 Red */
118 {0xaa, 0x00, 0xaa}, /* 0x05 Magenta */
119 {0xaa, 0xaa, 0x00}, /* 0x06 */
120 {0xaa, 0xaa, 0xaa}, /* 0x07 Light Gray */
121 {0x00, 0x00, 0x55}, /* 0x08 */
122 {0x00, 0x00, 0xff}, /* 0x09 */
123 {0x00, 0xaa, 0x55}, /* 0x0a */
124 {0x00, 0xaa, 0xff}, /* 0x0b */
125 {0xaa, 0x00, 0x55}, /* 0x0c */
126 {0xaa, 0x00, 0xff}, /* 0x0d */
127 {0xaa, 0xaa, 0x55}, /* 0x0e */
128 {0xaa, 0xaa, 0xff}, /* 0x0f */
129 {0x00, 0x55, 0x00}, /* 0x10 */
130 {0x00, 0x55, 0xaa}, /* 0x11 */
131 {0x00, 0xff, 0x00}, /* 0x12 */
132 {0x00, 0xff, 0xaa}, /* 0x13 */
133 {0xaa, 0x55, 0x00}, /* 0x14 Brown */
134 {0xaa, 0x55, 0xaa}, /* 0x15 */
135 {0xaa, 0xff, 0x00}, /* 0x16 */
136 {0xaa, 0xff, 0xaa}, /* 0x17 */
137 {0x00, 0x55, 0x55}, /* 0x18 */
138 {0x00, 0x55, 0xff}, /* 0x19 */
139 {0x00, 0xff, 0x55}, /* 0x1a */
140 {0x00, 0xff, 0xff}, /* 0x1b */
141 {0xaa, 0x55, 0x55}, /* 0x1c */
142 {0xaa, 0x55, 0xff}, /* 0x1d */
143 {0xaa, 0xff, 0x55}, /* 0x1e */
144 {0xaa, 0xff, 0xff}, /* 0x1f */
145 {0x55, 0x00, 0x00}, /* 0x20 */
146 {0x55, 0x00, 0xaa}, /* 0x21 */
147 {0x55, 0xaa, 0x00}, /* 0x22 */
148 {0x55, 0xaa, 0xaa}, /* 0x23 */
149 {0xff, 0x00, 0x00}, /* 0x24 */
150 {0xff, 0x00, 0xaa}, /* 0x25 */
151 {0xff, 0xaa, 0x00}, /* 0x26 */
152 {0xff, 0xaa, 0xaa}, /* 0x27 */
153 {0x55, 0x00, 0x55}, /* 0x28 */
154 {0x55, 0x00, 0xff}, /* 0x29 */
155 {0x55, 0xaa, 0x55}, /* 0x2a */
156 {0x55, 0xaa, 0xff}, /* 0x2b */
157 {0xff, 0x00, 0x55}, /* 0x2c */
158 {0xff, 0x00, 0xff}, /* 0x2d */
159 {0xff, 0xaa, 0x55}, /* 0x2e */
160 {0xff, 0xaa, 0xff}, /* 0x2f */
161 {0x55, 0x55, 0x00}, /* 0x30 */
162 {0x55, 0x55, 0xaa}, /* 0x31 */
163 {0x55, 0xff, 0x00}, /* 0x32 */
164 {0x55, 0xff, 0xaa}, /* 0x33 */
165 {0xff, 0x55, 0x00}, /* 0x34 */
166 {0xff, 0x55, 0xaa}, /* 0x35 */
167 {0xff, 0xff, 0x00}, /* 0x36 */
168 {0xff, 0xff, 0xaa}, /* 0x37 */
169 {0x55, 0x55, 0x55}, /* 0x38 Dark Gray */
170 {0x55, 0x55, 0xff}, /* 0x39 Light Blue */
171 {0x55, 0xff, 0x55}, /* 0x3a Light Green */
172 {0x55, 0xff, 0xff}, /* 0x3b Light Cyan */
173 {0xff, 0x55, 0x55}, /* 0x3c Light Red */
174 {0xff, 0x55, 0xff}, /* 0x3d Light Magenta */
175 {0xff, 0xff, 0x55}, /* 0x3e Yellow */
176 {0xff, 0xff, 0xff}, /* 0x3f White */
177 {0,0,0} /* The next 192 entries are all zeros */
180 static HANDLE VGA_timer
;
181 static HANDLE VGA_timer_thread
;
183 /* set the timer rate; called in the polling thread context */
184 static void CALLBACK
set_timer_rate( ULONG_PTR arg
)
188 when
.s
.LowPart
= when
.s
.HighPart
= 0;
189 SetWaitableTimer( VGA_timer
, &when
, arg
, VGA_Poll
, 0, FALSE
);
192 static DWORD CALLBACK
VGA_TimerThread( void *dummy
)
194 for (;;) WaitForMultipleObjectsEx( 0, NULL
, FALSE
, INFINITE
, TRUE
);
197 static void VGA_DeinstallTimer(void)
199 if (VGA_timer_thread
)
201 CancelWaitableTimer( VGA_timer
);
202 CloseHandle( VGA_timer
);
203 TerminateThread( VGA_timer_thread
, 0 );
204 CloseHandle( VGA_timer_thread
);
205 VGA_timer_thread
= 0;
209 static void VGA_InstallTimer(unsigned Rate
)
211 if (!VGA_timer_thread
)
213 VGA_timer
= CreateWaitableTimerA( NULL
, FALSE
, NULL
);
214 VGA_timer_thread
= CreateThread( NULL
, 0, VGA_TimerThread
, NULL
, 0, NULL
);
216 QueueUserAPC( set_timer_rate
, VGA_timer_thread
, (ULONG_PTR
)Rate
);
219 HANDLE
VGA_AlphaConsole(void)
221 /* this assumes that no Win32 redirection has taken place, but then again,
222 * only 16-bit apps are likely to use this part of Wine... */
223 return GetStdHandle(STD_OUTPUT_HANDLE
);
226 char*VGA_AlphaBuffer(void)
228 return DOSMEM_MapDosToLinear(0xb8000);
231 /*** GRAPHICS MODE ***/
234 unsigned Xres
, Yres
, Depth
;
238 static void WINAPI
VGA_DoExit(ULONG_PTR arg
)
240 VGA_DeinstallTimer();
241 IDirectDrawSurface_SetPalette(lpddsurf
,NULL
);
242 IDirectDrawSurface_Release(lpddsurf
);
244 IDirectDrawPalette_Release(lpddpal
);
246 IDirectDraw_Release(lpddraw
);
250 static void WINAPI
VGA_DoSetMode(ULONG_PTR arg
)
253 ModeSet
*par
= (ModeSet
*)arg
;
256 if (lpddraw
) VGA_DoExit(0);
258 if (!pDirectDrawCreate
)
260 HMODULE hmod
= LoadLibraryA( "ddraw.dll" );
261 if (hmod
) pDirectDrawCreate
= (DirectDrawCreateProc
)GetProcAddress( hmod
, "DirectDrawCreate" );
262 if (!pDirectDrawCreate
) {
263 ERR("Can't lookup DirectDrawCreate from ddraw.dll.\n");
267 res
= pDirectDrawCreate(NULL
,&lpddraw
,NULL
);
269 ERR("DirectDraw is not available (res = %lx)\n",res
);
273 vga_hwnd
= CreateWindowExA(0,"STATIC","WINEDOS VGA",WS_POPUP
|WS_VISIBLE
,0,0,par
->Xres
,par
->Yres
,0,0,0,NULL
);
275 ERR("Failed to create user window.\n");
276 IDirectDraw_Release(lpddraw
);
282 SetWindowPos(vga_hwnd
,0,0,0,par
->Xres
,par
->Yres
,SWP_NOMOVE
|SWP_NOZORDER
);
284 if ((res
=IDirectDraw_SetCooperativeLevel(lpddraw
,vga_hwnd
,DDSCL_FULLSCREEN
|DDSCL_EXCLUSIVE
))) {
285 ERR("Could not set cooperative level to exclusive (%lx)\n",res
);
288 if ((res
=IDirectDraw_SetDisplayMode(lpddraw
,par
->Xres
,par
->Yres
,par
->Depth
))) {
289 ERR("DirectDraw does not support requested display mode (%dx%dx%d), res = %lx!\n",par
->Xres
,par
->Yres
,par
->Depth
,res
);
290 IDirectDraw_Release(lpddraw
);
295 res
=IDirectDraw_CreatePalette(lpddraw
,DDPCAPS_8BIT
,NULL
,&lpddpal
,NULL
);
297 ERR("Could not create palette (res = %lx)\n",res
);
298 IDirectDraw_Release(lpddraw
);
302 if ((res
=IDirectDrawPalette_SetEntries(lpddpal
,0,0,256,vga_def_palette
))) {
303 ERR("Could not set default palette entries (res = %lx)\n", res
);
306 memset(&sdesc
,0,sizeof(sdesc
));
307 sdesc
.dwSize
=sizeof(sdesc
);
308 sdesc
.dwFlags
= DDSD_CAPS
;
309 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
310 if (IDirectDraw_CreateSurface(lpddraw
,&sdesc
,&lpddsurf
,NULL
)||(!lpddsurf
)) {
311 ERR("DirectDraw surface is not available\n");
312 IDirectDraw_Release(lpddraw
);
316 IDirectDrawSurface_SetPalette(lpddsurf
,lpddpal
);
318 /* poll every 20ms (50fps should provide adequate responsiveness) */
319 VGA_InstallTimer(20);
325 int VGA_SetMode(unsigned Xres
,unsigned Yres
,unsigned Depth
)
333 if(Xres
>= 640 || Yres
>= 480) {
341 par
.Depth
= (Depth
< 8) ? 8 : Depth
;
343 vga_mode_initialized
= TRUE
;
345 MZ_RunInThread(VGA_DoSetMode
, (ULONG_PTR
)&par
);
349 int VGA_GetMode(unsigned*Height
,unsigned*Width
,unsigned*Depth
)
351 if (!lpddraw
) return 1;
352 if (!lpddsurf
) return 1;
353 if (Height
) *Height
=sdesc
.dwHeight
;
354 if (Width
) *Width
=sdesc
.dwWidth
;
355 if (Depth
) *Depth
=sdesc
.ddpfPixelFormat
.u1
.dwRGBBitCount
;
361 if (lpddraw
) MZ_RunInThread(VGA_DoExit
, 0);
364 void VGA_SetPalette(PALETTEENTRY
*pal
,int start
,int len
)
366 if (!lpddraw
) return;
367 IDirectDrawPalette_SetEntries(lpddpal
,0,start
,len
,pal
);
370 /* set a single [char wide] color in 16 color mode. */
371 void VGA_SetColor16(int reg
,int color
)
375 if (!lpddraw
) return;
376 pal
= &vga_def64_palette
[color
];
377 IDirectDrawPalette_SetEntries(lpddpal
,0,reg
,1,pal
);
378 vga_16_palette
[reg
]=(char)color
;
381 /* Get a single [char wide] color in 16 color mode. */
382 char VGA_GetColor16(int reg
)
385 if (!lpddraw
) return 0;
386 return (char)vga_16_palette
[reg
];
389 /* set all 17 [char wide] colors at once in 16 color mode. */
390 void VGA_Set16Palette(char *Table
)
395 if (!lpddraw
) return; /* return if we're in text only mode */
396 bcopy((void *)&vga_16_palette
,(void *)Table
,17);
397 /* copy the entries into the table */
398 for (c
=0; c
<17; c
++) { /* 17 entries */
399 pal
= &vga_def64_palette
[(int)vga_16_palette
[c
]]; /* get color */
400 IDirectDrawPalette_SetEntries(lpddpal
,0,c
,1,pal
); /* set entry */
401 TRACE("Palette register %d set to %d\n",c
,(int)vga_16_palette
[c
]);
402 } /* end of the counting loop */
405 /* Get all 17 [ char wide ] colors at once in 16 color mode. */
406 void VGA_Get16Palette(char *Table
)
409 if (!lpddraw
) return; /* return if we're in text only mode */
410 bcopy((void *)Table
,(void *)&vga_16_palette
,17);
411 /* copy the entries into the table */
414 void VGA_SetQuadPalette(RGBQUAD
*color
,int start
,int len
)
416 PALETTEENTRY pal
[256];
419 if (!lpddraw
) return;
420 for (c
=0; c
<len
; c
++) {
421 pal
[c
].peRed
=color
[c
].rgbRed
;
422 pal
[c
].peGreen
=color
[c
].rgbGreen
;
423 pal
[c
].peBlue
=color
[c
].rgbBlue
;
426 IDirectDrawPalette_SetEntries(lpddpal
,0,start
,len
,pal
);
429 LPSTR
VGA_Lock(unsigned*Pitch
,unsigned*Height
,unsigned*Width
,unsigned*Depth
)
431 if (!lpddraw
) return NULL
;
432 if (!lpddsurf
) return NULL
;
433 if (IDirectDrawSurface_Lock(lpddsurf
,NULL
,&sdesc
,0,0)) {
434 ERR("could not lock surface!\n");
437 if (Pitch
) *Pitch
=sdesc
.u1
.lPitch
;
438 if (Height
) *Height
=sdesc
.dwHeight
;
439 if (Width
) *Width
=sdesc
.dwWidth
;
440 if (Depth
) *Depth
=sdesc
.ddpfPixelFormat
.u1
.dwRGBBitCount
;
441 return sdesc
.lpSurface
;
444 void VGA_Unlock(void)
446 IDirectDrawSurface_Unlock(lpddsurf
,sdesc
.lpSurface
);
451 /* prepare the text mode video memory copy that is used to only
452 * update the video memory line that did get updated. */
453 void VGA_PrepareVideoMemCopy(unsigned Xres
, unsigned Yres
)
458 textbuf_old
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, textbuf_old
, Xres
* Yres
* 2); /* char + attr */
460 p
= VGA_AlphaBuffer();
463 /* make sure the video mem copy contains the exact opposite of our
464 * actual text mode memory area to make sure the screen
465 * does get updated fully initially */
466 for (i
=0; i
< Xres
*Yres
*2; i
++)
467 *p2
++ ^= *p
++; /* XOR it */
470 int VGA_SetAlphaMode(unsigned Xres
,unsigned Yres
)
474 if (lpddraw
) VGA_Exit();
476 /* FIXME: Where to initialize text attributes? */
477 VGA_SetTextAttribute(0xf);
479 VGA_PrepareVideoMemCopy(Xres
, Yres
);
481 /* poll every 30ms (33fps should provide adequate responsiveness) */
482 VGA_InstallTimer(30);
486 SetConsoleScreenBufferSize(VGA_AlphaConsole(),siz
);
490 void VGA_GetAlphaMode(unsigned*Xres
,unsigned*Yres
)
492 CONSOLE_SCREEN_BUFFER_INFO info
;
493 GetConsoleScreenBufferInfo(VGA_AlphaConsole(),&info
);
494 if (Xres
) *Xres
=info
.dwSize
.X
;
495 if (Yres
) *Yres
=info
.dwSize
.Y
;
498 void VGA_SetCursorShape(unsigned char start_options
, unsigned char end
)
500 CONSOLE_CURSOR_INFO cci
;
502 /* standard cursor settings:
503 * 0x0607 == CGA, 0x0b0c == monochrome, 0x0d0e == EGA/VGA */
505 /* calculate percentage from bottom - assuming VGA (bottom 0x0e) */
506 cci
.dwSize
= ((end
& 0x1f) - (start_options
& 0x1f))/0x0e * 100;
507 if (!cci
.dwSize
) cci
.dwSize
++; /* NULL cursor would make SCCI() fail ! */
508 cci
.bVisible
= ((start_options
& 0x60) != 0x20); /* invisible ? */
510 SetConsoleCursorInfo(VGA_AlphaConsole(),&cci
);
513 void VGA_SetCursorPos(unsigned X
,unsigned Y
)
517 if (!poll_timer
) VGA_SetAlphaMode(80, 25);
520 SetConsoleCursorPosition(VGA_AlphaConsole(),pos
);
523 void VGA_GetCursorPos(unsigned*X
,unsigned*Y
)
525 CONSOLE_SCREEN_BUFFER_INFO info
;
526 GetConsoleScreenBufferInfo(VGA_AlphaConsole(),&info
);
527 if (X
) *X
=info
.dwCursorPosition
.X
;
528 if (Y
) *Y
=info
.dwCursorPosition
.Y
;
531 void VGA_WriteChars(unsigned X
,unsigned Y
,unsigned ch
,int attr
,int count
)
539 EnterCriticalSection(&vga_lock
);
541 info
.Char
.AsciiChar
= ch
;
542 info
.Attributes
= (WORD
)attr
;
550 VGA_GetAlphaMode(&XR
, &YR
);
551 dat
= VGA_AlphaBuffer() + ((XR
*Y
+ X
) * 2);
553 dest
.Left
= X
+ count
;
554 dest
.Right
= X
+ count
;
560 info
.Attributes
= *dat
;
563 WriteConsoleOutputA(VGA_AlphaConsole(), &info
, siz
, off
, &dest
);
566 LeaveCriticalSection(&vga_lock
);
569 static void VGA_PutCharAt(BYTE ascii
, unsigned x
, unsigned y
)
571 unsigned width
, height
;
574 VGA_GetAlphaMode(&width
, &height
);
575 dat
= VGA_AlphaBuffer() + ((width
*y
+ x
) * 2);
577 dat
[1] = vga_text_attr
;
580 void VGA_PutChar(BYTE ascii
)
582 unsigned width
, height
, x
, y
, nx
, ny
;
584 EnterCriticalSection(&vga_lock
);
586 VGA_GetAlphaMode(&width
, &height
);
587 VGA_GetCursorPos(&x
, &y
);
591 VGA_PutCharAt(' ', x
, y
);
596 x
+= ((x
+ 8) & ~7) - x
;
612 VGA_PutCharAt(ascii
, x
, y
);
617 * FIXME: add line wrapping and scrolling
620 WriteFile(VGA_AlphaConsole(), &ascii
, 1, NULL
, NULL
);
623 * The following is just a sanity check.
625 VGA_GetCursorPos(&nx
, &ny
);
626 if(nx
!= x
|| ny
!= y
)
627 WARN("VGA emulator and text console have become unsynchronized.\n");
629 LeaveCriticalSection(&vga_lock
);
632 void VGA_SetTextAttribute(BYTE attr
)
634 vga_text_attr
= attr
;
635 SetConsoleTextAttribute(VGA_AlphaConsole(), attr
);
638 void VGA_ClearText(unsigned row1
, unsigned col1
,
639 unsigned row2
, unsigned col2
,
642 unsigned width
, height
, x
, y
;
644 char *dat
= VGA_AlphaBuffer();
645 HANDLE con
= VGA_AlphaConsole();
646 VGA_GetAlphaMode(&width
, &height
);
648 EnterCriticalSection(&vga_lock
);
650 for(y
=row1
; y
<=row2
; y
++) {
653 FillConsoleOutputCharacterA(con
, ' ', col2
-col1
+1, off
, NULL
);
654 FillConsoleOutputAttribute(con
, attr
, col2
-col1
+1, off
, NULL
);
656 for(x
=col1
; x
<=col2
; x
++) {
657 char *ptr
= dat
+ ((width
*y
+ x
) * 2);
663 LeaveCriticalSection(&vga_lock
);
666 void VGA_ScrollUpText(unsigned row1
, unsigned col1
,
667 unsigned row2
, unsigned col2
,
668 unsigned lines
, BYTE attr
)
670 FIXME("not implemented\n");
673 void VGA_ScrollDownText(unsigned row1
, unsigned col1
,
674 unsigned row2
, unsigned col2
,
675 unsigned lines
, BYTE attr
)
677 FIXME("not implemented\n");
680 void VGA_GetCharacterAtCursor(BYTE
*ascii
, BYTE
*attr
)
682 unsigned width
, height
, x
, y
;
685 VGA_GetAlphaMode(&width
, &height
);
686 VGA_GetCursorPos(&x
, &y
);
687 dat
= VGA_AlphaBuffer() + ((width
*y
+ x
) * 2);
696 /* FIXME: optimize by doing this only if the data has actually changed
697 * (in a way similar to DIBSection, perhaps) */
698 static void VGA_Poll_Graphics(void)
700 unsigned int Pitch
, Height
, Width
, X
, Y
;
702 char *dat
= DOSMEM_MapDosToLinear(0xa0000);
704 surf
= VGA_Lock(&Pitch
,&Height
,&Width
,NULL
);
707 if(vga_width
== 320 && vga_depth
<= 4)
708 for (Y
=0; Y
<vga_height
; Y
++,surf
+=Pitch
*2,dat
+=vga_width
/8) {
709 for(X
=0; X
<vga_width
; X
+=8) {
713 int b0
= (dat
[offset
] >> Z
) & 0x1;
715 surf
[(X
+index
)*2] = b0
;
716 surf
[(X
+index
)*2+1] = b0
;
717 surf
[(X
+index
)*2+Pitch
] = b0
;
718 surf
[(X
+index
)*2+Pitch
+1] = b0
;
723 if(vga_width
== 320 && vga_depth
== 8)
724 for (Y
=0; Y
<vga_height
; Y
++,surf
+=Pitch
*2,dat
+=vga_width
) {
725 for(X
=0; X
<vga_width
; X
++) {
729 surf
[X
*2+Pitch
] = b0
;
730 surf
[X
*2+Pitch
+1] = b0
;
735 for (Y
=0; Y
<vga_height
; Y
++,surf
+=Pitch
,dat
+=vga_width
/8) {
736 for(X
=0; X
<vga_width
; X
+=8) {
740 int b0
= (dat
[offset
] >> Z
) & 0x1;
750 static void VGA_Poll_Text(void)
752 char *dat
, *old
, *p_line
;
753 unsigned int Height
,Width
,Y
,X
;
754 CHAR_INFO ch
[256]; /* that should suffice for the largest text width */
757 HANDLE con
= VGA_AlphaConsole();
758 BOOL linechanged
= FALSE
; /* video memory area differs from stored copy ? */
760 VGA_GetAlphaMode(&Width
,&Height
);
761 dat
= VGA_AlphaBuffer();
762 old
= textbuf_old
; /* pointer to stored video mem copy */
763 siz
.X
= Width
; siz
.Y
= 1;
764 off
.X
= 0; off
.Y
= 0;
765 /* copy from virtual VGA frame buffer to console */
766 for (Y
=0; Y
<Height
; Y
++) {
767 linechanged
= memcmp(dat
, old
, Width
*2);
770 /*TRACE("line %d changed\n", Y);*/
772 for (X
=0; X
<Width
; X
++) {
773 ch
[X
].Char
.AsciiChar
= *p_line
++;
774 /* WriteConsoleOutputA doesn't like "dead" chars */
775 if (ch
[X
].Char
.AsciiChar
== '\0')
776 ch
[X
].Char
.AsciiChar
= ' ';
777 ch
[X
].Attributes
= *p_line
++;
779 dest
.Top
=Y
; dest
.Bottom
=Y
;
780 dest
.Left
=0; dest
.Right
=Width
+1;
781 WriteConsoleOutputA(con
, ch
, siz
, off
, &dest
);
782 memcpy(old
, dat
, Width
*2);
784 /* advance to next text line */
790 static void CALLBACK
VGA_Poll( LPVOID arg
, DWORD low
, DWORD high
)
792 if(!TryEnterCriticalSection(&vga_lock
))
802 LeaveCriticalSection(&vga_lock
);
805 static BYTE palreg
,palcnt
;
806 static PALETTEENTRY paldat
;
808 void VGA_ioport_out( WORD port
, BYTE val
)
812 palreg
=val
; palcnt
=0; break;
814 ((BYTE
*)&paldat
)[palcnt
++]=val
<< 2;
816 VGA_SetPalette(&paldat
,palreg
++,1);
821 FIXME("Unsupported VGA register: 0x%04x (value 0x%02x)\n", port
, val
);
825 BYTE
VGA_ioport_in( WORD port
)
831 /* since we don't (yet?) serve DOS VM requests while VGA_Poll is running,
832 we need to fake the occurrence of the vertical refresh */
833 ret
=vga_refresh
?0x00:0x0b; /* toggle video RAM and lightpen and VGA refresh bits ! */
834 if (vga_mode_initialized
)
837 /* Also fake the occurence of the vertical refresh when no graphic
839 vga_refresh
=!vga_refresh
;
843 FIXME("Unsupported VGA register: 0x%04x\n", port
);
851 VGA_DeinstallTimer();