Moved most of the real-mode stuff to dlls/winedos.
This commit is contained in:
parent
a5d882dc44
commit
8cd55d0eba
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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];
|
|
@ -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");
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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();
|
|
@ -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;
|
|
@ -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) )
|
||||
{
|
|
@ -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");
|
||||
}
|
|
@ -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 );
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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 );
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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 */
|
||||
}
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
629
msdos/dpmi.c
629
msdos/dpmi.c
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
168
msdos/int21.c
168
msdos/int21.c
|
@ -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;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include <string.h>
|
||||
#include "wine/winbase16.h"
|
||||
#include "dosexe.h"
|
||||
#include "miscemu.h"
|
||||
#include "module.h"
|
||||
/* #define DEBUG_INT */
|
||||
|
|
|
@ -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)
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue