Skip to content

Commit

Permalink
Merge pull request #91 from cracyc/dispdibvga
Browse files Browse the repository at this point in the history
add support for int and ioport hooks and use in dispdib to get softwa…
  • Loading branch information
otya128 authored Nov 4, 2018
2 parents f69fa00 + 68454b7 commit 874ca31
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 15 deletions.
190 changes: 176 additions & 14 deletions dispdib/dispdib.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
Expand All @@ -29,17 +28,26 @@
#include "wine/wingdi16.h"
#include "windows/dispdib.h"
#include "wine/debug.h"
#include "../krnl386/dosexe.h"

WINE_DEFAULT_DEBUG_CHANNEL(ddraw);

static HTASK owner = 0;
#define width 320

static HTASK16 owner = 0;
static HDC dddc;
static int height;
static HWND ddhwnd;
static INTPROC oldproc;
static OUTPROC oldout[0x20];
static INPROC oldin[0x20];
static HANDLE running = 0;
static BOOL vsync;
static LPVOID vram;

LRESULT CALLBACK ddwndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
static LRESULT CALLBACK ddwndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND parhwnd = GetWindowLongA(hwnd, GWL_HWNDPARENT);
HWND parhwnd = (HWND)GetWindowLongA(hwnd, GWL_HWNDPARENT);
switch (uMsg)
{
case WM_KEYDOWN:
Expand All @@ -54,13 +62,150 @@ LRESULT CALLBACK ddwndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_TIMER:
case WM_SETFOCUS:
case WM_KILLFOCUS:
return CallWindowProcA(GetWindowLongA(parhwnd, GWL_WNDPROC), parhwnd, uMsg, wParam, lParam);
case WM_CLOSE:
return CallWindowProcA((WNDPROC)GetWindowLongA(parhwnd, GWL_WNDPROC), parhwnd, uMsg, wParam, lParam);
}
if (uMsg >= MM_JOY1MOVE)
return CallWindowProcA(GetWindowLongA(parhwnd, GWL_WNDPROC), parhwnd, uMsg, wParam, lParam);
return CallWindowProcA((WNDPROC)GetWindowLongA(parhwnd, GWL_WNDPROC), parhwnd, uMsg, wParam, lParam);
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}

static void CALLBACK retrace_cb(LPVOID arg, DWORD low, DWORD high)
{
vsync = TRUE;
if (WaitForSingleObject(running, 0))
{
SetEvent(running);
ExitThread(0);
}
RECT ddrect;
GetClientRect(ddhwnd, &ddrect);
HDC dc = GetDC(ddhwnd);
SetBitmapBits(GetCurrentObject(dddc, OBJ_BITMAP), width * height, vram);
StretchBlt(dc, 0, 0, ddrect.right, ddrect.bottom, dddc, 0, 0, width, height, SRCCOPY);
ReleaseDC(ddhwnd, dc);
}

static DWORD CALLBACK retrace_th(LPVOID arg)
{
LARGE_INTEGER when;
HANDLE timer;

if (!(timer = CreateWaitableTimerA( NULL, FALSE, NULL ))) return 0;

when.u.LowPart = when.u.HighPart = 0;
SetWaitableTimer(timer, &when, 17, retrace_cb, arg, FALSE);
for (;;) SleepEx(INFINITE, TRUE);
}

static void start_retrace_timer()
{
if (running) return;
if (height == 240) FIXME("240 px height doesn't work properly with direct fb access\n");
running = CreateEventA(NULL, TRUE, TRUE, NULL);
vram = MapSL((DWORD)GetProcAddress16(GetModuleHandle16("KERNEL"), (LPCSTR)174) << 16);
CloseHandle(CreateThread(NULL, 0, retrace_th, NULL, 0, NULL));
}

static void WINAPI ddInt10Handler(CONTEXT *context)
{
if (GetCurrentTask() != owner)
{
oldproc(context);
return;
}

switch (AH_reg(context))
{
case 0x00:
start_retrace_timer();
switch (AL_reg(context))
{
case 0x13:
height = 200;
break;
default:
FIXME("Vid mode %#x not supported\n", AL_reg(context));
break;
}
break;
default:
FIXME("Int 10 func: %#x unimplemented\n", AH_reg(context));
break;
}
}

static DWORD WINAPI ddVGAinHandler(int port, int size)
{
if (GetCurrentTask() != owner)
return oldin[port - 0x3c0] ? oldin[port - 0x3c0](port, size) : 0;

DWORD ret = -1;

switch (port)
{
case 0x3da:
{
start_retrace_timer();
ret = vsync ? 9 : 0;
vsync = FALSE;
break;
}
default:
FIXME("vga port %#x unimplemented\n", port);
break;
}
return ret;
}

static void WINAPI ddVGAoutHandler(int port, int size, DWORD value)
{
if (GetCurrentTask() != owner)
{
if (oldout[port - 0x3c0])
oldout[port - 0x3c0](port, size, value);
return;
}

if ((port & ~3) != 0x3c8) start_retrace_timer();

static BYTE dacidx;
static BYTE dacclr = 0;

switch (port)
{
case 0x3c8:
dacidx = value & 0xff;
dacclr = 0;
if (size == 1) break;
value >>= 8;
case 0x3c9:
{
RGBQUAD color;
GetDIBColorTable(dddc, dacidx, 1, &color);
switch (dacclr++)
{
case 0:
color.rgbRed = (BYTE)value << 2;
break;
case 1:
color.rgbGreen = (BYTE)value << 2;
break;
case 2:
color.rgbBlue = (BYTE)value << 2;
dacclr = 0;
break;
}
SetDIBColorTable(dddc, dacidx, 1, &color);
if (!dacclr) dacidx++;
break;
}
default:
FIXME("vga port %#x unimplemented\n", port);
break;
}
}

/*********************************************************************
* DisplayDib (DISPDIB.1)
*
Expand Down Expand Up @@ -95,7 +240,7 @@ WORD WINAPI DisplayDib(
WORD wFlags /* [in] */
)
{
HTASK task = GetCurrentTask();
HTASK16 task = GetCurrentTask();
if ((wFlags & DISPLAYDIB_BEGIN) && !owner)
{
switch (wFlags & DISPLAYDIB_MODE)
Expand All @@ -114,34 +259,41 @@ WORD WINAPI DisplayDib(
if (!GetClassInfoA(GetModuleHandleA(NULL), "DispDibClass", &wc))
{
WNDCLASSA ddwc = {0};
ddwc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
ddwc.style = CS_HREDRAW | CS_VREDRAW;
ddwc.lpfnWndProc = ddwndproc;
ddwc.hInstance = GetModuleHandleA(NULL);
ddwc.lpszClassName = "DispDibClass";
if (!RegisterClassA(&ddwc))
return DISPLAYDIB_NOTSUPPORTED;
}

owner = task;
dddc = CreateCompatibleDC(0);
BITMAPINFO *bmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 256*4 + sizeof(BITMAPINFOHEADER));
VOID *section;
bmap->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmap->bmiHeader.biWidth = 320;
bmap->bmiHeader.biWidth = width;
bmap->bmiHeader.biHeight = height;
bmap->bmiHeader.biPlanes = 1;
bmap->bmiHeader.biBitCount = 8;
HBITMAP ddbmap = CreateDIBSection(dddc, bmap, DIB_RGB_COLORS, &section, NULL, 0);
HeapFree(GetProcessHeap(), 0, bmap);
SelectObject(dddc, ddbmap);

char title[32] = "DispDib";
char title[32] = "\0";
HWND parhwnd = GetActiveWindow();
GetWindowTextA(parhwnd, title, 32);
if (title[0] == '\0') GetModuleName16(GetCurrentTask(), title, 32);
ddhwnd = CreateWindowExA(0, "DispDibClass", title, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parhwnd, NULL, GetModuleHandleA(NULL), NULL);
if (!ddhwnd)
{
owner = 0;
return DISPLAYDIB_NOTSUPPORTED;
owner = task;
}
oldproc = DOSVM_SetBuiltinVector(0x10, ddInt10Handler);
for (int i = 0; i < 0x20; i++)
DOSVM_setportcb(ddVGAoutHandler, ddVGAinHandler, i + 0x3c0, &oldout[i], &oldin[i]);
return DISPLAYDIB_NOERROR;
}
else if ((owner != task) || !owner)
Expand All @@ -150,14 +302,24 @@ WORD WINAPI DisplayDib(
{
DestroyWindow(ddhwnd);
DeleteDC(dddc);
DOSVM_SetBuiltinVector(0x10, oldproc);
for (int i = 0; i < 0x20; i++)
DOSVM_setportcb(oldout[i], oldin[i], i + 0x3c0, &oldout[i], &oldin[i]);
if (running)
{
ResetEvent(running);
WaitForSingleObject(running, INFINITE);
CloseHandle(running);
running = 0;
}
owner = 0;
return DISPLAYDIB_NOERROR;
}
if (!(wFlags & DISPLAYDIB_NOPALETTE))
{
if (!lpbi)
return DISPLAYDIB_INVALIDDIB;
SetDIBColorTable(dddc, 0, lpbi->bmiHeader.biClrUsed, &lpbi->bmiColors);
SetDIBColorTable(dddc, 0, lpbi->bmiHeader.biClrUsed, (RGBQUAD *)&lpbi->bmiColors);
}
if(!(wFlags & /*DISPLAYDIB_NOIMAGE*/ 0x80))
{
Expand All @@ -166,8 +328,8 @@ WORD WINAPI DisplayDib(
RECT ddrect;
GetClientRect(ddhwnd, &ddrect);
HDC dc = GetDC(ddhwnd);
SetDIBitsToDevice(dddc, 0, 0, 320, height, 0, 0, 0, 320, lpBits, lpbi, DIB_RGB_COLORS);
StretchBlt(dc, 0, 0, ddrect.right, ddrect.bottom, dddc, 0, 0, 320, height, SRCCOPY);
SetDIBitsToDevice(dddc, 0, 0, width, height, 0, 0, 0, height, lpBits, lpbi, DIB_RGB_COLORS);
StretchBlt(dc, 0, 0, ddrect.right, ddrect.bottom, dddc, 0, 0, width, height, SRCCOPY);
ReleaseDC(ddhwnd, dc);
}
return DISPLAYDIB_NOERROR;
Expand Down
7 changes: 7 additions & 0 deletions krnl386/dosexe.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include "winnt.h" /* for PCONTEXT */
#include "wincon.h" /* for MOUSE_EVENT_RECORD */

#ifndef DECLSPEC_HIDDEN
#define DECLSPEC_HIDDEN
#endif

#define MAX_DOS_DRIVES 26

struct _DOSEVENT;
Expand Down Expand Up @@ -68,6 +72,8 @@ typedef struct {
typedef void (*DOSRELAY)(CONTEXT*,void*);
typedef void (WINAPI *RMCBPROC)(CONTEXT*);
typedef void (WINAPI *INTPROC)(CONTEXT*);
typedef void (WINAPI *OUTPROC)(int port, int size, DWORD value);
typedef DWORD (WINAPI *INPROC)(int port, int size);

#define DOS_PRIORITY_REALTIME 0 /* IRQ0 */
#define DOS_PRIORITY_KEYBOARD 1 /* IRQ1 */
Expand Down Expand Up @@ -456,6 +462,7 @@ extern void DOSVM_SetRMHandler( BYTE, FARPROC16 ) DECLSPEC_HIDDEN;
/* ioports.c */
extern DWORD DOSVM_inport( int port, int size ) DECLSPEC_HIDDEN;
extern void DOSVM_outport( int port, int size, DWORD value ) DECLSPEC_HIDDEN;
extern void DOSVM_setportcb(OUTPROC outproc, INPROC inproc, int port, OUTPROC *oldout, INPROC* oldin) DECLSPEC_HIDDEN;

/* relay.c */
void DOSVM_RelayHandler( CONTEXT * ) DECLSPEC_HIDDEN;
Expand Down
12 changes: 11 additions & 1 deletion krnl386/interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static void WINAPI DOSVM_DefaultHandler(CONTEXT*);

static FARPROC16 DOSVM_Vectors16[256];
static FARPROC48 DOSVM_Vectors48[256];
static const INTPROC DOSVM_VectorsBuiltin[] =
static INTPROC DOSVM_VectorsBuiltin[] =
{
/* 00 */ 0, 0, 0, 0,
/* 04 */ 0, 0, 0, 0,
Expand Down Expand Up @@ -88,6 +88,16 @@ static const INTPROC DOSVM_VectorsBuiltin[] =
#define DOSVM_STUB_PM16 5
#define DOSVM_STUB_PM48 6

INTPROC DOSVM_SetBuiltinVector(BYTE intnum, INTPROC handler)
{
if (intnum < ARRAY_SIZE(DOSVM_VectorsBuiltin)) {
INTPROC ret = DOSVM_VectorsBuiltin[intnum];
DOSVM_VectorsBuiltin[intnum] = handler;
return ret;
}
WARN("failed to set builtin int%x\n", intnum );
return NULL;
}

/**********************************************************************
* DOSVM_GetRMVector
Expand Down
17 changes: 17 additions & 0 deletions krnl386/ioports.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(int);
# undef DIRECT_IO_ACCESS
#endif

OUTPROC outcb[1024] = {0};
INPROC incb[1024] = {0};

static struct {
WORD countmax;
WORD latch;
Expand Down Expand Up @@ -728,6 +731,16 @@ static BOOL IO_pp_outp(int port, DWORD* res)

#endif /* HAVE_PPDEV */

void DOSVM_setportcb(OUTPROC outproc, INPROC inproc, int port, OUTPROC *oldout, INPROC *oldin)
{
if (port > 1024)
return;

*oldout = outcb[port];
*oldin = incb[port];
outcb[port] = outproc;
incb[port] = inproc;
}

/**********************************************************************
* DOSVM_inport
Expand All @@ -741,6 +754,8 @@ DWORD DOSVM_inport( int port, int size )

TRACE("%d-byte value from port 0x%04x\n", size, port );

if (incb[port]) return incb[port](port, size);

DOSMEM_InitDosMemory();

#ifdef HAVE_PPDEV
Expand Down Expand Up @@ -936,6 +951,8 @@ void DOSVM_outport( int port, int size, DWORD value )
{
TRACE("IO: 0x%x (%d-byte value) to port 0x%04x\n", value, size, port );

if (outcb[port]) return outcb[port](port, size, value);

DOSMEM_InitDosMemory();

#ifdef HAVE_PPDEV
Expand Down
3 changes: 3 additions & 0 deletions krnl386/krnl386.def
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ EXPORTS
krnl386_set_compat_path

GetModuleFileName16
GetModuleName16
_EnterWin16Lock
_LeaveWin16Lock
IsRealModeTask
Expand All @@ -214,3 +215,5 @@ EXPORTS

DOSVM_inport
DOSVM_outport
DOSVM_setportcb
DOSVM_SetBuiltinVector

0 comments on commit 874ca31

Please sign in to comment.