Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
16df50ef
Commit
16df50ef
authored
May 10, 2005
by
Eric Pouech
Committed by
Alexandre Julliard
May 10, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moved DOS memory handling to winedos.
parent
e6267369
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
783 additions
and
688 deletions
+783
-688
dosmem.c
dlls/kernel/dosmem.c
+56
-531
global16.c
dlls/kernel/global16.c
+19
-3
instr.c
dlls/kernel/instr.c
+14
-39
kernel32.spec
dlls/kernel/kernel32.spec
+0
-5
kernel_private.h
dlls/kernel/kernel_private.h
+25
-0
Makefile.in
dlls/winedos/Makefile.in
+1
-0
dosexe.h
dlls/winedos/dosexe.h
+75
-4
dosmem.c
dlls/winedos/dosmem.c
+576
-0
dosvm.c
dlls/winedos/dosvm.c
+1
-20
int21.c
dlls/winedos/int21.c
+2
-2
int31.c
dlls/winedos/int31.c
+3
-3
module.c
dlls/winedos/module.c
+3
-3
winedos.spec
dlls/winedos/winedos.spec
+8
-0
miscemu.h
include/miscemu.h
+0
-78
No files found.
dlls/kernel/dosmem.c
View file @
16df50ef
...
...
@@ -40,7 +40,6 @@
#include "kernel_private.h"
#include "toolhelp.h"
#include "miscemu.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dosmem
);
...
...
@@ -54,33 +53,6 @@ WORD DOSMEM_BiosSysSeg; /* BIOS ROM segment at 0xf000:0 */
#define DOSMEM_SIZE 0x110000
#define DOSMEM_64KB 0x10000
/* use 2 low bits of 'size' for the housekeeping */
#define DM_BLOCK_DEBUG 0xABE00000
#define DM_BLOCK_TERMINAL 0x00000001
#define DM_BLOCK_FREE 0x00000002
#define DM_BLOCK_MASK 0x001FFFFC
/*
#define __DOSMEM_DEBUG__
*/
typedef
struct
{
unsigned
size
;
}
dosmem_entry
;
typedef
struct
{
unsigned
blocks
;
unsigned
free
;
}
dosmem_info
;
#define NEXT_BLOCK(block) \
(dosmem_entry*)(((char*)(block)) + \
sizeof(dosmem_entry) + ((block)->size & DM_BLOCK_MASK))
#define VM_STUB(x) (0x90CF00CD|(x<<8))
/* INT x; IRET; NOP */
#define VM_STUB_SEGMENT 0xf000
/* BIOS segment */
/* when looking at DOS and real mode memory, we activate in three different
* modes, depending the situation.
* 1/ By default (protected mode), the first MB of memory (actually 0x110000,
...
...
@@ -91,242 +63,71 @@ typedef struct {
* commit this memory, made of: BIOS segment, but also some system
* information, usually low in memory that we map for the circumstance also
* in the BIOS segment, so that we keep the low memory protected (for NULL
* pointer deref catching for example). In this case, we'res still in PM
* mode, accessing part of the "physicale" real mode memory.
* 3/ if the process enters the real mode, then we commit the full first MB of
* memory (and also initialize the DOS structures in it).
* pointer deref catching for example). In this case, we're still in PM
* mode, accessing part of the "physical" real mode memory. In fact, we don't
* map all the first meg, we keep 64k uncommitted to still catch NULL
* pointers dereference
* 3/ if the process enters the real mode, then we (also) commit the full first
* MB of memory (and also initialize the DOS structures in it).
*/
/* DOS memory base (linear in process address space) */
static
char
*
DOSMEM_dosmem
;
/* DOS system base (for interrupt vector table and BIOS data area)
* ...should in theory (i.e. Windows) be equal to DOSMEM_dosmem (NULL),
* but is normally set to 0xf0000 in Wine to allow trapping of NULL pointers,
* and only relocated to NULL when absolutely necessary */
static
char
*
DOSMEM_sysmem
;
/* number of bytes protected from _dosmem. 0 when DOS memory is initialized,
* 64k otherwise to trap NULL pointers deref */
static
DWORD
DOSMEM_protect
;
static
void
DOSMEM_InitMemory
(
void
);
/***********************************************************************
* DOSMEM_MemoryTop
*
* Gets the DOS memory top.
*/
static
char
*
DOSMEM_MemoryTop
(
void
)
{
return
DOSMEM_dosmem
+
0x9FFFC
;
/* 640K */
}
/***********************************************************************
* DOSMEM_InfoBlock
*
* Gets the DOS memory info block.
*/
static
dosmem_info
*
DOSMEM_InfoBlock
(
void
)
{
/* Start of DOS conventional memory */
static
char
*
DOSMEM_membase
;
if
(
!
DOSMEM_membase
)
{
DWORD
reserve
;
/*
* Reserve either:
* - lowest 64k for NULL pointer catching (Win16)
* - lowest 1k for interrupt handlers and
* another 0.5k for BIOS, DOS and intra-application
* areas (DOS)
*/
if
(
DOSMEM_dosmem
!=
DOSMEM_sysmem
)
reserve
=
DOSMEM_64KB
;
else
reserve
=
0x600
;
/* 1.5k */
/*
* Round to paragraph boundary in order to make
* sure the alignment is correct.
*/
reserve
=
((
reserve
+
15
)
>>
4
)
<<
4
;
/*
* Set DOS memory base and initialize conventional memory.
*/
DOSMEM_membase
=
DOSMEM_dosmem
+
reserve
;
DOSMEM_InitMemory
();
}
return
(
dosmem_info
*
)
DOSMEM_membase
;
}
/***********************************************************************
* DOSMEM_RootBlock
*
* Gets the DOS memory root block.
*/
static
dosmem_entry
*
DOSMEM_RootBlock
(
void
)
{
/* first block has to be paragraph-aligned */
return
(
dosmem_entry
*
)(((
char
*
)
DOSMEM_InfoBlock
())
+
((((
sizeof
(
dosmem_info
)
+
0xf
)
&
~
0xf
)
-
sizeof
(
dosmem_entry
))));
}
/***********************************************************************
* DOSMEM_FillIsrTable
*
* Fill the interrupt table with fake BIOS calls to BIOSSEG (0xf000).
*
* NOTES:
* Linux normally only traps INTs performed from or destined to BIOSSEG
* for us to handle, if the int_revectored table is empty. Filling the
* interrupt table with calls to INT stubs in BIOSSEG allows DOS programs
* to hook interrupts, as well as use their familiar retf tricks to call
* them, AND let Wine handle any unhooked interrupts transparently.
*/
static
void
DOSMEM_FillIsrTable
(
void
)
{
SEGPTR
*
isr
=
(
SEGPTR
*
)
DOSMEM_sysmem
;
int
x
;
for
(
x
=
0
;
x
<
256
;
x
++
)
isr
[
x
]
=
MAKESEGPTR
(
VM_STUB_SEGMENT
,
x
*
4
);
}
static
void
DOSMEM_MakeIsrStubs
(
void
)
{
DWORD
*
stub
=
(
DWORD
*
)(
DOSMEM_dosmem
+
(
VM_STUB_SEGMENT
<<
4
));
int
x
;
for
(
x
=
0
;
x
<
256
;
x
++
)
stub
[
x
]
=
VM_STUB
(
x
);
}
static
BIOSDATA
*
DOSMEM_BiosData
(
void
)
{
return
(
BIOSDATA
*
)(
DOSMEM_sysmem
+
0x400
);
}
/**********************************************************************
* DOSMEM_GetTicksSinceMidnight
*
* Return number of clock ticks since midnight.
*/
static
DWORD
DOSMEM_GetTicksSinceMidnight
(
void
)
{
SYSTEMTIME
time
;
/* This should give us the (approximately) correct
* 18.206 clock ticks per second since midnight.
*/
GetLocalTime
(
&
time
);
static
LONG
WINAPI
dosmem_handler
(
EXCEPTION_POINTERS
*
except
);
return
(((
time
.
wHour
*
3600
+
time
.
wMinute
*
60
+
time
.
wSecond
)
*
18206
)
/
1000
)
+
(
time
.
wMilliseconds
*
1000
/
54927
);
}
struct
winedos_exports
winedos
;
/***********************************************************************
* DOSMEM_FillBiosSegments
*
* Fill the BIOS data segment with dummy values.
*/
static
void
DOSMEM_FillBiosSegments
(
void
)
void
load_winedos
(
void
)
{
char
*
pBiosSys
=
DOSMEM_dosmem
+
0xf0000
;
BYTE
*
pBiosROMTable
=
pBiosSys
+
0xe6f5
;
BIOSDATA
*
pBiosData
=
DOSMEM_BiosData
();
/* Clear all unused values */
memset
(
pBiosData
,
0
,
sizeof
(
*
pBiosData
)
);
/* FIXME: should check the number of configured drives and ports */
pBiosData
->
Com1Addr
=
0x3f8
;
pBiosData
->
Com2Addr
=
0x2f8
;
pBiosData
->
Lpt1Addr
=
0x378
;
pBiosData
->
Lpt2Addr
=
0x278
;
pBiosData
->
InstalledHardware
=
0x5463
;
pBiosData
->
MemSize
=
640
;
pBiosData
->
NextKbdCharPtr
=
0x1e
;
pBiosData
->
FirstKbdCharPtr
=
0x1e
;
pBiosData
->
VideoMode
=
3
;
pBiosData
->
VideoColumns
=
80
;
pBiosData
->
VideoPageSize
=
80
*
25
*
2
;
pBiosData
->
VideoPageStartAddr
=
0xb800
;
pBiosData
->
VideoCtrlAddr
=
0x3d4
;
pBiosData
->
Ticks
=
DOSMEM_GetTicksSinceMidnight
();
pBiosData
->
NbHardDisks
=
2
;
pBiosData
->
KbdBufferStart
=
0x1e
;
pBiosData
->
KbdBufferEnd
=
0x3e
;
pBiosData
->
RowsOnScreenMinus1
=
24
;
pBiosData
->
BytesPerChar
=
0x10
;
pBiosData
->
ModeOptions
=
0x64
;
pBiosData
->
FeatureBitsSwitches
=
0xf9
;
pBiosData
->
VGASettings
=
0x51
;
pBiosData
->
DisplayCombination
=
0x08
;
pBiosData
->
DiskDataRate
=
0
;
/* fill ROM configuration table (values from Award) */
*
(
pBiosROMTable
+
0x0
)
=
0x08
;
/* number of bytes following LO */
*
(
pBiosROMTable
+
0x1
)
=
0x00
;
/* number of bytes following HI */
*
(
pBiosROMTable
+
0x2
)
=
0xfc
;
/* model */
*
(
pBiosROMTable
+
0x3
)
=
0x01
;
/* submodel */
*
(
pBiosROMTable
+
0x4
)
=
0x00
;
/* BIOS revision */
*
(
pBiosROMTable
+
0x5
)
=
0x74
;
/* feature byte 1 */
*
(
pBiosROMTable
+
0x6
)
=
0x00
;
/* feature byte 2 */
*
(
pBiosROMTable
+
0x7
)
=
0x00
;
/* feature byte 3 */
*
(
pBiosROMTable
+
0x8
)
=
0x00
;
/* feature byte 4 */
*
(
pBiosROMTable
+
0x9
)
=
0x00
;
/* feature byte 5 */
/* BIOS date string */
strcpy
(
pBiosSys
+
0xfff5
,
"13/01/99"
);
/* BIOS ID */
*
(
pBiosSys
+
0xfffe
)
=
0xfc
;
/* Reboot vector (f000:fff0 or ffff:0000) */
*
(
DWORD
*
)(
pBiosSys
+
0xfff0
)
=
VM_STUB
(
0x19
);
}
static
HANDLE
hRunOnce
/* = 0 */
;
static
HMODULE
hWineDos
/* = 0 */
;
/***********************************************************************
* DOSMEM_InitMemory
*
* Initialises the DOS memory structures.
/* FIXME: this isn't 100% thread safe, as we won't catch access to 1MB while
* loading winedos (and may return uninitialized valued)
*/
static
void
DOSMEM_InitMemory
(
void
)
{
dosmem_info
*
info_block
=
DOSMEM_InfoBlock
();
dosmem_entry
*
root_block
=
DOSMEM_RootBlock
();
dosmem_entry
*
dm
;
root_block
->
size
=
DOSMEM_MemoryTop
()
-
(((
char
*
)
root_block
)
+
sizeof
(
dosmem_entry
));
info_block
->
blocks
=
0
;
info_block
->
free
=
root_block
->
size
;
dm
=
NEXT_BLOCK
(
root_block
);
dm
->
size
=
DM_BLOCK_TERMINAL
;
root_block
->
size
|=
DM_BLOCK_FREE
#ifdef __DOSMEM_DEBUG__
|
DM_BLOCK_DEBUG
#endif
;
TRACE
(
"DOS conventional memory initialized, %d bytes free.
\n
"
,
DOSMEM_Available
()
);
}
static
void
dosmem_bios_init
(
void
)
{
static
int
bios_created
;
if
(
hWineDos
)
return
;
if
(
hRunOnce
==
0
)
{
HANDLE
hEvent
=
CreateEventW
(
NULL
,
TRUE
,
FALSE
,
NULL
);
if
(
InterlockedCompareExchangePointer
(
(
PVOID
)
&
hRunOnce
,
hEvent
,
0
)
==
0
)
{
HMODULE
hModule
;
if
(
!
bios_created
)
/* ok, we're the winning thread */
VirtualProtect
(
DOSMEM_dosmem
+
DOSMEM_protect
,
DOSMEM_SIZE
-
DOSMEM_protect
,
PAGE_EXECUTE_READWRITE
,
NULL
);
if
(
!
(
hModule
=
LoadLibraryA
(
"winedos.dll"
)))
{
DOSMEM_FillBiosSegments
();
DOSMEM_FillIsrTable
();
bios_created
=
TRUE
;
ERR
(
"Could not load winedos.dll, DOS subsystem unavailable
\n
"
);
hWineDos
=
(
HMODULE
)
1
;
/* not to try to load it again */
return
;
}
#define GET_ADDR(func) winedos.func = (void *)GetProcAddress( hModule, #func );
GET_ADDR
(
AllocDosBlock
);
GET_ADDR
(
FreeDosBlock
);
GET_ADDR
(
ResizeDosBlock
);
GET_ADDR
(
inport
);
GET_ADDR
(
outport
);
GET_ADDR
(
EmulateInterruptPM
);
GET_ADDR
(
CallBuiltinHandler
);
GET_ADDR
(
BiosTick
);
#undef GET_ADDR
RtlRemoveVectoredExceptionHandler
(
dosmem_handler
);
hWineDos
=
hModule
;
SetEvent
(
hRunOnce
);
return
;
}
/* someone beat us here... */
CloseHandle
(
hEvent
);
}
/* and wait for the winner to have finished */
WaitForSingleObject
(
hRunOnce
,
INFINITE
);
}
/******************************************************************
...
...
@@ -339,19 +140,10 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except)
if
(
except
->
ExceptionRecord
->
ExceptionCode
==
EXCEPTION_ACCESS_VIOLATION
)
{
DWORD
addr
=
except
->
ExceptionRecord
->
ExceptionInformation
[
1
];
if
(
addr
>=
(
ULONG_PTR
)
DOSMEM_sysmem
&&
addr
<
(
ULONG_PTR
)
DOSMEM_sysmem
+
DOSMEM_64KB
)
{
VirtualProtect
(
DOSMEM_sysmem
,
DOSMEM_64KB
,
PAGE_EXECUTE_READWRITE
,
NULL
);
dosmem_bios_init
();
return
EXCEPTION_CONTINUE_EXECUTION
;
}
if
(
addr
>=
(
ULONG_PTR
)
DOSMEM_dosmem
+
DOSMEM_protect
&&
addr
<
(
ULONG_PTR
)
DOSMEM_dosmem
+
DOSMEM_SIZE
)
{
VirtualProtect
(
DOSMEM_dosmem
+
DOSMEM_protect
,
DOSMEM_SIZE
-
DOSMEM_protect
,
PAGE_EXECUTE_READWRITE
,
NULL
);
dosmem_bios_init
();
load_winedos
();
return
EXCEPTION_CONTINUE_EXECUTION
;
}
}
...
...
@@ -363,7 +155,7 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except)
*
* Setup the first megabyte for DOS memory access
*/
static
void
setup_dos_mem
(
void
)
static
char
*
setup_dos_mem
(
void
)
{
int
sys_offset
=
0
;
int
page_size
=
getpagesize
();
...
...
@@ -399,8 +191,8 @@ static void setup_dos_mem(void)
}
}
DOSMEM_dosmem
=
addr
;
DOSMEM_sysmem
=
(
char
*
)
addr
+
sys_offset
;
RtlAddVectoredExceptionHandler
(
FALSE
,
dosmem_handler
);
return
(
char
*
)
addr
+
sys_offset
;
}
...
...
@@ -412,285 +204,18 @@ static void setup_dos_mem(void)
*/
BOOL
DOSMEM_Init
(
void
)
{
setup_dos_mem
();
char
*
sysmem
=
setup_dos_mem
();
DOSMEM_0000H
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
DOSMEM_
sysmem
,
DOSMEM_0000H
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
sysmem
,
DOSMEM_64KB
,
0
,
WINE_LDT_FLAGS_DATA
);
DOSMEM_BiosDataSeg
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
DOSMEM_
sysmem
+
0x400
,
DOSMEM_BiosDataSeg
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
sysmem
+
0x400
,
0x100
,
0
,
WINE_LDT_FLAGS_DATA
);
DOSMEM_BiosSysSeg
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
DOSMEM_dosmem
+
0xf0000
,
DOSMEM_BiosSysSeg
=
GLOBAL_CreateBlock
(
GMEM_FIXED
,
DOSMEM_dosmem
+
0xf0000
,
DOSMEM_64KB
,
0
,
WINE_LDT_FLAGS_DATA
);
return
TRUE
;
}
/******************************************************************
* DOSMEM_InitDosMem
*
* Initialize the first MB of memory to look like a real DOS setup
*/
BOOL
DOSMEM_InitDosMem
(
void
)
{
static
int
already_mapped
;
if
(
!
already_mapped
)
{
if
(
DOSMEM_dosmem
)
{
ERR
(
"Needs access to the first megabyte for DOS mode
\n
"
);
ExitProcess
(
1
);
}
MESSAGE
(
"Warning: unprotecting memory to allow real-mode calls.
\n
"
" NULL pointer accesses will no longer be caught.
\n
"
);
VirtualProtect
(
NULL
,
DOSMEM_SIZE
,
PAGE_EXECUTE_READWRITE
,
NULL
);
DOSMEM_protect
=
0
;
dosmem_bios_init
();
/* copy the BIOS and ISR area down */
memcpy
(
DOSMEM_dosmem
,
DOSMEM_sysmem
,
0x400
+
0x100
);
DOSMEM_sysmem
=
DOSMEM_dosmem
;
SetSelectorBase
(
DOSMEM_0000H
,
0
);
SetSelectorBase
(
DOSMEM_BiosDataSeg
,
0x400
);
/* we may now need the actual interrupt stubs, and since we've just moved the
* interrupt vector table away, we can fill the area with stubs instead... */
DOSMEM_MakeIsrStubs
();
already_mapped
=
1
;
}
return
TRUE
;
}
/***********************************************************************
* DOSMEM_Tick
*
* Increment the BIOS tick counter. Called by timer signal handler.
*/
void
DOSMEM_Tick
(
WORD
timer
)
{
BIOSDATA
*
pBiosData
=
DOSMEM_BiosData
();
if
(
pBiosData
)
pBiosData
->
Ticks
++
;
}
/***********************************************************************
* DOSMEM_GetBlock
*
* Carve a chunk of the DOS memory block (without selector).
*/
LPVOID
DOSMEM_GetBlock
(
UINT
size
,
UINT16
*
pseg
)
{
UINT
blocksize
;
char
*
block
=
NULL
;
dosmem_info
*
info_block
=
DOSMEM_InfoBlock
();
dosmem_entry
*
dm
;
#ifdef __DOSMEM_DEBUG_
dosmem_entry
*
prev
=
NULL
;
#endif
if
(
size
>
info_block
->
free
)
return
NULL
;
dm
=
DOSMEM_RootBlock
();
while
(
dm
&&
dm
->
size
!=
DM_BLOCK_TERMINAL
)
{
#ifdef __DOSMEM_DEBUG__
if
(
(
dm
->
size
&
DM_BLOCK_DEBUG
)
!=
DM_BLOCK_DEBUG
)
{
WARN
(
"MCB overrun! [prev = 0x%08x]
\n
"
,
4
+
(
UINT
)
prev
);
return
NULL
;
}
prev
=
dm
;
#endif
if
(
dm
->
size
&
DM_BLOCK_FREE
)
{
dosmem_entry
*
next
=
NEXT_BLOCK
(
dm
);
while
(
next
->
size
&
DM_BLOCK_FREE
)
/* collapse free blocks */
{
dm
->
size
+=
sizeof
(
dosmem_entry
)
+
(
next
->
size
&
DM_BLOCK_MASK
);
next
->
size
=
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
);
next
=
NEXT_BLOCK
(
dm
);
}
blocksize
=
dm
->
size
&
DM_BLOCK_MASK
;
if
(
blocksize
>=
size
)
{
block
=
((
char
*
)
dm
)
+
sizeof
(
dosmem_entry
);
if
(
blocksize
-
size
>
0x20
)
{
/* split dm so that the next one stays
* paragraph-aligned (and dm loses free bit) */
dm
->
size
=
(((
size
+
0xf
+
sizeof
(
dosmem_entry
))
&
~
0xf
)
-
sizeof
(
dosmem_entry
));
next
=
(
dosmem_entry
*
)(((
char
*
)
dm
)
+
sizeof
(
dosmem_entry
)
+
dm
->
size
);
next
->
size
=
(
blocksize
-
(
dm
->
size
+
sizeof
(
dosmem_entry
)))
|
DM_BLOCK_FREE
#ifdef __DOSMEM_DEBUG__
|
DM_BLOCK_DEBUG
#endif
;
}
else
dm
->
size
&=
DM_BLOCK_MASK
;
info_block
->
blocks
++
;
info_block
->
free
-=
dm
->
size
;
if
(
pseg
)
*
pseg
=
(
block
-
DOSMEM_dosmem
)
>>
4
;
#ifdef __DOSMEM_DEBUG__
dm
->
size
|=
DM_BLOCK_DEBUG
;
#endif
break
;
}
dm
=
next
;
}
else
dm
=
NEXT_BLOCK
(
dm
);
}
return
(
LPVOID
)
block
;
}
/***********************************************************************
* DOSMEM_FreeBlock
*/
BOOL
DOSMEM_FreeBlock
(
void
*
ptr
)
{
dosmem_info
*
info_block
=
DOSMEM_InfoBlock
();
if
(
ptr
>=
(
void
*
)(((
char
*
)
DOSMEM_RootBlock
())
+
sizeof
(
dosmem_entry
))
&&
ptr
<
(
void
*
)
DOSMEM_MemoryTop
()
&&
!
((((
char
*
)
ptr
)
-
DOSMEM_dosmem
)
&
0xf
)
)
{
dosmem_entry
*
dm
=
(
dosmem_entry
*
)(((
char
*
)
ptr
)
-
sizeof
(
dosmem_entry
));
if
(
!
(
dm
->
size
&
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
))
#ifdef __DOSMEM_DEBUG__
&&
((
dm
->
size
&
DM_BLOCK_DEBUG
)
==
DM_BLOCK_DEBUG
)
#endif
)
{
info_block
->
blocks
--
;
info_block
->
free
+=
dm
->
size
;
dm
->
size
|=
DM_BLOCK_FREE
;
return
TRUE
;
}
}
return
FALSE
;
}
/***********************************************************************
* DOSMEM_ResizeBlock
*
* Resize DOS memory block in place. Returns block size or -1 on error.
*
* If exact is TRUE, returned value is either old or requested block
* size. If exact is FALSE, block is expanded even if there is not
* enough space for full requested block size.
*/
UINT
DOSMEM_ResizeBlock
(
void
*
ptr
,
UINT
size
,
BOOL
exact
)
{
char
*
block
=
NULL
;
dosmem_info
*
info_block
=
DOSMEM_InfoBlock
();
dosmem_entry
*
dm
;
dosmem_entry
*
next
;
UINT
blocksize
;
UINT
orgsize
;
if
(
(
ptr
<
(
void
*
)(
sizeof
(
dosmem_entry
)
+
(
char
*
)
DOSMEM_RootBlock
()))
||
(
ptr
>=
(
void
*
)
DOSMEM_MemoryTop
())
||
(((((
char
*
)
ptr
)
-
DOSMEM_dosmem
)
&
0xf
)
!=
0
)
)
return
(
UINT
)
-
1
;
dm
=
(
dosmem_entry
*
)(((
char
*
)
ptr
)
-
sizeof
(
dosmem_entry
));
if
(
dm
->
size
&
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
)
)
return
(
UINT
)
-
1
;
next
=
NEXT_BLOCK
(
dm
);
orgsize
=
dm
->
size
&
DM_BLOCK_MASK
;
/* collapse free blocks */
while
(
next
->
size
&
DM_BLOCK_FREE
)
{
dm
->
size
+=
sizeof
(
dosmem_entry
)
+
(
next
->
size
&
DM_BLOCK_MASK
);
next
->
size
=
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
);
next
=
NEXT_BLOCK
(
dm
);
}
blocksize
=
dm
->
size
&
DM_BLOCK_MASK
;
/*
* If collapse didn't help we either expand block to maximum
* available size (exact == FALSE) or give collapsed blocks
* back to free storage (exact == TRUE).
*/
if
(
blocksize
<
size
)
size
=
exact
?
orgsize
:
blocksize
;
block
=
((
char
*
)
dm
)
+
sizeof
(
dosmem_entry
);
if
(
blocksize
-
size
>
0x20
)
{
/*
* split dm so that the next one stays
* paragraph-aligned (and next gains free bit)
*/
dm
->
size
=
(((
size
+
0xf
+
sizeof
(
dosmem_entry
))
&
~
0xf
)
-
sizeof
(
dosmem_entry
));
next
=
(
dosmem_entry
*
)(((
char
*
)
dm
)
+
sizeof
(
dosmem_entry
)
+
dm
->
size
);
next
->
size
=
(
blocksize
-
(
dm
->
size
+
sizeof
(
dosmem_entry
)))
|
DM_BLOCK_FREE
;
}
else
{
dm
->
size
&=
DM_BLOCK_MASK
;
}
/*
* Adjust available memory if block size changes.
*/
info_block
->
free
+=
orgsize
-
dm
->
size
;
return
size
;
}
/***********************************************************************
* DOSMEM_Available
*/
UINT
DOSMEM_Available
(
void
)
{
UINT
blocksize
,
available
=
0
;
dosmem_entry
*
dm
;
dm
=
DOSMEM_RootBlock
();
while
(
dm
&&
dm
->
size
!=
DM_BLOCK_TERMINAL
)
{
#ifdef __DOSMEM_DEBUG__
if
(
(
dm
->
size
&
DM_BLOCK_DEBUG
)
!=
DM_BLOCK_DEBUG
)
{
WARN
(
"MCB overrun! [prev = 0x%08x]
\n
"
,
4
+
(
UINT
)
prev
);
return
NULL
;
}
prev
=
dm
;
#endif
if
(
dm
->
size
&
DM_BLOCK_FREE
)
{
dosmem_entry
*
next
=
NEXT_BLOCK
(
dm
);
while
(
next
->
size
&
DM_BLOCK_FREE
)
/* collapse free blocks */
{
dm
->
size
+=
sizeof
(
dosmem_entry
)
+
(
next
->
size
&
DM_BLOCK_MASK
);
next
->
size
=
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
);
next
=
NEXT_BLOCK
(
dm
);
}
blocksize
=
dm
->
size
&
DM_BLOCK_MASK
;
if
(
blocksize
>
available
)
available
=
blocksize
;
dm
=
next
;
}
else
dm
=
NEXT_BLOCK
(
dm
);
}
return
available
;
}
/***********************************************************************
* DOSMEM_MapLinearToDos
*
...
...
dlls/kernel/global16.c
View file @
16df50ef
...
...
@@ -40,7 +40,6 @@
#include "wine/winbase16.h"
#include "ntstatus.h"
#include "toolhelp.h"
#include "miscemu.h"
#include "stackframe.h"
#include "kernel_private.h"
#include "wine/debug.h"
...
...
@@ -77,6 +76,23 @@ static int globalArenaSize;
#define VALID_HANDLE(handle) (((handle)>>__AHSHIFT)<globalArenaSize)
#define GET_ARENA_PTR(handle) (pGlobalArena + ((handle) >> __AHSHIFT))
static
inline
void
*
DOSMEM_AllocBlock
(
UINT
size
,
UINT16
*
pseg
)
{
if
(
!
winedos
.
AllocDosBlock
)
load_winedos
();
return
winedos
.
AllocDosBlock
?
winedos
.
AllocDosBlock
(
size
,
pseg
)
:
NULL
;
}
static
inline
BOOL
DOSMEM_FreeBlock
(
void
*
ptr
)
{
if
(
!
winedos
.
FreeDosBlock
)
load_winedos
();
return
winedos
.
FreeDosBlock
?
winedos
.
FreeDosBlock
(
ptr
)
:
FALSE
;
}
static
inline
UINT
DOSMEM_ResizeBlock
(
void
*
ptr
,
UINT
size
,
BOOL
exact
)
{
if
(
!
winedos
.
ResizeDosBlock
)
load_winedos
();
return
winedos
.
ResizeDosBlock
?
winedos
.
ResizeDosBlock
(
ptr
,
size
,
TRUE
)
:
0
;
}
/***********************************************************************
* GLOBAL_GetArena
...
...
@@ -336,7 +352,7 @@ HGLOBAL16 WINAPI GlobalReAlloc16(
newptr
=
0
;
else
{
newptr
=
DOSMEM_
Get
Block
(
size
,
0
);
newptr
=
DOSMEM_
Alloc
Block
(
size
,
0
);
if
(
newptr
)
{
memcpy
(
newptr
,
ptr
,
oldsize
);
...
...
@@ -757,7 +773,7 @@ DWORD WINAPI GlobalDOSAlloc16(
DWORD
size
/* [in] Number of bytes to be allocated */
)
{
UINT16
uParagraph
;
LPVOID
lpBlock
=
DOSMEM_
Get
Block
(
size
,
&
uParagraph
);
LPVOID
lpBlock
=
DOSMEM_
Alloc
Block
(
size
,
&
uParagraph
);
if
(
lpBlock
)
{
...
...
dlls/kernel/instr.c
View file @
16df50ef
...
...
@@ -30,7 +30,6 @@
#include "wine/winuser16.h"
#include "excpt.h"
#include "module.h"
#include "miscemu.h"
#include "wine/debug.h"
#include "kernel_private.h"
#include "thread.h"
...
...
@@ -67,34 +66,6 @@ inline static void *get_stack( CONTEXT86 *context )
return
wine_ldt_get_ptr
(
context
->
SegSs
,
context
->
Esp
);
}
static
void
(
WINAPI
*
DOS_EmulateInterruptPM
)(
CONTEXT86
*
context
,
BYTE
intnum
);
static
void
(
WINAPI
*
DOS_CallBuiltinHandler
)(
CONTEXT86
*
context
,
BYTE
intnum
);
static
DWORD
(
WINAPI
*
DOS_inport
)(
int
port
,
int
size
);
static
void
(
WINAPI
*
DOS_outport
)(
int
port
,
int
size
,
DWORD
val
);
static
void
init_winedos
(
void
)
{
static
HMODULE
module
;
if
(
module
)
return
;
module
=
LoadLibraryA
(
"winedos.dll"
);
if
(
!
module
)
{
ERR
(
"could not load winedos.dll, DOS subsystem unavailable
\n
"
);
module
=
(
HMODULE
)
1
;
/* don't try again */
return
;
}
#define GET_ADDR(func) DOS_##func = (void *)GetProcAddress(module, #func);
GET_ADDR
(
inport
);
GET_ADDR
(
outport
);
GET_ADDR
(
EmulateInterruptPM
);
GET_ADDR
(
CallBuiltinHandler
);
#undef GET_ADDR
}
/***********************************************************************
* INSTR_ReplaceSelector
*
...
...
@@ -112,7 +83,11 @@ static BOOL INSTR_ReplaceSelector( CONTEXT86 *context, WORD *sel )
{
static
WORD
sys_timer
=
0
;
if
(
!
sys_timer
)
sys_timer
=
CreateSystemTimer
(
55
,
DOSMEM_Tick
);
{
if
(
!
winedos
.
BiosTick
)
load_winedos
();
if
(
winedos
.
BiosTick
)
sys_timer
=
CreateSystemTimer
(
55
,
winedos
.
BiosTick
);
}
*
sel
=
DOSMEM_BiosDataSeg
;
return
TRUE
;
}
...
...
@@ -367,8 +342,8 @@ static DWORD INSTR_inport( WORD port, int size, CONTEXT86 *context )
{
DWORD
res
=
~
0U
;
if
(
!
DOS_inport
)
init
_winedos
();
if
(
DOS_inport
)
res
=
DOS_
inport
(
port
,
size
);
if
(
!
winedos
.
inport
)
load
_winedos
();
if
(
winedos
.
inport
)
res
=
winedos
.
inport
(
port
,
size
);
if
(
TRACE_ON
(
io
))
{
...
...
@@ -399,8 +374,8 @@ static DWORD INSTR_inport( WORD port, int size, CONTEXT86 *context )
*/
static
void
INSTR_outport
(
WORD
port
,
int
size
,
DWORD
val
,
CONTEXT86
*
context
)
{
if
(
!
DOS_outport
)
init
_winedos
();
if
(
DOS_outport
)
DOS_
outport
(
port
,
size
,
val
);
if
(
!
winedos
.
outport
)
load
_winedos
();
if
(
winedos
.
outport
)
winedos
.
outport
(
port
,
size
,
val
);
if
(
TRACE_ON
(
io
))
{
...
...
@@ -733,11 +708,11 @@ DWORD INSTR_EmulateInstruction( EXCEPTION_RECORD *rec, CONTEXT86 *context )
case
0xcd
:
/* int <XX> */
if
(
wine_ldt_is_system
(
context
->
SegCs
))
break
;
/* don't emulate it in 32-bit code */
if
(
!
DOS_EmulateInterruptPM
)
init
_winedos
();
if
(
DOS_
EmulateInterruptPM
)
if
(
!
winedos
.
EmulateInterruptPM
)
load
_winedos
();
if
(
winedos
.
EmulateInterruptPM
)
{
context
->
Eip
+=
prefixlen
+
2
;
DOS_
EmulateInterruptPM
(
context
,
instr
[
1
]
);
winedos
.
EmulateInterruptPM
(
context
,
instr
[
1
]
);
return
ExceptionContinueExecution
;
}
break
;
/* Unable to emulate it */
...
...
@@ -839,8 +814,8 @@ DWORD INSTR_EmulateInstruction( EXCEPTION_RECORD *rec, CONTEXT86 *context )
*/
void
INSTR_CallBuiltinHandler
(
CONTEXT86
*
context
,
BYTE
intnum
)
{
if
(
!
DOS_CallBuiltinHandler
)
init
_winedos
();
if
(
DOS_CallBuiltinHandler
)
DOS_
CallBuiltinHandler
(
context
,
intnum
);
if
(
!
winedos
.
CallBuiltinHandler
)
load
_winedos
();
if
(
winedos
.
CallBuiltinHandler
)
winedos
.
CallBuiltinHandler
(
context
,
intnum
);
}
...
...
dlls/kernel/kernel32.spec
View file @
16df50ef
...
...
@@ -1167,11 +1167,6 @@
# Wine dll separation hacks, these will go away, don't use them
#
@ cdecl DOSMEM_AllocSelector(long)
@ cdecl DOSMEM_Available()
@ cdecl DOSMEM_FreeBlock(ptr)
@ cdecl DOSMEM_GetBlock(long ptr)
@ cdecl DOSMEM_InitDosMem(long)
@ cdecl DOSMEM_ResizeBlock(ptr long long)
@ cdecl LOCAL_Alloc(long long long)
@ cdecl LOCAL_Compact(long long long)
@ cdecl LOCAL_CountFree(long)
...
...
dlls/kernel/kernel_private.h
View file @
16df50ef
...
...
@@ -90,5 +90,30 @@ typedef struct
WORD
stackbottom
;
/* Bottom of the stack */
}
INSTANCEDATA
;
#include "poppack.h"
extern
WORD
DOSMEM_0000H
;
extern
WORD
DOSMEM_BiosDataSeg
;
extern
WORD
DOSMEM_BiosSysSeg
;
/* msdos/dosmem.c */
extern
BOOL
DOSMEM_Init
(
void
);
extern
WORD
DOSMEM_AllocSelector
(
WORD
);
extern
LPVOID
DOSMEM_MapRealToLinear
(
DWORD
);
/* real-mode to linear */
extern
LPVOID
DOSMEM_MapDosToLinear
(
UINT
);
/* linear DOS to Wine */
extern
UINT
DOSMEM_MapLinearToDos
(
LPVOID
);
/* linear Wine to DOS */
extern
void
load_winedos
(
void
);
extern
struct
winedos_exports
{
/* for global16.c */
void
*
(
*
AllocDosBlock
)(
UINT
size
,
UINT16
*
pseg
);
BOOL
(
*
FreeDosBlock
)(
void
*
ptr
);
UINT
(
*
ResizeDosBlock
)(
void
*
ptr
,
UINT
size
,
BOOL
exact
);
/* for instr.c */
void
(
WINAPI
*
EmulateInterruptPM
)(
CONTEXT86
*
context
,
BYTE
intnum
);
void
(
WINAPI
*
CallBuiltinHandler
)(
CONTEXT86
*
context
,
BYTE
intnum
);
DWORD
(
WINAPI
*
inport
)(
int
port
,
int
size
);
void
(
WINAPI
*
outport
)(
int
port
,
int
size
,
DWORD
val
);
void
(
*
BiosTick
)(
WORD
timer
);
}
winedos
;
#endif
dlls/winedos/Makefile.in
View file @
16df50ef
...
...
@@ -14,6 +14,7 @@ C_SRCS = \
dma.c
\
dosaspi.c
\
dosconf.c
\
dosmem.c
\
dosvm.c
\
fpu.c
\
himem.c
\
...
...
dlls/winedos/dosexe.h
View file @
16df50ef
...
...
@@ -24,11 +24,11 @@
#include <stdarg.h>
#include "windef.h"
#include "wine/library.h"
#include "wine/windef16.h"
#include "winbase.h"
#include "winnt.h"
/* for PCONTEXT */
#include "wincon.h"
/* for MOUSE_EVENT_RECORD */
#include "miscemu.h"
#define MAX_DOS_DRIVES 26
...
...
@@ -182,6 +182,68 @@ extern struct DPMI_segments *DOSVM_dpmi_segments;
#define SET_CH(context,val) ((void)((context)->Ecx = ((context)->Ecx & ~0xff00) | (((BYTE)(val)) << 8)))
#define SET_DH(context,val) ((void)((context)->Edx = ((context)->Edx & ~0xff00) | (((BYTE)(val)) << 8)))
#include <pshpack1.h>
typedef
struct
{
WORD
Com1Addr
;
/* 00: COM1 I/O address */
WORD
Com2Addr
;
/* 02: COM2 I/O address */
WORD
Com3Addr
;
/* 04: COM3 I/O address */
WORD
Com4Addr
;
/* 06: COM4 I/O address */
WORD
Lpt1Addr
;
/* 08: LPT1 I/O address */
WORD
Lpt2Addr
;
/* 0a: LPT2 I/O address */
WORD
Lpt3Addr
;
/* 0c: LPT3 I/O address */
WORD
Lpt4Addr
;
/* 0e: LPT4 I/O address */
WORD
InstalledHardware
;
/* 10: Installed hardware flags */
BYTE
POSTstatus
;
/* 12: Power-On Self Test status */
WORD
MemSize
;
/* 13: Base memory size in Kb */
WORD
unused1
;
/* 15: Manufacturing test scratch pad */
BYTE
KbdFlags1
;
/* 17: Keyboard flags 1 */
BYTE
KbdFlags2
;
/* 18: Keyboard flags 2 */
BYTE
unused2
;
/* 19: Keyboard driver workspace */
WORD
NextKbdCharPtr
;
/* 1a: Next character in kbd buffer */
WORD
FirstKbdCharPtr
;
/* 1c: First character in kbd buffer */
WORD
KbdBuffer
[
16
];
/* 1e: Keyboard buffer */
BYTE
DisketteStatus1
;
/* 3e: Diskette recalibrate status */
BYTE
DisketteStatus2
;
/* 3f: Diskette motor status */
BYTE
DisketteStatus3
;
/* 40: Diskette motor timeout */
BYTE
DisketteStatus4
;
/* 41: Diskette last operation status */
BYTE
DiskStatus
[
7
];
/* 42: Disk status/command bytes */
BYTE
VideoMode
;
/* 49: Video mode */
WORD
VideoColumns
;
/* 4a: Number of columns */
WORD
VideoPageSize
;
/* 4c: Video page size in bytes */
WORD
VideoPageStartAddr
;
/* 4e: Video page start address */
BYTE
VideoCursorPos
[
16
];
/* 50: Cursor position for 8 pages, column/row order */
WORD
VideoCursorType
;
/* 60: Video cursor type */
BYTE
VideoCurPage
;
/* 62: Video current page */
WORD
VideoCtrlAddr
;
/* 63: Video controller address */
BYTE
VideoReg1
;
/* 65: Video mode select register */
BYTE
VideoReg2
;
/* 66: Video CGA palette register */
DWORD
ResetEntry
;
/* 67: Warm reset entry point */
BYTE
LastIRQ
;
/* 6b: Last unexpected interrupt */
DWORD
Ticks
;
/* 6c: Ticks since midnight */
BYTE
TicksOverflow
;
/* 70: Timer overflow if past midnight */
BYTE
CtrlBreakFlag
;
/* 71: Ctrl-Break flag */
WORD
ResetFlag
;
/* 72: POST Reset flag */
BYTE
DiskOpStatus
;
/* 74: Last hard-disk operation status */
BYTE
NbHardDisks
;
/* 75: Number of hard disks */
BYTE
DiskCtrlByte
;
/* 76: Disk control byte */
BYTE
DiskIOPort
;
/* 77: Disk I/O port offset */
BYTE
LptTimeout
[
4
];
/* 78: Timeouts for parallel ports */
BYTE
ComTimeout
[
4
];
/* 7c: Timeouts for serial ports */
WORD
KbdBufferStart
;
/* 80: Keyboard buffer start */
WORD
KbdBufferEnd
;
/* 82: Keyboard buffer end */
BYTE
RowsOnScreenMinus1
;
/* 84: EGA only */
WORD
BytesPerChar
;
/* 85: EGA only */
BYTE
ModeOptions
;
/* 87: EGA only */
BYTE
FeatureBitsSwitches
;
/* 88: EGA only */
BYTE
VGASettings
;
/* 89: VGA misc settings */
BYTE
DisplayCombination
;
/* 8A: VGA display combinations */
BYTE
DiskDataRate
;
/* 8B: Last disk data rate selected */
}
BIOSDATA
;
#include <poppack.h>
/* module.c */
extern
void
WINAPI
MZ_LoadImage
(
LPCSTR
filename
,
HANDLE
hFile
);
extern
BOOL
WINAPI
MZ_Exec
(
CONTEXT86
*
context
,
LPCSTR
filename
,
BYTE
func
,
LPVOID
paramblk
);
...
...
@@ -201,7 +263,6 @@ extern void WINAPI DOSVM_QueueEvent( INT irq, INT priority, DOSRELAY relay, LPVO
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
BIOSDATA
*
DOSVM_BiosData
(
void
);
/* devices.c */
extern
void
DOSDEV_InstallDOSDevices
(
void
);
...
...
@@ -221,10 +282,20 @@ extern void DMA_ioport_out( WORD port, BYTE val );
extern
BYTE
DMA_ioport_in
(
WORD
port
);
/* dosaspi.c */
void
WINAPI
DOSVM_ASPIHandler
(
CONTEXT86
*
);
extern
void
WINAPI
DOSVM_ASPIHandler
(
CONTEXT86
*
);
/* dosconf.c */
DOSCONF
*
DOSCONF_GetConfig
(
void
);
extern
DOSCONF
*
DOSCONF_GetConfig
(
void
);
/* dosmem.c */
extern
void
DOSMEM_InitDosMemory
(
void
);
extern
BOOL
DOSMEM_MapDosLayout
(
void
);
extern
WORD
DOSMEM_AllocSelector
(
WORD
);
/* FIXME: to be removed */
extern
LPVOID
DOSMEM_AllocBlock
(
UINT
size
,
WORD
*
p
);
extern
BOOL
DOSMEM_FreeBlock
(
void
*
ptr
);
extern
UINT
DOSMEM_ResizeBlock
(
void
*
ptr
,
UINT
size
,
BOOL
exact
);
extern
UINT
DOSMEM_Available
(
void
);
extern
BIOSDATA
*
DOSVM_BiosData
(
void
);
/* fpu.c */
extern
void
WINAPI
DOSVM_Int34Handler
(
CONTEXT86
*
);
...
...
dlls/winedos/dosmem.c
0 → 100644
View file @
16df50ef
/*
* DOS memory emulation
*
* Copyright 1995 Alexandre Julliard
* Copyright 1996 Marcus Meissner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "wine/port.h"
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "excpt.h"
#include "winternl.h"
#include "wine/winbase16.h"
#include "dosexe.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
dosmem
);
/* DOS memory highest address (including HMA) */
#define DOSMEM_SIZE 0x110000
#define DOSMEM_64KB 0x10000
/* see dlls/kernel/dosmem.c for the details */
static
char
*
DOSMEM_dosmem
;
static
char
*
DOSMEM_sysmem
;
/* use 2 low bits of 'size' for the housekeeping */
#define DM_BLOCK_DEBUG 0xABE00000
#define DM_BLOCK_TERMINAL 0x00000001
#define DM_BLOCK_FREE 0x00000002
#define DM_BLOCK_MASK 0x001FFFFC
/*
#define __DOSMEM_DEBUG__
*/
typedef
struct
{
unsigned
size
;
}
dosmem_entry
;
typedef
struct
{
unsigned
blocks
;
unsigned
free
;
}
dosmem_info
;
static
inline
dosmem_entry
*
next_block
(
dosmem_entry
*
block
)
{
return
(
dosmem_entry
*
)((
char
*
)
block
+
sizeof
(
dosmem_entry
)
+
(
block
->
size
&
DM_BLOCK_MASK
));
}
#define VM_STUB(x) (0x90CF00CD|(x<<8))
/* INT x; IRET; NOP */
#define VM_STUB_SEGMENT 0xf000
/* BIOS segment */
/* FIXME: this should be moved to the LOL, and the whole allocation strategy
* should use real MCB
*/
static
dosmem_info
*
DOSMEM_info_block
;
/***********************************************************************
* DOSMEM_MemoryTop
*
* Gets the DOS memory top.
*/
static
char
*
DOSMEM_MemoryTop
(
void
)
{
return
DOSMEM_dosmem
+
0x9FFFC
;
/* 640K */
}
/***********************************************************************
* DOSMEM_RootBlock
*
* Gets the DOS memory root block.
*/
static
dosmem_entry
*
DOSMEM_RootBlock
(
void
)
{
/* first block has to be paragraph-aligned */
return
(
dosmem_entry
*
)(((
char
*
)
DOSMEM_info_block
)
+
((((
sizeof
(
dosmem_info
)
+
0xf
)
&
~
0xf
)
-
sizeof
(
dosmem_entry
))));
}
/***********************************************************************
* DOSMEM_FillIsrTable
*
* Fill the interrupt table with fake BIOS calls to BIOSSEG (0xf000).
*
* NOTES:
* Linux normally only traps INTs performed from or destined to BIOSSEG
* for us to handle, if the int_revectored table is empty. Filling the
* interrupt table with calls to INT stubs in BIOSSEG allows DOS programs
* to hook interrupts, as well as use their familiar retf tricks to call
* them, AND let Wine handle any unhooked interrupts transparently.
*/
static
void
DOSMEM_FillIsrTable
(
void
)
{
SEGPTR
*
isr
=
(
SEGPTR
*
)
DOSMEM_sysmem
;
int
x
;
for
(
x
=
0
;
x
<
256
;
x
++
)
isr
[
x
]
=
MAKESEGPTR
(
VM_STUB_SEGMENT
,
x
*
4
);
}
static
void
DOSMEM_MakeIsrStubs
(
void
)
{
DWORD
*
stub
=
(
DWORD
*
)(
DOSMEM_dosmem
+
(
VM_STUB_SEGMENT
<<
4
));
int
x
;
for
(
x
=
0
;
x
<
256
;
x
++
)
stub
[
x
]
=
VM_STUB
(
x
);
}
BIOSDATA
*
DOSVM_BiosData
(
void
)
{
return
(
BIOSDATA
*
)(
DOSMEM_sysmem
+
0x400
);
}
/**********************************************************************
* DOSMEM_GetTicksSinceMidnight
*
* Return number of clock ticks since midnight.
*/
static
DWORD
DOSMEM_GetTicksSinceMidnight
(
void
)
{
SYSTEMTIME
time
;
/* This should give us the (approximately) correct
* 18.206 clock ticks per second since midnight.
*/
GetLocalTime
(
&
time
);
return
(((
time
.
wHour
*
3600
+
time
.
wMinute
*
60
+
time
.
wSecond
)
*
18206
)
/
1000
)
+
(
time
.
wMilliseconds
*
1000
/
54927
);
}
/***********************************************************************
* DOSMEM_FillBiosSegments
*
* Fill the BIOS data segment with dummy values.
*/
static
void
DOSMEM_FillBiosSegments
(
void
)
{
char
*
pBiosSys
=
DOSMEM_dosmem
+
0xf0000
;
BYTE
*
pBiosROMTable
=
pBiosSys
+
0xe6f5
;
BIOSDATA
*
pBiosData
=
DOSVM_BiosData
();
/* Clear all unused values */
memset
(
pBiosData
,
0
,
sizeof
(
*
pBiosData
)
);
/* FIXME: should check the number of configured drives and ports */
pBiosData
->
Com1Addr
=
0x3f8
;
pBiosData
->
Com2Addr
=
0x2f8
;
pBiosData
->
Lpt1Addr
=
0x378
;
pBiosData
->
Lpt2Addr
=
0x278
;
pBiosData
->
InstalledHardware
=
0x5463
;
pBiosData
->
MemSize
=
640
;
pBiosData
->
NextKbdCharPtr
=
0x1e
;
pBiosData
->
FirstKbdCharPtr
=
0x1e
;
pBiosData
->
VideoMode
=
3
;
pBiosData
->
VideoColumns
=
80
;
pBiosData
->
VideoPageSize
=
80
*
25
*
2
;
pBiosData
->
VideoPageStartAddr
=
0xb800
;
pBiosData
->
VideoCtrlAddr
=
0x3d4
;
pBiosData
->
Ticks
=
DOSMEM_GetTicksSinceMidnight
();
pBiosData
->
NbHardDisks
=
2
;
pBiosData
->
KbdBufferStart
=
0x1e
;
pBiosData
->
KbdBufferEnd
=
0x3e
;
pBiosData
->
RowsOnScreenMinus1
=
24
;
pBiosData
->
BytesPerChar
=
0x10
;
pBiosData
->
ModeOptions
=
0x64
;
pBiosData
->
FeatureBitsSwitches
=
0xf9
;
pBiosData
->
VGASettings
=
0x51
;
pBiosData
->
DisplayCombination
=
0x08
;
pBiosData
->
DiskDataRate
=
0
;
/* fill ROM configuration table (values from Award) */
*
(
pBiosROMTable
+
0x0
)
=
0x08
;
/* number of bytes following LO */
*
(
pBiosROMTable
+
0x1
)
=
0x00
;
/* number of bytes following HI */
*
(
pBiosROMTable
+
0x2
)
=
0xfc
;
/* model */
*
(
pBiosROMTable
+
0x3
)
=
0x01
;
/* submodel */
*
(
pBiosROMTable
+
0x4
)
=
0x00
;
/* BIOS revision */
*
(
pBiosROMTable
+
0x5
)
=
0x74
;
/* feature byte 1 */
*
(
pBiosROMTable
+
0x6
)
=
0x00
;
/* feature byte 2 */
*
(
pBiosROMTable
+
0x7
)
=
0x00
;
/* feature byte 3 */
*
(
pBiosROMTable
+
0x8
)
=
0x00
;
/* feature byte 4 */
*
(
pBiosROMTable
+
0x9
)
=
0x00
;
/* feature byte 5 */
/* BIOS date string */
strcpy
(
pBiosSys
+
0xfff5
,
"13/01/99"
);
/* BIOS ID */
*
(
pBiosSys
+
0xfffe
)
=
0xfc
;
/* Reboot vector (f000:fff0 or ffff:0000) */
*
(
DWORD
*
)(
pBiosSys
+
0xfff0
)
=
VM_STUB
(
0x19
);
}
/***********************************************************************
* BiosTick
*
* Increment the BIOS tick counter. Called by timer signal handler.
*/
void
BiosTick
(
WORD
timer
)
{
BIOSDATA
*
pBiosData
=
DOSVM_BiosData
();
if
(
pBiosData
)
pBiosData
->
Ticks
++
;
}
/***********************************************************************
* DOSMEM_AllocBlock
*
* Carve a chunk of the DOS memory block (without selector).
*/
LPVOID
DOSMEM_AllocBlock
(
UINT
size
,
UINT16
*
pseg
)
{
UINT
blocksize
;
char
*
block
=
NULL
;
dosmem_info
*
info_block
=
DOSMEM_info_block
;
dosmem_entry
*
dm
;
#ifdef __DOSMEM_DEBUG_
dosmem_entry
*
prev
=
NULL
;
#endif
if
(
size
>
info_block
->
free
)
return
NULL
;
dm
=
DOSMEM_RootBlock
();
while
(
dm
&&
dm
->
size
!=
DM_BLOCK_TERMINAL
)
{
#ifdef __DOSMEM_DEBUG__
if
(
(
dm
->
size
&
DM_BLOCK_DEBUG
)
!=
DM_BLOCK_DEBUG
)
{
WARN
(
"MCB overrun! [prev = 0x%08x]
\n
"
,
4
+
(
UINT
)
prev
);
return
NULL
;
}
prev
=
dm
;
#endif
if
(
dm
->
size
&
DM_BLOCK_FREE
)
{
dosmem_entry
*
next
=
next_block
(
dm
);
while
(
next
->
size
&
DM_BLOCK_FREE
)
/* collapse free blocks */
{
dm
->
size
+=
sizeof
(
dosmem_entry
)
+
(
next
->
size
&
DM_BLOCK_MASK
);
next
->
size
=
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
);
next
=
next_block
(
dm
);
}
blocksize
=
dm
->
size
&
DM_BLOCK_MASK
;
if
(
blocksize
>=
size
)
{
block
=
((
char
*
)
dm
)
+
sizeof
(
dosmem_entry
);
if
(
blocksize
-
size
>
0x20
)
{
/* split dm so that the next one stays
* paragraph-aligned (and dm loses free bit) */
dm
->
size
=
(((
size
+
0xf
+
sizeof
(
dosmem_entry
))
&
~
0xf
)
-
sizeof
(
dosmem_entry
));
next
=
(
dosmem_entry
*
)(((
char
*
)
dm
)
+
sizeof
(
dosmem_entry
)
+
dm
->
size
);
next
->
size
=
(
blocksize
-
(
dm
->
size
+
sizeof
(
dosmem_entry
)))
|
DM_BLOCK_FREE
#ifdef __DOSMEM_DEBUG__
|
DM_BLOCK_DEBUG
#endif
;
}
else
dm
->
size
&=
DM_BLOCK_MASK
;
info_block
->
blocks
++
;
info_block
->
free
-=
dm
->
size
;
if
(
pseg
)
*
pseg
=
(
block
-
DOSMEM_dosmem
)
>>
4
;
#ifdef __DOSMEM_DEBUG__
dm
->
size
|=
DM_BLOCK_DEBUG
;
#endif
break
;
}
dm
=
next
;
}
else
dm
=
next_block
(
dm
);
}
return
(
LPVOID
)
block
;
}
/***********************************************************************
* DOSMEM_FreeBlock
*/
BOOL
DOSMEM_FreeBlock
(
void
*
ptr
)
{
dosmem_info
*
info_block
=
DOSMEM_info_block
;
if
(
ptr
>=
(
void
*
)(((
char
*
)
DOSMEM_RootBlock
())
+
sizeof
(
dosmem_entry
))
&&
ptr
<
(
void
*
)
DOSMEM_MemoryTop
()
&&
!
((((
char
*
)
ptr
)
-
DOSMEM_dosmem
)
&
0xf
)
)
{
dosmem_entry
*
dm
=
(
dosmem_entry
*
)(((
char
*
)
ptr
)
-
sizeof
(
dosmem_entry
));
if
(
!
(
dm
->
size
&
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
))
#ifdef __DOSMEM_DEBUG__
&&
((
dm
->
size
&
DM_BLOCK_DEBUG
)
==
DM_BLOCK_DEBUG
)
#endif
)
{
info_block
->
blocks
--
;
info_block
->
free
+=
dm
->
size
;
dm
->
size
|=
DM_BLOCK_FREE
;
return
TRUE
;
}
}
return
FALSE
;
}
/***********************************************************************
* DOSMEM_ResizeBlock
*
* Resize DOS memory block in place. Returns block size or -1 on error.
*
* If exact is TRUE, returned value is either old or requested block
* size. If exact is FALSE, block is expanded even if there is not
* enough space for full requested block size.
*/
UINT
DOSMEM_ResizeBlock
(
void
*
ptr
,
UINT
size
,
BOOL
exact
)
{
char
*
block
=
NULL
;
dosmem_info
*
info_block
=
DOSMEM_info_block
;
dosmem_entry
*
dm
;
dosmem_entry
*
next
;
UINT
blocksize
;
UINT
orgsize
;
if
(
(
ptr
<
(
void
*
)(
sizeof
(
dosmem_entry
)
+
(
char
*
)
DOSMEM_RootBlock
()))
||
(
ptr
>=
(
void
*
)
DOSMEM_MemoryTop
())
||
(((((
char
*
)
ptr
)
-
DOSMEM_dosmem
)
&
0xf
)
!=
0
)
)
return
(
UINT
)
-
1
;
dm
=
(
dosmem_entry
*
)(((
char
*
)
ptr
)
-
sizeof
(
dosmem_entry
));
if
(
dm
->
size
&
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
)
)
return
(
UINT
)
-
1
;
next
=
next_block
(
dm
);
orgsize
=
dm
->
size
&
DM_BLOCK_MASK
;
/* collapse free blocks */
while
(
next
->
size
&
DM_BLOCK_FREE
)
{
dm
->
size
+=
sizeof
(
dosmem_entry
)
+
(
next
->
size
&
DM_BLOCK_MASK
);
next
->
size
=
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
);
next
=
next_block
(
dm
);
}
blocksize
=
dm
->
size
&
DM_BLOCK_MASK
;
/*
* If collapse didn't help we either expand block to maximum
* available size (exact == FALSE) or give collapsed blocks
* back to free storage (exact == TRUE).
*/
if
(
blocksize
<
size
)
size
=
exact
?
orgsize
:
blocksize
;
block
=
((
char
*
)
dm
)
+
sizeof
(
dosmem_entry
);
if
(
blocksize
-
size
>
0x20
)
{
/*
* split dm so that the next one stays
* paragraph-aligned (and next gains free bit)
*/
dm
->
size
=
(((
size
+
0xf
+
sizeof
(
dosmem_entry
))
&
~
0xf
)
-
sizeof
(
dosmem_entry
));
next
=
(
dosmem_entry
*
)(((
char
*
)
dm
)
+
sizeof
(
dosmem_entry
)
+
dm
->
size
);
next
->
size
=
(
blocksize
-
(
dm
->
size
+
sizeof
(
dosmem_entry
)))
|
DM_BLOCK_FREE
;
}
else
{
dm
->
size
&=
DM_BLOCK_MASK
;
}
/*
* Adjust available memory if block size changes.
*/
info_block
->
free
+=
orgsize
-
dm
->
size
;
return
size
;
}
/***********************************************************************
* DOSMEM_Available
*/
UINT
DOSMEM_Available
(
void
)
{
UINT
blocksize
,
available
=
0
;
dosmem_entry
*
dm
;
dm
=
DOSMEM_RootBlock
();
while
(
dm
&&
dm
->
size
!=
DM_BLOCK_TERMINAL
)
{
#ifdef __DOSMEM_DEBUG__
if
(
(
dm
->
size
&
DM_BLOCK_DEBUG
)
!=
DM_BLOCK_DEBUG
)
{
WARN
(
"MCB overrun! [prev = 0x%08x]
\n
"
,
4
+
(
UINT
)
prev
);
return
NULL
;
}
prev
=
dm
;
#endif
if
(
dm
->
size
&
DM_BLOCK_FREE
)
{
dosmem_entry
*
next
=
next_block
(
dm
);
while
(
next
->
size
&
DM_BLOCK_FREE
)
/* collapse free blocks */
{
dm
->
size
+=
sizeof
(
dosmem_entry
)
+
(
next
->
size
&
DM_BLOCK_MASK
);
next
->
size
=
(
DM_BLOCK_FREE
|
DM_BLOCK_TERMINAL
);
next
=
next_block
(
dm
);
}
blocksize
=
dm
->
size
&
DM_BLOCK_MASK
;
if
(
blocksize
>
available
)
available
=
blocksize
;
dm
=
next
;
}
else
dm
=
next_block
(
dm
);
}
return
available
;
}
/***********************************************************************
* DOSMEM_InitMemory
*
* Initialises the DOS memory structures.
*/
static
void
DOSMEM_InitMemory
(
char
*
addr
)
{
dosmem_entry
*
root_block
;
dosmem_entry
*
dm
;
DOSMEM_FillBiosSegments
();
DOSMEM_FillIsrTable
();
DOSMEM_info_block
=
(
dosmem_info
*
)
addr
;
root_block
=
DOSMEM_RootBlock
();
root_block
->
size
=
DOSMEM_MemoryTop
()
-
(((
char
*
)
root_block
)
+
sizeof
(
dosmem_entry
));
DOSMEM_info_block
->
blocks
=
0
;
DOSMEM_info_block
->
free
=
root_block
->
size
;
dm
=
next_block
(
root_block
);
dm
->
size
=
DM_BLOCK_TERMINAL
;
root_block
->
size
|=
DM_BLOCK_FREE
#ifdef __DOSMEM_DEBUG__
|
DM_BLOCK_DEBUG
#endif
;
TRACE
(
"DOS conventional memory initialized, %d bytes free.
\n
"
,
DOSMEM_Available
());
}
/******************************************************************
* DOSMEM_InitDosMemory
*
* When WineDOS is loaded, initializes the current DOS memory layout.
*/
void
DOSMEM_InitDosMemory
(
void
)
{
HMODULE16
hModule
;
unsigned
short
sel
;
LDT_ENTRY
entry
;
DWORD
reserve
;
hModule
=
GetModuleHandle16
(
"KERNEL"
);
/* KERNEL.194: __F000H */
sel
=
LOWORD
(
GetProcAddress16
(
hModule
,
(
LPCSTR
)(
ULONG_PTR
)
194
));
wine_ldt_get_entry
(
sel
,
&
entry
);
DOSMEM_dosmem
=
(
char
*
)
wine_ldt_get_base
(
&
entry
)
-
0xF0000
;
/* KERNEL.183: __0000H */
sel
=
LOWORD
(
GetProcAddress16
(
hModule
,
(
LPCSTR
)(
DWORD_PTR
)
183
));
wine_ldt_get_entry
(
sel
,
&
entry
);
DOSMEM_sysmem
=
wine_ldt_get_base
(
&
entry
);
/*
* Reserve either:
* - lowest 64k for NULL pointer catching (Win16)
* - lowest 1k for interrupt handlers and
* another 0.5k for BIOS, DOS and intra-application
* areas (DOS)
*/
if
(
DOSMEM_dosmem
!=
DOSMEM_sysmem
)
reserve
=
0x10000
;
/* 64k */
else
reserve
=
0x600
;
/* 1.5k */
/*
* Round to paragraph boundary in order to make
* sure the alignment is correct.
*/
reserve
=
((
reserve
+
15
)
>>
4
)
<<
4
;
/*
* Set DOS memory base and initialize conventional memory.
*/
DOSMEM_InitMemory
(
DOSMEM_dosmem
+
reserve
);
}
/******************************************************************
* DOSMEM_MapDosLayout
*
* Initialize the first MB of memory to look like a real DOS setup
*/
BOOL
DOSMEM_MapDosLayout
(
void
)
{
static
int
already_mapped
;
if
(
!
already_mapped
)
{
HMODULE16
hModule
;
unsigned
short
sel
;
LDT_ENTRY
entry
;
if
(
DOSMEM_dosmem
)
{
ERR
(
"Needs access to the first megabyte for DOS mode
\n
"
);
ExitProcess
(
1
);
}
MESSAGE
(
"Warning: unprotecting memory to allow real-mode calls.
\n
"
" NULL pointer accesses will no longer be caught.
\n
"
);
VirtualProtect
(
NULL
,
DOSMEM_SIZE
,
PAGE_EXECUTE_READWRITE
,
NULL
);
/* copy the BIOS and ISR area down */
memcpy
(
DOSMEM_dosmem
,
DOSMEM_sysmem
,
0x400
+
0x100
);
DOSMEM_sysmem
=
DOSMEM_dosmem
;
hModule
=
GetModuleHandle16
(
"KERNEL"
);
/* selector to 0000H */
sel
=
LOWORD
(
GetProcAddress16
(
hModule
,
(
LPCSTR
)(
DWORD_PTR
)
183
));
wine_ldt_get_entry
(
sel
,
&
entry
);
wine_ldt_set_base
(
&
entry
,
NULL
);
wine_ldt_set_entry
(
sel
,
&
entry
);
/* selector to BiosData */
sel
=
LOWORD
(
GetProcAddress16
(
hModule
,
(
LPCSTR
)(
DWORD_PTR
)
193
));
wine_ldt_get_entry
(
sel
,
&
entry
);
wine_ldt_set_base
(
&
entry
,
(
const
void
*
)
0x400
);
wine_ldt_set_entry
(
sel
,
&
entry
);
/* we may now need the actual interrupt stubs, and since we've just moved the
* interrupt vector table away, we can fill the area with stubs instead... */
DOSMEM_MakeIsrStubs
();
already_mapped
=
1
;
}
return
TRUE
;
}
dlls/winedos/dosvm.c
View file @
16df50ef
...
...
@@ -694,26 +694,6 @@ void WINAPI DOSVM_AcknowledgeIRQ( CONTEXT86 *context )
/**********************************************************************
* DOSVM_BiosData
*
* Get pointer to BIOS data area. This is not at fixed location
* because those Win16 programs that do not use any real mode code have
* protected NULL pointer catching block at low linear memory and
* BIOS data has been moved to another location.
*/
BIOSDATA
*
DOSVM_BiosData
(
void
)
{
LDT_ENTRY
entry
;
FARPROC16
proc
;
proc
=
GetProcAddress16
(
GetModuleHandle16
(
"KERNEL"
),
(
LPCSTR
)(
ULONG_PTR
)
193
);
wine_ldt_get_entry
(
LOWORD
(
proc
),
&
entry
);
return
(
BIOSDATA
*
)
wine_ldt_get_base
(
&
entry
);
}
/**********************************************************************
* DllMain (DOSVM.0)
*/
BOOL
WINAPI
DllMain
(
HINSTANCE
hinstDLL
,
DWORD
fdwReason
,
LPVOID
lpvReserved
)
...
...
@@ -723,6 +703,7 @@ BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
if
(
fdwReason
==
DLL_PROCESS_ATTACH
)
{
DisableThreadLibraryCalls
(
hinstDLL
);
DOSMEM_InitDosMemory
();
DOSVM_InitSegments
();
event_notifier
=
CreateEventW
(
NULL
,
FALSE
,
FALSE
,
NULL
);
...
...
dlls/winedos/int21.c
View file @
16df50ef
...
...
@@ -4904,7 +4904,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
selector
=
LOWORD
(
rv
);
}
else
DOSMEM_
Get
Block
(
bytes
,
&
selector
);
DOSMEM_
Alloc
Block
(
bytes
,
&
selector
);
if
(
selector
)
{
...
...
@@ -4934,7 +4934,7 @@ void WINAPI DOSVM_Int21Handler( CONTEXT86 *context )
context
->
SegEs
=
0
;
}
else
ok
=
DOSMEM_FreeBlock
(
(
void
*
)((
DWORD
)
context
->
SegEs
<<
4
)
);
ok
=
DOSMEM_FreeBlock
(
PTR_REAL_TO_LIN
(
context
->
SegEs
,
0
)
);
if
(
!
ok
)
{
...
...
dlls/winedos/int31.c
View file @
16df50ef
...
...
@@ -470,7 +470,7 @@ callrmproc_again:
if
(
!
already
)
{
if
(
!
context
->
SegSs
)
{
alloc
=
1
;
/* allocate default stack */
stack16
=
addr
=
DOSMEM_
Get
Block
(
64
,
(
UINT16
*
)
&
(
context
->
SegSs
)
);
stack16
=
addr
=
DOSMEM_
Alloc
Block
(
64
,
(
UINT16
*
)
&
(
context
->
SegSs
)
);
context
->
Esp
=
64
-
2
;
stack16
+=
32
-
1
;
if
(
!
addr
)
{
...
...
@@ -649,7 +649,7 @@ static RMCB *DPMI_AllocRMCB( void )
if
(
NewRMCB
)
{
LPVOID
RMCBmem
=
DOSMEM_
Get
Block
(
4
,
&
uParagraph
);
LPVOID
RMCBmem
=
DOSMEM_
Alloc
Block
(
4
,
&
uParagraph
);
LPBYTE
p
=
RMCBmem
;
*
p
++
=
0xcd
;
/* RMCB: */
...
...
@@ -968,7 +968,7 @@ void WINAPI DOSVM_Int31Handler( CONTEXT86 *context )
/* check if Win16 app wants to access lower 64K of DOS memory */
if
(
base
<
0x10000
&&
DOSVM_IsWin16
())
DOSMEM_
InitDosMem
();
DOSMEM_
MapDosLayout
();
SetSelectorBase
(
sel
,
base
);
}
...
...
dlls/winedos/module.c
View file @
16df50ef
...
...
@@ -169,7 +169,7 @@ static WORD MZ_InitEnvironment( LPCSTR env, LPCSTR name )
while
(
env
[
sz
++
])
sz
+=
strlen
(
env
+
sz
)
+
1
;
}
else
sz
++
;
/* allocate it */
envblk
=
DOSMEM_
Get
Block
(
sz
+
sizeof
(
WORD
)
+
strlen
(
name
)
+
1
,
&
seg
);
envblk
=
DOSMEM_
Alloc
Block
(
sz
+
sizeof
(
WORD
)
+
strlen
(
name
)
+
1
,
&
seg
);
/* fill it */
if
(
env
)
{
memcpy
(
envblk
,
env
,
sz
);
...
...
@@ -195,7 +195,7 @@ static BOOL MZ_InitMemory(void)
{
/* initialize the memory */
TRACE
(
"Initializing DOS memory structures
\n
"
);
DOSMEM_
InitDosMem
();
DOSMEM_
MapDosLayout
();
DOSDEV_InstallDOSDevices
();
return
TRUE
;
...
...
@@ -283,7 +283,7 @@ static BOOL MZ_DoLoadImage( HANDLE hFile, LPCSTR filename, OverlayBlock *oblk, W
goto
load_error
;
}
if
(
avail
>
max_size
)
avail
=
max_size
;
psp_start
=
DOSMEM_
Get
Block
(
avail
,
&
DOSVM_psp
);
psp_start
=
DOSMEM_
Alloc
Block
(
avail
,
&
DOSVM_psp
);
if
(
!
psp_start
)
{
ERR
(
"error allocating DOS memory
\n
"
);
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
...
...
dlls/winedos/winedos.spec
View file @
16df50ef
...
...
@@ -6,3 +6,11 @@
# I/O functions
@ stdcall inport(long long) DOSVM_inport
@ stdcall outport(long long long) DOSVM_outport
# DOS memory functions
@ cdecl FreeDosBlock(ptr) DOSMEM_FreeBlock
@ cdecl AllocDosBlock(long ptr) DOSMEM_AllocBlock
@ cdecl ResizeDosBlock(ptr long long) DOSMEM_ResizeBlock
# BIOS functions
@ cdecl BiosTick(long)
include/miscemu.h
View file @
16df50ef
...
...
@@ -26,83 +26,5 @@
#include <wine/windef16.h>
/* msdos/dosmem.c */
#include <pshpack1.h>
typedef
struct
{
WORD
Com1Addr
;
/* 00: COM1 I/O address */
WORD
Com2Addr
;
/* 02: COM2 I/O address */
WORD
Com3Addr
;
/* 04: COM3 I/O address */
WORD
Com4Addr
;
/* 06: COM4 I/O address */
WORD
Lpt1Addr
;
/* 08: LPT1 I/O address */
WORD
Lpt2Addr
;
/* 0a: LPT2 I/O address */
WORD
Lpt3Addr
;
/* 0c: LPT3 I/O address */
WORD
Lpt4Addr
;
/* 0e: LPT4 I/O address */
WORD
InstalledHardware
;
/* 10: Installed hardware flags */
BYTE
POSTstatus
;
/* 12: Power-On Self Test status */
WORD
MemSize
;
/* 13: Base memory size in Kb */
WORD
unused1
;
/* 15: Manufacturing test scratch pad */
BYTE
KbdFlags1
;
/* 17: Keyboard flags 1 */
BYTE
KbdFlags2
;
/* 18: Keyboard flags 2 */
BYTE
unused2
;
/* 19: Keyboard driver workspace */
WORD
NextKbdCharPtr
;
/* 1a: Next character in kbd buffer */
WORD
FirstKbdCharPtr
;
/* 1c: First character in kbd buffer */
WORD
KbdBuffer
[
16
];
/* 1e: Keyboard buffer */
BYTE
DisketteStatus1
;
/* 3e: Diskette recalibrate status */
BYTE
DisketteStatus2
;
/* 3f: Diskette motor status */
BYTE
DisketteStatus3
;
/* 40: Diskette motor timeout */
BYTE
DisketteStatus4
;
/* 41: Diskette last operation status */
BYTE
DiskStatus
[
7
];
/* 42: Disk status/command bytes */
BYTE
VideoMode
;
/* 49: Video mode */
WORD
VideoColumns
;
/* 4a: Number of columns */
WORD
VideoPageSize
;
/* 4c: Video page size in bytes */
WORD
VideoPageStartAddr
;
/* 4e: Video page start address */
BYTE
VideoCursorPos
[
16
];
/* 50: Cursor position for 8 pages, column/row order */
WORD
VideoCursorType
;
/* 60: Video cursor type */
BYTE
VideoCurPage
;
/* 62: Video current page */
WORD
VideoCtrlAddr
;
/* 63: Video controller address */
BYTE
VideoReg1
;
/* 65: Video mode select register */
BYTE
VideoReg2
;
/* 66: Video CGA palette register */
DWORD
ResetEntry
;
/* 67: Warm reset entry point */
BYTE
LastIRQ
;
/* 6b: Last unexpected interrupt */
DWORD
Ticks
;
/* 6c: Ticks since midnight */
BYTE
TicksOverflow
;
/* 70: Timer overflow if past midnight */
BYTE
CtrlBreakFlag
;
/* 71: Ctrl-Break flag */
WORD
ResetFlag
;
/* 72: POST Reset flag */
BYTE
DiskOpStatus
;
/* 74: Last hard-disk operation status */
BYTE
NbHardDisks
;
/* 75: Number of hard disks */
BYTE
DiskCtrlByte
;
/* 76: Disk control byte */
BYTE
DiskIOPort
;
/* 77: Disk I/O port offset */
BYTE
LptTimeout
[
4
];
/* 78: Timeouts for parallel ports */
BYTE
ComTimeout
[
4
];
/* 7c: Timeouts for serial ports */
WORD
KbdBufferStart
;
/* 80: Keyboard buffer start */
WORD
KbdBufferEnd
;
/* 82: Keyboard buffer end */
BYTE
RowsOnScreenMinus1
;
/* 84: EGA only */
WORD
BytesPerChar
;
/* 85: EGA only */
BYTE
ModeOptions
;
/* 87: EGA only */
BYTE
FeatureBitsSwitches
;
/* 88: EGA only */
BYTE
VGASettings
;
/* 89: VGA misc settings */
BYTE
DisplayCombination
;
/* 8A: VGA display combinations */
BYTE
DiskDataRate
;
/* 8B: Last disk data rate selected */
}
BIOSDATA
;
#include <poppack.h>
extern
WORD
DOSMEM_0000H
;
extern
WORD
DOSMEM_BiosDataSeg
;
extern
WORD
DOSMEM_BiosSysSeg
;
/* msdos/dosmem.c */
extern
BOOL
DOSMEM_Init
(
void
);
extern
BOOL
DOSMEM_InitDosMem
(
void
);
extern
void
DOSMEM_Tick
(
WORD
timer
);
extern
WORD
DOSMEM_AllocSelector
(
WORD
);
extern
LPVOID
DOSMEM_GetBlock
(
UINT
size
,
WORD
*
p
);
extern
BOOL
DOSMEM_FreeBlock
(
void
*
ptr
);
extern
UINT
DOSMEM_ResizeBlock
(
void
*
ptr
,
UINT
size
,
BOOL
exact
);
extern
UINT
DOSMEM_Available
(
void
);
extern
LPVOID
DOSMEM_MapRealToLinear
(
DWORD
);
/* real-mode to linear */
extern
LPVOID
DOSMEM_MapDosToLinear
(
UINT
);
/* linear DOS to Wine */
extern
UINT
DOSMEM_MapLinearToDos
(
LPVOID
);
/* linear Wine to DOS */
#endif
/* __WINE_MISCEMU_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment