Moved most of the real-mode stuff to dlls/winedos.

This commit is contained in:
Alexandre Julliard 2001-12-04 19:54:44 +00:00
parent a5d882dc44
commit 8cd55d0eba
38 changed files with 1338 additions and 1200 deletions

View File

@ -76,9 +76,6 @@ static BOOL process_attach(void)
/* Force loading of some dlls */
if (LoadLibrary16( "system" ) < 32) return FALSE;
/* Read DOS config.sys */
if (!DOSCONF_ReadConfig()) return FALSE;
/* Create 16-bit task */
TASK_CreateMainTask();

View File

@ -4,7 +4,6 @@ owner kernel32
# Interrupt vectors 0-255 are ordinals 100-355
# The 'interrupt' keyword takes care of the flags pushed on the stack by the interrupt
116 interrupt INT_Int10Handler() INT_Int10Handler
117 interrupt INT_Int11Handler() INT_Int11Handler
118 interrupt INT_Int12Handler() INT_Int12Handler
119 interrupt INT_Int13Handler() INT_Int13Handler

View File

@ -28,7 +28,6 @@ C_SRCS = \
wcstring.c
EXTRA_OBJS = \
$(TOPOBJDIR)/console/console.o \
$(TOPOBJDIR)/files/files.o \
$(TOPOBJDIR)/if1632/if1632.o \
$(TOPOBJDIR)/loader/loader.o \
@ -42,7 +41,6 @@ EXTRA_OBJS = \
$(TOPOBJDIR)/win32/win32.o
SUBDIRS = \
$(TOPOBJDIR)/console \
$(TOPOBJDIR)/files \
$(TOPOBJDIR)/if1632 \
$(TOPOBJDIR)/loader \

View File

@ -1,11 +1,11 @@
name ntdll
type win32
debug_channels (aspi atom cdrom console ddraw debug delayhlp dll dosfs dosmem
file fixup global heap int int10 int16 int17 int19 int21 int31
io loaddll local module ntdll process profile reg relay resource
segment seh selector server snoop string system tape task thread
thunk tid timer toolhelp ver virtual vxd win32)
debug_channels (atom cdrom console debug delayhlp dll dosfs dosmem file fixup
global heap int int21 int31 io loaddll local module ntdll process
profile reg relay resource segment seh selector server snoop
string system tape task thread thunk tid timer toolhelp ver
virtual vxd win32)
#note that the Zw... functions are alternate names for the
#Nt... functions. (see www.sysinternals.com for details)

View File

@ -7,10 +7,33 @@ SOVERSION = 1.0
IMPORTS = user32 kernel32 ntdll
C_SRCS = \
dosaspi.c \
devices.c \
dosvm.c \
int09.c \
module.c
int10.c \
int16.c \
int17.c \
int19.c \
int20.c \
int21.c \
int29.c \
int31.c \
int33.c \
ioports.c \
module.c \
vga.c \
xms.c
EXTRA_OBJS = \
$(TOPOBJDIR)/console/console.o
SUBDIRS = \
$(TOPOBJDIR)/console
@MAKE_DLL_RULES@
$(EXTRA_OBJS): dummy
@cd `dirname $@` && $(MAKE) `basename $@`
### Dependencies:

View File

@ -10,7 +10,6 @@
#include "msdos.h"
#include "miscemu.h"
#include "dosexe.h"
#include "callback.h"
#include "debugtools.h"
#include "pshpack1.h"
@ -107,7 +106,6 @@ typedef struct
WORD attr;
RMCBPROC strategy;
RMCBPROC interrupt;
} WINEDEV;
static WINEDEV devs[] =
@ -136,7 +134,11 @@ typedef struct
#define DOS_DATASEG_OFF(xxx) FIELD_OFFSET(DOS_DATASEG, xxx)
DWORD DOS_LOLSeg;
struct _DOS_LISTOFLISTS * DOSMEM_LOL()
{
return (struct _DOS_LISTOFLISTS *)DOSMEM_MapRealToLinear
(MAKESEGPTR(HIWORD(DOS_LOLSeg),0));
}
/* the device implementations */
@ -265,7 +267,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx)
/* check for new keyboard input */
while (CurOfs == bios->FirstKbdCharPtr) {
/* no input available yet, so wait... */
Dosvm.Wait( -1, 0 );
DOSVM_Wait( -1, 0 );
}
/* read from keyboard queue (call int16?) */
data = ((WORD*)bios)[CurOfs];
@ -284,7 +286,7 @@ static void WINAPI con_interrupt(CONTEXT86*ctx)
/* check for new keyboard input */
while (CurOfs == bios->FirstKbdCharPtr) {
/* no input available yet, so wait... */
Dosvm.Wait( -1, 0 );
DOSVM_Wait( -1, 0 );
}
/* read from keyboard queue (call int16?) */
data = ((WORD*)bios)[CurOfs];

View File

@ -167,8 +167,12 @@ void WINAPI ASPI_DOS_func(CONTEXT86 *context)
}
/* returns the address of a real mode callback to ASPI_DOS_func() */
void ASPI_DOS_HandleInt(CONTEXT86 *context)
/**********************************************************************
* DOSVM_ASPIHandler (WINEDOS.@)
*
* returns the address of a real mode callback to ASPI_DOS_func()
*/
void WINAPI DOSVM_ASPIHandler( CONTEXT86 *context )
{
FARPROC16 *p = (FARPROC16 *)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx);
TRACE("DOS ASPI opening\n");

98
dlls/winedos/dosexe.h Normal file
View File

@ -0,0 +1,98 @@
/*
* DOS EXE loader
*
* Copyright 1998 Ove Kåven
*/
#ifndef __WINE_DOSEXE_H
#define __WINE_DOSEXE_H
#include "wine/windef16.h"
#include "winbase.h" /* for LPSTARTUPINFO32A */
#include "winnt.h" /* for PCONTEXT */
struct _DOSEVENT;
typedef void (*DOSRELAY)(CONTEXT86*,void*);
#define DOS_PRIORITY_REALTIME 0 /* IRQ0 */
#define DOS_PRIORITY_KEYBOARD 1 /* IRQ1 */
#define DOS_PRIORITY_VGA 2 /* IRQ9 */
#define DOS_PRIORITY_MOUSE 5 /* IRQ12 */
#define DOS_PRIORITY_SERIAL 10 /* IRQ4 */
extern WORD DOSVM_psp; /* psp of current DOS task */
extern WORD DOSVM_retval; /* return value of previous DOS task */
#if defined(linux) && defined(__i386__)
#define MZ_SUPPORTED
#endif /* linux-i386 */
#define V86_FLAG 0x00020000
extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile );
extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
extern void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
extern BOOL WINAPI MZ_Current( void );
extern void WINAPI MZ_AllocDPMITask( void );
extern void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg );
extern INT WINAPI DOSVM_Enter( CONTEXT86 *context );
extern void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject );
extern DWORD WINAPI DOSVM_Loop( LPVOID lpExtra );
extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data );
extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val );
extern void WINAPI DOSVM_SetTimer( UINT ticks );
extern UINT WINAPI DOSVM_GetTimer( void );
extern FARPROC16 DOSVM_GetRMHandler( BYTE intnum );
extern void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler );
extern void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context );
/* devices.c */
extern void DOSDEV_InstallDOSDevices(void);
extern DWORD DOSDEV_Console(void);
extern DWORD DOSDEV_FindCharDevice(char*name);
extern int DOSDEV_Peek(DWORD dev, BYTE*data);
extern int DOSDEV_Read(DWORD dev, DWORD buf, int buflen);
extern int DOSDEV_Write(DWORD dev, DWORD buf, int buflen, int verify);
extern int DOSDEV_IoctlRead(DWORD dev, DWORD buf, int buflen);
extern int DOSDEV_IoctlWrite(DWORD dev, DWORD buf, int buflen);
/* int09.c */
extern void WINAPI DOSVM_Int09Handler(CONTEXT86*);
extern void WINAPI DOSVM_Int09SendScan(BYTE scan,BYTE ascii);
extern BYTE WINAPI DOSVM_Int09ReadScan(BYTE*ascii);
/* int10.c */
extern void WINAPI DOSVM_Int10Handler(CONTEXT86*);
/* int16.c */
extern void WINAPI DOSVM_Int16Handler(CONTEXT86*);
extern int WINAPI DOSVM_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek);
extern int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan);
/* int17.c */
extern void WINAPI DOSVM_Int17Handler(CONTEXT86*);
/* int19.c */
extern void WINAPI DOSVM_Int19Handler(CONTEXT86*);
/* int20.c */
extern void WINAPI DOSVM_Int20Handler(CONTEXT86*);
/* int21.c */
extern void WINAPI DOSVM_Int21Handler(CONTEXT86*);
/* int29.c */
extern void WINAPI DOSVM_Int29Handler(CONTEXT86*);
/* int31.c */
extern void WINAPI DOSVM_Int31Handler(CONTEXT86*);
/* int33.c */
extern void WINAPI DOSVM_Int33Handler(CONTEXT86*);
extern void WINAPI DOSVM_Int33Message(UINT,WPARAM,LPARAM);
/* xms.c */
extern void WINAPI XMS_Handler(CONTEXT86*);
#endif /* __WINE_DOSEXE_H */

View File

@ -35,10 +35,13 @@
#include "stackframe.h"
#include "debugtools.h"
DECLARE_DEBUG_CHANNEL(int);
DEFAULT_DEBUG_CHANNEL(int);
DECLARE_DEBUG_CHANNEL(module);
DECLARE_DEBUG_CHANNEL(relay);
WORD DOSVM_psp = 0;
WORD DOSVM_retval = 0;
#ifdef MZ_SUPPORTED
#ifdef HAVE_SYS_VM86_H
@ -128,7 +131,7 @@ static void DOSVM_Dump( int fn, int sig, struct vm86plus_struct*VM86 )
static int DOSVM_SimulateInt( int vect, CONTEXT86 *context, BOOL inwine )
{
FARPROC16 handler=INT_GetRMHandler(vect);
FARPROC16 handler=DOSVM_GetRMHandler(vect);
/* check for our real-mode hooks */
if (vect==0x31) {
@ -141,16 +144,16 @@ static int DOSVM_SimulateInt( int vect, CONTEXT86 *context, BOOL inwine )
/* check if the call is from our fake BIOS interrupt stubs */
if ((context->SegCs==0xf000) && !inwine) {
if (vect != (context->Eip/4)) {
TRACE_(int)("something fishy going on here (interrupt stub is %02lx)\n", context->Eip/4);
TRACE("something fishy going on here (interrupt stub is %02lx)\n", context->Eip/4);
}
TRACE_(int)("builtin interrupt %02x has been branched to\n", vect);
INT_RealModeInterrupt(vect, context);
TRACE("builtin interrupt %02x has been branched to\n", vect);
DOSVM_RealModeInterrupt(vect, context);
}
/* check if the call goes to an unhooked interrupt */
else if (SELECTOROF(handler)==0xf000) {
/* if so, call it directly */
TRACE_(int)("builtin interrupt %02x has been invoked (through vector %02x)\n", OFFSETOF(handler)/4, vect);
INT_RealModeInterrupt(OFFSETOF(handler)/4, context);
TRACE("builtin interrupt %02x has been invoked (through vector %02x)\n", OFFSETOF(handler)/4, vect);
DOSVM_RealModeInterrupt(OFFSETOF(handler)/4, context);
}
/* the interrupt is hooked, simulate interrupt in DOS space */
else {
@ -186,19 +189,19 @@ static void DOSVM_SendQueuedEvent(CONTEXT86 *context)
/* it's an IRQ, move it to "current" list */
event->next = current_event;
current_event = event;
TRACE_(int)("dispatching IRQ %d\n",event->irq);
TRACE("dispatching IRQ %d\n",event->irq);
/* note that if DOSVM_SimulateInt calls an internal interrupt directly,
* current_event might be cleared (and event freed) in this very call! */
DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context,TRUE);
} else {
/* callback event */
TRACE_(int)("dispatching callback event\n");
TRACE("dispatching callback event\n");
(*event->relay)(context,event->data);
free(event);
}
}
if (!SHOULD_PEND(pending_event)) {
TRACE_(int)("clearing Pending flag\n");
TRACE("clearing Pending flag\n");
CLR_PEND(context);
}
}
@ -221,7 +224,7 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data
if (entered) {
event = malloc(sizeof(DOSEVENT));
if (!event) {
ERR_(int)("out of memory allocating event entry\n");
ERR("out of memory allocating event entry\n");
return;
}
event->irq = irq; event->priority = priority;
@ -240,11 +243,11 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data
/* get dosmod's attention to the new event, if necessary */
if (!sig_sent) {
TRACE_(int)("new event queued, signalling dosmod\n");
TRACE("new event queued, signalling dosmod\n");
kill(dosmod_pid,SIGUSR2);
sig_sent++;
} else {
TRACE_(int)("new event queued\n");
TRACE("new event queued\n");
}
} else {
/* DOS subsystem not running */
@ -256,7 +259,7 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data
memset(&context,0,sizeof(context));
(*relay)(&context,data);
} else {
ERR_(int)("IRQ without DOS task: should not happen");
ERR("IRQ without DOS task: should not happen");
}
}
}
@ -299,19 +302,19 @@ static int DOSVM_Process( int fn, int sig, struct vm86plus_struct*VM86 )
switch (VM86_TYPE(fn)) {
case VM86_SIGNAL:
TRACE_(int)("DOS module caught signal %d\n",sig);
TRACE("DOS module caught signal %d\n",sig);
if ((sig==SIGALRM) || (sig==SIGUSR2)) {
if (sig==SIGALRM) {
sig_sent++;
DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL);
}
if (pending_event) {
TRACE_(int)("setting Pending flag, interrupts are currently %s\n",
TRACE("setting Pending flag, interrupts are currently %s\n",
IF_ENABLED(&context) ? "enabled" : "disabled");
SET_PEND(&context);
DOSVM_SendQueuedEvents(&context);
} else {
TRACE_(int)("no events are pending, clearing Pending flag\n");
TRACE("no events are pending, clearing Pending flag\n");
CLR_PEND(&context);
}
sig_sent--;
@ -337,7 +340,7 @@ static int DOSVM_Process( int fn, int sig, struct vm86plus_struct*VM86 )
case VM86_STI:
IF_SET(&context);
/* case VM86_PICRETURN: */
TRACE_(int)("DOS task enabled interrupts %s events pending, sending events\n", IS_PEND(&context)?"with":"without");
TRACE("DOS task enabled interrupts %s events pending, sending events\n", IS_PEND(&context)?"with":"without");
DOSVM_SendQueuedEvents(&context);
break;
case VM86_TRAP:
@ -375,12 +378,12 @@ static void DOSVM_ProcessConsole(void)
/* check whether extended bit is set,
* and if so, queue the extension prefix */
if (msg.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY) {
INT_Int09SendScan(0xE0,0);
DOSVM_Int09SendScan(0xE0,0);
}
INT_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar);
DOSVM_Int09SendScan(scan,msg.Event.KeyEvent.uChar.AsciiChar);
break;
default:
FIXME_(int)("unhandled console event: %d\n", msg.EventType);
FIXME("unhandled console event: %d\n", msg.EventType);
}
}
}
@ -389,10 +392,10 @@ static void DOSVM_ProcessMessage(MSG *msg)
{
BYTE scan = 0;
TRACE_(int)("got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam);
TRACE("got message %04x, wparam=%08x, lparam=%08lx\n",msg->message,msg->wParam,msg->lParam);
if ((msg->message>=WM_MOUSEFIRST)&&
(msg->message<=WM_MOUSELAST)) {
INT_Int33Message(msg->message,msg->wParam,msg->lParam);
DOSVM_Int33Message(msg->message,msg->wParam,msg->lParam);
} else {
switch (msg->message) {
case WM_KEYUP:
@ -406,9 +409,9 @@ static void DOSVM_ProcessMessage(MSG *msg)
/* FIXME: some keys (function keys) have
* extended bit set even when they shouldn't,
* should check for them */
INT_Int09SendScan(0xE0,0);
DOSVM_Int09SendScan(0xE0,0);
}
INT_Int09SendScan(scan,0);
DOSVM_Int09SendScan(scan,0);
break;
}
}
@ -571,7 +574,7 @@ void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val)
if ((port==0x20) && (val==0x20)) {
if (current_event) {
/* EOI (End Of Interrupt) */
TRACE_(int)("received EOI for current IRQ, clearing\n");
TRACE("received EOI for current IRQ, clearing\n");
event = current_event;
current_event = event->next;
if (event->relay)
@ -582,15 +585,15 @@ void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val)
!sig_sent) {
/* another event is pending, which we should probably
* be able to process now, so tell dosmod about it */
TRACE_(int)("another event pending, signalling dosmod\n");
TRACE("another event pending, signalling dosmod\n");
kill(dosmod_pid,SIGUSR2);
sig_sent++;
}
} else {
WARN_(int)("EOI without active IRQ\n");
WARN("EOI without active IRQ\n");
}
} else {
FIXME_(int)("unrecognized PIC command %02x\n",val);
FIXME("unrecognized PIC command %02x\n",val);
}
}
@ -602,7 +605,7 @@ void WINAPI DOSVM_SetTimer( UINT ticks )
int stat=DOSMOD_SET_TIMER;
struct timeval tim;
if (MZ_Current()) {
if (write_pipe != -1) {
/* the PC clocks ticks at 1193180 Hz */
tim.tv_sec=0;
tim.tv_usec=MulDiv(ticks,1000000,1193180);
@ -629,7 +632,7 @@ UINT WINAPI DOSVM_GetTimer( void )
int stat=DOSMOD_GET_TIMER;
struct timeval tim;
if (MZ_Current()) {
if (write_pipe != -1) {
if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return 0;
@ -688,23 +691,82 @@ void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data
memset(&context,0,sizeof(context));
(*relay)(&context,data);
} else {
ERR_(int)("IRQ without DOS task: should not happen");
ERR("IRQ without DOS task: should not happen");
}
}
#endif
/**********************************************************************
* DOSVM_GetRMHandler
*
* Return the real mode interrupt vector for a given interrupt.
*/
FARPROC16 DOSVM_GetRMHandler( BYTE intnum )
{
return ((FARPROC16*)DOSMEM_SystemBase())[intnum];
}
/**********************************************************************
* DOSVM_SetRMHandler
*
* Set the real mode interrupt handler for a given interrupt.
*/
void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler )
{
TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n",
intnum, HIWORD(handler), LOWORD(handler) );
((FARPROC16*)DOSMEM_SystemBase())[intnum] = handler;
}
static const INTPROC real_mode_handlers[] =
{
/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 08 */ 0, DOSVM_Int09Handler, 0, 0, 0, 0, 0, 0,
/* 10 */ DOSVM_Int10Handler, INT_Int11Handler, INT_Int12Handler, INT_Int13Handler,
0, INT_Int15Handler, DOSVM_Int16Handler, DOSVM_Int17Handler,
/* 18 */ 0, 0, INT_Int1aHandler, 0, 0, 0, 0, 0,
/* 20 */ DOSVM_Int20Handler, DOSVM_Int21Handler, 0, 0, 0, INT_Int25Handler, 0, 0,
/* 28 */ 0, DOSVM_Int29Handler, INT_Int2aHandler, 0, 0, 0, 0, INT_Int2fHandler,
/* 30 */ 0, DOSVM_Int31Handler, 0, DOSVM_Int33Handler
};
/**********************************************************************
* DOSVM_RealModeInterrupt
*
* Handle real mode interrupts
*/
void DOSVM_RealModeInterrupt( BYTE intnum, CONTEXT86 *context )
{
if (intnum < sizeof(real_mode_handlers)/sizeof(INTPROC) && real_mode_handlers[intnum])
(*real_mode_handlers[intnum])(context);
else
{
FIXME("Unknown Interrupt in DOS mode: 0x%x\n", intnum);
FIXME(" eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx\n",
context->Eax, context->Ebx, context->Ecx, context->Edx);
FIXME(" esi=%08lx edi=%08lx ds=%04lx es=%04lx\n",
context->Esi, context->Edi, context->SegDs, context->SegEs );
}
}
/**********************************************************************
* DOSVM_Init
*/
BOOL WINAPI DOSVM_Init( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
TRACE_(module)("(0x%08x,%ld,%p)\n", hinstDLL, fdwReason, lpvReserved);
if (fdwReason == DLL_PROCESS_ATTACH) {
INT_SetWineHandler(9, INT_Int09Handler);
}
else if (fdwReason == DLL_PROCESS_DETACH)
if (fdwReason == DLL_PROCESS_ATTACH)
{
INT_SetWineHandler(9, NULL);
/* initialize the memory */
TRACE("Initializing DOS memory structures\n");
DOSMEM_Init( TRUE );
DOSDEV_InstallDOSDevices();
}
return TRUE;
}

View File

@ -11,7 +11,6 @@
#include "winuser.h"
#include "miscemu.h"
#include "debugtools.h"
#include "callback.h"
#include "dosexe.h"
DEFAULT_DEBUG_CHANNEL(int);
@ -25,13 +24,13 @@ static struct
/**********************************************************************
* INT_Int09Handler
* DOSVM_Int09Handler
*
* Handler for int 09h.
*/
void WINAPI INT_Int09Handler( CONTEXT86 *context )
void WINAPI DOSVM_Int09Handler( CONTEXT86 *context )
{
BYTE ascii, scan = INT_Int09ReadScan(&ascii);
BYTE ascii, scan = DOSVM_Int09ReadScan(&ascii);
BYTE ch[2];
int cnt, c2;
@ -49,21 +48,21 @@ void WINAPI INT_Int09Handler( CONTEXT86 *context )
}
if (cnt>0) {
for (c2=0; c2<cnt; c2++)
INT_Int16AddChar(ch[c2], scan);
DOSVM_Int16AddChar(ch[c2], scan);
} else
if (cnt==0) {
/* FIXME: need to handle things like shift-F-keys,
* 0xE0 extended keys, etc */
INT_Int16AddChar(0, scan);
DOSVM_Int16AddChar(0, scan);
}
}
Dosvm.OutPIC(0x20, 0x20); /* send EOI */
DOSVM_PIC_ioport_out( 0x20, 0x20 ); /* send EOI */
}
static void KbdRelay( CONTEXT86 *context, void *data )
{
if (kbdinfo.queuelen) {
/* cleanup operation, called from Dosvm.OutPIC:
/* cleanup operation, called from DOSVM_PIC_ioport_out:
* we'll remove current scancode from keyboard buffer here,
* rather than in ReadScan, because some DOS apps depend on
* the scancode being available for reading multiple times... */
@ -74,7 +73,7 @@ static void KbdRelay( CONTEXT86 *context, void *data )
}
}
void WINAPI INT_Int09SendScan( BYTE scan, BYTE ascii )
void WINAPI DOSVM_Int09SendScan( BYTE scan, BYTE ascii )
{
if (kbdinfo.queuelen == QUEUELEN) {
ERR("keyboard queue overflow\n");
@ -84,13 +83,13 @@ void WINAPI INT_Int09SendScan( BYTE scan, BYTE ascii )
kbdinfo.queue[kbdinfo.queuelen] = scan;
kbdinfo.ascii[kbdinfo.queuelen++] = ascii;
/* tell app to read it by triggering IRQ 1 (int 09) */
Dosvm.QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL);
DOSVM_QueueEvent(1,DOS_PRIORITY_KEYBOARD,KbdRelay,NULL);
}
/**********************************************************************
* KbdReadScan (WINEDOS.@)
*/
BYTE WINAPI INT_Int09ReadScan( BYTE*ascii )
BYTE WINAPI DOSVM_Int09ReadScan( BYTE*ascii )
{
if (ascii) *ascii = kbdinfo.ascii[0];
return kbdinfo.queue[0];

View File

@ -11,7 +11,7 @@
#include "debugtools.h"
#include "console.h"
DEFAULT_DEBUG_CHANNEL(int10);
DEFAULT_DEBUG_CHANNEL(int);
static void conv_text_mode_attributes(char attribute, int *fg, int *bg,
int *wattribute);
@ -37,7 +37,7 @@ static void BIOS_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
}
/**********************************************************************
* INT_Int10Handler (WPROCS.116)
* DOSVM_Int10Handler (WPROCS.116)
*
* Handler for int 10h (video).
*
@ -70,7 +70,7 @@ static void BIOS_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
* Added additional vga graphic support - 3/99
*/
void WINAPI INT_Int10Handler( CONTEXT86 *context )
void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
{
static int registered_colors = FALSE;
BIOSDATA *data = DOSMEM_BiosData();

View File

@ -9,7 +9,6 @@
#include <unistd.h>
#include "module.h"
#include "callback.h"
#include "dosexe.h"
#include "wincon.h"
#include "debugtools.h"
@ -18,10 +17,10 @@
#include "winuser.h"
#include "miscemu.h"
DEFAULT_DEBUG_CHANNEL(int16);
DEFAULT_DEBUG_CHANNEL(int);
/**********************************************************************
* INT_Int16Handler
* DOSVM_Int16Handler
*
* Handler for int 16h (keyboard)
*
@ -31,7 +30,7 @@ DEFAULT_DEBUG_CHANNEL(int16);
* not currently listed here.
*/
void WINAPI INT_Int16Handler( CONTEXT86 *context )
void WINAPI DOSVM_Int16Handler( CONTEXT86 *context )
{
switch AH_reg(context) {
@ -39,7 +38,7 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context )
/* Returns: AH = Scan code
AL = ASCII character */
TRACE("Get Keystroke\n");
INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
break;
case 0x01: /* Check for Keystroke */
@ -47,7 +46,7 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context )
/* AH = Scan code */
/* AL = ASCII character */
TRACE("Check for Keystroke\n");
if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
if (!DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
{
SET_ZFLAG(context);
}
@ -60,7 +59,6 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context )
case 0x02: /* Get Shift Flags */
AL_reg(context) = 0;
#if 0 /* FIXME: cannot call USER functions here */
if (GetAsyncKeyState(VK_RSHIFT))
AL_reg(context) |= 0x01;
if (GetAsyncKeyState(VK_LSHIFT))
@ -77,7 +75,6 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context )
AL_reg(context) |= 0x40;
if (GetAsyncKeyState(VK_INSERT))
AL_reg(context) |= 0x80;
#endif
TRACE("Get Shift Flags: returning 0x%02x\n", AL_reg(context));
break;
@ -99,7 +96,7 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context )
TRACE("Get Enhanced Keystroke - Partially supported\n");
/* Returns: AH = Scan code
AL = ASCII character */
INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), FALSE);
break;
@ -108,7 +105,7 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context )
/* AH = Scan code */
/* AL = ASCII character */
TRACE("Check for Enhanced Keystroke - Partially supported\n");
if (!INT_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
if (!DOSVM_Int16ReadChar(&AL_reg(context), &AH_reg(context), TRUE))
{
SET_ZFLAG(context);
}
@ -129,7 +126,7 @@ void WINAPI INT_Int16Handler( CONTEXT86 *context )
}
}
int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
int WINAPI DOSVM_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
{
BIOSDATA *data = DOSMEM_BiosData();
WORD CurOfs = data->NextKbdCharPtr;
@ -141,7 +138,7 @@ int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
} else {
while (CurOfs == data->FirstKbdCharPtr) {
/* no input available yet, so wait... */
Dosvm.Wait( -1, 0 );
DOSVM_Wait( -1, 0 );
}
}
/* read from keyboard queue */
@ -156,7 +153,7 @@ int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek)
return 1;
}
int WINAPI INT_Int16AddChar(BYTE ascii,BYTE scan)
int WINAPI DOSVM_Int16AddChar(BYTE ascii,BYTE scan)
{
BIOSDATA *data = DOSMEM_BiosData();
WORD CurOfs = data->FirstKbdCharPtr;

View File

@ -9,14 +9,14 @@
#include "msdos.h"
#include "winnt.h"
DEFAULT_DEBUG_CHANNEL(int17);
DEFAULT_DEBUG_CHANNEL(int);
/**********************************************************************
* INT_Int17Handler
* DOSVM_Int17Handler
*
* Handler for int 17h (printer - output character).
*/
void WINAPI INT_Int17Handler( CONTEXT86 *context )
void WINAPI DOSVM_Int17Handler( CONTEXT86 *context )
{
switch( AH_reg(context) )
{

View File

@ -6,15 +6,15 @@
#include "miscemu.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(int19);
DEFAULT_DEBUG_CHANNEL(int);
/**********************************************************************
* INT_Int19Handler
* DOSVM_Int19Handler
*
* Handler for int 19h (Reboot).
*/
void WINAPI INT_Int19Handler( CONTEXT86 *context )
void WINAPI DOSVM_Int19Handler( CONTEXT86 *context )
{
WARN("Attempted Reboot\n");
}

18
dlls/winedos/int20.c Normal file
View File

@ -0,0 +1,18 @@
/*
* DOS interrupt 20h handler (TERMINATE PROGRAM)
*/
#include <stdlib.h>
#include "winbase.h"
#include "dosexe.h"
#include "miscemu.h"
/**********************************************************************
* DOSVM_Int20Handler
*
* Handler for int 20h.
*/
void WINAPI DOSVM_Int20Handler( CONTEXT86 *context )
{
MZ_Exit( context, TRUE, 0 );
}

187
dlls/winedos/int21.c Normal file
View File

@ -0,0 +1,187 @@
/*
* DOS interrupt 21h handler
*/
#include "config.h"
#include "windef.h"
#include "winbase.h"
#include "ntddk.h"
#include "wine/winbase16.h"
#include "dosexe.h"
#include "miscemu.h"
#include "msdos.h"
#include "console.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(int21);
/***********************************************************************
* DOSVM_Int21Handler
*
* int 21h real-mode handler. Most calls are passed directly to DOS3Call.
*/
void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
{
RESET_CFLAG(context); /* Not sure if this is a good idea */
switch(AH_reg(context))
{
case 0x00: /* TERMINATE PROGRAM */
TRACE("TERMINATE PROGRAM\n");
MZ_Exit( context, FALSE, 0 );
break;
case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
AL_reg(context) = CONSOLE_GetCharacter();
/* FIXME: no echo */
break;
case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
TRACE("Write Character to Standard Output\n");
CONSOLE_Write(DL_reg(context), 0, 0, 0);
break;
case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
/* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */
if (DL_reg(context) == 0xff) {
static char scan = 0;
TRACE("Direct Console Input\n");
if (scan) {
/* return pending scancode */
AL_reg(context) = scan;
RESET_ZFLAG(context);
scan = 0;
} else {
char ascii;
if (DOSVM_Int16ReadChar(&ascii,&scan,TRUE)) {
DOSVM_Int16ReadChar(&ascii,&scan,FALSE);
/* return ASCII code */
AL_reg(context) = ascii;
RESET_ZFLAG(context);
/* return scan code on next call only if ascii==0 */
if (ascii) scan = 0;
} else {
/* nothing pending, clear everything */
AL_reg(context) = 0;
SET_ZFLAG(context);
scan = 0; /* just in case */
}
}
} else {
TRACE("Direct Console Output\n");
CONSOLE_Write(DL_reg(context), 0, 0, 0);
}
break;
case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
/* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
break;
case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
/* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
TRACE("CHARACTER INPUT WITHOUT ECHO\n");
DOSVM_Int16ReadChar(&AL_reg(context), NULL, FALSE);
break;
case 0x0b: /* GET STDIN STATUS */
{
char x1,x2;
if (CONSOLE_CheckForKeystroke(&x1,&x2))
AL_reg(context) = 0xff;
else
AL_reg(context) = 0;
}
break;
case 0x25: /* SET INTERRUPT VECTOR */
DOSVM_SetRMHandler( AL_reg(context),
(FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
break;
case 0x35: /* GET INTERRUPT VECTOR */
TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
{
FARPROC16 addr = DOSVM_GetRMHandler( AL_reg(context) );
context->SegEs = SELECTOROF(addr);
BX_reg(context) = OFFSETOF(addr);
}
break;
case 0x44: /* IOCTL */
switch (AL_reg(context))
{
case 0x0b: /* SET SHARING RETRY COUNT */
TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n",
CX_reg(context), DX_reg(context));
if (!CX_reg(context))
{
AX_reg(context) = 1;
SET_CFLAG(context);
break;
}
DOSMEM_LOL()->sharing_retry_delay = CX_reg(context);
if (!DX_reg(context))
DOSMEM_LOL()->sharing_retry_count = DX_reg(context);
RESET_CFLAG(context);
break;
}
break;
case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
if (!MZ_Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) ))
{
AX_reg(context) = GetLastError();
SET_CFLAG(context);
}
break;
case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
TRACE("EXIT with return code %d\n",AL_reg(context));
MZ_Exit( context, FALSE, AL_reg(context) );
break;
case 0x4d: /* GET RETURN CODE */
TRACE("GET RETURN CODE (ERRORLEVEL)\n");
AX_reg(context) = DOSVM_retval;
DOSVM_retval = 0;
break;
case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n");
DOSVM_psp = BX_reg(context);
break;
case 0x51: /* GET PSP ADDRESS */
TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n");
/* FIXME: should we return the original DOS PSP upon */
/* Windows startup ? */
BX_reg(context) = DOSVM_psp;
break;
case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
TRACE("SYSVARS - GET LIST OF LISTS\n");
{
context->SegEs = HIWORD(DOS_LOLSeg);
BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB);
}
break;
case 0x62: /* GET PSP ADDRESS */
TRACE("GET CURRENT PSP ADDRESS\n");
/* FIXME: should we return the original DOS PSP upon */
/* Windows startup ? */
BX_reg(context) = DOSVM_psp;
break;
default:
DOS3Call( context );
}
}

View File

@ -10,11 +10,11 @@
#include "miscemu.h"
/**********************************************************************
* INT_Int29Handler
* DOSVM_Int29Handler
*
* Handler for int 29h (fast console output)
*/
void WINAPI INT_Int29Handler( CONTEXT86 *context )
void WINAPI DOSVM_Int29Handler( CONTEXT86 *context )
{
/* Yes, it seems that this is really all this interrupt does. */
CONSOLE_Write(AL_reg(context), 0, 0, 0);

634
dlls/winedos/int31.c Normal file
View File

@ -0,0 +1,634 @@
/*
* DPMI 0.9 emulation
*
* Copyright 1995 Alexandre Julliard
*/
#include "config.h"
#include "windef.h"
#include "wine/winbase16.h"
#include "miscemu.h"
#include "task.h"
#include "msdos.h"
#include "dosexe.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(int31);
/* Structure for real-mode callbacks */
typedef struct
{
DWORD edi;
DWORD esi;
DWORD ebp;
DWORD reserved;
DWORD ebx;
DWORD edx;
DWORD ecx;
DWORD eax;
WORD fl;
WORD es;
WORD ds;
WORD fs;
WORD gs;
WORD ip;
WORD cs;
WORD sp;
WORD ss;
} REALMODECALL;
typedef struct tagRMCB {
DWORD address;
DWORD proc_ofs,proc_sel;
DWORD regs_ofs,regs_sel;
struct tagRMCB *next;
} RMCB;
static RMCB *FirstRMCB = NULL;
static WORD dpmi_flag;
/**********************************************************************
* INT_GetRealModeContext
*/
static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
{
context->Eax = call->eax;
context->Ebx = call->ebx;
context->Ecx = call->ecx;
context->Edx = call->edx;
context->Esi = call->esi;
context->Edi = call->edi;
context->Ebp = call->ebp;
context->EFlags = call->fl | V86_FLAG;
context->Eip = call->ip;
context->Esp = call->sp;
context->SegCs = call->cs;
context->SegDs = call->ds;
context->SegEs = call->es;
context->SegFs = call->fs;
context->SegGs = call->gs;
context->SegSs = call->ss;
}
/**********************************************************************
* INT_SetRealModeContext
*/
static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
{
call->eax = context->Eax;
call->ebx = context->Ebx;
call->ecx = context->Ecx;
call->edx = context->Edx;
call->esi = context->Esi;
call->edi = context->Edi;
call->ebp = context->Ebp;
call->fl = LOWORD(context->EFlags);
call->ip = LOWORD(context->Eip);
call->sp = LOWORD(context->Esp);
call->cs = context->SegCs;
call->ds = context->SegDs;
call->es = context->SegEs;
call->fs = context->SegFs;
call->gs = context->SegGs;
call->ss = context->SegSs;
}
#ifdef __i386__
void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi)
#if 0 /* original code, which early gccs puke on */
{
int _clobber;
__asm__ __volatile__(
"pushl %%ebp\n"
"pushl %%ebx\n"
"pushl %%es\n"
"pushl %%ds\n"
"pushfl\n"
"mov %7,%%es\n"
"mov %5,%%ds\n"
".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */
"popl %%ds\n"
"mov %%es,%0\n"
"popl %%es\n"
"popl %%ebx\n"
"popl %%ebp\n"
: "=d" (*es), "=D" (*edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber)
: "0" (ss), "2" (esp),
"4" (rmcb->regs_sel), "1" (rmcb->regs_ofs),
"3" (&rmcb->proc_ofs) );
}
#else /* code generated by a gcc new enough */
;
__ASM_GLOBAL_FUNC(DPMI_CallRMCB32,
"pushl %ebp\n\t"
"movl %esp,%ebp\n\t"
"pushl %edi\n\t"
"pushl %esi\n\t"
"movl 0x8(%ebp),%eax\n\t"
"movl 0x10(%ebp),%esi\n\t"
"movl 0xc(%ebp),%edx\n\t"
"movl 0x10(%eax),%ecx\n\t"
"movl 0xc(%eax),%edi\n\t"
"addl $0x4,%eax\n\t"
"pushl %ebp\n\t"
"pushl %ebx\n\t"
"pushl %es\n\t"
"pushl %ds\n\t"
"pushfl\n\t"
"mov %cx,%es\n\t"
"mov %dx,%ds\n\t"
".byte 0x36, 0xff, 0x18\n\t" /* lcall *%ss:(%eax) */
"popl %ds\n\t"
"mov %es,%dx\n\t"
"popl %es\n\t"
"popl %ebx\n\t"
"popl %ebp\n\t"
"movl 0x14(%ebp),%eax\n\t"
"movw %dx,(%eax)\n\t"
"movl 0x18(%ebp),%edx\n\t"
"movl %edi,(%edx)\n\t"
"popl %esi\n\t"
"popl %edi\n\t"
"leave\n\t"
"ret")
#endif
#endif /* __i386__ */
/**********************************************************************
* DPMI_CallRMCBProc
*
* This routine does the hard work of calling a callback procedure.
*/
static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
{
if (IS_SELECTOR_SYSTEM( rmcb->proc_sel )) {
/* Wine-internal RMCB, call directly */
((RMCBPROC)rmcb->proc_ofs)(context);
} else {
#ifdef __i386__
UINT16 ss,es;
DWORD esp,edi;
INT_SetRealModeContext(MapSL(MAKESEGPTR( rmcb->regs_sel, rmcb->regs_ofs )), context);
ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, WINE_LDT_FLAGS_DATA );
esp = context->Esp;
FIXME("untested!\n");
/* The called proc ends with an IRET, and takes these parameters:
* DS:ESI = pointer to real-mode SS:SP
* ES:EDI = pointer to real-mode call structure
* It returns:
* ES:EDI = pointer to real-mode call structure (may be a copy)
* It is the proc's responsibility to change the return CS:IP in the
* real-mode call structure. */
if (flag & 1) {
/* 32-bit DPMI client */
DPMI_CallRMCB32(rmcb, ss, esp, &es, &edi);
} else {
/* 16-bit DPMI client */
CONTEXT86 ctx = *context;
ctx.SegCs = rmcb->proc_sel;
ctx.Eip = rmcb->proc_ofs;
ctx.SegDs = ss;
ctx.Esi = esp;
ctx.SegEs = rmcb->regs_sel;
ctx.Edi = rmcb->regs_ofs;
/* FIXME: I'm pretty sure this isn't right - should push flags first */
wine_call_to_16_regs_short(&ctx, 0);
es = ctx.SegEs;
edi = ctx.Edi;
}
FreeSelector16(ss);
INT_GetRealModeContext( MapSL( MAKESEGPTR( es, edi )), context);
#else
ERR("RMCBs only implemented for i386\n");
#endif
}
}
/**********************************************************************
* DPMI_CallRMProc
*
* This routine does the hard work of calling a real mode procedure.
*/
int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret )
{
LPWORD stack16;
LPVOID addr = NULL; /* avoid gcc warning */
RMCB *CurrRMCB;
int alloc = 0, already = 0;
BYTE *code;
TRACE("EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
context->Eax, context->Ebx, context->Ecx, context->Edx );
TRACE("ESI=%08lx EDI=%08lx ES=%04lx DS=%04lx CS:IP=%04lx:%04x, %d WORD arguments, %s\n",
context->Esi, context->Edi, context->SegEs, context->SegDs,
context->SegCs, LOWORD(context->Eip), args, iret?"IRET":"FAR" );
callrmproc_again:
/* there might be some code that just jumps to RMCBs or the like,
in which case following the jumps here might get us to a shortcut */
code = CTX_SEG_OFF_TO_LIN(context, context->SegCs, context->Eip);
switch (*code) {
case 0xe9: /* JMP NEAR */
context->Eip += 3 + *(WORD *)(code+1);
/* yeah, I know these gotos don't look good... */
goto callrmproc_again;
case 0xea: /* JMP FAR */
context->Eip = *(WORD *)(code+1);
context->SegCs = *(WORD *)(code+3);
/* ...but since the label is there anyway... */
goto callrmproc_again;
case 0xeb: /* JMP SHORT */
context->Eip += 2 + *(signed char *)(code+1);
/* ...because of other gotos below, so... */
goto callrmproc_again;
}
/* shortcut for chaining to internal interrupt handlers */
if ((context->SegCs == 0xF000) && iret)
{
DOSVM_RealModeInterrupt( LOWORD(context->Eip)/4, context);
return 0;
}
/* shortcut for RMCBs */
CurrRMCB = FirstRMCB;
while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
CurrRMCB = CurrRMCB->next;
if (!CurrRMCB && !MZ_Current())
{
FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
TRACE("creating VM86 task\n");
MZ_AllocDPMITask();
}
if (!already) {
if (!context->SegSs) {
alloc = 1; /* allocate default stack */
stack16 = addr = DOSMEM_GetBlock( 64, (UINT16 *)&(context->SegSs) );
context->Esp = 64-2;
stack16 += 32-1;
if (!addr) {
ERR("could not allocate default stack\n");
return 1;
}
} else {
stack16 = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
}
context->Esp -= (args + (iret?1:0)) * sizeof(WORD);
stack16 -= args;
if (args) memcpy(stack16, stack, args*sizeof(WORD) );
/* push flags if iret */
if (iret) {
stack16--; args++;
*stack16 = LOWORD(context->EFlags);
}
/* push return address (return to interrupt wrapper) */
*(--stack16) = DOSMEM_wrap_seg;
*(--stack16) = 0;
/* adjust stack */
context->Esp -= 2*sizeof(WORD);
already = 1;
}
if (CurrRMCB) {
/* RMCB call, invoke protected-mode handler directly */
DPMI_CallRMCBProc(context, CurrRMCB, dpmi_flag);
/* check if we returned to where we thought we would */
if ((context->SegCs != DOSMEM_wrap_seg) ||
(LOWORD(context->Eip) != 0)) {
/* we need to continue at different address in real-mode space,
so we need to set it all up for real mode again */
goto callrmproc_again;
}
} else {
TRACE("entering real mode...\n");
DOSVM_Enter( context );
TRACE("returned from real-mode call\n");
}
if (alloc) DOSMEM_FreeBlock( addr );
return 0;
}
/**********************************************************************
* DOSVM_CallRMInt (WINEDOS.@)
*/
void WINAPI DOSVM_CallRMInt( CONTEXT86 *context )
{
CONTEXT86 realmode_ctx;
FARPROC16 rm_int = DOSVM_GetRMHandler( BL_reg(context) );
REALMODECALL *call = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) ));
INT_GetRealModeContext( call, &realmode_ctx );
/* we need to check if a real-mode program has hooked the interrupt */
if (HIWORD(rm_int)!=0xF000) {
/* yup, which means we need to switch to real mode... */
realmode_ctx.SegCs = HIWORD(rm_int);
realmode_ctx.Eip = LOWORD(rm_int);
if (DPMI_CallRMProc( &realmode_ctx, NULL, 0, TRUE))
SET_CFLAG(context);
} else {
RESET_CFLAG(context);
/* use the IP we have instead of BL_reg, in case some apps
decide to move interrupts around for whatever reason... */
DOSVM_RealModeInterrupt( LOWORD(rm_int)/4, &realmode_ctx );
}
INT_SetRealModeContext( call, &realmode_ctx );
}
/**********************************************************************
* DOSVM_CallRMProc (WINEDOS.@)
*/
void WINAPI DOSVM_CallRMProc( CONTEXT86 *context, int iret )
{
REALMODECALL *p = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) ));
CONTEXT86 context16;
TRACE("RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
p->eax, p->ebx, p->ecx, p->edx);
TRACE(" ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s\n",
p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context), iret?"IRET":"FAR" );
if (!(p->cs) && !(p->ip)) { /* remove this check
if Int21/6501 case map function
has been implemented */
SET_CFLAG(context);
return;
}
INT_GetRealModeContext(p, &context16);
DPMI_CallRMProc( &context16, ((LPWORD)MapSL(MAKESEGPTR(context->SegSs, LOWORD(context->Esp))))+3,
CX_reg(context), iret );
INT_SetRealModeContext(p, &context16);
}
/* (see dosmem.c, function DOSMEM_InitDPMI) */
static void StartPM( CONTEXT86 *context )
{
UINT16 cs, ss, ds, es;
CONTEXT86 pm_ctx;
DWORD psp_ofs = (DWORD)(DOSVM_psp<<4);
PDB16 *psp = (PDB16 *)psp_ofs;
HANDLE16 env_seg = psp->environment;
unsigned char selflags = WINE_LDT_FLAGS_DATA;
RESET_CFLAG(context);
dpmi_flag = AX_reg(context);
/* our mode switch wrapper have placed the desired CS into DX */
cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, WINE_LDT_FLAGS_CODE );
/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
32-bit code using this stack. */
if (dpmi_flag & 1) selflags |= WINE_LDT_FLAGS_32BIT;
ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, selflags );
/* do the same for the data segments, just in case */
if (context->SegDs == context->SegSs) ds = ss;
else ds = SELECTOR_AllocBlock( (void *)(context->SegDs<<4), 0x10000, selflags );
es = SELECTOR_AllocBlock( psp, 0x100, selflags );
/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4), 0x10000, WINE_LDT_FLAGS_DATA );
pm_ctx = *context;
pm_ctx.SegCs = DOSMEM_dpmi_sel;
/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */
pm_ctx.Eax = ss;
pm_ctx.Edx = cs;
pm_ctx.SegDs = ds;
pm_ctx.SegEs = es;
pm_ctx.SegFs = 0;
pm_ctx.SegGs = 0;
TRACE("DOS program is now entering protected mode\n");
wine_call_to_16_regs_short(&pm_ctx, 0);
/* in the current state of affairs, we won't ever actually return here... */
/* we should have int21/ah=4c do it someday, though... */
FreeSelector16(psp->environment);
psp->environment = env_seg;
FreeSelector16(es);
if (ds != ss) FreeSelector16(ds);
FreeSelector16(ss);
FreeSelector16(cs);
}
static RMCB *DPMI_AllocRMCB( void )
{
RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB));
UINT16 uParagraph;
if (NewRMCB)
{
LPVOID RMCBmem = DOSMEM_GetBlock(4, &uParagraph);
LPBYTE p = RMCBmem;
*p++ = 0xcd; /* RMCB: */
*p++ = 0x31; /* int $0x31 */
/* it is the called procedure's task to change the return CS:EIP
the DPMI 0.9 spec states that if it doesn't, it will be called again */
*p++ = 0xeb;
*p++ = 0xfc; /* jmp RMCB */
NewRMCB->address = MAKELONG(0, uParagraph);
NewRMCB->next = FirstRMCB;
FirstRMCB = NewRMCB;
}
return NewRMCB;
}
FARPROC16 WINAPI DPMI_AllocInternalRMCB( RMCBPROC proc )
{
RMCB *NewRMCB = DPMI_AllocRMCB();
if (NewRMCB) {
NewRMCB->proc_ofs = (DWORD)proc;
NewRMCB->proc_sel = 0;
NewRMCB->regs_ofs = 0;
NewRMCB->regs_sel = 0;
return (FARPROC16)(NewRMCB->address);
}
return NULL;
}
static int DPMI_FreeRMCB( DWORD address )
{
RMCB *CurrRMCB = FirstRMCB;
RMCB *PrevRMCB = NULL;
while (CurrRMCB && (CurrRMCB->address != address))
{
PrevRMCB = CurrRMCB;
CurrRMCB = CurrRMCB->next;
}
if (CurrRMCB)
{
if (PrevRMCB)
PrevRMCB->next = CurrRMCB->next;
else
FirstRMCB = CurrRMCB->next;
DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(CurrRMCB->address));
HeapFree(GetProcessHeap(), 0, CurrRMCB);
return 0;
}
return 1;
}
void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc )
{
DPMI_FreeRMCB( (DWORD)proc );
}
/* DPMI Raw Mode Switch handler */
#if 0
void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
{
LPDOSTASK lpDosTask = MZ_Current();
CONTEXT86 rm_ctx;
int ret;
if (!lpDosTask) {
/* we could probably start a DPMI-only dosmod task here, but I doubt
anything other than real DOS apps want to call raw mode switch */
ERR("attempting raw mode switch without DOS task!\n");
ExitProcess(1);
}
/* initialize real-mode context as per spec */
memset(&rm_ctx, 0, sizeof(rm_ctx));
rm_ctx.SegDs = AX_sig(context);
rm_ctx.SegEs = CX_sig(context);
rm_ctx.SegSs = DX_sig(context);
rm_ctx.Esp = EBX_sig(context);
rm_ctx.SegCs = SI_sig(context);
rm_ctx.Eip = EDI_sig(context);
rm_ctx.Ebp = EBP_sig(context);
rm_ctx.SegFs = 0;
rm_ctx.SegGs = 0;
rm_ctx.EFlags = EFL_sig(context); /* at least we need the IF flag */
/* enter real mode again */
TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip);
ret = DOSVM_Enter( &rm_ctx );
/* when the real-mode stuff call its mode switch address,
DOSVM_Enter will return and we will continue here */
if (ret<0) {
/* if the sync was lost, there's no way to recover */
ExitProcess(1);
}
/* alter protected-mode context as per spec */
DS_sig(context) = LOWORD(rm_ctx.Eax);
ES_sig(context) = LOWORD(rm_ctx.Ecx);
SS_sig(context) = LOWORD(rm_ctx.Edx);
ESP_sig(context) = rm_ctx.Ebx;
CS_sig(context) = LOWORD(rm_ctx.Esi);
EIP_sig(context) = rm_ctx.Edi;
EBP_sig(context) = rm_ctx.Ebp;
FS_sig(context) = 0;
GS_sig(context) = 0;
/* Return to new address and hope that we didn't mess up */
TRACE("re-entering protected mode at %04x:%08lx\n",
CS_sig(context), EIP_sig(context));
}
#endif
/**********************************************************************
* DOSVM_AllocRMCB (WINEDOS.@)
*/
void WINAPI DOSVM_AllocRMCB( CONTEXT86 *context )
{
RMCB *NewRMCB = DPMI_AllocRMCB();
TRACE("Function to call: %04x:%04x\n", (WORD)context->SegDs, SI_reg(context) );
if (NewRMCB)
{
/* FIXME: if 32-bit DPMI client, use ESI and EDI */
NewRMCB->proc_ofs = LOWORD(context->Esi);
NewRMCB->proc_sel = context->SegDs;
NewRMCB->regs_ofs = LOWORD(context->Edi);
NewRMCB->regs_sel = context->SegEs;
SET_LOWORD( context->Ecx, HIWORD(NewRMCB->address) );
SET_LOWORD( context->Edx, LOWORD(NewRMCB->address) );
}
else
{
SET_LOWORD( context->Eax, 0x8015 ); /* callback unavailable */
SET_CFLAG(context);
}
}
/**********************************************************************
* DOSVM_FreeRMCB (WINEDOS.@)
*/
void WINAPI DOSVM_FreeRMCB( CONTEXT86 *context )
{
FIXME("callback address: %04x:%04x\n",
CX_reg(context), DX_reg(context));
if (DPMI_FreeRMCB(MAKELONG(DX_reg(context), CX_reg(context)))) {
SET_LOWORD( context->Eax, 0x8024 ); /* invalid callback address */
SET_CFLAG(context);
}
}
/**********************************************************************
* DOSVM_Int31Handler
*
* Handler for real-mode int 31h (DPMI).
*/
void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
{
/* check if it's our wrapper */
TRACE("called from real mode\n");
if (context->SegCs==DOSMEM_dpmi_seg) {
/* This is the protected mode switch */
StartPM(context);
return;
}
else if (context->SegCs==DOSMEM_xms_seg)
{
/* This is the XMS driver entry point */
XMS_Handler(context);
return;
}
else
{
/* Check for RMCB */
RMCB *CurrRMCB = FirstRMCB;
while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
CurrRMCB = CurrRMCB->next;
if (CurrRMCB) {
/* RMCB call, propagate to protected-mode handler */
DPMI_CallRMCBProc(context, CurrRMCB, dpmi_flag);
return;
}
}
/* chain to protected mode handler */
INT_Int31Handler( context );
}

View File

@ -10,7 +10,6 @@
#include "wingdi.h"
#include "winuser.h"
#include "miscemu.h"
#include "callback.h"
#include "dosexe.h"
#include "vga.h"
#include "debugtools.h"
@ -25,11 +24,11 @@ static struct
} mouse_info;
/**********************************************************************
* INT_Int33Handler
* DOSVM_Int33Handler
*
* Handler for int 33h (MS MOUSE).
*/
void WINAPI INT_Int33Handler( CONTEXT86 *context )
void WINAPI DOSVM_Int33Handler( CONTEXT86 *context )
{
switch (LOWORD(context->Eax)) {
case 0x00:
@ -100,7 +99,7 @@ static void MouseRelay(CONTEXT86 *context,void *mdata)
DPMI_CallRMProc(&ctx, NULL, 0, 0);
}
void WINAPI INT_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
void WINAPI DOSVM_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
{
WORD mask = 0;
unsigned Height, Width, SX=1, SY=1;
@ -152,6 +151,6 @@ void WINAPI INT_Int33Message(UINT message,WPARAM wParam,LPARAM lParam)
data->but = mouse_info.but;
data->x = mouse_info.x;
data->y = mouse_info.y;
Dosvm.QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data);
DOSVM_QueueEvent(-1, DOS_PRIORITY_MOUSE, MouseRelay, data);
}
}

54
dlls/winedos/ioports.c Normal file
View File

@ -0,0 +1,54 @@
/*
* Emulation of processor ioports.
*
* Copyright 1995 Morten Welinder
* Copyright 1998 Andreas Mohr, Ove Kaaven
*/
#include "config.h"
#include "windef.h"
#include "dosexe.h"
#include "vga.h"
/**********************************************************************
* DOSVM_inport
*/
BOOL WINAPI DOSVM_inport( int port, int size, DWORD *res )
{
switch (port)
{
case 0x60:
*res = DOSVM_Int09ReadScan(NULL);
break;
case 0x3ba:
case 0x3da:
*res = (DWORD)VGA_ioport_in( port );
break;
default:
return FALSE; /* not handled */
}
return TRUE; /* handled */
}
/**********************************************************************
* DOSVM_outport
*/
BOOL WINAPI DOSVM_outport( int port, int size, DWORD value )
{
switch (port)
{
case 0x20:
DOSVM_PIC_ioport_out( port, (BYTE)value );
break;
case 0x3c8:
case 0x3c9:
VGA_ioport_out( port, (BYTE)value );
break;
default:
return FALSE; /* not handled */
}
return TRUE; /* handled */
}

View File

@ -33,8 +33,6 @@
DEFAULT_DEBUG_CHANNEL(module);
static LPDOSTASK dos_current;
#ifdef MZ_SUPPORTED
#ifdef HAVE_SYS_MMAN_H
@ -74,7 +72,7 @@ typedef struct {
static WORD init_cs,init_ip,init_ss,init_sp;
static char mm_name[128];
int read_pipe, write_pipe;
int read_pipe = -1, write_pipe = -1;
HANDLE hReadPipe, hWritePipe;
pid_t dosmod_pid;
@ -90,9 +88,9 @@ static void MZ_CreatePSP( LPVOID lpPSP, WORD env, WORD par )
/* some programs use this to calculate how much memory they need */
psp->nextParagraph=0x9FFF; /* FIXME: use a real value */
/* FIXME: dispatcher */
psp->savedint22 = INT_GetRMHandler(0x22);
psp->savedint23 = INT_GetRMHandler(0x23);
psp->savedint24 = INT_GetRMHandler(0x24);
psp->savedint22 = DOSVM_GetRMHandler(0x22);
psp->savedint23 = DOSVM_GetRMHandler(0x23);
psp->savedint24 = DOSVM_GetRMHandler(0x24);
psp->parentPSP=par;
psp->environment=env;
/* FIXME: more PSP stuff */
@ -175,10 +173,6 @@ static BOOL MZ_InitMemory(void)
int mm_fd;
void *img_base;
/* initialize the memory */
TRACE("Initializing DOS memory structures\n");
DOSMEM_Init(TRUE);
/* allocate 1MB+64K shared memory */
tmpnam(mm_name);
/* strcpy(mm_name,"/tmp/mydosimage"); */
@ -201,7 +195,6 @@ static BOOL MZ_InitMemory(void)
static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
{
LPDOSTASK lpDosTask = dos_current;
IMAGE_DOS_HEADER mz_header;
DWORD image_start,image_size,min_size,max_size,avail;
BYTE*psp_start,*load_start,*oldenv;
@ -210,17 +203,15 @@ static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
WORD env_seg, load_seg, rel_seg, oldpsp_seg;
DWORD len;
if (lpDosTask) {
if (DOSVM_psp) {
/* DOS process already running, inherit from it */
PDB16* par_psp = (PDB16*)((DWORD)lpDosTask->psp_seg << 4);
PDB16* par_psp = (PDB16*)((DWORD)DOSVM_psp << 4);
alloc=0;
oldenv = (LPBYTE)((DWORD)par_psp->environment << 4);
oldpsp_seg = lpDosTask->psp_seg;
oldpsp_seg = DOSVM_psp;
} else {
/* allocate new DOS process, inheriting from Wine environment */
alloc=1;
lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
dos_current = lpDosTask;
oldenv = GetEnvironmentStringsA();
oldpsp_seg = 0;
}
@ -272,13 +263,13 @@ static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
goto load_error;
}
if (avail>max_size) avail=max_size;
psp_start=DOSMEM_GetBlock(avail,&lpDosTask->psp_seg);
psp_start=DOSMEM_GetBlock(avail,&DOSVM_psp);
if (!psp_start) {
ERR("error allocating DOS memory\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto load_error;
}
load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE);
load_seg=DOSVM_psp+(old_com?0:PSP_SIZE);
rel_seg=load_seg;
load_start=psp_start+(PSP_SIZE<<4);
MZ_CreatePSP(psp_start, env_seg, oldpsp_seg);
@ -324,9 +315,8 @@ static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk )
return TRUE;
load_error:
lpDosTask->psp_seg = oldpsp_seg;
DOSVM_psp = oldpsp_seg;
if (alloc) {
dos_current = NULL;
if (mm_name[0]!=0) unlink(mm_name);
}
@ -342,7 +332,7 @@ void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile )
}
/***********************************************************************
* Exec (WINEDOS.@)
* MZ_Exec
*/
BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
{
@ -350,7 +340,6 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para
* (i.e. one DOS app spawning another) */
/* FIXME: do we want to check binary type first, to check
* whether it's a NE/PE executable? */
LPDOSTASK lpDosTask = MZ_Current();
HFILE hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, 0);
BOOL ret = FALSE;
@ -360,19 +349,19 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para
case 1: /* load but don't execute */
{
/* save current process's return SS:SP now */
LPBYTE psp_start = (LPBYTE)((DWORD)lpDosTask->psp_seg << 4);
LPBYTE psp_start = (LPBYTE)((DWORD)DOSVM_psp << 4);
PDB16 *psp = (PDB16 *)psp_start;
psp->saveStack = (DWORD)MAKESEGPTR(context->SegSs, LOWORD(context->Esp));
}
ret = MZ_DoLoadImage( hFile, filename, NULL );
if (ret) {
/* MZ_LoadImage created a new PSP and loaded new values into lpDosTask,
/* MZ_LoadImage created a new PSP and loaded new values into it,
* let's work on the new values now */
LPBYTE psp_start = (LPBYTE)((DWORD)lpDosTask->psp_seg << 4);
LPBYTE psp_start = (LPBYTE)((DWORD)DOSVM_psp << 4);
ExecBlock *blk = (ExecBlock *)paramblk;
MZ_FillPSP(psp_start, DOSMEM_MapRealToLinear(blk->cmdline));
/* the lame MS-DOS engineers decided that the return address should be in int22 */
INT_SetRMHandler(0x22, (FARPROC16)MAKESEGPTR(context->SegCs, LOWORD(context->Eip)));
DOSVM_SetRMHandler(0x22, (FARPROC16)MAKESEGPTR(context->SegCs, LOWORD(context->Eip)));
if (func) {
/* don't execute, just return startup state */
blk->init_cs = init_cs;
@ -385,8 +374,8 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para
context->Eip = init_ip;
context->SegSs = init_ss;
context->Esp = init_sp;
context->SegDs = lpDosTask->psp_seg;
context->SegEs = lpDosTask->psp_seg;
context->SegDs = DOSVM_psp;
context->SegEs = DOSVM_psp;
context->Eax = 0;
}
}
@ -407,22 +396,16 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para
}
/***********************************************************************
* LoadDPMI (WINEDOS.@)
* MZ_AllocDPMITask
*/
LPDOSTASK WINAPI MZ_AllocDPMITask( void )
void WINAPI MZ_AllocDPMITask( void )
{
LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
if (lpDosTask) {
dos_current = lpDosTask;
MZ_InitMemory();
MZ_InitTask();
}
return lpDosTask;
}
/***********************************************************************
* RunInThread (WINEDOS.@)
* MZ_RunInThread
*/
void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg )
{
@ -536,10 +519,9 @@ static BOOL MZ_InitTask(void)
static void MZ_Launch(void)
{
LPDOSTASK lpDosTask = MZ_Current();
CONTEXT context;
TDB *pTask = TASK_GetCurrent();
BYTE *psp_start = PTR_REAL_TO_LIN( lpDosTask->psp_seg, 0 );
TDB *pTask = GlobalLock16( GetCurrentTask() );
BYTE *psp_start = PTR_REAL_TO_LIN( DOSVM_psp, 0 );
MZ_FillPSP(psp_start, GetCommandLineA());
pTask->flags |= TDBF_WINOLDAP;
@ -549,8 +531,8 @@ static void MZ_Launch(void)
context.Eip = init_ip;
context.SegSs = init_ss;
context.Esp = init_sp;
context.SegDs = lpDosTask->psp_seg;
context.SegEs = lpDosTask->psp_seg;
context.SegDs = DOSVM_psp;
context.SegEs = DOSVM_psp;
context.EFlags = 0x00080000; /* virtual interrupt flag */
_LeaveWin16Lock();
DOSVM_Enter( &context );
@ -564,34 +546,33 @@ static void MZ_KillTask(void)
}
/***********************************************************************
* Exit (WINEDOS.@)
* MZ_Exit
*/
void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
{
LPDOSTASK lpDosTask = MZ_Current();
if (lpDosTask) {
WORD psp_seg = cs_psp ? context->SegCs : lpDosTask->psp_seg;
if (DOSVM_psp) {
WORD psp_seg = cs_psp ? context->SegCs : DOSVM_psp;
LPBYTE psp_start = (LPBYTE)((DWORD)psp_seg << 4);
PDB16 *psp = (PDB16 *)psp_start;
WORD parpsp = psp->parentPSP; /* check for parent DOS process */
if (parpsp) {
/* retrieve parent's return address */
FARPROC16 retaddr = INT_GetRMHandler(0x22);
FARPROC16 retaddr = DOSVM_GetRMHandler(0x22);
/* restore interrupts */
INT_SetRMHandler(0x22, psp->savedint22);
INT_SetRMHandler(0x23, psp->savedint23);
INT_SetRMHandler(0x24, psp->savedint24);
DOSVM_SetRMHandler(0x22, psp->savedint22);
DOSVM_SetRMHandler(0x23, psp->savedint23);
DOSVM_SetRMHandler(0x24, psp->savedint24);
/* FIXME: deallocate file handles etc */
/* free process's associated memory
* FIXME: walk memory and deallocate all blocks owned by process */
DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,psp->environment)));
DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,lpDosTask->psp_seg)));
DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(MAKELONG(0,DOSVM_psp)));
/* switch to parent's PSP */
lpDosTask->psp_seg = parpsp;
DOSVM_psp = parpsp;
psp_start = (LPBYTE)((DWORD)parpsp << 4);
psp = (PDB16 *)psp_start;
/* now return to parent */
lpDosTask->retval = retval;
DOSVM_retval = retval;
context->SegCs = SELECTOROF(retaddr);
context->Eip = OFFSETOF(retaddr);
context->SegSs = SELECTOROF(psp->saveStack);
@ -615,7 +596,7 @@ void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile )
}
/***********************************************************************
* Exec (WINEDOS.@)
* MZ_Exec
*/
BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
{
@ -625,16 +606,16 @@ BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID para
}
/***********************************************************************
* LoadDPMI (WINEDOS.@)
* MZ_AllocDPMITask
*/
LPDOSTASK WINAPI MZ_AllocDPMITask( void )
void WINAPI MZ_AllocDPMITask( void )
{
ERR("Actual real-mode calls not supported on this platform!\n");
return NULL;
}
/***********************************************************************
* Exit (WINEDOS.@)
* MZ_Exit
*/
void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
{
@ -644,9 +625,9 @@ void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
#endif /* !MZ_SUPPORTED */
/***********************************************************************
* GetCurrent (WINEDOS.@)
* MZ_Current
*/
LPDOSTASK WINAPI MZ_Current( void )
BOOL WINAPI MZ_Current( void )
{
return dos_current;
return (write_pipe != -1); /* FIXME: do a better check */
}

View File

@ -11,7 +11,7 @@
#include "winuser.h"
#include "wincon.h"
#include "miscemu.h"
#include "callback.h"
#include "dosexe.h"
#include "vga.h"
#include "ddraw.h"
#include "services.h"
@ -29,9 +29,6 @@ static HANDLE poll_timer;
typedef HRESULT WINAPI (*DirectDrawCreateProc)(LPGUID,LPDIRECTDRAW *,LPUNKNOWN);
static DirectDrawCreateProc pDirectDrawCreate;
typedef HWND WINAPI (*CreateWindowExAProc)(DWORD,LPCSTR,LPCSTR,DWORD,INT,INT, INT,INT,HWND,HMENU,HINSTANCE,LPVOID);
static CreateWindowExAProc pCreateWindowExA;
static PALETTEENTRY vga_def_palette[256]={
/* red green blue */
{0x00, 0x00, 0x00}, /* 0 - Black */
@ -105,25 +102,12 @@ static void WINAPI VGA_DoSetMode(ULONG_PTR arg)
return;
}
}
if (!pCreateWindowExA)
{
HMODULE hmod = LoadLibraryA( "user32.dll" );
if (!hmod) {
ERR("Can't load user32.dll.\n");
return;
}
if (hmod) pCreateWindowExA = (CreateWindowExAProc)GetProcAddress( hmod, "CreateWindowExA" );
if (!pCreateWindowExA) {
ERR("Can't lookup CreateWindowExA from user32.dll.\n");
return;
}
}
res = pDirectDrawCreate(NULL,&lpddraw,NULL);
if (!lpddraw) {
ERR("DirectDraw is not available (res = %lx)\n",res);
return;
}
hwnd = pCreateWindowExA(0,"STATIC","WINEDOS VGA",WS_POPUP|WS_BORDER|WS_CAPTION|WS_SYSMENU,0,0,par->Xres,par->Yres,0,0,0,NULL);
hwnd = CreateWindowExA(0,"STATIC","WINEDOS VGA",WS_POPUP|WS_BORDER|WS_CAPTION|WS_SYSMENU,0,0,par->Xres,par->Yres,0,0,0,NULL);
if (!hwnd) {
ERR("Failed to create user window.\n");
}
@ -174,8 +158,7 @@ int VGA_SetMode(unsigned Xres,unsigned Yres,unsigned Depth)
par.Xres = Xres;
par.Yres = Yres;
par.Depth = Depth;
if (Dosvm.RunInThread) Dosvm.RunInThread(VGA_DoSetMode, (ULONG_PTR)&par);
else VGA_DoSetMode((ULONG_PTR)&par);
MZ_RunInThread(VGA_DoSetMode, (ULONG_PTR)&par);
return par.ret;
}
@ -203,10 +186,7 @@ static void WINAPI VGA_DoExit(ULONG_PTR arg)
void VGA_Exit(void)
{
if (lpddraw) {
if (Dosvm.RunInThread) Dosvm.RunInThread(VGA_DoExit, 0);
else VGA_DoExit(0);
}
if (lpddraw) MZ_RunInThread(VGA_DoExit, 0);
}
void VGA_SetPalette(PALETTEENTRY*pal,int start,int len)
@ -352,8 +332,7 @@ void CALLBACK VGA_Poll( ULONG_PTR arg )
ch[X].Attributes = *dat++;
}
dest.Left=0; dest.Right=Width+1;
FIXME("output commented out for now, should be moved to winedos.dll\n");
/*WriteConsoleOutputA(con, ch, siz, off, &dest);*/
WriteConsoleOutputA(con, ch, siz, off, &dest);
}
}
vga_refresh=1;

View File

@ -6,20 +6,19 @@ import user32.dll
import kernel32.dll
import ntdll.dll
debug_channels (int module relay)
debug_channels (aspi console ddraw int int21 int31 module relay)
@ stdcall GetCurrent() MZ_Current
@ stdcall LoadDPMI() MZ_AllocDPMITask
@ stdcall LoadDosExe(str long) MZ_LoadImage
@ stdcall Exec(ptr str long ptr) MZ_Exec
@ stdcall Exit(ptr long long) MZ_Exit
@ stdcall RunInThread(ptr long) MZ_RunInThread
@ stdcall Enter(ptr) DOSVM_Enter
@ stdcall Wait(long long) DOSVM_Wait
@ stdcall QueueEvent(long long ptr ptr) DOSVM_QueueEvent
@ stdcall OutPIC(long long) DOSVM_PIC_ioport_out
# DPMI functions
@ stdcall CallRMInt(ptr) DOSVM_CallRMInt
@ stdcall CallRMProc(ptr ptr long long) DOSVM_CallRMProc
@ stdcall AllocRMCB(ptr) DOSVM_AllocRMCB
@ stdcall FreeRMCB(ptr) DOSVM_FreeRMCB
# I/O functions
@ stdcall SetTimer(long) DOSVM_SetTimer
@ stdcall GetTimer() DOSVM_GetTimer
@ stdcall KbdReadScan(ptr) INT_Int09ReadScan
@ stdcall inport(long long ptr) DOSVM_inport
@ stdcall outport(long long long) DOSVM_outport
@ stdcall ASPIHandler(ptr) DOSVM_ASPIHandler

View File

@ -9,13 +9,13 @@
#include "windef.h"
#include "wingdi.h"
#include "wine/wingdi16.h"
#include "miscemu.h"
#include "dispdib.h"
#include "vga.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ddraw);
#if 0
static int dispdib_multi = 0;
static WORD DISPDIB_Begin(WORD wFlags)
@ -80,6 +80,8 @@ static void DISPDIB_Show(LPBITMAPINFOHEADER lpbi,LPSTR lpBits,WORD uFlags)
VGA_Poll(0);
}
#endif
/*********************************************************************
* DisplayDib (DISPDIB.1)
@ -115,6 +117,7 @@ WORD WINAPI DisplayDib(
WORD wFlags /* [in] */
)
{
#if 0
WORD ret;
if (wFlags&DISPLAYDIB_END) {
@ -138,5 +141,7 @@ WORD WINAPI DisplayDib(
FIXME("wait not implemented\n");
}
if (!dispdib_multi) DISPDIB_End();
#endif
FIXME( "broken, should be rewritten using ddraw\n" );
return DISPLAYDIB_NOERROR;
}

View File

@ -31,19 +31,20 @@ extern CALLOUT_TABLE Callout;
typedef struct {
struct _DOSTASK* WINAPI (*Current)( void );
struct _DOSTASK* WINAPI (*LoadDPMI)( void );
void WINAPI (*LoadDosExe)( LPCSTR filename, HANDLE hFile );
BOOL WINAPI (*Exec)( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
void WINAPI (*Exit)( CONTEXT86 *context, BOOL cs_psp, WORD retval );
int WINAPI (*Enter)( CONTEXT86 *context );
void WINAPI (*RunInThread)( PAPCFUNC proc, ULONG_PTR arg );
void WINAPI (*Wait)( int read_pipe, HANDLE hObject );
void WINAPI (*QueueEvent)( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data );
void WINAPI (*OutPIC)( WORD port, BYTE val );
/* DPMI functions */
void WINAPI (*CallRMInt)( CONTEXT86 *context );
void WINAPI (*CallRMProc)( CONTEXT86 *context, int iret );
void WINAPI (*AllocRMCB)( CONTEXT86 *context );
void WINAPI (*FreeRMCB)( CONTEXT86 *context );
/* I/O functions */
void WINAPI (*SetTimer)( unsigned ticks );
unsigned WINAPI (*GetTimer)( void );
BYTE WINAPI (*KbdReadScan)( BYTE *ascii );
BOOL WINAPI (*inport)( int port, int size, DWORD *res );
BOOL WINAPI (*outport)( int port, int size, DWORD val );
void WINAPI (*ASPIHandler)( CONTEXT86 *context );
} DOSVM_TABLE;
extern DOSVM_TABLE Dosvm;

View File

@ -1,49 +0,0 @@
/*
* DOS EXE loader
*
* Copyright 1998 Ove Kåven
*/
#ifndef __WINE_DOSEXE_H
#define __WINE_DOSEXE_H
#include <sys/types.h> /* pid_t */
#include "winbase.h" /* for LPSTARTUPINFO32A */
#include "winnt.h" /* for PCONTEXT */
struct _DOSEVENT;
typedef void (*DOSRELAY)(CONTEXT86*,void*);
typedef struct _DOSTASK {
WORD psp_seg, retval;
WORD dpmi_flag;
} DOSTASK, *LPDOSTASK;
#define DOS_PRIORITY_REALTIME 0 /* IRQ0 */
#define DOS_PRIORITY_KEYBOARD 1 /* IRQ1 */
#define DOS_PRIORITY_VGA 2 /* IRQ9 */
#define DOS_PRIORITY_MOUSE 5 /* IRQ12 */
#define DOS_PRIORITY_SERIAL 10 /* IRQ4 */
#if defined(linux) && defined(__i386__)
#define MZ_SUPPORTED
#endif /* linux-i386 */
#define V86_FLAG 0x00020000
extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile );
extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
extern void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
extern LPDOSTASK WINAPI MZ_Current( void );
extern LPDOSTASK WINAPI MZ_AllocDPMITask( void );
extern void WINAPI MZ_RunInThread( PAPCFUNC proc, ULONG_PTR arg );
extern INT WINAPI DOSVM_Enter( CONTEXT86 *context );
extern void WINAPI DOSVM_Wait( INT read_pipe, HANDLE hObject );
extern DWORD WINAPI DOSVM_Loop( LPVOID lpExtra );
extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVOID data );
extern void WINAPI DOSVM_PIC_ioport_out( WORD port, BYTE val );
extern void WINAPI DOSVM_SetTimer( UINT ticks );
extern UINT WINAPI DOSVM_GetTimer( void );
#endif /* __WINE_DOSEXE_H */

View File

@ -155,40 +155,15 @@ extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
/* memory/instr.c */
extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context );
/* msdos/devices.c */
extern void DOSDEV_InstallDOSDevices(void);
extern DWORD DOSDEV_Console(void);
extern DWORD DOSDEV_FindCharDevice(char*name);
extern int DOSDEV_Peek(DWORD dev, BYTE*data);
extern int DOSDEV_Read(DWORD dev, DWORD buf, int buflen);
extern int DOSDEV_Write(DWORD dev, DWORD buf, int buflen, int verify);
extern int DOSDEV_IoctlRead(DWORD dev, DWORD buf, int buflen);
extern int DOSDEV_IoctlWrite(DWORD dev, DWORD buf, int buflen);
/* msdos/interrupts.c */
typedef void WINAPI (*INTPROC)(CONTEXT86*);
extern FARPROC16 INT_GetPMHandler( BYTE intnum );
extern void INT_SetPMHandler( BYTE intnum, FARPROC16 handler );
extern FARPROC16 INT_GetRMHandler( BYTE intnum );
extern void INT_SetRMHandler( BYTE intnum, FARPROC16 handler );
extern FARPROC16 INT_CtxGetHandler( CONTEXT86 *context, BYTE intnum );
extern void INT_CtxSetHandler( CONTEXT86 *context, BYTE intnum, FARPROC16 handler );
extern int INT_RealModeInterrupt( BYTE intnum, CONTEXT86 *context );
extern INTPROC INT_GetWineHandler( BYTE intnum );
extern void INT_SetWineHandler( BYTE intnum, INTPROC proc );
/* msdos/ioports.c */
extern DWORD IO_inport( int port, int count );
extern void IO_outport( int port, int count, DWORD value );
/* msdos/int09.c */
extern void WINAPI INT_Int09Handler(CONTEXT86*);
extern void WINAPI INT_Int09SendScan(BYTE scan,BYTE ascii);
extern BYTE WINAPI INT_Int09ReadScan(BYTE*ascii);
/* msdos/int10.c */
extern void WINAPI INT_Int10Handler(CONTEXT86*);
/* msdos/int11.c */
extern void WINAPI INT_Int11Handler(CONTEXT86*);
@ -201,17 +176,6 @@ extern void WINAPI INT_Int13Handler(CONTEXT86*);
/* msdos/int15.c */
extern void WINAPI INT_Int15Handler(CONTEXT86*);
/* msdos/int16.c */
extern void WINAPI INT_Int16Handler(CONTEXT86*);
extern int WINAPI INT_Int16ReadChar(BYTE*ascii,BYTE*scan,BOOL peek);
extern int WINAPI INT_Int16AddChar(BYTE ascii,BYTE scan);
/* msdos/int17.c */
extern void WINAPI INT_Int17Handler(CONTEXT86*);
/* msdos/int19.c */
extern void WINAPI INT_Int19Handler(CONTEXT86*);
/* msdos/int1a.c */
extern DWORD INT1A_GetTicksSinceMidnight(void);
extern void WINAPI INT_Int1aHandler(CONTEXT86*);
@ -225,19 +189,12 @@ extern void WINAPI INT_Int25Handler(CONTEXT86*);
/* msdos/int26.c */
extern void WINAPI INT_Int26Handler(CONTEXT86*);
/* msdos/int29.c */
extern void WINAPI INT_Int29Handler(CONTEXT86*);
/* msdos/int2a.c */
extern void WINAPI INT_Int2aHandler(CONTEXT86*);
/* msdos/int2f.c */
extern void WINAPI INT_Int2fHandler(CONTEXT86*);
/* msdos/int33.c */
extern void WINAPI INT_Int33Handler(CONTEXT86*);
extern void WINAPI INT_Int33Message(UINT,WPARAM,LPARAM);
/* msdos/dpmi.c */
typedef void WINAPI (*RMCBPROC)(CONTEXT86*);
extern void WINAPI INT_Int31Handler(CONTEXT86*);
@ -246,12 +203,6 @@ extern FARPROC16 WINAPI DPMI_AllocInternalRMCB(RMCBPROC);
extern void WINAPI DPMI_FreeInternalRMCB(FARPROC16);
extern int DPMI_CallRMProc(CONTEXT86*,LPWORD,int,int);
/* msdos/xms.c */
extern void WINAPI XMS_Handler(CONTEXT86*);
/* misc/aspi.c */
extern void ASPI_DOS_HandleInt(CONTEXT86 *context);
/* misc/ppdev.c */
extern BOOL IO_pp_outp(int port, DWORD* res);

View File

@ -11,7 +11,6 @@
#include "miscemu.h"
#include "callback.h"
#include "options.h"
#include "dosexe.h"
#include "debugtools.h"
static char main_exe_name[MAX_PATH];

View File

@ -6,29 +6,20 @@ VPATH = @srcdir@
MODULE = msdos
C_SRCS = \
devices.c \
dosaspi.c \
dosconf.c \
dosmem.c \
dpmi.c \
xms.c \
int10.c \
int11.c \
int12.c \
int13.c \
int15.c \
int16.c \
int17.c \
int19.c \
int1a.c \
int20.c \
int21.c \
int25.c \
int26.c \
int29.c \
int2a.c \
int2f.c \
int33.c \
int3d.c \
int41.c \
int4b.c \
@ -36,7 +27,6 @@ C_SRCS = \
interrupts.c \
ioports.c \
ppdev.c \
vga.c \
vxd.c
all: $(MODULE).o

View File

@ -22,8 +22,6 @@
#include "global.h"
#include "selectors.h"
#include "miscemu.h"
#include "vga.h"
#include "dosexe.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(dosmem);
@ -76,6 +74,8 @@ WORD DOSMEM_xms_seg;
WORD DOSMEM_dpmi_seg;
WORD DOSMEM_dpmi_sel;
DWORD DOS_LOLSeg;
/***********************************************************************
* DOSMEM_SystemBase
*
@ -225,12 +225,6 @@ BYTE * DOSMEM_BiosSys()
return DOSMEM_dosmem+0xf0000;
}
struct _DOS_LISTOFLISTS * DOSMEM_LOL()
{
return (struct _DOS_LISTOFLISTS *)DOSMEM_MapRealToLinear
(MAKESEGPTR(HIWORD(DOS_LOLSeg),0));
}
/***********************************************************************
* DOSMEM_FillBiosSegments
*
@ -516,7 +510,6 @@ BOOL DOSMEM_Init(BOOL dos_init)
DOSMEM_InitCollateTable();
DOSMEM_InitErrorTable();
DOSMEM_InitDPMI();
DOSDEV_InstallDOSDevices();
already_done = 1;
}
else if (dos_init && !already_mapped)

View File

@ -15,7 +15,6 @@
#include "builtin16.h"
#include "miscemu.h"
#include "msdos.h"
#include "dosexe.h"
#include "task.h"
#include "toolhelp.h"
#include "selectors.h"
@ -30,42 +29,8 @@ void CreateBPB(int drive, BYTE *data, BOOL16 limited); /* defined in int21.c */
static void* lastvalloced = NULL;
/* Structure for real-mode callbacks */
typedef struct
{
DWORD edi;
DWORD esi;
DWORD ebp;
DWORD reserved;
DWORD ebx;
DWORD edx;
DWORD ecx;
DWORD eax;
WORD fl;
WORD es;
WORD ds;
WORD fs;
WORD gs;
WORD ip;
WORD cs;
WORD sp;
WORD ss;
} REALMODECALL;
typedef struct tagRMCB {
DWORD address;
DWORD proc_ofs,proc_sel;
DWORD regs_ofs,regs_sel;
struct tagRMCB *next;
} RMCB;
static RMCB *FirstRMCB = NULL;
static LPDOSTASK WINAPI DPMI_NoCurrent(void) { return NULL; }
DOSVM_TABLE Dosvm = { DPMI_NoCurrent };
DOSVM_TABLE Dosvm = { NULL, };
static HMODULE DosModule;
@ -80,19 +45,19 @@ BOOL DPMI_LoadDosSystem(void)
ERR("could not load winedos.dll, DOS subsystem unavailable\n");
return FALSE;
}
Dosvm.Current = (void *)GetProcAddress(DosModule, "GetCurrent");
Dosvm.LoadDPMI = (void *)GetProcAddress(DosModule, "LoadDPMI");
Dosvm.LoadDosExe = (void *)GetProcAddress(DosModule, "LoadDosExe");
Dosvm.Exec = (void *)GetProcAddress(DosModule, "Exec");
Dosvm.Exit = (void *)GetProcAddress(DosModule, "Exit");
Dosvm.Enter = (void *)GetProcAddress(DosModule, "Enter");
Dosvm.RunInThread = (void *)GetProcAddress(DosModule, "RunInThread");
Dosvm.Wait = (void *)GetProcAddress(DosModule, "Wait");
Dosvm.QueueEvent = (void *)GetProcAddress(DosModule, "QueueEvent");
Dosvm.OutPIC = (void *)GetProcAddress(DosModule, "OutPIC");
Dosvm.SetTimer = (void *)GetProcAddress(DosModule, "SetTimer");
Dosvm.GetTimer = (void *)GetProcAddress(DosModule, "GetTimer");
Dosvm.KbdReadScan = (void *)GetProcAddress(DosModule, "KbdReadScan");
#define GET_ADDR(func) Dosvm.func = (void *)GetProcAddress(DosModule, #func);
GET_ADDR(LoadDosExe);
GET_ADDR(CallRMInt);
GET_ADDR(CallRMProc);
GET_ADDR(AllocRMCB);
GET_ADDR(FreeRMCB);
GET_ADDR(SetTimer);
GET_ADDR(GetTimer);
GET_ADDR(inport);
GET_ADDR(outport);
GET_ADDR(ASPIHandler);
#undef GET_ADDR
return TRUE;
}
@ -167,552 +132,52 @@ DPMI_xrealloc(LPVOID ptr,DWORD newsize) {
}
return newptr;
}
/**********************************************************************
* INT_GetRealModeContext
*/
static void INT_GetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
{
context->Eax = call->eax;
context->Ebx = call->ebx;
context->Ecx = call->ecx;
context->Edx = call->edx;
context->Esi = call->esi;
context->Edi = call->edi;
context->Ebp = call->ebp;
context->EFlags = call->fl | V86_FLAG;
context->Eip = call->ip;
context->Esp = call->sp;
context->SegCs = call->cs;
context->SegDs = call->ds;
context->SegEs = call->es;
context->SegFs = call->fs;
context->SegGs = call->gs;
context->SegSs = call->ss;
}
/**********************************************************************
* INT_SetRealModeContext
*/
static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
{
call->eax = context->Eax;
call->ebx = context->Ebx;
call->ecx = context->Ecx;
call->edx = context->Edx;
call->esi = context->Esi;
call->edi = context->Edi;
call->ebp = context->Ebp;
call->fl = LOWORD(context->EFlags);
call->ip = LOWORD(context->Eip);
call->sp = LOWORD(context->Esp);
call->cs = context->SegCs;
call->ds = context->SegDs;
call->es = context->SegEs;
call->fs = context->SegFs;
call->gs = context->SegGs;
call->ss = context->SegSs;
}
#ifdef __i386__
void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi)
#if 0 /* original code, which early gccs puke on */
{
int _clobber;
__asm__ __volatile__(
"pushl %%ebp\n"
"pushl %%ebx\n"
"pushl %%es\n"
"pushl %%ds\n"
"pushfl\n"
"mov %7,%%es\n"
"mov %5,%%ds\n"
".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */
"popl %%ds\n"
"mov %%es,%0\n"
"popl %%es\n"
"popl %%ebx\n"
"popl %%ebp\n"
: "=d" (*es), "=D" (*edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber)
: "0" (ss), "2" (esp),
"4" (rmcb->regs_sel), "1" (rmcb->regs_ofs),
"3" (&rmcb->proc_ofs) );
}
#else /* code generated by a gcc new enough */
;
__ASM_GLOBAL_FUNC(DPMI_CallRMCB32,
"pushl %ebp\n\t"
"movl %esp,%ebp\n\t"
"pushl %edi\n\t"
"pushl %esi\n\t"
"movl 0x8(%ebp),%eax\n\t"
"movl 0x10(%ebp),%esi\n\t"
"movl 0xc(%ebp),%edx\n\t"
"movl 0x10(%eax),%ecx\n\t"
"movl 0xc(%eax),%edi\n\t"
"addl $0x4,%eax\n\t"
"pushl %ebp\n\t"
"pushl %ebx\n\t"
"pushl %es\n\t"
"pushl %ds\n\t"
"pushfl\n\t"
"mov %cx,%es\n\t"
"mov %dx,%ds\n\t"
".byte 0x36, 0xff, 0x18\n\t" /* lcall *%ss:(%eax) */
"popl %ds\n\t"
"mov %es,%dx\n\t"
"popl %es\n\t"
"popl %ebx\n\t"
"popl %ebp\n\t"
"movl 0x14(%ebp),%eax\n\t"
"movw %dx,(%eax)\n\t"
"movl 0x18(%ebp),%edx\n\t"
"movl %edi,(%edx)\n\t"
"popl %esi\n\t"
"popl %edi\n\t"
"leave\n\t"
"ret")
#endif
#endif /* __i386__ */
/**********************************************************************
* DPMI_CallRMCBProc
*
* This routine does the hard work of calling a callback procedure.
*/
static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
{
if (IS_SELECTOR_SYSTEM( rmcb->proc_sel )) {
/* Wine-internal RMCB, call directly */
((RMCBPROC)rmcb->proc_ofs)(context);
} else {
#ifdef __i386__
UINT16 ss,es;
DWORD esp,edi;
INT_SetRealModeContext(MapSL(MAKESEGPTR( rmcb->regs_sel, rmcb->regs_ofs )), context);
ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, WINE_LDT_FLAGS_DATA );
esp = context->Esp;
FIXME("untested!\n");
/* The called proc ends with an IRET, and takes these parameters:
* DS:ESI = pointer to real-mode SS:SP
* ES:EDI = pointer to real-mode call structure
* It returns:
* ES:EDI = pointer to real-mode call structure (may be a copy)
* It is the proc's responsibility to change the return CS:IP in the
* real-mode call structure. */
if (flag & 1) {
/* 32-bit DPMI client */
DPMI_CallRMCB32(rmcb, ss, esp, &es, &edi);
} else {
/* 16-bit DPMI client */
CONTEXT86 ctx = *context;
ctx.SegCs = rmcb->proc_sel;
ctx.Eip = rmcb->proc_ofs;
ctx.SegDs = ss;
ctx.Esi = esp;
ctx.SegEs = rmcb->regs_sel;
ctx.Edi = rmcb->regs_ofs;
/* FIXME: I'm pretty sure this isn't right - should push flags first */
wine_call_to_16_regs_short(&ctx, 0);
es = ctx.SegEs;
edi = ctx.Edi;
}
FreeSelector16(ss);
INT_GetRealModeContext( MapSL( MAKESEGPTR( es, edi )), context);
#else
ERR("RMCBs only implemented for i386\n");
#endif
}
}
/**********************************************************************
* DPMI_CallRMProc
*
* This routine does the hard work of calling a real mode procedure.
*/
int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret )
{
LPWORD stack16;
LPVOID addr = NULL; /* avoid gcc warning */
LPDOSTASK lpDosTask = Dosvm.Current();
RMCB *CurrRMCB;
int alloc = 0, already = 0;
BYTE *code;
TRACE("EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
context->Eax, context->Ebx, context->Ecx, context->Edx );
TRACE("ESI=%08lx EDI=%08lx ES=%04lx DS=%04lx CS:IP=%04lx:%04x, %d WORD arguments, %s\n",
context->Esi, context->Edi, context->SegEs, context->SegDs,
context->SegCs, LOWORD(context->Eip), args, iret?"IRET":"FAR" );
callrmproc_again:
/* there might be some code that just jumps to RMCBs or the like,
in which case following the jumps here might get us to a shortcut */
code = CTX_SEG_OFF_TO_LIN(context, context->SegCs, context->Eip);
switch (*code) {
case 0xe9: /* JMP NEAR */
context->Eip += 3 + *(WORD *)(code+1);
/* yeah, I know these gotos don't look good... */
goto callrmproc_again;
case 0xea: /* JMP FAR */
context->Eip = *(WORD *)(code+1);
context->SegCs = *(WORD *)(code+3);
/* ...but since the label is there anyway... */
goto callrmproc_again;
case 0xeb: /* JMP SHORT */
context->Eip += 2 + *(signed char *)(code+1);
/* ...because of other gotos below, so... */
goto callrmproc_again;
}
/* shortcut for chaining to internal interrupt handlers */
if ((context->SegCs == 0xF000) && iret) {
return INT_RealModeInterrupt( LOWORD(context->Eip)/4, context);
}
/* shortcut for RMCBs */
CurrRMCB = FirstRMCB;
while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
CurrRMCB = CurrRMCB->next;
if (!(CurrRMCB || lpDosTask)) {
FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
TRACE("creating VM86 task\n");
if ((!DPMI_LoadDosSystem()) || !(lpDosTask = Dosvm.LoadDPMI() )) {
ERR("could not setup VM86 task\n");
return 1;
}
}
if (!already) {
if (!context->SegSs) {
alloc = 1; /* allocate default stack */
stack16 = addr = DOSMEM_GetBlock( 64, (UINT16 *)&(context->SegSs) );
context->Esp = 64-2;
stack16 += 32-1;
if (!addr) {
ERR("could not allocate default stack\n");
return 1;
}
} else {
stack16 = CTX_SEG_OFF_TO_LIN(context, context->SegSs, context->Esp);
}
context->Esp -= (args + (iret?1:0)) * sizeof(WORD);
stack16 -= args;
if (args) memcpy(stack16, stack, args*sizeof(WORD) );
/* push flags if iret */
if (iret) {
stack16--; args++;
*stack16 = LOWORD(context->EFlags);
}
/* push return address (return to interrupt wrapper) */
*(--stack16) = DOSMEM_wrap_seg;
*(--stack16) = 0;
/* adjust stack */
context->Esp -= 2*sizeof(WORD);
already = 1;
}
if (CurrRMCB) {
/* RMCB call, invoke protected-mode handler directly */
DPMI_CallRMCBProc(context, CurrRMCB, lpDosTask ? lpDosTask->dpmi_flag : 0);
/* check if we returned to where we thought we would */
if ((context->SegCs != DOSMEM_wrap_seg) ||
(LOWORD(context->Eip) != 0)) {
/* we need to continue at different address in real-mode space,
so we need to set it all up for real mode again */
goto callrmproc_again;
}
} else {
TRACE("entering real mode...\n");
Dosvm.Enter( context );
TRACE("returned from real-mode call\n");
}
if (alloc) DOSMEM_FreeBlock( addr );
return 0;
}
/**********************************************************************
* CallRMInt
*/
static void CallRMInt( CONTEXT86 *context )
{
CONTEXT86 realmode_ctx;
FARPROC16 rm_int = INT_GetRMHandler( BL_reg(context) );
REALMODECALL *call = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) ));
INT_GetRealModeContext( call, &realmode_ctx );
/* we need to check if a real-mode program has hooked the interrupt */
if (HIWORD(rm_int)!=0xF000) {
/* yup, which means we need to switch to real mode... */
realmode_ctx.SegCs = HIWORD(rm_int);
realmode_ctx.Eip = LOWORD(rm_int);
if (DPMI_CallRMProc( &realmode_ctx, NULL, 0, TRUE))
SET_CFLAG(context);
} else {
RESET_CFLAG(context);
/* use the IP we have instead of BL_reg, in case some apps
decide to move interrupts around for whatever reason... */
if (INT_RealModeInterrupt( LOWORD(rm_int)/4, &realmode_ctx ))
SET_CFLAG(context);
if (context->EFlags & 1) {
FIXME("%02x: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
BL_reg(context), realmode_ctx.Eax, realmode_ctx.Ebx,
realmode_ctx.Ecx, realmode_ctx.Edx);
FIXME(" ESI=%08lx EDI=%08lx DS=%04lx ES=%04lx\n",
realmode_ctx.Esi, realmode_ctx.Edi,
realmode_ctx.SegDs, realmode_ctx.SegEs );
if (!Dosvm.CallRMInt && !DPMI_LoadDosSystem())
{
ERR("could not setup real-mode calls\n");
return;
}
}
INT_SetRealModeContext( call, &realmode_ctx );
Dosvm.CallRMInt( context );
}
static void CallRMProc( CONTEXT86 *context, int iret )
{
REALMODECALL *p = MapSL( MAKESEGPTR( context->SegEs, DI_reg(context) ));
CONTEXT86 context16;
TRACE("RealModeCall: EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n",
p->eax, p->ebx, p->ecx, p->edx);
TRACE(" ESI=%08lx EDI=%08lx ES=%04x DS=%04x CS:IP=%04x:%04x, %d WORD arguments, %s\n",
p->esi, p->edi, p->es, p->ds, p->cs, p->ip, CX_reg(context), iret?"IRET":"FAR" );
if (!(p->cs) && !(p->ip)) { /* remove this check
if Int21/6501 case map function
has been implemented */
SET_CFLAG(context);
if (!Dosvm.CallRMProc && !DPMI_LoadDosSystem())
{
ERR("could not setup real-mode calls\n");
return;
}
INT_GetRealModeContext(p, &context16);
DPMI_CallRMProc( &context16, ((LPWORD)MapSL(MAKESEGPTR(context->SegSs, LOWORD(context->Esp))))+3,
CX_reg(context), iret );
INT_SetRealModeContext(p, &context16);
Dosvm.CallRMProc( context, iret );
}
static RMCB *DPMI_AllocRMCB( void )
{
RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB));
UINT16 uParagraph;
if (NewRMCB)
{
LPVOID RMCBmem = DOSMEM_GetBlock(4, &uParagraph);
LPBYTE p = RMCBmem;
*p++ = 0xcd; /* RMCB: */
*p++ = 0x31; /* int $0x31 */
/* it is the called procedure's task to change the return CS:EIP
the DPMI 0.9 spec states that if it doesn't, it will be called again */
*p++ = 0xeb;
*p++ = 0xfc; /* jmp RMCB */
NewRMCB->address = MAKELONG(0, uParagraph);
NewRMCB->next = FirstRMCB;
FirstRMCB = NewRMCB;
}
return NewRMCB;
}
static void AllocRMCB( CONTEXT86 *context )
{
RMCB *NewRMCB = DPMI_AllocRMCB();
TRACE("Function to call: %04x:%04x\n", (WORD)context->SegDs, SI_reg(context) );
if (NewRMCB)
if (!Dosvm.AllocRMCB && !DPMI_LoadDosSystem())
{
/* FIXME: if 32-bit DPMI client, use ESI and EDI */
NewRMCB->proc_ofs = LOWORD(context->Esi);
NewRMCB->proc_sel = context->SegDs;
NewRMCB->regs_ofs = LOWORD(context->Edi);
NewRMCB->regs_sel = context->SegEs;
SET_LOWORD( context->Ecx, HIWORD(NewRMCB->address) );
SET_LOWORD( context->Edx, LOWORD(NewRMCB->address) );
ERR("could not setup real-mode calls\n");
return;
}
else
{
SET_LOWORD( context->Eax, 0x8015 ); /* callback unavailable */
SET_CFLAG(context);
Dosvm.AllocRMCB( context );
}
}
FARPROC16 WINAPI DPMI_AllocInternalRMCB( RMCBPROC proc )
{
RMCB *NewRMCB = DPMI_AllocRMCB();
if (NewRMCB) {
NewRMCB->proc_ofs = (DWORD)proc;
NewRMCB->proc_sel = 0;
NewRMCB->regs_ofs = 0;
NewRMCB->regs_sel = 0;
return (FARPROC16)(NewRMCB->address);
}
return NULL;
}
static int DPMI_FreeRMCB( DWORD address )
{
RMCB *CurrRMCB = FirstRMCB;
RMCB *PrevRMCB = NULL;
while (CurrRMCB && (CurrRMCB->address != address))
{
PrevRMCB = CurrRMCB;
CurrRMCB = CurrRMCB->next;
}
if (CurrRMCB)
{
if (PrevRMCB)
PrevRMCB->next = CurrRMCB->next;
else
FirstRMCB = CurrRMCB->next;
DOSMEM_FreeBlock(DOSMEM_MapRealToLinear(CurrRMCB->address));
HeapFree(GetProcessHeap(), 0, CurrRMCB);
return 0;
}
return 1;
}
static void FreeRMCB( CONTEXT86 *context )
{
FIXME("callback address: %04x:%04x\n",
CX_reg(context), DX_reg(context));
if (DPMI_FreeRMCB(MAKELONG(DX_reg(context), CX_reg(context)))) {
if (!Dosvm.FreeRMCB) /* cannot have allocated one if dosvm not loaded */
{
SET_LOWORD( context->Eax, 0x8024 ); /* invalid callback address */
SET_CFLAG( context );
}
else Dosvm.FreeRMCB( context );
}
void WINAPI DPMI_FreeInternalRMCB( FARPROC16 proc )
{
DPMI_FreeRMCB( (DWORD)proc );
}
/* (see dosmem.c, function DOSMEM_InitDPMI) */
static void StartPM( CONTEXT86 *context, LPDOSTASK lpDosTask )
{
UINT16 cs, ss, ds, es;
CONTEXT86 pm_ctx;
DWORD psp_ofs = (DWORD)(lpDosTask->psp_seg<<4);
PDB16 *psp = (PDB16 *)psp_ofs;
HANDLE16 env_seg = psp->environment;
unsigned char selflags = WINE_LDT_FLAGS_DATA;
RESET_CFLAG(context);
lpDosTask->dpmi_flag = AX_reg(context);
/* our mode switch wrapper have placed the desired CS into DX */
cs = SELECTOR_AllocBlock( (void *)(DX_reg(context)<<4), 0x10000, WINE_LDT_FLAGS_CODE );
/* due to a flaw in some CPUs (at least mine), it is best to mark stack segments as 32-bit if they
can be used in 32-bit code. Otherwise, these CPUs may not set the high word of esp during a
ring transition (from kernel code) to the 16-bit stack, and this causes trouble if executing
32-bit code using this stack. */
if (lpDosTask->dpmi_flag & 1) selflags |= WINE_LDT_FLAGS_32BIT;
ss = SELECTOR_AllocBlock( (void *)(context->SegSs<<4), 0x10000, selflags );
/* do the same for the data segments, just in case */
if (context->SegDs == context->SegSs) ds = ss;
else ds = SELECTOR_AllocBlock( (void *)(context->SegDs<<4), 0x10000, selflags );
es = SELECTOR_AllocBlock( psp, 0x100, selflags );
/* convert environment pointer, as the spec says, but we're a bit lazy about the size here... */
psp->environment = SELECTOR_AllocBlock( (void *)(env_seg<<4), 0x10000, WINE_LDT_FLAGS_DATA );
pm_ctx = *context;
pm_ctx.SegCs = DOSMEM_dpmi_sel;
/* our mode switch wrapper expects the new CS in DX, and the new SS in AX */
pm_ctx.Eax = ss;
pm_ctx.Edx = cs;
pm_ctx.SegDs = ds;
pm_ctx.SegEs = es;
pm_ctx.SegFs = 0;
pm_ctx.SegGs = 0;
TRACE("DOS program is now entering protected mode\n");
wine_call_to_16_regs_short(&pm_ctx, 0);
/* in the current state of affairs, we won't ever actually return here... */
/* we should have int21/ah=4c do it someday, though... */
FreeSelector16(psp->environment);
psp->environment = env_seg;
FreeSelector16(es);
if (ds != ss) FreeSelector16(ds);
FreeSelector16(ss);
FreeSelector16(cs);
}
/* DPMI Raw Mode Switch handler */
#if 0
void WINAPI DPMI_RawModeSwitch( SIGCONTEXT *context )
{
LPDOSTASK lpDosTask = Dosvm.Current();
CONTEXT86 rm_ctx;
int ret;
if (!lpDosTask) {
/* we could probably start a DPMI-only dosmod task here, but I doubt
anything other than real DOS apps want to call raw mode switch */
ERR("attempting raw mode switch without DOS task!\n");
ExitProcess(1);
}
/* initialize real-mode context as per spec */
memset(&rm_ctx, 0, sizeof(rm_ctx));
rm_ctx.SegDs = AX_sig(context);
rm_ctx.SegEs = CX_sig(context);
rm_ctx.SegSs = DX_sig(context);
rm_ctx.Esp = EBX_sig(context);
rm_ctx.SegCs = SI_sig(context);
rm_ctx.Eip = EDI_sig(context);
rm_ctx.Ebp = EBP_sig(context);
rm_ctx.SegFs = 0;
rm_ctx.SegGs = 0;
rm_ctx.EFlags = EFL_sig(context); /* at least we need the IF flag */
/* enter real mode again */
TRACE("re-entering real mode at %04lx:%04lx\n",rm_ctx.SegCs,rm_ctx.Eip);
ret = Dosvm.Enter( &rm_ctx );
/* when the real-mode stuff call its mode switch address,
Dosvm.Enter will return and we will continue here */
if (ret<0) {
/* if the sync was lost, there's no way to recover */
ExitProcess(1);
}
/* alter protected-mode context as per spec */
DS_sig(context) = LOWORD(rm_ctx.Eax);
ES_sig(context) = LOWORD(rm_ctx.Ecx);
SS_sig(context) = LOWORD(rm_ctx.Edx);
ESP_sig(context) = rm_ctx.Ebx;
CS_sig(context) = LOWORD(rm_ctx.Esi);
EIP_sig(context) = rm_ctx.Edi;
EBP_sig(context) = rm_ctx.Ebp;
FS_sig(context) = 0;
GS_sig(context) = 0;
/* Return to new address and hope that we didn't mess up */
TRACE("re-entering protected mode at %04x:%08lx\n",
CS_sig(context), EIP_sig(context));
}
#endif
/**********************************************************************
* INT_Int31Handler (WPROCS.149)
*
@ -729,36 +194,6 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
DWORD dw;
BYTE *ptr;
LPDOSTASK lpDosTask = Dosvm.Current();
if (ISV86(context) && lpDosTask) {
/* Called from real mode, check if it's our wrapper */
TRACE("called from real mode\n");
if (context->SegCs==DOSMEM_dpmi_seg) {
/* This is the protected mode switch */
StartPM(context,lpDosTask);
return;
} else
if (context->SegCs==DOSMEM_xms_seg) {
/* This is the XMS driver entry point */
XMS_Handler(context);
return;
} else
{
/* Check for RMCB */
RMCB *CurrRMCB = FirstRMCB;
while (CurrRMCB && (HIWORD(CurrRMCB->address) != context->SegCs))
CurrRMCB = CurrRMCB->next;
if (CurrRMCB) {
/* RMCB call, propagate to protected-mode handler */
DPMI_CallRMCBProc(context, CurrRMCB, lpDosTask->dpmi_flag);
return;
}
}
}
RESET_CFLAG(context);
switch(AX_reg(context))
{
@ -851,8 +286,8 @@ void WINAPI INT_Int31Handler( CONTEXT86 *context )
W32S_APP2WINE(MAKELONG(DX_reg(context),CX_reg(context))));
dw = W32S_APP2WINE(MAKELONG(DX_reg(context), CX_reg(context)));
if (dw < 0x10000)
/* app wants to access lower 64K of DOS memory, map it in now */
DOSMEM_Init(TRUE);
/* app wants to access lower 64K of DOS memory, load DOS subsystem */
DPMI_LoadDosSystem();
SetSelectorBase(BX_reg(context), dw);
break;

View File

@ -5,9 +5,6 @@
#include <stdlib.h>
#include "winbase.h"
#include "miscemu.h"
/* #define DEBUG_INT */
#include "debugtools.h"
#include "callback.h"
/**********************************************************************
* INT_Int20Handler (WPROCS.132)
@ -16,6 +13,5 @@
*/
void WINAPI INT_Int20Handler( CONTEXT86 *context )
{
if (Dosvm.Exit) Dosvm.Exit( context, TRUE, 0 );
else ExitThread( 0 );
ExitThread( 0 );
}

View File

@ -26,12 +26,11 @@
#include "winerror.h"
#include "drive.h"
#include "file.h"
#include "callback.h"
#include "msdos.h"
#include "options.h"
#include "miscemu.h"
#include "task.h"
#include "dosexe.h"
#include "callback.h"
#include "debugtools.h"
#include "console.h"
@ -111,6 +110,13 @@ static WORD DosHeapHandle;
extern char TempDirectory[];
static void INT21_ReadConfigSys(void)
{
static int done;
if (!done) DOSCONF_ReadConfig();
done = 1;
}
static BOOL INT21_CreateHeap(void)
{
if (!(DosHeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct DosHeap))))
@ -944,32 +950,15 @@ INT21_networkfunc (CONTEXT86 *context)
}
}
static void INT21_SetCurrentPSP(WORD psp)
{
LPDOSTASK lpDosTask = Dosvm.Current();
if (lpDosTask)
lpDosTask->psp_seg = psp;
else
ERR("Cannot change PSP for non-DOS task!\n");
}
static WORD INT21_GetCurrentPSP(void)
static void ASPI_DOS_HandleInt( CONTEXT86 *context )
{
LPDOSTASK lpDosTask = Dosvm.Current();
if (lpDosTask)
return lpDosTask->psp_seg;
else
return GetCurrentPDB16();
if (!Dosvm.ASPIHandler && !DPMI_LoadDosSystem())
{
ERR("could not setup ASPI handler\n");
return;
}
static WORD INT21_GetReturnCode(void)
{
LPDOSTASK lpDosTask = Dosvm.Current();
if (lpDosTask) {
WORD ret = lpDosTask->retval;
lpDosTask->retval = 0;
return ret;
} else return 0;
Dosvm.ASPIHandler( context );
}
/***********************************************************************
@ -1125,9 +1114,15 @@ void WINAPI DOS3Call( CONTEXT86 *context )
switch(AH_reg(context))
{
case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
case 0x03: /* READ CHARACTER FROM STDAUX */
case 0x04: /* WRITE CHARACTER TO STDAUX */
case 0x05: /* WRITE CHARACTER TO PRINTER */
case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
case 0x0b: /* GET STDIN STATUS */
case 0x0f: /* OPEN FILE USING FCB */
case 0x10: /* CLOSE FILE USING FCB */
case 0x14: /* SEQUENTIAL READ FROM FCB FILE */
@ -1140,68 +1135,14 @@ void WINAPI DOS3Call( CONTEXT86 *context )
case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
case 0x4d: /* GET RETURN CODE */
case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
INT_BARF( context, 0x21 );
break;
case 0x00: /* TERMINATE PROGRAM */
TRACE("TERMINATE PROGRAM\n");
if (Dosvm.Exit) Dosvm.Exit( context, FALSE, 0 );
else ExitThread( 0 );
break;
case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
TRACE("DIRECT CHARACTER INPUT WITH ECHO\n");
AL_reg(context) = CONSOLE_GetCharacter();
/* FIXME: no echo */
break;
case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
TRACE("Write Character to Standard Output\n");
CONSOLE_Write(DL_reg(context), 0, 0, 0);
break;
case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
/* FIXME: Use DOSDEV_Peek/Read/Write(DOSDEV_Console(),...) !! */
if (DL_reg(context) == 0xff) {
static char scan = 0;
TRACE("Direct Console Input\n");
if (scan) {
/* return pending scancode */
AL_reg(context) = scan;
RESET_ZFLAG(context);
scan = 0;
} else {
char ascii;
if (INT_Int16ReadChar(&ascii,&scan,TRUE)) {
INT_Int16ReadChar(&ascii,&scan,FALSE);
/* return ASCII code */
AL_reg(context) = ascii;
RESET_ZFLAG(context);
/* return scan code on next call only if ascii==0 */
if (ascii) scan = 0;
} else {
/* nothing pending, clear everything */
AL_reg(context) = 0;
SET_ZFLAG(context);
scan = 0; /* just in case */
}
}
} else {
TRACE("Direct Console Output\n");
CONSOLE_Write(DL_reg(context), 0, 0, 0);
}
break;
case 0x07: /* DIRECT CHARACTER INPUT WITHOUT ECHO */
/* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
TRACE("DIRECT CHARACTER INPUT WITHOUT ECHO\n");
INT_Int16ReadChar(&AL_reg(context), NULL, FALSE);
break;
case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
/* FIXME: Use DOSDEV_Peek/Read(DOSDEV_Console(),...) !! */
TRACE("CHARACTER INPUT WITHOUT ECHO\n");
INT_Int16ReadChar(&AL_reg(context), NULL, FALSE);
ExitThread( 0 );
break;
case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
@ -1235,15 +1176,6 @@ void WINAPI DOS3Call( CONTEXT86 *context )
break;
}
case 0x0b: {/* GET STDIN STATUS */
char x1,x2;
if (CONSOLE_CheckForKeystroke(&x1,&x2))
AL_reg(context) = 0xff;
else
AL_reg(context) = 0;
break;
}
case 0x2e: /* SET VERIFY FLAG */
TRACE("SET VERIFY FLAG ignored\n");
/* we cannot change the behaviour anyway, so just ignore it */
@ -1320,8 +1252,7 @@ void WINAPI DOS3Call( CONTEXT86 *context )
break;
case 0x25: /* SET INTERRUPT VECTOR */
INT_CtxSetHandler( context, AL_reg(context),
(FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
INT_SetPMHandler( AL_reg(context), (FARPROC16)MAKESEGPTR( context->SegDs, DX_reg(context)));
break;
case 0x29: /* PARSE FILENAME INTO FCB */
@ -1387,16 +1318,19 @@ void WINAPI DOS3Call( CONTEXT86 *context )
{
case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
TRACE("GET CURRENT EXTENDED BREAK STATE\n");
INT21_ReadConfigSys();
DL_reg(context) = DOSCONF_config.brk_flag;
break;
case 0x01: /* SET EXTENDED BREAK STATE */
TRACE("SET CURRENT EXTENDED BREAK STATE\n");
INT21_ReadConfigSys();
DOSCONF_config.brk_flag = (DL_reg(context) > 0);
break;
case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE*/
TRACE("GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE\n");
INT21_ReadConfigSys();
/* ugly coding in order to stay reentrant */
if (DL_reg(context))
{
@ -1439,7 +1373,7 @@ void WINAPI DOS3Call( CONTEXT86 *context )
case 0x35: /* GET INTERRUPT VECTOR */
TRACE("GET INTERRUPT VECTOR 0x%02x\n",AL_reg(context));
{
FARPROC16 addr = INT_CtxGetHandler( context, AL_reg(context) );
FARPROC16 addr = INT_GetPMHandler( AL_reg(context) );
context->SegEs = SELECTOROF(addr);
BX_reg(context) = OFFSETOF(addr);
}
@ -1691,21 +1625,6 @@ void WINAPI DOS3Call( CONTEXT86 *context )
DX_reg(context) = 0;
break;
case 0x0b: /* SET SHARING RETRY COUNT */
TRACE("IOCTL - SET SHARING RETRY COUNT pause %d retries %d\n",
CX_reg(context), DX_reg(context));
if (!CX_reg(context))
{
AX_reg(context) = 1;
SET_CFLAG(context);
break;
}
DOSMEM_LOL()->sharing_retry_delay = CX_reg(context);
if (!DX_reg(context))
DOSMEM_LOL()->sharing_retry_count = DX_reg(context);
RESET_CFLAG(context);
break;
case 0x0d:
TRACE("IOCTL - GENERIC BLOCK DEVICE REQUEST %s\n",
INT21_DriveName( BL_reg(context)));
@ -1842,29 +1761,15 @@ void WINAPI DOS3Call( CONTEXT86 *context )
break;
case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
TRACE("EXEC %s\n",
(LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
if (ISV86(context)) {
if (!Dosvm.Exec( context, CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx),
AL_reg(context), CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Ebx) ))
bSetDOSExtendedError = TRUE;
} else {
AX_reg(context) = WinExec16( CTX_SEG_OFF_TO_LIN(context, context->SegDs,
context->Edx ),
TRACE("EXEC %s\n", (LPCSTR)CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ));
AX_reg(context) = WinExec16( CTX_SEG_OFF_TO_LIN(context, context->SegDs, context->Edx ),
SW_NORMAL );
if (AX_reg(context) < 32) SET_CFLAG(context);
}
break;
case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
TRACE("EXIT with return code %d\n",AL_reg(context));
if (Dosvm.Exit) Dosvm.Exit( context, FALSE, AL_reg(context) );
else ExitThread( AL_reg(context) );
break;
case 0x4d: /* GET RETURN CODE */
TRACE("GET RETURN CODE (ERRORLEVEL)\n");
AX_reg(context) = INT21_GetReturnCode();
ExitThread( AL_reg(context) );
break;
case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
@ -1883,27 +1788,22 @@ void WINAPI DOS3Call( CONTEXT86 *context )
}
else AX_reg(context) = 0; /* OK */
break;
case 0x50: /* SET CURRENT PROCESS ID (SET PSP ADDRESS) */
TRACE("SET CURRENT PROCESS ID (SET PSP ADDRESS)\n");
INT21_SetCurrentPSP(BX_reg(context));
break;
case 0x51: /* GET PSP ADDRESS */
TRACE("GET CURRENT PROCESS ID (GET PSP ADDRESS)\n");
/* FIXME: should we return the original DOS PSP upon */
/* Windows startup ? */
BX_reg(context) = INT21_GetCurrentPSP();
BX_reg(context) = GetCurrentPDB16();
break;
case 0x62: /* GET PSP ADDRESS */
TRACE("GET CURRENT PSP ADDRESS\n");
/* FIXME: should we return the original DOS PSP upon */
/* Windows startup ? */
BX_reg(context) = INT21_GetCurrentPSP();
BX_reg(context) = GetCurrentPDB16();
break;
case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
TRACE("SYSVARS - GET LIST OF LISTS\n");
{
context->SegEs = ISV86(context) ? HIWORD(DOS_LOLSeg) : LOWORD(DOS_LOLSeg);
context->SegEs = LOWORD(DOS_LOLSeg);
BX_reg(context) = FIELD_OFFSET(DOS_LISTOFLISTS, ptr_first_DPB);
}
break;

View File

@ -11,7 +11,6 @@
#include <string.h>
#include "wine/winbase16.h"
#include "dosexe.h"
#include "miscemu.h"
#include "module.h"
/* #define DEBUG_INT */

View File

@ -14,17 +14,6 @@
DEFAULT_DEBUG_CHANNEL(int);
static INTPROC INT_WineHandler[256] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
INT_Int10Handler, INT_Int11Handler, INT_Int12Handler, INT_Int13Handler,
0, INT_Int15Handler, INT_Int16Handler, INT_Int17Handler,
0, 0, INT_Int1aHandler, 0, 0, 0, 0, 0,
INT_Int20Handler, DOS3Call, 0, 0, 0, INT_Int25Handler, 0, 0,
0, INT_Int29Handler, INT_Int2aHandler, 0, 0, 0, 0, INT_Int2fHandler,
0, INT_Int31Handler, 0, INT_Int33Handler
};
static FARPROC16 INT_Vectors[256];
/* Ordinal number for interrupt 0 handler in WPROCS.DLL */
@ -73,97 +62,6 @@ void INT_SetPMHandler( BYTE intnum, FARPROC16 handler )
}
/**********************************************************************
* INT_GetRMHandler
*
* Return the real mode interrupt vector for a given interrupt.
*/
FARPROC16 INT_GetRMHandler( BYTE intnum )
{
return ((FARPROC16*)DOSMEM_SystemBase())[intnum];
}
/**********************************************************************
* INT_SetRMHandler
*
* Set the real mode interrupt handler for a given interrupt.
*/
void INT_SetRMHandler( BYTE intnum, FARPROC16 handler )
{
TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n",
intnum, HIWORD(handler), LOWORD(handler) );
((FARPROC16*)DOSMEM_SystemBase())[intnum] = handler;
}
/**********************************************************************
* INT_CtxGetHandler
*
* Return the interrupt vector for a given interrupt.
*/
FARPROC16 INT_CtxGetHandler( CONTEXT86 *context, BYTE intnum )
{
if (ISV86(context))
return INT_GetRMHandler(intnum);
else
return INT_GetPMHandler(intnum);
}
/**********************************************************************
* INT_CtxSetHandler
*
* Set the interrupt handler for a given interrupt.
*/
void INT_CtxSetHandler( CONTEXT86 *context, BYTE intnum, FARPROC16 handler )
{
if (ISV86(context))
INT_SetRMHandler(intnum, handler);
else
INT_SetPMHandler(intnum, handler);
}
/**********************************************************************
* INT_GetWineHandler
*
* Return the Wine interrupt handler for a given interrupt.
*/
INTPROC INT_GetWineHandler( BYTE intnum )
{
return INT_WineHandler[intnum];
}
/**********************************************************************
* INT_SetWineHandler
*
* Set the Wine interrupt handler for a given interrupt.
*/
void INT_SetWineHandler( BYTE intnum, INTPROC handler )
{
TRACE("Set Wine interrupt vector %02x <- %p\n", intnum, handler );
INT_WineHandler[intnum] = handler;
}
/**********************************************************************
* INT_RealModeInterrupt
*
* Handle real mode interrupts
*/
int INT_RealModeInterrupt( BYTE intnum, CONTEXT86 *context )
{
if (INT_WineHandler[intnum]) {
(*INT_WineHandler[intnum])(context);
return 0;
}
FIXME("Unknown Interrupt in DOS mode: 0x%x\n", intnum);
return 1;
}
/**********************************************************************
* INT_DefaultHandler (WPROCS.356)
*

View File

@ -20,9 +20,7 @@
#include <time.h>
#include <unistd.h>
#include "windef.h"
#include "vga.h"
#include "callback.h"
#include "dosexe.h"
#include "options.h"
#include "miscemu.h"
#include "debugtools.h"
@ -98,8 +96,7 @@ static void set_timer_maxval(unsigned timer, unsigned maxval)
{
switch (timer) {
case 0: /* System timer counter divisor */
if (Dosvm.Current())
Dosvm.SetTimer(maxval);
if (Dosvm.SetTimer) Dosvm.SetTimer(maxval);
break;
case 1: /* RAM refresh */
FIXME("RAM refresh counter handling not implemented !\n");
@ -292,6 +289,9 @@ DWORD IO_inport( int port, int size )
}
#endif
/* first give the DOS VM a chance to handle it */
if (Dosvm.inport && Dosvm.inport( port, size, &res )) return res;
switch (port)
{
case 0x40:
@ -308,7 +308,7 @@ DWORD IO_inport( int port, int size )
if (chan == 0) /* System timer counter divisor */
{
/* FIXME: Dosvm.GetTimer() returns quite rigid values */
if (Dosvm.Current())
if (Dosvm.GetTimer)
tempval = dummy_ctr + (WORD)Dosvm.GetTimer();
else
tempval = dummy_ctr;
@ -345,7 +345,6 @@ DWORD IO_inport( int port, int size )
}
break;
case 0x60:
res = Dosvm.KbdReadScan ? Dosvm.KbdReadScan(NULL) : 0;
#if 0 /* what's this port got to do with parport ? */
res = (DWORD)parport_8255[0];
#endif
@ -366,10 +365,6 @@ DWORD IO_inport( int port, int size )
case 0x201:
res = 0xffffffff; /* no joystick */
break;
case 0x3ba:
case 0x3da:
res = (DWORD)VGA_ioport_in( port );
break;
default:
WARN("Direct I/O read attempted from port %x\n", port);
res = 0xffffffff;
@ -416,12 +411,11 @@ void IO_outport( int port, int size, DWORD value )
}
#endif
/* first give the DOS VM a chance to handle it */
if (Dosvm.outport && Dosvm.outport( port, size, value )) return;
switch (port)
{
case 0x20:
if (Dosvm.Current())
Dosvm.OutPIC( port, (BYTE)value );
break;
case 0x40:
case 0x41:
case 0x42:
@ -477,7 +471,7 @@ void IO_outport( int port, int size, DWORD value )
tmr_8253[chan].latched = TRUE;
dummy_ctr -= 1 + (int)(10.0 * rand() / (RAND_MAX + 1.0));
if (chan == 0) /* System timer divisor */
if (Dosvm.Current())
if (Dosvm.GetTimer)
tmr_8253[chan].latch = dummy_ctr + (WORD)Dosvm.GetTimer();
else
tmr_8253[chan].latch = dummy_ctr;
@ -511,10 +505,6 @@ void IO_outport( int port, int size, DWORD value )
case 0x71:
cmosimage[cmosaddress & 0x3f] = (BYTE)value;
break;
case 0x3c8:
case 0x3c9:
VGA_ioport_out( port, (BYTE)value );
break;
default:
WARN("Direct I/O write attempted to port %x\n", port );
break;