Skip to content

Commit 874ca31

Browse files
authored
Merge pull request #91 from cracyc/dispdibvga
add support for int and ioport hooks and use in dispdib to get softwa…
2 parents f69fa00 + 68454b7 commit 874ca31

File tree

5 files changed

+214
-15
lines changed

5 files changed

+214
-15
lines changed

dispdib/dispdib.c

Lines changed: 176 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
#include <stdarg.h>
2222
#include <string.h>
23-
#include <stdlib.h>
2423
#include "windef.h"
2524
#include "winbase.h"
2625
#include "wingdi.h"
@@ -29,17 +28,26 @@
2928
#include "wine/wingdi16.h"
3029
#include "windows/dispdib.h"
3130
#include "wine/debug.h"
31+
#include "../krnl386/dosexe.h"
3232

3333
WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
3434

35-
static HTASK owner = 0;
35+
#define width 320
36+
37+
static HTASK16 owner = 0;
3638
static HDC dddc;
3739
static int height;
3840
static HWND ddhwnd;
41+
static INTPROC oldproc;
42+
static OUTPROC oldout[0x20];
43+
static INPROC oldin[0x20];
44+
static HANDLE running = 0;
45+
static BOOL vsync;
46+
static LPVOID vram;
3947

40-
LRESULT CALLBACK ddwndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
48+
static LRESULT CALLBACK ddwndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
4149
{
42-
HWND parhwnd = GetWindowLongA(hwnd, GWL_HWNDPARENT);
50+
HWND parhwnd = (HWND)GetWindowLongA(hwnd, GWL_HWNDPARENT);
4351
switch (uMsg)
4452
{
4553
case WM_KEYDOWN:
@@ -54,13 +62,150 @@ LRESULT CALLBACK ddwndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
5462
case WM_TIMER:
5563
case WM_SETFOCUS:
5664
case WM_KILLFOCUS:
57-
return CallWindowProcA(GetWindowLongA(parhwnd, GWL_WNDPROC), parhwnd, uMsg, wParam, lParam);
65+
case WM_CLOSE:
66+
return CallWindowProcA((WNDPROC)GetWindowLongA(parhwnd, GWL_WNDPROC), parhwnd, uMsg, wParam, lParam);
5867
}
5968
if (uMsg >= MM_JOY1MOVE)
60-
return CallWindowProcA(GetWindowLongA(parhwnd, GWL_WNDPROC), parhwnd, uMsg, wParam, lParam);
69+
return CallWindowProcA((WNDPROC)GetWindowLongA(parhwnd, GWL_WNDPROC), parhwnd, uMsg, wParam, lParam);
6170
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
6271
}
6372

73+
static void CALLBACK retrace_cb(LPVOID arg, DWORD low, DWORD high)
74+
{
75+
vsync = TRUE;
76+
if (WaitForSingleObject(running, 0))
77+
{
78+
SetEvent(running);
79+
ExitThread(0);
80+
}
81+
RECT ddrect;
82+
GetClientRect(ddhwnd, &ddrect);
83+
HDC dc = GetDC(ddhwnd);
84+
SetBitmapBits(GetCurrentObject(dddc, OBJ_BITMAP), width * height, vram);
85+
StretchBlt(dc, 0, 0, ddrect.right, ddrect.bottom, dddc, 0, 0, width, height, SRCCOPY);
86+
ReleaseDC(ddhwnd, dc);
87+
}
88+
89+
static DWORD CALLBACK retrace_th(LPVOID arg)
90+
{
91+
LARGE_INTEGER when;
92+
HANDLE timer;
93+
94+
if (!(timer = CreateWaitableTimerA( NULL, FALSE, NULL ))) return 0;
95+
96+
when.u.LowPart = when.u.HighPart = 0;
97+
SetWaitableTimer(timer, &when, 17, retrace_cb, arg, FALSE);
98+
for (;;) SleepEx(INFINITE, TRUE);
99+
}
100+
101+
static void start_retrace_timer()
102+
{
103+
if (running) return;
104+
if (height == 240) FIXME("240 px height doesn't work properly with direct fb access\n");
105+
running = CreateEventA(NULL, TRUE, TRUE, NULL);
106+
vram = MapSL((DWORD)GetProcAddress16(GetModuleHandle16("KERNEL"), (LPCSTR)174) << 16);
107+
CloseHandle(CreateThread(NULL, 0, retrace_th, NULL, 0, NULL));
108+
}
109+
110+
static void WINAPI ddInt10Handler(CONTEXT *context)
111+
{
112+
if (GetCurrentTask() != owner)
113+
{
114+
oldproc(context);
115+
return;
116+
}
117+
118+
switch (AH_reg(context))
119+
{
120+
case 0x00:
121+
start_retrace_timer();
122+
switch (AL_reg(context))
123+
{
124+
case 0x13:
125+
height = 200;
126+
break;
127+
default:
128+
FIXME("Vid mode %#x not supported\n", AL_reg(context));
129+
break;
130+
}
131+
break;
132+
default:
133+
FIXME("Int 10 func: %#x unimplemented\n", AH_reg(context));
134+
break;
135+
}
136+
}
137+
138+
static DWORD WINAPI ddVGAinHandler(int port, int size)
139+
{
140+
if (GetCurrentTask() != owner)
141+
return oldin[port - 0x3c0] ? oldin[port - 0x3c0](port, size) : 0;
142+
143+
DWORD ret = -1;
144+
145+
switch (port)
146+
{
147+
case 0x3da:
148+
{
149+
start_retrace_timer();
150+
ret = vsync ? 9 : 0;
151+
vsync = FALSE;
152+
break;
153+
}
154+
default:
155+
FIXME("vga port %#x unimplemented\n", port);
156+
break;
157+
}
158+
return ret;
159+
}
160+
161+
static void WINAPI ddVGAoutHandler(int port, int size, DWORD value)
162+
{
163+
if (GetCurrentTask() != owner)
164+
{
165+
if (oldout[port - 0x3c0])
166+
oldout[port - 0x3c0](port, size, value);
167+
return;
168+
}
169+
170+
if ((port & ~3) != 0x3c8) start_retrace_timer();
171+
172+
static BYTE dacidx;
173+
static BYTE dacclr = 0;
174+
175+
switch (port)
176+
{
177+
case 0x3c8:
178+
dacidx = value & 0xff;
179+
dacclr = 0;
180+
if (size == 1) break;
181+
value >>= 8;
182+
case 0x3c9:
183+
{
184+
RGBQUAD color;
185+
GetDIBColorTable(dddc, dacidx, 1, &color);
186+
switch (dacclr++)
187+
{
188+
case 0:
189+
color.rgbRed = (BYTE)value << 2;
190+
break;
191+
case 1:
192+
color.rgbGreen = (BYTE)value << 2;
193+
break;
194+
case 2:
195+
color.rgbBlue = (BYTE)value << 2;
196+
dacclr = 0;
197+
break;
198+
}
199+
SetDIBColorTable(dddc, dacidx, 1, &color);
200+
if (!dacclr) dacidx++;
201+
break;
202+
}
203+
default:
204+
FIXME("vga port %#x unimplemented\n", port);
205+
break;
206+
}
207+
}
208+
64209
/*********************************************************************
65210
* DisplayDib (DISPDIB.1)
66211
*
@@ -95,7 +240,7 @@ WORD WINAPI DisplayDib(
95240
WORD wFlags /* [in] */
96241
)
97242
{
98-
HTASK task = GetCurrentTask();
243+
HTASK16 task = GetCurrentTask();
99244
if ((wFlags & DISPLAYDIB_BEGIN) && !owner)
100245
{
101246
switch (wFlags & DISPLAYDIB_MODE)
@@ -114,34 +259,41 @@ WORD WINAPI DisplayDib(
114259
if (!GetClassInfoA(GetModuleHandleA(NULL), "DispDibClass", &wc))
115260
{
116261
WNDCLASSA ddwc = {0};
117-
ddwc.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
262+
ddwc.style = CS_HREDRAW | CS_VREDRAW;
118263
ddwc.lpfnWndProc = ddwndproc;
119264
ddwc.hInstance = GetModuleHandleA(NULL);
120265
ddwc.lpszClassName = "DispDibClass";
121266
if (!RegisterClassA(&ddwc))
122267
return DISPLAYDIB_NOTSUPPORTED;
123268
}
124269

270+
owner = task;
125271
dddc = CreateCompatibleDC(0);
126272
BITMAPINFO *bmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 256*4 + sizeof(BITMAPINFOHEADER));
127273
VOID *section;
128274
bmap->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
129-
bmap->bmiHeader.biWidth = 320;
275+
bmap->bmiHeader.biWidth = width;
130276
bmap->bmiHeader.biHeight = height;
131277
bmap->bmiHeader.biPlanes = 1;
132278
bmap->bmiHeader.biBitCount = 8;
133279
HBITMAP ddbmap = CreateDIBSection(dddc, bmap, DIB_RGB_COLORS, &section, NULL, 0);
134280
HeapFree(GetProcessHeap(), 0, bmap);
135281
SelectObject(dddc, ddbmap);
136282

137-
char title[32] = "DispDib";
283+
char title[32] = "\0";
138284
HWND parhwnd = GetActiveWindow();
139285
GetWindowTextA(parhwnd, title, 32);
286+
if (title[0] == '\0') GetModuleName16(GetCurrentTask(), title, 32);
140287
ddhwnd = CreateWindowExA(0, "DispDibClass", title, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT,
141288
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parhwnd, NULL, GetModuleHandleA(NULL), NULL);
142289
if (!ddhwnd)
290+
{
291+
owner = 0;
143292
return DISPLAYDIB_NOTSUPPORTED;
144-
owner = task;
293+
}
294+
oldproc = DOSVM_SetBuiltinVector(0x10, ddInt10Handler);
295+
for (int i = 0; i < 0x20; i++)
296+
DOSVM_setportcb(ddVGAoutHandler, ddVGAinHandler, i + 0x3c0, &oldout[i], &oldin[i]);
145297
return DISPLAYDIB_NOERROR;
146298
}
147299
else if ((owner != task) || !owner)
@@ -150,14 +302,24 @@ WORD WINAPI DisplayDib(
150302
{
151303
DestroyWindow(ddhwnd);
152304
DeleteDC(dddc);
305+
DOSVM_SetBuiltinVector(0x10, oldproc);
306+
for (int i = 0; i < 0x20; i++)
307+
DOSVM_setportcb(oldout[i], oldin[i], i + 0x3c0, &oldout[i], &oldin[i]);
308+
if (running)
309+
{
310+
ResetEvent(running);
311+
WaitForSingleObject(running, INFINITE);
312+
CloseHandle(running);
313+
running = 0;
314+
}
153315
owner = 0;
154316
return DISPLAYDIB_NOERROR;
155317
}
156318
if (!(wFlags & DISPLAYDIB_NOPALETTE))
157319
{
158320
if (!lpbi)
159321
return DISPLAYDIB_INVALIDDIB;
160-
SetDIBColorTable(dddc, 0, lpbi->bmiHeader.biClrUsed, &lpbi->bmiColors);
322+
SetDIBColorTable(dddc, 0, lpbi->bmiHeader.biClrUsed, (RGBQUAD *)&lpbi->bmiColors);
161323
}
162324
if(!(wFlags & /*DISPLAYDIB_NOIMAGE*/ 0x80))
163325
{
@@ -166,8 +328,8 @@ WORD WINAPI DisplayDib(
166328
RECT ddrect;
167329
GetClientRect(ddhwnd, &ddrect);
168330
HDC dc = GetDC(ddhwnd);
169-
SetDIBitsToDevice(dddc, 0, 0, 320, height, 0, 0, 0, 320, lpBits, lpbi, DIB_RGB_COLORS);
170-
StretchBlt(dc, 0, 0, ddrect.right, ddrect.bottom, dddc, 0, 0, 320, height, SRCCOPY);
331+
SetDIBitsToDevice(dddc, 0, 0, width, height, 0, 0, 0, height, lpBits, lpbi, DIB_RGB_COLORS);
332+
StretchBlt(dc, 0, 0, ddrect.right, ddrect.bottom, dddc, 0, 0, width, height, SRCCOPY);
171333
ReleaseDC(ddhwnd, dc);
172334
}
173335
return DISPLAYDIB_NOERROR;

krnl386/dosexe.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
#include "winnt.h" /* for PCONTEXT */
3333
#include "wincon.h" /* for MOUSE_EVENT_RECORD */
3434

35+
#ifndef DECLSPEC_HIDDEN
36+
#define DECLSPEC_HIDDEN
37+
#endif
38+
3539
#define MAX_DOS_DRIVES 26
3640

3741
struct _DOSEVENT;
@@ -68,6 +72,8 @@ typedef struct {
6872
typedef void (*DOSRELAY)(CONTEXT*,void*);
6973
typedef void (WINAPI *RMCBPROC)(CONTEXT*);
7074
typedef void (WINAPI *INTPROC)(CONTEXT*);
75+
typedef void (WINAPI *OUTPROC)(int port, int size, DWORD value);
76+
typedef DWORD (WINAPI *INPROC)(int port, int size);
7177

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

460467
/* relay.c */
461468
void DOSVM_RelayHandler( CONTEXT * ) DECLSPEC_HIDDEN;

krnl386/interrupts.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ static void WINAPI DOSVM_DefaultHandler(CONTEXT*);
4949

5050
static FARPROC16 DOSVM_Vectors16[256];
5151
static FARPROC48 DOSVM_Vectors48[256];
52-
static const INTPROC DOSVM_VectorsBuiltin[] =
52+
static INTPROC DOSVM_VectorsBuiltin[] =
5353
{
5454
/* 00 */ 0, 0, 0, 0,
5555
/* 04 */ 0, 0, 0, 0,
@@ -88,6 +88,16 @@ static const INTPROC DOSVM_VectorsBuiltin[] =
8888
#define DOSVM_STUB_PM16 5
8989
#define DOSVM_STUB_PM48 6
9090

91+
INTPROC DOSVM_SetBuiltinVector(BYTE intnum, INTPROC handler)
92+
{
93+
if (intnum < ARRAY_SIZE(DOSVM_VectorsBuiltin)) {
94+
INTPROC ret = DOSVM_VectorsBuiltin[intnum];
95+
DOSVM_VectorsBuiltin[intnum] = handler;
96+
return ret;
97+
}
98+
WARN("failed to set builtin int%x\n", intnum );
99+
return NULL;
100+
}
91101

92102
/**********************************************************************
93103
* DOSVM_GetRMVector

krnl386/ioports.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(int);
6666
# undef DIRECT_IO_ACCESS
6767
#endif
6868

69+
OUTPROC outcb[1024] = {0};
70+
INPROC incb[1024] = {0};
71+
6972
static struct {
7073
WORD countmax;
7174
WORD latch;
@@ -728,6 +731,16 @@ static BOOL IO_pp_outp(int port, DWORD* res)
728731

729732
#endif /* HAVE_PPDEV */
730733

734+
void DOSVM_setportcb(OUTPROC outproc, INPROC inproc, int port, OUTPROC *oldout, INPROC *oldin)
735+
{
736+
if (port > 1024)
737+
return;
738+
739+
*oldout = outcb[port];
740+
*oldin = incb[port];
741+
outcb[port] = outproc;
742+
incb[port] = inproc;
743+
}
731744

732745
/**********************************************************************
733746
* DOSVM_inport
@@ -741,6 +754,8 @@ DWORD DOSVM_inport( int port, int size )
741754

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

757+
if (incb[port]) return incb[port](port, size);
758+
744759
DOSMEM_InitDosMemory();
745760

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

954+
if (outcb[port]) return outcb[port](port, size, value);
955+
939956
DOSMEM_InitDosMemory();
940957

941958
#ifdef HAVE_PPDEV

krnl386/krnl386.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ EXPORTS
193193
krnl386_set_compat_path
194194

195195
GetModuleFileName16
196+
GetModuleName16
196197
_EnterWin16Lock
197198
_LeaveWin16Lock
198199
IsRealModeTask
@@ -214,3 +215,5 @@ EXPORTS
214215

215216
DOSVM_inport
216217
DOSVM_outport
218+
DOSVM_setportcb
219+
DOSVM_SetBuiltinVector

0 commit comments

Comments
 (0)