More DOS text mode fixes
Jukka Heinonen
jhei at iki.fi
Sat Apr 6 15:54:31 CST 2002
After this patch, DOS NetHack console output seems to work.
Some fixing would still be needed, since parts of the
screen are not erased properly.
Changelog:
Writes to stdout and VGA_WriteChars routine
now update both VGA buffers and Windows console.
Added routine for changing current console attributes.
Moved text mode handling from VGA_Poll into new routine and
changed locking primitive into critical section.
Index: int10.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/int10.c,v
retrieving revision 1.4
diff -u -r1.4 int10.c
--- int10.c 3 Apr 2002 02:34:45 -0000 1.4
+++ int10.c 6 Apr 2002 21:36:11 -0000
@@ -840,9 +840,7 @@
TRACE("char: 0x%02x\n", ascii);
- // FIXME: Update VGA text buffers here...
- WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), &ascii, 1, NULL, NULL);
-
+ VGA_PutChar(ascii);
VGA_GetCursorPos(&xpos, &ypos);
BIOS_SetCursorPos(data, 0, xpos, ypos);
}
Index: vga.h
===================================================================
RCS file: /home/wine/wine/dlls/winedos/vga.h,v
retrieving revision 1.4
diff -u -r1.4 vga.h
--- vga.h 23 Mar 2002 18:48:53 -0000 1.4
+++ vga.h 6 Apr 2002 21:36:25 -0000
@@ -40,6 +40,8 @@
void VGA_SetCursorPos(unsigned X,unsigned Y);
void VGA_GetCursorPos(unsigned*X,unsigned*Y);
void VGA_WriteChars(unsigned X,unsigned Y,unsigned ch,int attr,int count);
+void VGA_PutChar(BYTE ascii);
+void VGA_SetTextAttribute(BYTE attr);
/* control */
void VGA_ioport_out(WORD port, BYTE val);
Index: vga.c
===================================================================
RCS file: /home/wine/wine/dlls/winedos/vga.c,v
retrieving revision 1.6
diff -u -r1.6 vga.c
--- vga.c 23 Mar 2002 18:48:53 -0000 1.6
+++ vga.c 6 Apr 2002 21:36:40 -0000
@@ -35,12 +35,15 @@
static IDirectDrawSurface *lpddsurf;
static IDirectDrawPalette *lpddpal;
static DDSURFACEDESC sdesc;
-static LONG vga_polling,vga_refresh;
+static LONG vga_refresh;
static HANDLE poll_timer;
static int vga_width;
static int vga_height;
static int vga_depth;
+static BYTE vga_text_attr;
+
+static CRITICAL_SECTION vga_lock = CRITICAL_SECTION_INIT("VGA");
typedef HRESULT (WINAPI *DirectDrawCreateProc)(LPGUID,LPDIRECTDRAW *,LPUNKNOWN);
static DirectDrawCreateProc pDirectDrawCreate;
@@ -404,6 +407,9 @@
if (lpddraw) VGA_Exit();
+ /* FIXME: Where to initialize text attributes? */
+ VGA_SetTextAttribute(0xf);
+
/* the xterm is slow, so refresh only every 200ms (5fps) */
VGA_InstallTimer(200);
@@ -441,17 +447,109 @@
void VGA_WriteChars(unsigned X,unsigned Y,unsigned ch,int attr,int count)
{
+ CHAR_INFO info;
+ COORD siz, off;
+ SMALL_RECT dest;
unsigned XR, YR;
- char*dat;
+ char *dat;
+
+ EnterCriticalSection(&vga_lock);
+
+ info.Char.AsciiChar = ch;
+ info.Attributes = (WORD)attr;
+ siz.X = 1;
+ siz.Y = 1;
+ off.X = 0;
+ off.Y = 0;
+ dest.Top=Y;
+ dest.Bottom=Y;
VGA_GetAlphaMode(&XR, &YR);
dat = VGA_AlphaBuffer() + ((XR*Y + X) * 2);
- /* FIXME: also call WriteConsoleOutputA, for better responsiveness */
while (count--) {
+ dest.Left = X + count;
+ dest.Right = X + count;
+
*dat++ = ch;
- if (attr>=0) *dat = attr;
+ if (attr>=0)
+ *dat = attr;
+ else
+ info.Attributes = *dat;
dat++;
+
+ WriteConsoleOutputA(VGA_AlphaConsole(), &info, siz, off, &dest);
}
+
+ LeaveCriticalSection(&vga_lock);
+}
+
+static void VGA_PutCharAt(BYTE ascii, unsigned x, unsigned y)
+{
+ unsigned width, height;
+ char *dat;
+
+ VGA_GetAlphaMode(&width, &height);
+ dat = VGA_AlphaBuffer() + ((width*y + x) * 2);
+ dat[0] = ascii;
+ dat[1] = vga_text_attr;
+}
+
+void VGA_PutChar(BYTE ascii)
+{
+ unsigned width, height, x, y, nx, ny;
+
+ EnterCriticalSection(&vga_lock);
+
+ VGA_GetAlphaMode(&width, &height);
+ VGA_GetCursorPos(&x, &y);
+
+ switch(ascii) {
+ case '\b':
+ VGA_PutCharAt(' ', x, y);
+ x--;
+ break;
+
+ case '\t':
+ x += ((x + 8) & ~7) - x;
+ break;
+
+ case '\n':
+ y++;
+ x = 0;
+ break;
+
+ case '\a':
+ break;
+
+ case '\r':
+ x = 0;
+ break;
+
+ default:
+ VGA_PutCharAt(ascii, x, y);
+ x++;
+ }
+
+ /*
+ * FIXME: add line wrapping and scrolling
+ */
+
+ WriteFile(VGA_AlphaConsole(), &ascii, 1, NULL, NULL);
+
+ /*
+ * The following is just a sanity check.
+ */
+ VGA_GetCursorPos(&nx, &ny);
+ if(nx != x || ny != y)
+ WARN("VGA emulator and text console have become unsynchronized.\n");
+
+ LeaveCriticalSection(&vga_lock);
+}
+
+void VGA_SetTextAttribute(BYTE attr)
+{
+ vga_text_attr = attr;
+ SetConsoleTextAttribute(VGA_AlphaConsole(), attr);
}
/*** CONTROL ***/
@@ -508,45 +606,49 @@
VGA_Unlock();
}
-
-static void CALLBACK VGA_Poll( LPVOID arg, DWORD low, DWORD high )
+static void VGA_Poll_Text(void)
{
char *dat;
unsigned int Height,Width,Y,X;
+ CHAR_INFO ch[80];
+ COORD siz, off;
+ SMALL_RECT dest;
+ HANDLE con = VGA_AlphaConsole();
+
+ VGA_GetAlphaMode(&Width,&Height);
+ dat = VGA_AlphaBuffer();
+ siz.X = 80; siz.Y = 1;
+ off.X = 0; off.Y = 0;
+ /* copy from virtual VGA frame buffer to console */
+ for (Y=0; Y<Height; Y++) {
+ dest.Top=Y; dest.Bottom=Y;
+ for (X=0; X<Width; X++) {
+ ch[X].Char.AsciiChar = *dat++;
+ /* WriteConsoleOutputA doesn't like "dead" chars */
+ if (ch[X].Char.AsciiChar == '\0')
+ ch[X].Char.AsciiChar = ' ';
+ ch[X].Attributes = *dat++;
+ }
+ dest.Left=0; dest.Right=Width+1;
+ WriteConsoleOutputA(con, ch, siz, off, &dest);
+ }
+}
- if (!InterlockedExchangeAdd(&vga_polling, 1)) {
- /* FIXME: optimize by doing this only if the data has actually changed
- * (in a way similar to DIBSection, perhaps) */
- if (lpddraw) {
- VGA_Poll_Graphics();
- } else {
- /* text mode */
- CHAR_INFO ch[80];
- COORD siz, off;
- SMALL_RECT dest;
- HANDLE con = VGA_AlphaConsole();
-
- VGA_GetAlphaMode(&Width,&Height);
- dat = VGA_AlphaBuffer();
- siz.X = 80; siz.Y = 1;
- off.X = 0; off.Y = 0;
- /* copy from virtual VGA frame buffer to console */
- for (Y=0; Y<Height; Y++) {
- dest.Top=Y; dest.Bottom=Y;
- for (X=0; X<Width; X++) {
- ch[X].Char.AsciiChar = *dat++;
- /* WriteConsoleOutputA doesn't like "dead" chars */
- if (ch[X].Char.AsciiChar == '\0')
- ch[X].Char.AsciiChar = ' ';
- ch[X].Attributes = *dat++;
- }
- dest.Left=0; dest.Right=Width+1;
- WriteConsoleOutputA(con, ch, siz, off, &dest);
- }
- }
- vga_refresh=1;
+static void CALLBACK VGA_Poll( LPVOID arg, DWORD low, DWORD high )
+{
+ if(!TryEnterCriticalSection(&vga_lock))
+ return;
+
+ /* FIXME: optimize by doing this only if the data has actually changed
+ * (in a way similar to DIBSection, perhaps) */
+ if (lpddraw) {
+ VGA_Poll_Graphics();
+ } else {
+ VGA_Poll_Text();
}
- InterlockedDecrement(&vga_polling);
+
+ vga_refresh=1;
+ LeaveCriticalSection(&vga_lock);
}
static BYTE palreg,palcnt;
--
Jukka Heinonen <http://www.iki.fi/jhei/>
More information about the wine-patches
mailing list