mirror of
https://github.com/retro100/dosbox-wii.git
synced 2024-12-26 02:21:49 +01:00
DOSBox 0.55
This commit is contained in:
parent
acd61d619e
commit
0284615f36
5
AUTHORS
5
AUTHORS
@ -3,6 +3,5 @@ The DOSBox Team
|
|||||||
|
|
||||||
Sjoerd v.d. Berg <harekiet@zophar.net>
|
Sjoerd v.d. Berg <harekiet@zophar.net>
|
||||||
Peter Veenstra <qbix79@users.sourceforge.net>
|
Peter Veenstra <qbix79@users.sourceforge.net>
|
||||||
|
Felix Jakschitsch <yot@users.sourceforge.net>
|
||||||
|
Ulf Wohlers <finsterr@users.sourceforge.net>
|
||||||
|
|
||||||
|
27
ChangeLog
27
ChangeLog
@ -1,3 +1,26 @@
|
|||||||
- fixed the errors/warnings in prefix_66.h and prefix_66_of.h (decimal too large becomming unsigned).
|
- fixed the errors/warnings in prefix_66.h and prefix_66_of.h (decimal too large becomming unsigned).
|
||||||
|
- fixed compilation error on FreeBSD when #disable_joystick was defined
|
||||||
|
- int10_writechar has been updated to move the cursor position.
|
||||||
|
- changed the basedir routines to use the current working dir instead of argv[0]. This will fix and brake things :)
|
||||||
|
- illegal command, now displays the command
|
||||||
|
- wildcmp updated to be case insensitive
|
||||||
|
- added fcb:open,close,findfirst, findnext.
|
||||||
|
- fixed rename in drive_local
|
||||||
|
- added new features to the debugger: breakpoint support / data view / command line
|
||||||
|
- partial support of list of lists (dos info block)
|
||||||
|
- full emm 3.2 support
|
||||||
|
- partial emm 4.0 support
|
||||||
|
- fixes to graphics core fonts (text in sierra games is now correct)
|
||||||
|
- improved support for user mousehandlers
|
||||||
|
- fixed EGA graphics
|
||||||
|
- fixed VGA graphics
|
||||||
|
- fixed write with size 0
|
||||||
|
- changed memory management.
|
||||||
|
- fixed and cleaned up the cpu flags.
|
||||||
|
- changed interrupt handler.
|
||||||
|
- speeded up the graphics.
|
||||||
|
- speeded up the cpu-core
|
||||||
|
- changed dma
|
||||||
|
- improved dma streams from emm memory
|
||||||
|
- added some cga videomodes
|
||||||
|
- added more funtions to the keyboard handler
|
||||||
|
23
NEWS
23
NEWS
@ -1,3 +1,26 @@
|
|||||||
|
0.55:
|
||||||
|
- changed basedir handling. (linux/winXP)
|
||||||
|
- added some FCB-calls
|
||||||
|
- improved support for user mousehandlers
|
||||||
|
- fixed EGA graphics
|
||||||
|
- fixed VGA graphics
|
||||||
|
- fixed the displaying of text in some graphics modes
|
||||||
|
- fixed write with size 0
|
||||||
|
- changed memory management.
|
||||||
|
- added full emm 3.2 support.
|
||||||
|
- fixed and cleaned up the cpu flags.
|
||||||
|
changed interrupt handler.
|
||||||
|
- speeded up the graphics.
|
||||||
|
- speeded up the cpu-core
|
||||||
|
- added new features to the debugger: breakpoint support / data view / command line
|
||||||
|
- partial support of list of lists (dos info block)
|
||||||
|
- partial emm 4.0 support
|
||||||
|
- fixes to graphics core fonts (text in sierra games is now correct)
|
||||||
|
- changed dma
|
||||||
|
- improved dma streams from emm memory
|
||||||
|
- added some cga videomodes
|
||||||
|
- added more funtions to the keyboard handler
|
||||||
|
|
||||||
0.50:
|
0.50:
|
||||||
-added F3 to repeat the last typed command.
|
-added F3 to repeat the last typed command.
|
||||||
-made it possible to change the shellmessages(dosshell). so
|
-made it possible to change the shellmessages(dosshell). so
|
||||||
|
33
acinclude.m4
33
acinclude.m4
@ -159,3 +159,36 @@ int main (int argc, char *argv[])
|
|||||||
AC_SUBST(SDL_LIBS)
|
AC_SUBST(SDL_LIBS)
|
||||||
rm -f conf.sdltest
|
rm -f conf.sdltest
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AH_TOP([
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 The DOSBox Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
])
|
||||||
|
|
||||||
|
AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures])
|
||||||
|
|
||||||
|
AH_BOTTOM([#define INLINE inline])
|
||||||
|
|
||||||
|
AH_BOTTOM([#if C_HAS_ATTRIBUTE
|
||||||
|
#define GCC_ATTRIBUTE(x) __attribute__ ((x))
|
||||||
|
#else
|
||||||
|
#define GCC_ATTRIBUTE(x) /* attribute not supported */
|
||||||
|
#endif])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
33
aclocal.m4
vendored
33
aclocal.m4
vendored
@ -173,6 +173,39 @@ int main (int argc, char *argv[])
|
|||||||
rm -f conf.sdltest
|
rm -f conf.sdltest
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AH_TOP([
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 The DOSBox Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
])
|
||||||
|
|
||||||
|
AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures])
|
||||||
|
|
||||||
|
AH_BOTTOM([#define INLINE inline])
|
||||||
|
|
||||||
|
AH_BOTTOM([#if C_HAS_ATTRIBUTE
|
||||||
|
#define GCC_ATTRIBUTE(x) __attribute__ ((x))
|
||||||
|
#else
|
||||||
|
#define GCC_ATTRIBUTE(x) /* attribute not supported */
|
||||||
|
#endif])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Do all the work for Automake. -*- Autoconf -*-
|
# Do all the work for Automake. -*- Autoconf -*-
|
||||||
|
|
||||||
# This macro actually does too much some checks are only needed if
|
# This macro actually does too much some checks are only needed if
|
||||||
|
13
autogen.sh
13
autogen.sh
@ -1,18 +1,17 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
|
||||||
echo "Generating build information using aclocal, auotheader, automake and autoconf"
|
echo "Generating build information using aclocal, autoheader, automake and autoconf"
|
||||||
echo "This may take a while ..."
|
echo "This may take a while ..."
|
||||||
|
|
||||||
# Touch the timestamps on all the files since CVS messes them up
|
# Regenerate configuration files.
|
||||||
directory=`dirname $0`
|
|
||||||
touch $directory/configure.in
|
|
||||||
|
|
||||||
# Regenerate configuration files
|
|
||||||
|
|
||||||
aclocal
|
aclocal
|
||||||
autoheader
|
autoheader
|
||||||
automake --gnits --include-deps --add-missing --copy
|
automake --gnits --include-deps --add-missing --copy
|
||||||
autoconf
|
autoconf
|
||||||
|
|
||||||
|
#Copy settings.h.cvs to settings.h and that's it,
|
||||||
|
|
||||||
|
directory=`dirname $0`
|
||||||
cp $directory/settings.h.cvs $directory/settings.h
|
cp $directory/settings.h.cvs $directory/settings.h
|
||||||
echo "Now you are ready to run ./configure also check settings.h for extra build settings"
|
echo "Now you are ready to run ./configure also check settings.h for extra build settings"
|
||||||
|
31
config.h.in
31
config.h.in
@ -1,5 +1,28 @@
|
|||||||
/* config.h.in. Generated from configure.in by autoheader. */
|
/* config.h.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2002 The DOSBox Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Determines if the compilers supports attributes for structures */
|
||||||
|
#undef C_HAS_ATTRIBUTE
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||||
#undef HAVE_INTTYPES_H
|
#undef HAVE_INTTYPES_H
|
||||||
|
|
||||||
@ -63,3 +86,11 @@
|
|||||||
|
|
||||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||||
#undef size_t
|
#undef size_t
|
||||||
|
|
||||||
|
#define INLINE inline
|
||||||
|
|
||||||
|
#if C_HAS_ATTRIBUTE
|
||||||
|
#define GCC_ATTRIBUTE(x) __attribute__ ((x))
|
||||||
|
#else
|
||||||
|
#define GCC_ATTRIBUTE(x) /* attribute not supported */
|
||||||
|
#endif
|
||||||
|
65
configure
vendored
65
configure
vendored
@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.53a for dosbox 0.50.
|
# Generated by GNU Autoconf 2.53a for dosbox 0.55.
|
||||||
#
|
#
|
||||||
# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
|
# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
|
||||||
# Free Software Foundation, Inc.
|
# Free Software Foundation, Inc.
|
||||||
@ -272,8 +272,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='dosbox'
|
PACKAGE_NAME='dosbox'
|
||||||
PACKAGE_TARNAME='dosbox'
|
PACKAGE_TARNAME='dosbox'
|
||||||
PACKAGE_VERSION='0.50'
|
PACKAGE_VERSION='0.55'
|
||||||
PACKAGE_STRING='dosbox 0.50'
|
PACKAGE_STRING='dosbox 0.55'
|
||||||
PACKAGE_BUGREPORT=''
|
PACKAGE_BUGREPORT=''
|
||||||
|
|
||||||
ac_unique_file="README"
|
ac_unique_file="README"
|
||||||
@ -786,7 +786,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures dosbox 0.50 to adapt to many kinds of systems.
|
\`configure' configures dosbox 0.55 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -853,7 +853,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of dosbox 0.50:";;
|
short | recursive ) echo "Configuration of dosbox 0.55:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -946,7 +946,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit 0
|
test -n "$ac_init_help" && exit 0
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
dosbox configure 0.50
|
dosbox configure 0.55
|
||||||
generated by GNU Autoconf 2.53a
|
generated by GNU Autoconf 2.53a
|
||||||
|
|
||||||
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
|
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
|
||||||
@ -961,7 +961,7 @@ cat >&5 <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by dosbox $as_me 0.50, which was
|
It was created by dosbox $as_me 0.55, which was
|
||||||
generated by GNU Autoconf 2.53a. Invocation command line was
|
generated by GNU Autoconf 2.53a. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -1579,7 +1579,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE=dosbox
|
PACKAGE=dosbox
|
||||||
VERSION=0.50
|
VERSION=0.55
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -4232,9 +4232,52 @@ _ACEOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
#Check if the compiler support attributes
|
||||||
|
echo "$as_me:$LINENO: checking if compiler allows __attribute__" >&5
|
||||||
|
echo $ECHO_N "checking if compiler allows __attribute__... $ECHO_C" >&6
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
#line $LINENO "configure"
|
||||||
|
#include "confdefs.h"
|
||||||
|
|
||||||
|
#ifdef F77_DUMMY_MAIN
|
||||||
|
# ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
# endif
|
||||||
|
int F77_DUMMY_MAIN() { return 1; }
|
||||||
|
#endif
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
typedef struct { } __attribute__ ((packed)) junk;
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext
|
||||||
|
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||||
|
(eval $ac_compile) 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } &&
|
||||||
|
{ ac_try='test -s conftest.$ac_objext'
|
||||||
|
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||||
|
(eval $ac_try) 2>&5
|
||||||
|
ac_status=$?
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); }; }; then
|
||||||
|
echo "$as_me:$LINENO: result: yes" >&5
|
||||||
|
echo "${ECHO_T}yes" >&6;cat >>confdefs.h <<\_ACEOF
|
||||||
|
#define C_HAS_ATTRIBUTE 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
cat conftest.$ac_ext >&5
|
||||||
|
echo "$as_me:$LINENO: result: no" >&5
|
||||||
|
echo "${ECHO_T}no" >&6
|
||||||
|
fi
|
||||||
|
rm -f conftest.$ac_objext conftest.$ac_ext
|
||||||
|
|
||||||
#Always include the standard include dir in all makefiless
|
|
||||||
|
|
||||||
ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_16/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/ints/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc/Makefile include/Makefile"
|
ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_16/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/ints/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc/Makefile include/Makefile"
|
||||||
cat >confcache <<\_ACEOF
|
cat >confcache <<\_ACEOF
|
||||||
@ -4594,7 +4637,7 @@ _ASBOX
|
|||||||
} >&5
|
} >&5
|
||||||
cat >&5 <<_CSEOF
|
cat >&5 <<_CSEOF
|
||||||
|
|
||||||
This file was extended by dosbox $as_me 0.50, which was
|
This file was extended by dosbox $as_me 0.55, which was
|
||||||
generated by GNU Autoconf 2.53a. Invocation command line was
|
generated by GNU Autoconf 2.53a. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@ -4656,7 +4699,7 @@ _ACEOF
|
|||||||
|
|
||||||
cat >>$CONFIG_STATUS <<_ACEOF
|
cat >>$CONFIG_STATUS <<_ACEOF
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
dosbox config.status 0.50
|
dosbox config.status 0.55
|
||||||
configured by $0, generated by GNU Autoconf 2.53a,
|
configured by $0, generated by GNU Autoconf 2.53a,
|
||||||
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
dnl Init.
|
dnl Init.
|
||||||
AC_INIT(dosbox,0.50)
|
AC_INIT(dosbox,0.55)
|
||||||
AC_CONFIG_SRCDIR(README)
|
AC_CONFIG_SRCDIR(README)
|
||||||
|
|
||||||
dnl Detect the canonical host and target build environment
|
dnl Detect the canonical host and target build environment
|
||||||
@ -36,11 +36,12 @@ AC_C_INLINE
|
|||||||
AC_TYPE_SIZE_T
|
AC_TYPE_SIZE_T
|
||||||
AC_STRUCT_TM
|
AC_STRUCT_TM
|
||||||
|
|
||||||
dnl Checks for library functions.
|
#Check if the compiler support attributes
|
||||||
|
AC_MSG_CHECKING(if compiler allows __attribute__)
|
||||||
|
AC_TRY_COMPILE([], [typedef struct { } __attribute__ ((packed)) junk;],
|
||||||
|
[ AC_MSG_RESULT(yes);AC_DEFINE(C_HAS_ATTRIBUTE)],AC_MSG_RESULT(no))
|
||||||
|
|
||||||
|
|
||||||
#Always include the standard include dir in all makefiless
|
|
||||||
|
|
||||||
AC_OUTPUT([
|
AC_OUTPUT([
|
||||||
Makefile
|
Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
/* #define bios_keyboard_buffer (*(unsigned int *) 0x41e) */
|
/* #define bios_keyboard_buffer (*(unsigned int *) 0x41e) */
|
||||||
#define BIOS_DRIVE_ACTIVE 0x43e
|
#define BIOS_DRIVE_ACTIVE 0x43e
|
||||||
#define BIOS_DRIVE_RUNNING 0x43f
|
#define BIOS_DRIVE_RUNNING 0x43f
|
||||||
#define BIOS_MOTOR_NACHLAUFZEIT 0x440
|
#define BIOS_DISK_MOTOR_TIMEOUT 0x440
|
||||||
#define BIOS_DISK_STATUS 0x441
|
#define BIOS_DISK_STATUS 0x441
|
||||||
/* #define bios_fdc_result_buffer (*(unsigned short *) 0x442) */
|
/* #define bios_fdc_result_buffer (*(unsigned short *) 0x442) */
|
||||||
#define BIOS_VIDEO_MODE 0x449
|
#define BIOS_VIDEO_MODE 0x449
|
||||||
|
@ -29,12 +29,8 @@ typedef Bitu (CPU_Decoder)(Bitu count);
|
|||||||
extern CPU_Decoder * cpudecoder;
|
extern CPU_Decoder * cpudecoder;
|
||||||
extern Bit32u cpu_cycles;
|
extern Bit32u cpu_cycles;
|
||||||
|
|
||||||
|
|
||||||
extern Bit32u hoever;
|
|
||||||
|
|
||||||
//CPU Stuff
|
//CPU Stuff
|
||||||
void SetCPU16bit();
|
void SetCPU16bit();
|
||||||
void SetSegment_16(Bit32u seg,Bit16u val);
|
|
||||||
|
|
||||||
|
|
||||||
//Types of Flag changing instructions
|
//Types of Flag changing instructions
|
||||||
@ -80,20 +76,11 @@ bool get_SF(void);
|
|||||||
bool get_OF(void);
|
bool get_OF(void);
|
||||||
bool get_PF(void);
|
bool get_PF(void);
|
||||||
|
|
||||||
Bit8u get_Flags8(void);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define LoadCF flags.cf=get_CF();
|
#define LoadCF flags.cf=get_CF();
|
||||||
#define LoadZF flags.zf=get_ZF();
|
#define LoadZF flags.zf=get_ZF();
|
||||||
#define LoadSF flags.sf=get_SF();
|
#define LoadSF flags.sf=get_SF();
|
||||||
#define LoadOF flags.of=get_OF();
|
#define LoadOF flags.of=get_OF();
|
||||||
//The opcode handlers
|
|
||||||
|
|
||||||
|
|
||||||
void FPU_ESC0_Normal(Bitu rm);
|
|
||||||
void FPU_ESC0_EA(Bitu func,PhysOff ea);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -46,7 +46,9 @@
|
|||||||
#define CROSS_NONE 0
|
#define CROSS_NONE 0
|
||||||
#define CROSS_FILE 1
|
#define CROSS_FILE 1
|
||||||
#define CROSS_DIR 2
|
#define CROSS_DIR 2
|
||||||
|
#if defined (_MSC_VER)
|
||||||
|
#define ftruncate(blah,blah2) chsize(blah,blah2)
|
||||||
|
#endif
|
||||||
|
|
||||||
extern const char * dosbox_datadir;
|
extern const char * dosbox_datadir;
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
void DEBUG_DrawScreen(void);
|
void DEBUG_DrawScreen(void);
|
||||||
bool DEBUG_BreakPoint(void);
|
bool DEBUG_BreakPoint(void);
|
||||||
|
bool DEBUG_IntBreakpoint(Bit8u intNum);
|
||||||
void DEBUG_Enable(void);
|
void DEBUG_Enable(void);
|
||||||
|
|
||||||
extern Bitu cycle_count;
|
extern Bitu cycle_count;
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DMA_8_Read(Bit32u channel,Bit8u * buffer,Bit16u count);
|
|
||||||
void DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count);
|
|
||||||
|
|
||||||
void DMA_16_Read(Bit32u channel,Bit8u * buffer,Bit16u count);
|
Bit16u DMA_8_Read(Bit32u channel,Bit8u * buffer,Bit16u count);
|
||||||
void DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count);
|
Bit16u DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count);
|
||||||
|
|
||||||
|
Bit16u DMA_16_Read(Bit32u channel,Bit8u * buffer,Bit16u count);
|
||||||
|
Bit16u DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count);
|
||||||
|
|
||||||
|
@ -22,12 +22,12 @@
|
|||||||
#include <dos_system.h>
|
#include <dos_system.h>
|
||||||
#include <mem.h>
|
#include <mem.h>
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack (1)
|
||||||
|
|
||||||
struct CommandTail{
|
struct CommandTail{
|
||||||
Bit8u count; /* number of bytes returned */
|
Bit8u count; /* number of bytes returned */
|
||||||
char buffer[127]; /* the buffer itself */
|
char buffer[127]; /* the buffer itself */
|
||||||
};
|
} GCC_ATTRIBUTE(packed);
|
||||||
|
|
||||||
struct PSP {
|
struct PSP {
|
||||||
Bit8u exit[2]; /* CP/M-like exit poimt */
|
Bit8u exit[2]; /* CP/M-like exit poimt */
|
||||||
@ -55,7 +55,7 @@ struct PSP {
|
|||||||
|
|
||||||
CommandTail cmdtail;
|
CommandTail cmdtail;
|
||||||
|
|
||||||
};
|
} GCC_ATTRIBUTE(packed);
|
||||||
|
|
||||||
struct ParamBlock {
|
struct ParamBlock {
|
||||||
union {
|
union {
|
||||||
@ -72,7 +72,8 @@ struct ParamBlock {
|
|||||||
RealPt initcsip;
|
RealPt initcsip;
|
||||||
} exec;
|
} exec;
|
||||||
};
|
};
|
||||||
};
|
} GCC_ATTRIBUTE(packed);
|
||||||
|
|
||||||
|
|
||||||
struct MCB {
|
struct MCB {
|
||||||
Bit8u type;
|
Bit8u type;
|
||||||
@ -80,23 +81,9 @@ struct MCB {
|
|||||||
Bit16u size;
|
Bit16u size;
|
||||||
Bit8u unused[3];
|
Bit8u unused[3];
|
||||||
Bit8u filename[8];
|
Bit8u filename[8];
|
||||||
};
|
} GCC_ATTRIBUTE(packed);
|
||||||
|
|
||||||
struct FCB {
|
#pragma pack ()
|
||||||
Bit8u drive; //0 is current drive. when opened 0 is replaced by drivenumber
|
|
||||||
Bit8u filename[8]; //spacepadded to fit
|
|
||||||
Bit8u ext[3]; //spacepadded to fit
|
|
||||||
Bit16u current_block; // set to 0 by open
|
|
||||||
Bit16u record_size; // used by reads Set to 80h by OPEN function
|
|
||||||
Bit32u filesize; //in bytes In this field, the first word is the low-order part of the size
|
|
||||||
Bit16u date;
|
|
||||||
Bit16u time;
|
|
||||||
Bit8u reserved[8];
|
|
||||||
Bit8u current_relative_record_number; //open doesn't set this
|
|
||||||
Bit32u rel_record; //open does not handle this
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma pack()
|
|
||||||
|
|
||||||
struct DOS_Date {
|
struct DOS_Date {
|
||||||
Bit16u year;
|
Bit16u year;
|
||||||
@ -125,7 +112,6 @@ struct DOS_Block {
|
|||||||
struct {
|
struct {
|
||||||
RealPt indosflag;
|
RealPt indosflag;
|
||||||
} tables;
|
} tables;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
|
enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
|
||||||
@ -157,20 +143,21 @@ bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount);
|
|||||||
bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type);
|
bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type);
|
||||||
bool DOS_CloseFile(Bit16u handle);
|
bool DOS_CloseFile(Bit16u handle);
|
||||||
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry);
|
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry);
|
||||||
|
bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry);
|
||||||
/* Routines for Drive Class */
|
/* Routines for Drive Class */
|
||||||
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry);
|
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry);
|
||||||
bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry);
|
bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry);
|
||||||
bool DOS_UnlinkFile(char * name);
|
bool DOS_UnlinkFile(char * name);
|
||||||
bool DOS_FindFirst(char *search,Bit16u attr);
|
bool DOS_FindFirst(char *search,Bit16u attr);
|
||||||
bool DOS_FindNext(void);
|
bool DOS_FindNext(void);
|
||||||
bool DOS_Canonicalize(char * small,Bit8u * big);
|
bool DOS_Canonicalize(char * name,char * big);
|
||||||
bool DOS_CreateTempFile(char * name,Bit16u * entry);
|
bool DOS_CreateTempFile(char * name,Bit16u * entry);
|
||||||
bool DOS_FileExists(char * name);
|
bool DOS_FileExists(char * name);
|
||||||
/* Drive Handing Routines */
|
/* Drive Handing Routines */
|
||||||
Bit8u DOS_GetDefaultDrive(void);
|
Bit8u DOS_GetDefaultDrive(void);
|
||||||
void DOS_SetDefaultDrive(Bit8u drive);
|
void DOS_SetDefaultDrive(Bit8u drive);
|
||||||
bool DOS_SetDrive(Bit8u drive);
|
bool DOS_SetDrive(Bit8u drive);
|
||||||
bool DOS_GetCurrentDir(Bit8u drive,Bit8u * buffer);
|
bool DOS_GetCurrentDir(Bit8u drive,char * bugger);
|
||||||
bool DOS_ChangeDir(char * dir);
|
bool DOS_ChangeDir(char * dir);
|
||||||
bool DOS_MakeDir(char * dir);
|
bool DOS_MakeDir(char * dir);
|
||||||
bool DOS_RemoveDir(char * dir);
|
bool DOS_RemoveDir(char * dir);
|
||||||
@ -195,6 +182,13 @@ bool DOS_FreeMemory(Bit16u segment);
|
|||||||
void DOS_FreeProcessMemory(Bit16u pspseg);
|
void DOS_FreeProcessMemory(Bit16u pspseg);
|
||||||
Bit16u DOS_GetMemory(Bit16u pages);
|
Bit16u DOS_GetMemory(Bit16u pages);
|
||||||
|
|
||||||
|
|
||||||
|
/* FCB stuff */
|
||||||
|
bool DOS_FCBOpen(Bit16u seg,Bit16u offset);
|
||||||
|
bool DOS_FCBClose(Bit16u seg,Bit16u offset);
|
||||||
|
bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset);
|
||||||
|
bool DOS_FCBFindNext(Bit16u seg,Bit16u offset);
|
||||||
|
Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change);
|
||||||
/* Extra DOS Interrupts */
|
/* Extra DOS Interrupts */
|
||||||
void DOS_SetupMisc(void);
|
void DOS_SetupMisc(void);
|
||||||
|
|
||||||
@ -211,8 +205,8 @@ INLINE Bit16u long2para(Bit32u size) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
INLINE Bit8u RealHandle(Bit16u handle) {
|
INLINE Bit8u RealHandle(Bit16u handle) {
|
||||||
PSP * psp=(PSP *)real_off(dos.psp,0);
|
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||||
if (handle>=psp->max_files) return DOS_FILES;
|
if (handle>=psp->max_files) return 0xff;
|
||||||
return mem_readb(Real2Phys(psp->file_table)+handle);
|
return mem_readb(Real2Phys(psp->file_table)+handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -245,7 +239,7 @@ public:
|
|||||||
off=pt;
|
off=pt;
|
||||||
}
|
}
|
||||||
DOS_FCB(Bit16u seg, Bit16u offset){
|
DOS_FCB(Bit16u seg, Bit16u offset){
|
||||||
off=Real2Phys(RealMake(seg,offset));
|
off=PhysMake(seg,offset);
|
||||||
}
|
}
|
||||||
void Set_drive(Bit8u a);
|
void Set_drive(Bit8u a);
|
||||||
void Set_filename(char* a); //writes an the first 8 bytes of a as the filename
|
void Set_filename(char* a); //writes an the first 8 bytes of a as the filename
|
||||||
@ -270,6 +264,54 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DOS_ParamBlock {
|
||||||
|
public:
|
||||||
|
DOS_ParamBlock(PhysPt pt){
|
||||||
|
off=pt;
|
||||||
|
};
|
||||||
|
void InitExec(RealPt cmdtail);
|
||||||
|
Bit16u loadseg(void);
|
||||||
|
Bit16u relocation(void);
|
||||||
|
Bit16u envseg(void);
|
||||||
|
RealPt initsssp(void);
|
||||||
|
RealPt initcsip(void);
|
||||||
|
RealPt fcb1(void);
|
||||||
|
RealPt fcb2(void);
|
||||||
|
RealPt cmdtail(void);
|
||||||
|
private:
|
||||||
|
PhysPt off;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DOS_InfoBlock {
|
||||||
|
public:
|
||||||
|
DOS_InfoBlock (void) { seg=0; dib=0; };
|
||||||
|
|
||||||
|
void SetLocation (Bit16u segment);
|
||||||
|
void SetFirstMCB (RealPt pt);
|
||||||
|
void GetDIBPointer (Bit16u& segment, Bit16u& offset);
|
||||||
|
|
||||||
|
private:
|
||||||
|
#pragma pack (push,1)
|
||||||
|
struct SDosInfoBlock {
|
||||||
|
Bit8u stuff1[22]; // some stuff, hopefully never used....
|
||||||
|
RealPt firstMCB; // first memory control block
|
||||||
|
RealPt firstDPB; // first drive parameter block
|
||||||
|
RealPt firstFileTable; // first system file table
|
||||||
|
RealPt activeClock; // active clock device header
|
||||||
|
RealPt activeCon; // active console device header
|
||||||
|
Bit16u maxSectorLength; // maximum bytes per sector of any block device;
|
||||||
|
RealPt discInfoBuffer; // pointer to disc info buffer
|
||||||
|
RealPt curDirStructure; // pointer to current array of directory structure
|
||||||
|
RealPt fcbTable; // pointer to system FCB table
|
||||||
|
// some more stuff, hopefully never used.
|
||||||
|
} GCC_ATTRIBUTE(packed);
|
||||||
|
#pragma pack (pop)
|
||||||
|
|
||||||
|
SDosInfoBlock* dib;
|
||||||
|
Bit16u seg;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DOS_InfoBlock dosInfoBlock;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -35,7 +35,9 @@ enum {
|
|||||||
DOS_ATTR_ARCHIVE= 0x20
|
DOS_ATTR_ARCHIVE= 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack (1)
|
#if defined (_MSC_VER)
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
struct DTA_FindBlock {
|
struct DTA_FindBlock {
|
||||||
Bit8u sdrive; /* The Drive the search is taking place */
|
Bit8u sdrive; /* The Drive the search is taking place */
|
||||||
Bit16u sattr; /* The attributes that need to be found */
|
Bit16u sattr; /* The attributes that need to be found */
|
||||||
@ -45,8 +47,13 @@ struct DTA_FindBlock {
|
|||||||
Bit16u date;
|
Bit16u date;
|
||||||
Bit32u size;
|
Bit32u size;
|
||||||
char name[DOS_NAMELENGTH];
|
char name[DOS_NAMELENGTH];
|
||||||
};
|
}
|
||||||
#pragma pack ()
|
#if defined (_MSC_VER)
|
||||||
|
;
|
||||||
|
#pragma pack()
|
||||||
|
#else
|
||||||
|
__attribute__ ((packed));
|
||||||
|
#endif
|
||||||
|
|
||||||
class DOS_File {
|
class DOS_File {
|
||||||
public:
|
public:
|
||||||
@ -82,6 +89,8 @@ public:
|
|||||||
virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
|
virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
|
||||||
virtual bool Rename(char * oldname,char * newname)=0;
|
virtual bool Rename(char * oldname,char * newname)=0;
|
||||||
virtual bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free)=0;
|
virtual bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free)=0;
|
||||||
|
virtual bool FileExists(const char* name) const=0;
|
||||||
|
virtual bool FileStat(const char* name, struct stat* const stat_block) const=0;
|
||||||
char * GetInfo(void);
|
char * GetInfo(void);
|
||||||
char curdir[DOS_PATHLENGTH];
|
char curdir[DOS_PATHLENGTH];
|
||||||
char info[256];
|
char info[256];
|
||||||
|
@ -19,45 +19,43 @@
|
|||||||
#if !defined __DOSBOX_H
|
#if !defined __DOSBOX_H
|
||||||
#define __DOSBOX_H
|
#define __DOSBOX_H
|
||||||
|
|
||||||
typedef unsigned char Bit8u;
|
|
||||||
typedef signed char Bit8s;
|
void E_Exit(char * message,...);
|
||||||
typedef unsigned short Bit16u;
|
|
||||||
typedef signed short Bit16s;
|
void S_Warn(char * message,...);
|
||||||
typedef unsigned long Bit32u;
|
|
||||||
typedef signed long Bit32s;
|
/* The internal types */
|
||||||
|
typedef unsigned char Bit8u;
|
||||||
|
typedef signed char Bit8s;
|
||||||
|
typedef unsigned short Bit16u;
|
||||||
|
typedef signed short Bit16s;
|
||||||
|
typedef unsigned long Bit32u;
|
||||||
|
typedef signed long Bit32s;
|
||||||
|
typedef double Real64;
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
typedef unsigned __int64 Bit64u;
|
typedef unsigned __int64 Bit64u;
|
||||||
typedef signed __int64 Bit64s;
|
typedef signed __int64 Bit64s;
|
||||||
#else
|
#else
|
||||||
typedef unsigned long long int Bit64u;
|
typedef unsigned long long Bit64u;
|
||||||
typedef signed long long int Bit64s;
|
typedef signed long long Bit64s;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef unsigned int Bitu;
|
typedef unsigned int Bitu;
|
||||||
typedef signed int Bits;
|
typedef signed int Bits;
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include "config.h"
|
||||||
void E_Exit(char * message,...);
|
#include "../settings.h"
|
||||||
|
|
||||||
void S_Warn(char * message,...);
|
|
||||||
|
|
||||||
|
|
||||||
#include "../settings.h" /* General extra setting */
|
|
||||||
#if defined (_MSC_VER)
|
|
||||||
#include "../src/platform/visualc/config.h"
|
|
||||||
#else
|
|
||||||
#include "../config.h"
|
|
||||||
#define INLINE inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef Bitu (LoopHandler)(void);
|
typedef Bitu (LoopHandler)(void);
|
||||||
|
|
||||||
void DOSBOX_RunMachine();
|
void DOSBOX_RunMachine();
|
||||||
void DOSBOX_SetLoop(LoopHandler * handler);
|
void DOSBOX_SetLoop(LoopHandler * handler);
|
||||||
|
void DOSBOX_SetNormalLoop();
|
||||||
|
|
||||||
void DOSBOX_Init(int argc, char* argv[]);
|
void DOSBOX_Init(int argc, char* argv[]);
|
||||||
void DOSBOX_StartUp(void);
|
void DOSBOX_StartUp(void);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002 The DOSBox Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FPU_H
|
||||||
|
#define __FPU_H
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
void FPU_ESC0_Normal(Bitu rm);
|
||||||
|
void FPU_ESC0_EA(Bitu func,PhysPt ea);
|
||||||
|
void FPU_ESC1_Normal(Bitu rm);
|
||||||
|
void FPU_ESC1_EA(Bitu func,PhysPt ea);
|
||||||
|
void FPU_ESC2_Normal(Bitu rm);
|
||||||
|
void FPU_ESC2_EA(Bitu func,PhysPt ea);
|
||||||
|
void FPU_ESC3_Normal(Bitu rm);
|
||||||
|
void FPU_ESC3_EA(Bitu func,PhysPt ea);
|
||||||
|
void FPU_ESC4_Normal(Bitu rm);
|
||||||
|
void FPU_ESC4_EA(Bitu func,PhysPt ea);
|
||||||
|
void FPU_ESC5_Normal(Bitu rm);
|
||||||
|
void FPU_ESC5_EA(Bitu func,PhysPt ea);
|
||||||
|
void FPU_ESC6_Normal(Bitu rm);
|
||||||
|
void FPU_ESC6_EA(Bitu func,PhysPt ea);
|
||||||
|
void FPU_ESC7_Normal(Bitu rm);
|
||||||
|
void FPU_ESC7_EA(Bitu func,PhysPt ea);
|
||||||
|
|
||||||
|
#define FPU_ESC(code) { \
|
||||||
|
Bit8u rm=Fetchb(); \
|
||||||
|
if (rm>=0xc0) { \
|
||||||
|
FPU_ESC ## code ## _Normal(rm); \
|
||||||
|
} else { \
|
||||||
|
GetEAa;FPU_ESC ## code ## _EA(rm,eaa); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
176
include/mem.h
176
include/mem.h
@ -20,79 +20,62 @@
|
|||||||
#define __MEM_H
|
#define __MEM_H
|
||||||
#include <dosbox.h>
|
#include <dosbox.h>
|
||||||
|
|
||||||
enum { MEMORY_HANDLER=1,MEMORY_RELOCATE=2};
|
|
||||||
|
|
||||||
#define bmemcpy(mem1,mem2,size) memcpy((void *)mem1,(void *)mem2,size)
|
#define bmemcpy(mem1,mem2,size) memcpy((void *)mem1,(void *)mem2,size)
|
||||||
|
|
||||||
typedef Bit8u (MEMORY_ReadHandler)(Bit32u start);
|
|
||||||
typedef void (MEMORY_WriteHandler)(Bit32u start,Bit8u val);
|
|
||||||
|
|
||||||
typedef Bit32u PhysOff;
|
|
||||||
typedef Bit32u PhysPt;
|
typedef Bit32u PhysPt;
|
||||||
typedef Bit8u * HostOff;
|
|
||||||
typedef Bit8u * HostPt;
|
typedef Bit8u * HostPt;
|
||||||
typedef Bit32u RealPt;
|
typedef Bit32u RealPt;
|
||||||
|
|
||||||
struct PageEntry {
|
typedef Bit8u (*MEMORY_ReadHandler)(PhysPt pt);
|
||||||
Bit8u type;
|
typedef void (*MEMORY_WriteHandler)(PhysPt pt,Bit8u val);
|
||||||
PhysOff base; /* Used to calculate relative offset */
|
|
||||||
struct {
|
#define PAGE_KB 16
|
||||||
MEMORY_WriteHandler * write;
|
#define PAGE_SIZE PAGE_KB*1024
|
||||||
MEMORY_ReadHandler * read;
|
#define PAGE_SHIFT 14
|
||||||
} handler;
|
#define PAGE_COUNT(A) (A & ((1 << PAGE_SHIFT)-1) ? 1+(A >> PAGE_SHIFT) : (A >> PAGE_SHIFT) )
|
||||||
HostOff relocate; /* This points to host machine address */
|
#define MAX_PAGES PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024)
|
||||||
};
|
|
||||||
|
extern HostPt ReadHostTable[MAX_PAGES];
|
||||||
|
extern HostPt WriteHostTable[MAX_PAGES];
|
||||||
|
extern MEMORY_ReadHandler ReadHandlerTable[MAX_PAGES];
|
||||||
|
extern MEMORY_WriteHandler WriteHandlerTable[MAX_PAGES];
|
||||||
|
|
||||||
struct EMM_Handle {
|
|
||||||
Bit16u next;
|
|
||||||
Bit16u size; /* Size in pages */
|
|
||||||
PhysOff phys_base;
|
|
||||||
HostOff host_base;
|
|
||||||
bool active;
|
|
||||||
bool free;
|
|
||||||
};
|
|
||||||
|
|
||||||
INLINE Bit16u PAGES(Bit32u bytes) {
|
INLINE Bit16u PAGES(Bit32u bytes) {
|
||||||
if ((bytes & 4095) == 0) return (Bit16u)(bytes>>12);
|
if ((bytes & 4095) == 0) return (Bit16u)(bytes>>12);
|
||||||
return (Bit16u)(1+(bytes>>12));
|
return (Bit16u)(1+(bytes>>12));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern Bit8u * memory;
|
|
||||||
extern EMM_Handle EMM_Handles[];
|
|
||||||
extern PageEntry * PageEntries[]; /* Number of pages */
|
|
||||||
|
|
||||||
bool MEMORY_TestSpecial(PhysOff off);
|
void MEM_SetupPageHandlers(Bitu startpage,Bitu pages,MEMORY_ReadHandler read,MEMORY_WriteHandler write);
|
||||||
void MEMORY_SetupHandler(Bit32u page,Bit32u extra,PageEntry * handler);
|
void MEM_ClearPageHandlers(Bitu startpage,Bitu pages);
|
||||||
void MEMORY_ResetHandler(Bit32u page,Bit32u pages);
|
|
||||||
|
|
||||||
|
void MEM_SetupMapping(Bitu startpage,Bitu pages,void * data);
|
||||||
|
void MEM_ClearMapping(Bitu startpage,Bitu pages);
|
||||||
|
|
||||||
void EMM_GetFree(Bit16u * maxblock,Bit16u * total);
|
extern HostPt memory;
|
||||||
void EMM_Allocate(Bit16u size,Bit16u * handle);
|
|
||||||
void EMM_Free(Bit16u handle);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The folowing six functions are used everywhere in the end so these should be changed for
|
The folowing six functions are used everywhere in the end so these should be changed for
|
||||||
Working on big or little endian machines
|
Working on big or little endian machines
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
INLINE Bit8u readb(HostOff off) {
|
INLINE Bit8u readb(HostPt off) {
|
||||||
return *(Bit8u *)off;
|
return *(Bit8u *)off;
|
||||||
};
|
};
|
||||||
INLINE Bit16u readw(HostOff off) {
|
INLINE Bit16u readw(HostPt off) {
|
||||||
return *(Bit16u *)off;
|
return *(Bit16u *)off;
|
||||||
};
|
};
|
||||||
INLINE Bit32u readd(HostOff off) {
|
INLINE Bit32u readd(HostPt off) {
|
||||||
return *(Bit32u *)off;
|
return *(Bit32u *)off;
|
||||||
};
|
};
|
||||||
INLINE void writeb(HostOff off,Bit8u val) {
|
INLINE void writeb(HostPt off,Bit8u val) {
|
||||||
*(Bit8u *)(off)=val;
|
*(Bit8u *)(off)=val;
|
||||||
};
|
};
|
||||||
INLINE void writew(HostOff off,Bit16u val) {
|
INLINE void writew(HostPt off,Bit16u val) {
|
||||||
*(Bit16u *)(off)=val;
|
*(Bit16u *)(off)=val;
|
||||||
};
|
};
|
||||||
INLINE void writed(HostOff off,Bit32u val) {
|
INLINE void writed(HostPt off,Bit32u val) {
|
||||||
*(Bit32u *)(off)=val;
|
*(Bit32u *)(off)=val;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,38 +83,79 @@ INLINE void writed(HostOff off,Bit32u val) {
|
|||||||
/* The Folowing six functions are slower but they recognize the paged memory system */
|
/* The Folowing six functions are slower but they recognize the paged memory system */
|
||||||
//TODO maybe make em inline to go a bit faster
|
//TODO maybe make em inline to go a bit faster
|
||||||
|
|
||||||
Bit8u mem_readb(PhysOff off);
|
#if (!C_EXTRAINLINE)
|
||||||
Bit16u mem_readw(PhysOff off);
|
Bit8u mem_readb(PhysPt pt);
|
||||||
Bit32u mem_readd(PhysOff off);
|
Bit16u mem_readw(PhysPt pt);
|
||||||
|
Bit32u mem_readd(PhysPt pt);
|
||||||
|
|
||||||
void mem_writeb(PhysOff off,Bit8u val);
|
void mem_writeb(PhysPt pt,Bit8u val);
|
||||||
void mem_writew(PhysOff off,Bit16u val);
|
void mem_writew(PhysPt pt,Bit16u val);
|
||||||
void mem_writed(PhysOff off,Bit32u val);
|
void mem_writed(PhysPt pt,Bit32u val);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
INLINE void mem_writeb(PhysPt pt,Bit8u val) {
|
||||||
|
if (WriteHostTable[pt >> PAGE_SHIFT]) writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val);
|
||||||
|
else {
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt,val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE void mem_writew(PhysPt pt,Bit16u val) {
|
||||||
|
if (WriteHostTable[pt >> PAGE_SHIFT]) writew(WriteHostTable[pt >> PAGE_SHIFT]+pt,val);
|
||||||
|
else {
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff));
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE void mem_writed(PhysPt pt,Bit32u val) {
|
||||||
|
if (WriteHostTable[pt >> PAGE_SHIFT]) writed(WriteHostTable[pt >> PAGE_SHIFT]+pt,val);
|
||||||
|
else {
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff));
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) );
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+2,(Bit8u)((val >> 16) & 0xff) );
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+3,(Bit8u)((val >> 24) & 0xff) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MEM_BlockWrite(PhysOff off,void * data,Bitu size);
|
INLINE Bit8u mem_readb(PhysPt pt) {
|
||||||
void MEM_BlockRead(PhysOff off,void * data,Bitu size);
|
if (ReadHostTable[pt >> PAGE_SHIFT]) return readb(ReadHostTable[pt >> PAGE_SHIFT]+pt);
|
||||||
void MEM_BlockCopy(PhysOff dest,PhysOff src,Bitu size);
|
else {
|
||||||
void MEM_StrCopy(PhysOff off,char * data,Bitu size);
|
return ReadHandlerTable[pt >> PAGE_SHIFT](pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE Bit16u mem_readw(PhysPt pt) {
|
||||||
|
if (ReadHostTable[pt >> PAGE_SHIFT]) return readw(ReadHostTable[pt >> PAGE_SHIFT]+pt);
|
||||||
|
else {
|
||||||
|
return
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) |
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE Bit32u mem_readd(PhysPt pt){
|
||||||
|
if (ReadHostTable[pt >> PAGE_SHIFT]) return readd(ReadHostTable[pt >> PAGE_SHIFT]+pt);
|
||||||
|
else {
|
||||||
|
return
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) |
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8 |
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+2)) << 16 |
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+3)) << 24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void MEM_BlockWrite(PhysPt pt,void * data,Bitu size);
|
||||||
|
void MEM_BlockRead(PhysPt pt,void * data,Bitu size);
|
||||||
|
void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size);
|
||||||
|
void MEM_StrCopy(PhysPt pt,char * data,Bitu size);
|
||||||
|
|
||||||
/* The folowing functions are all shortcuts to the above functions using physical addressing */
|
/* The folowing functions are all shortcuts to the above functions using physical addressing */
|
||||||
|
|
||||||
INLINE HostOff real_off(Bit16u seg,Bit32u off) {
|
|
||||||
return memory+(seg<<4)+off;
|
|
||||||
};
|
|
||||||
|
|
||||||
INLINE HostOff real_host(Bit16u seg,Bit32u off) {
|
|
||||||
return memory+(seg<<4)+off;
|
|
||||||
};
|
|
||||||
INLINE PhysOff real_phys(Bit16u seg,Bit32u off) {
|
|
||||||
return (seg<<4)+off;
|
|
||||||
};
|
|
||||||
|
|
||||||
INLINE Bit8u real_readb(Bit16u seg,Bit16u off) {
|
INLINE Bit8u real_readb(Bit16u seg,Bit16u off) {
|
||||||
return mem_readb((seg<<4)+off);
|
return mem_readb((seg<<4)+off);
|
||||||
}
|
}
|
||||||
@ -141,9 +165,6 @@ INLINE Bit16u real_readw(Bit16u seg,Bit16u off) {
|
|||||||
INLINE Bit32u real_readd(Bit16u seg,Bit16u off) {
|
INLINE Bit32u real_readd(Bit16u seg,Bit16u off) {
|
||||||
return mem_readd((seg<<4)+off);
|
return mem_readd((seg<<4)+off);
|
||||||
}
|
}
|
||||||
//#define real_readb(seg,off) mem_readb(((seg)<<4)+(off))
|
|
||||||
//#define real_readw(seg,off) mem_readw(((seg)<<4)+(off))
|
|
||||||
//#define real_readd(seg,off) mem_readd(((seg)<<4)+(off))
|
|
||||||
|
|
||||||
INLINE void real_writeb(Bit16u seg,Bit16u off,Bit8u val) {
|
INLINE void real_writeb(Bit16u seg,Bit16u off,Bit8u val) {
|
||||||
mem_writeb(((seg<<4)+off),val);
|
mem_writeb(((seg<<4)+off),val);
|
||||||
@ -155,20 +176,13 @@ INLINE void real_writed(Bit16u seg,Bit16u off,Bit32u val) {
|
|||||||
mem_writed(((seg<<4)+off),val);
|
mem_writed(((seg<<4)+off),val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE HostPt HostMake(Bit16u seg,Bit16u off) {
|
||||||
//#define real_writeb(seg,off,val) mem_writeb((((seg)<<4)+(off)),val)
|
return memory+(seg<<4)+off;
|
||||||
//#define real_writew(seg,off,val) mem_writew((((seg)<<4)+(off)),val)
|
|
||||||
//#define real_writed(seg,off,val) mem_writed((((seg)<<4)+(off)),val)
|
|
||||||
|
|
||||||
inline Bit32u real_getvec(Bit8u num) {
|
|
||||||
return real_readd(0,(num<<2));
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
inline void real_setvec(Bit8u num,Bit32u addr) {
|
|
||||||
real_writed(0,(num<<2),addr);
|
|
||||||
};
|
|
||||||
|
|
||||||
*/
|
INLINE HostPt Phys2Host(PhysPt pt) {
|
||||||
|
return memory+pt;
|
||||||
|
}
|
||||||
|
|
||||||
INLINE Bit16u RealSeg(RealPt pt) {
|
INLINE Bit16u RealSeg(RealPt pt) {
|
||||||
return (Bit16u)(pt>>16);
|
return (Bit16u)(pt>>16);
|
||||||
@ -182,17 +196,18 @@ INLINE PhysPt Real2Phys(RealPt pt) {
|
|||||||
return (RealSeg(pt)<<4) +RealOff(pt);
|
return (RealSeg(pt)<<4) +RealOff(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE PhysPt PhysMake(Bit16u seg,Bit16u off) {
|
||||||
|
return (seg<<4)+off;
|
||||||
|
}
|
||||||
|
|
||||||
INLINE HostPt Real2Host(RealPt pt) {
|
INLINE HostPt Real2Host(RealPt pt) {
|
||||||
return memory+(RealSeg(pt)<<4) +RealOff(pt);
|
return memory+(RealSeg(pt)<<4) +RealOff(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE RealPt RealMake(Bit16u seg,Bit16u off) {
|
INLINE RealPt RealMake(Bit16u seg,Bit16u off) {
|
||||||
return (seg<<16)+off;
|
return (seg<<16)+off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
INLINE void RealSetVec(Bit8u vec,RealPt pt) {
|
INLINE void RealSetVec(Bit8u vec,RealPt pt) {
|
||||||
mem_writed(vec<<2,pt);
|
mem_writed(vec<<2,pt);
|
||||||
}
|
}
|
||||||
@ -201,8 +216,5 @@ INLINE RealPt RealGetVec(Bit8u vec) {
|
|||||||
return mem_readd(vec<<2);
|
return mem_readd(vec<<2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
113
include/regs.h
113
include/regs.h
@ -24,11 +24,8 @@
|
|||||||
struct Flag_Info {
|
struct Flag_Info {
|
||||||
union {
|
union {
|
||||||
Bit8u b;
|
Bit8u b;
|
||||||
Bit8u bs;
|
|
||||||
Bit16u w;
|
Bit16u w;
|
||||||
Bit16s ws;
|
|
||||||
Bit32u d;
|
Bit32u d;
|
||||||
Bit32s ds;
|
|
||||||
} var1,var2,result;
|
} var1,var2,result;
|
||||||
Bitu type;
|
Bitu type;
|
||||||
Bitu prev_type;
|
Bitu prev_type;
|
||||||
@ -38,26 +35,13 @@ struct Flag_Info {
|
|||||||
bool oldcf;
|
bool oldcf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Segment {
|
struct Segment {
|
||||||
Bit16u value;
|
Bit16u val;
|
||||||
bool special; /* Signal for pointing to special memory */
|
PhysPt phys; /* The phyiscal address start in emulated machine */
|
||||||
HostOff host; /* The address of start in host memory */
|
|
||||||
PhysOff phys; /* The phyiscal address start in emulated machine */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum SegNames { cs=0,ds,es,fs,gs,ss};
|
||||||
|
|
||||||
enum { cs=0,ds,es,fs,gs,ss};
|
|
||||||
|
|
||||||
extern Segment Segs[6];
|
|
||||||
extern Flag_Info flags;
|
|
||||||
//extern Regs regs;
|
|
||||||
|
|
||||||
void SetSegment_16(Bit32u seg,Bit16u val);
|
|
||||||
|
|
||||||
|
|
||||||
struct CPU_Regs {
|
struct CPU_Regs {
|
||||||
union {
|
union {
|
||||||
@ -66,52 +50,83 @@ struct CPU_Regs {
|
|||||||
struct {
|
struct {
|
||||||
Bit8u l,h;
|
Bit8u l,h;
|
||||||
}b;
|
}b;
|
||||||
} ax,bx,cx,dx,si,di,sp,bp,ip;
|
} regs[8],ip;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern Segment Segs[6];
|
||||||
|
extern Flag_Info flags;
|
||||||
extern CPU_Regs cpu_regs;
|
extern CPU_Regs cpu_regs;
|
||||||
|
|
||||||
#define reg_al cpu_regs.ax.b.l
|
|
||||||
|
|
||||||
//extern Bit8u & reg_al=cpu_regs.ax.b.l;
|
//#define SegPhys(index) Segs[index].phys
|
||||||
|
//#define SegValue(index) Segs[index].val
|
||||||
|
|
||||||
#define reg_ah cpu_regs.ax.b.h
|
INLINE PhysPt SegPhys(SegNames index) {
|
||||||
#define reg_ax cpu_regs.ax.w
|
return Segs[index].phys;
|
||||||
#define reg_eax cpu_regs.ax.d
|
}
|
||||||
|
|
||||||
#define reg_bl cpu_regs.bx.b.l
|
INLINE Bit16u SegValue(SegNames index) {
|
||||||
#define reg_bh cpu_regs.bx.b.h
|
return Segs[index].val;
|
||||||
#define reg_bx cpu_regs.bx.w
|
}
|
||||||
#define reg_ebx cpu_regs.bx.d
|
|
||||||
|
|
||||||
#define reg_cl cpu_regs.cx.b.l
|
|
||||||
#define reg_ch cpu_regs.cx.b.h
|
INLINE RealPt RealMakeSeg(SegNames index,Bit16u off) {
|
||||||
#define reg_cx cpu_regs.cx.w
|
return RealMake(SegValue(index),off);
|
||||||
#define reg_ecx cpu_regs.cx.d
|
}
|
||||||
|
|
||||||
#define reg_dl cpu_regs.dx.b.l
|
|
||||||
#define reg_dh cpu_regs.dx.b.h
|
|
||||||
#define reg_dx cpu_regs.dx.w
|
|
||||||
#define reg_edx cpu_regs.dx.d
|
|
||||||
|
|
||||||
#define reg_si cpu_regs.si.w
|
INLINE void SegSet16(Bitu index,Bit16u val) {
|
||||||
#define reg_esi cpu_regs.si.d
|
Segs[index].val=val;
|
||||||
|
Segs[index].phys=val << 4;
|
||||||
|
}
|
||||||
|
|
||||||
#define reg_di cpu_regs.di.w
|
|
||||||
#define reg_edi cpu_regs.di.d
|
|
||||||
|
|
||||||
#define reg_sp cpu_regs.sp.w
|
enum REG_NUM {
|
||||||
#define reg_esp cpu_regs.sp.d
|
REG_NUM_AX, REG_NUM_CX, REG_NUM_DX, REG_NUM_BX,
|
||||||
|
REG_NUM_SP, REG_NUM_BP, REG_NUM_SI, REG_NUM_DI
|
||||||
|
};
|
||||||
|
|
||||||
#define reg_bp cpu_regs.bp.w
|
//macros to convert a 3-bit register index to the correct register
|
||||||
#define reg_ebp cpu_regs.bp.d
|
#define reg_8l(reg) (cpu_regs.regs[(reg)].b.l)
|
||||||
|
#define reg_8h(reg) (cpu_regs.regs[(reg)].b.h)
|
||||||
|
#define reg_8(reg) ((reg) & 4 ? reg_8h((reg) & 3) : reg_8l((reg) & 3))
|
||||||
|
#define reg_16(reg) (cpu_regs.regs[(reg)].w)
|
||||||
|
#define reg_32(reg) (cpu_regs.regs[(reg)].d)
|
||||||
|
|
||||||
|
#define reg_al cpu_regs.regs[REG_NUM_AX].b.l
|
||||||
|
#define reg_ah cpu_regs.regs[REG_NUM_AX].b.h
|
||||||
|
#define reg_ax cpu_regs.regs[REG_NUM_AX].w
|
||||||
|
#define reg_eax cpu_regs.regs[REG_NUM_AX].d
|
||||||
|
|
||||||
|
#define reg_bl cpu_regs.regs[REG_NUM_BX].b.l
|
||||||
|
#define reg_bh cpu_regs.regs[REG_NUM_BX].b.h
|
||||||
|
#define reg_bx cpu_regs.regs[REG_NUM_BX].w
|
||||||
|
#define reg_ebx cpu_regs.regs[REG_NUM_BX].d
|
||||||
|
|
||||||
|
#define reg_cl cpu_regs.regs[REG_NUM_CX].b.l
|
||||||
|
#define reg_ch cpu_regs.regs[REG_NUM_CX].b.h
|
||||||
|
#define reg_cx cpu_regs.regs[REG_NUM_CX].w
|
||||||
|
#define reg_ecx cpu_regs.regs[REG_NUM_CX].d
|
||||||
|
|
||||||
|
#define reg_dl cpu_regs.regs[REG_NUM_DX].b.l
|
||||||
|
#define reg_dh cpu_regs.regs[REG_NUM_DX].b.h
|
||||||
|
#define reg_dx cpu_regs.regs[REG_NUM_DX].w
|
||||||
|
#define reg_edx cpu_regs.regs[REG_NUM_DX].d
|
||||||
|
|
||||||
|
#define reg_si cpu_regs.regs[REG_NUM_SI].w
|
||||||
|
#define reg_esi cpu_regs.regs[REG_NUM_SI].d
|
||||||
|
|
||||||
|
#define reg_di cpu_regs.regs[REG_NUM_DI].w
|
||||||
|
#define reg_edi cpu_regs.regs[REG_NUM_DI].d
|
||||||
|
|
||||||
|
#define reg_sp cpu_regs.regs[REG_NUM_SP].w
|
||||||
|
#define reg_esp cpu_regs.regs[REG_NUM_SP].d
|
||||||
|
|
||||||
|
#define reg_bp cpu_regs.regs[REG_NUM_BP].w
|
||||||
|
#define reg_ebp cpu_regs.regs[REG_NUM_BP].d
|
||||||
|
|
||||||
#define reg_ip cpu_regs.ip.w
|
#define reg_ip cpu_regs.ip.w
|
||||||
#define reg_eip cpu_regs.ip.d
|
#define reg_eip cpu_regs.ip.d
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
59
settings.h
59
settings.h
@ -1,21 +1,56 @@
|
|||||||
/* Enable the debugger */
|
/*
|
||||||
//#define C_DEBUG
|
* Copyright (C) 2002 The DOSBox Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Enable logging of debug information */
|
#ifndef _SETTINGS_H_
|
||||||
//#define C_LOGGING
|
#define _SETTINSG_H_
|
||||||
|
|
||||||
|
/* Enable the debugger, this only seems to work in win32 for now. */
|
||||||
|
#define C_DEBUG 0
|
||||||
|
|
||||||
|
/* Enable the logging of extra information for debugging to the console */
|
||||||
|
#define C_LOGGING 0
|
||||||
|
|
||||||
/* Use multi threading to speed up things on multi cpu's, also gives a nice frame-skipping effect :) */
|
/* Use multi threading to speed up things on multi cpu's, also gives a nice frame-skipping effect :) */
|
||||||
#define C_THREADED
|
#define C_THREADED 1
|
||||||
|
|
||||||
/* Enable debugging for several modules, requires C_LOGGING */
|
/* Enable some big compile-time increasing inlines, great for speed though */
|
||||||
#define DEBUG_SBLASTER /* SoundBlaster Debugging*/
|
#define C_EXTRAINLINE 0
|
||||||
#define DEBUG_DMA /* DMA Debugging */
|
|
||||||
#define DEBUG_DOS /* DOS Debugging */
|
|
||||||
|
|
||||||
|
/* Enable the FPU module, still only for beta testing */
|
||||||
|
#define C_FPU 0
|
||||||
|
|
||||||
|
/* Maximum memory range in megabytes */
|
||||||
|
#define C_MEM_MAX_SIZE 12
|
||||||
|
|
||||||
|
/* Maximum memory available for xms, should be lower than maxsize-1 */
|
||||||
|
#define C_MEM_XMS_SIZE 8
|
||||||
|
|
||||||
|
/* Maximum memory available for ems, should be lower than 32 */
|
||||||
|
#define C_MEM_EMS_SIZE 4
|
||||||
|
|
||||||
|
/* Enable debug messages for several modules, requires C_LOGGING */
|
||||||
|
#define DEBUG_SBLASTER 0 /* SoundBlaster Debugging*/
|
||||||
|
#define DEBUG_DMA 0 /* DMA Debugging */
|
||||||
|
#define DEBUG_DOS 0 /* DOS Debugging */
|
||||||
|
|
||||||
#define LOG_MSG S_Warn
|
#define LOG_MSG S_Warn
|
||||||
|
|
||||||
#ifdef C_LOGGING
|
#if C_LOGGING
|
||||||
#define LOG_DEBUG S_Warn
|
#define LOG_DEBUG S_Warn
|
||||||
#define LOG_WARN S_Warn
|
#define LOG_WARN S_Warn
|
||||||
#define LOG_ERROR S_Warn
|
#define LOG_ERROR S_Warn
|
||||||
@ -23,4 +58,6 @@
|
|||||||
#define LOG_DEBUG
|
#define LOG_DEBUG
|
||||||
#define LOG_WARN
|
#define LOG_WARN
|
||||||
#define LOG_ERROR
|
#define LOG_ERROR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -32,14 +32,13 @@
|
|||||||
|
|
||||||
|
|
||||||
CallBack_Handler CallBack_Handlers[CB_MAX];
|
CallBack_Handler CallBack_Handlers[CB_MAX];
|
||||||
static Bitu call_runint16,call_idle,call_default,call_runfar16;
|
static Bitu call_stop,call_idle,call_default;
|
||||||
|
|
||||||
static Bitu illegal_handler(void) {
|
static Bitu illegal_handler(void) {
|
||||||
E_Exit("Illegal CallBack Called");
|
E_Exit("Illegal CallBack Called");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* when this returns -1 all CallBacks are taken */
|
|
||||||
Bitu CALLBACK_Allocate(void) {
|
Bitu CALLBACK_Allocate(void) {
|
||||||
for (Bitu i=0;(i<CB_MAX);i++) {
|
for (Bitu i=0;(i<CB_MAX);i++) {
|
||||||
if (CallBack_Handlers[i]==&illegal_handler) {
|
if (CallBack_Handlers[i]==&illegal_handler) {
|
||||||
@ -53,13 +52,13 @@ Bitu CALLBACK_Allocate(void) {
|
|||||||
|
|
||||||
void CALLBACK_Idle(void) {
|
void CALLBACK_Idle(void) {
|
||||||
/* this makes the cpu execute instructions to handle irq's and then come back */
|
/* this makes the cpu execute instructions to handle irq's and then come back */
|
||||||
Bit16u oldcs=Segs[cs].value;
|
Bit16u oldcs=SegValue(cs);
|
||||||
Bit32u oldeip=reg_eip;
|
Bit32u oldeip=reg_eip;
|
||||||
SetSegment_16(cs,CB_SEG);
|
SegSet16(cs,CB_SEG);
|
||||||
reg_eip=call_idle<<4;
|
reg_eip=call_idle<<4;
|
||||||
DOSBOX_RunMachine();
|
DOSBOX_RunMachine();
|
||||||
reg_eip=oldeip;
|
reg_eip=oldeip;
|
||||||
SetSegment_16(cs,oldcs);
|
SegSet16(cs,oldcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bitu default_handler(void) {
|
static Bitu default_handler(void) {
|
||||||
@ -74,40 +73,41 @@ static Bitu stop_handler(void) {
|
|||||||
|
|
||||||
|
|
||||||
void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) {
|
void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) {
|
||||||
real_writew((Bit16u)CB_SEG,(call_runfar16<<4)+1,off);
|
reg_sp-=4;
|
||||||
real_writew((Bit16u)CB_SEG,(call_runfar16<<4)+3,seg);
|
mem_writew(SegPhys(ss)+reg_sp,call_stop<<4);
|
||||||
|
mem_writew(SegPhys(ss)+reg_sp+2,CB_SEG);
|
||||||
Bit32u oldeip=reg_eip;
|
Bit32u oldeip=reg_eip;
|
||||||
Bit16u oldcs=Segs[cs].value;
|
Bit16u oldcs=SegValue(cs);
|
||||||
reg_eip=call_runfar16<<4;
|
reg_eip=off;
|
||||||
SetSegment_16(cs,CB_SEG);
|
SegSet16(cs,seg);
|
||||||
DOSBOX_RunMachine();
|
DOSBOX_RunMachine();
|
||||||
reg_eip=oldeip;
|
reg_eip=oldeip;
|
||||||
SetSegment_16(cs,oldcs);
|
SegSet16(cs,oldcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CALLBACK_RunRealInt(Bit8u intnum) {
|
void CALLBACK_RunRealInt(Bit8u intnum) {
|
||||||
real_writeb((Bit16u)CB_SEG,(call_runint16<<4)+1,intnum);
|
|
||||||
Bit32u oldeip=reg_eip;
|
Bit32u oldeip=reg_eip;
|
||||||
Bit16u oldcs=Segs[cs].value;
|
Bit16u oldcs=SegValue(cs);
|
||||||
reg_eip=call_runint16<<4;
|
reg_eip=call_stop<<4;
|
||||||
SetSegment_16(cs,CB_SEG);
|
SegSet16(cs,CB_SEG);
|
||||||
|
Interrupt(intnum);
|
||||||
DOSBOX_RunMachine();
|
DOSBOX_RunMachine();
|
||||||
reg_eip=oldeip;
|
reg_eip=oldeip;
|
||||||
SetSegment_16(cs,oldcs);
|
SegSet16(cs,oldcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CALLBACK_SZF(bool val) {
|
void CALLBACK_SZF(bool val) {
|
||||||
Bit16u tempf=real_readw(Segs[ss].value,reg_sp+4) & 0xFFBF;
|
Bit16u tempf=mem_readw(SegPhys(ss)+reg_sp+4) & 0xFFBF;
|
||||||
Bit16u newZF=(val==true) << 6;
|
Bit16u newZF=(val==true) << 6;
|
||||||
real_writew(Segs[ss].value,reg_sp+4,(tempf | newZF));
|
mem_writew(SegPhys(ss)+reg_sp+4,(tempf | newZF));
|
||||||
};
|
};
|
||||||
|
|
||||||
void CALLBACK_SCF(bool val) {
|
void CALLBACK_SCF(bool val) {
|
||||||
Bit16u tempf=real_readw(Segs[ss].value,reg_sp+4) & 0xFFFE;
|
Bit16u tempf=mem_readw(SegPhys(ss)+reg_sp+4) & 0xFFFE;
|
||||||
Bit16u newCF=(val==true);
|
Bit16u newCF=(val==true);
|
||||||
real_writew(Segs[ss].value,reg_sp+4,(tempf | newCF));
|
mem_writew(SegPhys(ss)+reg_sp+4,(tempf | newCF));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -140,20 +140,12 @@ void CALLBACK_Init(void) {
|
|||||||
for (i=0;i<CB_MAX;i++) {
|
for (i=0;i<CB_MAX;i++) {
|
||||||
CallBack_Handlers[i]=&illegal_handler;
|
CallBack_Handlers[i]=&illegal_handler;
|
||||||
}
|
}
|
||||||
/* Setup the Software interrupt handler */
|
/* Setup the Stop Handler */
|
||||||
call_runint16=CALLBACK_Allocate();
|
call_stop=CALLBACK_Allocate();
|
||||||
CallBack_Handlers[call_runint16]=stop_handler;
|
CallBack_Handlers[call_stop]=stop_handler;
|
||||||
real_writeb((Bit16u)CB_SEG,(call_runint16<<4),0xCD);
|
real_writeb((Bit16u)CB_SEG,(call_stop<<4)+0,0xFE);
|
||||||
real_writeb((Bit16u)CB_SEG,(call_runint16<<4)+2,0xFE);
|
real_writeb((Bit16u)CB_SEG,(call_stop<<4)+1,0x38);
|
||||||
real_writeb((Bit16u)CB_SEG,(call_runint16<<4)+3,0x38);
|
real_writew((Bit16u)CB_SEG,(call_stop<<4)+2,call_stop);
|
||||||
real_writew((Bit16u)CB_SEG,(call_runint16<<4)+4,call_runint16);
|
|
||||||
/* Setup the Far Call handler */
|
|
||||||
call_runfar16=CALLBACK_Allocate();
|
|
||||||
CallBack_Handlers[call_runfar16]=stop_handler;
|
|
||||||
real_writeb((Bit16u)CB_SEG,(call_runfar16<<4),0x9A);
|
|
||||||
real_writeb((Bit16u)CB_SEG,(call_runfar16<<4)+5,0xFE);
|
|
||||||
real_writeb((Bit16u)CB_SEG,(call_runfar16<<4)+6,0x38);
|
|
||||||
real_writew((Bit16u)CB_SEG,(call_runfar16<<4)+7,call_runfar16);
|
|
||||||
/* Setup the idle handler */
|
/* Setup the idle handler */
|
||||||
call_idle=CALLBACK_Allocate();
|
call_idle=CALLBACK_Allocate();
|
||||||
CallBack_Handlers[call_idle]=stop_handler;
|
CallBack_Handlers[call_idle]=stop_handler;
|
||||||
@ -161,12 +153,15 @@ void CALLBACK_Init(void) {
|
|||||||
real_writeb((Bit16u)CB_SEG,(call_idle<<4)+12,0xFE);
|
real_writeb((Bit16u)CB_SEG,(call_idle<<4)+12,0xFE);
|
||||||
real_writeb((Bit16u)CB_SEG,(call_idle<<4)+13,0x38);
|
real_writeb((Bit16u)CB_SEG,(call_idle<<4)+13,0x38);
|
||||||
real_writew((Bit16u)CB_SEG,(call_idle<<4)+14,call_idle);
|
real_writew((Bit16u)CB_SEG,(call_idle<<4)+14,call_idle);
|
||||||
|
|
||||||
|
#if C_DEBUG
|
||||||
/* Setup all Interrupt to point to the default handler */
|
/* Setup all Interrupt to point to the default handler */
|
||||||
call_default=CALLBACK_Allocate();
|
call_default=CALLBACK_Allocate();
|
||||||
CALLBACK_Setup(call_default,&default_handler,CB_IRET);
|
CALLBACK_Setup(call_default,&default_handler,CB_IRET);
|
||||||
for (i=0;i<256;i++) {
|
for (i=0;i<256;i++) {
|
||||||
real_writed(0,i*4,CALLBACK_RealPointer(call_default));
|
real_writed(0,i*4,CALLBACK_RealPointer(call_default));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,6 +36,13 @@
|
|||||||
ADDIPFAST(2); \
|
ADDIPFAST(2); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SETcc(cc) \
|
||||||
|
{ \
|
||||||
|
GetRM; \
|
||||||
|
if (rm >= 0xc0 ) {GetEArb;*earb=(cc) ? 1 : 0;} \
|
||||||
|
else {GetEAa;SaveMb(eaa,(cc) ? 1 : 0);} \
|
||||||
|
}
|
||||||
|
|
||||||
#define INTERRUPT(blah) \
|
#define INTERRUPT(blah) \
|
||||||
{ \
|
{ \
|
||||||
Bit8u new_num=blah; \
|
Bit8u new_num=blah; \
|
||||||
@ -257,207 +264,248 @@
|
|||||||
//TODO Maybe make this into a bigger split up because of the rm >=0xc0 this seems make it a bit slower
|
//TODO Maybe make this into a bigger split up because of the rm >=0xc0 this seems make it a bit slower
|
||||||
//TODO set Zero and Sign flag in one run
|
//TODO set Zero and Sign flag in one run
|
||||||
#define ROLB(op1,op2,load,save) \
|
#define ROLB(op1,op2,load,save) \
|
||||||
if (!(op2&0x07)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.var1.b=load(op1);flags.var2.b=op2&0x07; \
|
flags.var2.b=op2&0x07;flags.var1.b=load(op1); \
|
||||||
flags.result.b=(flags.var1.b << flags.var2.b) | \
|
if (!flags.var2.b) { \
|
||||||
|
flags.result.b=flags.var1.b; \
|
||||||
|
} else { \
|
||||||
|
flags.result.b=(flags.var1.b << flags.var2.b) | \
|
||||||
(flags.var1.b >> (8-flags.var2.b)); \
|
(flags.var1.b >> (8-flags.var2.b)); \
|
||||||
|
} \
|
||||||
save(op1,flags.result.b); \
|
save(op1,flags.result.b); \
|
||||||
flags.type=t_ROLb;
|
flags.type=t_ROLb;
|
||||||
|
|
||||||
#define ROLW(op1,op2,load,save) \
|
#define ROLW(op1,op2,load,save) \
|
||||||
if (!(op2&0x0F)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.var1.w=load(op1);flags.var2.b=op2&0x0F; \
|
flags.var2.b=op2&0x0F;flags.var1.w=load(op1); \
|
||||||
flags.result.w=(flags.var1.w << flags.var2.b) | \
|
if (!flags.var2.b) { \
|
||||||
(flags.var1.w >> (16-flags.var2.b)); \
|
flags.result.w=flags.var1.w; \
|
||||||
|
} else { \
|
||||||
|
flags.result.w=(flags.var1.w << flags.var2.b) | \
|
||||||
|
(flags.var1.w >> (16-flags.var2.b)); \
|
||||||
|
} \
|
||||||
save(op1,flags.result.w); \
|
save(op1,flags.result.w); \
|
||||||
flags.type=t_ROLw;
|
flags.type=t_ROLw;
|
||||||
|
|
||||||
|
|
||||||
#define ROLD(op1,op2,load,save) \
|
#define ROLD(op1,op2,load,save) \
|
||||||
if (!(op2&0x0F)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op2&0x0F; \
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
||||||
flags.result.d=(flags.var1.d << flags.var2.b) | \
|
flags.result.d=(flags.var1.d << flags.var2.b) | \
|
||||||
(flags.var1.d >> (32-flags.var2.b)); \
|
(flags.var1.d >> (32-flags.var2.b)); \
|
||||||
save(op1,flags.result.d); \
|
save(op1,flags.result.d); \
|
||||||
flags.type=t_ROLd;
|
flags.type=t_ROLd;
|
||||||
|
|
||||||
|
|
||||||
#define RORB(op1,op2,load,save) \
|
#define RORB(op1,op2,load,save) \
|
||||||
if (!(op2&0x07)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.var1.b=load(op1);flags.var2.b=op2&0x07; \
|
flags.var2.b=op2&0x07;flags.var1.b=load(op1); \
|
||||||
flags.result.b=(flags.var1.b >> flags.var2.b) | \
|
if (!flags.var2.b) { \
|
||||||
|
flags.result.b=flags.var1.b; \
|
||||||
|
} else { \
|
||||||
|
flags.result.b=(flags.var1.b >> flags.var2.b) | \
|
||||||
(flags.var1.b << (8-flags.var2.b)); \
|
(flags.var1.b << (8-flags.var2.b)); \
|
||||||
|
} \
|
||||||
save(op1,flags.result.b); \
|
save(op1,flags.result.b); \
|
||||||
flags.type=t_RORb;
|
flags.type=t_RORb;
|
||||||
|
|
||||||
|
|
||||||
#define RORW(op1,op2,load,save) \
|
#define RORW(op1,op2,load,save) \
|
||||||
if (!(op2&0x0F)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.var1.w=load(op1);flags.var2.b=op2&0x0F; \
|
flags.var2.b=op2&0x0F;flags.var1.w=load(op1); \
|
||||||
flags.result.w=(flags.var1.w >> flags.var2.b) | \
|
if (!flags.var2.b) { \
|
||||||
(flags.var1.w << (16-flags.var2.b)); \
|
flags.result.w=flags.var1.w; \
|
||||||
|
} else { \
|
||||||
|
flags.result.w=(flags.var1.w >> flags.var2.b) | \
|
||||||
|
(flags.var1.w << (16-flags.var2.b)); \
|
||||||
|
} \
|
||||||
save(op1,flags.result.w); \
|
save(op1,flags.result.w); \
|
||||||
flags.type=t_RORw;
|
flags.type=t_RORw;
|
||||||
|
|
||||||
#define RORD(op1,op2,load,save) \
|
#define RORD(op1,op2,load,save) \
|
||||||
if (!(op2&0x0F)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op2&0x0F; \
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
||||||
flags.result.d=(flags.var1.d >> flags.var2.b) | \
|
flags.result.d=(flags.var1.d >> flags.var2.b) | \
|
||||||
(flags.var1.d << (32-flags.var2.b)); \
|
(flags.var1.d << (32-flags.var2.b)); \
|
||||||
save(op1,flags.result.d); \
|
save(op1,flags.result.d); \
|
||||||
flags.type=t_RORd;
|
flags.type=t_RORd;
|
||||||
|
|
||||||
|
|
||||||
|
/* flags.oldcf=get_CF();*/ \
|
||||||
|
|
||||||
#define RCLB(op1,op2,load,save) \
|
#define RCLB(op1,op2,load,save) \
|
||||||
if (!(op2%9)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.cf=get_CF();flags.type=t_RCLb; \
|
flags.cf=get_CF();flags.type=t_RCLb; \
|
||||||
flags.var1.b=load(op1);flags.var2.b=op2%9; \
|
flags.var2.b=op2%9;flags.var1.b=load(op1); \
|
||||||
flags.result.b=(flags.var1.b << flags.var2.b) | \
|
if (!flags.var2.b) { \
|
||||||
(flags.cf << (flags.var2.b-1)) | \
|
flags.result.b=flags.var1.b; \
|
||||||
|
} else { \
|
||||||
|
flags.result.b=(flags.var1.b << flags.var2.b) | \
|
||||||
|
(flags.cf << (flags.var2.b-1)) | \
|
||||||
(flags.var1.b >> (9-flags.var2.b)); \
|
(flags.var1.b >> (9-flags.var2.b)); \
|
||||||
save(op1,flags.result.b);
|
flags.cf=((flags.var1.b >> (8-flags.var2.b)) & 1); \
|
||||||
|
} \
|
||||||
|
flags.of=((flags.result.b & 0x80) ^ (flags.cf ? 0x80 : 0)) != 0; \
|
||||||
|
save(op1,flags.result.b);
|
||||||
|
|
||||||
#define RCLW(op1,op2,load,save) \
|
#define RCLW(op1,op2,load,save) \
|
||||||
if (!(op2%17)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.cf=get_CF();flags.type=t_RCLw; \
|
flags.cf=get_CF();flags.type=t_RCLw; \
|
||||||
flags.var1.w=load(op1);flags.var2.b=op2%17; \
|
flags.var2.b=op2%17;flags.var1.w=load(op1); \
|
||||||
flags.result.w=(flags.var1.w << flags.var2.b) | \
|
if (!flags.var2.b) { \
|
||||||
(flags.cf << (flags.var2.b-1)) | \
|
flags.result.w=flags.var1.w; \
|
||||||
(flags.var1.w >> (17-flags.var2.b)); \
|
} else { \
|
||||||
|
flags.result.w=(flags.var1.w << flags.var2.b) | \
|
||||||
|
(flags.cf << (flags.var2.b-1)) | \
|
||||||
|
(flags.var1.w >> (17-flags.var2.b)); \
|
||||||
|
flags.cf=((flags.var1.w >> (16-flags.var2.b)) & 1); \
|
||||||
|
} \
|
||||||
|
flags.of=((flags.result.w & 0x8000) ^ (flags.cf ? 0x8000 : 0)) != 0; \
|
||||||
save(op1,flags.result.w);
|
save(op1,flags.result.w);
|
||||||
|
|
||||||
#define RCLD(op1,op2,load,save) \
|
#define RCLD(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.cf=get_CF();flags.type=t_RCLd; \
|
flags.cf=get_CF();flags.type=t_RCLd; \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op2; \
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
||||||
if (flags.var2.b==1) { \
|
if (flags.var2.b==1) { \
|
||||||
flags.result.d=flags.var1.d << 1 | flags.cf; \
|
flags.result.d=flags.var1.d << 1 | flags.cf; \
|
||||||
} else { \
|
} else { \
|
||||||
flags.result.d=(flags.var1.d << flags.var2.b) | \
|
flags.result.d=(flags.var1.d << flags.var2.b) | \
|
||||||
(flags.cf << (flags.var2.b-1)) | \
|
(flags.cf << (flags.var2.b-1)) | \
|
||||||
(flags.var1.d >> (33-flags.var2.b)); \
|
(flags.var1.d >> (33-flags.var2.b)); \
|
||||||
} \
|
} \
|
||||||
|
flags.cf=((flags.var1.d >> (32-flags.var2.b)) & 1); \
|
||||||
|
flags.of=((flags.result.d & 0x80000000) ^ (flags.cf ? 0x80000000 : 0)) != 0; \
|
||||||
save(op1,flags.result.d);
|
save(op1,flags.result.d);
|
||||||
|
|
||||||
#define RCRB(op1,op2,load,save) \
|
#define RCRB(op1,op2,load,save) \
|
||||||
if (!(op2%9)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.cf=get_CF();flags.type=t_RCRb; \
|
flags.cf=get_CF();flags.type=t_RCRb; \
|
||||||
flags.var1.b=load(op1);flags.var2.b=op2%9; \
|
flags.var2.b=op2%9;flags.var1.b=load(op1); \
|
||||||
flags.result.b=(flags.var1.b >> flags.var2.b) | \
|
if (!flags.var2.b) { \
|
||||||
(flags.cf << (8-flags.var2.b)) | \
|
flags.result.b=flags.var1.b; \
|
||||||
|
} else { \
|
||||||
|
flags.result.b=(flags.var1.b >> flags.var2.b) | \
|
||||||
|
(flags.cf << (8-flags.var2.b)) | \
|
||||||
(flags.var1.b << (9-flags.var2.b)); \
|
(flags.var1.b << (9-flags.var2.b)); \
|
||||||
|
} \
|
||||||
save(op1,flags.result.b);
|
save(op1,flags.result.b);
|
||||||
|
|
||||||
#define RCRW(op1,op2,load,save) \
|
#define RCRW(op1,op2,load,save) \
|
||||||
if (!(op2%17)) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.cf=get_CF();flags.type=t_RCRw; \
|
flags.cf=get_CF();flags.type=t_RCRw; \
|
||||||
flags.var1.w=load(op1);flags.var2.b=op2%17; \
|
flags.var2.b=op2%17;flags.var1.w=load(op1); \
|
||||||
flags.result.w=(flags.var1.w >> flags.var2.b) | \
|
if (!flags.var2.b) { \
|
||||||
|
flags.result.w=flags.var1.w; \
|
||||||
|
} else { \
|
||||||
|
flags.result.w=(flags.var1.w >> flags.var2.b) | \
|
||||||
(flags.cf << (16-flags.var2.b)) | \
|
(flags.cf << (16-flags.var2.b)) | \
|
||||||
(flags.var1.w << (17-flags.var2.b)); \
|
(flags.var1.w << (17-flags.var2.b)); \
|
||||||
|
} \
|
||||||
save(op1,flags.result.w);
|
save(op1,flags.result.w);
|
||||||
|
|
||||||
|
|
||||||
#define RCRD(op1,op2,load,save) \
|
#define RCRD(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
|
||||||
flags.cf=get_CF();flags.type=t_RCRd; \
|
flags.cf=get_CF();flags.type=t_RCRd; \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op2; \
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
||||||
if (flags.var2.b==1) { \
|
if (flags.var2.b==1) { \
|
||||||
flags.result.d=flags.var1.d >> 1 | flags.cf << 31; \
|
flags.result.d=flags.var1.d >> 1 | flags.cf << 31; \
|
||||||
} else { \
|
} else { \
|
||||||
flags.result.d=(flags.var1.d >> flags.var2.b) | \
|
flags.result.d=(flags.var1.d >> flags.var2.b) | \
|
||||||
(flags.cf << (32-flags.var2.b)) | \
|
(flags.cf << (32-flags.var2.b)) | \
|
||||||
(flags.var1.d << (33-flags.var2.b)); \
|
(flags.var1.d << (33-flags.var2.b)); \
|
||||||
} \
|
} \
|
||||||
save(op1,flags.result.d);
|
save(op1,flags.result.d);
|
||||||
|
|
||||||
|
|
||||||
#define SHLB(op1,op2,load,save) \
|
#define SHLB(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.b=load(op1);flags.var2.b=op2; \
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
||||||
flags.result.b=flags.var1.b << flags.var2.b; \
|
flags.result.b=flags.var1.b << flags.var2.b; \
|
||||||
save(op1,flags.result.b); \
|
save(op1,flags.result.b); \
|
||||||
flags.type=t_SHLb;
|
flags.type=t_SHLb;
|
||||||
|
|
||||||
#define SHLW(op1,op2,load,save) \
|
#define SHLW(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.w=load(op1);flags.var2.b=op2; \
|
flags.var1.w=load(op1);flags.var2.b=op2 ; \
|
||||||
flags.result.w=flags.var1.w << flags.var2.b; \
|
flags.result.w=flags.var1.w << flags.var2.b; \
|
||||||
save(op1,flags.result.w); \
|
save(op1,flags.result.w); \
|
||||||
flags.type=t_SHLw;
|
flags.type=t_SHLw;
|
||||||
|
|
||||||
#define SHLD(op1,op2,load,save) \
|
#define SHLD(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op2; \
|
flags.var1.d=load(op1);flags.var2.b=op2; \
|
||||||
flags.result.d=flags.var1.d << flags.var2.b; \
|
flags.result.d=flags.var1.d << flags.var2.b; \
|
||||||
save(op1,flags.result.d); \
|
save(op1,flags.result.d); \
|
||||||
flags.type=t_SHLd;
|
flags.type=t_SHLd;
|
||||||
|
|
||||||
|
|
||||||
#define SHRB(op1,op2,load,save) \
|
#define SHRB(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.b=load(op1);flags.var2.b=op2; \
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
||||||
flags.result.b=flags.var1.b >> flags.var2.b; \
|
flags.result.b=flags.var1.b >> flags.var2.b; \
|
||||||
save(op1,flags.result.b); \
|
save(op1,flags.result.b); \
|
||||||
flags.type=t_SHRb;
|
flags.type=t_SHRb;
|
||||||
|
|
||||||
#define SHRW(op1,op2,load,save) \
|
#define SHRW(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.w=load(op1);flags.var2.b=op2; \
|
flags.var1.w=load(op1);flags.var2.b=op2; \
|
||||||
flags.result.w=flags.var1.w >> flags.var2.b; \
|
flags.result.w=flags.var1.w >> flags.var2.b; \
|
||||||
save(op1,flags.result.w); \
|
save(op1,flags.result.w); \
|
||||||
flags.type=t_SHRw;
|
flags.type=t_SHRw;
|
||||||
|
|
||||||
#define SHRD(op1,op2,load,save) \
|
#define SHRD(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op2; \
|
flags.var1.d=load(op1);flags.var2.b=op2; \
|
||||||
flags.result.d=flags.var1.d >> flags.var2.b; \
|
flags.result.d=flags.var1.d >> flags.var2.b; \
|
||||||
save(op1,flags.result.d); \
|
save(op1,flags.result.d); \
|
||||||
flags.type=t_SHRd;
|
flags.type=t_SHRd;
|
||||||
|
|
||||||
|
|
||||||
#define SARB(op1,op2,load,save) \
|
#define SARB(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.b=load(op1);flags.var2.b=op2; \
|
flags.var1.b=load(op1);flags.var2.b=op2; \
|
||||||
if (flags.var2.b>8) flags.var2.b=8; \
|
if (flags.var2.b>8) flags.var2.b=8; \
|
||||||
if (flags.var1.b & 0x80) { \
|
if (flags.var1.b & 0x80) { \
|
||||||
flags.result.b=(flags.var1.b >> flags.var2.b)| \
|
flags.result.b=(flags.var1.b >> flags.var2.b)| \
|
||||||
(0xff << (8 - flags.var2.b)); \
|
(0xff << (8 - flags.var2.b)); \
|
||||||
} else { \
|
} else { \
|
||||||
flags.result.b=flags.var1.b >> flags.var2.b; \
|
flags.result.b=flags.var1.b >> flags.var2.b; \
|
||||||
} \
|
} \
|
||||||
save(op1,flags.result.b); \
|
save(op1,flags.result.b); \
|
||||||
flags.type=t_SARb;
|
flags.type=t_SARb;
|
||||||
|
|
||||||
#define SARW(op1,op2,load,save) \
|
#define SARW(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.w=load(op1);flags.var2.b=op2; \
|
flags.var1.w=load(op1);flags.var2.b=op2; \
|
||||||
if (flags.var2.b>16) flags.var2.b=16; \
|
if (flags.var2.b>16) flags.var2.b=16; \
|
||||||
if (flags.var1.w & 0x8000) { \
|
if (flags.var1.w & 0x8000) { \
|
||||||
flags.result.w=(flags.var1.w >> flags.var2.b)| \
|
flags.result.w=(flags.var1.w >> flags.var2.b)| \
|
||||||
(0xffff << (16 - flags.var2.b)); \
|
(0xffff << (16 - flags.var2.b)); \
|
||||||
} else { \
|
} else { \
|
||||||
flags.result.w=flags.var1.w >> flags.var2.b; \
|
flags.result.w=flags.var1.w >> flags.var2.b; \
|
||||||
} \
|
} \
|
||||||
save(op1,flags.result.w); \
|
save(op1,flags.result.w); \
|
||||||
flags.type=t_SARw;
|
flags.type=t_SARw;
|
||||||
|
|
||||||
#define SARD(op1,op2,load,save) \
|
#define SARD(op1,op2,load,save) \
|
||||||
if (!op2) break; \
|
if (!op2) break; \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op2; \
|
flags.var2.b=op2;flags.var1.d=load(op1); \
|
||||||
if (flags.var1.d & 0x80000000) { \
|
if (flags.var1.d & 0x80000000) { \
|
||||||
flags.result.d=(flags.var1.d >> flags.var2.b)| \
|
flags.result.d=(flags.var1.d >> flags.var2.b)| \
|
||||||
(0xffffffff << (32 - flags.var2.b)); \
|
(0xffffffff << (32 - flags.var2.b)); \
|
||||||
} else { \
|
} else { \
|
||||||
flags.result.d=flags.var1.d >> flags.var2.b; \
|
flags.result.d=flags.var1.d >> flags.var2.b; \
|
||||||
} \
|
} \
|
||||||
save(op1,flags.result.d); \
|
save(op1,flags.result.d); \
|
||||||
flags.type=t_SARd;
|
flags.type=t_SARd;
|
||||||
@ -564,30 +612,43 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* let's hope bochs has it correct with the higher than 16 shifts */
|
/* let's hope bochs has it correct with the higher than 16 shifts */
|
||||||
|
/* double-precision shift left has low bits in second argument */
|
||||||
#define DSHLW(op1,op2,op3,load,save) \
|
#define DSHLW(op1,op2,op3,load,save) \
|
||||||
flags.var1.d=(load(op1)<<16)|op2;flags.var2.b=op3; \
|
Bit8u val=op3 & 0x1F; \
|
||||||
|
if (!val) break; \
|
||||||
|
flags.var2.b=val;flags.var1.d=(load(op1)<<16)|op2; \
|
||||||
Bit32u tempd=flags.var1.d << flags.var2.b; \
|
Bit32u tempd=flags.var1.d << flags.var2.b; \
|
||||||
if (flags.var2.b>16) tempd |= (op2 << (flags.var2.b - 16)); \
|
if (flags.var2.b>16) tempd |= (op2 << (flags.var2.b - 16)); \
|
||||||
flags.result.w=(Bit16u)(tempd >> 16); \
|
flags.result.w=(Bit16u)(tempd >> 16); \
|
||||||
save(op1,flags.result.w); \
|
save(op1,flags.result.w); \
|
||||||
flags.type=t_DSHLw;
|
flags.type=t_DSHLw;
|
||||||
|
|
||||||
#define DSHLD(op1,op2,op3,load,save) \
|
#define DSHLD(op1,op2,op3,load,save) \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op3; \
|
Bit8u val=op3 & 0x1F; \
|
||||||
|
if (!val) break; \
|
||||||
|
flags.var2.b=val;flags.var1.d=load(op1); \
|
||||||
flags.result.d=(flags.var1.d << flags.var2.b) | (op2 >> (32-flags.var2.b)); \
|
flags.result.d=(flags.var1.d << flags.var2.b) | (op2 >> (32-flags.var2.b)); \
|
||||||
save(op1,flags.result.d); \
|
save(op1,flags.result.d); \
|
||||||
flags.type=t_DSHLd;
|
flags.type=t_DSHLd;
|
||||||
|
|
||||||
|
/* double-precision shift right has high bits in second argument */
|
||||||
#define DSHRW(op1,op2,op3,load,save) \
|
#define DSHRW(op1,op2,op3,load,save) \
|
||||||
flags.var1.d=(load(op1)<<16)|op2;flags.var2.b=op3; \
|
Bit8u val=op3 & 0x1F; \
|
||||||
|
if (!val) break; \
|
||||||
|
flags.var2.b=val;flags.var1.d=(op2<<16)|load(op1); \
|
||||||
Bit32u tempd=flags.var1.d >> flags.var2.b; \
|
Bit32u tempd=flags.var1.d >> flags.var2.b; \
|
||||||
if (flags.var2.b>16) tempd |= (op2 << (32-flags.var2.b )); \
|
if (flags.var2.b>16) tempd |= (op2 << (32-flags.var2.b )); \
|
||||||
flags.result.w=(Bit16u)(tempd); \
|
flags.result.w=(Bit16u)(tempd); \
|
||||||
save(op1,flags.result.w); \
|
save(op1,flags.result.w); \
|
||||||
flags.type=t_DSHRw;
|
flags.type=t_DSHRw;
|
||||||
|
|
||||||
#define DSHRD(op1,op2,op3,load,save) \
|
#define DSHRD(op1,op2,op3,load,save) \
|
||||||
flags.var1.d=load(op1);flags.var2.b=op3; \
|
Bit8u val=op3 & 0x1F; \
|
||||||
|
if (!val) break; \
|
||||||
|
flags.var2.b=val;flags.var1.d=load(op1); \
|
||||||
flags.result.d=(flags.var1.d >> flags.var2.b) | (op2 << (32-flags.var2.b)); \
|
flags.result.d=(flags.var1.d >> flags.var2.b) | (op2 << (32-flags.var2.b)); \
|
||||||
save(op1,flags.result.d); \
|
save(op1,flags.result.d); \
|
||||||
flags.type=t_DSHRd;
|
flags.type=t_DSHRd;
|
||||||
|
|
||||||
|
#define BSWAP(op1) \
|
||||||
|
op1 = (op1>>24)|((op1>>8)&0xFF00)|((op1<<8)&0xFF0000)|((op1<<24)&0xFF000000);
|
||||||
|
@ -32,9 +32,9 @@ restart:
|
|||||||
case 0x05: /* ADD AX,Iw */
|
case 0x05: /* ADD AX,Iw */
|
||||||
AXIw(ADDW);break;
|
AXIw(ADDW);break;
|
||||||
case 0x06: /* PUSH ES */
|
case 0x06: /* PUSH ES */
|
||||||
Push_16(Segs[es].value);break;
|
Push_16(SegValue(es));break;
|
||||||
case 0x07: /* POP ES */
|
case 0x07: /* POP ES */
|
||||||
SetSegment_16(es,Pop_16());break;
|
SegSet16(es,Pop_16());break;
|
||||||
case 0x08: /* OR Eb,Gb */
|
case 0x08: /* OR Eb,Gb */
|
||||||
RMEbGb(ORB);break;
|
RMEbGb(ORB);break;
|
||||||
case 0x09: /* OR Ew,Gw */
|
case 0x09: /* OR Ew,Gw */
|
||||||
@ -48,7 +48,7 @@ restart:
|
|||||||
case 0x0d: /* OR AX,Iw */
|
case 0x0d: /* OR AX,Iw */
|
||||||
AXIw(ORW);break;
|
AXIw(ORW);break;
|
||||||
case 0x0e: /* PUSH CS */
|
case 0x0e: /* PUSH CS */
|
||||||
Push_16(Segs[cs].value);break;
|
Push_16(SegValue(cs));break;
|
||||||
case 0x0f: /* 2 byte opcodes*/
|
case 0x0f: /* 2 byte opcodes*/
|
||||||
#include "prefix_of.h"
|
#include "prefix_of.h"
|
||||||
break;
|
break;
|
||||||
@ -65,9 +65,9 @@ restart:
|
|||||||
case 0x15: /* ADC AX,Iw */
|
case 0x15: /* ADC AX,Iw */
|
||||||
AXIw(ADCW);break;
|
AXIw(ADCW);break;
|
||||||
case 0x16: /* PUSH SS */
|
case 0x16: /* PUSH SS */
|
||||||
Push_16(Segs[ss].value);break;
|
Push_16(SegValue(ss));break;
|
||||||
case 0x17: /* POP SS */
|
case 0x17: /* POP SS */
|
||||||
SetSegment_16(ss,Pop_16());break;
|
SegSet16(ss,Pop_16());break;
|
||||||
case 0x18: /* SBB Eb,Gb */
|
case 0x18: /* SBB Eb,Gb */
|
||||||
RMEbGb(SBBB);break;
|
RMEbGb(SBBB);break;
|
||||||
case 0x19: /* SBB Ew,Gw */
|
case 0x19: /* SBB Ew,Gw */
|
||||||
@ -81,9 +81,9 @@ restart:
|
|||||||
case 0x1d: /* SBB AX,Iw */
|
case 0x1d: /* SBB AX,Iw */
|
||||||
AXIw(SBBW);break;
|
AXIw(SBBW);break;
|
||||||
case 0x1e: /* PUSH DS */
|
case 0x1e: /* PUSH DS */
|
||||||
Push_16(Segs[ds].value);break;
|
Push_16(SegValue(ds));break;
|
||||||
case 0x1f: /* POP DS */
|
case 0x1f: /* POP DS */
|
||||||
SetSegment_16(ds,Pop_16());break;
|
SegSet16(ds,Pop_16());break;
|
||||||
case 0x20: /* AND Eb,Gb */
|
case 0x20: /* AND Eb,Gb */
|
||||||
RMEbGb(ANDB);break;
|
RMEbGb(ANDB);break;
|
||||||
case 0x21: /* AND Ew,Gw */
|
case 0x21: /* AND Ew,Gw */
|
||||||
@ -235,9 +235,9 @@ restart:
|
|||||||
Push_16(reg_dx);break;
|
Push_16(reg_dx);break;
|
||||||
case 0x53: /* PUSH BX */
|
case 0x53: /* PUSH BX */
|
||||||
Push_16(reg_bx);break;
|
Push_16(reg_bx);break;
|
||||||
case 0x54: /* PUSH SP */
|
case 0x54: /* PUSH SP */
|
||||||
//TODO Check if this is correct i think it's SP+2 or something
|
//TODO Check if this is correct i think it's SP+2 or something
|
||||||
Push_16(reg_sp);break;
|
Push_16(reg_sp);break;
|
||||||
case 0x55: /* PUSH BP */
|
case 0x55: /* PUSH BP */
|
||||||
Push_16(reg_bp);break;
|
Push_16(reg_bp);break;
|
||||||
case 0x56: /* PUSH SI */
|
case 0x56: /* PUSH SI */
|
||||||
@ -252,8 +252,8 @@ restart:
|
|||||||
reg_dx=Pop_16();break;
|
reg_dx=Pop_16();break;
|
||||||
case 0x5b: /* POP BX */
|
case 0x5b: /* POP BX */
|
||||||
reg_bx=Pop_16();break;
|
reg_bx=Pop_16();break;
|
||||||
case 0x5c: /* POP SP */
|
case 0x5c: /* POP SP */
|
||||||
reg_sp=Pop_16();break;
|
reg_sp=Pop_16();break;
|
||||||
case 0x5d: /* POP BP */
|
case 0x5d: /* POP BP */
|
||||||
reg_bp=Pop_16();break;
|
reg_bp=Pop_16();break;
|
||||||
case 0x5e: /* POP SI */
|
case 0x5e: /* POP SI */
|
||||||
@ -274,7 +274,7 @@ restart:
|
|||||||
GetRMrw;GetEAa;
|
GetRMrw;GetEAa;
|
||||||
bound_min=LoadMw(eaa);
|
bound_min=LoadMw(eaa);
|
||||||
bound_max=LoadMw(eaa+2);
|
bound_max=LoadMw(eaa+2);
|
||||||
if ( (*rmrw < bound_min) || (*rmrw > bound_max) ) {
|
if ( (((Bit16s)*rmrw) < bound_min) || (((Bit16s)*rmrw) > bound_max) ) {
|
||||||
INTERRUPT(5);
|
INTERRUPT(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -524,17 +524,17 @@ restart:
|
|||||||
GetRM;Bit16u val;
|
GetRM;Bit16u val;
|
||||||
switch (rm & 0x38) {
|
switch (rm & 0x38) {
|
||||||
case 0x00: /* MOV Ew,ES */
|
case 0x00: /* MOV Ew,ES */
|
||||||
val=Segs[es].value;break;
|
val=SegValue(es);break;
|
||||||
case 0x08: /* MOV Ew,CS */
|
case 0x08: /* MOV Ew,CS */
|
||||||
val=Segs[cs].value;break;
|
val=SegValue(cs);break;
|
||||||
case 0x10: /* MOV Ew,SS */
|
case 0x10: /* MOV Ew,SS */
|
||||||
val=Segs[ss].value;break;
|
val=SegValue(ss);break;
|
||||||
case 0x18: /* MOV Ew,DS */
|
case 0x18: /* MOV Ew,DS */
|
||||||
val=Segs[ds].value;break;
|
val=SegValue(ds);break;
|
||||||
case 0x20: /* MOV Ew,FS */
|
case 0x20: /* MOV Ew,FS */
|
||||||
val=Segs[fs].value;break;
|
val=SegValue(fs);break;
|
||||||
case 0x28: /* MOV Ew,GS */
|
case 0x28: /* MOV Ew,GS */
|
||||||
val=Segs[gs].value;break;
|
val=SegValue(gs);break;
|
||||||
default:
|
default:
|
||||||
val=0;
|
val=0;
|
||||||
E_Exit("CPU:8c:Illegal RM Byte");
|
E_Exit("CPU:8c:Illegal RM Byte");
|
||||||
@ -583,18 +583,18 @@ restart:
|
|||||||
else {GetEAa;val=LoadMw(eaa);}
|
else {GetEAa;val=LoadMw(eaa);}
|
||||||
switch (rm & 0x38) {
|
switch (rm & 0x38) {
|
||||||
case 0x00: /* MOV ES,Ew */
|
case 0x00: /* MOV ES,Ew */
|
||||||
SetSegment_16(es,val);break;
|
SegSet16(es,val);break;
|
||||||
case 0x08: /* MOV CS,Ew Illegal*/
|
case 0x08: /* MOV CS,Ew Illegal*/
|
||||||
E_Exit("CPU:Illegal MOV CS Call");
|
E_Exit("CPU:Illegal MOV CS Call");
|
||||||
break;
|
break;
|
||||||
case 0x10: /* MOV SS,Ew */
|
case 0x10: /* MOV SS,Ew */
|
||||||
SetSegment_16(ss,val);break;
|
SegSet16(ss,val);break;
|
||||||
case 0x18: /* MOV DS,Ew */
|
case 0x18: /* MOV DS,Ew */
|
||||||
SetSegment_16(ds,val);break;
|
SegSet16(ds,val);break;
|
||||||
case 0x20: /* MOV FS,Ew */
|
case 0x20: /* MOV FS,Ew */
|
||||||
SetSegment_16(fs,val);break;
|
SegSet16(fs,val);break;
|
||||||
case 0x28: /* MOV GS,Ew */
|
case 0x28: /* MOV GS,Ew */
|
||||||
SetSegment_16(gs,val);break;
|
SegSet16(gs,val);break;
|
||||||
default:
|
default:
|
||||||
E_Exit("CPU:8e:Illegal RM Byte");
|
E_Exit("CPU:8e:Illegal RM Byte");
|
||||||
}
|
}
|
||||||
@ -639,8 +639,8 @@ restart:
|
|||||||
case 0x9a: /* CALL Ap */
|
case 0x9a: /* CALL Ap */
|
||||||
{
|
{
|
||||||
Bit16u newip=Fetchw();Bit16u newcs=Fetchw();
|
Bit16u newip=Fetchw();Bit16u newcs=Fetchw();
|
||||||
Push_16(Segs[cs].value);Push_16(GETIP);
|
Push_16(SegValue(cs));Push_16(GETIP);
|
||||||
SetSegment_16(cs,newcs);SETIP(newip);
|
SegSet16(cs,newcs);SETIP(newip);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x9b: /* WAIT */
|
case 0x9b: /* WAIT */
|
||||||
@ -675,35 +675,27 @@ restart:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xa0: /* MOV AL,Ob */
|
case 0xa0: /* MOV AL,Ob */
|
||||||
if (segprefix_on) {
|
{
|
||||||
reg_al=LoadMb(segprefix_base+Fetchw());
|
GetEADirect;
|
||||||
SegPrefixReset;
|
reg_al=LoadMb(eaa);
|
||||||
} else {
|
|
||||||
reg_al=LoadMb(SegBase(ds)+Fetchw());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xa1: /* MOV AX,Ow */
|
case 0xa1: /* MOV AX,Ow */
|
||||||
if (segprefix_on) {
|
{
|
||||||
reg_ax=LoadMw(segprefix_base+Fetchw());
|
GetEADirect;
|
||||||
SegPrefixReset;
|
reg_ax=LoadMw(eaa);
|
||||||
} else {
|
|
||||||
reg_ax=LoadMw(SegBase(ds)+Fetchw());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xa2: /* MOV Ob,AL */
|
case 0xa2: /* MOV Ob,AL */
|
||||||
if (segprefix_on) {
|
{
|
||||||
SaveMb((segprefix_base+Fetchw()),reg_al);
|
GetEADirect;
|
||||||
SegPrefixReset;
|
SaveMb(eaa,reg_al);
|
||||||
} else {
|
|
||||||
SaveMb((SegBase(ds)+Fetchw()),reg_al);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xa3: /* MOV Ow,AX */
|
case 0xa3: /* MOV Ow,AX */
|
||||||
if (segprefix_on) {
|
{
|
||||||
SaveMw((segprefix_base+Fetchw()),reg_ax);
|
GetEADirect;
|
||||||
SegPrefixReset;
|
SaveMw(eaa,reg_ax);
|
||||||
} else {
|
|
||||||
SaveMw((SegBase(ds)+Fetchw()),reg_ax);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xa4: /* MOVSB */
|
case 0xa4: /* MOVSB */
|
||||||
@ -838,13 +830,13 @@ restart:
|
|||||||
case 0xc4: /* LES */
|
case 0xc4: /* LES */
|
||||||
{
|
{
|
||||||
GetRMrw;GetEAa;
|
GetRMrw;GetEAa;
|
||||||
*rmrw=LoadMw(eaa);SetSegment_16(es,LoadMw(eaa+2));
|
*rmrw=LoadMw(eaa);SegSet16(es,LoadMw(eaa+2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xc5: /* LDS */
|
case 0xc5: /* LDS */
|
||||||
{
|
{
|
||||||
GetRMrw;GetEAa;
|
GetRMrw;GetEAa;
|
||||||
*rmrw=LoadMw(eaa);SetSegment_16(ds,LoadMw(eaa+2));
|
*rmrw=LoadMw(eaa);SegSet16(ds,LoadMw(eaa+2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xc6: /* MOV Eb,Ib */
|
case 0xc6: /* MOV Eb,Ib */
|
||||||
@ -876,21 +868,28 @@ restart:
|
|||||||
{
|
{
|
||||||
Bit16u addsp=Fetchw();
|
Bit16u addsp=Fetchw();
|
||||||
Bit16u newip=Pop_16();Bit16u newcs=Pop_16();
|
Bit16u newip=Pop_16();Bit16u newcs=Pop_16();
|
||||||
reg_sp+=addsp;SetSegment_16(cs,newcs);SETIP(newip);
|
reg_sp+=addsp;SegSet16(cs,newcs);SETIP(newip);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xcb: /* RETF */
|
case 0xcb: /* RETF */
|
||||||
{
|
{
|
||||||
Bit16u newip=Pop_16();Bit16u newcs=Pop_16();
|
Bit16u newip=Pop_16();Bit16u newcs=Pop_16();
|
||||||
SetSegment_16(cs,newcs);SETIP(newip);
|
SegSet16(cs,newcs);SETIP(newip);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xcc: /* INT3 */
|
case 0xcc: /* INT3 */
|
||||||
INTERRUPT(3);
|
INTERRUPT(3);
|
||||||
|
#if C_DEBUG
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case 0xcd: /* INT Ib */
|
case 0xcd: /* INT Ib */
|
||||||
{
|
{
|
||||||
Bit8u num=Fetchb();
|
Bit8u num=Fetchb();
|
||||||
|
#if C_DEBUG
|
||||||
|
SAVEIP;
|
||||||
|
if (DEBUG_IntBreakpoint(num)) return 0;
|
||||||
|
#endif
|
||||||
INTERRUPT(num);
|
INTERRUPT(num);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -900,7 +899,7 @@ restart:
|
|||||||
case 0xcf: /* IRET */
|
case 0xcf: /* IRET */
|
||||||
{
|
{
|
||||||
Bit16u newip=Pop_16();Bit16u newcs=Pop_16();
|
Bit16u newip=Pop_16();Bit16u newcs=Pop_16();
|
||||||
SetSegment_16(cs,newcs);SETIP(newip);
|
SegSet16(cs,newcs);SETIP(newip);
|
||||||
Bit16u pflags=Pop_16();Save_Flagsw(pflags);
|
Bit16u pflags=Pop_16();Save_Flagsw(pflags);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -933,17 +932,35 @@ restart:
|
|||||||
//TODO PF
|
//TODO PF
|
||||||
flags.type=t_UNKNOWN;
|
flags.type=t_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
case 0xd6: /* Not in intel specs */
|
case 0xd6: /* SALC */
|
||||||
NOTDONE;
|
reg_al = get_CF() ? 0xFF : 0;
|
||||||
break;
|
break;
|
||||||
case 0xd7: /* XLAT */
|
case 0xd7: /* XLAT */
|
||||||
if (segprefix_on) {
|
if (prefixes & PREFIX_SEG) {
|
||||||
reg_al=LoadMb(segprefix_base+(Bit16u)(reg_bx+reg_al));
|
reg_al=LoadMb(segprefix_base+(Bit16u)(reg_bx+reg_al));
|
||||||
SegPrefixReset;
|
PrefixReset;
|
||||||
} else {
|
} else {
|
||||||
reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
|
reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef CPU_FPU
|
||||||
|
case 0xd8: /* FPU ESC 0 */
|
||||||
|
FPU_ESC(0);break;
|
||||||
|
case 0xd9: /* FPU ESC 1 */
|
||||||
|
FPU_ESC(1);break;
|
||||||
|
case 0xda: /* FPU ESC 2 */
|
||||||
|
FPU_ESC(2);break;
|
||||||
|
case 0xdb: /* FPU ESC 3 */
|
||||||
|
FPU_ESC(3);break;
|
||||||
|
case 0xdc: /* FPU ESC 4 */
|
||||||
|
FPU_ESC(4);break;
|
||||||
|
case 0xdd: /* FPU ESC 5 */
|
||||||
|
FPU_ESC(5);break;
|
||||||
|
case 0xde: /* FPU ESC 6 */
|
||||||
|
FPU_ESC(6);break;
|
||||||
|
case 0xdf: /* FPU ESC 7 */
|
||||||
|
FPU_ESC(7);break;
|
||||||
|
#else
|
||||||
case 0xd8: /* FPU ESC 0 */
|
case 0xd8: /* FPU ESC 0 */
|
||||||
case 0xd9: /* FPU ESC 1 */
|
case 0xd9: /* FPU ESC 1 */
|
||||||
case 0xda: /* FPU ESC 2 */
|
case 0xda: /* FPU ESC 2 */
|
||||||
@ -954,15 +971,10 @@ restart:
|
|||||||
case 0xdf: /* FPU ESC 7 */
|
case 0xdf: /* FPU ESC 7 */
|
||||||
{
|
{
|
||||||
Bit8u rm=Fetchb();
|
Bit8u rm=Fetchb();
|
||||||
if (rm>=0xc0) {
|
if (rm<0xc0) GetEAa;
|
||||||
FPU_ESC0_Normal(rm);
|
|
||||||
} else {
|
|
||||||
GetEAa;FPU_ESC0_EA(rm,eaa);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 0xe0: /* LOOPNZ */
|
case 0xe0: /* LOOPNZ */
|
||||||
if ((--reg_cx) && !get_ZF()) ADDIPFAST(Fetchbs());
|
if ((--reg_cx) && !get_ZF()) ADDIPFAST(Fetchbs());
|
||||||
else ADDIPFAST(1);
|
else ADDIPFAST(1);
|
||||||
@ -1005,7 +1017,7 @@ restart:
|
|||||||
{
|
{
|
||||||
Bit16u newip=Fetchw();
|
Bit16u newip=Fetchw();
|
||||||
Bit16u newcs=Fetchw();
|
Bit16u newcs=Fetchw();
|
||||||
SetSegment_16(cs,newcs);
|
SegSet16(cs,newcs);
|
||||||
SETIP(newip);
|
SETIP(newip);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1041,9 +1053,9 @@ restart:
|
|||||||
{
|
{
|
||||||
EAPoint to=SegBase(es);
|
EAPoint to=SegBase(es);
|
||||||
EAPoint from;
|
EAPoint from;
|
||||||
if (segprefix_on) {
|
if (prefixes & PREFIX_SEG) {
|
||||||
from=(segprefix_base);
|
from=(segprefix_base);
|
||||||
SegPrefixReset;
|
PrefixReset;
|
||||||
} else {
|
} else {
|
||||||
from=SegBase(ds);
|
from=SegBase(ds);
|
||||||
}
|
}
|
||||||
@ -1453,11 +1465,11 @@ restart:
|
|||||||
break;
|
break;
|
||||||
case 0x18: /* CALL Ep */
|
case 0x18: /* CALL Ep */
|
||||||
{
|
{
|
||||||
Push_16(Segs[cs].value);
|
Push_16(SegValue(cs));
|
||||||
GetEAa;Push_16(GETIP);
|
GetEAa;Push_16(GETIP);
|
||||||
Bit16u newip=LoadMw(eaa);
|
Bit16u newip=LoadMw(eaa);
|
||||||
Bit16u newcs=LoadMw(eaa+2);
|
Bit16u newcs=LoadMw(eaa+2);
|
||||||
SetSegment_16(cs,newcs);
|
SegSet16(cs,newcs);
|
||||||
SETIP(newip);
|
SETIP(newip);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1470,7 +1482,7 @@ restart:
|
|||||||
GetEAa;
|
GetEAa;
|
||||||
Bit16u newip=LoadMw(eaa);
|
Bit16u newip=LoadMw(eaa);
|
||||||
Bit16u newcs=LoadMw(eaa+2);
|
Bit16u newcs=LoadMw(eaa+2);
|
||||||
SetSegment_16(cs,newcs);
|
SegSet16(cs,newcs);
|
||||||
SETIP(newip);
|
SETIP(newip);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -230,6 +230,8 @@ switch(Fetchb()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0x85: /* TEST Ed,Gd */
|
||||||
|
RMEdGd(TESTD);break;
|
||||||
case 0x8f: /* POP Ed */
|
case 0x8f: /* POP Ed */
|
||||||
{
|
{
|
||||||
GetRM;
|
GetRM;
|
||||||
@ -271,23 +273,20 @@ switch(Fetchb()) {
|
|||||||
}
|
}
|
||||||
case 0x9d: /* POPFD */
|
case 0x9d: /* POPFD */
|
||||||
{
|
{
|
||||||
Save_Flagsw((Bit16u)(Pop_32()&0xffff));
|
Bit16u val=(Bit16u)(Pop_32()&0xffff);
|
||||||
|
Save_Flagsw(val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xa1: /* MOV EAX,Ow */
|
case 0xa1: /* MOV EAX,Ow */
|
||||||
if (segprefix_on) {
|
{
|
||||||
reg_eax=LoadMd(segprefix_base+Fetchw());
|
GetEADirect;
|
||||||
SegPrefixReset;
|
reg_eax=LoadMd(eaa);
|
||||||
} else {
|
|
||||||
reg_eax=LoadMd(SegBase(ds)+Fetchw());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xa3: /* MOV Ow,EAX */
|
case 0xa3: /* MOV Ow,EAX */
|
||||||
if (segprefix_on) {
|
{
|
||||||
SaveMd((segprefix_base+Fetchw()),reg_eax);
|
GetEADirect;
|
||||||
SegPrefixReset;
|
SaveMd(eaa,reg_eax);
|
||||||
} else {
|
|
||||||
SaveMd((SegBase(ds)+Fetchw()),reg_eax);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0xa5: /* MOVSD */
|
case 0xa5: /* MOVSD */
|
||||||
@ -411,13 +410,13 @@ switch(Fetchb()) {
|
|||||||
Bit32u val;
|
Bit32u val;
|
||||||
if (rm >= 0xc0 ) {GetEArd;val=*eard;}
|
if (rm >= 0xc0 ) {GetEArd;val=*eard;}
|
||||||
else {GetEAa;val=LoadMd(eaa);}
|
else {GetEAa;val=LoadMd(eaa);}
|
||||||
if (val==0) {Interrupt(0);break;}
|
if (val==0) {INTERRUPT(0);break;}
|
||||||
temp.u=(((Bit64u)reg_edx)<<32)|reg_eax;
|
temp.u=(((Bit64u)reg_edx)<<32)|reg_eax;
|
||||||
quotient.u=temp.u/val;
|
quotient.u=temp.u/val;
|
||||||
reg_edx=(Bit32u)(temp.u % val);
|
reg_edx=(Bit32u)(temp.u % val);
|
||||||
reg_eax=(Bit32u)(quotient.u & 0xffffffff);
|
reg_eax=(Bit32u)(quotient.u & 0xffffffff);
|
||||||
if (quotient.u>0xffffffff)
|
if (quotient.u>0xffffffff)
|
||||||
Interrupt(0);
|
INTERRUPT(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x38: /* IDIV Ed */
|
case 0x38: /* IDIV Ed */
|
||||||
@ -426,13 +425,13 @@ switch(Fetchb()) {
|
|||||||
Bit32s val;
|
Bit32s val;
|
||||||
if (rm >= 0xc0 ) {GetEArd;val=*eards;}
|
if (rm >= 0xc0 ) {GetEArd;val=*eards;}
|
||||||
else {GetEAa;val=LoadMds(eaa);}
|
else {GetEAa;val=LoadMds(eaa);}
|
||||||
if (val==0) {Interrupt(0);break;}
|
if (val==0) {INTERRUPT(0);break;}
|
||||||
temp.s=(((Bit64u)reg_edx)<<32)|reg_eax;
|
temp.s=(((Bit64u)reg_edx)<<32)|reg_eax;
|
||||||
quotient.s=(temp.s/val);
|
quotient.s=(temp.s/val);
|
||||||
reg_edx=(Bit32s)(temp.s % val);
|
reg_edx=(Bit32s)(temp.s % val);
|
||||||
reg_eax=(Bit32s)(quotient.s);
|
reg_eax=(Bit32s)(quotient.s);
|
||||||
if (quotient.s!=(Bit32s)reg_eax)
|
if (quotient.s!=(Bit32s)reg_eax)
|
||||||
Interrupt(0);
|
INTERRUPT(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
switch(Fetchb()) {
|
switch(Fetchb()) {
|
||||||
|
case 0x00: /* GRP 6 */
|
||||||
|
{
|
||||||
|
INTERRUPT(6);
|
||||||
|
break;
|
||||||
|
GetRM;
|
||||||
|
switch (rm & 0x38) {
|
||||||
|
case 0x00:
|
||||||
|
default:
|
||||||
|
E_Exit("CPU:GRP6:Illegal call %2X",(rm>>3) &3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x01: /* GRP 7 */
|
case 0x01: /* GRP 7 */
|
||||||
{
|
{
|
||||||
GetRM;
|
GetRM;
|
||||||
@ -27,10 +40,67 @@ switch(Fetchb()) {
|
|||||||
else {GetEAa;SaveMw(eaa,0);}
|
else {GetEAa;SaveMw(eaa,0);}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
E_Exit("CPU:GRP7:Illegal call %2X",rm);
|
E_Exit("CPU:GRP7:Illegal call %2X",(rm>>3) &3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
/* 0x02 LAR Gw,Ew (286) */
|
||||||
|
/* 0x03 LSL Gw,Ew (286) */
|
||||||
|
/* 0x05 LOADALL (286 only?) */
|
||||||
|
/* 0x06 CLTS (286) */
|
||||||
|
/* 0x07 LOADALL (386 only?) */
|
||||||
|
/* 0x08 INVD (486) */
|
||||||
|
/* 0x02 WBINVD (486) */
|
||||||
|
/* 0x10 UMOV Eb,Gb (386) */
|
||||||
|
/* 0x11 UMOV Ew,Gw (386) */
|
||||||
|
/* 0x12 UMOV Gb,Eb (386) */
|
||||||
|
/* 0x13 UMOV Gw,Ew (386) */
|
||||||
|
/* 0x20 MOV Rd,CRx (386) */
|
||||||
|
/* 0x21 MOV Rd,DRx (386) */
|
||||||
|
/* 0x22 MOV CRx,Rd (386) */
|
||||||
|
/* 0x23 MOV DRx,Rd (386) */
|
||||||
|
/* 0x24 MOV Rd,TRx (386) */
|
||||||
|
/* 0x26 MOV TRx,Rd (386) */
|
||||||
|
/* 0x30 WRMSR (P5) */
|
||||||
|
/* 0x31 RDTSC (P5) */
|
||||||
|
/* 0x32 RDMSR (P5) */
|
||||||
|
/* 0x33 RDPMC (P6) */
|
||||||
|
/* 0x40-4F CMOVcc Gw,Ew (P6) */
|
||||||
|
/* 0x50 PAVEB Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x51 PADDSIW Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x52 PMAGW Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x54 PDISTIB Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x55 PSUBSIW Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x58 PMVZB Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x59 PMULHRW Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x5A PMVNZB Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x5B PMVLZB Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x5C PMVGEZB Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x5D PMULHRIW Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x5E PMACHRIW Rq,Eq (CYRIX MMX) */
|
||||||
|
/* 0x60 PUNPCKLBW Rq,Eq (MMX) */
|
||||||
|
/* 0x61 PUNPCKLWD Rq,Eq (MMX) */
|
||||||
|
/* 0x62 PUNPCKLDQ Rq,Eq (MMX) */
|
||||||
|
/* 0x63 PACKSSWB Rq,Eq (MMX) */
|
||||||
|
/* 0x64 PCMPGTB Rq,Eq (MMX) */
|
||||||
|
/* 0x65 PCMPGTW Rq,Eq (MMX) */
|
||||||
|
/* 0x66 PCMPGTD Rq,Eq (MMX) */
|
||||||
|
/* 0x67 PACKUSWB Rq,Eq (MMX) */
|
||||||
|
/* 0x68 PUNPCKHBW Rq,Eq (MMX) */
|
||||||
|
/* 0x69 PUNPCKHWD Rq,Eq (MMX) */
|
||||||
|
/* 0x6A PUNPCKHDQ Rq,Eq (MMX) */
|
||||||
|
/* 0x6B PACKSSDW Rq,Eq (MMX) */
|
||||||
|
/* 0x6E MOVD Rq,Ed (MMX) */
|
||||||
|
/* 0x6F MOVQ Rq,Eq (MMX) */
|
||||||
|
/* 0x71 PSLLW/PSRAW/PSRLW Rq,Ib (MMX) */
|
||||||
|
/* 0x72 PSLLD/PSRAD/PSRLD Rq,Ib (MMX) */
|
||||||
|
/* 0x73 PSLLQ/PSRLQ Rq,Ib (MMX) */
|
||||||
|
/* 0x74 PCMPEQB Rq,Eq (MMX) */
|
||||||
|
/* 0x75 PCMPEQW Rq,Eq (MMX) */
|
||||||
|
/* 0x76 PCMPEQD Rq,Eq (MMX) */
|
||||||
|
/* 0x77 EMMS (MMX) */
|
||||||
|
/* 0x7E MOVD Ed,Rq (MMX) */
|
||||||
|
/* 0x7F MOVQ Ed,Rq (MMX) */
|
||||||
case 0x80: /* JO */
|
case 0x80: /* JO */
|
||||||
JumpSIw(get_OF());break;
|
JumpSIw(get_OF());break;
|
||||||
case 0x81: /* JNO */
|
case 0x81: /* JNO */
|
||||||
@ -63,10 +133,59 @@ switch(Fetchb()) {
|
|||||||
JumpSIw(get_ZF() || (get_SF() != get_OF()));break;
|
JumpSIw(get_ZF() || (get_SF() != get_OF()));break;
|
||||||
case 0x8f: /* JNLE */
|
case 0x8f: /* JNLE */
|
||||||
JumpSIw((get_SF() == get_OF()) && !get_ZF());break;
|
JumpSIw((get_SF() == get_OF()) && !get_ZF());break;
|
||||||
|
|
||||||
|
case 0x90: /* SETO */
|
||||||
|
SETcc(get_OF());break;
|
||||||
|
case 0x91: /* SETNO */
|
||||||
|
SETcc(!get_OF());break;
|
||||||
|
case 0x92: /* SETB */
|
||||||
|
SETcc(get_CF());break;
|
||||||
|
case 0x93: /* SETNB */
|
||||||
|
SETcc(!get_CF());break;
|
||||||
|
case 0x94: /* SETZ */
|
||||||
|
SETcc(get_ZF());break;
|
||||||
|
case 0x95: /* SETNZ */
|
||||||
|
SETcc(!get_ZF()); break;
|
||||||
|
case 0x96: /* SETBE */
|
||||||
|
SETcc(get_CF() || get_ZF());break;
|
||||||
|
case 0x97: /* SETNBE */
|
||||||
|
SETcc(!get_CF() && !get_ZF());break;
|
||||||
|
case 0x98: /* SETS */
|
||||||
|
SETcc(get_SF());break;
|
||||||
|
case 0x99: /* SETNS */
|
||||||
|
SETcc(!get_SF());break;
|
||||||
|
case 0x9a: /* SETP */
|
||||||
|
SETcc(get_PF());break;
|
||||||
|
case 0x9b: /* SETNP */
|
||||||
|
SETcc(!get_PF());break;
|
||||||
|
case 0x9c: /* SETL */
|
||||||
|
SETcc(get_SF() != get_OF());break;
|
||||||
|
case 0x9d: /* SETNL */
|
||||||
|
SETcc(get_SF() == get_OF());break;
|
||||||
|
case 0x9e: /* SETLE */
|
||||||
|
SETcc(get_ZF() || (get_SF() != get_OF()));break;
|
||||||
|
case 0x9f: /* SETNLE */
|
||||||
|
SETcc((get_SF() == get_OF()) && !get_ZF());break;
|
||||||
|
|
||||||
case 0xa0: /* PUSH FS */
|
case 0xa0: /* PUSH FS */
|
||||||
Push_16(Segs[fs].value);break;
|
Push_16(SegValue(fs));break;
|
||||||
case 0xa1: /* POP FS */
|
case 0xa1: /* POP FS */
|
||||||
SetSegment_16(fs,Pop_16());break;
|
SegSet16(fs,Pop_16());break;
|
||||||
|
/* 0xa2 CPUID */
|
||||||
|
case 0xa3: /* BT Ew,Gw */
|
||||||
|
{
|
||||||
|
GetRMrw;
|
||||||
|
Bit16u mask=1 << (*rmrw & 15);
|
||||||
|
if (rm >= 0xc0 ) {
|
||||||
|
GetEArw;
|
||||||
|
flags.cf=(*earw & mask)>0;
|
||||||
|
} else {
|
||||||
|
GetEAa;Bit16u old=LoadMw(eaa);
|
||||||
|
flags.cf=(old & mask)>0;
|
||||||
|
}
|
||||||
|
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 0xa4: /* SHLD Ew,Gw,Ib */
|
case 0xa4: /* SHLD Ew,Gw,Ib */
|
||||||
{
|
{
|
||||||
GetRMrw;
|
GetRMrw;
|
||||||
@ -81,10 +200,29 @@ switch(Fetchb()) {
|
|||||||
else {GetEAa;DSHLW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);}
|
else {GetEAa;DSHLW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* 0xa6 XBTS (early 386 only) CMPXCHG (early 486 only) */
|
||||||
|
/* 0xa7 IBTS (early 386 only) CMPXCHG (early 486 only) */
|
||||||
case 0xa8: /* PUSH GS */
|
case 0xa8: /* PUSH GS */
|
||||||
Push_16(Segs[gs].value);break;
|
Push_16(SegValue(gs));break;
|
||||||
case 0xa9: /* POP GS */
|
case 0xa9: /* POP GS */
|
||||||
SetSegment_16(gs,Pop_16());break;
|
SegSet16(gs,Pop_16());break;
|
||||||
|
/* 0xaa RSM */
|
||||||
|
case 0xab: /* BTS Ew,Gw */
|
||||||
|
{
|
||||||
|
GetRMrw;
|
||||||
|
Bit16u mask=1 << (*rmrw & 15);
|
||||||
|
if (rm >= 0xc0 ) {
|
||||||
|
GetEArw;
|
||||||
|
flags.cf=(*earw & mask)>0;
|
||||||
|
*earw|=mask;
|
||||||
|
} else {
|
||||||
|
GetEAa;Bit16u old=LoadMw(eaa);
|
||||||
|
flags.cf=(old & mask)>0;
|
||||||
|
SaveMw(eaa,old | mask);
|
||||||
|
}
|
||||||
|
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 0xac: /* SHRD Ew,Gw,Ib */
|
case 0xac: /* SHRD Ew,Gw,Ib */
|
||||||
{
|
{
|
||||||
GetRMrw;
|
GetRMrw;
|
||||||
@ -111,16 +249,35 @@ switch(Fetchb()) {
|
|||||||
else {flags.cf=true;flags.of=true;}
|
else {flags.cf=true;flags.of=true;}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* 0xb0 CMPXCHG Eb,Gb */
|
||||||
|
/* 0xb1 CMPXCHG Ew,Gw */
|
||||||
|
/* 0xb2 LSS */
|
||||||
|
case 0xb3: /* BTR Ew,Gw */
|
||||||
|
{
|
||||||
|
GetRMrw;
|
||||||
|
Bit16u mask=1 << (*rmrw & 15);
|
||||||
|
if (rm >= 0xc0 ) {
|
||||||
|
GetEArw;
|
||||||
|
flags.cf=(*earw & mask)>0;
|
||||||
|
*earw&= ~mask;
|
||||||
|
} else {
|
||||||
|
GetEAa;Bit16u old=LoadMw(eaa);
|
||||||
|
flags.cf=(old & mask)>0;
|
||||||
|
SaveMw(eaa,old & ~mask);
|
||||||
|
}
|
||||||
|
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 0xb4: /* LFS */
|
case 0xb4: /* LFS */
|
||||||
{
|
{
|
||||||
GetRMrw;GetEAa;
|
GetRMrw;GetEAa;
|
||||||
*rmrw=LoadMw(eaa);SetSegment_16(fs,LoadMw(eaa+2));
|
*rmrw=LoadMw(eaa);SegSet16(fs,LoadMw(eaa+2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xb5: /* LGS */
|
case 0xb5: /* LGS */
|
||||||
{
|
{
|
||||||
GetRMrw;GetEAa;
|
GetRMrw;GetEAa;
|
||||||
*rmrw=LoadMw(eaa);SetSegment_16(gs,LoadMw(eaa+2));
|
*rmrw=LoadMw(eaa);SegSet16(gs,LoadMw(eaa+2));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xb6: /* MOVZX Gw,Eb */
|
case 0xb6: /* MOVZX Gw,Eb */
|
||||||
@ -130,12 +287,20 @@ switch(Fetchb()) {
|
|||||||
else {GetEAa;*rmrw=LoadMb(eaa);}
|
else {GetEAa;*rmrw=LoadMb(eaa);}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0xb7: /* MOVZX Gw,Ew */
|
||||||
|
case 0xbf: /* MOVSX Gw,Ew */
|
||||||
|
{
|
||||||
|
GetRMrw;
|
||||||
|
if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;}
|
||||||
|
else {GetEAa;*rmrw=LoadMw(eaa);}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 0xba: /* GRP8 Ew,Ib */
|
case 0xba: /* GRP8 Ew,Ib */
|
||||||
{
|
{
|
||||||
GetRM;
|
GetRM;
|
||||||
|
Bit16u mask=1 << (Fetchb() & 15);
|
||||||
if (rm >= 0xc0 ) {
|
if (rm >= 0xc0 ) {
|
||||||
GetEArw;
|
GetEArw;
|
||||||
Bit16u mask=1 << (Fetchb() & 15);
|
|
||||||
flags.cf=(*earw & mask)>0;
|
flags.cf=(*earw & mask)>0;
|
||||||
switch (rm & 0x38) {
|
switch (rm & 0x38) {
|
||||||
case 0x20: /* BT */
|
case 0x20: /* BT */
|
||||||
@ -144,16 +309,14 @@ switch(Fetchb()) {
|
|||||||
*earw|=mask;
|
*earw|=mask;
|
||||||
break;
|
break;
|
||||||
case 0x30: /* BTR */
|
case 0x30: /* BTR */
|
||||||
*earw&=~mask;
|
*earw&= ~mask;
|
||||||
break;
|
break;
|
||||||
case 0x38: /* BTC */
|
case 0x38: /* BTC */
|
||||||
if (flags.cf) *earw&=~mask;
|
*earw^=mask;
|
||||||
else *earw|=mask;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GetEAa;Bit16u old=LoadMw(eaa);
|
GetEAa;Bit16u old=LoadMw(eaa);
|
||||||
Bit16u mask=1 << (Fetchb() & 15);
|
|
||||||
flags.cf=(old & mask)>0;
|
flags.cf=(old & mask)>0;
|
||||||
switch (rm & 0x38) {
|
switch (rm & 0x38) {
|
||||||
case 0x20: /* BT */
|
case 0x20: /* BT */
|
||||||
@ -165,16 +328,64 @@ switch(Fetchb()) {
|
|||||||
SaveMw(eaa,old & ~mask);
|
SaveMw(eaa,old & ~mask);
|
||||||
break;
|
break;
|
||||||
case 0x38: /* BTC */
|
case 0x38: /* BTC */
|
||||||
if (flags.cf) old&=~mask;
|
SaveMw(eaa,old ^ mask);
|
||||||
else old|=mask;
|
|
||||||
SaveMw(eaa,old);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flags.type!=t_CF) flags.prev_type=flags.type;
|
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
|
||||||
flags.type=t_CF;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0xbb: /* BTC Ew,Gw */
|
||||||
|
{
|
||||||
|
GetRMrw;
|
||||||
|
Bit16u mask=1 << (*rmrw & 15);
|
||||||
|
if (rm >= 0xc0 ) {
|
||||||
|
GetEArw;
|
||||||
|
flags.cf=(*earw & mask)>0;
|
||||||
|
*earw^=mask;
|
||||||
|
} else {
|
||||||
|
GetEAa;Bit16u old=LoadMw(eaa);
|
||||||
|
flags.cf=(old & mask)>0;
|
||||||
|
SaveMw(eaa,old ^ mask);
|
||||||
|
}
|
||||||
|
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xbc: /* 0xbc BSF Gw,Ew */
|
||||||
|
{
|
||||||
|
GetRMrw;
|
||||||
|
Bit16u result,value;
|
||||||
|
if (rm >= 0xc0) { GetEArw; value=*earw; }
|
||||||
|
else { GetEAa; value=LoadMw(eaa); }
|
||||||
|
if (value==0) {
|
||||||
|
flags.zf = true;
|
||||||
|
} else {
|
||||||
|
result = 0;
|
||||||
|
while ((value & 0x01)==0) { result++; value>>=1; }
|
||||||
|
flags.zf = false;
|
||||||
|
*rmrw = result;
|
||||||
|
}
|
||||||
|
flags.type=t_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xbd: /* 0xbd BSR Gw,Ew */
|
||||||
|
{
|
||||||
|
GetRMrw;
|
||||||
|
Bit16u result,value;
|
||||||
|
if (rm >= 0xc0) { GetEArw; value=*earw; }
|
||||||
|
else { GetEAa; value=LoadMw(eaa); }
|
||||||
|
if (value==0) {
|
||||||
|
flags.zf = true;
|
||||||
|
} else {
|
||||||
|
result = 15; // Operandsize-1
|
||||||
|
while ((value & 0x8000)==0) { result--; value<<=1; }
|
||||||
|
flags.zf = false;
|
||||||
|
*rmrw = result;
|
||||||
|
}
|
||||||
|
flags.type=t_UNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* 0xbd BSR Gw,Ew */
|
||||||
case 0xbe: /* MOVSX Gw,Eb */
|
case 0xbe: /* MOVSX Gw,Eb */
|
||||||
{
|
{
|
||||||
GetRMrw;
|
GetRMrw;
|
||||||
@ -182,6 +393,48 @@ switch(Fetchb()) {
|
|||||||
else {GetEAa;*rmrw=LoadMbs(eaa);}
|
else {GetEAa;*rmrw=LoadMbs(eaa);}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* 0xc0 XADD Eb,Gb (486) */
|
||||||
|
/* 0xc1 XADD Ew,Gw (486) */
|
||||||
|
/* 0xc7 CMPXCHG8B Mq (P5) */
|
||||||
|
/* 0xc8-cf BSWAP Rw (odd behavior,486) */
|
||||||
|
case 0xc8: BSWAP(reg_eax); break;
|
||||||
|
case 0xc9: BSWAP(reg_ecx); break;
|
||||||
|
case 0xca: BSWAP(reg_edx); break;
|
||||||
|
case 0xcb: BSWAP(reg_ebx); break;
|
||||||
|
case 0xcc: BSWAP(reg_esp); break;
|
||||||
|
case 0xcd: BSWAP(reg_ebp); break;
|
||||||
|
case 0xce: BSWAP(reg_esi); break;
|
||||||
|
case 0xcf: BSWAP(reg_edi); break;
|
||||||
|
|
||||||
|
/* 0xd1 PSRLW Rq,Eq (MMX) */
|
||||||
|
/* 0xd2 PSRLD Rq,Eq (MMX) */
|
||||||
|
/* 0xd3 PSRLQ Rq,Eq (MMX) */
|
||||||
|
/* 0xd5 PMULLW Rq,Eq (MMX) */
|
||||||
|
/* 0xd8 PSUBUSB Rq,Eq (MMX) */
|
||||||
|
/* 0xd9 PSUBUSW Rq,Eq (MMX) */
|
||||||
|
/* 0xdb PAND Rq,Eq (MMX) */
|
||||||
|
/* 0xdc PADDUSB Rq,Eq (MMX) */
|
||||||
|
/* 0xdd PADDUSW Rq,Eq (MMX) */
|
||||||
|
/* 0xdf PANDN Rq,Eq (MMX) */
|
||||||
|
/* 0xe1 PSRAW Rq,Eq (MMX) */
|
||||||
|
/* 0xe2 PSRAD Rq,Eq (MMX) */
|
||||||
|
/* 0xe5 PMULHW Rq,Eq (MMX) */
|
||||||
|
/* 0xe8 PSUBSB Rq,Eq (MMX) */
|
||||||
|
/* 0xe9 PSUBSW Rq,Eq (MMX) */
|
||||||
|
/* 0xeb POR Rq,Eq (MMX) */
|
||||||
|
/* 0xec PADDSB Rq,Eq (MMX) */
|
||||||
|
/* 0xed PADDSW Rq,Eq (MMX) */
|
||||||
|
/* 0xef PXOR Rq,Eq (MMX) */
|
||||||
|
/* 0xf1 PSLLW Rq,Eq (MMX) */
|
||||||
|
/* 0xf2 PSLLD Rq,Eq (MMX) */
|
||||||
|
/* 0xf3 PSLLQ Rq,Eq (MMX) */
|
||||||
|
/* 0xf5 PMADDWD Rq,Eq (MMX) */
|
||||||
|
/* 0xf8 PSUBB Rq,Eq (MMX) */
|
||||||
|
/* 0xf9 PSUBW Rq,Eq (MMX) */
|
||||||
|
/* 0xfa PSUBD Rq,Eq (MMX) */
|
||||||
|
/* 0xfc PADDB Rq,Eq (MMX) */
|
||||||
|
/* 0xfd PADDW Rq,Eq (MMX) */
|
||||||
|
/* 0xfe PADDD Rq,Eq (MMX) */
|
||||||
default:
|
default:
|
||||||
SUBIP(1);
|
SUBIP(1);
|
||||||
E_Exit("CPU:Opcode 0F:%2X Unhandled",Fetchb());
|
E_Exit("CPU:Opcode 0F:%2X Unhandled",Fetchb());
|
||||||
|
@ -18,25 +18,13 @@
|
|||||||
|
|
||||||
EAPoint IPPoint;
|
EAPoint IPPoint;
|
||||||
|
|
||||||
|
|
||||||
#define SUBIP(a) IPPoint-=a
|
#define SUBIP(a) IPPoint-=a
|
||||||
#define SETIP(a) IPPoint=SegBase(cs)+a
|
#define SETIP(a) IPPoint=SegBase(cs)+a
|
||||||
#define GETIP (Bit16u)(IPPoint-SegBase(cs))
|
#define GETIP (Bit16u)(IPPoint-SegBase(cs))
|
||||||
#define SAVEIP reg_ip=GETIP
|
#define SAVEIP reg_ip=GETIP
|
||||||
#define LOADIP IPPoint=SegBase(cs)+reg_ip
|
#define LOADIP IPPoint=SegBase(cs)+reg_ip
|
||||||
/*
|
|
||||||
#define ADDIP(a) { \
|
|
||||||
Bit16u add_ip=(Bit16u)(IPPoint-SegBase(cs)); \
|
|
||||||
add_ip+=a; \
|
|
||||||
IPPoint=SegBase(cs)+add_ip; \
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static INLINE void ADDIP(Bit16u add) {
|
static INLINE void ADDIP(Bit16u add) {
|
||||||
|
|
||||||
// Bit16u oldip=(IPPoint-SegBase(cs));
|
|
||||||
// oldip+=add;
|
|
||||||
// IPPoint=SegBase(cs)+oldip;
|
|
||||||
IPPoint=SegBase(cs)+((Bit16u)(((Bit16u)(IPPoint-SegBase(cs)))+(Bit16u)add));
|
IPPoint=SegBase(cs)+((Bit16u)(((Bit16u)(IPPoint-SegBase(cs)))+(Bit16u)add));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,9 +32,6 @@ static INLINE void ADDIPFAST(Bit16s blah) {
|
|||||||
IPPoint+=blah;
|
IPPoint+=blah;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ERRORRETURN(a) { error_ret=a;goto errorreturn; }
|
|
||||||
|
|
||||||
|
|
||||||
static INLINE Bit8u Fetchb() {
|
static INLINE Bit8u Fetchb() {
|
||||||
Bit8u temp=LoadMb(IPPoint);
|
Bit8u temp=LoadMb(IPPoint);
|
||||||
IPPoint+=1;
|
IPPoint+=1;
|
||||||
@ -75,7 +60,6 @@ static INLINE Bit32s Fetchds() {
|
|||||||
return Fetchd();
|
return Fetchd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static INLINE void Push_16(Bit16u blah) {
|
static INLINE void Push_16(Bit16u blah) {
|
||||||
reg_sp-=2;
|
reg_sp-=2;
|
||||||
SaveMw(SegBase(ss)+reg_sp,blah);
|
SaveMw(SegBase(ss)+reg_sp,blah);
|
||||||
@ -98,21 +82,15 @@ static INLINE Bit32u Pop_32() {
|
|||||||
return temp;
|
return temp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define stringDI \
|
#define stringDI \
|
||||||
EAPoint to; \
|
EAPoint to; \
|
||||||
to=SegBase(es)+reg_di
|
to=SegBase(es)+reg_di
|
||||||
|
|
||||||
#define stringSI \
|
#define stringSI \
|
||||||
EAPoint from; \
|
EAPoint from; \
|
||||||
if (segprefix_on) { \
|
if (prefixes & PREFIX_SEG) { \
|
||||||
from=(segprefix_base+reg_si); \
|
from=(segprefix_base+reg_si); \
|
||||||
SegPrefixReset; \
|
PrefixReset; \
|
||||||
} else { \
|
} else { \
|
||||||
from=SegBase(ds)+reg_si; \
|
from=SegBase(ds)+reg_si; \
|
||||||
}
|
}
|
||||||
@ -185,7 +163,3 @@ static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// if (flags.tf) { \
|
|
||||||
// cpudecoder=CPU_Real_16_Slow_Decode_Special; \
|
|
||||||
// return CBRET_NONE; \
|
|
||||||
// } \
|
|
||||||
|
@ -21,25 +21,44 @@
|
|||||||
typedef EAPoint (*GetEATable[256])(void);
|
typedef EAPoint (*GetEATable[256])(void);
|
||||||
static GetEATable * lookupEATable;
|
static GetEATable * lookupEATable;
|
||||||
|
|
||||||
|
#define PREFIX_NONE 0x0
|
||||||
|
#define PREFIX_SEG 0x1
|
||||||
|
#define PREFIX_ADDR 0x2
|
||||||
|
#define PREFIX_SEG_ADDR 0x3
|
||||||
|
|
||||||
|
|
||||||
|
static Bitu prefixes;
|
||||||
static EAPoint segprefix_base;
|
static EAPoint segprefix_base;
|
||||||
static bool segprefix_on=false;
|
|
||||||
|
/* Gets initialized at the bottem, can't seem to declare forward references */
|
||||||
|
static GetEATable * EAPrefixTable[4];
|
||||||
|
|
||||||
|
|
||||||
#define SegPrefix(blah) \
|
#define SegPrefix(blah) \
|
||||||
segprefix_base=SegBase(blah); \
|
segprefix_base=SegBase(blah); \
|
||||||
segprefix_on=true; \
|
prefixes|=PREFIX_SEG; \
|
||||||
lookupEATable=&GetEA_16_s; \
|
lookupEATable=EAPrefixTable[prefixes]; \
|
||||||
goto restart; \
|
goto restart; \
|
||||||
|
|
||||||
#define SegPrefix_66(blah) \
|
#define SegPrefix_66(blah) \
|
||||||
segprefix_base=SegBase(blah); \
|
segprefix_base=SegBase(blah); \
|
||||||
segprefix_on=true; \
|
prefixes|=PREFIX_SEG; \
|
||||||
lookupEATable=&GetEA_16_s; \
|
lookupEATable=EAPrefixTable[prefixes]; \
|
||||||
goto restart_66; \
|
goto restart_66; \
|
||||||
|
|
||||||
|
|
||||||
|
#define PrefixReset \
|
||||||
|
prefixes=PREFIX_NONE;lookupEATable=EAPrefixTable[PREFIX_NONE];
|
||||||
|
|
||||||
|
#define GetEADirect \
|
||||||
|
EAPoint eaa;switch (prefixes) { \
|
||||||
|
case PREFIX_NONE:eaa=SegBase(ds)+Fetchw();break; \
|
||||||
|
case PREFIX_SEG:eaa=segprefix_base+Fetchw();PrefixReset;break; \
|
||||||
|
case PREFIX_ADDR:eaa=SegBase(ds)+Fetchd();PrefixReset;break; \
|
||||||
|
case PREFIX_SEG_ADDR:eaa=segprefix_base+Fetchd();PrefixReset;break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define SegPrefixReset \
|
|
||||||
segprefix_on=false;lookupEATable=&GetEA_16_n;
|
|
||||||
|
|
||||||
|
|
||||||
/* The MOD/RM Decoder for EA for this decoder's addressing modes */
|
/* The MOD/RM Decoder for EA for this decoder's addressing modes */
|
||||||
@ -106,34 +125,34 @@ static GetEATable GetEA_16_n={
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define prefixed(val) EAPoint ret=segprefix_base+val;SegPrefixReset;return ret;
|
#define segprefixed(val) EAPoint ret=segprefix_base+val;PrefixReset;return ret;
|
||||||
|
|
||||||
static EAPoint EA_16_00_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) }
|
static EAPoint EA_16_00_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) }
|
||||||
static EAPoint EA_16_01_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) }
|
static EAPoint EA_16_01_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) }
|
||||||
static EAPoint EA_16_02_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si)) }
|
static EAPoint EA_16_02_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si)) }
|
||||||
static EAPoint EA_16_03_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di)) }
|
static EAPoint EA_16_03_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di)) }
|
||||||
static EAPoint EA_16_04_s(void) { prefixed((Bit16u)(reg_si)) }
|
static EAPoint EA_16_04_s(void) { segprefixed((Bit16u)(reg_si)) }
|
||||||
static EAPoint EA_16_05_s(void) { prefixed((Bit16u)(reg_di)) }
|
static EAPoint EA_16_05_s(void) { segprefixed((Bit16u)(reg_di)) }
|
||||||
static EAPoint EA_16_06_s(void) { prefixed((Bit16u)(Fetchw())) }
|
static EAPoint EA_16_06_s(void) { segprefixed((Bit16u)(Fetchw())) }
|
||||||
static EAPoint EA_16_07_s(void) { prefixed((Bit16u)(reg_bx)) }
|
static EAPoint EA_16_07_s(void) { segprefixed((Bit16u)(reg_bx)) }
|
||||||
|
|
||||||
static EAPoint EA_16_40_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs())) }
|
static EAPoint EA_16_40_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs())) }
|
||||||
static EAPoint EA_16_41_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs())) }
|
static EAPoint EA_16_41_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs())) }
|
||||||
static EAPoint EA_16_42_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs())) }
|
static EAPoint EA_16_42_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs())) }
|
||||||
static EAPoint EA_16_43_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs())) }
|
static EAPoint EA_16_43_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs())) }
|
||||||
static EAPoint EA_16_44_s(void) { prefixed((Bit16u)(reg_si+Fetchbs())) }
|
static EAPoint EA_16_44_s(void) { segprefixed((Bit16u)(reg_si+Fetchbs())) }
|
||||||
static EAPoint EA_16_45_s(void) { prefixed((Bit16u)(reg_di+Fetchbs())) }
|
static EAPoint EA_16_45_s(void) { segprefixed((Bit16u)(reg_di+Fetchbs())) }
|
||||||
static EAPoint EA_16_46_s(void) { prefixed((Bit16u)(reg_bp+Fetchbs())) }
|
static EAPoint EA_16_46_s(void) { segprefixed((Bit16u)(reg_bp+Fetchbs())) }
|
||||||
static EAPoint EA_16_47_s(void) { prefixed((Bit16u)(reg_bx+Fetchbs())) }
|
static EAPoint EA_16_47_s(void) { segprefixed((Bit16u)(reg_bx+Fetchbs())) }
|
||||||
|
|
||||||
static EAPoint EA_16_80_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws())) }
|
static EAPoint EA_16_80_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws())) }
|
||||||
static EAPoint EA_16_81_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws())) }
|
static EAPoint EA_16_81_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws())) }
|
||||||
static EAPoint EA_16_82_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws())) }
|
static EAPoint EA_16_82_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws())) }
|
||||||
static EAPoint EA_16_83_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws())) }
|
static EAPoint EA_16_83_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws())) }
|
||||||
static EAPoint EA_16_84_s(void) { prefixed((Bit16u)(reg_si+Fetchws())) }
|
static EAPoint EA_16_84_s(void) { segprefixed((Bit16u)(reg_si+Fetchws())) }
|
||||||
static EAPoint EA_16_85_s(void) { prefixed((Bit16u)(reg_di+Fetchws())) }
|
static EAPoint EA_16_85_s(void) { segprefixed((Bit16u)(reg_di+Fetchws())) }
|
||||||
static EAPoint EA_16_86_s(void) { prefixed((Bit16u)(reg_bp+Fetchws())) }
|
static EAPoint EA_16_86_s(void) { segprefixed((Bit16u)(reg_bp+Fetchws())) }
|
||||||
static EAPoint EA_16_87_s(void) { prefixed((Bit16u)(reg_bx+Fetchws())) }
|
static EAPoint EA_16_87_s(void) { segprefixed((Bit16u)(reg_bx+Fetchws())) }
|
||||||
|
|
||||||
static GetEATable GetEA_16_s={
|
static GetEATable GetEA_16_s={
|
||||||
/* 00 */
|
/* 00 */
|
||||||
@ -281,3 +300,117 @@ static GetEATable GetEA_32_n={
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
INLINE EAPoint Sib_s(Bitu mode) {
|
||||||
|
Bit8u sib=Fetchb();
|
||||||
|
EAPoint base;
|
||||||
|
switch (sib&7) {
|
||||||
|
case 0: /* EAX Base */
|
||||||
|
base=segprefix_base+reg_eax;break;
|
||||||
|
case 1: /* ECX Base */
|
||||||
|
base=segprefix_base+reg_ecx;break;
|
||||||
|
case 2: /* EDX Base */
|
||||||
|
base=segprefix_base+reg_edx;break;
|
||||||
|
case 3: /* EBX Base */
|
||||||
|
base=segprefix_base+reg_ebx;break;
|
||||||
|
case 4: /* ESP Base */
|
||||||
|
base=segprefix_base+reg_esp;break;
|
||||||
|
case 5: /* #1 Base */
|
||||||
|
if (!mode) {
|
||||||
|
base=segprefix_base+Fetchd();break;
|
||||||
|
} else {
|
||||||
|
base=segprefix_base+reg_ebp;break;
|
||||||
|
}
|
||||||
|
case 6: /* ESI Base */
|
||||||
|
base=segprefix_base+reg_esi;break;
|
||||||
|
case 7: /* EDI Base */
|
||||||
|
base=segprefix_base+reg_edi;break;
|
||||||
|
}
|
||||||
|
Bitu shift=sib >> 6;
|
||||||
|
switch ((sib >>3) &7) {
|
||||||
|
case 0: /* EAX Index */
|
||||||
|
base+=(Bit32s)reg_eax<<shift;break;
|
||||||
|
case 1: /* ECX Index */
|
||||||
|
base+=(Bit32s)reg_ecx<<shift;break;
|
||||||
|
case 2: /* EDX Index */
|
||||||
|
base+=(Bit32s)reg_edx<<shift;break;
|
||||||
|
case 3: /* EBX Index */
|
||||||
|
base+=(Bit32s)reg_ebx<<shift;break;
|
||||||
|
case 4: /* None */
|
||||||
|
break;
|
||||||
|
case 5: /* EBP Index */
|
||||||
|
base+=(Bit32s)reg_ebp<<shift;break;
|
||||||
|
case 6: /* ESI Index */
|
||||||
|
base+=(Bit32s)reg_esi<<shift;break;
|
||||||
|
case 7: /* EDI Index */
|
||||||
|
base+=(Bit32s)reg_edi<<shift;break;
|
||||||
|
};
|
||||||
|
PrefixReset;
|
||||||
|
return base;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define segprefixed_32(val) EAPoint ret=segprefix_base+(Bit32u)(val);PrefixReset;return ret;
|
||||||
|
|
||||||
|
static EAPoint EA_32_00_s(void) { segprefixed_32(reg_eax); }
|
||||||
|
static EAPoint EA_32_01_s(void) { segprefixed_32(reg_ecx); }
|
||||||
|
static EAPoint EA_32_02_s(void) { segprefixed_32(reg_edx); }
|
||||||
|
static EAPoint EA_32_03_s(void) { segprefixed_32(reg_ebx); }
|
||||||
|
static EAPoint EA_32_04_s(void) { return Sib_s(0);}
|
||||||
|
static EAPoint EA_32_05_s(void) { segprefixed_32(Fetchd()); }
|
||||||
|
static EAPoint EA_32_06_s(void) { segprefixed_32(reg_esi); }
|
||||||
|
static EAPoint EA_32_07_s(void) { segprefixed_32(reg_edi); }
|
||||||
|
|
||||||
|
static EAPoint EA_32_40_s(void) { segprefixed_32(reg_eax+Fetchbs()); }
|
||||||
|
static EAPoint EA_32_41_s(void) { segprefixed_32(reg_ecx+Fetchbs()); }
|
||||||
|
static EAPoint EA_32_42_s(void) { segprefixed_32(reg_edx+Fetchbs()); }
|
||||||
|
static EAPoint EA_32_43_s(void) { segprefixed_32(reg_ebx+Fetchbs()); }
|
||||||
|
static EAPoint EA_32_44_s(void) { return Sib(1)+Fetchbs();}
|
||||||
|
static EAPoint EA_32_45_s(void) { segprefixed_32(reg_ebp+Fetchbs()); }
|
||||||
|
static EAPoint EA_32_46_s(void) { segprefixed_32(reg_esi+Fetchbs()); }
|
||||||
|
static EAPoint EA_32_47_s(void) { segprefixed_32(reg_edi+Fetchbs()); }
|
||||||
|
|
||||||
|
static EAPoint EA_32_80_s(void) { segprefixed_32(reg_eax+Fetchds()); }
|
||||||
|
static EAPoint EA_32_81_s(void) { segprefixed_32(reg_ecx+Fetchds()); }
|
||||||
|
static EAPoint EA_32_82_s(void) { segprefixed_32(reg_edx+Fetchds()); }
|
||||||
|
static EAPoint EA_32_83_s(void) { segprefixed_32(reg_ebx+Fetchds()); }
|
||||||
|
static EAPoint EA_32_84_s(void) { return Sib(2)+Fetchds();}
|
||||||
|
static EAPoint EA_32_85_s(void) { segprefixed_32(reg_ebp+Fetchds()); }
|
||||||
|
static EAPoint EA_32_86_s(void) { segprefixed_32(reg_esi+Fetchds()); }
|
||||||
|
static EAPoint EA_32_87_s(void) { segprefixed_32(reg_edi+Fetchds()); }
|
||||||
|
|
||||||
|
|
||||||
|
static GetEATable GetEA_32_s={
|
||||||
|
/* 00 */
|
||||||
|
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||||
|
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||||
|
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||||
|
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||||
|
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||||
|
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||||
|
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||||
|
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||||
|
/* 01 */
|
||||||
|
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||||
|
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||||
|
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||||
|
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||||
|
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||||
|
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||||
|
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||||
|
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||||
|
/* 10 */
|
||||||
|
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||||
|
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||||
|
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||||
|
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||||
|
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||||
|
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||||
|
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||||
|
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||||
|
/* 11 These are illegal so make em 0 */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ void Interrupt(Bit8u num) {
|
|||||||
case 0xcd:
|
case 0xcd:
|
||||||
E_Exit("Call to interrupt 0xCD this is BAD");
|
E_Exit("Call to interrupt 0xCD this is BAD");
|
||||||
case 0x03:
|
case 0x03:
|
||||||
#ifdef C_DEBUG
|
#if C_DEBUG
|
||||||
if (DEBUG_BreakPoint()) return;
|
if (DEBUG_BreakPoint()) return;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@ -117,15 +117,15 @@ void Interrupt(Bit8u num) {
|
|||||||
flags.tf=false;
|
flags.tf=false;
|
||||||
/* Save everything on a 16-bit stack */
|
/* Save everything on a 16-bit stack */
|
||||||
reg_sp-=2;
|
reg_sp-=2;
|
||||||
mem_writew(Segs[ss].phys+reg_sp,pflags);
|
mem_writew(SegPhys(ss)+reg_sp,pflags);
|
||||||
reg_sp-=2;
|
reg_sp-=2;
|
||||||
mem_writew(Segs[ss].phys+reg_sp,Segs[cs].value);
|
mem_writew(SegPhys(ss)+reg_sp,SegValue(cs));
|
||||||
reg_sp-=2;
|
reg_sp-=2;
|
||||||
mem_writew(Segs[ss].phys+reg_sp,reg_ip);
|
mem_writew(SegPhys(ss)+reg_sp,reg_ip);
|
||||||
/* Get the new CS:IP from vector table */
|
/* Get the new CS:IP from vector table */
|
||||||
Bit16u newip=mem_readw(num << 2);
|
Bit16u newip=mem_readw(num << 2);
|
||||||
Bit16u newcs=mem_readw((num <<2)+2);
|
Bit16u newcs=mem_readw((num <<2)+2);
|
||||||
SetSegment_16(cs,newcs);
|
SegSet16(cs,newcs);
|
||||||
reg_ip=newip;
|
reg_ip=newip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,15 +136,6 @@ void SetCPU16bit()
|
|||||||
CPU_Real_16_Slow_Start();
|
CPU_Real_16_Slow_Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSegment_16(Bit32u seg,Bit16u val) {
|
|
||||||
Segs[seg].value=val;
|
|
||||||
Bit32u off=(val << 4);
|
|
||||||
Segs[seg].host=memory+off;
|
|
||||||
Segs[seg].phys=off;
|
|
||||||
//TODO Maybe use this feature one day :)
|
|
||||||
// Segs[seg].special=MEMORY_TestSpecial(off);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void CPU_Init(void) {
|
void CPU_Init(void) {
|
||||||
reg_eax=0;
|
reg_eax=0;
|
||||||
@ -156,12 +147,12 @@ void CPU_Init(void) {
|
|||||||
reg_ebp=0;
|
reg_ebp=0;
|
||||||
reg_esp=0;
|
reg_esp=0;
|
||||||
|
|
||||||
SetSegment_16(cs,0);
|
SegSet16(cs,0);
|
||||||
SetSegment_16(ds,0);
|
SegSet16(ds,0);
|
||||||
SetSegment_16(es,0);
|
SegSet16(es,0);
|
||||||
SetSegment_16(fs,0);
|
SegSet16(fs,0);
|
||||||
SetSegment_16(gs,0);
|
SegSet16(gs,0);
|
||||||
SetSegment_16(ss,0);
|
SegSet16(ss,0);
|
||||||
|
|
||||||
reg_eip=0;
|
reg_eip=0;
|
||||||
flags.type=t_UNKNOWN;
|
flags.type=t_UNKNOWN;
|
||||||
|
@ -41,6 +41,9 @@ bool get_CF(void) {
|
|||||||
case t_DECw:
|
case t_DECw:
|
||||||
case t_DECd:
|
case t_DECd:
|
||||||
case t_MUL:
|
case t_MUL:
|
||||||
|
case t_RCLb:
|
||||||
|
case t_RCLw:
|
||||||
|
case t_RCLd:
|
||||||
return flags.cf;
|
return flags.cf;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -72,34 +75,32 @@ bool get_CF(void) {
|
|||||||
case t_CMPd:
|
case t_CMPd:
|
||||||
return (flags.var1.d<flags.var2.d);
|
return (flags.var1.d<flags.var2.d);
|
||||||
case t_SHLb:
|
case t_SHLb:
|
||||||
if (flags.var2.b>=8) return false;
|
if (flags.var2.b>8) return false;
|
||||||
else return (flags.var1.b >> (8-flags.var2.b)) & 1;
|
else return (flags.var1.b >> (8-flags.var2.b)) & 1;
|
||||||
case t_SHLw:
|
case t_SHLw:
|
||||||
if (flags.var2.b>=16) return false;
|
if (flags.var2.b>16) return false;
|
||||||
else return (flags.var1.w >> (16-flags.var2.b)) & 1;
|
else return (flags.var1.w >> (16-flags.var2.b)) & 1;
|
||||||
case t_SHLd:
|
case t_SHLd:
|
||||||
return (flags.var1.d >> (32 - flags.var2.b)) & 0x01;
|
|
||||||
case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */
|
case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */
|
||||||
return (flags.var1.d >> (32 - flags.var2.b)) & 0x01;
|
|
||||||
case t_DSHLd:
|
case t_DSHLd:
|
||||||
return (flags.var1.d >> (32 - flags.var2.b)) & 0x01;
|
return (flags.var1.d >> (32 - flags.var2.b)) & 1;
|
||||||
|
case t_RCRb:
|
||||||
case t_SHRb:
|
case t_SHRb:
|
||||||
return (flags.var1.b >> (flags.var2.b - 1)) & 0x01;
|
return (flags.var1.b >> (flags.var2.b - 1)) & 1;
|
||||||
|
case t_RCRw:
|
||||||
case t_SHRw:
|
case t_SHRw:
|
||||||
return (flags.var1.w >> (flags.var2.b - 1)) & 0x01;
|
return (flags.var1.w >> (flags.var2.b - 1)) & 1;
|
||||||
|
case t_RCRd:
|
||||||
case t_SHRd:
|
case t_SHRd:
|
||||||
return (flags.var1.d >> (flags.var2.b - 1)) & 0x01;
|
|
||||||
case t_SARb:
|
|
||||||
return (flags.var1.b >> (flags.var2.b - 1)) & 0x01;
|
|
||||||
case t_SARw:
|
|
||||||
return (flags.var1.w >> (flags.var2.b - 1)) & 0x01;
|
|
||||||
case t_SARd:
|
|
||||||
return (flags.var1.d >> (flags.var2.b - 1)) & 0x01;
|
|
||||||
case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */
|
case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */
|
||||||
return (flags.var1.d >> (flags.var2.b - 1)) & 0x01;
|
|
||||||
case t_DSHRd:
|
case t_DSHRd:
|
||||||
return (flags.var1.d >> (flags.var2.b - 1)) & 0x01;
|
return (flags.var1.d >> (flags.var2.b - 1)) & 1;
|
||||||
|
case t_SARb:
|
||||||
|
return (((Bit8s) flags.var1.b) >> (flags.var2.b - 1)) & 1;
|
||||||
|
case t_SARw:
|
||||||
|
return (((Bit16s) flags.var1.w) >> (flags.var2.b - 1)) & 1;
|
||||||
|
case t_SARd:
|
||||||
|
return (((Bit32s) flags.var1.d) >> (flags.var2.b - 1)) & 1;
|
||||||
case t_NEGb:
|
case t_NEGb:
|
||||||
return (flags.var1.b!=0);
|
return (flags.var1.b!=0);
|
||||||
case t_NEGw:
|
case t_NEGw:
|
||||||
@ -107,29 +108,17 @@ bool get_CF(void) {
|
|||||||
case t_NEGd:
|
case t_NEGd:
|
||||||
return (flags.var1.d!=0);
|
return (flags.var1.d!=0);
|
||||||
case t_ROLb:
|
case t_ROLb:
|
||||||
return (flags.result.b & 1)>0;
|
return flags.result.b & 1;
|
||||||
case t_ROLw:
|
case t_ROLw:
|
||||||
return (flags.result.w & 1)>0;
|
return flags.result.w & 1;
|
||||||
case t_ROLd:
|
case t_ROLd:
|
||||||
return (flags.result.d & 1)>0;
|
return flags.result.d & 1;
|
||||||
case t_RORb:
|
case t_RORb:
|
||||||
return (flags.result.b & 0x80)>0;
|
return (flags.result.b & 0x80)>0;
|
||||||
case t_RORw:
|
case t_RORw:
|
||||||
return (flags.result.w & 0x8000)>0;
|
return (flags.result.w & 0x8000)>0;
|
||||||
case t_RORd:
|
case t_RORd:
|
||||||
return (flags.result.d & 0x80000000)>0;
|
return (flags.result.d & 0x80000000)>0;
|
||||||
case t_RCLb:
|
|
||||||
return ((flags.var1.b >> (8-flags.var2.b))&1)>0;
|
|
||||||
case t_RCLw:
|
|
||||||
return ((flags.var1.w >> (16-flags.var2.b))&1)>0;
|
|
||||||
case t_RCLd:
|
|
||||||
return ((flags.var1.d >> (32-flags.var2.b))&1)>0;
|
|
||||||
case t_RCRb:
|
|
||||||
return ((flags.var1.b >> (flags.var2.b-1))&1)>0;
|
|
||||||
case t_RCRw:
|
|
||||||
return ((flags.var1.w >> (flags.var2.b-1))&1)>0;
|
|
||||||
case t_RCRd:
|
|
||||||
return ((flags.var1.d >> (flags.var2.b-1))&1)>0;
|
|
||||||
case t_ORb:
|
case t_ORb:
|
||||||
case t_ORw:
|
case t_ORw:
|
||||||
case t_ORd:
|
case t_ORd:
|
||||||
@ -427,6 +416,9 @@ again:
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case t_UNKNOWN:
|
case t_UNKNOWN:
|
||||||
case t_MUL:
|
case t_MUL:
|
||||||
|
case t_RCLb:
|
||||||
|
case t_RCLw:
|
||||||
|
case t_RCLd:
|
||||||
return flags.of;
|
return flags.of;
|
||||||
case t_CF:
|
case t_CF:
|
||||||
type=flags.prev_type;
|
type=flags.prev_type;
|
||||||
@ -448,9 +440,9 @@ again:
|
|||||||
case t_ADDd:
|
case t_ADDd:
|
||||||
case t_ADCd:
|
case t_ADCd:
|
||||||
//TODO fix dword Overflow
|
//TODO fix dword Overflow
|
||||||
var1d31 = flags.var1.d & 0x8000;
|
var1d31 = flags.var1.d & 0x80000000;
|
||||||
var2d31 = flags.var2.d & 0x8000;
|
var2d31 = flags.var2.d & 0x80000000;
|
||||||
resultd31 = flags.result.d & 0x8000;
|
resultd31 = flags.result.d & 0x80000000;
|
||||||
return (var1d31 == var2d31) && (resultd31 ^ var2d31);
|
return (var1d31 == var2d31) && (resultd31 ^ var2d31);
|
||||||
case t_SBBb:
|
case t_SBBb:
|
||||||
case t_SUBb:
|
case t_SUBb:
|
||||||
@ -471,10 +463,10 @@ again:
|
|||||||
case t_SBBd:
|
case t_SBBd:
|
||||||
case t_SUBd:
|
case t_SUBd:
|
||||||
case t_CMPd:
|
case t_CMPd:
|
||||||
var1d31 = flags.var1.d & 0x8000;
|
var1d31 = flags.var1.d & 0x80000000;
|
||||||
var2d31 = flags.var2.d & 0x8000;
|
var2d31 = flags.var2.d & 0x80000000;
|
||||||
resultd31 = flags.result.d & 0x8000;
|
resultd31 = flags.result.d & 0x80000000;
|
||||||
return (var1d31 ^ var2d31) && (var1d31 ^ resultd31);
|
return (var1d31 ^ var2d31) && (var1d31 ^ resultd31);
|
||||||
case t_INCb:
|
case t_INCb:
|
||||||
return (flags.result.b == 0x80);
|
return (flags.result.b == 0x80);
|
||||||
case t_INCw:
|
case t_INCw:
|
||||||
@ -494,39 +486,43 @@ again:
|
|||||||
case t_NEGd:
|
case t_NEGd:
|
||||||
return (flags.var1.d == 0x80000000);
|
return (flags.var1.d == 0x80000000);
|
||||||
case t_ROLb:
|
case t_ROLb:
|
||||||
case t_RORb:
|
return ((flags.result.b & 0x80) ^ (flags.result.b & 1 ? 0x80 : 0)) != 0;
|
||||||
case t_RCLb:
|
|
||||||
case t_RCRb:
|
|
||||||
case t_SHLb:
|
|
||||||
if (flags.var2.b==1) return ((flags.var1.b ^ flags.result.b) & 0x80) >0;
|
|
||||||
break;
|
|
||||||
case t_ROLw:
|
case t_ROLw:
|
||||||
case t_RORw:
|
return ((flags.result.w & 0x8000) ^ (flags.result.w & 1 ? 0x8000 : 0)) != 0;
|
||||||
case t_RCLw:
|
|
||||||
case t_RCRw:
|
|
||||||
case t_SHLw:
|
|
||||||
case t_DSHLw: //TODO This is euhm inccorect i think but let's keep it for now
|
|
||||||
if (flags.var2.b==1) return ((flags.var1.w ^ flags.result.w) & 0x8000) >0;
|
|
||||||
break;
|
|
||||||
case t_ROLd:
|
case t_ROLd:
|
||||||
case t_RORd:
|
return ((flags.result.d & 0x80000000) ^ (flags.result.d & 1 ? 0x80000000 : 0)) != 0;
|
||||||
case t_RCLd:
|
case t_SHLb:
|
||||||
case t_RCRd:
|
if (flags.var2.b>9) return false;
|
||||||
|
return ((flags.result.b & 0x80) ^
|
||||||
|
((flags.var1.b << (flags.var2.b - 1)) & 0x80)) != 0;
|
||||||
|
case t_SHLw:
|
||||||
|
if (flags.var2.b>17) return false;
|
||||||
|
return ((flags.result.w & 0x8000) ^
|
||||||
|
((flags.var1.w << (flags.var2.b - 1)) & 0x8000)) != 0;
|
||||||
|
case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */
|
||||||
|
return ((flags.result.w & 0x8000) ^
|
||||||
|
(((flags.var1.d << (flags.var2.b - 1)) >> 16) & 0x8000)) != 0;
|
||||||
case t_SHLd:
|
case t_SHLd:
|
||||||
case t_DSHLd:
|
case t_DSHLd:
|
||||||
if (flags.var2.b==1) return ((flags.var1.d ^ flags.result.d) & 0x80000000) >0;
|
return ((flags.result.d & 0x80000000) ^
|
||||||
break;
|
((flags.var1.d << (flags.var2.b - 1)) & 0x80000000)) != 0;
|
||||||
|
case t_RORb:
|
||||||
|
case t_RCRb:
|
||||||
|
return ((flags.result.b ^ (flags.result.b << 1)) & 0x80) > 0;
|
||||||
|
case t_RORw:
|
||||||
|
case t_RCRw:
|
||||||
|
case t_DSHRw:
|
||||||
|
return ((flags.result.w ^ (flags.result.w << 1)) & 0x8000) > 0;
|
||||||
|
case t_RORd:
|
||||||
|
case t_RCRd:
|
||||||
|
case t_DSHRd:
|
||||||
|
return ((flags.result.d ^ (flags.result.d << 1)) & 0x80000000) > 0;
|
||||||
case t_SHRb:
|
case t_SHRb:
|
||||||
if (flags.var2.b==1) return (flags.var1.b >= 0x80);
|
return (flags.result.b >= 0x40);
|
||||||
break;
|
|
||||||
case t_SHRw:
|
case t_SHRw:
|
||||||
case t_DSHRw: //TODO
|
return (flags.result.w >= 0x4000);
|
||||||
if (flags.var2.b==1) return (flags.var1.w >= 0x8000);
|
|
||||||
break;
|
|
||||||
case t_SHRd:
|
case t_SHRd:
|
||||||
case t_DSHRd: //TODO
|
return (flags.result.d >= 0x40000000);
|
||||||
if (flags.var2.b==1) return (flags.var1.d >= 0x80000000);
|
|
||||||
break;
|
|
||||||
case t_SARb:
|
case t_SARb:
|
||||||
case t_SARw:
|
case t_SARw:
|
||||||
case t_SARd:
|
case t_SARd:
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
@ -24,11 +25,12 @@
|
|||||||
#include "pic.h"
|
#include "pic.h"
|
||||||
#include "fpu.h"
|
#include "fpu.h"
|
||||||
|
|
||||||
|
#if C_DEBUG
|
||||||
|
#include "debug.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef PhysOff EAPoint;
|
typedef PhysPt EAPoint;
|
||||||
|
#define SegBase(c) SegPhys(c)
|
||||||
#define SegBase(seg) Segs[seg].phys
|
|
||||||
|
|
||||||
#define LoadMb(off) mem_readb(off)
|
#define LoadMb(off) mem_readb(off)
|
||||||
#define LoadMw(off) mem_readw(off)
|
#define LoadMw(off) mem_readw(off)
|
||||||
#define LoadMd(off) mem_readd(off)
|
#define LoadMd(off) mem_readd(off)
|
||||||
@ -41,27 +43,6 @@ typedef PhysOff EAPoint;
|
|||||||
#define SaveMw(off,val) mem_writew(off,val)
|
#define SaveMw(off,val) mem_writew(off,val)
|
||||||
#define SaveMd(off,val) mem_writed(off,val)
|
#define SaveMd(off,val) mem_writed(off,val)
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
typedef HostOff EAPoint;
|
|
||||||
|
|
||||||
#define SegBase(seg) Segs[seg].host
|
|
||||||
|
|
||||||
#define LoadMb(off) readb(off)
|
|
||||||
#define LoadMw(off) readw(off)
|
|
||||||
#define LoadMd(off) readd(off)
|
|
||||||
|
|
||||||
#define LoadMbs(off) (Bit8s)(LoadMb(off))
|
|
||||||
#define LoadMws(off) (Bit16s)(LoadMw(off))
|
|
||||||
#define LoadMds(off) (Bit32s)(LoadMd(off))
|
|
||||||
|
|
||||||
#define SaveMb(off,val) writeb(off,val)
|
|
||||||
#define SaveMw(off,val) writew(off,val)
|
|
||||||
#define SaveMd(off,val) writed(off,val)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#define LoadRb(reg) reg
|
#define LoadRb(reg) reg
|
||||||
#define LoadRw(reg) reg
|
#define LoadRw(reg) reg
|
||||||
#define LoadRd(reg) reg
|
#define LoadRd(reg) reg
|
||||||
@ -72,17 +53,18 @@ typedef HostOff EAPoint;
|
|||||||
|
|
||||||
extern Bitu cycle_count;
|
extern Bitu cycle_count;
|
||||||
|
|
||||||
#define CPU_386
|
/* Enable parts of the cpu emulation */
|
||||||
//TODO Change name
|
#define CPU_386 //Enable 386 instructions
|
||||||
#define FULLFLAGS
|
#if C_FPU
|
||||||
|
#define CPU_FPU //Enable FPU escape instructions
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "core_16/support.h"
|
#include "core_16/support.h"
|
||||||
static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count);
|
static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count);
|
||||||
static Bitu CPU_Real_16_Slow_Decode(Bitu count) {
|
static Bitu CPU_Real_16_Slow_Decode(Bitu count) {
|
||||||
#include "core_16/start.h"
|
#include "core_16/start.h"
|
||||||
while (count) {
|
while (count) {
|
||||||
#ifdef C_DEBUG
|
#if C_DEBUG
|
||||||
cycle_count++;
|
cycle_count++;
|
||||||
#endif
|
#endif
|
||||||
count--;
|
count--;
|
||||||
@ -112,9 +94,10 @@ static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count) {
|
|||||||
|
|
||||||
void CPU_Real_16_Slow_Start(void) {
|
void CPU_Real_16_Slow_Start(void) {
|
||||||
|
|
||||||
lookupEATable=&GetEA_16_n;
|
|
||||||
segprefix_base=0;
|
|
||||||
segprefix_on=false;
|
|
||||||
cpudecoder=&CPU_Real_16_Slow_Decode;
|
cpudecoder=&CPU_Real_16_Slow_Decode;
|
||||||
|
EAPrefixTable[0]=&GetEA_16_n;
|
||||||
|
EAPrefixTable[1]=&GetEA_16_s;
|
||||||
|
EAPrefixTable[2]=&GetEA_32_n;
|
||||||
|
EAPrefixTable[3]=&GetEA_32_s;
|
||||||
|
PrefixReset;
|
||||||
};
|
};
|
||||||
|
@ -18,9 +18,10 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#ifdef C_DEBUG
|
#if C_DEBUG
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "video.h"
|
#include "video.h"
|
||||||
@ -35,22 +36,20 @@
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
void WIN32_Console();
|
void WIN32_Console();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
|
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
|
||||||
} oldregs;
|
} oldregs;
|
||||||
|
|
||||||
|
static void DrawCode(void);
|
||||||
|
|
||||||
static Segment oldsegs[6];
|
static Segment oldsegs[6];
|
||||||
static Flag_Info oldflags;
|
static Flag_Info oldflags;
|
||||||
DBGBlock dbg;
|
DBGBlock dbg;
|
||||||
|
|
||||||
static char input_line[256];
|
static char input_line[256];
|
||||||
static Bitu input_count;
|
static Bitu input_count;
|
||||||
Bitu cycle_count;
|
Bitu cycle_count;
|
||||||
|
|
||||||
static bool debugging;
|
static bool debugging;
|
||||||
|
|
||||||
static void SetColor(bool test) {
|
static void SetColor(bool test) {
|
||||||
if (test) {
|
if (test) {
|
||||||
if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));}
|
if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));}
|
||||||
@ -58,22 +57,228 @@ static void SetColor(bool test) {
|
|||||||
if (has_colors()) { wattrset(dbg.win_reg,0);}
|
if (has_colors()) { wattrset(dbg.win_reg,0);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#define MAX_BREAKPOINT 10
|
|
||||||
|
|
||||||
enum { BKPNT_REALMODE,BKPNT_PHYSICAL };
|
struct SCodeViewData {
|
||||||
|
int cursorPos;
|
||||||
|
Bit16u firstInstSize;
|
||||||
|
Bit16u useCS;
|
||||||
|
Bit32u useEIPlast, useEIPmid;
|
||||||
|
Bit32u useEIP;
|
||||||
|
Bit16u cursorSeg;
|
||||||
|
Bit32u cursorOfs;
|
||||||
|
bool inputMode;
|
||||||
|
char inputStr[255];
|
||||||
|
|
||||||
struct BreakPoint {
|
} codeViewData;
|
||||||
PhysOff location;
|
|
||||||
Bit8u olddata;
|
static Bit16u dataSeg,dataOfs;
|
||||||
Bit16u seg;
|
|
||||||
Bit16u off_16;
|
/********************/
|
||||||
Bit32u off_32;
|
/* Breakpoint stuff */
|
||||||
Bit8u type;
|
/********************/
|
||||||
bool enabled;
|
|
||||||
bool active;
|
enum { BKPNT_REALMODE, BKPNT_PHYSICAL, BKPNT_INTERRUPT };
|
||||||
|
|
||||||
|
#define BPINT_ALL 0x100
|
||||||
|
|
||||||
|
typedef struct SBreakPoint {
|
||||||
|
PhysPt location;
|
||||||
|
Bit8u olddata;
|
||||||
|
Bit8u type;
|
||||||
|
Bit16u ahValue;
|
||||||
|
Bit16u segment;
|
||||||
|
Bit32u offset;
|
||||||
|
bool once;
|
||||||
|
bool enabled;
|
||||||
|
bool active;
|
||||||
|
} TBreakpoint;
|
||||||
|
|
||||||
|
static std::list<TBreakpoint> BPoints;
|
||||||
|
|
||||||
|
static bool IsBreakpoint(PhysPt off)
|
||||||
|
{
|
||||||
|
// iterate list and remove TBreakpoint
|
||||||
|
std::list<TBreakpoint>::iterator i;
|
||||||
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
||||||
|
if (((*i).type==BKPNT_PHYSICAL) && ((*i).location==off)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
BreakPoint bpoints[MAX_BREAKPOINT];
|
/* This clears all breakpoints by replacing their 0xcc by the original byte */
|
||||||
|
static void ClearBreakpoints(void)
|
||||||
|
{
|
||||||
|
// iterate list and place 0xCC
|
||||||
|
std::list<TBreakpoint>::iterator i;
|
||||||
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
||||||
|
if (((*i).type==BKPNT_PHYSICAL) && (*i).active) {
|
||||||
|
if (mem_readb((*i).location)==0xCC) mem_writeb((*i).location,(*i).olddata);
|
||||||
|
(*i).active = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DeleteBreakpoint(PhysPt off)
|
||||||
|
{
|
||||||
|
// iterate list and place 0xCC
|
||||||
|
std::list<TBreakpoint>::iterator i;
|
||||||
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
||||||
|
if (((*i).type==BKPNT_PHYSICAL) && (off==(*i).location)) {
|
||||||
|
if ((*i).active && (mem_readb((*i).location)==0xCC)) mem_writeb((*i).location,(*i).olddata);
|
||||||
|
(BPoints.erase)(i);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetBreakpoints(void)
|
||||||
|
{
|
||||||
|
// iterate list and place 0xCC
|
||||||
|
std::list<TBreakpoint>::iterator i;
|
||||||
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
||||||
|
if (((*i).type==BKPNT_PHYSICAL) && (*i).enabled) {
|
||||||
|
Bit8u data = mem_readb((*i).location);
|
||||||
|
if (data!=0xCC) {
|
||||||
|
(*i).olddata = data;
|
||||||
|
(*i).active = true;
|
||||||
|
mem_writeb((*i).location,0xCC);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddBreakpoint(Bit16u seg, Bit32u ofs, bool once)
|
||||||
|
{
|
||||||
|
TBreakpoint bp;
|
||||||
|
bp.type = BKPNT_PHYSICAL;
|
||||||
|
bp.enabled = true;
|
||||||
|
bp.active = false;
|
||||||
|
bp.location = PhysMake(seg,ofs);
|
||||||
|
bp.segment = seg;
|
||||||
|
bp.offset = ofs;
|
||||||
|
bp.once = once;
|
||||||
|
BPoints.push_front(bp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddIntBreakpoint(Bit8u intNum, Bit16u ah, bool once)
|
||||||
|
{
|
||||||
|
TBreakpoint bp;
|
||||||
|
bp.type = BKPNT_INTERRUPT;
|
||||||
|
bp.olddata = intNum;
|
||||||
|
bp.ahValue = ah;
|
||||||
|
bp.enabled = true;
|
||||||
|
bp.active = true;
|
||||||
|
bp.once = once;
|
||||||
|
BPoints.push_front(bp);
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool RemoveBreakpoint(PhysPt off)
|
||||||
|
{
|
||||||
|
// iterate list and remove TBreakpoint
|
||||||
|
std::list<TBreakpoint>::iterator i;
|
||||||
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
||||||
|
if (((*i).type==BKPNT_PHYSICAL) && ((*i).location==off)) {
|
||||||
|
TBreakpoint* bp = &(*i);
|
||||||
|
if ((*i).active && (mem_readb((*i).location)==0xCC)) mem_writeb((*i).location,(*i).olddata);
|
||||||
|
(*i).active = false;
|
||||||
|
if ((*i).once) (BPoints.erase)(i);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool StepOver()
|
||||||
|
{
|
||||||
|
PhysPt start=Segs[cs].phys+reg_eip;
|
||||||
|
char dline[200];Bitu size;
|
||||||
|
size=DasmI386(dline, start, reg_eip, false);
|
||||||
|
|
||||||
|
if (strstr(dline,"call") || strstr(dline,"int")) {
|
||||||
|
AddBreakpoint (SegValue(cs),reg_eip+size, true);
|
||||||
|
SetBreakpoints();
|
||||||
|
debugging=false;
|
||||||
|
DrawCode();
|
||||||
|
DOSBOX_SetNormalLoop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool DEBUG_BreakPoint(void) {
|
||||||
|
/* First get the phyiscal address and check for a set TBreakpoint */
|
||||||
|
PhysPt where=SegPhys(cs)+reg_eip-1;
|
||||||
|
bool found = false;
|
||||||
|
std::list<TBreakpoint>::iterator i;
|
||||||
|
for(i=BPoints.begin(); i != BPoints.end(); ++i) {
|
||||||
|
if ((*i).active && (*i).enabled) {
|
||||||
|
if ((*i).location==where) {
|
||||||
|
found=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) return false;
|
||||||
|
RemoveBreakpoint(where);
|
||||||
|
ClearBreakpoints();
|
||||||
|
reg_eip -= 1;
|
||||||
|
DEBUG_Enable();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DEBUG_IntBreakpoint(Bit8u intNum)
|
||||||
|
{
|
||||||
|
PhysPt where=SegPhys(cs)+reg_eip-2;
|
||||||
|
bool found=false;
|
||||||
|
std::list<TBreakpoint>::iterator i;
|
||||||
|
for(i=BPoints.begin(); i != BPoints.end(); ++i) {
|
||||||
|
if ( ((*i).type==BKPNT_INTERRUPT) && (*i).enabled) {
|
||||||
|
if (((*i).olddata==intNum) && ( ((*i).ahValue==(Bit16u)reg_ah) || ((*i).ahValue==BPINT_ALL)) ) {
|
||||||
|
if ((*i).active) {
|
||||||
|
found=true;
|
||||||
|
(*i).active=false;
|
||||||
|
//(BPoints.erase)(i);
|
||||||
|
//break;
|
||||||
|
} else {
|
||||||
|
// One step over is ok -> activate for next occurence
|
||||||
|
(*i).active=true;
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) return false;
|
||||||
|
|
||||||
|
// Remove normal breakpoint here, cos otherwise 0xCC wont be removed here
|
||||||
|
RemoveBreakpoint(where);
|
||||||
|
ClearBreakpoints();
|
||||||
|
reg_eip -= 2;
|
||||||
|
DEBUG_Enable();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/********************/
|
||||||
|
/* Draw windows */
|
||||||
|
/********************/
|
||||||
|
|
||||||
|
static void DrawData(void) {
|
||||||
|
|
||||||
|
Bit16u add = dataOfs;
|
||||||
|
/* Data win */
|
||||||
|
for (int y=0; y<8; y++) {
|
||||||
|
// Adress
|
||||||
|
mvwprintw (dbg.win_data,1+y,0,"%04X:%04X ",dataSeg,add);
|
||||||
|
for (int x=0; x<16; x++) {
|
||||||
|
Bit8u ch = real_readb(dataSeg,add);
|
||||||
|
mvwprintw (dbg.win_data,1+y,11+3*x,"%02X",ch);
|
||||||
|
if (ch<32) ch='.';
|
||||||
|
mvwprintw (dbg.win_data,1+y,60+x,"%c",ch);
|
||||||
|
add++;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
wrefresh(dbg.win_data);
|
||||||
|
};
|
||||||
|
|
||||||
static void DrawRegisters(void) {
|
static void DrawRegisters(void) {
|
||||||
/* Main Registers */
|
/* Main Registers */
|
||||||
@ -88,12 +293,12 @@ static void DrawRegisters(void) {
|
|||||||
SetColor(reg_esp!=oldregs.esp);oldregs.esp=reg_esp;mvwprintw (dbg.win_reg,3,18,"%08X",reg_esp);
|
SetColor(reg_esp!=oldregs.esp);oldregs.esp=reg_esp;mvwprintw (dbg.win_reg,3,18,"%08X",reg_esp);
|
||||||
SetColor(reg_eip!=oldregs.eip);oldregs.eip=reg_eip;mvwprintw (dbg.win_reg,1,42,"%08X",reg_eip);
|
SetColor(reg_eip!=oldregs.eip);oldregs.eip=reg_eip;mvwprintw (dbg.win_reg,1,42,"%08X",reg_eip);
|
||||||
|
|
||||||
SetColor(Segs[ds].value!=oldsegs[ds].value);oldsegs[ds].value=Segs[ds].value;mvwprintw (dbg.win_reg,0,31,"%04X",Segs[ds].value);
|
SetColor(SegValue(ds)!=oldsegs[ds].val);oldsegs[ds].val=SegValue(ds);mvwprintw (dbg.win_reg,0,31,"%04X",SegValue(ds));
|
||||||
SetColor(Segs[es].value!=oldsegs[es].value);oldsegs[es].value=Segs[es].value;mvwprintw (dbg.win_reg,0,41,"%04X",Segs[es].value);
|
SetColor(SegValue(es)!=oldsegs[es].val);oldsegs[es].val=SegValue(es);mvwprintw (dbg.win_reg,0,41,"%04X",SegValue(es));
|
||||||
SetColor(Segs[fs].value!=oldsegs[fs].value);oldsegs[fs].value=Segs[fs].value;mvwprintw (dbg.win_reg,0,51,"%04X",Segs[fs].value);
|
SetColor(SegValue(fs)!=oldsegs[fs].val);oldsegs[fs].val=SegValue(fs);mvwprintw (dbg.win_reg,0,51,"%04X",SegValue(fs));
|
||||||
SetColor(Segs[gs].value!=oldsegs[gs].value);oldsegs[gs].value=Segs[gs].value;mvwprintw (dbg.win_reg,0,61,"%04X",Segs[gs].value);
|
SetColor(SegValue(gs)!=oldsegs[gs].val);oldsegs[gs].val=SegValue(gs);mvwprintw (dbg.win_reg,0,61,"%04X",SegValue(gs));
|
||||||
SetColor(Segs[ss].value!=oldsegs[ss].value);oldsegs[ss].value=Segs[ss].value;mvwprintw (dbg.win_reg,0,71,"%04X",Segs[ss].value);
|
SetColor(SegValue(ss)!=oldsegs[ss].val);oldsegs[ss].val=SegValue(ss);mvwprintw (dbg.win_reg,0,71,"%04X",SegValue(ss));
|
||||||
SetColor(Segs[cs].value!=oldsegs[cs].value);oldsegs[cs].value=Segs[cs].value;mvwprintw (dbg.win_reg,1,31,"%04X",Segs[cs].value);
|
SetColor(SegValue(cs)!=oldsegs[cs].val);oldsegs[cs].val=SegValue(cs);mvwprintw (dbg.win_reg,1,31,"%04X",SegValue(cs));
|
||||||
|
|
||||||
/*Individual flags*/
|
/*Individual flags*/
|
||||||
|
|
||||||
@ -114,76 +319,269 @@ static void DrawRegisters(void) {
|
|||||||
wrefresh(dbg.win_reg);
|
wrefresh(dbg.win_reg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void DrawCode(void)
|
||||||
static void DrawCode(void) {
|
{
|
||||||
PhysOff start=Segs[cs].phys+reg_eip;
|
Bit32u disEIP = codeViewData.useEIP;
|
||||||
|
PhysPt start = codeViewData.useCS*16 + codeViewData.useEIP;
|
||||||
char dline[200];Bitu size;Bitu c;
|
char dline[200];Bitu size;Bitu c;
|
||||||
|
|
||||||
for (Bit32u i=0;i<10;i++) {
|
for (Bit32u i=0;i<10;i++) {
|
||||||
// size=DEBUG_Disasm(start,false,dline);
|
if (has_colors()) {
|
||||||
size=DasmI386(dline, start, reg_eip, false);
|
if ((codeViewData.useCS==SegValue(cs)) && (disEIP == reg_eip)) {
|
||||||
mvwprintw(dbg.win_code,i,0,"%02X:%04X ",Segs[cs].value,(start-Segs[cs].phys));
|
wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK));
|
||||||
|
if (codeViewData.cursorPos==-1) {
|
||||||
|
codeViewData.cursorPos = i; // Set Cursor
|
||||||
|
codeViewData.cursorSeg = SegValue(cs);
|
||||||
|
codeViewData.cursorOfs = disEIP;
|
||||||
|
}
|
||||||
|
} else if (i == codeViewData.cursorPos) {
|
||||||
|
wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY));
|
||||||
|
codeViewData.cursorSeg = codeViewData.useCS;
|
||||||
|
codeViewData.cursorOfs = disEIP;
|
||||||
|
} else if (IsBreakpoint(start)) {
|
||||||
|
wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED));
|
||||||
|
} else {
|
||||||
|
wattrset(dbg.win_code,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size=DasmI386(dline, start, disEIP, false);
|
||||||
|
mvwprintw(dbg.win_code,i,0,"%04X:%04X ",codeViewData.useCS,disEIP);
|
||||||
for (c=0;c<size;c++) wprintw(dbg.win_code,"%02X",mem_readb(start+c));
|
for (c=0;c<size;c++) wprintw(dbg.win_code,"%02X",mem_readb(start+c));
|
||||||
for (c=20;c>=size*2;c--) waddch(dbg.win_code,' ');
|
for (c=20;c>=size*2;c--) waddch(dbg.win_code,' ');
|
||||||
waddstr(dbg.win_code,dline);
|
waddstr(dbg.win_code,dline);
|
||||||
for (c=30-strlen(dline);c>0;c--) waddch(dbg.win_code,' ');
|
for (c=30-strlen(dline);c>0;c--) waddch(dbg.win_code,' ');
|
||||||
start+=size;
|
start+=size;
|
||||||
|
disEIP+=size;
|
||||||
|
|
||||||
|
if (i==0) codeViewData.firstInstSize = size;
|
||||||
|
if (i==4) codeViewData.useEIPmid = disEIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codeViewData.useEIPlast = disEIP;
|
||||||
|
|
||||||
|
wattrset(dbg.win_code,0);
|
||||||
|
if (!debugging) {
|
||||||
|
mvwprintw(dbg.win_code,10,0,"(Running)",codeViewData.inputStr);
|
||||||
|
} else if (codeViewData.inputMode) {
|
||||||
|
mvwprintw(dbg.win_code,10,0,"-> %s_ ",codeViewData.inputStr);
|
||||||
|
} else {
|
||||||
|
mvwprintw(dbg.win_code,10,0," ");
|
||||||
|
for (c=0;c<50;c++) waddch(dbg.win_code,' ');
|
||||||
|
};
|
||||||
|
|
||||||
wrefresh(dbg.win_code);
|
wrefresh(dbg.win_code);
|
||||||
}
|
}
|
||||||
/* This clears all breakpoints by replacing their 0xcc by the original byte */
|
|
||||||
static void ClearBreakPoints(void) {
|
static void SetCodeWinStart()
|
||||||
for (Bit32u i=0;i<MAX_BREAKPOINT;i++) {
|
{
|
||||||
if (bpoints[i].active && bpoints[i].enabled) {
|
if ((SegValue(cs)==codeViewData.useCS) && (reg_eip>=codeViewData.useEIP) && (reg_eip<=codeViewData.useEIPlast)) {
|
||||||
mem_writeb(bpoints[i].location,bpoints[i].olddata);
|
// in valid window - scroll ?
|
||||||
}
|
if (reg_eip>=codeViewData.useEIPmid) codeViewData.useEIP += codeViewData.firstInstSize;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// totally out of range.
|
||||||
|
codeViewData.useCS = SegValue(cs);
|
||||||
|
codeViewData.useEIP = reg_eip;
|
||||||
}
|
}
|
||||||
}
|
codeViewData.cursorPos = -1; // Recalc Cursor position
|
||||||
|
};
|
||||||
|
|
||||||
static void SetBreakPoints(void) {
|
/********************/
|
||||||
for (Bit32u i=0;i<MAX_BREAKPOINT;i++) {
|
/* User input */
|
||||||
if (bpoints[i].active && bpoints[i].enabled) {
|
/********************/
|
||||||
bpoints[i].olddata=mem_readb(bpoints[i].location);
|
|
||||||
mem_writeb(bpoints[i].location,0xcc);
|
Bit32u GetHexValue(char* str, char*& hex)
|
||||||
}
|
{
|
||||||
|
Bit32u value = 0;
|
||||||
|
|
||||||
|
hex = str;
|
||||||
|
while (*hex==' ') hex++;
|
||||||
|
if (strstr(hex,"AX")==hex) { hex+=2; return reg_ax; };
|
||||||
|
if (strstr(hex,"BX")==hex) { hex+=2; return reg_bx; };
|
||||||
|
if (strstr(hex,"CX")==hex) { hex+=2; return reg_cx; };
|
||||||
|
if (strstr(hex,"DX")==hex) { hex+=2; return reg_dx; };
|
||||||
|
if (strstr(hex,"SI")==hex) { hex+=2; return reg_si; };
|
||||||
|
if (strstr(hex,"DI")==hex) { hex+=2; return reg_di; };
|
||||||
|
if (strstr(hex,"BP")==hex) { hex+=2; return reg_bp; };
|
||||||
|
if (strstr(hex,"SP")==hex) { hex+=2; return reg_sp; };
|
||||||
|
if (strstr(hex,"IP")==hex) { hex+=2; return reg_ip; };
|
||||||
|
if (strstr(hex,"CS")==hex) { hex+=2; return SegValue(cs); };
|
||||||
|
if (strstr(hex,"DS")==hex) { hex+=2; return SegValue(ds); };
|
||||||
|
if (strstr(hex,"ES")==hex) { hex+=2; return SegValue(es); };
|
||||||
|
if (strstr(hex,"FS")==hex) { hex+=2; return SegValue(fs); };
|
||||||
|
if (strstr(hex,"GS")==hex) { hex+=2; return SegValue(gs); };
|
||||||
|
if (strstr(hex,"SS")==hex) { hex+=2; return SegValue(ss); };
|
||||||
|
if (strstr(hex,"EAX")==hex) { hex+=3; return reg_eax; };
|
||||||
|
if (strstr(hex,"EBX")==hex) { hex+=3; return reg_ebx; };
|
||||||
|
if (strstr(hex,"ECX")==hex) { hex+=3; return reg_ecx; };
|
||||||
|
if (strstr(hex,"EDX")==hex) { hex+=3; return reg_edx; };
|
||||||
|
if (strstr(hex,"ESI")==hex) { hex+=3; return reg_esi; };
|
||||||
|
if (strstr(hex,"EDI")==hex) { hex+=3; return reg_edi; };
|
||||||
|
if (strstr(hex,"EBP")==hex) { hex+=3; return reg_ebp; };
|
||||||
|
if (strstr(hex,"ESP")==hex) { hex+=3; return reg_esp; };
|
||||||
|
if (strstr(hex,"EIP")==hex) { hex+=3; return reg_eip; };
|
||||||
|
|
||||||
|
while (*hex) {
|
||||||
|
if ((*hex>='0') && (*hex<='9')) value = (value<<4)+*hex-'0'; else
|
||||||
|
if ((*hex>='A') && (*hex<='F')) value = (value<<4)+*hex-'A'+10;
|
||||||
|
else break; // No valid char
|
||||||
|
hex++;
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ParseCommand(char* str)
|
||||||
|
{
|
||||||
|
char* found = str;
|
||||||
|
while (*found) *found++=toupper(*found);
|
||||||
|
found = strstr(str,"BP ");
|
||||||
|
if (found) { // Add new breakpoint
|
||||||
|
found+=3;
|
||||||
|
Bit16u seg = GetHexValue(found,found);found++; // skip ":"
|
||||||
|
Bit32u ofs = GetHexValue(found,found);
|
||||||
|
AddBreakpoint(seg,ofs,false);
|
||||||
|
LOG_DEBUG("DEBUG: Set breakpoint at %04X:%04X",seg,ofs);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
found = strstr(str,"BPINT");
|
||||||
|
if (found) { // Add Interrupt Breakpoint
|
||||||
|
found+=5;
|
||||||
|
Bit8u intNr = GetHexValue(found,found); found++;
|
||||||
|
Bit8u valAH = GetHexValue(found,found);
|
||||||
|
if ((valAH==0x00) && (*found=='*')) {
|
||||||
|
AddIntBreakpoint(intNr,BPINT_ALL,false);
|
||||||
|
LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X",intNr);
|
||||||
|
} else {
|
||||||
|
AddIntBreakpoint(intNr,valAH,false);
|
||||||
|
LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
found = strstr(str,"BPLIST");
|
||||||
|
if (found) {
|
||||||
|
wprintw(dbg.win_out,"Breakpoint list:\n");
|
||||||
|
wprintw(dbg.win_out,"-------------------------------------------------------------------------\n");
|
||||||
|
Bit32u nr = 0;
|
||||||
|
// iterate list
|
||||||
|
std::list<TBreakpoint>::iterator i;
|
||||||
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
||||||
|
if ((*i).type==BKPNT_PHYSICAL) {
|
||||||
|
wprintw(dbg.win_out,"%02X. BP %04X:%04X\n",nr,(*i).segment,(*i).offset);
|
||||||
|
nr++;
|
||||||
|
} else if ((*i).type==BKPNT_INTERRUPT) {
|
||||||
|
if ((*i).ahValue==BPINT_ALL) wprintw(dbg.win_out,"%02X. BPINT %02X\n",nr,(*i).olddata);
|
||||||
|
else wprintw(dbg.win_out,"%02X. BPINT %02X AH=%02X\n",nr,(*i).olddata,(*i).ahValue);
|
||||||
|
nr++;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
wrefresh(dbg.win_out);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
found = strstr(str,"BPDEL");
|
||||||
|
if (found) { // Delete Breakpoints
|
||||||
static void AddBreakPoint(PhysOff off) {
|
found+=5;
|
||||||
|
Bit8u bpNr = GetHexValue(found,found);
|
||||||
}
|
if ((bpNr==0x00) && (*found=='*')) { // Delete all
|
||||||
|
(BPoints.clear)();
|
||||||
|
LOG_DEBUG("DEBUG: Breakpoints deleted.");
|
||||||
|
} else {
|
||||||
bool DEBUG_BreakPoint(void) {
|
// delete single breakpoint
|
||||||
/* First get the phyiscal address and check for a set breakpoint */
|
Bit16u nr = 0;
|
||||||
PhysOff where=real_phys(Segs[cs].value,reg_ip-1);
|
std::list<TBreakpoint>::iterator i;
|
||||||
bool found=false;
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
||||||
for (Bit32u i=0;i<MAX_BREAKPOINT;i++) {
|
if ((*i).type==BKPNT_PHYSICAL) {
|
||||||
if (bpoints[i].active && bpoints[i].enabled) {
|
if (nr==bpNr) {
|
||||||
if (bpoints[i].location==where) {
|
DeleteBreakpoint((*i).location);
|
||||||
found=true;
|
LOG_DEBUG("DEBUG: Breakpoint %02X deleted.",nr);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
nr++;
|
||||||
|
} else if ((*i).type==BKPNT_INTERRUPT) {
|
||||||
|
if (nr==bpNr) {
|
||||||
|
(BPoints.erase)(i);
|
||||||
|
LOG_DEBUG("DEBUG: Breakpoint %02X. deleted.",nr);
|
||||||
|
break;;
|
||||||
|
}
|
||||||
|
nr++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
found = strstr(str,"C ");
|
||||||
|
if (found) { // Set code overview
|
||||||
|
found++;
|
||||||
|
Bit16u codeSeg = GetHexValue(found,found); found++;
|
||||||
|
Bit32u codeOfs = GetHexValue(found,found);
|
||||||
|
LOG_DEBUG("DEBUG: Set code overview to %04X:%04X",codeSeg,codeOfs);
|
||||||
|
codeViewData.useCS = codeSeg;
|
||||||
|
codeViewData.useEIP = codeOfs;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
found = strstr(str,"D ");
|
||||||
|
if (found) { // Set data overview
|
||||||
|
found++;
|
||||||
|
dataSeg = GetHexValue(found,found); found++;
|
||||||
|
dataOfs = GetHexValue(found,found);
|
||||||
|
LOG_DEBUG("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((*str=='H') || (*str=='?')) {
|
||||||
|
wprintw(dbg.win_out,"Debugger keys:\n");
|
||||||
|
wprintw(dbg.win_out,"--------------------------------------------------------------------------\n");
|
||||||
|
wprintw(dbg.win_out,"F5 - Run\n");
|
||||||
|
wprintw(dbg.win_out,"F9 - Set/Remove breakpoint\n");
|
||||||
|
wprintw(dbg.win_out,"F10/F11 - Step over / trace into instruction\n");
|
||||||
|
wprintw(dbg.win_out,"Up/Down - Move code view cursor\n");
|
||||||
|
wprintw(dbg.win_out,"Return - Enable command line input\n");
|
||||||
|
wprintw(dbg.win_out,"D/E/S/X/B - Set data view to DS:SI/ES:DI/SS:SP/DS:DX/ES:BX\n");
|
||||||
|
wprintw(dbg.win_out,"R/F - Scroll data view\n");
|
||||||
|
wprintw(dbg.win_out,"\n");
|
||||||
|
wprintw(dbg.win_out,"Debugger commands (enter all values in hex or as register):\n");
|
||||||
|
wprintw(dbg.win_out,"--------------------------------------------------------------------------\n");
|
||||||
|
wprintw(dbg.win_out,"BP [segment]:[offset] - Set breakpoint\n");
|
||||||
|
wprintw(dbg.win_out,"BPINT [intNr] * - Set interrupt breakpoint\n");
|
||||||
|
wprintw(dbg.win_out,"BPINT [intNr] [ah] - Set interrupt breakpoint with ah\n");
|
||||||
|
wprintw(dbg.win_out,"BPLIST - List breakpoints\n");
|
||||||
|
wprintw(dbg.win_out,"BPDEL [bpNr] / * - Delete breakpoint nr / all\n");
|
||||||
|
wprintw(dbg.win_out,"C / D [segment]:[offset] - Set code / data view address\n");
|
||||||
|
wprintw(dbg.win_out,"H - Help\n");
|
||||||
|
wrefresh(dbg.win_out);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (!found) return false;
|
|
||||||
ClearBreakPoints();
|
|
||||||
DEBUG_Enable();
|
|
||||||
|
|
||||||
SetBreakPoints();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Bit32u DEBUG_CheckKeys(void) {
|
Bit32u DEBUG_CheckKeys(void) {
|
||||||
|
|
||||||
|
if (codeViewData.inputMode) {
|
||||||
|
int key = getch();
|
||||||
|
if (key>0) {
|
||||||
|
switch (key) {
|
||||||
|
case 0x0A: codeViewData.inputMode = FALSE;
|
||||||
|
ParseCommand(codeViewData.inputStr);
|
||||||
|
break;
|
||||||
|
case 0x08: // delete
|
||||||
|
if (strlen(codeViewData.inputStr)>0) codeViewData.inputStr[strlen(codeViewData.inputStr)-1] = 0;
|
||||||
|
break;
|
||||||
|
default : if ((key>=32) && (key<=128) && (strlen(codeViewData.inputStr)<253)) {
|
||||||
|
Bit32u len = strlen(codeViewData.inputStr);
|
||||||
|
codeViewData.inputStr[len] = char(key);
|
||||||
|
codeViewData.inputStr[len+1] = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DEBUG_DrawScreen();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
int key=getch();
|
int key=getch();
|
||||||
Bit32u ret=0;
|
Bit32u ret=0;
|
||||||
if (key>0) {
|
if (key>0) {
|
||||||
switch (key) {
|
switch (toupper(key)) {
|
||||||
case '1':
|
case '1':
|
||||||
ret=(*cpudecoder)(100);
|
ret=(*cpudecoder)(100);
|
||||||
break;
|
break;
|
||||||
@ -202,32 +600,102 @@ Bit32u DEBUG_CheckKeys(void) {
|
|||||||
case 'q':
|
case 'q':
|
||||||
ret=(*cpudecoder)(5);
|
ret=(*cpudecoder)(5);
|
||||||
break;
|
break;
|
||||||
|
case 'D': dataSeg = SegValue(ds);
|
||||||
|
dataOfs = reg_si;
|
||||||
|
break;
|
||||||
|
case 'E': dataSeg = SegValue(es);
|
||||||
|
dataOfs = reg_di;
|
||||||
|
break;
|
||||||
|
case 'X': dataSeg = SegValue(ds);
|
||||||
|
dataOfs = reg_dx;
|
||||||
|
break;
|
||||||
|
case 'B': dataSeg = SegValue(es);
|
||||||
|
dataOfs = reg_bx;
|
||||||
|
break;
|
||||||
|
case 'S': dataSeg = SegValue(ss);
|
||||||
|
dataOfs = reg_sp;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
case 'R' : dataOfs -= 16; break;
|
||||||
ret=(*cpudecoder)(1);
|
case 'F' : dataOfs += 16; break;
|
||||||
|
case 'H' : strcpy(codeViewData.inputStr,"H ");
|
||||||
|
ParseCommand(codeViewData.inputStr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0A : // Return : input
|
||||||
|
codeViewData.inputMode = true;
|
||||||
|
codeViewData.inputStr[0] = 0;
|
||||||
|
break;
|
||||||
|
case KEY_DOWN: // down
|
||||||
|
if (codeViewData.cursorPos<9) codeViewData.cursorPos++;
|
||||||
|
else codeViewData.useEIP += codeViewData.firstInstSize;
|
||||||
|
break;
|
||||||
|
case KEY_UP: // up
|
||||||
|
if (codeViewData.cursorPos>0) codeViewData.cursorPos--;
|
||||||
|
else codeViewData.useEIP -= 1;
|
||||||
|
break;
|
||||||
|
case KEY_F(5): // Run Programm
|
||||||
|
debugging=false;
|
||||||
|
SetBreakpoints();
|
||||||
|
DOSBOX_SetNormalLoop();
|
||||||
|
break;
|
||||||
|
case KEY_F(9): // Set/Remove TBreakpoint
|
||||||
|
{ PhysPt ptr = PhysMake(codeViewData.cursorSeg,codeViewData.cursorOfs);
|
||||||
|
if (IsBreakpoint(ptr)) DeleteBreakpoint(ptr);
|
||||||
|
else AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_F(10): // Step over inst
|
||||||
|
if (StepOver()) return 0;
|
||||||
|
else {
|
||||||
|
Bitu ret=(*cpudecoder)(1);
|
||||||
|
SetCodeWinStart();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_F(11): // trace into
|
||||||
|
ret = (*cpudecoder)(1);
|
||||||
|
SetCodeWinStart();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// // FIXME : Is this correct ?
|
||||||
|
// if (key<0x200) ret=(*cpudecoder)(1);
|
||||||
|
// break;
|
||||||
};
|
};
|
||||||
DEBUG_DrawScreen();
|
DEBUG_DrawScreen();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Bitu DEBUG_Loop(void) {
|
Bitu DEBUG_Loop(void) {
|
||||||
//TODO Disable sound
|
//TODO Disable sound
|
||||||
GFX_Events();
|
GFX_Events();
|
||||||
|
// Interrupt started ? - then skip it
|
||||||
|
Bit16u oldCS = SegValue(cs);
|
||||||
|
Bit32u oldEIP = reg_eip;
|
||||||
PIC_runIRQs();
|
PIC_runIRQs();
|
||||||
|
if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) {
|
||||||
|
AddBreakpoint(oldCS,oldEIP,true);
|
||||||
|
SetBreakpoints();
|
||||||
|
debugging=false;
|
||||||
|
DOSBOX_SetNormalLoop();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return DEBUG_CheckKeys();
|
return DEBUG_CheckKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DEBUG_Enable(void) {
|
void DEBUG_Enable(void) {
|
||||||
DEBUG_DrawScreen();
|
|
||||||
debugging=true;
|
debugging=true;
|
||||||
|
SetCodeWinStart();
|
||||||
|
DEBUG_DrawScreen();
|
||||||
DOSBOX_SetLoop(&DEBUG_Loop);
|
DOSBOX_SetLoop(&DEBUG_Loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DEBUG_DrawScreen(void) {
|
void DEBUG_DrawScreen(void) {
|
||||||
DrawRegisters();
|
DrawRegisters();
|
||||||
|
DrawData();
|
||||||
DrawCode();
|
DrawCode();
|
||||||
}
|
}
|
||||||
static void DEBUG_RaiseTimerIrq(void) {
|
static void DEBUG_RaiseTimerIrq(void) {
|
||||||
@ -248,5 +716,10 @@ void DEBUG_Init(void) {
|
|||||||
/* Add some keyhandlers */
|
/* Add some keyhandlers */
|
||||||
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable);
|
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable);
|
||||||
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
|
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
|
||||||
|
/* Clear the TBreakpoint list */
|
||||||
|
memset((void*)&codeViewData,0,sizeof(codeViewData));
|
||||||
|
(BPoints.clear)();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ Any comments/updates/bug reports to:
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#ifdef C_DEBUG
|
#if C_DEBUG
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -456,7 +456,7 @@ static char *addr_to_hex(UINT32 addr, int splitup) {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PhysOff getbyte_mac;
|
static PhysPt getbyte_mac;
|
||||||
|
|
||||||
|
|
||||||
static UINT8 getbyte(void) {
|
static UINT8 getbyte(void) {
|
||||||
@ -1070,7 +1070,7 @@ static void ua_str(char *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Bitu DasmI386(char* buffer, PhysOff pc, Bitu cur_ip, bool bit32)
|
Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32)
|
||||||
{
|
{
|
||||||
Bitu c;
|
Bitu c;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#ifdef C_DEBUG
|
#if C_DEBUG
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -96,8 +96,8 @@ static void MakeSubWindows(void) {
|
|||||||
dbg.win_data=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0);
|
dbg.win_data=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0);
|
||||||
outy+=11;
|
outy+=11;
|
||||||
/* The Code Window */
|
/* The Code Window */
|
||||||
dbg.win_code=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0);
|
dbg.win_code=subwin(dbg.win_main,11,dbg.win_main->_maxx,outy,0);
|
||||||
outy+=11;
|
outy+=12;
|
||||||
/* The output Window */
|
/* The output Window */
|
||||||
dbg.win_out=subwin(dbg.win_main,dbg.win_main->_maxy-outy-1,dbg.win_main->_maxx,outy,0);
|
dbg.win_out=subwin(dbg.win_main,dbg.win_main->_maxy-outy-1,dbg.win_main->_maxx,outy,0);
|
||||||
dbg.input_y=dbg.win_main->_maxy-1;
|
dbg.input_y=dbg.win_main->_maxy-1;
|
||||||
@ -110,6 +110,9 @@ static void MakeSubWindows(void) {
|
|||||||
static void MakePairs(void) {
|
static void MakePairs(void) {
|
||||||
init_pair(PAIR_BLACK_BLUE, COLOR_BLACK, COLOR_CYAN);
|
init_pair(PAIR_BLACK_BLUE, COLOR_BLACK, COLOR_CYAN);
|
||||||
init_pair(PAIR_BYELLOW_BLACK, COLOR_YELLOW /*| FOREGROUND_INTENSITY */, COLOR_BLACK);
|
init_pair(PAIR_BYELLOW_BLACK, COLOR_YELLOW /*| FOREGROUND_INTENSITY */, COLOR_BLACK);
|
||||||
|
init_pair(PAIR_GREEN_BLACK, COLOR_GREEN /*| FOREGROUND_INTENSITY */, COLOR_BLACK);
|
||||||
|
init_pair(PAIR_BLACK_GREY, COLOR_BLACK /*| FOREGROUND_INTENSITY */, COLOR_WHITE);
|
||||||
|
init_pair(PAIR_GREY_RED, COLOR_WHITE/*| FOREGROUND_INTENSITY */, COLOR_RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,11 +22,14 @@
|
|||||||
|
|
||||||
#define PAIR_BLACK_BLUE 1
|
#define PAIR_BLACK_BLUE 1
|
||||||
#define PAIR_BYELLOW_BLACK 2
|
#define PAIR_BYELLOW_BLACK 2
|
||||||
|
#define PAIR_GREEN_BLACK 3
|
||||||
|
#define PAIR_BLACK_GREY 4
|
||||||
|
#define PAIR_GREY_RED 5
|
||||||
|
|
||||||
|
|
||||||
void DBGUI_StartUp(void);
|
void DBGUI_StartUp(void);
|
||||||
|
|
||||||
struct DBGBlock {
|
struct DBGBlock {
|
||||||
WINDOW * win_main; /* The Main Window */
|
WINDOW * win_main; /* The Main Window */
|
||||||
WINDOW * win_reg; /* Register Window */
|
WINDOW * win_reg; /* Register Window */
|
||||||
WINDOW * win_data; /* Data Output window */
|
WINDOW * win_data; /* Data Output window */
|
||||||
@ -40,7 +43,7 @@ struct DBGBlock {
|
|||||||
struct DASMLine {
|
struct DASMLine {
|
||||||
Bit32u pc;
|
Bit32u pc;
|
||||||
char dasm[80];
|
char dasm[80];
|
||||||
PhysOff ea;
|
PhysPt ea;
|
||||||
Bit16u easeg;
|
Bit16u easeg;
|
||||||
Bit32u eaoff;
|
Bit32u eaoff;
|
||||||
};
|
};
|
||||||
@ -49,4 +52,4 @@ extern DBGBlock dbg;
|
|||||||
|
|
||||||
|
|
||||||
/* Local Debug Stuff */
|
/* Local Debug Stuff */
|
||||||
Bitu DasmI386(char* buffer, PhysOff pc, Bitu cur_ip, bool bit32);
|
Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32);
|
||||||
|
@ -63,21 +63,13 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
|
|||||||
|
|
||||||
extern void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page);
|
extern void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page);
|
||||||
bool device_CON::Write(Bit8u * data,Bit16u * size) {
|
bool device_CON::Write(Bit8u * data,Bit16u * size) {
|
||||||
//TODO Hack a way to call int 0x10
|
|
||||||
Bit16u oldax=reg_ax;Bit16u oldbx=reg_bx;
|
|
||||||
Bit16u count=0;
|
Bit16u count=0;
|
||||||
while (*size>count) {
|
while (*size>count) {
|
||||||
/*
|
|
||||||
reg_al=data[count];
|
|
||||||
reg_ah=0x0e;
|
|
||||||
reg_bx=0x0007;
|
|
||||||
CALLBACK_RunRealInt(0x10);
|
|
||||||
*/
|
|
||||||
INT10_TeletypeOutput(data[count],7,false,0);
|
INT10_TeletypeOutput(data[count],7,false,0);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
*size=count;
|
*size=count;
|
||||||
// reg_ax=oldax;reg_bx=oldbx;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
164
src/dos/dos.cpp
164
src/dos/dos.cpp
@ -29,6 +29,8 @@
|
|||||||
#include "dos_inc.h"
|
#include "dos_inc.h"
|
||||||
|
|
||||||
DOS_Block dos;
|
DOS_Block dos;
|
||||||
|
DOS_InfoBlock dosInfoBlock;
|
||||||
|
|
||||||
static Bit8u dos_copybuf[0x10000];
|
static Bit8u dos_copybuf[0x10000];
|
||||||
static Bitu call_20,call_21,call_theend;
|
static Bitu call_20,call_21,call_theend;
|
||||||
|
|
||||||
@ -105,7 +107,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
case 0x09: /* Write string to STDOUT */
|
case 0x09: /* Write string to STDOUT */
|
||||||
{
|
{
|
||||||
Bit8u c;Bit16u n=1;
|
Bit8u c;Bit16u n=1;
|
||||||
PhysOff buf=real_phys(Segs[ds].value,reg_dx);
|
PhysPt buf=SegPhys(ds)+reg_dx;
|
||||||
while ((c=mem_readb(buf++))!='$') {
|
while ((c=mem_readb(buf++))!='$') {
|
||||||
DOS_WriteFile(STDOUT,&c,&n);
|
DOS_WriteFile(STDOUT,&c,&n);
|
||||||
}
|
}
|
||||||
@ -114,18 +116,16 @@ static Bitu DOS_21Handler(void) {
|
|||||||
case 0x0a: /* Buffered Input */
|
case 0x0a: /* Buffered Input */
|
||||||
{
|
{
|
||||||
//TODO ADD Break checkin in STDIN but can't care that much for it
|
//TODO ADD Break checkin in STDIN but can't care that much for it
|
||||||
PhysOff data=real_phys(Segs[ds].value,reg_dx);
|
PhysPt data=SegPhys(ds)+reg_dx;
|
||||||
Bit8u free=mem_readb(data);
|
Bit8u free=mem_readb(data);
|
||||||
Bit8u read=0;Bit8u c;Bit16u n=1;
|
Bit8u read=0;Bit8u c;Bit16u n=1;
|
||||||
if (!free) break;
|
if (!free) break;
|
||||||
while (read<free) {
|
while (read<free) {
|
||||||
DOS_ReadFile(STDIN,&c,&n);
|
DOS_ReadFile(STDIN,&c,&n);
|
||||||
DOS_WriteFile(STDOUT,&c,&n);
|
DOS_WriteFile(STDOUT,&c,&n);
|
||||||
if (c==13) {
|
|
||||||
DOS_ReadFile(STDIN,&c,&n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mem_writeb(data+read+2,c);
|
mem_writeb(data+read+2,c);
|
||||||
|
if (c==13)
|
||||||
|
break;
|
||||||
read++;
|
read++;
|
||||||
};
|
};
|
||||||
mem_writeb(data+1,read);
|
mem_writeb(data+1,read);
|
||||||
@ -166,9 +166,41 @@ static Bitu DOS_21Handler(void) {
|
|||||||
reg_al=26;
|
reg_al=26;
|
||||||
break;
|
break;
|
||||||
case 0x0f: /* Open File using FCB */
|
case 0x0f: /* Open File using FCB */
|
||||||
|
if(DOS_FCBOpen(SegValue(ds),reg_dx)){
|
||||||
|
reg_al=0;
|
||||||
|
}else{
|
||||||
|
reg_al=0xff;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("DOS:0x0f FCB-fileopen used, result:al=%d",reg_al);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x10: /* Close File using FCB */
|
case 0x10: /* Close File using FCB */
|
||||||
|
if(DOS_FCBClose(SegValue(ds),reg_dx)){
|
||||||
|
reg_al=0;
|
||||||
|
}else{
|
||||||
|
reg_al=0xff;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("DOS:0x10 FCB-fileclose used, result:al=%d",reg_al);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x11: /* Find First Matching File using FCB */
|
case 0x11: /* Find First Matching File using FCB */
|
||||||
|
if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){
|
||||||
|
reg_al=0;
|
||||||
|
}else{
|
||||||
|
reg_al=0xff;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x12: /* Find Next Matching File using FCB */
|
case 0x12: /* Find Next Matching File using FCB */
|
||||||
|
if(DOS_FCBFindNext(SegValue(ds),reg_dx)){
|
||||||
|
reg_al=0;
|
||||||
|
}else{
|
||||||
|
reg_al=0xff;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("DOS:0x12 FCB-FindNext used, result:al=%d",reg_al);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x13: /* Delete File using FCB */
|
case 0x13: /* Delete File using FCB */
|
||||||
case 0x14: /* Sequential read from FCB */
|
case 0x14: /* Sequential read from FCB */
|
||||||
case 0x15: /* Sequential write to FCB */
|
case 0x15: /* Sequential write to FCB */
|
||||||
@ -182,23 +214,19 @@ static Bitu DOS_21Handler(void) {
|
|||||||
case 0x28: /* Random Block read to FCB */
|
case 0x28: /* Random Block read to FCB */
|
||||||
LOG_ERROR("DOS:Unhandled call %02X, FCB Stuff",reg_ah);
|
LOG_ERROR("DOS:Unhandled call %02X, FCB Stuff",reg_ah);
|
||||||
reg_al=0xff; /* FCB Calls FAIL */
|
reg_al=0xff; /* FCB Calls FAIL */
|
||||||
CALLBACK_SCF(true);
|
//CALLBACK_SCF(true); not needed.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x29: /* Parse filename into FCB */
|
case 0x29: /* Parse filename into FCB */
|
||||||
//TODO Give errors for unsupported functions
|
{ Bit8u difference;
|
||||||
{
|
char string[1024];
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_si),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_si,string,1024);
|
||||||
/* only detect the call program use to detect the existence of a harddisk */
|
reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference);
|
||||||
if ((strlen((char *)name1)==2) && (name1[1]==':')) {
|
reg_di+=difference;
|
||||||
Bit8u drive=toupper(name1[0])-'A';
|
}
|
||||||
if (Drives[drive]) reg_al=0;
|
LOG_DEBUG("DOS:29:FCB Parse Filename, result:al=%d",reg_al);
|
||||||
else reg_al=0xff;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
LOG_DEBUG("DOS:29:FCB Parse Filename:%s",name1);
|
|
||||||
};
|
|
||||||
reg_al=0xff; /* FCB Calls FAIL */
|
|
||||||
break;
|
|
||||||
case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */
|
case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */
|
||||||
case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */
|
case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */
|
||||||
case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */
|
case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */
|
||||||
@ -211,12 +239,12 @@ static Bitu DOS_21Handler(void) {
|
|||||||
reg_al=DOS_GetDefaultDrive();
|
reg_al=DOS_GetDefaultDrive();
|
||||||
break;
|
break;
|
||||||
case 0x1a: /* Set Disk Transfer Area Address */
|
case 0x1a: /* Set Disk Transfer Area Address */
|
||||||
//TODO find out what a DTA does
|
dos.dta=RealMakeSeg(ds,reg_dx);
|
||||||
dos.dta=RealMake(Segs[ds].value,reg_dx);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1c: /* Get allocation info for specific drive */
|
case 0x1c: /* Get allocation info for specific drive */
|
||||||
LOG_DEBUG("DOS: Allocation Info call not supported correctly");
|
LOG_DEBUG("DOS: Allocation Info call not supported correctly");
|
||||||
SetSegment_16(ds,0xf000);
|
SegSet16(ds,0xf000);
|
||||||
reg_bx=0;
|
reg_bx=0;
|
||||||
real_writeb(0xf000,0,0);
|
real_writeb(0xf000,0,0);
|
||||||
reg_al=0x7f;
|
reg_al=0x7f;
|
||||||
@ -225,7 +253,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
break; /* TODO maybe but hardly think a game needs this */
|
break; /* TODO maybe but hardly think a game needs this */
|
||||||
case 0x1b: /* Get allocation info for default drive */
|
case 0x1b: /* Get allocation info for default drive */
|
||||||
LOG_DEBUG("DOS: Allocation Info call not supported correctly");
|
LOG_DEBUG("DOS: Allocation Info call not supported correctly");
|
||||||
SetSegment_16(ds,0xf000);
|
SegSet16(ds,0xf000);
|
||||||
reg_bx=0;
|
reg_bx=0;
|
||||||
real_writeb(0xf000,0,0);
|
real_writeb(0xf000,0,0);
|
||||||
reg_al=0x7f;
|
reg_al=0x7f;
|
||||||
@ -237,7 +265,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
E_Exit("DOS:Unhandled call %02X",reg_ah);
|
E_Exit("DOS:Unhandled call %02X",reg_ah);
|
||||||
break; /* TODO maybe but hardly think a game needs this */
|
break; /* TODO maybe but hardly think a game needs this */
|
||||||
case 0x25: /* Set Interrupt Vector */
|
case 0x25: /* Set Interrupt Vector */
|
||||||
RealSetVec(reg_al,RealMake(Segs[ds].value,reg_dx));
|
RealSetVec(reg_al,RealMakeSeg(ds,reg_dx));
|
||||||
break;
|
break;
|
||||||
case 0x26: /* Create new PSP */
|
case 0x26: /* Create new PSP */
|
||||||
DOS_NewPSP(reg_dx);
|
DOS_NewPSP(reg_dx);
|
||||||
@ -277,7 +305,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
dos.verify=(reg_al==1);
|
dos.verify=(reg_al==1);
|
||||||
break;
|
break;
|
||||||
case 0x2f: /* Get Disk Transfer Area */
|
case 0x2f: /* Get Disk Transfer Area */
|
||||||
SetSegment_16(es,RealSeg(dos.dta));
|
SegSet16(es,RealSeg(dos.dta));
|
||||||
reg_bx=RealOff(dos.dta);
|
reg_bx=RealOff(dos.dta);
|
||||||
break;
|
break;
|
||||||
case 0x30: /* Get DOS Version */
|
case 0x30: /* Get DOS Version */
|
||||||
@ -315,12 +343,12 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x34: /* Get INDos Flag */
|
case 0x34: /* Get INDos Flag */
|
||||||
SetSegment_16(es,RealSeg(dos.tables.indosflag));
|
SegSet16(es,RealSeg(dos.tables.indosflag));
|
||||||
reg_bx=RealOff(dos.tables.indosflag);
|
reg_bx=RealOff(dos.tables.indosflag);
|
||||||
break;
|
break;
|
||||||
case 0x35: /* Get interrupt vector */
|
case 0x35: /* Get interrupt vector */
|
||||||
reg_bx=real_readw(0,((Bit16u)reg_al)*4);
|
reg_bx=real_readw(0,((Bit16u)reg_al)*4);
|
||||||
SetSegment_16(es,real_readw(0,((Bit16u)reg_al)*4+2));
|
SegSet16(es,real_readw(0,((Bit16u)reg_al)*4+2));
|
||||||
break;
|
break;
|
||||||
case 0x36: /* Get Free Disk Space */
|
case 0x36: /* Get Free Disk Space */
|
||||||
{
|
{
|
||||||
@ -361,7 +389,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x39: /* MKDIR Create directory */
|
case 0x39: /* MKDIR Create directory */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_MakeDir(name1)) {
|
if (DOS_MakeDir(name1)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -370,7 +398,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3a: /* RMDIR Remove directory */
|
case 0x3a: /* RMDIR Remove directory */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_RemoveDir(name1)) {
|
if (DOS_RemoveDir(name1)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -379,7 +407,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3b: /* CHDIR Set current directory */
|
case 0x3b: /* CHDIR Set current directory */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_ChangeDir(name1)) {
|
if (DOS_ChangeDir(name1)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -388,7 +416,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3c: /* CREATE Create of truncate file */
|
case 0x3c: /* CREATE Create of truncate file */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_CreateFile(name1,reg_cx,®_ax)) {
|
if (DOS_CreateFile(name1,reg_cx,®_ax)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -397,7 +425,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x3d: /* OPEN Open existing file */
|
case 0x3d: /* OPEN Open existing file */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_OpenFile(name1,reg_al,®_ax)) {
|
if (DOS_OpenFile(name1,reg_al,®_ax)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -417,7 +445,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
{
|
{
|
||||||
Bit16u toread=reg_cx;
|
Bit16u toread=reg_cx;
|
||||||
if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) {
|
if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) {
|
||||||
MEM_BlockWrite(real_phys(Segs[ds].value,reg_dx),dos_copybuf,toread);
|
MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread);
|
||||||
reg_ax=toread;
|
reg_ax=toread;
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -429,7 +457,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
case 0x40: /* WRITE Write to file or device */
|
case 0x40: /* WRITE Write to file or device */
|
||||||
{
|
{
|
||||||
Bit16u towrite=reg_cx;
|
Bit16u towrite=reg_cx;
|
||||||
MEM_BlockRead(real_phys(Segs[ds].value,reg_dx),dos_copybuf,towrite);
|
MEM_BlockRead(SegPhys(ds)+reg_dx,dos_copybuf,towrite);
|
||||||
if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) {
|
if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) {
|
||||||
reg_ax=towrite;
|
reg_ax=towrite;
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
@ -440,7 +468,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
case 0x41: /* UNLINK Delete file */
|
case 0x41: /* UNLINK Delete file */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_UnlinkFile(name1)) {
|
if (DOS_UnlinkFile(name1)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -463,7 +491,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
case 0x43: /* Get/Set file attributes */
|
case 0x43: /* Get/Set file attributes */
|
||||||
//TODO FIX THIS HACK
|
//TODO FIX THIS HACK
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
switch (reg_al)
|
switch (reg_al)
|
||||||
case 0x00: /* Get */
|
case 0x00: /* Get */
|
||||||
{
|
{
|
||||||
@ -499,11 +527,17 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x46: /* DUP2,FORCEDUP Force duplicate file handle */
|
case 0x46: /* DUP2,FORCEDUP Force duplicate file handle */
|
||||||
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
|
if (DOS_ForceDuplicateEntry(reg_bx,reg_ax)) {
|
||||||
|
CALLBACK_SCF(false);
|
||||||
|
} else {
|
||||||
|
reg_ax=dos.errorcode;
|
||||||
|
CALLBACK_SCF(true);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x47: /* CWD Get current directory */
|
case 0x47: /* CWD Get current directory */
|
||||||
//TODO Memory
|
//TODO Memory
|
||||||
if (DOS_GetCurrentDir(reg_dl,real_off(Segs[ds].value,reg_si))) {
|
if (DOS_GetCurrentDir(reg_dl,name1)) {
|
||||||
|
MEM_BlockWrite(SegPhys(ds)+reg_si,name1,strlen(name1)+1);
|
||||||
reg_ax=0x0100;
|
reg_ax=0x0100;
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -525,7 +559,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x49: /* Free memory */
|
case 0x49: /* Free memory */
|
||||||
if (DOS_FreeMemory(Segs[es].value)) {
|
if (DOS_FreeMemory(SegValue(es))) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
reg_ax=dos.errorcode;
|
reg_ax=dos.errorcode;
|
||||||
@ -535,7 +569,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
case 0x4a: /* Resize memory block */
|
case 0x4a: /* Resize memory block */
|
||||||
{
|
{
|
||||||
Bit16u size=reg_bx;
|
Bit16u size=reg_bx;
|
||||||
if (DOS_ResizeMemory(Segs[es].value,&size)) {
|
if (DOS_ResizeMemory(SegValue(es),&size)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
reg_ax=dos.errorcode;
|
reg_ax=dos.errorcode;
|
||||||
@ -546,8 +580,8 @@ static Bitu DOS_21Handler(void) {
|
|||||||
}
|
}
|
||||||
case 0x4b: /* EXEC Load and/or execute program */
|
case 0x4b: /* EXEC Load and/or execute program */
|
||||||
{
|
{
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_Execute(name1,(ParamBlock *)real_off(Segs[es].value,reg_bx),reg_al)) {
|
if (DOS_Execute(name1,(ParamBlock *)Phys2Host(SegPhys(es)+reg_bx),reg_al)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
reg_ax=dos.errorcode;
|
reg_ax=dos.errorcode;
|
||||||
@ -573,7 +607,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
reg_ah=dos.return_mode;
|
reg_ah=dos.return_mode;
|
||||||
break;
|
break;
|
||||||
case 0x4e: /* FINDFIRST Find first matching file */
|
case 0x4e: /* FINDFIRST Find first matching file */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_FindFirst(name1,reg_cx)) {
|
if (DOS_FindFirst(name1,reg_cx)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -595,11 +629,12 @@ static Bitu DOS_21Handler(void) {
|
|||||||
case 0x51: /* Get current PSP */
|
case 0x51: /* Get current PSP */
|
||||||
reg_bx=dos.psp;
|
reg_bx=dos.psp;
|
||||||
break;
|
break;
|
||||||
case 0x52: /* Get list of lists */
|
case 0x52: { /* Get list of lists */
|
||||||
SetSegment_16(es,0);
|
Bit16u seg;
|
||||||
reg_bx=0;
|
dosInfoBlock.GetDIBPointer(seg,reg_bx);
|
||||||
LOG_ERROR("Call is made for list of lists not supported let's hope for the best");
|
SegSet16(es,seg);
|
||||||
break;
|
LOG_DEBUG("Call is made for list of lists - let's hope for the best");
|
||||||
|
break; }
|
||||||
//TODO Think hard how shit this is gonna be
|
//TODO Think hard how shit this is gonna be
|
||||||
//And will any game ever use this :)
|
//And will any game ever use this :)
|
||||||
case 0x53: /* Translate BIOS parameter block to drive parameter block */
|
case 0x53: /* Translate BIOS parameter block to drive parameter block */
|
||||||
@ -609,8 +644,8 @@ static Bitu DOS_21Handler(void) {
|
|||||||
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
|
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
|
||||||
break;
|
break;
|
||||||
case 0x56: /* RENAME Rename file */
|
case 0x56: /* RENAME Rename file */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
MEM_StrCopy(real_phys(Segs[es].value,reg_di),name2,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(es)+reg_di,name2,DOSNAMEBUF);
|
||||||
if (DOS_Rename(name1,name2)) {
|
if (DOS_Rename(name1,name2)) {
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
@ -627,12 +662,15 @@ static Bitu DOS_21Handler(void) {
|
|||||||
LOG_DEBUG("DOS:58:Not Supported Set//Get memory allocation");
|
LOG_DEBUG("DOS:58:Not Supported Set//Get memory allocation");
|
||||||
break;
|
break;
|
||||||
case 0x59: /* Get Extended error information */
|
case 0x59: /* Get Extended error information */
|
||||||
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
|
reg_ax=dos.errorcode;
|
||||||
|
reg_bh=0; //Unkown error class
|
||||||
|
reg_bl=1; //Retry retry retry
|
||||||
|
reg_ch=0; //Unkown error locus
|
||||||
break;
|
break;
|
||||||
case 0x5a: /* Create temporary file */
|
case 0x5a: /* Create temporary file */
|
||||||
{
|
{
|
||||||
Bit16u handle;
|
Bit16u handle;
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_CreateTempFile(name1,&handle)) {
|
if (DOS_CreateTempFile(name1,&handle)) {
|
||||||
reg_ax=handle;
|
reg_ax=handle;
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
@ -644,7 +682,7 @@ static Bitu DOS_21Handler(void) {
|
|||||||
break;
|
break;
|
||||||
case 0x5b: /* Create new file */
|
case 0x5b: /* Create new file */
|
||||||
{
|
{
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
Bit16u handle;
|
Bit16u handle;
|
||||||
if (DOS_OpenFile(name1,0,&handle)) {
|
if (DOS_OpenFile(name1,0,&handle)) {
|
||||||
DOS_CloseFile(handle);
|
DOS_CloseFile(handle);
|
||||||
@ -669,8 +707,9 @@ static Bitu DOS_21Handler(void) {
|
|||||||
E_Exit("DOS:Unhandled call %02X",reg_ah);
|
E_Exit("DOS:Unhandled call %02X",reg_ah);
|
||||||
break;
|
break;
|
||||||
case 0x60: /* Canonicalize filename or path */
|
case 0x60: /* Canonicalize filename or path */
|
||||||
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
|
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||||
if (DOS_Canonicalize(name1,real_off(Segs[es].value,reg_di))) {
|
if (DOS_Canonicalize(name1,name2)) {
|
||||||
|
MEM_BlockWrite(SegPhys(es)+reg_di,name2,strlen(name2)+1);
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
} else {
|
} else {
|
||||||
reg_ax=dos.errorcode;
|
reg_ax=dos.errorcode;
|
||||||
@ -691,13 +730,13 @@ static Bitu DOS_21Handler(void) {
|
|||||||
/* Todo maybe fully support this for now we set it standard for USA */
|
/* Todo maybe fully support this for now we set it standard for USA */
|
||||||
{
|
{
|
||||||
LOG_DEBUG("DOS:65:Extended country information call");
|
LOG_DEBUG("DOS:65:Extended country information call");
|
||||||
Bit8u * data=real_off(Segs[es].value,reg_di);
|
PhysPt data=SegPhys(es)+reg_di;
|
||||||
switch (reg_al) {
|
switch (reg_al) {
|
||||||
case 1:
|
case 1:
|
||||||
real_writeb(Segs[es].value,reg_di,reg_al);
|
mem_writeb(data,reg_al);
|
||||||
real_writew(Segs[es].value,reg_di+1,4);
|
mem_writew(data+1,4);
|
||||||
real_writew(Segs[es].value,reg_di+3,1);
|
mem_writew(data+3,1);
|
||||||
real_writew(Segs[es].value,reg_di+5,37);
|
mem_writew(data+5,37);
|
||||||
reg_cx=4;
|
reg_cx=4;
|
||||||
CALLBACK_SCF(false);
|
CALLBACK_SCF(false);
|
||||||
break;
|
break;
|
||||||
@ -725,7 +764,6 @@ static Bitu DOS_21Handler(void) {
|
|||||||
break;
|
break;
|
||||||
case 0x69: /* Get/Set disk serial number */
|
case 0x69: /* Get/Set disk serial number */
|
||||||
{
|
{
|
||||||
Bit8u * temp=real_off(Segs[ds].value,reg_dx);
|
|
||||||
switch(reg_al) {
|
switch(reg_al) {
|
||||||
case 0x00: /* Get */
|
case 0x00: /* Get */
|
||||||
LOG_DEBUG("DOS:Get Disk serial number");
|
LOG_DEBUG("DOS:Get Disk serial number");
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "dos_inc.h"
|
#include "dos_inc.h"
|
||||||
|
#include "support.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Work in progress, making classes for handling certain internal memory structures in dos
|
Work in progress, making classes for handling certain internal memory structures in dos
|
||||||
@ -28,6 +29,7 @@
|
|||||||
dos work a bit easier.
|
dos work a bit easier.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma pack (1)
|
||||||
|
|
||||||
struct sPSP {
|
struct sPSP {
|
||||||
Bit8u exit[2]; /* CP/M-like exit poimt */
|
Bit8u exit[2]; /* CP/M-like exit poimt */
|
||||||
@ -52,130 +54,235 @@ struct sPSP {
|
|||||||
Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */
|
Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */
|
||||||
Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */
|
Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */
|
||||||
Bit8u fill_3[45]; /* This has some blocks with FCB info */
|
Bit8u fill_3[45]; /* This has some blocks with FCB info */
|
||||||
|
|
||||||
CommandTail cmdtail;
|
CommandTail cmdtail;
|
||||||
|
} GCC_ATTRIBUTE(packed);
|
||||||
};
|
|
||||||
|
union sParamBlock {
|
||||||
|
struct {
|
||||||
|
Bit16u loadseg;
|
||||||
|
Bit16u relocation;
|
||||||
|
} overlay;
|
||||||
|
struct {
|
||||||
|
Bit16u envseg;
|
||||||
|
RealPt cmdtail;
|
||||||
|
RealPt fcb1;
|
||||||
|
RealPt fcb2;
|
||||||
|
RealPt initsssp;
|
||||||
|
RealPt initcsip;
|
||||||
|
} exec;
|
||||||
|
} GCC_ATTRIBUTE(packed);
|
||||||
|
|
||||||
|
struct sFCB {
|
||||||
|
Bit8u drive; //0 is current drive. when opened 0 is replaced by drivenumber
|
||||||
|
Bit8u filename[8]; //spacepadded to fit
|
||||||
|
Bit8u ext[3]; //spacepadded to fit
|
||||||
|
Bit16u current_block; // set to 0 by open
|
||||||
|
Bit16u record_size; // used by reads Set to 80h by OPEN function
|
||||||
|
Bit32u filesize; //in bytes In this field, the first word is the low-order part of the size
|
||||||
|
Bit16u date;
|
||||||
|
Bit16u time;
|
||||||
|
Bit8u reserved[8];
|
||||||
|
Bit8u current_relative_record_number; //open doesn't set this
|
||||||
|
Bit32u rel_record; //open does not handle this
|
||||||
|
} GCC_ATTRIBUTE(packed);
|
||||||
|
|
||||||
|
#pragma pack ()
|
||||||
|
|
||||||
|
#define sGet(s,m) GetIt(((s *)0)->m,(PhysPt)&(((s *)0)->m))
|
||||||
|
#define sSave(s,m,val) SaveIt(((s *)0)->m,(PhysPt)&(((s *)0)->m),val)
|
||||||
|
|
||||||
|
|
||||||
|
class MemStruct {
|
||||||
class DOS_PSP {
|
|
||||||
public:
|
public:
|
||||||
DOS_PSP(Bit16u segment);
|
Bit8u GetIt(Bit8u,PhysPt addr) {
|
||||||
|
return mem_readb(pt+addr);
|
||||||
|
};
|
||||||
|
Bit16u GetIt(Bit16u,PhysPt addr) {
|
||||||
|
return mem_readw(pt+addr);
|
||||||
|
};
|
||||||
|
Bit32u GetIt(Bit32u,PhysPt addr) {
|
||||||
|
return mem_readd(pt+addr);
|
||||||
|
};
|
||||||
|
void SaveIt(Bit8u,PhysPt addr,Bit8u val) {
|
||||||
|
mem_writeb(pt+addr,val);
|
||||||
|
};
|
||||||
|
void SaveIt(Bit16u,PhysPt addr,Bit16u val) {
|
||||||
|
mem_writew(pt+addr,val);
|
||||||
|
};
|
||||||
|
void SaveIt(Bit32u,PhysPt addr,Bit32u val) {
|
||||||
|
mem_writed(pt+addr,val);
|
||||||
|
};
|
||||||
|
|
||||||
void MakeNew(Bit16u env,Bit16u memsize);
|
|
||||||
|
|
||||||
|
|
||||||
Bit16u base_seg;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PhysOff off;
|
PhysPt pt;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DOS_PSP::DOS_PSP(Bit16u segment) {
|
|
||||||
base_seg=segment;
|
class DOS_PSP :public MemStruct {
|
||||||
off=Real2Phys(RealMake(segment,0));
|
public:
|
||||||
|
DOS_PSP(Bit16u segment){NewPt(segment);};
|
||||||
|
void NewPt(Bit16u segment);
|
||||||
|
void MakeNew(Bit16u mem_size);
|
||||||
|
Bit8u GetFileHandle(Bitu index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Bit16u seg;
|
||||||
|
PhysPt pt;
|
||||||
};
|
};
|
||||||
|
|
||||||
void DOS_PSP::MakeNew(Bit16u env,Bit16u next_para) {
|
void DOS_PSP::NewPt(Bit16u segment) {
|
||||||
|
seg=segment;
|
||||||
|
pt=PhysMake(segment,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void DOS_PSP::MakeNew(Bit16u mem_size) {
|
||||||
Bitu i;
|
Bitu i;
|
||||||
for (i=0;i<256;i++) mem_writeb(off+i,0);
|
/* Clear it first */
|
||||||
/* Standard blocks */
|
for (i=0;i<256;i++) mem_writeb(pt+i,0);
|
||||||
mem_writeb(off+offsetof(sPSP,exit[0]),0xcd);
|
/* Standard blocks,int 20 and int21 retf */
|
||||||
mem_writeb(off+offsetof(sPSP,exit[1]),0x20);
|
sGet(sPSP,max_files);
|
||||||
|
sSave(sPSP,exit[0],0xcd);
|
||||||
mem_writeb(off+offsetof(sPSP,service[0]),0xcd);
|
sSave(sPSP,exit[1],0x20);
|
||||||
mem_writeb(off+offsetof(sPSP,service[1]),0x21);
|
sSave(sPSP,service[0],0xcd);
|
||||||
mem_writeb(off+offsetof(sPSP,service[2]),0xcb);
|
sSave(sPSP,service[1],0x21);
|
||||||
|
sSave(sPSP,service[2],0xcb);
|
||||||
mem_writew(off+offsetof(sPSP,next_seg),next_para);
|
/* psp and psp-parent */
|
||||||
|
sSave(sPSP,psp_parent,dos.psp);
|
||||||
|
sSave(sPSP,prev_psp,RealMake(dos.psp,0));
|
||||||
// mem_writew(off+offsetof(sPSP,psp_parent),dos.psp->base_seg);
|
/* terminate 22,break 23,crititcal error 24 address stored */
|
||||||
|
sSave(sPSP,int_22,RealGetVec(0x22));
|
||||||
/* Setup initial file table */
|
sSave(sPSP,int_23,RealGetVec(0x23));
|
||||||
mem_writed(off+offsetof(sPSP,int_22),RealGetVec(0x22));
|
sSave(sPSP,int_24,RealGetVec(0x24));
|
||||||
mem_writed(off+offsetof(sPSP,int_23),RealGetVec(0x23));
|
/* Memory size */
|
||||||
mem_writed(off+offsetof(sPSP,int_24),RealGetVec(0x24));
|
sSave(sPSP,next_seg,seg+mem_size);
|
||||||
|
/* Process DTA */
|
||||||
|
sSave(sPSP,dta,RealMake(seg,128));
|
||||||
#if 0
|
/* User Stack pointer */
|
||||||
|
//Copy from previous psp
|
||||||
newpsp->mem_size=prevpsp->mem_size;
|
// mem_writed(pt+offsetof(sPSP,stack),
|
||||||
newpsp->environment=0;
|
|
||||||
|
|
||||||
newpsp->int_22.full=real_getvec(0x22);
|
|
||||||
newpsp->int_23.full=real_getvec(0x23);
|
|
||||||
newpsp->int_24.full=real_getvec(0x24);
|
|
||||||
|
|
||||||
newpsp->psp_parent=dos.psp;
|
|
||||||
newpsp->prev_psp.full=0xFFFFFFFF;
|
|
||||||
|
|
||||||
Bit32u i;
|
|
||||||
Bit8u * prevfile=real_off(prevpsp->file_table.seg,prevpsp->file_table.off);
|
|
||||||
for (i=0;i<20;i++) newpsp->files[i]=prevfile[i];
|
|
||||||
|
|
||||||
newpsp->max_files=20;
|
|
||||||
newpsp->file_table.seg=pspseg;
|
|
||||||
newpsp->file_table.off=offsetof(PSP,files);
|
|
||||||
/* Save the old DTA in this psp */
|
|
||||||
newpsp->dta.seg=dos.dta.seg;
|
|
||||||
newpsp->dta.off=dos.dta.off;
|
|
||||||
/* Setup the DTA */
|
|
||||||
dos.dta.seg=pspseg;
|
|
||||||
dos.dta.off=0x80;
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Init file pointer and max_files */
|
||||||
|
sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files[0])));
|
||||||
|
sSave(sPSP,max_files,20);
|
||||||
|
/* Copy file table from calling process */
|
||||||
|
for (i=0;i<20;i++) {
|
||||||
|
Bit8u handle=0;
|
||||||
|
// Bitu handle=dos.psp.GetFileHandle(i);
|
||||||
|
sSave(sPSP,files[i],handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bit8u DOS_PSP::GetFileHandle(Bitu index) {
|
||||||
|
if (index>=sGet(sPSP,max_files)) return 0xff;
|
||||||
|
PhysPt files=Real2Phys(sGet(sPSP,file_table));
|
||||||
|
return mem_readb(files+index);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FCB_EXTENDED (mem_readb(off)==0xFF ? 7:0)
|
||||||
|
|
||||||
void DOS_FCB::Set_drive(Bit8u a){
|
void DOS_FCB::Set_drive(Bit8u a){
|
||||||
mem_writeb(off+offsetof(FCB,drive),a);
|
mem_writeb(off+offsetof(sFCB,drive)+FCB_EXTENDED,a);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Set_filename(char * a){
|
void DOS_FCB::Set_filename(char * a){
|
||||||
MEM_BlockWrite(off+offsetof(FCB,filename),a,8);
|
MEM_BlockWrite(off+offsetof(sFCB,filename)+FCB_EXTENDED,a,8);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Set_ext(char * a) {
|
void DOS_FCB::Set_ext(char * a) {
|
||||||
MEM_BlockWrite(off+offsetof(FCB,ext),a,3);
|
MEM_BlockWrite(off+offsetof(sFCB,ext)+FCB_EXTENDED,a,3);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Set_current_block(Bit16u a){
|
void DOS_FCB::Set_current_block(Bit16u a){
|
||||||
mem_writew(off+offsetof(FCB,current_block),a);
|
mem_writew(off+offsetof(sFCB,current_block)+FCB_EXTENDED,a);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Set_record_size(Bit16u a){
|
void DOS_FCB::Set_record_size(Bit16u a){
|
||||||
mem_writew(off+offsetof(FCB,record_size),a);
|
mem_writew(off+offsetof(sFCB,record_size)+FCB_EXTENDED,a);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Set_filesize(Bit32u a){
|
void DOS_FCB::Set_filesize(Bit32u a){
|
||||||
mem_writed(off+offsetof(FCB,filesize),a);
|
mem_writed(off+offsetof(sFCB,filesize)+FCB_EXTENDED,a);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Set_date(Bit16u a){
|
void DOS_FCB::Set_date(Bit16u a){
|
||||||
mem_writew(off+offsetof(FCB,date),a);
|
mem_writew(off+offsetof(sFCB,date)+FCB_EXTENDED,a);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Set_time(Bit16u a){
|
void DOS_FCB::Set_time(Bit16u a){
|
||||||
mem_writew(off+offsetof(FCB,time),a);
|
mem_writew(off+offsetof(sFCB,time)+FCB_EXTENDED,a);
|
||||||
}
|
}
|
||||||
Bit8u DOS_FCB::Get_drive(void){
|
Bit8u DOS_FCB::Get_drive(void){
|
||||||
return mem_readb(off+offsetof(FCB,drive));
|
return mem_readb(off+offsetof(sFCB,drive)+FCB_EXTENDED);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Get_filename(char * a){
|
void DOS_FCB::Get_filename(char * a){
|
||||||
MEM_BlockRead(off+offsetof(FCB,filename),a,8);
|
MEM_BlockRead(off+offsetof(sFCB,filename)+FCB_EXTENDED,a,8);
|
||||||
}
|
}
|
||||||
void DOS_FCB::Get_ext(char * a){
|
void DOS_FCB::Get_ext(char * a){
|
||||||
MEM_BlockRead(off+offsetof(FCB,ext),a,3);
|
MEM_BlockRead(off+offsetof(sFCB,ext)+FCB_EXTENDED,a,3);
|
||||||
}
|
}
|
||||||
Bit16u DOS_FCB::Get_current_block(void){
|
Bit16u DOS_FCB::Get_current_block(void){
|
||||||
return mem_readw(off+offsetof(FCB,current_block));
|
return mem_readw(off+offsetof(sFCB,current_block)+FCB_EXTENDED);
|
||||||
}
|
}
|
||||||
Bit16u DOS_FCB::Get_record_size(void){
|
Bit16u DOS_FCB::Get_record_size(void){
|
||||||
return mem_readw(off+offsetof(FCB,record_size));
|
return mem_readw(off+offsetof(sFCB,record_size)+FCB_EXTENDED);
|
||||||
}
|
}
|
||||||
Bit32u DOS_FCB::Get_filesize(void){
|
Bit32u DOS_FCB::Get_filesize(void){
|
||||||
return mem_readd(off+offsetof(FCB,filesize));
|
return mem_readd(off+offsetof(sFCB,filesize)+FCB_EXTENDED);
|
||||||
}
|
}
|
||||||
Bit16u DOS_FCB::Get_date(void){
|
Bit16u DOS_FCB::Get_date(void){
|
||||||
return mem_readw(off+offsetof(FCB,date));
|
return mem_readw(off+offsetof(sFCB,date)+FCB_EXTENDED);
|
||||||
}
|
}
|
||||||
Bit16u DOS_FCB::Get_time(void){
|
Bit16u DOS_FCB::Get_time(void){
|
||||||
return mem_readw(off+offsetof(FCB,time));
|
return mem_readw(off+offsetof(sFCB,time)+FCB_EXTENDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DOS_ParamBlock::InitExec(RealPt cmdtail) {
|
||||||
|
mem_writew(off+offsetof(sParamBlock,exec.envseg),0);
|
||||||
|
mem_writed(off+offsetof(sParamBlock,exec.fcb1),0);
|
||||||
|
mem_writed(off+offsetof(sParamBlock,exec.fcb2),0);
|
||||||
|
mem_writed(off+offsetof(sParamBlock,exec.cmdtail),cmdtail);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bit16u DOS_ParamBlock::loadseg(void) {
|
||||||
|
return mem_readw(off+offsetof(sParamBlock,overlay.loadseg));
|
||||||
|
}
|
||||||
|
Bit16u DOS_ParamBlock::relocation(void){
|
||||||
|
return mem_readw(off+offsetof(sParamBlock,overlay.loadseg));
|
||||||
|
}
|
||||||
|
Bit16u DOS_ParamBlock::envseg(void){
|
||||||
|
return mem_readw(off+offsetof(sParamBlock,exec.envseg));
|
||||||
|
}
|
||||||
|
RealPt DOS_ParamBlock::initsssp(void){
|
||||||
|
return mem_readd(off+offsetof(sParamBlock,exec.initsssp));
|
||||||
|
}
|
||||||
|
RealPt DOS_ParamBlock::initcsip(void){
|
||||||
|
return mem_readd(off+offsetof(sParamBlock,exec.initcsip));
|
||||||
|
}
|
||||||
|
RealPt DOS_ParamBlock::fcb1(void){
|
||||||
|
return mem_readd(off+offsetof(sParamBlock,exec.fcb1));
|
||||||
|
}
|
||||||
|
RealPt DOS_ParamBlock::fcb2(void){
|
||||||
|
return mem_readd(off+offsetof(sParamBlock,exec.fcb2));
|
||||||
|
}
|
||||||
|
RealPt DOS_ParamBlock::cmdtail(void){
|
||||||
|
return mem_readd(off+offsetof(sParamBlock,exec.cmdtail));
|
||||||
|
}
|
||||||
|
|
||||||
|
// * Dos Info Block (list of lists) *
|
||||||
|
|
||||||
|
void DOS_InfoBlock::SetLocation(Bit16u segment)
|
||||||
|
{
|
||||||
|
seg = segment;
|
||||||
|
dib = (SDosInfoBlock*)HostMake(segment,0);
|
||||||
|
Bit16u size = sizeof(SDosInfoBlock);
|
||||||
|
memset(dib,0,sizeof(SDosInfoBlock));
|
||||||
|
};
|
||||||
|
|
||||||
|
void DOS_InfoBlock::SetFirstMCB(RealPt pt)
|
||||||
|
{
|
||||||
|
dib->firstMCB = pt;
|
||||||
|
};
|
||||||
|
|
||||||
|
void DOS_InfoBlock::GetDIBPointer(Bit16u& segment, Bit16u& offset)
|
||||||
|
{
|
||||||
|
segment = seg;
|
||||||
|
offset = offsetof(SDosInfoBlock,firstDPB);
|
||||||
|
};
|
||||||
|
@ -21,8 +21,9 @@
|
|||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "dos_inc.h"
|
#include "dos_inc.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#if defined (_MSC_VER)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct EXE_Header {
|
struct EXE_Header {
|
||||||
|
|
||||||
@ -40,8 +41,13 @@ struct EXE_Header {
|
|||||||
Bit16u initCS;
|
Bit16u initCS;
|
||||||
Bit16u reloctable;
|
Bit16u reloctable;
|
||||||
Bit16u overlay;
|
Bit16u overlay;
|
||||||
};
|
}
|
||||||
|
#if defined (_MSC_VER)
|
||||||
|
;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
#else
|
||||||
|
__attribute__ ((packed));
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAGIC1 0x5a4d
|
#define MAGIC1 0x5a4d
|
||||||
#define MAGIC2 0x4d5a
|
#define MAGIC2 0x4d5a
|
||||||
@ -58,7 +64,7 @@ struct EXE_Header {
|
|||||||
|
|
||||||
|
|
||||||
bool DOS_Terminate(bool tsr) {
|
bool DOS_Terminate(bool tsr) {
|
||||||
PSP * psp=(PSP *)real_off(dos.psp,0);
|
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||||
if (!tsr) {
|
if (!tsr) {
|
||||||
/* Free Files owned by process */
|
/* Free Files owned by process */
|
||||||
for (Bit16u i=0;i<psp->max_files;i++) {
|
for (Bit16u i=0;i<psp->max_files;i++) {
|
||||||
@ -67,16 +73,16 @@ bool DOS_Terminate(bool tsr) {
|
|||||||
DOS_FreeProcessMemory(dos.psp);
|
DOS_FreeProcessMemory(dos.psp);
|
||||||
};
|
};
|
||||||
dos.psp=psp->psp_parent;
|
dos.psp=psp->psp_parent;
|
||||||
PSP * oldpsp=(PSP *)real_off(dos.psp,0);
|
PSP * oldpsp=(PSP *)HostMake(dos.psp,0);
|
||||||
/* Restore the DTA */
|
/* Restore the DTA */
|
||||||
dos.dta=psp->dta;
|
dos.dta=psp->dta;
|
||||||
/* Restore the old CS:IP from int 22h */
|
/* Restore the old CS:IP from int 22h */
|
||||||
RealPt old22;
|
RealPt old22;
|
||||||
old22=RealGetVec(0x22);
|
old22=RealGetVec(0x22);
|
||||||
SetSegment_16(cs,RealSeg(old22));
|
SegSet16(cs,RealSeg(old22));
|
||||||
reg_ip=RealOff(old22);
|
reg_ip=RealOff(old22);
|
||||||
/* Restore the SS:SP to the previous one */
|
/* Restore the SS:SP to the previous one */
|
||||||
SetSegment_16(ss,RealSeg(oldpsp->stack));
|
SegSet16(ss,RealSeg(oldpsp->stack));
|
||||||
reg_sp=RealOff(oldpsp->stack);
|
reg_sp=RealOff(oldpsp->stack);
|
||||||
/* Restore interrupt 22,23,24 */
|
/* Restore interrupt 22,23,24 */
|
||||||
RealSetVec(0x22,psp->int_22);
|
RealSetVec(0x22,psp->int_22);
|
||||||
@ -91,17 +97,17 @@ bool DOS_Terminate(bool tsr) {
|
|||||||
static bool MakeEnv(char * name,Bit16u * segment) {
|
static bool MakeEnv(char * name,Bit16u * segment) {
|
||||||
|
|
||||||
/* If segment to copy environment is 0 copy the caller's environment */
|
/* If segment to copy environment is 0 copy the caller's environment */
|
||||||
PSP * psp=(PSP *)real_off(dos.psp,0);
|
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||||
Bit8u * envread,*envwrite;
|
Bit8u * envread,*envwrite;
|
||||||
Bit16u envsize=1;
|
Bit16u envsize=1;
|
||||||
bool parentenv=true;
|
bool parentenv=true;
|
||||||
|
|
||||||
if (*segment==0) {
|
if (*segment==0) {
|
||||||
if (!psp->environment) parentenv=false; //environment seg=0
|
if (!psp->environment) parentenv=false; //environment seg=0
|
||||||
envread=real_off(psp->environment,0);
|
envread=HostMake(psp->environment,0);
|
||||||
} else {
|
} else {
|
||||||
if (!*segment) parentenv=false; //environment seg=0
|
if (!*segment) parentenv=false; //environment seg=0
|
||||||
envread=real_off(*segment,0);
|
envread=HostMake(*segment,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO Make a good DOS first psp
|
//TODO Make a good DOS first psp
|
||||||
@ -117,7 +123,7 @@ static bool MakeEnv(char * name,Bit16u * segment) {
|
|||||||
}
|
}
|
||||||
Bit16u size=long2para(envsize+ENV_KEEPFREE);
|
Bit16u size=long2para(envsize+ENV_KEEPFREE);
|
||||||
if (!DOS_AllocateMemory(segment,&size)) return false;
|
if (!DOS_AllocateMemory(segment,&size)) return false;
|
||||||
envwrite=real_off(*segment,0);
|
envwrite=HostMake(*segment,0);
|
||||||
if (parentenv) {
|
if (parentenv) {
|
||||||
bmemcpy(envwrite,envread,envsize);
|
bmemcpy(envwrite,envread,envsize);
|
||||||
envwrite+=envsize;
|
envwrite+=envsize;
|
||||||
@ -127,12 +133,12 @@ static bool MakeEnv(char * name,Bit16u * segment) {
|
|||||||
*((Bit16u *) envwrite)=1;
|
*((Bit16u *) envwrite)=1;
|
||||||
envwrite+=2;
|
envwrite+=2;
|
||||||
//TODO put the filename here
|
//TODO put the filename here
|
||||||
return DOS_Canonicalize(name,envwrite);
|
return DOS_Canonicalize(name,(char *)envwrite);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool DOS_NewPSP(Bit16u pspseg) {
|
bool DOS_NewPSP(Bit16u pspseg) {
|
||||||
PSP * newpsp=(PSP *)real_off(pspseg,0);
|
PSP * newpsp=(PSP *)HostMake(pspseg,0);
|
||||||
PSP * prevpsp=(PSP *)real_off(dos.psp,0);
|
PSP * prevpsp=(PSP *)HostMake(dos.psp,0);
|
||||||
|
|
||||||
memset((void *)newpsp,0,sizeof(PSP));
|
memset((void *)newpsp,0,sizeof(PSP));
|
||||||
newpsp->exit[0]=0xcd;newpsp->exit[1]=0x20;
|
newpsp->exit[0]=0xcd;newpsp->exit[1]=0x20;
|
||||||
@ -163,11 +169,11 @@ bool DOS_NewPSP(Bit16u pspseg) {
|
|||||||
|
|
||||||
static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
|
static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
|
||||||
|
|
||||||
PSP * psp=(PSP *)real_off(pspseg,0);
|
PSP * psp=(PSP *)HostMake(pspseg,0);
|
||||||
/* Fix the PSP index of this MCB */
|
/* Fix the PSP index of this MCB */
|
||||||
MCB * pspmcb=(MCB *)real_off(pspseg-1,0);
|
MCB * pspmcb=(MCB *)HostMake(pspseg-1,0);
|
||||||
pspmcb->psp_segment=pspseg;
|
pspmcb->psp_segment=pspseg;
|
||||||
MCB * envmcb=(MCB *)real_off(envseg-1,0);
|
MCB * envmcb=(MCB *)HostMake(envseg-1,0);
|
||||||
envmcb->psp_segment=pspseg;
|
envmcb->psp_segment=pspseg;
|
||||||
|
|
||||||
memset((void *)psp,0,sizeof(PSP));
|
memset((void *)psp,0,sizeof(PSP));
|
||||||
@ -204,7 +210,7 @@ static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void SetupCMDLine(Bit16u pspseg,ParamBlock * block) {
|
static void SetupCMDLine(Bit16u pspseg,ParamBlock * block) {
|
||||||
PSP * psp=(PSP *)real_off(pspseg,0);
|
PSP * psp=(PSP *)HostMake(pspseg,0);
|
||||||
|
|
||||||
if (block->exec.cmdtail) {
|
if (block->exec.cmdtail) {
|
||||||
memcpy((void *)&psp->cmdtail,(void *)Real2Host(block->exec.cmdtail),128);
|
memcpy((void *)&psp->cmdtail,(void *)Real2Host(block->exec.cmdtail),128);
|
||||||
@ -226,7 +232,7 @@ static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) {
|
|||||||
Bit16u envseg,comseg;
|
Bit16u envseg,comseg;
|
||||||
Bit32u pos;
|
Bit32u pos;
|
||||||
|
|
||||||
PSP * callpsp=(PSP *)real_off(dos.psp,0);
|
PSP * callpsp=(PSP *)HostMake(dos.psp,0);
|
||||||
|
|
||||||
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
|
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
|
||||||
if (flag!=OVERLAY) {
|
if (flag!=OVERLAY) {
|
||||||
@ -252,9 +258,9 @@ static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) {
|
|||||||
DOS_SeekFile(fhandle,&pos,0);
|
DOS_SeekFile(fhandle,&pos,0);
|
||||||
readsize=0xffff-256;
|
readsize=0xffff-256;
|
||||||
if (flag==OVERLAY) {
|
if (flag==OVERLAY) {
|
||||||
DOS_ReadFile(fhandle,real_host(comseg,0),&readsize);
|
DOS_ReadFile(fhandle,HostMake(comseg,0),&readsize);
|
||||||
} else {
|
} else {
|
||||||
DOS_ReadFile(fhandle,real_host(comseg,256),&readsize);
|
DOS_ReadFile(fhandle,HostMake(comseg,256),&readsize);
|
||||||
}
|
}
|
||||||
DOS_CloseFile(fhandle);
|
DOS_CloseFile(fhandle);
|
||||||
if (flag==OVERLAY) /* Everything what should be done for Overlays */
|
if (flag==OVERLAY) /* Everything what should be done for Overlays */
|
||||||
@ -262,19 +268,19 @@ static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) {
|
|||||||
SetupPSP(comseg,size,envseg);
|
SetupPSP(comseg,size,envseg);
|
||||||
SetupCMDLine(comseg,block);
|
SetupCMDLine(comseg,block);
|
||||||
/* Setup termination Address */
|
/* Setup termination Address */
|
||||||
RealSetVec(0x22,RealMake(Segs[cs].value,reg_ip));
|
RealSetVec(0x22,RealMakeSeg(cs,reg_ip));
|
||||||
/* Everything setup somewhat setup CS:IP and SS:SP */
|
/* Everything setup somewhat setup CS:IP and SS:SP */
|
||||||
/* First save the SS:SP of program that called execute */
|
/* First save the SS:SP of program that called execute */
|
||||||
callpsp->stack=RealMake(Segs[ss].value,reg_sp);
|
callpsp->stack=RealMakeSeg(ss,reg_sp);
|
||||||
/* Clear out first Stack entry to point to int 20h at psp:0 */
|
/* Clear out first Stack entry to point to int 20h at psp:0 */
|
||||||
real_writew(comseg,0xfffe,0);
|
real_writew(comseg,0xfffe,0);
|
||||||
dos.psp=comseg;
|
dos.psp=comseg;
|
||||||
switch (flag) {
|
switch (flag) {
|
||||||
case LOADNGO:
|
case LOADNGO:
|
||||||
SetSegment_16(cs,comseg);
|
SegSet16(cs,comseg);
|
||||||
SetSegment_16(ss,comseg);
|
SegSet16(ss,comseg);
|
||||||
SetSegment_16(ds,comseg);
|
SegSet16(ds,comseg);
|
||||||
SetSegment_16(es,comseg);
|
SegSet16(es,comseg);
|
||||||
flags.intf=true;
|
flags.intf=true;
|
||||||
reg_ip=0x100;
|
reg_ip=0x100;
|
||||||
reg_sp=0xFFFE;
|
reg_sp=0xFFFE;
|
||||||
@ -291,7 +297,7 @@ static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) {
|
static bool EXE_Load(char * name,ParamBlock* _block,Bit8u flag) {
|
||||||
|
|
||||||
EXE_Header header;
|
EXE_Header header;
|
||||||
Bit16u fhandle;Bit32u i;
|
Bit16u fhandle;Bit32u i;
|
||||||
@ -299,12 +305,17 @@ static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) {
|
|||||||
Bit16u envseg,pspseg,exeseg;
|
Bit16u envseg,pspseg,exeseg;
|
||||||
Bit32u imagesize,headersize;
|
Bit32u imagesize,headersize;
|
||||||
|
|
||||||
PSP * callpsp=(PSP *)real_off(dos.psp,0);
|
// During loading process, th param-block-mem might be overwritten (HostPt!) and
|
||||||
|
// therefore change the relocation address, so save these values.
|
||||||
|
ParamBlock block;
|
||||||
|
memcpy(&block,_block,sizeof(ParamBlock));
|
||||||
|
|
||||||
|
PSP * callpsp=(PSP *)HostMake(dos.psp,0);
|
||||||
|
|
||||||
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
|
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
|
||||||
if (flag!=OVERLAY) {
|
if (flag!=OVERLAY) {
|
||||||
/* Allocate a new Environment */
|
/* Allocate a new Environment */
|
||||||
envseg=block->exec.envseg;
|
envseg=block.exec.envseg;
|
||||||
if (!MakeEnv(name,&envseg)) return false;
|
if (!MakeEnv(name,&envseg)) return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -339,15 +350,15 @@ static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SetupPSP(pspseg,size,envseg);
|
SetupPSP(pspseg,size,envseg);
|
||||||
SetupCMDLine(pspseg,block);
|
SetupCMDLine(pspseg,&block);
|
||||||
exeseg=pspseg+16;
|
exeseg=pspseg+16;
|
||||||
} else {
|
} else {
|
||||||
/* For OVERLAY */
|
/* For OVERLAY */
|
||||||
exeseg=block->overlay.loadseg;
|
exeseg=block.overlay.loadseg;
|
||||||
}
|
}
|
||||||
/* Load the image in 32k blocks */
|
/* Load the image in 32k blocks */
|
||||||
DOS_SeekFile(fhandle,&headersize,0);
|
DOS_SeekFile(fhandle,&headersize,0);
|
||||||
Bit8u * imageoff=real_off(exeseg,0);
|
Bit8u * imageoff=HostMake(exeseg,0);
|
||||||
//TODO File size checking and remove size
|
//TODO File size checking and remove size
|
||||||
// Remove psp size
|
// Remove psp size
|
||||||
// imagesize=256;
|
// imagesize=256;
|
||||||
@ -378,7 +389,7 @@ static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) {
|
|||||||
PhysPt address=Real2Phys(RealMake(RealSeg(reloc)+exeseg,RealOff(reloc)));
|
PhysPt address=Real2Phys(RealMake(RealSeg(reloc)+exeseg,RealOff(reloc)));
|
||||||
Bit16u change=mem_readw(address);
|
Bit16u change=mem_readw(address);
|
||||||
if (flag==OVERLAY) {
|
if (flag==OVERLAY) {
|
||||||
change+=block->overlay.relocation;
|
change+=block.overlay.relocation;
|
||||||
} else {
|
} else {
|
||||||
change+=exeseg;
|
change+=exeseg;
|
||||||
};
|
};
|
||||||
@ -389,15 +400,15 @@ static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) {
|
|||||||
if (flag==OVERLAY) return true;
|
if (flag==OVERLAY) return true;
|
||||||
|
|
||||||
/* Setup termination Address */
|
/* Setup termination Address */
|
||||||
RealSetVec(0x22,RealMake(Segs[cs].value,reg_ip));
|
RealSetVec(0x22,RealMakeSeg(cs,reg_ip));
|
||||||
/* Start up the actual EXE if we need to */
|
/* Start up the actual EXE if we need to */
|
||||||
//TODO check for load and return
|
//TODO check for load and return
|
||||||
callpsp->stack=RealMake(Segs[ss].value,reg_sp);
|
callpsp->stack=RealMakeSeg(ss,reg_sp);
|
||||||
dos.psp=pspseg;
|
dos.psp=pspseg;
|
||||||
SetSegment_16(cs,exeseg+header.initCS);
|
SegSet16(cs,exeseg+header.initCS);
|
||||||
SetSegment_16(ss,exeseg+header.initSS);
|
SegSet16(ss,exeseg+header.initSS);
|
||||||
SetSegment_16(ds,pspseg);
|
SegSet16(ds,pspseg);
|
||||||
SetSegment_16(es,pspseg);
|
SegSet16(es,pspseg);
|
||||||
reg_ip=header.initIP;
|
reg_ip=header.initIP;
|
||||||
reg_sp=header.initSP;
|
reg_sp=header.initSP;
|
||||||
reg_ax=0;
|
reg_ax=0;
|
||||||
|
@ -18,11 +18,15 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "dos_inc.h"
|
#include "dos_inc.h"
|
||||||
#include "drives.h"
|
#include "drives.h"
|
||||||
|
#include "cross.h"
|
||||||
|
|
||||||
#define DOS_FILESTART 4
|
#define DOS_FILESTART 4
|
||||||
|
|
||||||
@ -37,7 +41,7 @@ Bit8u DOS_GetDefaultDrive(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DOS_SetDefaultDrive(Bit8u drive) {
|
void DOS_SetDefaultDrive(Bit8u drive) {
|
||||||
CurrentDrive=drive;
|
if (drive<=DOS_DRIVES) CurrentDrive=drive;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
|
bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
|
||||||
@ -46,7 +50,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
|
|||||||
Bit32u r=0;Bit32u w=0;Bit32u namestart=0;
|
Bit32u r=0;Bit32u w=0;Bit32u namestart=0;
|
||||||
bool hasdrive=false;
|
bool hasdrive=false;
|
||||||
*drive=CurrentDrive;
|
*drive=CurrentDrive;
|
||||||
char tempdir[DOS_NAMELENGTH];
|
char tempdir[128];
|
||||||
//TODO Maybe check for illegal characters
|
//TODO Maybe check for illegal characters
|
||||||
while (name[r]!=0 && (r<DOS_PATHLENGTH)) {
|
while (name[r]!=0 && (r<DOS_PATHLENGTH)) {
|
||||||
Bit8u c=name[r++];
|
Bit8u c=name[r++];
|
||||||
@ -133,14 +137,14 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DOS_GetCurrentDir(Bit8u drive,Bit8u * buffer) {
|
bool DOS_GetCurrentDir(Bit8u drive,char * buffer) {
|
||||||
if (drive==0) drive=DOS_GetDefaultDrive();
|
if (drive==0) drive=DOS_GetDefaultDrive();
|
||||||
else drive--;
|
else drive--;
|
||||||
if ((drive>DOS_DRIVES) || (!Drives[drive])) {
|
if ((drive>DOS_DRIVES) || (!Drives[drive])) {
|
||||||
DOS_SetError(DOSERR_INVALID_DRIVE);
|
DOS_SetError(DOSERR_INVALID_DRIVE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
strcpy((char *) buffer,Drives[drive]->curdir);
|
strcpy(buffer,Drives[drive]->curdir);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +269,7 @@ bool DOS_CloseFile(Bit16u entry) {
|
|||||||
};
|
};
|
||||||
//TODO Figure this out with devices :)
|
//TODO Figure this out with devices :)
|
||||||
|
|
||||||
PSP * psp=(PSP *)real_off(dos.psp,0);
|
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||||
Bit8u * table=Real2Host(psp->file_table);
|
Bit8u * table=Real2Host(psp->file_table);
|
||||||
table[entry]=0xFF;
|
table[entry]=0xFF;
|
||||||
/* Devices won't allow themselves to be closed or killed */
|
/* Devices won't allow themselves to be closed or killed */
|
||||||
@ -278,7 +282,7 @@ bool DOS_CloseFile(Bit16u entry) {
|
|||||||
|
|
||||||
bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
|
bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
|
||||||
char fullname[DOS_PATHLENGTH];Bit8u drive;
|
char fullname[DOS_PATHLENGTH];Bit8u drive;
|
||||||
PSP * psp=(PSP *)real_off(dos.psp,0);
|
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||||
if (!DOS_MakeName(name,fullname,&drive)) return false;
|
if (!DOS_MakeName(name,fullname,&drive)) return false;
|
||||||
/* Check for a free file handle */
|
/* Check for a free file handle */
|
||||||
Bit8u handle=DOS_FILES;Bit8u i;
|
Bit8u handle=DOS_FILES;Bit8u i;
|
||||||
@ -316,7 +320,7 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
|
|||||||
|
|
||||||
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
|
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
|
||||||
/* First check for devices */
|
/* First check for devices */
|
||||||
PSP * psp=(PSP *)real_off(dos.psp,0);
|
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||||
Bit8u handle=DOS_FindDevice((char *)name);
|
Bit8u handle=DOS_FindDevice((char *)name);
|
||||||
bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i;
|
bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i;
|
||||||
if (handle!=255) {
|
if (handle!=255) {
|
||||||
@ -377,7 +381,7 @@ bool DOS_GetFileAttr(char * name,Bit16u * attr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DOS_Canonicalize(char * name,Bit8u * big) {
|
bool DOS_Canonicalize(char * name,char * big) {
|
||||||
//TODO Add Better support for devices and shit but will it be needed i doubt it :)
|
//TODO Add Better support for devices and shit but will it be needed i doubt it :)
|
||||||
Bit8u drive;
|
Bit8u drive;
|
||||||
char fullname[DOS_PATHLENGTH];
|
char fullname[DOS_PATHLENGTH];
|
||||||
@ -385,7 +389,7 @@ bool DOS_Canonicalize(char * name,Bit8u * big) {
|
|||||||
big[0]=drive+'A';
|
big[0]=drive+'A';
|
||||||
big[1]=':';
|
big[1]=':';
|
||||||
big[2]='\\';
|
big[2]='\\';
|
||||||
strcpy((char *)&big[3],fullname);
|
strcpy(&big[3],fullname);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -409,7 +413,7 @@ bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) {
|
|||||||
DOS_SetError(DOSERR_INVALID_HANDLE);
|
DOS_SetError(DOSERR_INVALID_HANDLE);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
PSP * psp=(PSP *)real_off(dos.psp,0);
|
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||||
Bit8u * table=Real2Host(psp->file_table);
|
Bit8u * table=Real2Host(psp->file_table);
|
||||||
*newentry=0xff;
|
*newentry=0xff;
|
||||||
for (Bit16u i=0;i<psp->max_files;i++) {
|
for (Bit16u i=0;i<psp->max_files;i++) {
|
||||||
@ -426,6 +430,32 @@ bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) {
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) {
|
||||||
|
Bit8u orig=RealHandle(entry);
|
||||||
|
if (orig>=DOS_FILES) {
|
||||||
|
DOS_SetError(DOSERR_INVALID_HANDLE);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if (!Files[orig]) {
|
||||||
|
DOS_SetError(DOSERR_INVALID_HANDLE);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
Bit8u newone=RealHandle(newentry);
|
||||||
|
if (newone>=DOS_FILES) {
|
||||||
|
DOS_SetError(DOSERR_INVALID_HANDLE);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if (Files[newone]) {
|
||||||
|
DOS_CloseFile(newentry);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||||
|
Bit8u * table=Real2Host(psp->file_table);
|
||||||
|
table[newentry]=(Bit8u)entry;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool DOS_CreateTempFile(char * name,Bit16u * entry) {
|
bool DOS_CreateTempFile(char * name,Bit16u * entry) {
|
||||||
|
|
||||||
@ -446,9 +476,11 @@ bool DOS_CreateTempFile(char * name,Bit16u * entry) {
|
|||||||
} while (!DOS_CreateFile(name,0,entry));
|
} while (!DOS_CreateFile(name,0,entry));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
void FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){
|
#if 1
|
||||||
|
static bool FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){
|
||||||
char naam[15];
|
char naam[15];
|
||||||
|
Bit8s teller=0;
|
||||||
Bit8u drive=fcb->Get_drive();
|
Bit8u drive=fcb->Get_drive();
|
||||||
if(drive!=0){
|
if(drive!=0){
|
||||||
naam[0]=(drive-1)+'A';
|
naam[0]=(drive-1)+'A';
|
||||||
@ -457,115 +489,218 @@ void FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){
|
|||||||
else{
|
else{
|
||||||
naam[0]='\0';
|
naam[0]='\0';
|
||||||
};
|
};
|
||||||
char temp[9];
|
char temp[10];
|
||||||
fcb->Get_filename(temp);
|
fcb->Get_filename(temp);
|
||||||
temp[9]='.';
|
temp[8]='.';
|
||||||
strncat(naam,temp,9);
|
temp[9]='\0';
|
||||||
char ext[3];
|
strcat(naam,temp);
|
||||||
|
char ext[4];
|
||||||
fcb->Get_ext(ext);
|
fcb->Get_ext(ext);
|
||||||
if(drive!=0) {
|
ext[3]='\0';
|
||||||
strncat(&naam[11],ext,3);
|
strcat(naam,ext);
|
||||||
naam[14]='\0';
|
return DOS_MakeName(naam,outname, outdrive);
|
||||||
}else{
|
}
|
||||||
strncat(&naam[9],ext,3);
|
#define FCB_SEP ":.;,=+"
|
||||||
naam[12]='\0';
|
#define ILLEGAL ":.;,=+ \t/\"[]<>|"
|
||||||
};
|
|
||||||
DOS_MakeName(naam,outname, outdrive);
|
static bool isvalid(const char* in){
|
||||||
return;
|
|
||||||
|
const char ill[]=ILLEGAL;
|
||||||
|
return (Bit8u(*in)>0x1F) && (strchr(ill,*in)==0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vullen (char* veld,char* pveld){
|
||||||
|
for(Bitu i=(pveld-veld);i<strlen(veld);i++){
|
||||||
|
*(veld+i)='?';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change){
|
||||||
|
char* backup;
|
||||||
|
backup=string;
|
||||||
|
DOS_FCB fcb(seg,offset);
|
||||||
|
Bit8u retwaarde=0;
|
||||||
|
char naam[9]=" ";
|
||||||
|
char ext[4]=" ";
|
||||||
|
if(parser & 1) { //ignore leading seperator
|
||||||
|
char sep[] = FCB_SEP;
|
||||||
|
char a[2];
|
||||||
|
a[0]= *string;a[1]='\0';
|
||||||
|
if (strcspn(a,sep)==0) string++;
|
||||||
|
}
|
||||||
|
if((!(parser &4)) ==true){ // fill name with spaces if no name
|
||||||
|
fcb.Set_filename(naam);
|
||||||
|
}
|
||||||
|
if((!(parser &8)) ==true){ // fill ext with spaces if no ext
|
||||||
|
fcb.Set_ext(ext);
|
||||||
|
}
|
||||||
|
if((parser & 2)==false) fcb.Set_drive(0); //Set allready the defaultdrive (Will stay set when it's not specified)
|
||||||
|
// strip leading spaces
|
||||||
|
while((*string==' ')||(*string=='\t')) string++;
|
||||||
|
if( *(string+1)==':') {
|
||||||
|
Bit8u drive=toupper(*string);
|
||||||
|
if( (drive>'Z') | (drive<'A') | (Drives[drive-'A']==NULL)) {
|
||||||
|
*change=string-backup;
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
fcb.Set_drive(drive-'A'+1);
|
||||||
|
string+=2;
|
||||||
|
}
|
||||||
|
//startparsing
|
||||||
|
char* pnaam=naam;
|
||||||
|
while(isvalid(string)==true) {
|
||||||
|
if(*string=='*'){
|
||||||
|
vullen(naam,pnaam); //fill with ????
|
||||||
|
string++;
|
||||||
|
retwaarde=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pnaam=*string;
|
||||||
|
pnaam++;
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
fcb.Set_filename(naam);
|
||||||
|
if((*string=='.')==false) {
|
||||||
|
*change=string-backup;
|
||||||
|
return retwaarde;
|
||||||
|
}
|
||||||
|
//extension exist
|
||||||
|
string++;
|
||||||
|
char* pext=ext;
|
||||||
|
while(isvalid(string)==true) {
|
||||||
|
if(*string=='*'){
|
||||||
|
vullen(ext,pext); //fill with ????
|
||||||
|
string++;
|
||||||
|
retwaarde=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pext=*string;
|
||||||
|
pext++;
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
fcb.Set_ext(ext);
|
||||||
|
*change=string-backup;
|
||||||
|
return retwaarde;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
bool DOS_FCBOpen(Bit16u seg,Bit16u offset) {
|
bool DOS_FCBOpen(Bit16u seg,Bit16u offset) {
|
||||||
DOS_FCB fcb(seg,offset);
|
DOS_FCB fcb(seg,offset);
|
||||||
Bit8u drive;
|
Bit8u drive;
|
||||||
char fullname[DOS_PATHLENGTH];
|
char fullname[DOS_PATHLENGTH];
|
||||||
FCB_MakeName (&fcb, fullname, &drive);
|
if(!FCB_MakeName (&fcb, fullname, &drive)) return false;
|
||||||
if(DOS_FileExists(fullname)==false) return false;
|
if(!Drives[drive]->FileExists(fullname)) return false; //not really needed as stat will error.
|
||||||
|
|
||||||
|
|
||||||
struct stat stat_block;
|
struct stat stat_block;
|
||||||
stat(fullname, &stat_block);
|
if(!Drives[drive]->FileStat(fullname, &stat_block)) return false;
|
||||||
fcb.Set_filesize((Bit32u)stat_block.st_size);
|
fcb.Set_filesize((Bit32u)stat_block.st_size);
|
||||||
Bit16u constant =0;
|
Bit16u constant = 0;
|
||||||
fcb.Set_current_block(constant);
|
fcb.Set_current_block(constant);
|
||||||
constant=0x80;
|
constant=0x80;
|
||||||
fcb.Set_record_size(constant);
|
fcb.Set_record_size(constant);
|
||||||
|
|
||||||
struct tm *time;
|
struct tm *time;
|
||||||
time=localtime(&stat_block.st_mtime);
|
if((time=localtime(&stat_block.st_mtime))!=0){
|
||||||
|
|
||||||
constant=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */
|
constant=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */
|
||||||
fcb->Set_time(constant);
|
fcb.Set_time(constant);
|
||||||
constant=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
|
constant=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
|
||||||
fcb->Set_date(constant);
|
fcb.Set_date(constant);
|
||||||
fcb->Set_drive(drive +1);
|
}
|
||||||
|
else{
|
||||||
|
constant=6;
|
||||||
|
fcb.Set_time(constant);
|
||||||
|
constant=4;
|
||||||
|
fcb.Set_date(constant);
|
||||||
|
}
|
||||||
|
fcb.Set_drive(drive +1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCB_Close(void)
|
bool DOS_FCBClose(Bit16u seg,Bit16u offset)
|
||||||
{ return true;}
|
{ DOS_FCB fcb(seg,offset);
|
||||||
|
Bit8u drive;
|
||||||
|
char fullname[DOS_PATHLENGTH];
|
||||||
|
if(!FCB_MakeName (&fcb, fullname, &drive)) return false;
|
||||||
|
if(!Drives[drive]->FileExists(fullname)) return false;
|
||||||
|
|
||||||
|
return true;}
|
||||||
|
|
||||||
bool FCB_FindFirst(Bit16u seg,Bit16u offset)
|
bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset)
|
||||||
{FCB* fcb = new FCB(seg,offset);
|
{
|
||||||
|
DOS_FCB* fcb = new DOS_FCB(seg,offset);
|
||||||
|
Bit8u drive;
|
||||||
|
Bitu i;
|
||||||
|
char fullname[DOS_PATHLENGTH];
|
||||||
|
FCB_MakeName (fcb, fullname, &drive);
|
||||||
|
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
|
||||||
|
dtablock->sattr=DOS_ATTR_ARCHIVE;
|
||||||
|
dtablock->sdrive=drive;
|
||||||
|
|
||||||
|
if(Drives[drive]->FindFirst(fullname,dtablock)==false) return false;
|
||||||
|
|
||||||
|
char naam[9];
|
||||||
|
char ext[4];
|
||||||
|
char * point=strrchr(dtablock->name,'.');
|
||||||
|
if(point==NULL|| *(point+1)=='\0') {
|
||||||
|
ext[0]=' ';
|
||||||
|
ext[1]=' ';
|
||||||
|
ext[2]=' ';
|
||||||
|
}else{
|
||||||
|
strcpy(ext,(point+1));
|
||||||
|
i=strlen((point+1));
|
||||||
|
while(i!=3) {ext[i]=' ';i++;}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(point!=NULL) *point='\0';
|
||||||
|
|
||||||
|
strcpy (naam,dtablock->name);
|
||||||
|
i=strlen(dtablock->name);
|
||||||
|
while(i!=8) {naam[i]=' '; i++;}
|
||||||
|
delete fcb;
|
||||||
|
DOS_FCB* fcbout= new DOS_FCB((PhysPt)Real2Phys(dos.dta));
|
||||||
|
fcbout->Set_drive(drive +1);
|
||||||
|
fcbout->Set_filename(naam);
|
||||||
|
fcbout->Set_ext(ext);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool DOS_FCBFindNext(Bit16u seg,Bit16u offset)
|
||||||
|
{
|
||||||
|
DOS_FCB* fcb = new DOS_FCB(seg,offset);
|
||||||
Bit8u drive;
|
Bit8u drive;
|
||||||
Bitu i;
|
Bitu i;
|
||||||
char fullname[DOS_PATHLENGTH];
|
char fullname[DOS_PATHLENGTH];
|
||||||
FCB_MakeName (fcb, fullname, &drive);
|
FCB_MakeName (fcb, fullname, &drive);
|
||||||
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
|
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
|
||||||
if(Drives[drive]->FindFirst(fullname,dtablock)==false) return false;
|
dtablock->sattr=DOS_ATTR_ARCHIVE;
|
||||||
|
dtablock->sdrive=drive;
|
||||||
char naam[8];
|
|
||||||
char ext[3];
|
|
||||||
char * point=strrchr(dtablock->name,'.');
|
|
||||||
if(point==NULL|| *(point+1)=='\0') {
|
|
||||||
ext[0]=' ';
|
|
||||||
ext[1]=' ';
|
|
||||||
ext[2]=' ';
|
|
||||||
}else
|
|
||||||
{strcpy(ext,point+1);
|
|
||||||
Bitu i;
|
|
||||||
i=strlen(point+1);
|
|
||||||
while(i!=3) ext[i-1]=' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(point!=NULL) *point='\0';
|
|
||||||
|
|
||||||
strcpy (naam,dtablock->name);
|
|
||||||
i=strlen(dtablock->name);
|
|
||||||
while(i!=8) naam[i-1]=' ';
|
|
||||||
FCB* fcbout= new FCB((PhysPt)Real2Host(dos.dta));
|
|
||||||
fcbout->Set_drive(drive +1);
|
|
||||||
fcbout->Set_filename(naam);
|
|
||||||
fcbout->Set_ext(ext);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool FCB_FindNext(Bit16u seg,Bit16u offset)
|
|
||||||
{FCB* fcb = new FCB(seg,offset);
|
|
||||||
Bit8u drive;
|
|
||||||
Bitu i;
|
|
||||||
char fullname[DOS_PATHLENGTH];
|
|
||||||
FCB_MakeName (fcb, fullname, &drive);
|
|
||||||
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
|
|
||||||
if(Drives[dtablock->sdrive]->FindNext(dtablock)==false) return false;
|
if(Drives[dtablock->sdrive]->FindNext(dtablock)==false) return false;
|
||||||
char naam[8];
|
char naam[9];
|
||||||
char ext[3];
|
char ext[4];
|
||||||
char * point=strrchr(dtablock->name,'.');
|
char * point=strrchr(dtablock->name,'.');
|
||||||
if(point==NULL|| *(point+1)=='\0') {
|
if(point==NULL|| *(point+1)=='\0') {
|
||||||
ext[0]=' ';
|
ext[0]=' ';
|
||||||
ext[1]=' ';
|
ext[1]=' ';
|
||||||
ext[2]=' ';
|
ext[2]=' ';
|
||||||
}else
|
}else
|
||||||
{strcpy(ext,point+1);
|
{
|
||||||
Bitu i;
|
strcpy(ext,point+1);
|
||||||
i=strlen(point+1);
|
i=strlen(point+1);
|
||||||
while(i!=3) ext[i-1]=' ';
|
while(i!=3) {ext[i]=' ';i++;}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(point!=NULL) *point='\0';
|
if(point!=NULL) *point='\0';
|
||||||
|
|
||||||
strcpy (naam,dtablock->name);
|
strcpy (naam,dtablock->name);
|
||||||
i=strlen(dtablock->name);
|
i=strlen(dtablock->name);
|
||||||
while(i!=8) naam[i-1]=' ';
|
while(i!=8) {naam[i]=' '; i++;}
|
||||||
FCB* fcbout= new FCB((PhysPt)Real2Host(dos.dta));
|
delete fcb;
|
||||||
|
DOS_FCB* fcbout= new DOS_FCB(Real2Phys(dos.dta));
|
||||||
fcbout->Set_drive(drive +1);
|
fcbout->Set_drive(drive +1);
|
||||||
fcbout->Set_filename(naam);
|
fcbout->Set_filename(naam);
|
||||||
fcbout->Set_ext(ext);
|
fcbout->Set_ext(ext);
|
||||||
@ -575,12 +710,10 @@ bool FCB_FindNext(Bit16u seg,Bit16u offset)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool DOS_FileExists(char * name) {
|
bool DOS_FileExists(char * name) {
|
||||||
Bit16u handle;
|
|
||||||
if (DOS_OpenFile(name,0,&handle)) {
|
char fullname[DOS_PATHLENGTH];Bit8u drive;
|
||||||
DOS_CloseFile(handle);
|
if (!DOS_MakeName(name,fullname,&drive)) return false;
|
||||||
return true;
|
return Drives[drive]->FileExists(fullname);
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,6 +44,21 @@ bool DOS_IOCTL(Bit8u call,Bit16u entry) {
|
|||||||
LOG_DEBUG("DOS:IOCTL:07:Fakes output status is ready for handle %d",handle);
|
LOG_DEBUG("DOS:IOCTL:07:Fakes output status is ready for handle %d",handle);
|
||||||
reg_al=0xff;
|
reg_al=0xff;
|
||||||
return true;
|
return true;
|
||||||
|
case 0x0D: {
|
||||||
|
PhysPt ptr = SegPhys(ds)+reg_dx;
|
||||||
|
Bit8u drive = reg_bl ? reg_bl : DOS_GetDefaultDrive()+1; // A=1, B=2, C=3...
|
||||||
|
switch (reg_cl) {
|
||||||
|
case 0x60 : mem_writeb(ptr ,0x03); // special function
|
||||||
|
mem_writeb(ptr+1,(drive>=3)?0x05:0x14); // fixed disc(5), 1.44 floppy(14)
|
||||||
|
mem_writew(ptr+2,drive>=3); // nonremovable ?
|
||||||
|
mem_writew(ptr+4,0x0000); // num of cylinders
|
||||||
|
mem_writeb(ptr+6,0x00); // media type (00=other type)
|
||||||
|
break;
|
||||||
|
default : LOG_ERROR("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("DOS:IOCTL Call %2X Handle %2X unhandled",reg_al,handle);
|
LOG_ERROR("DOS:IOCTL Call %2X Handle %2X unhandled",reg_al,handle);
|
||||||
return false;
|
return false;
|
||||||
|
@ -29,15 +29,15 @@ static void DOS_CompressMemory(void) {
|
|||||||
MCB * pmcb;MCB * pmcbnext;
|
MCB * pmcb;MCB * pmcbnext;
|
||||||
Bit16u mcb_segment;
|
Bit16u mcb_segment;
|
||||||
mcb_segment=dos.firstMCB;
|
mcb_segment=dos.firstMCB;
|
||||||
pmcb=(MCB *)real_off(mcb_segment,0);
|
pmcb=(MCB *)HostMake(mcb_segment,0);
|
||||||
while (pmcb->type!=0x5a) {
|
while (pmcb->type!=0x5a) {
|
||||||
pmcbnext=pmcbnext=(MCB *)real_off(mcb_segment+pmcb->size+1,0);
|
pmcbnext=pmcbnext=(MCB *)HostMake(mcb_segment+pmcb->size+1,0);
|
||||||
if ((pmcb->psp_segment==0) && (pmcbnext->psp_segment==0)) {
|
if ((pmcb->psp_segment==0) && (pmcbnext->psp_segment==0)) {
|
||||||
pmcb->size+=pmcbnext->size+1;
|
pmcb->size+=pmcbnext->size+1;
|
||||||
pmcb->type=pmcbnext->type;
|
pmcb->type=pmcbnext->type;
|
||||||
} else {
|
} else {
|
||||||
mcb_segment+=pmcb->size+1;
|
mcb_segment+=pmcb->size+1;
|
||||||
pmcb=(MCB *)real_off(mcb_segment,0);
|
pmcb=(MCB *)HostMake(mcb_segment,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,14 +45,14 @@ static void DOS_CompressMemory(void) {
|
|||||||
void DOS_FreeProcessMemory(Bit16u pspseg) {
|
void DOS_FreeProcessMemory(Bit16u pspseg) {
|
||||||
MCB * pmcb;
|
MCB * pmcb;
|
||||||
Bit16u mcb_segment=dos.firstMCB;
|
Bit16u mcb_segment=dos.firstMCB;
|
||||||
pmcb=(MCB *)real_off(mcb_segment,0);
|
pmcb=(MCB *)HostMake(mcb_segment,0);
|
||||||
while (true) {
|
while (true) {
|
||||||
if (pmcb->psp_segment==pspseg) {
|
if (pmcb->psp_segment==pspseg) {
|
||||||
pmcb->psp_segment=MCB_FREE;
|
pmcb->psp_segment=MCB_FREE;
|
||||||
}
|
}
|
||||||
mcb_segment+=pmcb->size+1;
|
mcb_segment+=pmcb->size+1;
|
||||||
if (pmcb->type==0x5a) break;
|
if (pmcb->type==0x5a) break;
|
||||||
pmcb=(MCB *)real_off(mcb_segment,0);
|
pmcb=(MCB *)HostMake(mcb_segment,0);
|
||||||
}
|
}
|
||||||
DOS_CompressMemory();
|
DOS_CompressMemory();
|
||||||
};
|
};
|
||||||
@ -64,7 +64,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
|
|||||||
bool stop=false;mcb_segment=dos.firstMCB;
|
bool stop=false;mcb_segment=dos.firstMCB;
|
||||||
DOS_CompressMemory();
|
DOS_CompressMemory();
|
||||||
while(!stop) {
|
while(!stop) {
|
||||||
pmcb=(MCB *)real_off(mcb_segment,0);
|
pmcb=(MCB *)HostMake(mcb_segment,0);
|
||||||
if (pmcb->psp_segment==0) {
|
if (pmcb->psp_segment==0) {
|
||||||
/* Check for enough free memory in current block */
|
/* Check for enough free memory in current block */
|
||||||
if (pmcb->size<(*blocks)) {
|
if (pmcb->size<(*blocks)) {
|
||||||
@ -78,7 +78,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
/* If so allocate it */
|
/* If so allocate it */
|
||||||
pmcbnext=(MCB *)real_off(mcb_segment+*blocks+1,0);
|
pmcbnext=(MCB *)HostMake(mcb_segment+*blocks+1,0);
|
||||||
pmcbnext->psp_segment=MCB_FREE;
|
pmcbnext->psp_segment=MCB_FREE;
|
||||||
pmcbnext->type=pmcb->type;
|
pmcbnext->type=pmcb->type;
|
||||||
pmcbnext->size=pmcb->size-*blocks-1;
|
pmcbnext->size=pmcb->size-*blocks-1;
|
||||||
@ -105,8 +105,8 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
|
|||||||
bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
|
bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
|
||||||
DOS_CompressMemory();
|
DOS_CompressMemory();
|
||||||
MCB * pmcb,* pmcbnext,* pmcbnew;
|
MCB * pmcb,* pmcbnext,* pmcbnew;
|
||||||
pmcb=(MCB *)real_off(segment-1,0);
|
pmcb=(MCB *)HostMake(segment-1,0);
|
||||||
pmcbnext=(MCB *)real_off(segment+pmcb->size,0);
|
pmcbnext=(MCB *)HostMake(segment+pmcb->size,0);
|
||||||
Bit16u total=pmcb->size;
|
Bit16u total=pmcb->size;
|
||||||
if (pmcb->type!=0x5a) {
|
if (pmcb->type!=0x5a) {
|
||||||
if (pmcbnext->psp_segment==MCB_FREE) {
|
if (pmcbnext->psp_segment==MCB_FREE) {
|
||||||
@ -118,7 +118,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
|
|||||||
pmcb->type=pmcbnext->type;
|
pmcb->type=pmcbnext->type;
|
||||||
}
|
}
|
||||||
pmcb->size=*blocks;
|
pmcb->size=*blocks;
|
||||||
pmcbnew=(MCB *)real_off(segment+*blocks,0);
|
pmcbnew=(MCB *)HostMake(segment+*blocks,0);
|
||||||
pmcbnew->size=total-*blocks-1;
|
pmcbnew->size=total-*blocks-1;
|
||||||
pmcbnew->type=pmcb->type;
|
pmcbnew->type=pmcb->type;
|
||||||
pmcbnew->psp_segment=MCB_FREE;
|
pmcbnew->psp_segment=MCB_FREE;
|
||||||
@ -141,7 +141,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
|
|||||||
bool DOS_FreeMemory(Bit16u segment) {
|
bool DOS_FreeMemory(Bit16u segment) {
|
||||||
//TODO Check if allowed to free this segment
|
//TODO Check if allowed to free this segment
|
||||||
MCB * pmcb;
|
MCB * pmcb;
|
||||||
pmcb=(MCB *)real_off(segment-1,0);
|
pmcb=(MCB *)HostMake(segment-1,0);
|
||||||
pmcb->psp_segment=MCB_FREE;
|
pmcb->psp_segment=MCB_FREE;
|
||||||
DOS_CompressMemory();
|
DOS_CompressMemory();
|
||||||
return true;
|
return true;
|
||||||
@ -153,10 +153,14 @@ bool DOS_FreeMemory(Bit16u segment) {
|
|||||||
void DOS_SetupMemory(void) {
|
void DOS_SetupMemory(void) {
|
||||||
//TODO Maybe allocate some memory for dos transfer buffers
|
//TODO Maybe allocate some memory for dos transfer buffers
|
||||||
//Although i could use bios regions for that for max free low memory
|
//Although i could use bios regions for that for max free low memory
|
||||||
MCB * mcb=(MCB *) real_off(MEM_START,0);
|
MCB * mcb=(MCB *) HostMake(MEM_START,0);
|
||||||
mcb->psp_segment=MCB_FREE; //Free
|
mcb->psp_segment=MCB_FREE; //Free
|
||||||
mcb->size=0x9FFE - MEM_START;
|
mcb->size=0x9FFE - MEM_START;
|
||||||
mcb->type=0x5a; //Last Block
|
mcb->type=0x5a; //Last Block
|
||||||
dos.firstMCB=MEM_START;
|
dos.firstMCB=MEM_START;
|
||||||
|
|
||||||
|
// Create Dos Info Block : maximum size 95 Bytes....
|
||||||
|
dosInfoBlock.SetLocation(DOS_GetMemory(6));
|
||||||
|
dosInfoBlock.SetFirstMCB(RealMake(dos.firstMCB,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,96 +23,101 @@
|
|||||||
#include "support.h"
|
#include "support.h"
|
||||||
#include "drives.h"
|
#include "drives.h"
|
||||||
#include "cross.h"
|
#include "cross.h"
|
||||||
|
#include "regs.h"
|
||||||
|
#include "callback.h"
|
||||||
|
|
||||||
class MOUNT : public Program {
|
class MOUNT : public Program {
|
||||||
public:
|
public:
|
||||||
MOUNT(PROGRAM_Info * program_info);
|
MOUNT(PROGRAM_Info * program_info):Program(program_info){};
|
||||||
void Run(void);
|
void Run(void){
|
||||||
};
|
/* Parse the command line */
|
||||||
|
/* if the command line is empty show current mounts */
|
||||||
|
if (!*prog_info->cmd_line) {
|
||||||
MOUNT::MOUNT(PROGRAM_Info * info):Program(info) {
|
WriteOut("Current mounted drives are\n");
|
||||||
|
for (int d=0;d<DOS_DRIVES;d++) {
|
||||||
}
|
if (Drives[d]) {
|
||||||
|
WriteOut("Drive %c is mounted as %s\n",d+'A',Drives[d]->GetInfo());
|
||||||
|
}
|
||||||
void MOUNT::Run(void) {
|
|
||||||
/* Parse the command line */
|
|
||||||
/* if the command line is empty show current mounts */
|
|
||||||
|
|
||||||
if (!*prog_info->cmd_line) {
|
|
||||||
WriteOut("Current mounted drives are\n");
|
|
||||||
for (int d=0;d<DOS_DRIVES;d++) {
|
|
||||||
if (Drives[d]) {
|
|
||||||
WriteOut("Drive %c is mounted as %s\n",d+'A',Drives[d]->GetInfo());
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char drive;
|
char drive; drive=toupper(*prog_info->cmd_line);
|
||||||
drive=toupper(*prog_info->cmd_line);
|
|
||||||
char * dir=strchr(prog_info->cmd_line,' ');
|
|
||||||
if (dir) {
|
|
||||||
if (!*dir) dir=0;
|
|
||||||
else dir=trim(dir);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!isalpha(drive) || !dir) {
|
char * dir=strchr(prog_info->cmd_line,' '); if (dir) {
|
||||||
WriteOut("Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n");
|
if (!*dir) dir=0;
|
||||||
return;
|
else dir=trim(dir);
|
||||||
};
|
}
|
||||||
struct stat test;
|
if (!isalpha(drive) || !dir) {
|
||||||
if (stat(dir,&test)) {
|
WriteOut("Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n");
|
||||||
WriteOut("Directory %s Doesn't exist",dir);
|
return;
|
||||||
return;
|
};
|
||||||
|
struct stat test;
|
||||||
|
if (stat(dir,&test)) {
|
||||||
|
WriteOut("Directory %s Doesn't exist",dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Not a switch so a normal directory/file */
|
||||||
|
if (!(test.st_mode & S_IFDIR)) {
|
||||||
|
WriteOut("%s isn't a directory",dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Drives[drive-'A']) {
|
||||||
|
WriteOut("Drive %c already mounted with %s\n",drive,Drives[drive-'A']->GetInfo());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char fulldir[DOS_PATHLENGTH];
|
||||||
|
strcpy(fulldir,dir);
|
||||||
|
static char theend[2]={CROSS_FILESPLIT,0};
|
||||||
|
char * last=strrchr(fulldir,CROSS_FILESPLIT);
|
||||||
|
if (!last || *(++last)) strcat(fulldir,theend);
|
||||||
|
Drives[drive-'A']=new localDrive(fulldir);
|
||||||
|
WriteOut("Mounting drive %c as %s\n",drive,fulldir);
|
||||||
}
|
}
|
||||||
/* Not a switch so a normal directory/file */
|
};
|
||||||
if (!(test.st_mode & S_IFDIR)) {
|
|
||||||
WriteOut("%s isn't a directory",dir);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (Drives[drive-'A']) {
|
|
||||||
WriteOut("Drive %c already mounted with %s\n",drive,Drives[drive-'A']->GetInfo());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char fulldir[DOS_PATHLENGTH];
|
|
||||||
strcpy(fulldir,dir);
|
|
||||||
static char theend[2]={CROSS_FILESPLIT,0};
|
|
||||||
char * last=strrchr(fulldir,CROSS_FILESPLIT);
|
|
||||||
if (!last || *(++last)) strcat(fulldir,theend);
|
|
||||||
Drives[drive-'A']=new localDrive(fulldir);
|
|
||||||
WriteOut("Mounting drive %c as %s\n",drive,fulldir);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MOUNT_ProgramStart(PROGRAM_Info * info) {
|
static void MOUNT_ProgramStart(PROGRAM_Info * info) {
|
||||||
MOUNT * tempmount=new MOUNT(info);
|
MOUNT * tempmount=new MOUNT(info);
|
||||||
tempmount->Run();
|
tempmount->Run() ;
|
||||||
delete tempmount;
|
delete tempmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MEM : public Program {
|
class MEM : public Program {
|
||||||
public:
|
public:
|
||||||
MEM(PROGRAM_Info * program_info);
|
MEM(PROGRAM_Info * program_info):Program(program_info){};
|
||||||
void Run(void);
|
void Run(void) {
|
||||||
|
/* Show conventional Memory */
|
||||||
|
WriteOut("\n");
|
||||||
|
Bit16u seg,blocks;blocks=0xffff;
|
||||||
|
DOS_AllocateMemory(&seg,&blocks);
|
||||||
|
WriteOut("%10d Kb free conventional memory\n",blocks*16/1024);
|
||||||
|
/* Test for and show free XMS */
|
||||||
|
reg_ax=0x4300;CALLBACK_RunRealInt(0x2f);
|
||||||
|
if (reg_al==0x80) {
|
||||||
|
reg_ax=0x4310;CALLBACK_RunRealInt(0x2f);
|
||||||
|
Bit16u xms_seg=SegValue(es);Bit16u xms_off=reg_bx;
|
||||||
|
reg_ah=8;
|
||||||
|
CALLBACK_RunRealFar(xms_seg,xms_off);
|
||||||
|
if (!reg_bl) {
|
||||||
|
WriteOut("%10d Kb free extended memory\n",reg_dx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Test for and show free EMS */
|
||||||
|
Bit16u handle;
|
||||||
|
if (DOS_OpenFile("EMMXXXX0",0,&handle)) {
|
||||||
|
DOS_CloseFile(handle);
|
||||||
|
reg_ah=0x42;
|
||||||
|
CALLBACK_RunRealInt(0x67);
|
||||||
|
WriteOut("%10d Kb free expanded memory\n",reg_bx*16);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MEM::MEM(PROGRAM_Info * info):Program(info) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MEM::Run(void) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void MEM_ProgramStart(PROGRAM_Info * info) {
|
static void MEM_ProgramStart(PROGRAM_Info * info) {
|
||||||
MEM mem(info);
|
MEM mem(info);
|
||||||
mem.Run();
|
mem.Run();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -203,7 +208,7 @@ static void UPCASE_ProgramStart(PROGRAM_Info * info) {
|
|||||||
|
|
||||||
void DOS_SetupPrograms(void) {
|
void DOS_SetupPrograms(void) {
|
||||||
PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart);
|
PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart);
|
||||||
// PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart); /*next release */
|
PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart);
|
||||||
#if !defined (WIN32) /* Unix */
|
#if !defined (WIN32) /* Unix */
|
||||||
PROGRAMS_MakeFile("UPCASE.COM",UPCASE_ProgramStart);
|
PROGRAMS_MakeFile("UPCASE.COM",UPCASE_ProgramStart);
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,13 +20,19 @@
|
|||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "dos_inc.h"
|
#include "dos_inc.h"
|
||||||
|
|
||||||
|
#if defined (_MSC_VER)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
struct DOS_TableCase {
|
struct DOS_TableCase {
|
||||||
Bit16u size;
|
Bit16u size;
|
||||||
Bit8u chars[256];
|
Bit8u chars[256];
|
||||||
};
|
}
|
||||||
|
#if defined (_MSC_VER)
|
||||||
|
;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
#else
|
||||||
|
__attribute__ ((packed));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
RealPt DOS_TableUpCase;
|
RealPt DOS_TableUpCase;
|
||||||
|
@ -148,10 +148,14 @@ bool localDrive::FindNext(DTA_FindBlock * dta) {
|
|||||||
dta->attr=tempattr;
|
dta->attr=tempattr;
|
||||||
dta->size=(Bit32u) stat_block.st_size;
|
dta->size=(Bit32u) stat_block.st_size;
|
||||||
struct tm *time;
|
struct tm *time;
|
||||||
time=localtime(&stat_block.st_mtime);
|
if((time=localtime(&stat_block.st_mtime))!=0){
|
||||||
|
|
||||||
dta->time=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */
|
dta->time=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */
|
||||||
dta->date=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
|
dta->date=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
|
||||||
|
}else {
|
||||||
|
dta->time=6;
|
||||||
|
dta->date=4;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,15 +182,17 @@ bool localDrive::MakeDir(char * dir) {
|
|||||||
#if defined (WIN32) /* MS Visual C++ */
|
#if defined (WIN32) /* MS Visual C++ */
|
||||||
int temp=mkdir(newdir);
|
int temp=mkdir(newdir);
|
||||||
#else
|
#else
|
||||||
int temp=mkdir(newdir,0);
|
int temp=mkdir(newdir,0700);
|
||||||
#endif
|
#endif
|
||||||
return (temp==0);
|
// if dir already exists, return success too.
|
||||||
|
return (temp==0) || ((temp!=0) && (errno==EEXIST));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool localDrive::RemoveDir(char * dir) {
|
bool localDrive::RemoveDir(char * dir) {
|
||||||
char newdir[512];
|
char newdir[512];
|
||||||
strcpy(newdir,basedir);
|
strcpy(newdir,basedir);
|
||||||
strcat(newdir,dir);
|
strcat(newdir,dir);
|
||||||
|
CROSS_FILENAME(newdir);
|
||||||
int temp=rmdir(newdir);
|
int temp=rmdir(newdir);
|
||||||
return (temp==0);
|
return (temp==0);
|
||||||
}
|
}
|
||||||
@ -195,6 +201,7 @@ bool localDrive::TestDir(char * dir) {
|
|||||||
char newdir[512];
|
char newdir[512];
|
||||||
strcpy(newdir,basedir);
|
strcpy(newdir,basedir);
|
||||||
strcat(newdir,dir);
|
strcat(newdir,dir);
|
||||||
|
CROSS_FILENAME(newdir);
|
||||||
int temp=access(newdir,F_OK);
|
int temp=access(newdir,F_OK);
|
||||||
return (temp==0);
|
return (temp==0);
|
||||||
}
|
}
|
||||||
@ -206,8 +213,8 @@ bool localDrive::Rename(char * oldname,char * newname) {
|
|||||||
CROSS_FILENAME(newold);
|
CROSS_FILENAME(newold);
|
||||||
char newnew[512];
|
char newnew[512];
|
||||||
strcpy(newnew,basedir);
|
strcpy(newnew,basedir);
|
||||||
strcat(newnew,newnew);
|
strcat(newnew,newname);
|
||||||
CROSS_FILENAME(newname);
|
CROSS_FILENAME(newnew);
|
||||||
int temp=rename(newold,newnew);
|
int temp=rename(newold,newnew);
|
||||||
return (temp==0);
|
return (temp==0);
|
||||||
|
|
||||||
@ -223,6 +230,28 @@ bool localDrive::FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool localDrive::FileExists(const char* name) const {
|
||||||
|
char newname[512];
|
||||||
|
strcpy(newname,basedir);
|
||||||
|
strcat(newname,name);
|
||||||
|
CROSS_FILENAME(newname);
|
||||||
|
FILE* Temp=fopen(newname,"rb");
|
||||||
|
if(Temp==NULL) return false;
|
||||||
|
fclose(Temp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool localDrive::FileStat(const char* name, struct stat* const stat_block) const {
|
||||||
|
char newname[512];
|
||||||
|
strcpy(newname,basedir);
|
||||||
|
strcat(newname,name);
|
||||||
|
CROSS_FILENAME(newname);
|
||||||
|
if(stat(newname,stat_block)!=0) return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
localDrive::localDrive(char * startdir) {
|
localDrive::localDrive(char * startdir) {
|
||||||
strcpy(basedir,startdir);
|
strcpy(basedir,startdir);
|
||||||
@ -237,10 +266,15 @@ bool localFile::Read(Bit8u * data,Bit16u * size) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool localFile::Write(Bit8u * data,Bit16u * size) {
|
bool localFile::Write(Bit8u * data,Bit16u * size) {
|
||||||
*size=fwrite(data,1,*size,fhandle);
|
if(*size==0){
|
||||||
|
return (!ftruncate(fileno(fhandle),ftell(fhandle)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*size=fwrite(data,1,*size,fhandle);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool localFile::Seek(Bit32u * pos,Bit32u type) {
|
bool localFile::Seek(Bit32u * pos,Bit32u type) {
|
||||||
int seektype;
|
int seektype;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -275,3 +309,4 @@ localFile::localFile(FILE * handle,Bit16u devinfo) {
|
|||||||
info=devinfo;
|
info=devinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,10 +19,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "dos_system.h"
|
#include "dos_system.h"
|
||||||
#include "drives.h"
|
#include "drives.h"
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
#include "cross.h"
|
||||||
|
|
||||||
struct VFILE_Block {
|
struct VFILE_Block {
|
||||||
char * name;
|
char * name;
|
||||||
@ -151,6 +153,32 @@ bool Virtual_Drive::TestDir(char * dir) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Virtual_Drive::FileStat(const char* name, struct stat* const stat_block) const {
|
||||||
|
VFILE_Block * cur_file=first_file;
|
||||||
|
while (cur_file) {
|
||||||
|
if (strcasecmp(name,cur_file->name)==0) {
|
||||||
|
stat_block->st_size=cur_file->size;
|
||||||
|
struct tm tijd;
|
||||||
|
tijd.tm_hour=0;tijd.tm_min=0;tijd.tm_sec=0;
|
||||||
|
tijd.tm_year=80;tijd.tm_mday=6;tijd.tm_mon=0;
|
||||||
|
stat_block->st_mtime=mktime(&tijd);
|
||||||
|
/* more not needed at the moment (fcbopen.....)*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
cur_file=cur_file->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Virtual_Drive::FileExists(const char* name) const {
|
||||||
|
VFILE_Block * cur_file=first_file;
|
||||||
|
while (cur_file) {
|
||||||
|
if (strcasecmp(name,cur_file->name)==0) return true;
|
||||||
|
cur_file=cur_file->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void FillDTABlock(DTA_FindBlock * dta,VFILE_Block * fill_file) {
|
static void FillDTABlock(DTA_FindBlock * dta,VFILE_Block * fill_file) {
|
||||||
strcpy(dta->name,fill_file->name);
|
strcpy(dta->name,fill_file->name);
|
||||||
dta->size=fill_file->size;
|
dta->size=fill_file->size;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include "dos_system.h"
|
||||||
|
|
||||||
class localDrive : public DOS_Drive {
|
class localDrive : public DOS_Drive {
|
||||||
public:
|
public:
|
||||||
@ -37,6 +37,8 @@ public:
|
|||||||
bool GetFileAttr(char * name,Bit16u * attr);
|
bool GetFileAttr(char * name,Bit16u * attr);
|
||||||
bool Rename(char * oldname,char * newname);
|
bool Rename(char * oldname,char * newname);
|
||||||
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
|
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
|
||||||
|
bool FileExists(const char* name) const ;
|
||||||
|
bool FileStat(const char* name, struct stat* const stat_block) const;
|
||||||
private:
|
private:
|
||||||
bool FillDTABlock(DTA_FindBlock * dta);
|
bool FillDTABlock(DTA_FindBlock * dta);
|
||||||
char basedir[512];
|
char basedir[512];
|
||||||
@ -63,6 +65,9 @@ public:
|
|||||||
bool GetFileAttr(char * name,Bit16u * attr);
|
bool GetFileAttr(char * name,Bit16u * attr);
|
||||||
bool Rename(char * oldname,char * newname);
|
bool Rename(char * oldname,char * newname);
|
||||||
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
|
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
|
||||||
|
bool FileExists(const char* name) const ;
|
||||||
|
bool FileStat(const char* name, struct stat* const stat_block) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VFILE_Block * search_file;
|
VFILE_Block * search_file;
|
||||||
char search_string[255];
|
char search_string[255];
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
@ -104,7 +105,7 @@ void DOS_Init();
|
|||||||
void RENDER_Init(void);
|
void RENDER_Init(void);
|
||||||
|
|
||||||
void CPU_Init();
|
void CPU_Init();
|
||||||
void FPU_Init();
|
//void FPU_Init();
|
||||||
void IO_Init(void);
|
void IO_Init(void);
|
||||||
void DMA_Init(void);
|
void DMA_Init(void);
|
||||||
void MIXER_Init(void);
|
void MIXER_Init(void);
|
||||||
@ -188,6 +189,9 @@ void DOSBOX_SetLoop(LoopHandler * handler) {
|
|||||||
loop=handler;
|
loop=handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DOSBOX_SetNormalLoop() {
|
||||||
|
loop=Normal_Loop;
|
||||||
|
}
|
||||||
|
|
||||||
void DOSBOX_RunMachine(void){
|
void DOSBOX_RunMachine(void){
|
||||||
Bitu ret;
|
Bitu ret;
|
||||||
@ -207,9 +211,11 @@ static void InitSystems(void) {
|
|||||||
HARDWARE_Init();
|
HARDWARE_Init();
|
||||||
TIMER_Init();
|
TIMER_Init();
|
||||||
CPU_Init();
|
CPU_Init();
|
||||||
|
#if C_FPU
|
||||||
FPU_Init();
|
FPU_Init();
|
||||||
|
#endif
|
||||||
MIXER_Init();
|
MIXER_Init();
|
||||||
#ifdef C_DEBUG
|
#if C_DEBUG
|
||||||
DEBUG_Init();
|
DEBUG_Init();
|
||||||
#endif
|
#endif
|
||||||
//Start up individual hardware
|
//Start up individual hardware
|
||||||
@ -241,10 +247,19 @@ static void InitSystems(void) {
|
|||||||
|
|
||||||
void DOSBOX_Init(int argc, char* argv[]) {
|
void DOSBOX_Init(int argc, char* argv[]) {
|
||||||
/* Find the base directory */
|
/* Find the base directory */
|
||||||
strcpy(dosbox_basedir,argv[0]);
|
SHELL_AddAutoexec("SET PATH=Z:\\");
|
||||||
|
SHELL_AddAutoexec("SET COMSPEC=Z:\\COMMAND.COM");
|
||||||
|
strcpy(dosbox_basedir,argv[0]);
|
||||||
char * last=strrchr(dosbox_basedir,CROSS_FILESPLIT); //if windowsversion fails:
|
char * last=strrchr(dosbox_basedir,CROSS_FILESPLIT); //if windowsversion fails:
|
||||||
if (!last) E_Exit("Can't find basedir");
|
if (!last){
|
||||||
|
getcwd(dosbox_basedir,CROSS_LEN);
|
||||||
|
char a[2];
|
||||||
|
a[0]=CROSS_FILESPLIT;
|
||||||
|
a[1]='\0';
|
||||||
|
strcat(dosbox_basedir,a);
|
||||||
|
} else {
|
||||||
*++last=0;
|
*++last=0;
|
||||||
|
}
|
||||||
/* Parse the command line with a setup function */
|
/* Parse the command line with a setup function */
|
||||||
int argl=1;
|
int argl=1;
|
||||||
if (argc>1) {
|
if (argc>1) {
|
||||||
@ -291,7 +306,5 @@ void DOSBOX_Init(int argc, char* argv[]) {
|
|||||||
|
|
||||||
|
|
||||||
void DOSBOX_StartUp(void) {
|
void DOSBOX_StartUp(void) {
|
||||||
SHELL_AddAutoexec("SET PATH=Z:\\");
|
|
||||||
SHELL_AddAutoexec("SET COMSPEC=Z:\\COMMAND.COM");
|
|
||||||
SHELL_Init();
|
SHELL_Init();
|
||||||
};
|
};
|
||||||
|
@ -71,5 +71,5 @@ The DOSBox Team
|
|||||||
Drive %c does not exist!
|
Drive %c does not exist!
|
||||||
.
|
.
|
||||||
:SHELL_EXECUTE_ILLEGAL_COMMAND
|
:SHELL_EXECUTE_ILLEGAL_COMMAND
|
||||||
Illegal command
|
Illegal command: %s
|
||||||
.
|
.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||||
|
|
||||||
noinst_LIBRARIES = libfpu.a
|
noinst_LIBRARIES = libfpu.a
|
||||||
libfpu_a_SOURCES = fpu.cpp fpu_load.h
|
libfpu_a_SOURCES = fpu.cpp fpu_flags.cpp fpu_types.h fpu_instructions.h
|
@ -84,7 +84,7 @@ install_sh = @install_sh@
|
|||||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||||
|
|
||||||
noinst_LIBRARIES = libfpu.a
|
noinst_LIBRARIES = libfpu.a
|
||||||
libfpu_a_SOURCES = fpu.cpp fpu_load.h
|
libfpu_a_SOURCES = fpu.cpp fpu_flags.cpp fpu_types.h fpu_instructions.h
|
||||||
subdir = src/fpu
|
subdir = src/fpu
|
||||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||||
CONFIG_HEADER = $(top_builddir)/config.h
|
CONFIG_HEADER = $(top_builddir)/config.h
|
||||||
@ -93,7 +93,7 @@ LIBRARIES = $(noinst_LIBRARIES)
|
|||||||
|
|
||||||
libfpu_a_AR = $(AR) cru
|
libfpu_a_AR = $(AR) cru
|
||||||
libfpu_a_LIBADD =
|
libfpu_a_LIBADD =
|
||||||
am_libfpu_a_OBJECTS = fpu.$(OBJEXT)
|
am_libfpu_a_OBJECTS = fpu.$(OBJEXT) fpu_flags.$(OBJEXT)
|
||||||
libfpu_a_OBJECTS = $(am_libfpu_a_OBJECTS)
|
libfpu_a_OBJECTS = $(am_libfpu_a_OBJECTS)
|
||||||
|
|
||||||
DEFS = @DEFS@
|
DEFS = @DEFS@
|
||||||
@ -103,7 +103,7 @@ LDFLAGS = @LDFLAGS@
|
|||||||
LIBS = @LIBS@
|
LIBS = @LIBS@
|
||||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
am__depfiles_maybe = depfiles
|
am__depfiles_maybe = depfiles
|
||||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/fpu.Po
|
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/fpu.Po ./$(DEPDIR)/fpu_flags.Po
|
||||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||||
CXXLD = $(CXX)
|
CXXLD = $(CXX)
|
||||||
@ -145,6 +145,7 @@ distclean-compile:
|
|||||||
-rm -f *.tab.c
|
-rm -f *.tab.c
|
||||||
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fpu.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fpu.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fpu_flags.Po@am__quote@
|
||||||
|
|
||||||
distclean-depend:
|
distclean-depend:
|
||||||
-rm -rf ./$(DEPDIR)
|
-rm -rf ./$(DEPDIR)
|
||||||
|
231
src/fpu/fpu.cpp
231
src/fpu/fpu.cpp
@ -16,12 +16,15 @@
|
|||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "dosbox.h"
|
||||||
|
#if C_FPU
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "dosbox.h"
|
#include "fpu.h"
|
||||||
|
|
||||||
typedef PhysOff EAPoint;
|
typedef PhysPt EAPoint;
|
||||||
|
|
||||||
#define LoadMb(off) mem_readb(off)
|
#define LoadMb(off) mem_readb(off)
|
||||||
#define LoadMw(off) mem_readw(off)
|
#define LoadMw(off) mem_readw(off)
|
||||||
@ -35,28 +38,240 @@ typedef PhysOff EAPoint;
|
|||||||
#define SaveMw(off,val) mem_writew(off,val)
|
#define SaveMw(off,val) mem_writew(off,val)
|
||||||
#define SaveMd(off,val) mem_writed(off,val)
|
#define SaveMd(off,val) mem_writed(off,val)
|
||||||
|
|
||||||
typedef long double FPUREG;
|
typedef double Real;
|
||||||
|
|
||||||
|
#include "fpu_types.h"
|
||||||
|
#include "fpu_instructions.h"
|
||||||
|
|
||||||
#include "fpu_load.h"
|
FPU_Flag_Info fpu_flags;
|
||||||
|
FPU_Reg fpu_regs[8];
|
||||||
|
|
||||||
|
#define FPU_GetZF fpu_flags.sw.zf = FPU_get_ZF();
|
||||||
|
|
||||||
|
#define FPU_ParseCW(newcw) { \
|
||||||
|
fpu_flags.cw.ic = ((bool)((newcw&0x1000)>>12)?true:false); \
|
||||||
|
fpu_flags.cw.rc = (Bit8u)((newcw&0x0C00)>>10); \
|
||||||
|
fpu_flags.cw.pc = (Bit8u)((newcw&0x0300)>>8); \
|
||||||
|
fpu_flags.cw.ie = ((bool)((newcw&0x0080)>>7)?true:false); \
|
||||||
|
fpu_flags.cw.sf = ((bool)((newcw&0x0040)>>6)?true:false); \
|
||||||
|
fpu_flags.cw.pf = ((bool)((newcw&0x0020)>>5)?true:false); \
|
||||||
|
fpu_flags.cw.uf = ((bool)((newcw&0x0010)>>4)?true:false); \
|
||||||
|
fpu_flags.cw.of = ((bool)((newcw&0x0008)>>3)?true:false); \
|
||||||
|
fpu_flags.cw.zf = ((bool)((newcw&0x0004)>>2)?true:false); \
|
||||||
|
fpu_flags.cw.df = ((bool)((newcw&0x0002)>>1)?true:false); \
|
||||||
|
fpu_flags.cw.in = ((bool)(newcw&0x0001)?true:false); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FPU_makeCW(newcw) { \
|
||||||
|
newcw = (Bit16u)fpu_flags.cw.in; \
|
||||||
|
newcw |= (fpu_flags.cw.df<<1); \
|
||||||
|
newcw |= (fpu_flags.cw.zf<<2); \
|
||||||
|
newcw |= (fpu_flags.cw.of<<3); \
|
||||||
|
newcw |= (fpu_flags.cw.uf<<4); \
|
||||||
|
newcw |= (fpu_flags.cw.pf<<5); \
|
||||||
|
newcw |= (fpu_flags.cw.sf<<6); \
|
||||||
|
newcw |= (fpu_flags.cw.ie<<7); \
|
||||||
|
newcw |= (fpu_flags.cw.pc<<8); \
|
||||||
|
newcw |= (fpu_flags.cw.rc<<10); \
|
||||||
|
newcw |= (fpu_flags.cw.ic<<12); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FPU_ParseSW(newsw) { \
|
||||||
|
fpu_flags.sw.bf = ((bool)((newsw&0x8000)>>15)?true:false); \
|
||||||
|
fpu_flags.sw.c3 = ((bool)((newsw&0x4000)>>14)?true:false); \
|
||||||
|
fpu_flags.sw.tos = (Bit8s)((newsw&0x3800)>>11); \
|
||||||
|
fpu_flags.sw.c2 = ((bool)((newsw&0x0400)>>10)?true:false); \
|
||||||
|
fpu_flags.sw.c1 = ((bool)((newsw&0x0200)>>9)?true:false); \
|
||||||
|
fpu_flags.sw.c0 = ((bool)((newsw&0x0100)>>8)?true:false); \
|
||||||
|
fpu_flags.sw.ir = ((bool)((newsw&0x0080)>>7)?true:false); \
|
||||||
|
fpu_flags.sw.sf = ((bool)((newsw&0x0040)>>6)?true:false); \
|
||||||
|
fpu_flags.sw.pf = ((bool)((newsw&0x0020)>>5)?true:false); \
|
||||||
|
fpu_flags.sw.uf = ((bool)((newsw&0x0010)>>4)?true:false); \
|
||||||
|
fpu_flags.sw.of = ((bool)((newsw&0x0008)>>3)?true:false); \
|
||||||
|
fpu_flags.sw.zf = ((bool)((newsw&0x0004)>>2)?true:false); \
|
||||||
|
fpu_flags.sw.df = ((bool)((newsw&0x0002)>>1)?true:false); \
|
||||||
|
fpu_flags.sw.in = ((bool)(newsw&0x0001)?true:false); \
|
||||||
|
}
|
||||||
|
|
||||||
void FPU_ESC0_EA(Bitu rm,PhysOff addr) {
|
#define FPU_makeSW(newsw) { \
|
||||||
|
newsw = (Bit16u)fpu_flags.sw.in; \
|
||||||
|
newsw |= (fpu_flags.sw.df<<1); \
|
||||||
|
newsw |= (fpu_flags.sw.zf<<2); \
|
||||||
|
newsw |= (fpu_flags.sw.of<<3); \
|
||||||
|
newsw |= (fpu_flags.sw.uf<<4); \
|
||||||
|
newsw |= (fpu_flags.sw.pf<<5); \
|
||||||
|
newsw |= (fpu_flags.sw.sf<<6); \
|
||||||
|
newsw |= (fpu_flags.sw.ir<<7); \
|
||||||
|
newsw |= (fpu_flags.sw.c0<<8); \
|
||||||
|
newsw |= (fpu_flags.sw.c1<<9); \
|
||||||
|
newsw |= (fpu_flags.sw.c2<<10); \
|
||||||
|
newsw |= (fpu_flags.sw.tos<<11); \
|
||||||
|
newsw |= (fpu_flags.sw.c3<<14); \
|
||||||
|
newsw |= (fpu_flags.sw.bf<<15); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FPU_LOADFLAGS { \
|
||||||
|
fpu_flags.sw.bf = false; \
|
||||||
|
fpu_flags.sw.c3 = FPU_get_C3(); \
|
||||||
|
fpu_flags.sw.c2 = FPU_get_C2(); \
|
||||||
|
fpu_flags.sw.c1 = FPU_get_C1(); \
|
||||||
|
fpu_flags.sw.c0 = FPU_get_C0(); \
|
||||||
|
fpu_flags.sw.ir = FPU_get_IR(); \
|
||||||
|
fpu_flags.sw.sf = FPU_get_SF(); \
|
||||||
|
fpu_flags.sw.pf = FPU_get_PF(); \
|
||||||
|
fpu_flags.sw.uf = FPU_get_UF(); \
|
||||||
|
fpu_flags.sw.of = FPU_get_OF(); \
|
||||||
|
fpu_flags.sw.zf = FPU_get_ZF(); \
|
||||||
|
fpu_flags.sw.df = FPU_get_DF(); \
|
||||||
|
fpu_flags.sw.in = FPU_get_IN(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPU_ESC0_EA(Bitu rm,PhysPt addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FPU_ESC0_Normal(Bitu rm) {
|
void FPU_ESC0_Normal(Bitu rm) {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPU_ESC1_EA(Bitu rm,PhysPt addr) {
|
||||||
|
Bit16u cw;
|
||||||
|
Bitu opcode = (rm&0x38)>>3;
|
||||||
|
|
||||||
|
switch(opcode) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 6:
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
FPU_ParseCW(LoadMw(addr)); /* FLDCW */
|
||||||
|
break;
|
||||||
|
case 7: /* FSTCW */
|
||||||
|
FPU_makeCW(cw);
|
||||||
|
SaveMw(addr,cw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPU_ESC1_Normal(Bitu rm) {
|
||||||
|
Bitu opcode = (rm&0xF0);
|
||||||
|
|
||||||
|
switch(opcode) {
|
||||||
|
case 0xC0:
|
||||||
|
// if(rm&8)
|
||||||
|
// else
|
||||||
|
FLDST(rm-0xC0); /* FLDST */
|
||||||
|
break;
|
||||||
|
case 0xD0:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch(rm) {
|
||||||
|
case 0xE0: /* FCHS */
|
||||||
|
FCHS;
|
||||||
|
break;
|
||||||
|
case 0xE8: /* FLD1 */
|
||||||
|
FLD(1);
|
||||||
|
break;
|
||||||
|
case 0xEE: /* FLDZ */
|
||||||
|
FLD(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPU_ESC2_EA(Bitu rm,PhysPt addr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPU_ESC2_Normal(Bitu rm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPU_ESC3_EA(Bitu rm,PhysPt addr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPU_ESC3_Normal(Bitu rm) {
|
||||||
|
switch( rm ) {
|
||||||
|
case 0xE3: /* FINIT */
|
||||||
|
FPU_ParseCW(0x037F);
|
||||||
|
for(int i=0;i<8;i++) {
|
||||||
|
fpu_regs.st[i].r = 0;
|
||||||
|
fpu_regs.st[i].tag = FPUREG_EMPTY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPU_ESC4_EA(Bitu rm,PhysPt addr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPU_ESC4_Normal(Bitu rm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPU_ESC5_EA(Bitu rm,PhysPt addr) {
|
||||||
|
Bit16u sw;
|
||||||
|
Bitu opcode = (rm&0x38)>>3;
|
||||||
|
|
||||||
|
switch(opcode) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
case 7: /* FSTSW */
|
||||||
|
FPU_LOADFLAGS;
|
||||||
|
FPU_makeSW(sw);
|
||||||
|
SaveMw(addr,sw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPU_ESC5_Normal(Bitu rm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPU_ESC6_EA(Bitu rm,PhysPt addr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPU_ESC6_Normal(Bitu rm) {
|
||||||
|
Bitu opcode = (rm&0xF0);
|
||||||
|
|
||||||
|
if(rm==0xD9) { /* FCOMPP */
|
||||||
|
FCOMPP;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(opcode) {
|
||||||
|
case 0xC0:
|
||||||
|
// if(rm&8)
|
||||||
|
break;
|
||||||
|
case 0xD0:
|
||||||
|
// if(rm&8)
|
||||||
|
break;
|
||||||
|
case 0xE0:
|
||||||
|
// if(rm&8)
|
||||||
|
break;
|
||||||
|
case 0xF0:
|
||||||
|
if(rm&8)
|
||||||
|
FDIVP(rm-0xF8,0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FPU_ESC7_EA(Bitu rm,PhysPt addr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void FPU_ESC7_Normal(Bitu rm) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FPU_Init(void) {
|
void FPU_Init(void) {
|
||||||
|
fpu_flags.type = t_FUNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
#endif
|
||||||
|
235
src/fpu/fpu_flags.cpp
Normal file
235
src/fpu/fpu_flags.cpp
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002 The DOSBox Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dosbox.h"
|
||||||
|
#include "fpu.h"
|
||||||
|
#include "pic.h"
|
||||||
|
#include "fpu_types.h"
|
||||||
|
extern FPU_Flag_Info fpu_flags;
|
||||||
|
|
||||||
|
bool FPU_get_C3() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
return fpu_flags.sw.c3;
|
||||||
|
case t_FCOMP:
|
||||||
|
return (fpu_flags.result.tag==FPUREG_EMPTY||fpu_flags.result.tag==FPUREG_ZERO);
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_C3 Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_C2() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
return fpu_flags.sw.c2;
|
||||||
|
case t_FCOMP:
|
||||||
|
return (fpu_flags.result.tag==FPUREG_EMPTY);
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_C2 Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_C1() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
return fpu_flags.sw.c1;
|
||||||
|
case t_FCOMP:
|
||||||
|
return false; /* FIXME */
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_C1 Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_C0() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
return fpu_flags.sw.c0;
|
||||||
|
case t_FCOMP:
|
||||||
|
return (fpu_flags.result.tag!=FPUREG_ZERO&&fpu_flags.result.tag!=FPUREG_PNAN);
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_C0 Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_IR() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
case t_FCOMP:
|
||||||
|
return fpu_flags.sw.ir;
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_IR Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_SF() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
return fpu_flags.sw.sf;
|
||||||
|
case t_FCOMP:
|
||||||
|
return false; /* FIXME */
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_SF Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_PF() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
case t_FCOMP:
|
||||||
|
return fpu_flags.sw.pf;
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_PF Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_UF() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
case t_FCOMP:
|
||||||
|
return fpu_flags.sw.uf;
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_UF Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_OF() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
case t_FCOMP:
|
||||||
|
return fpu_flags.sw.of;
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_OF Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_ZF() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
case t_FCOMP:
|
||||||
|
return fpu_flags.sw.zf;
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
return (fpu_flags.result.tag==FPUREG_PNAN||fpu_flags.result.tag==FPUREG_NNAN);
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_ZF Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_DF() {
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
return fpu_flags.sw.df;
|
||||||
|
case t_FCOMP:
|
||||||
|
return false; /* FIXME */
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_DF Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FPU_get_IN(){
|
||||||
|
switch(fpu_flags.type) {
|
||||||
|
case t_FLD:
|
||||||
|
case t_FLDST:
|
||||||
|
case t_FDIV:
|
||||||
|
case t_FDIVP:
|
||||||
|
case t_FCHS:
|
||||||
|
case t_FUNKNOWN:
|
||||||
|
case t_FNOTDONE:
|
||||||
|
return fpu_flags.sw.in;
|
||||||
|
case t_FCOMP:
|
||||||
|
return (fpu_flags.result.tag==FPUREG_EMPTY); /* FIXME */
|
||||||
|
default:
|
||||||
|
E_Exit("FPU_get_IN Unknown %d",fpu_flags.type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
162
src/fpu/fpu_instructions.h
Normal file
162
src/fpu/fpu_instructions.h
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2002 The DOSBox Team
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FLD(op1) { \
|
||||||
|
FPU_GetZF; \
|
||||||
|
fpu_flags.type=t_FLD; \
|
||||||
|
if(--fpu_flags.sw.tos < 0) \
|
||||||
|
fpu_flags.sw.tos = 7; \
|
||||||
|
if( fpu_regs.st[fpu_flags.sw.tos].tag != FPUREG_EMPTY ) { \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if(op1) \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_VALID; \
|
||||||
|
else \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_ZERO; \
|
||||||
|
fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = op1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FLDST(op1) { \
|
||||||
|
FPU_GetZF; \
|
||||||
|
fpu_flags.type=t_FLDST; \
|
||||||
|
Bit8u reg = fpu_flags.sw.tos+op1; \
|
||||||
|
if(reg>7) reg-=8; \
|
||||||
|
if(--fpu_flags.sw.tos < 0) \
|
||||||
|
fpu_flags.sw.tos = 7; \
|
||||||
|
if(fpu_regs.st[fpu_flags.sw.tos].tag!=FPUREG_EMPTY) { \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = fpu_regs.st[reg].tag; \
|
||||||
|
fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = fpu_regs.st[reg].r; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FPOP { \
|
||||||
|
fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_EMPTY; \
|
||||||
|
if(++fpu_flags.sw.tos > 7 ) \
|
||||||
|
fpu_flags.sw.tos = 0; \
|
||||||
|
}
|
||||||
|
/* FPOP: fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = 0; is not really neccessary */
|
||||||
|
|
||||||
|
#define FDIVP(op1,op2) { \
|
||||||
|
Bit8u reg1 = fpu_flags.sw.tos+op1; \
|
||||||
|
Bit8u reg2 = fpu_flags.sw.tos+op2; \
|
||||||
|
fpu_flags.type=t_FDIVP; \
|
||||||
|
if(reg1>7) reg1-=8; \
|
||||||
|
if(reg2>7) reg2-=8; \
|
||||||
|
if((fpu_regs.st[reg1].tag!=FPUREG_VALID && fpu_regs.st[reg1].tag!=FPUREG_ZERO)||(fpu_regs.st[reg2].tag!=FPUREG_VALID && fpu_regs.st[reg2].tag!=FPUREG_ZERO)) { \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \
|
||||||
|
FPOP; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if(fpu_regs.st[reg2].tag == FPUREG_ZERO) { \
|
||||||
|
if(fpu_regs.st[reg1].r > 0) \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_PNAN; \
|
||||||
|
else \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \
|
||||||
|
FPOP; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if(fpu_regs.st[reg1].tag == FPUREG_ZERO) { \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_ZERO; \
|
||||||
|
FPOP; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
fpu_flags.result.tag = FPUREG_VALID; \
|
||||||
|
fpu_flags.result.r = fpu_regs.st[reg1].r = fpu_regs.st[reg1].r / fpu_regs.st[reg2].r; \
|
||||||
|
FPOP; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FDIV(op1,op2) { \
|
||||||
|
Bit8u reg1 = fpu_flags.sw.tos+op1; \
|
||||||
|
Bit8u reg2 = fpu_flags.sw.tos+op2; \
|
||||||
|
fpu_flags.type=t_FDIV; \
|
||||||
|
if(reg1>7) reg1-=7; \
|
||||||
|
if(reg2>7) reg2-=7; \
|
||||||
|
if((fpu_regs.st[reg1].tag!=FPUREG_VALID && fpu_regs.st[reg1].tag!=FPUREG_ZERO)||(fpu_regs.st[reg2].tag!=FPUREG_VALID && fpu_regs.st[reg2].tag!=FPUREG_ZERO)) { \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if(fpu_regs.st[reg2].tag == FPUREG_ZERO) { \
|
||||||
|
if(fpu_regs.st[reg1].r > 0) \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_PNAN; \
|
||||||
|
else \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
if(fpu_regs.st[reg1].tag == FPUREG_ZERO) { \
|
||||||
|
fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_ZERO; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
fpu_flags.result.tag = FPUREG_VALID; \
|
||||||
|
fpu_flags.result.r = fpu_regs.st[reg1].r = fpu_regs.st[reg1].r / fpu_regs.st[reg2].r; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FCHS { \
|
||||||
|
FPU_GetZF; \
|
||||||
|
fpu_flags.type=t_FCHS; \
|
||||||
|
if(fpu_regs.st[fpu_flags.sw.tos].tag == FPUREG_PNAN) { \
|
||||||
|
fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \
|
||||||
|
} else if(fpu_regs.st[fpu_flags.sw.tos].tag == FPUREG_NNAN) { \
|
||||||
|
fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_PNAN; \
|
||||||
|
} else \
|
||||||
|
fpu_regs.st[fpu_flags.sw.tos].r = -fpu_regs.st[fpu_flags.sw.tos].r; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FCOMPP { \
|
||||||
|
Bit8u reg = fpu_flags.sw.tos+1; \
|
||||||
|
FPU_GetZF; \
|
||||||
|
fpu_flags.type=t_FCOMP; \
|
||||||
|
if(reg>7) \
|
||||||
|
reg=0; \
|
||||||
|
if((fpu_regs.st[reg].tag==FPUREG_VALID||fpu_regs.st[reg].tag==FPUREG_ZERO)&&(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_VALID||fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_ZERO)) { \
|
||||||
|
fpu_flags.result.r = fpu_regs.st[reg].r - fpu_regs.st[fpu_flags.sw.tos].r; \
|
||||||
|
if(fpu_flags.result.r==0) \
|
||||||
|
fpu_flags.result.tag = FPUREG_ZERO; \
|
||||||
|
else \
|
||||||
|
fpu_flags.result.tag = FPUREG_VALID; \
|
||||||
|
FPOP; \
|
||||||
|
FPOP; \
|
||||||
|
return; \
|
||||||
|
} else if(((fpu_regs.st[reg].tag==FPUREG_EMPTY)||(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_EMPTY))||((fpu_regs.st[reg].tag==FPUREG_VALID||fpu_regs.st[reg].tag==FPUREG_ZERO)||(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_VALID||fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_ZERO))) { \
|
||||||
|
fpu_flags.result.tag = FPUREG_EMPTY; \
|
||||||
|
FPOP; \
|
||||||
|
FPOP; \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
Bit8s res = (fpu_regs.st[reg].tag-fpu_regs.st[fpu_flags.sw.tos].tag); \
|
||||||
|
if(res==0||fpu_flags.cw.ic==0) { \
|
||||||
|
fpu_flags.result.tag = FPUREG_ZERO; \
|
||||||
|
FPOP; \
|
||||||
|
FPOP; \
|
||||||
|
return; \
|
||||||
|
} else if(res>0) { \
|
||||||
|
fpu_flags.result.tag = FPUREG_NNAN; \
|
||||||
|
FPOP; \
|
||||||
|
FPOP; \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
fpu_flags.result.tag = FPUREG_PNAN; \
|
||||||
|
FPOP; \
|
||||||
|
FPOP; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2002 The DOSBox Team
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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 Library General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
INLINE FPUREG Load_Short(EAPoint addr) {
|
|
||||||
return (Bit16s)mem_readw(addr);
|
|
||||||
}
|
|
33
src/fpu/fpu_types.h
Normal file
33
src/fpu/fpu_types.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
|
||||||
|
enum { FPUREG_VALID=0, FPUREG_ZERO, FPUREG_PNAN, FPUREG_NNAN, FPUREG_EMPTY };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
t_FLD=0, t_FLDST, t_FDIV,
|
||||||
|
t_FDIVP, t_FCHS, t_FCOMP,
|
||||||
|
|
||||||
|
t_FUNKNOWN,
|
||||||
|
t_FNOTDONE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FPU_Flag_Info {
|
||||||
|
struct {
|
||||||
|
Real64 r;
|
||||||
|
Bit8u tag;
|
||||||
|
} var1,var2, result;
|
||||||
|
struct {
|
||||||
|
bool bf,c3,c2,c1,c0,ir,sf,pf,uf,of,zf,df,in;
|
||||||
|
Bit8s tos;
|
||||||
|
} sw;
|
||||||
|
struct {
|
||||||
|
bool ic,ie,sf,pf,uf,of,zf,df,in;
|
||||||
|
Bit8u rc,pc;
|
||||||
|
} cw;
|
||||||
|
Bitu type;
|
||||||
|
Bitu prev_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FPU_Reg {
|
||||||
|
Real64 r;
|
||||||
|
Bit8u tag;
|
||||||
|
};
|
@ -67,13 +67,13 @@ static void MakeTables(void) {
|
|||||||
Bitu i;Bit32u c,a;
|
Bitu i;Bit32u c,a;
|
||||||
c=0;a=(render.src.width<<16)/gfx_info.width;
|
c=0;a=(render.src.width<<16)/gfx_info.width;
|
||||||
for (i=0;i<gfx_info.width;i++) {
|
for (i=0;i<gfx_info.width;i++) {
|
||||||
render.stretch_x[i]=c>> 16;
|
|
||||||
c=(c&0xffff)+a;
|
c=(c&0xffff)+a;
|
||||||
|
render.stretch_x[i]=c>> 16;
|
||||||
}
|
}
|
||||||
c=0;a=(render.src.height<<16)/gfx_info.height;
|
c=0;a=(render.src.height<<16)/gfx_info.height;
|
||||||
for (i=0;i<gfx_info.height;i++) {
|
for (i=0;i<gfx_info.height;i++) {
|
||||||
render.stretch_y[i]=(c>> 16)*render.src.pitch;
|
|
||||||
c=(c&0xffff)+a;
|
c=(c&0xffff)+a;
|
||||||
|
render.stretch_y[i]=(c>>16)*render.src.pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ static void SwitchFullScreen(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void GFX_Redraw() {
|
static void GFX_Redraw() {
|
||||||
#ifdef C_THREADED
|
#if C_THREADED
|
||||||
if (SDL_mutexP(sdl.mutex)) {
|
if (SDL_mutexP(sdl.mutex)) {
|
||||||
E_Exit("Can't Lock Mutex");
|
E_Exit("Can't Lock Mutex");
|
||||||
};
|
};
|
||||||
@ -134,7 +134,7 @@ static void GFX_Redraw() {
|
|||||||
if (sdl.full_screen) SDL_Flip(sdl.surface);
|
if (sdl.full_screen) SDL_Flip(sdl.surface);
|
||||||
else SDL_UpdateRect(sdl.surface,0,0,0,0);
|
else SDL_UpdateRect(sdl.surface,0,0,0,0);
|
||||||
};
|
};
|
||||||
#ifdef C_THREADED
|
#if C_THREADED
|
||||||
if (SDL_mutexV(sdl.mutex)) {
|
if (SDL_mutexV(sdl.mutex)) {
|
||||||
E_Exit("Can't Release Mutex");
|
E_Exit("Can't Release Mutex");
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ static int SDLGFX_Thread(void * data) {
|
|||||||
|
|
||||||
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) {
|
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) {
|
||||||
/* I should probably not change the GFX_PalEntry :) */
|
/* I should probably not change the GFX_PalEntry :) */
|
||||||
#ifdef C_THREADED
|
#if C_THREADED
|
||||||
if (SDL_mutexP(sdl.mutex)) {
|
if (SDL_mutexP(sdl.mutex)) {
|
||||||
E_Exit("SDL:Can't Lock Mutex");
|
E_Exit("SDL:Can't Lock Mutex");
|
||||||
};
|
};
|
||||||
@ -166,7 +166,7 @@ void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Copy palette entries into some internal back up table */
|
/* Copy palette entries into some internal back up table */
|
||||||
#ifdef C_THREADED
|
#if C_THREADED
|
||||||
if (SDL_mutexV(sdl.mutex)) {
|
if (SDL_mutexV(sdl.mutex)) {
|
||||||
E_Exit("SDL:Can't Release Mutex");
|
E_Exit("SDL:Can't Release Mutex");
|
||||||
}
|
}
|
||||||
@ -179,11 +179,11 @@ void GFX_SetDrawHandler(GFX_DrawHandler * handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GFX_Stop() {
|
void GFX_Stop() {
|
||||||
#ifdef C_THREADED
|
#if C_THREADED
|
||||||
SDL_mutexP(sdl.mutex);
|
SDL_mutexP(sdl.mutex);
|
||||||
#endif
|
#endif
|
||||||
sdl.active=false;
|
sdl.active=false;
|
||||||
#ifdef C_THREADED
|
#if C_THREADED
|
||||||
SDL_mutexV(sdl.mutex);
|
SDL_mutexV(sdl.mutex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ void GFX_StartUp() {
|
|||||||
sdl.active=false;
|
sdl.active=false;
|
||||||
sdl.full_screen=false;
|
sdl.full_screen=false;
|
||||||
sdl.draw=0;
|
sdl.draw=0;
|
||||||
#ifdef C_THREADED
|
#if C_THREADED
|
||||||
sdl.mutex=SDL_CreateMutex();
|
sdl.mutex=SDL_CreateMutex();
|
||||||
sdl.thread = SDL_CreateThread(&SDLGFX_Thread,0);
|
sdl.thread = SDL_CreateThread(&SDLGFX_Thread,0);
|
||||||
#else
|
#else
|
||||||
@ -485,7 +485,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
) < 0 ) {
|
) < 0 ) {
|
||||||
E_Exit("Can't init SDL");
|
E_Exit("Can't init SDL %s",SDL_GetError());
|
||||||
}
|
}
|
||||||
GFX_StartUp();
|
GFX_StartUp();
|
||||||
/* Init all the dosbox subsystems */
|
/* Init all the dosbox subsystems */
|
||||||
@ -497,9 +497,9 @@ int main(int argc, char* argv[]) {
|
|||||||
sdl.joy=SDL_JoystickOpen(0);
|
sdl.joy=SDL_JoystickOpen(0);
|
||||||
LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(0),SDL_JoystickNumAxes(sdl.joy),SDL_JoystickNumButtons(sdl.joy));
|
LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(0),SDL_JoystickNumAxes(sdl.joy),SDL_JoystickNumButtons(sdl.joy));
|
||||||
JOYSTICK_Enable(0,true);
|
JOYSTICK_Enable(0,true);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
/* Start dosbox up */
|
#endif
|
||||||
|
/* Start dosbox up */
|
||||||
DOSBOX_StartUp();
|
DOSBOX_StartUp();
|
||||||
}
|
}
|
||||||
catch (Bitu e) {
|
catch (Bitu e) {
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#include "inout.h"
|
#include "inout.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
|
|
||||||
#ifdef DEBUG_DMA
|
#if DEBUG_DMA
|
||||||
#define DMA_DEBUG LOG_DEBUG
|
#define DMA_DEBUG LOG_DEBUG
|
||||||
#else
|
#else
|
||||||
#define DMA_DEBUG
|
#define DMA_DEBUG
|
||||||
@ -57,7 +57,7 @@ struct DMA_CHANNEL {
|
|||||||
Bit32u current_count;
|
Bit32u current_count;
|
||||||
Bit8u page;
|
Bit8u page;
|
||||||
bool masked;
|
bool masked;
|
||||||
HostOff host_address;
|
PhysPt address;
|
||||||
bool addr_changed;
|
bool addr_changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -142,73 +142,62 @@ void write_dma_page(Bit32u port,Bit8u val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
|
Bit16u DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
|
||||||
DMA_CHANNEL * chan=&dma[0].chan[dmachan];
|
DMA_CHANNEL * chan=&dma[0].chan[dmachan];
|
||||||
|
|
||||||
|
if (chan->masked) return 0;
|
||||||
|
if (!count) return 0;
|
||||||
/* DMA always does autoinit should work under normal situations */
|
/* DMA always does autoinit should work under normal situations */
|
||||||
if (chan->addr_changed) {
|
if (chan->addr_changed) {
|
||||||
/* Calculate the new starting position for dma read*/
|
/* Calculate the new starting position for dma read*/
|
||||||
chan->addr_changed=false;
|
chan->addr_changed=false;
|
||||||
chan->host_address=memory+(chan->page << 16)+chan->base_address;
|
chan->address=(chan->page << 16)+chan->base_address;
|
||||||
|
|
||||||
chan->current_count=chan->base_count+1;
|
chan->current_count=chan->base_count+1;
|
||||||
chan->current_address=chan->base_address;
|
chan->current_address=chan->base_address;
|
||||||
DMA_DEBUG("DMA:Transfer from %d size %d",(chan->page << 16)+chan->base_address,chan->current_count);
|
DMA_DEBUG("DMA:Transfer from %d size %d",(chan->page << 16)+chan->base_address,chan->current_count);
|
||||||
}
|
}
|
||||||
if (!count) return;
|
|
||||||
if (chan->current_count>=count) {
|
if (chan->current_count>=count) {
|
||||||
memcpy(buffer,chan->host_address,count);
|
MEM_BlockRead(chan->address,buffer,count);
|
||||||
chan->host_address+=count;
|
chan->address+=count;
|
||||||
chan->current_address+=count;
|
chan->current_address+=count;
|
||||||
chan->current_count-=count;
|
chan->current_count-=count;
|
||||||
return;
|
return count;
|
||||||
} else {
|
} else {
|
||||||
/* Copy remaining piece of first buffer */
|
/* Copy remaining piece of first buffer */
|
||||||
memcpy(buffer,chan->host_address,chan->current_count);
|
MEM_BlockRead(chan->address,buffer,chan->current_count);
|
||||||
buffer+=chan->current_count;
|
buffer+=chan->current_count;
|
||||||
count-=(Bit16u)chan->current_count;
|
count-=(Bit16u)chan->current_count;
|
||||||
/* Autoinit reset the dma channel */
|
/* Autoinit reset the dma channel */
|
||||||
chan->host_address=memory+(chan->page << 16)+chan->base_address;
|
chan->address=(chan->page << 16)+chan->base_address;
|
||||||
chan->current_count=chan->base_count+1;
|
chan->current_count=chan->base_count+1;
|
||||||
chan->current_address=chan->base_address;
|
chan->current_address=chan->base_address;
|
||||||
/* Copy the rest of the buffer */
|
/* Copy the rest of the buffer */
|
||||||
memcpy(buffer,chan->host_address,count);
|
MEM_BlockRead(chan->address,buffer,count);
|
||||||
chan->host_address+=count;
|
chan->address+=count;
|
||||||
chan->current_address+=count;
|
chan->current_address+=count;
|
||||||
chan->current_count-=count;
|
chan->current_count-=count;
|
||||||
return;
|
return count;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
|
Bit16u DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
|
||||||
if (dma[0].chan[dmachan].addr_changed) {
|
|
||||||
/* Calculate the new starting position for dma read*/
|
|
||||||
dma[0].chan[dmachan].addr_changed=false;
|
|
||||||
dma[0].chan[dmachan].host_address=memory+(dma[0].chan[dmachan].page << 16)+dma[0].chan[dmachan].base_address;
|
|
||||||
dma[0].chan[dmachan].current_count=dma[0].chan[dmachan].base_count;
|
|
||||||
dma[0].chan[dmachan].current_count=dma[0].chan[dmachan].current_count;
|
|
||||||
}
|
|
||||||
if (dma[0].chan[dmachan].current_count>=count) {
|
|
||||||
memcpy(dma[0].chan[dmachan].host_address,buffer,count);
|
|
||||||
dma[0].chan[dmachan].host_address+=count;
|
|
||||||
dma[0].chan[dmachan].current_address+=count;
|
|
||||||
dma[0].chan[dmachan].current_count-=count;
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
return 0;
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DMA_16_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
|
Bit16u DMA_16_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
|
Bit16u DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,117 +1,117 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2002 The DOSBox Team
|
* Copyright (C) 2002 The DOSBox Team
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU Library General Public License for more details.
|
* GNU Library General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This could do with a serious revision :)
|
This could do with a serious revision :)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "programs.h"
|
#include "programs.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
|
|
||||||
static HWBlock * firsthw=0;
|
static HWBlock * firsthw=0;
|
||||||
|
|
||||||
|
|
||||||
class HWSET : public Program {
|
class HWSET : public Program {
|
||||||
public:
|
public:
|
||||||
HWSET(PROGRAM_Info * program_info);
|
HWSET(PROGRAM_Info * program_info);
|
||||||
void Run(void);
|
void Run(void);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
HWSET::HWSET(PROGRAM_Info * info):Program(info) {
|
HWSET::HWSET(PROGRAM_Info * info):Program(info) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HW_Register(HWBlock * block) {
|
void HW_Register(HWBlock * block) {
|
||||||
block->next=firsthw;
|
block->next=firsthw;
|
||||||
firsthw=block;
|
firsthw=block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HWSET::Run(void) {
|
void HWSET::Run(void) {
|
||||||
/* Hopefull enough space */
|
/* Hopefull enough space */
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
|
||||||
HWBlock * loopblock;
|
HWBlock * loopblock;
|
||||||
if (!*prog_info->cmd_line) {
|
if (!*prog_info->cmd_line) {
|
||||||
/* No command line given give overview of hardware */
|
/* No command line given give overview of hardware */
|
||||||
loopblock=firsthw;
|
loopblock=firsthw;
|
||||||
WriteOut("ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿");
|
WriteOut("ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿");
|
||||||
WriteOut("³Device ³Full Name ³Status ³");
|
WriteOut("³Device ³Full Name ³Status ³");
|
||||||
WriteOut("ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´");
|
WriteOut("ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´");
|
||||||
while (loopblock) {
|
while (loopblock) {
|
||||||
if (loopblock->show_status) {
|
if (loopblock->show_status) {
|
||||||
loopblock->show_status(buf);
|
loopblock->show_status(buf);
|
||||||
} else {
|
} else {
|
||||||
strcpy(buf,"No Status Handler");
|
strcpy(buf,"No Status Handler");
|
||||||
}
|
}
|
||||||
WriteOut("³%-8s³%-25s³%-43s³",loopblock->dev_name,loopblock->full_name,buf);
|
WriteOut("³%-8s³%-25s³%-43s³",loopblock->dev_name,loopblock->full_name,buf);
|
||||||
loopblock=loopblock->next;
|
loopblock=loopblock->next;
|
||||||
}
|
}
|
||||||
WriteOut("ÀÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
|
WriteOut("ÀÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
|
||||||
WriteOut("If you want to setup specific hardware use \"HWSET Device\" for information.\n");
|
WriteOut("If you want to setup specific hardware use \"HWSET Device\" for information.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Command line given */
|
/* Command line given */
|
||||||
if (strcmp(prog_info->cmd_line,"/?")==0) {
|
if (strcmp(prog_info->cmd_line,"/?")==0) {
|
||||||
WriteOut("Hardware setup tool for DOSBox.\n");
|
WriteOut("Hardware setup tool for DOSBox.\n");
|
||||||
WriteOut("This program can be used to change the settings of internal hardware.\n\n"
|
WriteOut("This program can be used to change the settings of internal hardware.\n\n"
|
||||||
"HWSET [device] [switches]\n\n"
|
"HWSET [device] [switches]\n\n"
|
||||||
"Using an empty command line gives you a list of hardware.\n"
|
"Using an empty command line gives you a list of hardware.\n"
|
||||||
"You can get list of switches for a device with HWSET device.\n"
|
"You can get list of switches for a device with HWSET device.\n"
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char * rest=strchr(prog_info->cmd_line,' ');
|
char * rest=strchr(prog_info->cmd_line,' ');
|
||||||
if (rest) *rest++=0;
|
if (rest) *rest++=0;
|
||||||
loopblock=firsthw;
|
loopblock=firsthw;
|
||||||
while (loopblock) {
|
while (loopblock) {
|
||||||
if (strcasecmp(loopblock->dev_name,prog_info->cmd_line)==0) goto founddev;
|
if (strcasecmp(loopblock->dev_name,prog_info->cmd_line)==0) goto founddev;
|
||||||
loopblock=loopblock->next;
|
loopblock=loopblock->next;
|
||||||
}
|
}
|
||||||
WriteOut("Device %s not found\n",prog_info->cmd_line);
|
WriteOut("Device %s not found\n",prog_info->cmd_line);
|
||||||
return;
|
return;
|
||||||
founddev:
|
founddev:
|
||||||
/* Check for rest of line */
|
/* Check for rest of line */
|
||||||
if (rest) {
|
if (rest) {
|
||||||
strcpy(buf,rest);
|
strcpy(buf,rest);
|
||||||
loopblock->get_input(buf);
|
loopblock->get_input(buf);
|
||||||
WriteOut(buf);
|
WriteOut(buf);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
WriteOut("Command overview for %s\n%s",loopblock->full_name,loopblock->help);
|
WriteOut("Command overview for %s\n%s",loopblock->full_name,loopblock->help);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void HWSET_ProgramStart(PROGRAM_Info * info) {
|
static void HWSET_ProgramStart(PROGRAM_Info * info) {
|
||||||
HWSET * tempHWSET=new HWSET(info);
|
HWSET * tempHWSET=new HWSET(info);
|
||||||
tempHWSET->Run();
|
tempHWSET->Run();
|
||||||
delete tempHWSET;
|
delete tempHWSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void HARDWARE_Init(void) {
|
void HARDWARE_Init(void) {
|
||||||
PROGRAMS_MakeFile("HWSET.COM",HWSET_ProgramStart);
|
PROGRAMS_MakeFile("HWSET.COM",HWSET_ProgramStart);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -63,10 +63,12 @@ static Bit8u read_p61(Bit32u port) {
|
|||||||
static void write_p61(Bit32u port,Bit8u val) {
|
static void write_p61(Bit32u port,Bit8u val) {
|
||||||
//TODO Enable spreaker through here :)
|
//TODO Enable spreaker through here :)
|
||||||
if ((val&128)) { /* Keyboard acknowledge */
|
if ((val&128)) { /* Keyboard acknowledge */
|
||||||
kbuf_used--;
|
if (kbuf_used) {
|
||||||
kbuf_pos++;
|
kbuf_used--;
|
||||||
if (kbuf_pos>=KEYBUFSIZE) kbuf_pos=0;
|
kbuf_pos++;
|
||||||
if (kbuf_used>0) PIC_ActivateIRQ(1);
|
if (kbuf_pos>=KEYBUFSIZE) kbuf_pos=0;
|
||||||
|
if (kbuf_used) PIC_ActivateIRQ(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
port_61_data=val;
|
port_61_data=val;
|
||||||
if ((val & 3)==3) {
|
if ((val & 3)==3) {
|
||||||
|
@ -15,38 +15,25 @@
|
|||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
|
||||||
#define MEM_MAXSIZE 16 /* The Size of memory used to get size of page table */
|
HostPt memory;
|
||||||
#define memsize 8 /* 8 mb of memory */
|
HostPt ReadHostTable[MAX_PAGES];
|
||||||
#define EMM_HANDLECOUNT 250
|
HostPt WriteHostTable[MAX_PAGES];
|
||||||
|
MEMORY_ReadHandler ReadHandlerTable[MAX_PAGES];
|
||||||
|
MEMORY_WriteHandler WriteHandlerTable[MAX_PAGES];
|
||||||
|
|
||||||
EMM_Handle EMM_Handles[EMM_HANDLECOUNT];
|
/* Page handlers only work in lower memory */
|
||||||
PageEntry * PageEntries[MEM_MAXSIZE*1024*16]; /* Number of pages */
|
#define LOW_PAGE_LIMIT PAGE_COUNT(1024*1024)
|
||||||
Bit8u * memory=0;
|
#define MAX_PAGE_LIMIT PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024)
|
||||||
|
|
||||||
bool MEMORY_TestSpecial(PhysOff off) {
|
void MEM_BlockRead(PhysPt off,void * data,Bitu size) {
|
||||||
return (PageEntries[off >> 12]>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MEMORY_SetupHandler(Bit32u page,Bit32u pages,PageEntry * entry) {
|
|
||||||
for (Bit32u i=page;i<page+pages;i++) {
|
|
||||||
PageEntries[i]=entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MEMORY_ResetHandler(Bit32u page,Bit32u pages) {
|
|
||||||
for (Bit32u i=page;i<page+pages;i++) {
|
|
||||||
PageEntries[i]=0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void MEM_BlockRead(PhysOff off,void * data,Bitu size) {
|
|
||||||
Bitu c;
|
Bitu c;
|
||||||
Bit8u * idata=(Bit8u *)data;
|
Bit8u * idata=(Bit8u *)data;
|
||||||
for (c=1;c<=(size>>2);c++) {
|
for (c=1;c<=(size>>2);c++) {
|
||||||
@ -59,7 +46,7 @@ void MEM_BlockRead(PhysOff off,void * data,Bitu size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MEM_BlockWrite(PhysOff off,void * data,Bitu size) {
|
void MEM_BlockWrite(PhysPt off,void * data,Bitu size) {
|
||||||
Bitu c;
|
Bitu c;
|
||||||
Bit8u * idata=(Bit8u *)data;
|
Bit8u * idata=(Bit8u *)data;
|
||||||
for (c=1;c<=(size>>2);c++) {
|
for (c=1;c<=(size>>2);c++) {
|
||||||
@ -72,7 +59,7 @@ void MEM_BlockWrite(PhysOff off,void * data,Bitu size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MEM_BlockCopy(PhysOff dest,PhysOff src,Bitu size) {
|
void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size) {
|
||||||
Bitu c;
|
Bitu c;
|
||||||
for (c=1;c<=(size>>2);c++) {
|
for (c=1;c<=(size>>2);c++) {
|
||||||
mem_writed(dest,mem_readd(src));
|
mem_writed(dest,mem_readd(src));
|
||||||
@ -82,11 +69,9 @@ void MEM_BlockCopy(PhysOff dest,PhysOff src,Bitu size) {
|
|||||||
mem_writeb(dest,mem_readb(src));
|
mem_writeb(dest,mem_readb(src));
|
||||||
dest+=1;src+=1;
|
dest+=1;src+=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void MEM_StrCopy(PhysOff off,char * data,Bitu size) {
|
void MEM_StrCopy(PhysPt off,char * data,Bitu size) {
|
||||||
Bit8u c;
|
Bit8u c;
|
||||||
while ((c=mem_readb(off)) && size) {
|
while ((c=mem_readb(off)) && size) {
|
||||||
*data=c;
|
*data=c;
|
||||||
@ -95,205 +80,167 @@ void MEM_StrCopy(PhysOff off,char * data,Bitu size) {
|
|||||||
*data='\0';
|
*data='\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Bit8u Illegal_ReadHandler(PhysPt pt) {
|
||||||
|
LOG_ERROR("Illegal read from address %4X",pt);
|
||||||
|
|
||||||
/* TODO Maybe check for page boundaries but that would be wasting lot's of time */
|
|
||||||
void mem_writeb(PhysOff off,Bit8u val) {
|
|
||||||
PageEntry * entry=PageEntries[off >> 12];
|
|
||||||
if (!entry) { writeb(memory+off,val);return; }
|
|
||||||
switch (entry->type) {
|
|
||||||
case MEMORY_RELOCATE:
|
|
||||||
writeb(entry->relocate+(off-entry->base),val);
|
|
||||||
break;
|
|
||||||
case MEMORY_HANDLER:
|
|
||||||
entry->handler.write(off-entry->base,val);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
E_Exit("Write to Illegal Memory Address %4x",off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mem_writew(PhysOff off,Bit16u val) {
|
|
||||||
PageEntry * entry=PageEntries[off >> 12];
|
|
||||||
if (!entry) { writew(memory+off,val);return; }
|
|
||||||
switch (entry->type) {
|
|
||||||
case MEMORY_RELOCATE:
|
|
||||||
writew(entry->relocate+(off-entry->base),val);
|
|
||||||
break;
|
|
||||||
case MEMORY_HANDLER:
|
|
||||||
entry->handler.write(off-entry->base,(val & 0xFF));
|
|
||||||
entry->handler.write(off-entry->base+1,(val >> 8));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
E_Exit("Write to Illegal Memory Address %4x",off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mem_writed(PhysOff off,Bit32u val) {
|
|
||||||
PageEntry * entry=PageEntries[off >> 12];
|
|
||||||
if (!entry) { writed(memory+off,val);return; }
|
|
||||||
switch (entry->type) {
|
|
||||||
case MEMORY_RELOCATE:
|
|
||||||
writed(entry->relocate+(off-entry->base),val);
|
|
||||||
break;
|
|
||||||
case MEMORY_HANDLER:
|
|
||||||
entry->handler.write(off-entry->base, (Bit8u)(val & 0xFF));
|
|
||||||
entry->handler.write(off-entry->base+1,(Bit8u)(val >> 8) & 0xFF);
|
|
||||||
entry->handler.write(off-entry->base+2,(Bit8u)(val >> 16) & 0xFF);
|
|
||||||
entry->handler.write(off-entry->base+3,(Bit8u)(val >> 24) & 0xFF);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
E_Exit("Write to Illegal Memory Address %4x",off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Bit8u mem_readb(PhysOff off) {
|
|
||||||
PageEntry * entry=PageEntries[off >> 12];
|
|
||||||
if (!entry) { return readb(memory+off);}
|
|
||||||
switch (entry->type) {
|
|
||||||
case MEMORY_RELOCATE:
|
|
||||||
return readb(entry->relocate+(off-entry->base));
|
|
||||||
case MEMORY_HANDLER:
|
|
||||||
return entry->handler.read(off-entry->base);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
E_Exit("Read from Illegal Memory Address %4x",off);
|
|
||||||
}
|
|
||||||
return 0; /* Keep compiler happy */
|
|
||||||
}
|
|
||||||
|
|
||||||
Bit16u mem_readw(PhysOff off) {
|
|
||||||
PageEntry * entry=PageEntries[off >> 12];
|
|
||||||
if (!entry) { return readw(memory+off);}
|
|
||||||
switch (entry->type) {
|
|
||||||
case MEMORY_RELOCATE:
|
|
||||||
return readw(entry->relocate+(off-entry->base));
|
|
||||||
case MEMORY_HANDLER:
|
|
||||||
return entry->handler.read(off-entry->base) |
|
|
||||||
(entry->handler.read(off-entry->base+1) << 8);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
E_Exit("Read from Illegal Memory Address %4x",off);
|
|
||||||
}
|
|
||||||
return 0; /* Keep compiler happy */
|
|
||||||
}
|
|
||||||
|
|
||||||
Bit32u mem_readd(PhysOff off) {
|
|
||||||
PageEntry * entry=PageEntries[off >> 12];
|
|
||||||
if (!entry) { return readd(memory+off);}
|
|
||||||
switch (entry->type) {
|
|
||||||
case MEMORY_RELOCATE:
|
|
||||||
return readd(entry->relocate+(off-entry->base));
|
|
||||||
case MEMORY_HANDLER:
|
|
||||||
return entry->handler.read(off-entry->base) |
|
|
||||||
(entry->handler.read(off-entry->base+1) << 8) |
|
|
||||||
(entry->handler.read(off-entry->base+2) << 16)|
|
|
||||||
(entry->handler.read(off-entry->base+3) << 24);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
E_Exit("Read from Illegal Memory Address %4x",off);
|
|
||||||
}
|
|
||||||
return 0; /* Keep compiler happy */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The EMM Allocation Part */
|
|
||||||
|
|
||||||
/* If this returns 0 we got and error since 0 is always taken */
|
|
||||||
static Bit16u EMM_GetFreeHandle(void) {
|
|
||||||
Bit16u i=0;
|
|
||||||
while (i<EMM_HANDLECOUNT) {
|
|
||||||
if (!EMM_Handles[i].active) return i;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
E_Exit("MEMORY:Out of EMM Memory handles");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static void Illegal_WriteHandler(PhysPt pt,Bit8u val) {
|
||||||
|
LOG_ERROR("Illegal write val %2X to address %4X",val,pt);
|
||||||
|
}
|
||||||
|
|
||||||
void EMM_GetFree(Bit16u * maxblock,Bit16u * total) {
|
/* Could only be called when the pt host entry is 0 ah well :) */
|
||||||
Bit32u index=0;
|
static Bit8u Default_ReadHandler(PhysPt pt) {
|
||||||
*maxblock=0;*total=0;
|
return readb(WriteHostTable[pt >> PAGE_SHIFT]+pt);
|
||||||
while (EMM_Handles[index].active) {
|
}
|
||||||
if (EMM_Handles[index].free) {
|
static void Default_WriteHandler(PhysPt pt,Bit8u val) {
|
||||||
if(EMM_Handles[index].size>*maxblock) *maxblock=EMM_Handles[index].size;
|
writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val);
|
||||||
*total+=EMM_Handles[index].size;
|
}
|
||||||
}
|
|
||||||
if (EMM_Handles[index].next) index=EMM_Handles[index].next;
|
|
||||||
else break;
|
void MEM_SetupPageHandlers(Bitu startpage,Bitu pages,MEMORY_ReadHandler read,MEMORY_WriteHandler write) {
|
||||||
|
if (startpage+pages>=LOW_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler");
|
||||||
|
for (Bitu i=startpage;i<startpage+pages;i++) {
|
||||||
|
ReadHostTable[i]=0;
|
||||||
|
WriteHostTable[i]=0;
|
||||||
|
ReadHandlerTable[i]=read;
|
||||||
|
WriteHandlerTable[i]=write;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EMM_Allocate(Bit16u size,Bit16u * handle) {
|
|
||||||
Bit16u index=0;*handle=0;
|
void MEM_ClearPageHandlers(Bitu startpage,Bitu pages) {
|
||||||
while (EMM_Handles[index].active) {
|
if (startpage+pages>=LOW_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler");
|
||||||
if (EMM_Handles[index].free) {
|
for (Bitu i=startpage;i<startpage+pages;i++) {
|
||||||
/* Use entire block */
|
ReadHostTable[i]=memory;
|
||||||
if(EMM_Handles[index].size==size) {
|
WriteHostTable[i]=memory;
|
||||||
EMM_Handles[index].free=false;
|
ReadHandlerTable[i]=&Illegal_ReadHandler;;
|
||||||
*handle=index;
|
WriteHandlerTable[i]=&Illegal_WriteHandler;
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Split up block */
|
|
||||||
if(EMM_Handles[index].size>size) {
|
|
||||||
Bit16u newindex=EMM_GetFreeHandle();
|
|
||||||
EMM_Handles[newindex].active=true;
|
|
||||||
EMM_Handles[newindex].phys_base=EMM_Handles[newindex].phys_base+size*4096;
|
|
||||||
EMM_Handles[newindex].size=EMM_Handles[index].size-size;
|
|
||||||
EMM_Handles[newindex].free=true;
|
|
||||||
EMM_Handles[newindex].next=EMM_Handles[index].next;
|
|
||||||
EMM_Handles[index].next=newindex;
|
|
||||||
EMM_Handles[index].free=false;
|
|
||||||
EMM_Handles[index].size=size;
|
|
||||||
*handle=index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (EMM_Handles[index].next) index=EMM_Handles[index].next;
|
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EMM_Free(Bit16u handle) {
|
void MEM_SetupMapping(Bitu startpage,Bitu pages,void * data) {
|
||||||
if (!EMM_Handles[handle].active) E_Exit("EMM:Tried to free illegal handle");
|
if (startpage+pages>=MAX_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler");
|
||||||
EMM_Handles[handle].free=true;
|
HostPt base=(HostPt)(data)-startpage*PAGE_SIZE;
|
||||||
//TODO join memory blocks
|
if (!base) LOG_DEBUG("MEMORY:Unlucky memory allocation");
|
||||||
|
for (Bitu i=startpage;i<startpage+pages;i++) {
|
||||||
|
ReadHostTable[i]=base;
|
||||||
|
WriteHostTable[i]=base;
|
||||||
|
ReadHandlerTable[i]=&Default_ReadHandler;;
|
||||||
|
WriteHandlerTable[i]=&Default_WriteHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MEM_ClearMapping(Bitu startpage,Bitu pages) {
|
||||||
|
if (startpage+pages>=MAX_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler");
|
||||||
|
for (Bitu i=startpage;i<startpage+pages;i++) {
|
||||||
|
ReadHostTable[i]=0;
|
||||||
|
WriteHostTable[i]=0;
|
||||||
|
ReadHandlerTable[i]=&Illegal_ReadHandler;;
|
||||||
|
WriteHandlerTable[i]=&Illegal_WriteHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (!C_EXTRAINLINE)
|
||||||
|
static void HandlerWritew(Bitu page,PhysPt pt,Bit16u val) {
|
||||||
|
WriteHandlerTable[page](pt+0,(Bit8u)(val & 0xff));
|
||||||
|
WriteHandlerTable[page](pt+1,(Bit8u)((val >> 8) & 0xff) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HandlerWrited(Bitu page,PhysPt pt,Bit32u val) {
|
||||||
|
WriteHandlerTable[page](pt+0,(Bit8u)(val & 0xff));
|
||||||
|
WriteHandlerTable[page](pt+1,(Bit8u)((val >> 8) & 0xff) );
|
||||||
|
WriteHandlerTable[page](pt+2,(Bit8u)((val >> 16) & 0xff) );
|
||||||
|
WriteHandlerTable[page](pt+3,(Bit8u)((val >> 24) & 0xff) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_writeb(PhysPt pt,Bit8u val) {
|
||||||
|
if (WriteHostTable[pt >> PAGE_SHIFT]) writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val);
|
||||||
|
else {
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt,val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_writew(PhysPt pt,Bit16u val) {
|
||||||
|
if (!WriteHostTable[pt >> PAGE_SHIFT]) {
|
||||||
|
// HandlerWritew(pt >> PAGE_SHIFT,pt,val);
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff));
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) );
|
||||||
|
} else writew(WriteHostTable[pt >> PAGE_SHIFT]+pt,val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_writed(PhysPt pt,Bit32u val) {
|
||||||
|
if (!WriteHostTable[pt >> PAGE_SHIFT]) {
|
||||||
|
// HandlerWrited(pt >> PAGE_SHIFT,pt,val);
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff));
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) );
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+2,(Bit8u)((val >> 16) & 0xff) );
|
||||||
|
WriteHandlerTable[pt >> PAGE_SHIFT](pt+3,(Bit8u)((val >> 24) & 0xff) );
|
||||||
|
} else writed(WriteHostTable[pt >> PAGE_SHIFT]+pt,val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PageEntry HMA_PageEntry;
|
static Bit16u HandlerReadw(Bitu page,PhysPt pt) {
|
||||||
|
return (ReadHandlerTable[page](pt+0)) |
|
||||||
|
(ReadHandlerTable[page](pt+1)) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bit32u HandlerReadd(Bitu page,PhysPt pt) {
|
||||||
|
return (ReadHandlerTable[page](pt+0)) |
|
||||||
|
(ReadHandlerTable[page](pt+1)) << 8 |
|
||||||
|
(ReadHandlerTable[page](pt+2)) << 16 |
|
||||||
|
(ReadHandlerTable[page](pt+3)) << 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bit8u mem_readb(PhysPt pt) {
|
||||||
|
if (ReadHostTable[pt >> PAGE_SHIFT]) return readb(ReadHostTable[pt >> PAGE_SHIFT]+pt);
|
||||||
|
else {
|
||||||
|
return ReadHandlerTable[pt >> PAGE_SHIFT](pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bit16u mem_readw(PhysPt pt) {
|
||||||
|
if (!ReadHostTable[pt >> PAGE_SHIFT]) {
|
||||||
|
// return HandlerReadw(pt >> PAGE_SHIFT,pt);
|
||||||
|
return
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) |
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8;
|
||||||
|
} else return readw(ReadHostTable[pt >> PAGE_SHIFT]+pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bit32u mem_readd(PhysPt pt){
|
||||||
|
if (ReadHostTable[pt >> PAGE_SHIFT]) return readd(ReadHostTable[pt >> PAGE_SHIFT]+pt);
|
||||||
|
else {
|
||||||
|
// return HandlerReadd(pt >> PAGE_SHIFT,pt);
|
||||||
|
return
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) |
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8 |
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+2)) << 16 |
|
||||||
|
(ReadHandlerTable[pt >> PAGE_SHIFT](pt+3)) << 24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MEM_Init(void) {
|
void MEM_Init(void) {
|
||||||
memset((void *)&PageEntries,0,sizeof(PageEntries));
|
/* Init all tables */
|
||||||
memory=(Bit8u *)malloc(memsize*1024*1024);
|
Bitu i;
|
||||||
|
i=MAX_PAGES;
|
||||||
|
for (i=0;i<MAX_PAGES;i++) {
|
||||||
|
ReadHostTable[i]=0;
|
||||||
|
WriteHostTable[i]=0;
|
||||||
|
ReadHandlerTable[i]=&Default_ReadHandler;
|
||||||
|
WriteHandlerTable[i]=&Default_WriteHandler;
|
||||||
|
}
|
||||||
|
/* Allocate the first mb of memory */
|
||||||
|
memory=(Bit8u *)malloc(1024*1024);
|
||||||
if (!memory) {
|
if (!memory) {
|
||||||
E_Exit("Can't allocate memory for memory");
|
E_Exit("Can't allocate memory for memory");
|
||||||
}
|
}
|
||||||
/* Setup the HMA to wrap */
|
/* Setup tables for first mb */
|
||||||
HMA_PageEntry.type=MEMORY_RELOCATE;;
|
MEM_SetupMapping(0,PAGE_COUNT(1024*1024),memory);
|
||||||
HMA_PageEntry.base=1024*1024;
|
/* Setup tables for HMA Area */
|
||||||
HMA_PageEntry.relocate=memory;
|
MEM_SetupMapping(PAGE_COUNT(1024*1024),PAGE_COUNT(64*1024),memory);
|
||||||
Bitu i;
|
}
|
||||||
for (i=0;i<16;i++) {
|
|
||||||
PageEntries[i+256]=&HMA_PageEntry;
|
|
||||||
}
|
|
||||||
/* Setup the EMM Structures */
|
|
||||||
for (i=0;i<EMM_HANDLECOUNT;i++) {
|
|
||||||
EMM_Handles[i].active=false;
|
|
||||||
EMM_Handles[i].size=0;
|
|
||||||
}
|
|
||||||
/* Setup the first handle with free and max memory */
|
|
||||||
EMM_Handles[0].active=true;
|
|
||||||
EMM_Handles[0].free=false;
|
|
||||||
EMM_Handles[0].phys_base=0x110000;
|
|
||||||
EMM_Handles[0].next=1;
|
|
||||||
if (memsize>1) {
|
|
||||||
EMM_Handles[1].size=(memsize-1)*256-16;
|
|
||||||
} else {
|
|
||||||
EMM_Handles[0].size=0;;
|
|
||||||
}
|
|
||||||
EMM_Handles[1].active=true;
|
|
||||||
EMM_Handles[1].free=true;
|
|
||||||
EMM_Handles[1].phys_base=0x110000;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ enum {
|
|||||||
MODE_ADPCM_4S
|
MODE_ADPCM_4S
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DEBUG_SBLASTER
|
#if DEBUG_SBLASTER
|
||||||
#define SB_DEBUG LOG_DEBUG
|
#define SB_DEBUG LOG_DEBUG
|
||||||
#else
|
#else
|
||||||
#define SB_DEBUG
|
#define SB_DEBUG
|
||||||
@ -75,8 +75,11 @@ struct SB_INFO {
|
|||||||
Bit8u data_out[DSP_BUFSIZE];
|
Bit8u data_out[DSP_BUFSIZE];
|
||||||
Bit8u data_out_pos;
|
Bit8u data_out_pos;
|
||||||
Bit8u data_out_used;
|
Bit8u data_out_used;
|
||||||
Bit8u dac_data[DSP_DACSIZE];
|
struct {
|
||||||
Bit32u dac_used;
|
Bit8u data[DSP_DACSIZE];
|
||||||
|
Bitu used;
|
||||||
|
Bit8u last;
|
||||||
|
} dac;
|
||||||
Bit8u test_register;
|
Bit8u test_register;
|
||||||
/*ADPCM Part */
|
/*ADPCM Part */
|
||||||
Bits adpcm_reference;
|
Bits adpcm_reference;
|
||||||
@ -175,7 +178,7 @@ static void DSP_StartDMATranfser(Bit8u mode) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case MODE_ADPCM_4S:
|
case MODE_ADPCM_4S:
|
||||||
MIXER_SetFreq(sb.chan,sb.freq*2);
|
MIXER_SetFreq(sb.chan,sb.freq);
|
||||||
SB_DEBUG("DSP:ADPCM 4 bit single cycle rate %d size %X",sb.freq,sb.samples_total);
|
SB_DEBUG("DSP:ADPCM 4 bit single cycle rate %d size %X",sb.freq,sb.samples_total);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -204,7 +207,8 @@ static void DSP_Reset(void) {
|
|||||||
sb.cmd_len=0;
|
sb.cmd_len=0;
|
||||||
sb.cmd_in_pos=0;
|
sb.cmd_in_pos=0;
|
||||||
sb.use_time_constant=false;
|
sb.use_time_constant=false;
|
||||||
sb.dac_used=0;
|
sb.dac.used=0;
|
||||||
|
sb.dac.last=0x80;
|
||||||
e2_value=0xaa;
|
e2_value=0xaa;
|
||||||
e2_count=0;
|
e2_count=0;
|
||||||
DSP_HaltDMA();
|
DSP_HaltDMA();
|
||||||
@ -229,8 +233,8 @@ static void DSP_DoCommand(void) {
|
|||||||
switch (sb.cmd) {
|
switch (sb.cmd) {
|
||||||
case 0x10: /* Direct DAC */
|
case 0x10: /* Direct DAC */
|
||||||
sb.mode=MODE_DAC;
|
sb.mode=MODE_DAC;
|
||||||
if (sb.dac_used<DSP_DACSIZE) {
|
if (sb.dac.used<DSP_DACSIZE) {
|
||||||
sb.dac_data[sb.dac_used++]=sb.cmd_in[0];
|
sb.dac.data[sb.dac.used++]=sb.cmd_in[0];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x14: /* Singe Cycle 8-Bit DMA */
|
case 0x14: /* Singe Cycle 8-Bit DMA */
|
||||||
@ -425,38 +429,49 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) {
|
|||||||
case MODE_DAC:
|
case MODE_DAC:
|
||||||
/* Stretch the inputted dac data over len samples */
|
/* Stretch the inputted dac data over len samples */
|
||||||
{
|
{
|
||||||
Bit32u dac_add=(sb.dac_used<<16)/len;
|
if (sb.dac.used) {
|
||||||
Bit32u dac_pos=0;
|
Bitu dac_add=(sb.dac.used<<16)/len;
|
||||||
while (len-->0) {
|
Bitu dac_pos=0;
|
||||||
*(stream++)=sb.dac_data[dac_pos>>16];
|
while (len-->0) {
|
||||||
dac_pos+=dac_add;
|
*(stream++)=sb.dac.data[dac_pos>>16];
|
||||||
|
dac_pos+=dac_add;
|
||||||
|
}
|
||||||
|
dac_pos-=dac_add;
|
||||||
|
sb.dac.last=sb.dac.data[dac_pos>>16];
|
||||||
|
sb.dac.used=0;
|
||||||
|
} else {
|
||||||
|
memset(stream,sb.dac.last,len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.dac_used=0;
|
|
||||||
sb.mode=MODE_NONE;
|
|
||||||
break;
|
break;
|
||||||
case MODE_PCM_8A:
|
case MODE_PCM_8A:
|
||||||
DMA_8_Read(sb.dma,stream,(Bit16u)len);
|
{
|
||||||
if (sb.samples_left>len) {
|
Bit16u read=DMA_8_Read(sb.dma,stream,(Bit16u)len);
|
||||||
sb.samples_left-=len;
|
if (sb.samples_left>read) {
|
||||||
} else {
|
sb.samples_left-=read;
|
||||||
if (len>(sb.samples_total+sb.samples_left)) sb.samples_left=sb.samples_total;
|
} else {
|
||||||
else sb.samples_left=sb.samples_total+sb.samples_left-len;
|
if (read>(sb.samples_total+sb.samples_left)) sb.samples_left=sb.samples_total;
|
||||||
PIC_ActivateIRQ(sb.irq);
|
else sb.samples_left=sb.samples_total+sb.samples_left-read;
|
||||||
|
PIC_ActivateIRQ(sb.irq);
|
||||||
|
}
|
||||||
|
if (read<len) memset(stream+read,0x80,len-read);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MODE_PCM_8S:
|
case MODE_PCM_8S:
|
||||||
if (sb.samples_left>=len) {
|
{
|
||||||
DMA_8_Read(sb.dma,stream,(Bit16u)len);
|
Bit16u read;
|
||||||
sb.samples_left-=len;
|
if (sb.samples_left>=len) {
|
||||||
} else if (sb.samples_left && (sb.samples_left<len)) {
|
read=DMA_8_Read(sb.dma,stream,(Bit16u)len);
|
||||||
DMA_8_Read(sb.dma,stream,(Bit16u)sb.samples_left);
|
sb.samples_left-=read;
|
||||||
memset(stream+sb.samples_left,0x80,len-sb.samples_left);
|
} else {
|
||||||
sb.samples_left=0;
|
read=DMA_8_Read(sb.dma,stream,(Bit16u)sb.samples_left);
|
||||||
}
|
sb.samples_left=0;
|
||||||
if (sb.samples_left==0) {
|
}
|
||||||
DSP_StopDMA();
|
if (read<len) memset(stream+read,0x80,len-read);
|
||||||
PIC_ActivateIRQ(sb.irq);
|
if (sb.samples_left==0) {
|
||||||
|
DSP_StopDMA();
|
||||||
|
PIC_ActivateIRQ(sb.irq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MODE_ADPCM_4S:
|
case MODE_ADPCM_4S:
|
||||||
@ -470,26 +485,28 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) {
|
|||||||
if (sb.adpcm_reference < 0) {
|
if (sb.adpcm_reference < 0) {
|
||||||
dma_size++;
|
dma_size++;
|
||||||
}
|
}
|
||||||
|
Bit16u read;
|
||||||
/* Read from the DMA Channel */
|
/* Read from the DMA Channel */
|
||||||
if (sb.samples_left>=dma_size) {
|
if (sb.samples_left>=dma_size) {
|
||||||
DMA_8_Read(sb.dma,decode_pos,(Bit16u)dma_size);
|
read=DMA_8_Read(sb.dma,decode_pos,(Bit16u)dma_size);
|
||||||
sb.samples_left-=dma_size;
|
|
||||||
} else if (sb.samples_left<dma_size) {
|
} else if (sb.samples_left<dma_size) {
|
||||||
DMA_8_Read(sb.dma,decode_pos,(Bit16u)sb.samples_left);
|
read=DMA_8_Read(sb.dma,decode_pos,(Bit16u)sb.samples_left);
|
||||||
//Could go wrong with the reference byte i think.
|
}
|
||||||
memset(stream+sb.samples_left*2,0x80,len-sb.samples_left*2);
|
sb.samples_left-=read;
|
||||||
len=sb.samples_left*2;
|
if (sb.adpcm_reference < 0 && read) {
|
||||||
sb.samples_left=0;
|
sb.adpcm_reference=*decode_pos++;
|
||||||
|
read--;
|
||||||
|
}
|
||||||
|
if ((read*2U)<(Bitu)len) {
|
||||||
|
memset(stream+read*2,0x80,len-read*2);
|
||||||
|
len=read*2;
|
||||||
}
|
}
|
||||||
if (sb.samples_left==0) {
|
if (sb.samples_left==0) {
|
||||||
// if (sb.mode==MODE_PCM_8A) sb.samples_left=sb.samples_total;
|
|
||||||
// else
|
|
||||||
DSP_StopDMA();
|
DSP_StopDMA();
|
||||||
PIC_ActivateIRQ(sb.irq);
|
PIC_ActivateIRQ(sb.irq);
|
||||||
}
|
}
|
||||||
if (sb.adpcm_reference < 0) {
|
if (!read) return;
|
||||||
sb.adpcm_reference=*decode_pos++;
|
/* Decode the actual samples read from dma */
|
||||||
}
|
|
||||||
for (Bitu i=len/2;i>0;i--) {
|
for (Bitu i=len/2;i>0;i--) {
|
||||||
*stream++=decode_ADPCM_4_sample(*decode_pos >> 4,sb.adpcm_reference,sb.adpcm_scale);
|
*stream++=decode_ADPCM_4_sample(*decode_pos >> 4,sb.adpcm_reference,sb.adpcm_scale);
|
||||||
*stream++=decode_ADPCM_4_sample(*decode_pos++ ,sb.adpcm_reference,sb.adpcm_scale);
|
*stream++=decode_ADPCM_4_sample(*decode_pos++ ,sb.adpcm_reference,sb.adpcm_scale);
|
||||||
@ -501,7 +518,8 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) {
|
|||||||
sb.adpcm_remain=-1;
|
sb.adpcm_remain=-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
} /* End switch */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
VGA_Type vga;
|
VGA_Type vga;
|
||||||
Bit32u CGAWriteTable[256];
|
Bit32u CGAWriteTable[256];
|
||||||
Bit32u ExpandTable[256];
|
Bit32u ExpandTable[256];
|
||||||
|
Bit32u Expand16Table[4][16];
|
||||||
|
Bit32u Expand16BigTable[0x10000];
|
||||||
|
|
||||||
Bit32u FillTable[16]={
|
Bit32u FillTable[16]={
|
||||||
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
|
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
|
||||||
@ -37,8 +39,9 @@ Bit32u FillTable[16]={
|
|||||||
0xffff0000,0xffff00ff,0xffffff00,0xffffffff
|
0xffff0000,0xffff00ff,0xffffff00,0xffffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
static PageEntry VGA_PageEntry;
|
|
||||||
|
|
||||||
|
|
||||||
|
void VGA_Render_GFX_2(Bit8u * * data);
|
||||||
void VGA_Render_GFX_4(Bit8u * * data);
|
void VGA_Render_GFX_4(Bit8u * * data);
|
||||||
void VGA_Render_GFX_16(Bit8u * * data);
|
void VGA_Render_GFX_16(Bit8u * * data);
|
||||||
void VGA_Render_GFX_256C(Bit8u * * data);
|
void VGA_Render_GFX_256C(Bit8u * * data);
|
||||||
@ -47,8 +50,7 @@ void VGA_Render_TEXT_16(Bit8u * * data);
|
|||||||
|
|
||||||
void VGA_FindSettings(void) {
|
void VGA_FindSettings(void) {
|
||||||
/* Sets up the correct memory handler from the vga.mode setting */
|
/* Sets up the correct memory handler from the vga.mode setting */
|
||||||
MEMORY_ResetHandler(0xA0000/4096,128*1024/4096);
|
MEM_ClearPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x20000));
|
||||||
VGA_PageEntry.type=MEMORY_HANDLER;
|
|
||||||
/* Detect the kind of video mode this is */
|
/* Detect the kind of video mode this is */
|
||||||
if (vga.config.gfxmode) {
|
if (vga.config.gfxmode) {
|
||||||
if (vga.config.vga_enabled) {
|
if (vga.config.vga_enabled) {
|
||||||
@ -59,26 +61,20 @@ void VGA_FindSettings(void) {
|
|||||||
} else {
|
} else {
|
||||||
/* 256 color unchained vga */
|
/* 256 color unchained vga */
|
||||||
vga.mode=GFX_256U;
|
vga.mode=GFX_256U;
|
||||||
VGA_PageEntry.base=0xA0000;
|
MEM_SetupPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x10000),
|
||||||
VGA_PageEntry.handler.read=VGA_NormalReadHandler;
|
&VGA_NormalReadHandler,&VGA_GFX_256U_WriteHandler);
|
||||||
VGA_PageEntry.handler.write=VGA_GFX_256U_WriteHandler;
|
|
||||||
MEMORY_SetupHandler(0xA0000/4096,16,&VGA_PageEntry);
|
|
||||||
}
|
}
|
||||||
} else if (vga.config.cga_enabled) {
|
} else if (vga.config.cga_enabled) {
|
||||||
/* 4 color cga */
|
/* 4 color cga */
|
||||||
//TODO Detect hercules modes, probably set them up in bios too
|
//TODO Detect hercules modes, probably set them up in bios too
|
||||||
vga.mode=GFX_4;
|
if (vga.config.pixel_double) vga.mode=GFX_4;
|
||||||
// VGA_PageEntry.base=0xB8000;
|
else vga.mode=GFX_2;
|
||||||
// VGA_PageEntry.handler.read=VGA_GFX_4_ReadHandler;
|
//TODO Maybe also use a page handler for cga mode
|
||||||
// VGA_PageEntry.handler.write=VGA_GFX_4_WriteHandler;
|
|
||||||
// MEMORY_SetupHandler(0xB8000/4096,8,&VGA_PageEntry);
|
|
||||||
} else {
|
} else {
|
||||||
/* 16 color ega */
|
/* 16 color ega */
|
||||||
vga.mode=GFX_16;
|
vga.mode=GFX_16;
|
||||||
VGA_PageEntry.base=0xA0000;
|
MEM_SetupPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x10000),
|
||||||
VGA_PageEntry.handler.read=VGA_NormalReadHandler;
|
&VGA_NormalReadHandler,&VGA_GFX_16_WriteHandler);
|
||||||
VGA_PageEntry.handler.write=VGA_GFX_16_WriteHandler;
|
|
||||||
MEMORY_SetupHandler(0xA0000/4096,16,&VGA_PageEntry);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vga.mode=TEXT_16;
|
vga.mode=TEXT_16;
|
||||||
@ -119,6 +115,12 @@ static void VGA_DoResize(void) {
|
|||||||
pitch=width;
|
pitch=width;
|
||||||
renderer=&VGA_Render_GFX_4;
|
renderer=&VGA_Render_GFX_4;
|
||||||
break;
|
break;
|
||||||
|
case GFX_2:
|
||||||
|
width<<=3;
|
||||||
|
height<<=1;
|
||||||
|
pitch=width;
|
||||||
|
renderer=&VGA_Render_GFX_2;
|
||||||
|
break;
|
||||||
case TEXT_16:
|
case TEXT_16:
|
||||||
/* probably a 16-color text mode, got to detect mono mode somehow */
|
/* probably a 16-color text mode, got to detect mono mode somehow */
|
||||||
width<<=3; /* 8 bit wide text font */
|
width<<=3; /* 8 bit wide text font */
|
||||||
@ -144,22 +146,51 @@ void VGA_StartResize(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void VGA_Init() {
|
void VGA_Init() {
|
||||||
vga.draw.resizing=false;
|
vga.draw.resizing=false;
|
||||||
VGA_SetupMemory();
|
VGA_SetupMemory();
|
||||||
VGA_SetupMisc();
|
VGA_SetupMisc();
|
||||||
VGA_SetupDAC();
|
VGA_SetupDAC();
|
||||||
VGA_SetupCRTC();
|
|
||||||
VGA_SetupGFX();
|
VGA_SetupGFX();
|
||||||
VGA_SetupSEQ();
|
VGA_SetupSEQ();
|
||||||
VGA_SetupAttr();
|
VGA_SetupAttr();
|
||||||
/* Generate tables */
|
/* Generate tables */
|
||||||
Bit32u i;
|
Bitu i,j;
|
||||||
for (i=0;i<256;i++) {
|
for (i=0;i<256;i++) {
|
||||||
ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24);
|
ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24);
|
||||||
CGAWriteTable[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24);
|
CGAWriteTable[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24);
|
||||||
}
|
}
|
||||||
|
for (j=0;j<4;j++) {
|
||||||
|
for (i=0;i<16;i++) {
|
||||||
|
Expand16Table[j][i] =
|
||||||
|
((i & 1) ? 1 << (24 + j) : 0) |
|
||||||
|
((i & 2) ? 1 << (16 + j) : 0) |
|
||||||
|
((i & 4) ? 1 << (8 + j) : 0) |
|
||||||
|
((i & 8) ? 1 << j : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i=0;i<0x10000;i++) {
|
||||||
|
Bit32u val=0;
|
||||||
|
if (i & 0x1) val|=0x1 << 24;
|
||||||
|
if (i & 0x2) val|=0x1 << 16;
|
||||||
|
if (i & 0x4) val|=0x1 << 8;
|
||||||
|
if (i & 0x8) val|=0x1 << 0;
|
||||||
|
|
||||||
|
if (i & 0x10) val|=0x4 << 24;
|
||||||
|
if (i & 0x20) val|=0x4 << 16;
|
||||||
|
if (i & 0x40) val|=0x4 << 8;
|
||||||
|
if (i & 0x80) val|=0x4 << 0;
|
||||||
|
|
||||||
|
if (i & 0x100) val|=0x2 << 24;
|
||||||
|
if (i & 0x200) val|=0x2 << 16;
|
||||||
|
if (i & 0x400) val|=0x2 << 8;
|
||||||
|
if (i & 0x800) val|=0x2 << 0;
|
||||||
|
|
||||||
|
if (i & 0x1000) val|=0x8 << 24;
|
||||||
|
if (i & 0x2000) val|=0x8 << 16;
|
||||||
|
if (i & 0x4000) val|=0x8 << 8;
|
||||||
|
if (i & 0x8000) val|=0x8 << 0;
|
||||||
|
Expand16BigTable[i]=val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ typedef struct {
|
|||||||
bool vline_double;
|
bool vline_double;
|
||||||
Bit8u vline_height;
|
Bit8u vline_height;
|
||||||
|
|
||||||
|
bool pixel_double;
|
||||||
/* Pixel Scrolling */
|
/* Pixel Scrolling */
|
||||||
Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */
|
Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */
|
||||||
Bit8u hlines_skip;
|
Bit8u hlines_skip;
|
||||||
@ -64,11 +65,14 @@ typedef struct {
|
|||||||
Bit8u color_compare;
|
Bit8u color_compare;
|
||||||
Bit8u data_rotate;
|
Bit8u data_rotate;
|
||||||
Bit8u raster_op;
|
Bit8u raster_op;
|
||||||
Bit8u enable_set_reset;
|
|
||||||
Bit8u set_reset;
|
|
||||||
|
|
||||||
Bit32u full_bit_mask;
|
Bit32u full_bit_mask;
|
||||||
Bit32u full_map_mask;
|
Bit32u full_map_mask;
|
||||||
|
Bit32u full_not_map_mask;
|
||||||
|
Bit32u full_set_reset;
|
||||||
|
Bit32u full_not_enable_set_reset;
|
||||||
|
Bit32u full_enable_set_reset;
|
||||||
|
Bit32u full_enable_and_set_reset;
|
||||||
|
|
||||||
} VGA_Config;
|
} VGA_Config;
|
||||||
|
|
||||||
@ -211,17 +215,14 @@ void VGA_DrawGFX256_Fast(Bit8u * bitdata,Bitu next_line);
|
|||||||
void VGA_DrawGFX256_Full(Bit8u * bitdata,Bitu next_line);
|
void VGA_DrawGFX256_Full(Bit8u * bitdata,Bitu next_line);
|
||||||
void VGA_DrawGFX16_Full(Bit8u * bitdata,Bitu next_line);
|
void VGA_DrawGFX16_Full(Bit8u * bitdata,Bitu next_line);
|
||||||
void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu next_line);
|
void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu next_line);
|
||||||
|
void VGA_DrawGFX2_Full(Bit8u * bitdata,Bitu next_line);
|
||||||
/* The Different Memory Read/Write Handlers */
|
/* The Different Memory Read/Write Handlers */
|
||||||
Bit8u VGA_NormalReadHandler(Bit32u start);
|
Bit8u VGA_NormalReadHandler(Bit32u start);
|
||||||
void VGA_NormalWriteHandler(Bit32u start,Bit8u val);
|
|
||||||
|
|
||||||
void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val);
|
void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val);
|
||||||
void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val);
|
void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val);
|
||||||
void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val);
|
void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val);
|
||||||
|
|
||||||
Bit8u VGA_ChainedReadHandler(Bit32u start);
|
|
||||||
void VGA_ChainedWriteHandler(Bit32u start,Bit8u val);
|
|
||||||
|
|
||||||
Bit8u VGA_GFX_4_ReadHandler(Bit32u start);
|
Bit8u VGA_GFX_4_ReadHandler(Bit32u start);
|
||||||
|
|
||||||
|
|
||||||
@ -246,10 +247,19 @@ extern VGA_Type vga;
|
|||||||
extern Bit8u vga_rom_8[256 * 8];
|
extern Bit8u vga_rom_8[256 * 8];
|
||||||
extern Bit8u vga_rom_14[256 * 14];
|
extern Bit8u vga_rom_14[256 * 14];
|
||||||
extern Bit8u vga_rom_16[256 * 16];
|
extern Bit8u vga_rom_16[256 * 16];
|
||||||
//extern Bit8u vga_buffer[1024*1024];
|
|
||||||
extern Bit32u ExpandTable[256];
|
extern Bit32u ExpandTable[256];
|
||||||
extern Bit32u FillTable[16];
|
extern Bit32u FillTable[16];
|
||||||
extern Bit32u CGAWriteTable[256];
|
extern Bit32u CGAWriteTable[256];
|
||||||
|
extern Bit32u Expand16Table[4][16];
|
||||||
|
extern Bit32u Expand16BigTable[0x10000];
|
||||||
|
|
||||||
|
#if DEBUG_VGA
|
||||||
|
#define LOG_VGA LOG_DEBUG
|
||||||
|
#else
|
||||||
|
#define LOG_VGA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -129,6 +129,7 @@ void write_p3c0(Bit32u port,Bit8u val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bit8u read_p3c1(Bit32u port) {
|
Bit8u read_p3c1(Bit32u port) {
|
||||||
|
vga.internal.attrindex=false;
|
||||||
switch (attr(index)) {
|
switch (attr(index)) {
|
||||||
/* Palette */
|
/* Palette */
|
||||||
case 0x00: case 0x01: case 0x02: case 0x03:
|
case 0x00: case 0x01: case 0x02: case 0x03:
|
||||||
|
@ -28,6 +28,11 @@ void write_p3d4(Bit32u port,Bit8u val) {
|
|||||||
crtc(index)=val;
|
crtc(index)=val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bit8u read_p3d4(Bit32u port) {
|
||||||
|
return crtc(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void write_p3d5(Bit32u port,Bit8u val) {
|
void write_p3d5(Bit32u port,Bit8u val) {
|
||||||
switch(crtc(index)) {
|
switch(crtc(index)) {
|
||||||
case 0x00: /* Horizontal Total Register */
|
case 0x00: /* Horizontal Total Register */
|
||||||
@ -37,7 +42,7 @@ void write_p3d5(Bit32u port,Bit8u val) {
|
|||||||
case 0x01: /* Horizontal Display End Register */
|
case 0x01: /* Horizontal Display End Register */
|
||||||
crtc(horizontal_display_end)=val;
|
crtc(horizontal_display_end)=val;
|
||||||
vga.config.hdisplayend=val+1;
|
vga.config.hdisplayend=val+1;
|
||||||
VGA_FindSettings();
|
VGA_StartResize();
|
||||||
/* 0-7 Number of Character Clocks Displayed -1 */
|
/* 0-7 Number of Character Clocks Displayed -1 */
|
||||||
break;
|
break;
|
||||||
case 0x02: /* Start Horizontal Blanking Register */
|
case 0x02: /* Start Horizontal Blanking Register */
|
||||||
@ -78,8 +83,8 @@ void write_p3d5(Bit32u port,Bit8u val) {
|
|||||||
break;
|
break;
|
||||||
case 0x07: /* Overflow Register */
|
case 0x07: /* Overflow Register */
|
||||||
crtc(overflow)=val;
|
crtc(overflow)=val;
|
||||||
vga.config.vdisplayend=(vga.config.vdisplayend&0xFF)|((val&2)<<7)|((val&64)<<2);
|
vga.config.vdisplayend=(vga.config.vdisplayend&0xFF)|(((val>>1) & 1)<<8)|(((val>>6) & 1)<<9);
|
||||||
VGA_FindSettings();
|
VGA_StartResize();
|
||||||
/*
|
/*
|
||||||
0 Bit 8 of Vertical Total (3d4h index 6)
|
0 Bit 8 of Vertical Total (3d4h index 6)
|
||||||
1 Bit 8 of Vertical Display End (3d4h index 12h)
|
1 Bit 8 of Vertical Display End (3d4h index 12h)
|
||||||
@ -108,7 +113,7 @@ void write_p3d5(Bit32u port,Bit8u val) {
|
|||||||
crtc(maximum_scan_line)=val;
|
crtc(maximum_scan_line)=val;
|
||||||
vga.config.vline_double=(val & 128)>1;
|
vga.config.vline_double=(val & 128)>1;
|
||||||
vga.config.vline_height=(val & 0xf);
|
vga.config.vline_height=(val & 0xf);
|
||||||
VGA_FindSettings();
|
VGA_StartResize();
|
||||||
/*
|
/*
|
||||||
0-4 Number of scan lines in a character row -1. In graphics modes this is
|
0-4 Number of scan lines in a character row -1. In graphics modes this is
|
||||||
the number of times (-1) the line is displayed before passing on to
|
the number of times (-1) the line is displayed before passing on to
|
||||||
@ -183,7 +188,7 @@ void write_p3d5(Bit32u port,Bit8u val) {
|
|||||||
case 0x12: /* Vertical Display End Register */
|
case 0x12: /* Vertical Display End Register */
|
||||||
crtc(vertical_display_end)=val;
|
crtc(vertical_display_end)=val;
|
||||||
vga.config.vdisplayend=(vga.config.vdisplayend & 0x300)|val;
|
vga.config.vdisplayend=(vga.config.vdisplayend & 0x300)|val;
|
||||||
VGA_FindSettings();
|
VGA_StartResize();
|
||||||
/*
|
/*
|
||||||
0-7 Lower 8 bits of Vertical Display End. The display ends when the line
|
0-7 Lower 8 bits of Vertical Display End. The display ends when the line
|
||||||
counter reaches this value. Bit 8 is found in 3d4h index 7 bit 1.
|
counter reaches this value. Bit 8 is found in 3d4h index 7 bit 1.
|
||||||
@ -193,7 +198,7 @@ void write_p3d5(Bit32u port,Bit8u val) {
|
|||||||
case 0x13: /* Offset register */
|
case 0x13: /* Offset register */
|
||||||
crtc(offset)=val;
|
crtc(offset)=val;
|
||||||
vga.config.scan_len=val;
|
vga.config.scan_len=val;
|
||||||
VGA_FindSettings();
|
VGA_StartResize();
|
||||||
/*
|
/*
|
||||||
0-7 Number of bytes in a scanline / K. Where K is 2 for byte mode, 4 for
|
0-7 Number of bytes in a scanline / K. Where K is 2 for byte mode, 4 for
|
||||||
word mode and 8 for Double Word mode.
|
word mode and 8 for Double Word mode.
|
||||||
@ -317,16 +322,4 @@ Bit8u read_p3d5(Bit32u port) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void VGA_SetupCRTC(void) {
|
|
||||||
IO_RegisterWriteHandler(0x3d4,write_p3d4,"VGA:CRTC Index Select");
|
|
||||||
IO_RegisterWriteHandler(0x3d5,write_p3d5,"VGA:CRTC Data Register");
|
|
||||||
IO_RegisterReadHandler(0x3d5,read_p3d5,"VGA:CRTC Data Register");
|
|
||||||
|
|
||||||
// IO_RegisterWriteHandler(0x3b4,write_p3d4,"VGA:CRTC Index Select");
|
|
||||||
// IO_RegisterWriteHandler(0x3b5,write_p3d5,"VGA:CRTC Data Register");
|
|
||||||
// IO_RegisterReadHandler(0x3b5,read_p3d5,"VGA:CRTC Data Register");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -55,6 +55,12 @@ enum {DAC_READ,DAC_WRITE};
|
|||||||
|
|
||||||
static void write_p3c6(Bit32u port,Bit8u val) {
|
static void write_p3c6(Bit32u port,Bit8u val) {
|
||||||
if (val!=0xff) LOG_ERROR("VGA:Pel Mask not 0xff");
|
if (val!=0xff) LOG_ERROR("VGA:Pel Mask not 0xff");
|
||||||
|
vga.dac.pel_mask=val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Bit8u read_p3c6(Bit32u port) {
|
||||||
|
return vga.dac.pel_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -151,6 +157,7 @@ void VGA_SetupDAC(void) {
|
|||||||
|
|
||||||
/* Setup the DAC IO port Handlers */
|
/* Setup the DAC IO port Handlers */
|
||||||
IO_RegisterWriteHandler(0x3c6,write_p3c6,"PEL Mask");
|
IO_RegisterWriteHandler(0x3c6,write_p3c6,"PEL Mask");
|
||||||
|
IO_RegisterReadHandler(0x3c6,read_p3c6,"PEL Mask");
|
||||||
IO_RegisterWriteHandler(0x3c7,write_p3c7,"PEL Read Mode");
|
IO_RegisterWriteHandler(0x3c7,write_p3c7,"PEL Read Mode");
|
||||||
IO_RegisterWriteHandler(0x3c8,write_p3c8,"PEL Write Mode");
|
IO_RegisterWriteHandler(0x3c8,write_p3c8,"PEL Write Mode");
|
||||||
IO_RegisterWriteHandler(0x3c9,write_p3c9,"PEL Data");
|
IO_RegisterWriteHandler(0x3c9,write_p3c9,"PEL Data");
|
||||||
|
@ -23,6 +23,11 @@
|
|||||||
|
|
||||||
|
|
||||||
/* This Should draw a complete 16 colour screen */
|
/* This Should draw a complete 16 colour screen */
|
||||||
|
void VGA_Render_GFX_2(Bit8u * * data) {
|
||||||
|
*data=vga.buffer;
|
||||||
|
VGA_DrawGFX2_Full(vga.buffer,vga.draw.width);
|
||||||
|
vga.config.retrace=true;
|
||||||
|
}
|
||||||
|
|
||||||
void VGA_Render_GFX_4(Bit8u * * data) {
|
void VGA_Render_GFX_4(Bit8u * * data) {
|
||||||
*data=vga.buffer;
|
*data=vga.buffer;
|
||||||
@ -47,16 +52,43 @@ void VGA_Render_GFX_256C(Bit8u * * data) {
|
|||||||
|
|
||||||
void VGA_Render_TEXT_16(Bit8u * * data) {
|
void VGA_Render_TEXT_16(Bit8u * * data) {
|
||||||
*data=vga.buffer;
|
*data=vga.buffer;
|
||||||
VGA_DrawTEXT(vga.buffer,vga.draw.width);
|
if (!vga.draw.resizing) VGA_DrawTEXT(vga.buffer,vga.draw.width);
|
||||||
|
vga.config.retrace=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VGA_DrawGFX2_Full(Bit8u * bitdata,Bitu pitch) {
|
||||||
|
Bit8u * reader=HostMake(0xB800,0);
|
||||||
|
Bit8u * draw;
|
||||||
|
for (Bitu y=0;y<vga.draw.height;y++) {
|
||||||
|
Bit8u * tempread;
|
||||||
|
tempread=reader;
|
||||||
|
if (y&1) {
|
||||||
|
tempread+=8*1024;
|
||||||
|
reader+=80;
|
||||||
|
};
|
||||||
|
draw=bitdata;
|
||||||
|
//TODO Look up table like in 4color mode
|
||||||
|
for (Bit32u x=0;x<vga.draw.width>>3;x++) {
|
||||||
|
Bit8u val=*(tempread++);
|
||||||
|
*(draw+0)=(val>>7)&1;
|
||||||
|
*(draw+1)=(val>>6)&1;
|
||||||
|
*(draw+2)=(val>>5)&1;
|
||||||
|
*(draw+3)=(val>>4)&1;
|
||||||
|
*(draw+4)=(val>>3)&1;
|
||||||
|
*(draw+5)=(val>>2)&1;
|
||||||
|
*(draw+6)=(val>>1)&1;
|
||||||
|
*(draw+7)=(val>>0)&1;
|
||||||
|
draw+=8;
|
||||||
|
}
|
||||||
|
bitdata+=pitch;
|
||||||
|
};
|
||||||
vga.config.retrace=true;
|
vga.config.retrace=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu pitch) {
|
||||||
void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu next_line) {
|
Bit8u * reader=HostMake(0xB800,0);
|
||||||
//TODO use vga memory handler
|
|
||||||
Bit8u * reader=real_host(0xB800,0);
|
|
||||||
Bit8u * draw;
|
Bit8u * draw;
|
||||||
for (Bitu y=0;y<vga.draw.height;y++) {
|
for (Bitu y=0;y<vga.draw.height;y++) {
|
||||||
Bit8u * tempread;
|
Bit8u * tempread;
|
||||||
@ -68,23 +100,17 @@ void VGA_DrawGFX4_Full(Bit8u * bitdata,Bitu next_line) {
|
|||||||
draw=bitdata;
|
draw=bitdata;
|
||||||
for (Bit32u x=0;x<vga.draw.width>>2;x++) {
|
for (Bit32u x=0;x<vga.draw.width>>2;x++) {
|
||||||
Bit8u val=*(tempread++);
|
Bit8u val=*(tempread++);
|
||||||
/*
|
|
||||||
*(draw+0)=(val>>6)&3;
|
|
||||||
*(draw+1)=(val>>4)&3;
|
|
||||||
*(draw+2)=(val>>2)&3;
|
|
||||||
*(draw+3)=(val)&3;
|
|
||||||
draw+=4;
|
|
||||||
*/
|
|
||||||
*(Bit32u *)draw=CGAWriteTable[val];
|
*(Bit32u *)draw=CGAWriteTable[val];
|
||||||
draw+=4;
|
draw+=4;
|
||||||
}
|
}
|
||||||
//TODO use scanline length and dword mode crap
|
bitdata+=pitch;
|
||||||
bitdata+=next_line;
|
|
||||||
};
|
};
|
||||||
vga.config.retrace=true;
|
vga.config.retrace=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VGA_DrawGFX16_Full(Bit8u * bitdata,Bitu next_line) {
|
/* Draw the screen using the lookup buffer */
|
||||||
|
//TODO include split screen or something
|
||||||
|
void VGA_DrawGFX16_Fast(Bit8u * bitdata,Bitu next_line) {
|
||||||
Bit8u * reader=&vga.buffer[vga.config.display_start*8+vga.config.pel_panning];
|
Bit8u * reader=&vga.buffer[vga.config.display_start*8+vga.config.pel_panning];
|
||||||
for (Bitu y=0;y<vga.draw.height;y++) {
|
for (Bitu y=0;y<vga.draw.height;y++) {
|
||||||
memcpy((void *)bitdata,(void *)reader,vga.draw.width);
|
memcpy((void *)bitdata,(void *)reader,vga.draw.width);
|
||||||
@ -95,11 +121,10 @@ void VGA_DrawGFX16_Full(Bit8u * bitdata,Bitu next_line) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* This Should draw a complete 256 colour screen */
|
|
||||||
|
|
||||||
void VGA_DrawGFX256_Full(Bit8u * bitdata,Bitu next_line) {
|
void VGA_DrawGFX256_Full(Bit8u * bitdata,Bitu next_line) {
|
||||||
Bit16u yreader=vga.config.display_start*1;
|
Bit16u yreader=vga.config.display_start*1;
|
||||||
/* Now add pel panning */
|
/* TODO add pel panning */
|
||||||
for (Bitu y=0;y<vga.draw.height;y++) {
|
for (Bitu y=0;y<vga.draw.height;y++) {
|
||||||
Bit16u xreader=yreader;
|
Bit16u xreader=yreader;
|
||||||
for (Bitu x=0;x<vga.draw.width>>2;x++) {
|
for (Bitu x=0;x<vga.draw.width>>2;x++) {
|
||||||
@ -108,28 +133,26 @@ void VGA_DrawGFX256_Full(Bit8u * bitdata,Bitu next_line) {
|
|||||||
}
|
}
|
||||||
xreader++;
|
xreader++;
|
||||||
}
|
}
|
||||||
//TODO use scanline length and dword mode crap
|
|
||||||
yreader+=vga.config.scan_len*2;
|
yreader+=vga.config.scan_len*2;
|
||||||
bitdata+=next_line;
|
bitdata+=next_line;
|
||||||
};
|
};
|
||||||
vga.config.retrace=true;
|
vga.config.retrace=true;
|
||||||
};
|
};
|
||||||
|
|
||||||
void VGA_DrawGFX256_Fast(Bit8u * bitdata,Bitu next_line) {
|
void VGA_DrawGFX256_Fast(Bit8u * bitdata,Bitu pitch) {
|
||||||
/* For now just copy 64 kb of memory with pitch support */
|
/* For now just copy 64 kb of memory with pitch support */
|
||||||
Bit8u * reader=memory+0xa0000;
|
Bit8u * reader=memory+0xa0000;
|
||||||
for (Bitu y=0;y<vga.draw.height;y++) {
|
for (Bitu y=0;y<vga.draw.height;y++) {
|
||||||
memcpy((void *)bitdata,(void *)reader,vga.draw.width);
|
memcpy((void *)bitdata,(void *)reader,vga.draw.width);
|
||||||
bitdata+=vga.draw.width+next_line;
|
bitdata+=pitch;
|
||||||
reader+=vga.draw.width;
|
reader+=vga.draw.width;
|
||||||
}
|
}
|
||||||
//memcpy((void *)bitdata,(void *)(memory+0xa0000),320*200);
|
|
||||||
vga.config.retrace=true;
|
vga.config.retrace=true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void VGA_DrawTEXT(Bit8u * bitdata,Bitu next_line) {
|
void VGA_DrawTEXT(Bit8u * bitdata,Bitu pitch) {
|
||||||
Bit8u * reader=real_off(0xB800,0);
|
Bit8u * reader=HostMake(0xB800,0);
|
||||||
Bit8u * draw_start=bitdata;;
|
Bit8u * draw_start=bitdata;;
|
||||||
/* Todo Blinking and high intensity colors */
|
/* Todo Blinking and high intensity colors */
|
||||||
for (Bitu cy=0;cy<(vga.draw.height/16);cy++) {
|
for (Bitu cy=0;cy<(vga.draw.height/16);cy++) {
|
||||||
@ -144,18 +167,18 @@ void VGA_DrawTEXT(Bit8u * bitdata,Bitu next_line) {
|
|||||||
for (Bitu y=0;y<16;y++) {
|
for (Bitu y=0;y<16;y++) {
|
||||||
Bit8u bit_mask=*findex++;
|
Bit8u bit_mask=*findex++;
|
||||||
#include "font-switch.h"
|
#include "font-switch.h"
|
||||||
draw+=+next_line;
|
draw+=pitch;
|
||||||
};
|
};
|
||||||
draw_char+=8;
|
draw_char+=8;
|
||||||
};
|
};
|
||||||
draw_start+=16*next_line;
|
draw_start+=16*pitch;
|
||||||
};
|
};
|
||||||
vga.config.retrace=true;
|
vga.config.retrace=true;
|
||||||
|
|
||||||
/* Draw a cursor */
|
/* Draw a cursor */
|
||||||
if ((vga.draw.cursor_col*8)>=vga.draw.width) return;
|
if ((vga.draw.cursor_col*8)>=vga.draw.width) return;
|
||||||
if ((vga.draw.cursor_row*16)>=vga.draw.height) return;
|
if ((vga.draw.cursor_row*16)>=vga.draw.height) return;
|
||||||
Bit8u * cursor_draw=bitdata+(vga.draw.cursor_row*16+15)*vga.draw.width+vga.draw.cursor_col*8;
|
Bit8u * cursor_draw=bitdata+(vga.draw.cursor_row*16+15)*pitch+vga.draw.cursor_col*8;
|
||||||
if (vga.draw.cursor_count>8) {
|
if (vga.draw.cursor_count>8) {
|
||||||
for (Bit8u loop=0;loop<8;loop++) *cursor_draw++=15;
|
for (Bit8u loop=0;loop<8;loop++) *cursor_draw++=15;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,9 @@ void write_p3cf(Bit32u port,Bit8u val) {
|
|||||||
switch (gfx(index)) {
|
switch (gfx(index)) {
|
||||||
case 0: /* Set/Reset Register */
|
case 0: /* Set/Reset Register */
|
||||||
gfx(set_reset)=val & 0x0f;
|
gfx(set_reset)=val & 0x0f;
|
||||||
vga.config.set_reset=val & 0x0f;
|
vga.config.full_set_reset=FillTable[val & 0x0f];
|
||||||
|
vga.config.full_enable_and_set_reset=vga.config.full_set_reset &
|
||||||
|
vga.config.full_enable_set_reset;
|
||||||
/*
|
/*
|
||||||
0 If in Write Mode 0 and bit 0 of 3CEh index 1 is set a write to
|
0 If in Write Mode 0 and bit 0 of 3CEh index 1 is set a write to
|
||||||
display memory will set all the bits in plane 0 of the byte to this
|
display memory will set all the bits in plane 0 of the byte to this
|
||||||
@ -50,15 +52,10 @@ void write_p3cf(Bit32u port,Bit8u val) {
|
|||||||
break;
|
break;
|
||||||
case 1: /* Enable Set/Reset Register */
|
case 1: /* Enable Set/Reset Register */
|
||||||
gfx(enable_set_reset)=val & 0x0f;
|
gfx(enable_set_reset)=val & 0x0f;
|
||||||
vga.config.enable_set_reset=val & 0x0f;
|
vga.config.full_enable_set_reset=FillTable[val & 0x0f];
|
||||||
/*
|
vga.config.full_not_enable_set_reset=~vga.config.full_enable_set_reset;
|
||||||
0 If set enables Set/reset of plane 0 in Write Mode 0.
|
vga.config.full_enable_and_set_reset=vga.config.full_set_reset &
|
||||||
1 Same for plane 1.
|
vga.config.full_enable_set_reset;
|
||||||
2 Same for plane 2.
|
|
||||||
3 Same for plane 3.
|
|
||||||
*/
|
|
||||||
// LOG_DEBUG("Enable Set Reset = %2X",val);
|
|
||||||
break;
|
|
||||||
case 2: /* Color Compare Register */
|
case 2: /* Color Compare Register */
|
||||||
gfx(color_compare)=val & 0x0f;
|
gfx(color_compare)=val & 0x0f;
|
||||||
/*
|
/*
|
||||||
|
@ -35,7 +35,8 @@ void VGA_ChainedWriteHandler(Bit32u start,Bit8u val) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Bit8u VGA_NormalReadHandler(Bit32u start) {
|
Bit8u VGA_NormalReadHandler(PhysPt start) {
|
||||||
|
start-=0xa0000;
|
||||||
vga.latch.d=vga.mem.latched[start].d;
|
vga.latch.d=vga.mem.latched[start].d;
|
||||||
switch (vga.config.read_mode) {
|
switch (vga.config.read_mode) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -49,7 +50,7 @@ Bit8u VGA_NormalReadHandler(Bit32u start) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Nice one from DosEmu
|
//Nice one from DosEmu
|
||||||
INLINE Bit32u RasterOp(Bit32u input,Bit32u mask) {
|
INLINE static Bit32u RasterOp(Bit32u input,Bit32u mask) {
|
||||||
switch (vga.config.raster_op) {
|
switch (vga.config.raster_op) {
|
||||||
case 0x00: /* None */
|
case 0x00: /* None */
|
||||||
return (input & mask) | (vga.latch.d & ~mask);
|
return (input & mask) | (vga.latch.d & ~mask);
|
||||||
@ -63,11 +64,39 @@ INLINE Bit32u RasterOp(Bit32u input,Bit32u mask) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INLINE static Bit32u ModeOperation(Bit8u val) {
|
||||||
|
Bit32u full;
|
||||||
|
switch (vga.config.write_mode) {
|
||||||
|
case 0x00:
|
||||||
|
// Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
||||||
|
full=ExpandTable[val];
|
||||||
|
full=(full & vga.config.full_not_enable_set_reset) | vga.config.full_enable_and_set_reset;
|
||||||
|
full=RasterOp(full,vga.config.full_bit_mask);
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
// Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode.
|
||||||
|
full=vga.latch.d;
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
//Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
||||||
|
full=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask);
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
// Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
||||||
|
full=RasterOp(vga.config.full_set_reset,ExpandTable[val] & vga.config.full_bit_mask);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR("VGA:Unsupported write mode %d",vga.config.write_mode);
|
||||||
|
}
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
|
||||||
Bit8u VGA_GFX_4_ReadHandler(Bit32u start) {
|
Bit8u VGA_GFX_4_ReadHandler(Bit32u start) {
|
||||||
return vga.mem.linear[start];
|
return vga.mem.linear[start];
|
||||||
}
|
}
|
||||||
|
|
||||||
void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val) {
|
void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val) {
|
||||||
|
start-=0xa0000;
|
||||||
vga.mem.linear[start]=val;
|
vga.mem.linear[start]=val;
|
||||||
Bitu line=start / 320;
|
Bitu line=start / 320;
|
||||||
Bitu x=start % 320;
|
Bitu x=start % 320;
|
||||||
@ -80,114 +109,45 @@ void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val) {
|
void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val) {
|
||||||
VGA_Latch new_latch;
|
start-=0xa0000;
|
||||||
Bitu bit_mask;
|
Bit32u data=ModeOperation(val);
|
||||||
switch (vga.config.write_mode) {
|
|
||||||
case 0x00:
|
|
||||||
// Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
|
||||||
// val=(val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate));
|
|
||||||
//Todo could also include the rotation in the table :)
|
|
||||||
new_latch.d=ExpandTable[val];
|
|
||||||
{
|
|
||||||
Bit32u resetmask=FillTable[vga.config.enable_set_reset];
|
|
||||||
new_latch.d=(new_latch.d & ~resetmask) | ( FillTable[vga.config.set_reset] & resetmask);
|
|
||||||
};
|
|
||||||
new_latch.d=RasterOp(new_latch.d,vga.config.full_bit_mask);
|
|
||||||
bit_mask=vga.gfx.bit_mask;
|
|
||||||
break;
|
|
||||||
case 0x01:
|
|
||||||
// Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode.
|
|
||||||
new_latch.d=vga.latch.d;
|
|
||||||
bit_mask=0xff;
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
//Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
|
||||||
new_latch.d=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask);
|
|
||||||
bit_mask=vga.gfx.bit_mask;
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
// Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
|
||||||
new_latch.d=ExpandTable[val];
|
|
||||||
new_latch.d&=vga.config.full_bit_mask; //Dunno would anyone use this seems a bit pointless
|
|
||||||
bit_mask=new_latch.b[0];
|
|
||||||
new_latch.d=RasterOp(FillTable[vga.config.set_reset],new_latch.d);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_ERROR("VGA:Unsupported write mode %d",vga.config.write_mode);
|
|
||||||
}
|
|
||||||
/* Update video memory and the pixel buffer */
|
/* Update video memory and the pixel buffer */
|
||||||
VGA_Latch pixels;
|
VGA_Latch pixels;
|
||||||
pixels.d=vga.mem.latched[start].d;
|
pixels.d=vga.mem.latched[start].d;
|
||||||
pixels.d&=~vga.config.full_map_mask;
|
pixels.d&=vga.config.full_not_map_mask;
|
||||||
pixels.d|=(new_latch.d & vga.config.full_map_mask);
|
pixels.d|=(data & vga.config.full_map_mask);
|
||||||
vga.mem.latched[start].d=pixels.d;
|
vga.mem.latched[start].d=pixels.d;
|
||||||
Bit8u * write_pixels=&vga.buffer[start<<3];
|
Bit8u * write_pixels=&vga.buffer[start<<3];
|
||||||
#if 1
|
|
||||||
Bit8u sel=128;
|
|
||||||
do {
|
|
||||||
if (bit_mask & sel) {
|
|
||||||
Bitu color;
|
|
||||||
color=0;
|
|
||||||
if (pixels.b[0] & sel) color|=1;
|
|
||||||
if (pixels.b[1] & sel) color|=2;
|
|
||||||
if (pixels.b[2] & sel) color|=4;
|
|
||||||
if (pixels.b[3] & sel) color|=8;
|
|
||||||
*write_pixels=color;
|
|
||||||
*(write_pixels+512*1024)=color;
|
|
||||||
|
|
||||||
}
|
Bit32u colors0_3, colors4_7;
|
||||||
write_pixels++;
|
VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f;
|
||||||
sel>>=1;
|
colors0_3 =
|
||||||
} while (sel);
|
Expand16Table[0][temp.b[0]] |
|
||||||
#else
|
Expand16Table[1][temp.b[1]] |
|
||||||
#include "ega-switch.h"
|
Expand16Table[2][temp.b[2]] |
|
||||||
#endif
|
Expand16Table[3][temp.b[3]];
|
||||||
|
*(Bit32u *)write_pixels=colors0_3;
|
||||||
|
*(Bit32u *)(write_pixels+512*1024)=colors0_3;
|
||||||
|
temp.d=pixels.d & 0x0f0f0f0f;
|
||||||
|
colors4_7 =
|
||||||
|
Expand16Table[0][temp.b[0]] |
|
||||||
|
Expand16Table[1][temp.b[1]] |
|
||||||
|
Expand16Table[2][temp.b[2]] |
|
||||||
|
Expand16Table[3][temp.b[3]];
|
||||||
|
*(Bit32u *)(write_pixels+4)=colors4_7;
|
||||||
|
*(Bit32u *)(write_pixels+512*1024+4)=colors4_7;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val) {
|
void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val) {
|
||||||
VGA_Latch new_latch;
|
start-=0xa0000;
|
||||||
switch (vga.config.write_mode) {
|
Bit32u data=ModeOperation(val);
|
||||||
case 0x00:
|
|
||||||
/* This should be no problem with big or little endian */
|
|
||||||
// Write Mode 0: In this mode, the host data is first rotated as per the Rotate Count field, then the Enable Set/Reset mechanism selects data from this or the Set/Reset field. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
|
||||||
// val=(val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate));
|
|
||||||
//Todo could also include the rotation in the table :)
|
|
||||||
new_latch.d=ExpandTable[val];
|
|
||||||
{
|
|
||||||
Bit32u resetmask=FillTable[vga.config.enable_set_reset];
|
|
||||||
new_latch.d=(new_latch.d & ~resetmask) | ( FillTable[vga.config.set_reset] & resetmask);
|
|
||||||
};
|
|
||||||
new_latch.d=RasterOp(new_latch.d,vga.config.full_bit_mask);
|
|
||||||
break;
|
|
||||||
case 0x01:
|
|
||||||
// Write Mode 1: In this mode, data is transferred directly from the 32 bit latch register to display memory, affected only by the Memory Plane Write Enable field. The host data is not used in this mode.
|
|
||||||
new_latch.d=vga.latch.d;
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
//TODO this mode also has Raster op
|
|
||||||
//Write Mode 2: In this mode, the bits 3-0 of the host data are replicated across all 8 bits of their respective planes. Then the selected Logical Operation is performed on the resulting data and the data in the latch register. Then the Bit Mask field is used to select which bits come from the resulting data and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
|
||||||
new_latch.d=RasterOp(FillTable[val&0xF],vga.config.full_bit_mask);
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
// Write Mode 3: In this mode, the data in the Set/Reset field is used as if the Enable Set/Reset field were set to 1111b. Then the host data is first rotated as per the Rotate Count field, then logical ANDed with the value of the Bit Mask field. The resulting value is used on the data obtained from the Set/Reset field in the same way that the Bit Mask field would ordinarily be used. to select which bits come from the expansion of the Set/Reset field and which come from the latch register. Finally, only the bit planes enabled by the Memory Plane Write Enable field are written to memory.
|
|
||||||
new_latch.d=ExpandTable[val];
|
|
||||||
new_latch.d&=vga.config.full_bit_mask; //Dunno would anyone use this seems a bit pointless
|
|
||||||
new_latch.d=RasterOp(FillTable[vga.config.set_reset],new_latch.d);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
E_Exit("VGA:Unsupported write mode %d",vga.config.write_mode);
|
|
||||||
}
|
|
||||||
VGA_Latch pixels;
|
VGA_Latch pixels;
|
||||||
pixels.d=vga.mem.latched[start].d;
|
pixels.d=vga.mem.latched[start].d;
|
||||||
pixels.d&=~vga.config.full_map_mask;
|
pixels.d&=vga.config.full_not_map_mask;
|
||||||
pixels.d|=(new_latch.d & vga.config.full_map_mask);
|
pixels.d|=(data & vga.config.full_map_mask);
|
||||||
vga.mem.latched[start].d=pixels.d;
|
vga.mem.latched[start].d=pixels.d;
|
||||||
vga.mem.latched[start+64*1024].d=pixels.d;
|
vga.mem.latched[start+64*1024].d=pixels.d;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,12 @@
|
|||||||
static Bit8u flip=0;
|
static Bit8u flip=0;
|
||||||
static Bit32u keep_vretrace;
|
static Bit32u keep_vretrace;
|
||||||
static bool keeping=false;
|
static bool keeping=false;
|
||||||
static Bit8u p3c2data;
|
static Bit8u p3c2data=0;
|
||||||
|
|
||||||
|
void write_p3d4(Bit32u port,Bit8u val);
|
||||||
|
Bit8u read_p3d4(Bit32u port);
|
||||||
|
void write_p3d5(Bit32u port,Bit8u val);
|
||||||
|
Bit8u read_p3d5(Bit32u port);
|
||||||
|
|
||||||
static Bit8u read_p3da(Bit32u port) {
|
static Bit8u read_p3da(Bit32u port) {
|
||||||
vga.internal.attrindex=false;
|
vga.internal.attrindex=false;
|
||||||
@ -45,26 +50,68 @@ static Bit8u read_p3da(Bit32u port) {
|
|||||||
if (flip>5) return 1;
|
if (flip>5) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
/*
|
||||||
|
0 Either Vertical or Horizontal Retrace active if set
|
||||||
|
3 Vertical Retrace in progress if set
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void write_p3d8(Bit32u port,Bit8u val) {
|
static void write_p3d8(Bit32u port,Bit8u val) {
|
||||||
return;
|
/*
|
||||||
|
3 Vertical Sync Select. If set Vertical Sync to the monitor is the
|
||||||
|
logical OR of the vertical sync and the vertical display enable.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_p3c2(Bit32u port,Bit8u val) {
|
static void write_p3c2(Bit32u port,Bit8u val) {
|
||||||
p3c2data=val;
|
p3c2data=val;
|
||||||
|
if (val & 1) {
|
||||||
|
IO_RegisterWriteHandler(0x3d4,write_p3d4,"VGA:CRTC Index Select");
|
||||||
|
IO_RegisterReadHandler(0x3d4,read_p3d4,"VGA:CRTC Index Select");
|
||||||
|
IO_RegisterWriteHandler(0x3d5,write_p3d5,"VGA:CRTC Data Register");
|
||||||
|
IO_RegisterReadHandler(0x3d5,read_p3d5,"VGA:CRTC Data Register");
|
||||||
|
IO_FreeWriteHandler(0x3b4);
|
||||||
|
IO_FreeReadHandler(0x3b4);
|
||||||
|
IO_FreeWriteHandler(0x3b5);
|
||||||
|
IO_FreeReadHandler(0x3b5);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
IO_RegisterWriteHandler(0x3b4,write_p3d4,"VGA:CRTC Index Select");
|
||||||
|
IO_RegisterReadHandler(0x3b4,read_p3d4,"VGA:CRTC Index Select");
|
||||||
|
IO_RegisterWriteHandler(0x3b5,write_p3d5,"VGA:CRTC Data Register");
|
||||||
|
IO_RegisterReadHandler(0x3b5,read_p3d5,"VGA:CRTC Data Register");
|
||||||
|
IO_FreeWriteHandler(0x3d4);
|
||||||
|
IO_FreeReadHandler(0x3d4);
|
||||||
|
IO_FreeWriteHandler(0x3d5);
|
||||||
|
IO_FreeReadHandler(0x3d5);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
0 If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base Address=3Bxh.
|
||||||
|
2-3 Clock Select. 0: 25MHz, 1: 28MHz
|
||||||
|
5 When in Odd/Even modes Select High 64k bank if set
|
||||||
|
6 Horizontal Sync Polarity. Negative if set
|
||||||
|
7 Vertical Sync Polarity. Negative if set
|
||||||
|
Bit 6-7 indicates the number of lines on the display:
|
||||||
|
1: 400, 2: 350, 3: 480
|
||||||
|
Note: Set to all zero on a hardware reset.
|
||||||
|
Note: This register can be read from port 3CCh.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
static Bit8u read_p3c2(Bit32u port) {
|
|
||||||
|
|
||||||
|
static Bit8u read_p3cc(Bit32u port) {
|
||||||
return p3c2data;
|
return p3c2data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VGA_SetupMisc(void) {
|
void VGA_SetupMisc(void) {
|
||||||
IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1");
|
IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1");
|
||||||
// IO_RegisterWriteHandler(0x3d8,write_p3d8,"VGA Mode Control");
|
IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1");
|
||||||
|
|
||||||
|
IO_RegisterWriteHandler(0x3d8,write_p3d8,"VGA Feature Control Register");
|
||||||
IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output");
|
IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output");
|
||||||
IO_RegisterReadHandler(0x3c2,read_p3c2,"VGA Misc Output");
|
IO_RegisterReadHandler(0x3cc,read_p3cc,"VGA Misc Output");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ void write_p3c5(Bit32u port,Bit8u val) {
|
|||||||
break;
|
break;
|
||||||
case 1: /* Clocking Mode */
|
case 1: /* Clocking Mode */
|
||||||
seq(clocking_mode)=val;
|
seq(clocking_mode)=val;
|
||||||
|
vga.config.pixel_double=(val & 8)>0;
|
||||||
|
VGA_FindSettings();
|
||||||
/* TODO Figure this out :)
|
/* TODO Figure this out :)
|
||||||
0 If set character clocks are 8 dots wide, else 9.
|
0 If set character clocks are 8 dots wide, else 9.
|
||||||
2 If set loads video serializers every other character
|
2 If set loads video serializers every other character
|
||||||
@ -53,6 +55,7 @@ void write_p3c5(Bit32u port,Bit8u val) {
|
|||||||
case 2: /* Map Mask */
|
case 2: /* Map Mask */
|
||||||
seq(map_mask)=val & 15;
|
seq(map_mask)=val & 15;
|
||||||
vga.config.full_map_mask=FillTable[val & 15];
|
vga.config.full_map_mask=FillTable[val & 15];
|
||||||
|
vga.config.full_not_map_mask=~vga.config.full_map_mask;
|
||||||
/*
|
/*
|
||||||
0 Enable writes to plane 0 if set
|
0 Enable writes to plane 0 if set
|
||||||
1 Enable writes to plane 1 if set
|
1 Enable writes to plane 1 if set
|
||||||
|
@ -101,6 +101,10 @@ static Bitu INT11_Handler(void) {
|
|||||||
static Bitu INT8_Handler(void) {
|
static Bitu INT8_Handler(void) {
|
||||||
/* Increase the bios tick counter */
|
/* Increase the bios tick counter */
|
||||||
mem_writed(BIOS_TIMER,mem_readd(BIOS_TIMER)+1);
|
mem_writed(BIOS_TIMER,mem_readd(BIOS_TIMER)+1);
|
||||||
|
/* decrease floppy motor timer */
|
||||||
|
Bit8u val = mem_readb(BIOS_DISK_MOTOR_TIMEOUT);
|
||||||
|
if (val>0) mem_writeb(BIOS_DISK_MOTOR_TIMEOUT,val-1);
|
||||||
|
|
||||||
CALLBACK_RunRealInt(0x1c);
|
CALLBACK_RunRealInt(0x1c);
|
||||||
IO_Write(0x20,0x20);
|
IO_Write(0x20,0x20);
|
||||||
return CBRET_NONE;
|
return CBRET_NONE;
|
||||||
@ -141,6 +145,10 @@ static Bitu INT15_Handler(void) {
|
|||||||
LOG_WARN("Request BIOS Configuration INT 15 C0");
|
LOG_WARN("Request BIOS Configuration INT 15 C0");
|
||||||
CALLBACK_SCF(true);
|
CALLBACK_SCF(true);
|
||||||
break;
|
break;
|
||||||
|
case 0x4f: /* BIOS - Keyboard intercept */
|
||||||
|
/* Carry should be set but let's just set it just in case */
|
||||||
|
CALLBACK_SCF(true);
|
||||||
|
break;
|
||||||
case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */
|
case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */
|
||||||
//Does anyone even use this?
|
//Does anyone even use this?
|
||||||
LOG_WARN("INT15:84:Bios Joystick functionality not done");
|
LOG_WARN("INT15:84:Bios Joystick functionality not done");
|
||||||
|
@ -28,32 +28,6 @@ static BIOS_Disk * Floppys[2];
|
|||||||
static BIOS_Disk * Harddisks[BIOS_MAX_DISK];
|
static BIOS_Disk * Harddisks[BIOS_MAX_DISK];
|
||||||
static Bit8u last_status;
|
static Bit8u last_status;
|
||||||
|
|
||||||
static Bitu INT13_FullHandler(void) {
|
|
||||||
/* Check for disk numbers */
|
|
||||||
BIOS_Disk * disk=Floppys[0];
|
|
||||||
switch (reg_ah) {
|
|
||||||
case 0x00:
|
|
||||||
last_status=reg_ah=0;
|
|
||||||
break;
|
|
||||||
case 0x01: /* Get Status of last operation */
|
|
||||||
reg_ah=last_status;
|
|
||||||
break;
|
|
||||||
case 0x02: /* Read Sectors into Memory */
|
|
||||||
last_status=reg_ah=disk->Read_Sector(®_al,reg_dh,reg_ch,(reg_cl & 0x3f)-1,real_off(Segs[es].value,reg_bx));
|
|
||||||
CALLBACK_SCF(false);
|
|
||||||
break;
|
|
||||||
case 0x03: /* Write Sectors from Memory */
|
|
||||||
last_status=reg_ah=disk->Write_Sector(®_al,reg_dh,reg_ch,(reg_cl & 0x3f)-1,real_off(Segs[es].value,reg_bx));
|
|
||||||
CALLBACK_SCF(false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_DEBUG("INT13:Illegal call %2X",reg_ah);
|
|
||||||
reg_ah=0xff;
|
|
||||||
CALLBACK_SCF(true);
|
|
||||||
}
|
|
||||||
return CBRET_NONE;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static Bitu INT13_SmallHandler(void) {
|
static Bitu INT13_SmallHandler(void) {
|
||||||
switch (reg_ah) {
|
switch (reg_ah) {
|
||||||
@ -79,13 +53,7 @@ static Bitu INT13_SmallHandler(void) {
|
|||||||
void BIOS_SetupDisks(void) {
|
void BIOS_SetupDisks(void) {
|
||||||
/* TODO Start the time correctly */
|
/* TODO Start the time correctly */
|
||||||
call_int13=CALLBACK_Allocate();
|
call_int13=CALLBACK_Allocate();
|
||||||
#ifdef C_IMAGE
|
|
||||||
Floppys[0]=new imageDisk("c:\\test.img");
|
|
||||||
for (Bit32u i=0;i<BIOS_MAX_DISK;i++) Harddisks[i]=0;
|
|
||||||
CALLBACK_Setup(call_int13,&INT13_FullHandler,CB_IRET);
|
|
||||||
#else
|
|
||||||
CALLBACK_Setup(call_int13,&INT13_SmallHandler,CB_IRET);
|
CALLBACK_Setup(call_int13,&INT13_SmallHandler,CB_IRET);
|
||||||
#endif
|
|
||||||
RealSetVec(0x13,CALLBACK_RealPointer(call_int13));
|
RealSetVec(0x13,CALLBACK_RealPointer(call_int13));
|
||||||
/* Init the Disk Tables */
|
/* Init the Disk Tables */
|
||||||
last_status=0;
|
last_status=0;
|
||||||
|
@ -123,27 +123,6 @@ static struct {
|
|||||||
{ 0x5300, 0x532e, none, none } /* Del */
|
{ 0x5300, 0x532e, none, none } /* Del */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Old Stuff not needed after i ripped Bochs :)
|
|
||||||
static Bit8u KeyNoShift[128]={
|
|
||||||
27,'1','2','3', '4','5','6','7', '8','9','0','-', '=',8,9,'q',
|
|
||||||
'w','e','r','t', 'y','u','i','o', 'p','[',']',13, 255,'a','s','d',
|
|
||||||
'f','g','h','j', 'k','l',';','\'', '`',255,'\\','z', 'x','c','v','b',
|
|
||||||
'n','m',',','.', '/',255,'*',255, ' ',255,0,0, 0,0,0,0,
|
|
||||||
0,0,0,0, 255,255,0,0, 0,'-',0,255, 0,'+',0,0,
|
|
||||||
0,0,0,0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static Bit8u KeyShift[128]={
|
|
||||||
27,'!','@','#', '$','%','^','&', '*','(',')','_', '+',8,9,'Q',
|
|
||||||
'W','E','R','T', 'Y','U','I','O', 'P','{','}',13, 255,'A','S','D',
|
|
||||||
'F','G','H','J', 'K','L',':','"', '~',255,'|','Z', 'X','C','V','B',
|
|
||||||
'N','M','<','>', '?',255,'*',255, ' ',255,0,0, 0,0,0,0,
|
|
||||||
0,0,0,0, 255,255,0,0, 0,'-',0,255, 0,'+',0,0,
|
|
||||||
0,0,0,0, 0
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void add_key(Bit16u code) {
|
static void add_key(Bit16u code) {
|
||||||
Bit16u start,end,head,tail,ttail;
|
Bit16u start,end,head,tail,ttail;
|
||||||
start=mem_readw(BIOS_KEYBOARD_BUFFER_START);
|
start=mem_readw(BIOS_KEYBOARD_BUFFER_START);
|
||||||
@ -151,10 +130,12 @@ static void add_key(Bit16u code) {
|
|||||||
head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD);
|
head =mem_readw(BIOS_KEYBOARD_BUFFER_HEAD);
|
||||||
tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL);
|
tail =mem_readw(BIOS_KEYBOARD_BUFFER_TAIL);
|
||||||
ttail=tail+2;
|
ttail=tail+2;
|
||||||
if (ttail>=end) ttail=start;
|
if (ttail>=end) {
|
||||||
|
ttail=start;
|
||||||
|
}
|
||||||
/* Check for buffer Full */
|
/* Check for buffer Full */
|
||||||
//TODO Maybe beeeeeeep or something although that should happend when internal buffer is full
|
//TODO Maybe beeeeeeep or something although that should happend when internal buffer is full
|
||||||
if (ttail==head) return;
|
if (ttail==head) return;
|
||||||
real_writew(0x40,tail,code);
|
real_writew(0x40,tail,code);
|
||||||
mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,ttail);
|
mem_writew(BIOS_KEYBOARD_BUFFER_TAIL,ttail);
|
||||||
}
|
}
|
||||||
|
468
src/ints/ems.cpp
468
src/ints/ems.cpp
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
@ -28,105 +29,396 @@
|
|||||||
#include "dos_inc.h"
|
#include "dos_inc.h"
|
||||||
|
|
||||||
|
|
||||||
#define PAGEFRAME_SEG 0xe000
|
#define EMM_PAGEFRAME 0xE000
|
||||||
|
#define EMM_MAX_HANDLES 50 /* 255 Max */
|
||||||
|
#define EMM_PAGE_SIZE (16*1024)
|
||||||
|
#define EMM_MAX_PAGES (C_MEM_EMS_SIZE * 1024 / 16 )
|
||||||
|
#define EMM_MAX_PHYS 4 /* 4 16kb pages in pageframe */
|
||||||
|
|
||||||
class device_EMS : public DOS_Device {
|
#define EMM_VERSION 0x40
|
||||||
|
|
||||||
|
#define NULL_HANDLE 0xffff
|
||||||
|
#define NULL_PAGE 0xffff
|
||||||
|
|
||||||
|
/* EMM errors */
|
||||||
|
#define EMM_NO_ERROR 0x00
|
||||||
|
#define EMM_SOFT_MAL 0x80
|
||||||
|
#define EMM_HARD_MAL 0x81
|
||||||
|
#define EMM_INVALID_HANDLE 0x83
|
||||||
|
#define EMM_FUNC_NOSUP 0x84
|
||||||
|
#define EMM_OUT_OF_HANDLES 0x85
|
||||||
|
#define EMM_OUT_OF_PHYS 0x87
|
||||||
|
#define EMM_OUT_OF_LOG 0x88
|
||||||
|
#define EMM_ZERO_PAGES 0x89
|
||||||
|
#define EMM_LOG_OUT_RANGE 0x8a
|
||||||
|
#define EMM_ILL_PHYS 0x8b
|
||||||
|
#define EMM_PAGE_MAP_SAVED 0x8d
|
||||||
|
#define EMM_INVALID_SUB 0x8f
|
||||||
|
#define EMM_FEAT_NOSUP 0x91
|
||||||
|
#define EMM_MOVE_OVLAP 0x92
|
||||||
|
#define EMM_MOVE_OVLAPI 0x97
|
||||||
|
#define EMM_NOT_FOUND 0xa0
|
||||||
|
|
||||||
|
|
||||||
|
class device_EMM : public DOS_Device {
|
||||||
public:
|
public:
|
||||||
device_EMS();
|
device_EMM(){name="EMMXXXX0";}
|
||||||
bool Read(Bit8u * data,Bit16u * size);
|
bool Read(Bit8u * data,Bit16u * size) { return false;}
|
||||||
bool Write(Bit8u * data,Bit16u * size);
|
bool Write(Bit8u * data,Bit16u * size){
|
||||||
bool Seek(Bit32u * pos,Bit32u type);
|
LOG_DEBUG("Write to ems device");
|
||||||
bool Close();
|
return false;
|
||||||
Bit16u GetInformation(void);
|
}
|
||||||
|
bool Seek(Bit32u * pos,Bit32u type){return false;}
|
||||||
|
bool Close(){return false;}
|
||||||
|
Bit16u GetInformation(void){return 0x8093;}
|
||||||
private:
|
private:
|
||||||
Bit8u cache;
|
Bit8u cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool device_EMS::Read(Bit8u * data,Bit16u * size) {
|
struct EMM_Mapping {
|
||||||
return false;
|
Bit16u handle;
|
||||||
}
|
Bit16u page;
|
||||||
|
|
||||||
bool device_EMS::Write(Bit8u * data,Bit16u * size) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool device_EMS::Seek(Bit32u * pos,Bit32u type) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool device_EMS::Close() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bit16u device_EMS::GetInformation(void) {
|
|
||||||
return 0x8093;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
device_EMS::device_EMS() {
|
struct EMM_Page {
|
||||||
name="EMMXXXX0";
|
void * memory;
|
||||||
|
Bit16u handle;
|
||||||
|
Bit16u next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EMM_Handle {
|
||||||
|
Bit16u first_page;
|
||||||
|
Bit16u pages;
|
||||||
|
char name[9];
|
||||||
|
bool saved_page_map;
|
||||||
|
EMM_Mapping page_map[EMM_MAX_PHYS];
|
||||||
|
};
|
||||||
|
|
||||||
|
static EMM_Handle emm_handles[EMM_MAX_HANDLES];
|
||||||
|
static EMM_Page emm_pages[EMM_MAX_PAGES];
|
||||||
|
static EMM_Mapping emm_mappings[EMM_MAX_PHYS];
|
||||||
|
Bitu call_int67;
|
||||||
|
|
||||||
|
static Bit16u EMM_GetFreePages(void) {
|
||||||
|
Bit16u count=0;
|
||||||
|
for (Bitu index=0;index<EMM_MAX_PAGES;index++) {
|
||||||
|
if (emm_pages[index].handle==NULL_HANDLE) count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Bit8u EMM_AllocateMemory(Bit16u pages,Bit16u & handle) {
|
||||||
|
/* Check for 0 page allocation */
|
||||||
|
if (!pages) return EMM_ZERO_PAGES;
|
||||||
|
/* Check for enough free pages */
|
||||||
|
if (EMM_GetFreePages()<pages){ handle=NULL_HANDLE; return EMM_OUT_OF_LOG;}
|
||||||
|
handle=1;
|
||||||
|
/* Check for a free handle */
|
||||||
|
while (emm_handles[handle].first_page!=NULL_PAGE) {
|
||||||
|
if (++handle>=EMM_MAX_HANDLES) {handle=NULL_HANDLE;return EMM_OUT_OF_HANDLES;}
|
||||||
|
}
|
||||||
|
/* Allocate the pages */
|
||||||
|
Bit16u page=0;Bit16u last=NULL_PAGE;
|
||||||
|
emm_handles[handle].pages=pages;
|
||||||
|
while (pages) {
|
||||||
|
if (emm_pages[page].handle==NULL_HANDLE) {
|
||||||
|
emm_pages[page].handle=handle;
|
||||||
|
emm_pages[page].memory=malloc(EMM_PAGE_SIZE);
|
||||||
|
if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory");
|
||||||
|
if (last!=NULL_PAGE) emm_pages[last].next=page;
|
||||||
|
else emm_handles[handle].first_page=page;
|
||||||
|
last=page;
|
||||||
|
pages--;
|
||||||
|
} else {
|
||||||
|
if (++page>=EMM_MAX_PAGES) E_Exit("EMM:Ran out of pages");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
PageEntry ems_entries[4];
|
static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) {
|
||||||
|
/* Check for valid handle */
|
||||||
|
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE;
|
||||||
|
/* Check for enough pages */
|
||||||
|
if ((emm_handles[handle].pages+EMM_GetFreePages())<pages) return EMM_OUT_OF_LOG;
|
||||||
|
Bit16u page=emm_handles[handle].first_page;
|
||||||
|
Bit16u last=page;
|
||||||
|
Bit16u page_count=emm_handles[handle].pages;
|
||||||
|
while (pages>0 && page_count>0) {
|
||||||
|
if (emm_pages[page].handle!=handle) E_Exit("EMM:Error illegal handle reference");
|
||||||
|
last=page;
|
||||||
|
page=emm_pages[page].next;
|
||||||
|
pages--;
|
||||||
|
page_count--;
|
||||||
|
}
|
||||||
|
/* Free the rest of the handles */
|
||||||
|
if (page_count && !pages) {
|
||||||
|
emm_handles[handle].pages-=page_count;
|
||||||
|
while (page_count>0) {
|
||||||
|
free(emm_pages[page].memory);
|
||||||
|
emm_pages[page].memory=0;
|
||||||
|
emm_pages[page].handle=NULL_HANDLE;
|
||||||
|
Bit16u next_page=emm_pages[page].next;
|
||||||
|
emm_pages[page].next=NULL_PAGE;
|
||||||
|
page=next_page;page_count--;
|
||||||
|
}
|
||||||
|
pages=emm_handles[handle].pages;
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
if (!page_count && pages) {
|
||||||
|
/* Allocate extra pages */
|
||||||
|
emm_handles[handle].pages+=pages;
|
||||||
|
page=0;
|
||||||
|
while (pages) {
|
||||||
|
if (emm_pages[page].handle==NULL_HANDLE) {
|
||||||
|
emm_pages[page].handle=handle;
|
||||||
|
emm_pages[page].memory=malloc(EMM_PAGE_SIZE);
|
||||||
|
if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory");
|
||||||
|
emm_pages[last].next=page;
|
||||||
|
last=page;
|
||||||
|
pages--;
|
||||||
|
} else {
|
||||||
|
if (++page>=EMM_MAX_PAGES) E_Exit("EMM:Ran out of pages");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pages=emm_handles[handle].pages;
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
/* Size exactly the same as the original size */
|
||||||
|
pages=emm_handles[handle].pages;
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
|
||||||
|
/* Check for too high physical page */
|
||||||
|
if (phys_page>=EMM_MAX_PHYS) return EMM_ILL_PHYS;
|
||||||
|
/* Check for valid handle */
|
||||||
|
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE;
|
||||||
|
/* Check to do unmapping or mappning */
|
||||||
|
if (log_page<emm_handles[handle].pages) {
|
||||||
|
/* Mapping it is */
|
||||||
|
emm_mappings[phys_page].handle=handle;
|
||||||
|
emm_mappings[phys_page].page=log_page;
|
||||||
|
Bit16u index=emm_handles[handle].first_page;
|
||||||
|
while (log_page) {
|
||||||
|
index=emm_pages[index].next;
|
||||||
|
if (index==NULL_PAGE) E_Exit("EMM:Detected NULL Page in chain");
|
||||||
|
log_page--;
|
||||||
|
}
|
||||||
|
/* Do the actual mapping */
|
||||||
|
MEM_SetupMapping(PAGE_COUNT(PhysMake(EMM_PAGEFRAME,phys_page*EMM_PAGE_SIZE)),PAGE_COUNT(PAGE_SIZE),emm_pages[index].memory);
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
} else if (log_page==NULL_PAGE) {
|
||||||
|
/* Unmapping it is */
|
||||||
|
emm_mappings[phys_page].handle=NULL_HANDLE;
|
||||||
|
emm_mappings[phys_page].page=NULL_PAGE;
|
||||||
|
MEM_ClearMapping(PAGE_COUNT(PhysMake(EMM_PAGEFRAME,phys_page*EMM_PAGE_SIZE)),PAGE_COUNT(PAGE_SIZE));
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
} else {
|
||||||
|
/* Illegal logical page it is */
|
||||||
|
return EMM_LOG_OUT_RANGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bit8u EMM_ReleaseMemory(Bit16u handle) {
|
||||||
|
/* Check for valid handle */
|
||||||
|
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE;
|
||||||
|
Bit16u page=emm_handles[handle].first_page;
|
||||||
|
Bit16u pages=emm_handles[handle].pages;
|
||||||
|
while (pages) {
|
||||||
|
free(emm_pages[page].memory);
|
||||||
|
emm_pages[page].memory=0;
|
||||||
|
emm_pages[page].handle=NULL_HANDLE;
|
||||||
|
Bit16u next_page=emm_pages[page].next;
|
||||||
|
emm_pages[page].next=NULL_PAGE;
|
||||||
|
page=next_page;pages--;
|
||||||
|
}
|
||||||
|
/* Reset handle */
|
||||||
|
emm_handles[handle].first_page=NULL_PAGE;
|
||||||
|
emm_handles[handle].pages=0;
|
||||||
|
emm_handles[handle].saved_page_map=false;
|
||||||
|
memset(&emm_handles[handle].name,0,9);
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bit8u EMM_SavePageMap(Bit16u handle) {
|
||||||
|
/* Check for valid handle */
|
||||||
|
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE;
|
||||||
|
/* Check for previous save */
|
||||||
|
if (emm_handles[handle].saved_page_map) return EMM_PAGE_MAP_SAVED;
|
||||||
|
/* Copy the mappings over */
|
||||||
|
for (Bitu i=0;i<EMM_MAX_PHYS;i++) {
|
||||||
|
emm_handles[handle].page_map[i].page=emm_mappings[i].page;
|
||||||
|
emm_handles[handle].page_map[i].handle=emm_mappings[i].handle;
|
||||||
|
}
|
||||||
|
emm_handles[handle].saved_page_map=true;
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bitu EMM_RestoreMappingTable(void) {
|
||||||
|
Bit8u result;
|
||||||
|
/* Move through the mappings table and setup mapping accordingly */
|
||||||
|
for (Bitu i=0;i<EMM_MAX_PHYS;i++) {
|
||||||
|
result=EMM_MapPage(i,emm_mappings[i].handle,emm_mappings[i].page);
|
||||||
|
}
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
static Bit8u EMM_RestorePageMap(Bit16u handle) {
|
||||||
|
/* Check for valid handle */
|
||||||
|
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE;
|
||||||
|
/* Check for previous save */
|
||||||
|
if (!emm_handles[handle].saved_page_map) return EMM_INVALID_HANDLE;
|
||||||
|
/* Restore the mappings */
|
||||||
|
emm_handles[handle].saved_page_map=false;
|
||||||
|
for (Bitu i=0;i<EMM_MAX_PHYS;i++) {
|
||||||
|
emm_mappings[i].page=emm_handles[handle].page_map[i].page;
|
||||||
|
emm_mappings[i].handle=emm_handles[handle].page_map[i].handle;
|
||||||
|
}
|
||||||
|
return EMM_RestoreMappingTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bit8u EMM_GetPagesForAllHandles(PhysPt table,Bit16u & handles) {
|
||||||
|
handles=0;
|
||||||
|
for (Bit16u i=0;i<EMM_MAX_HANDLES;i++) {
|
||||||
|
if (emm_handles[i].first_page!=NULL_PAGE) {
|
||||||
|
handles++;
|
||||||
|
mem_writew(table,i);
|
||||||
|
mem_writew(table+2,emm_handles[i].pages);
|
||||||
|
table+=4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
Bitu call_int67;
|
|
||||||
static Bitu INT67_Handler(void) {
|
static Bitu INT67_Handler(void) {
|
||||||
|
Bitu i;
|
||||||
switch (reg_ah) {
|
switch (reg_ah) {
|
||||||
case 0x40: /* Get Status */
|
case 0x40: /* Get Status */
|
||||||
reg_ah=0; //Status ok :)
|
reg_ah=EMM_NO_ERROR;
|
||||||
break;
|
break;
|
||||||
case 0x41: /* Get PageFrame Segment */
|
case 0x41: /* Get PageFrame Segment */
|
||||||
reg_bx=PAGEFRAME_SEG;
|
reg_bx=EMM_PAGEFRAME;
|
||||||
reg_ah=0;
|
reg_ah=EMM_NO_ERROR;
|
||||||
break;
|
break;
|
||||||
case 0x42: /* Get number of pages */
|
case 0x42: /* Get number of pages */
|
||||||
{
|
reg_dx=EMM_MAX_PAGES;
|
||||||
//HEHE Hope this works not exactly like the specs but who cares
|
reg_bx=EMM_GetFreePages();
|
||||||
Bit16u maxfree,total;
|
reg_ah=EMM_NO_ERROR;
|
||||||
EMM_GetFree(&maxfree,&total);
|
|
||||||
reg_dx=maxfree>>2;
|
|
||||||
reg_bx=total>>2;
|
|
||||||
reg_ah=0;
|
|
||||||
};
|
|
||||||
break;
|
break;
|
||||||
case 0x43: /* Get Handle and Allocate Pages */
|
case 0x43: /* Get Handle and Allocate Pages */
|
||||||
{
|
reg_ah=EMM_AllocateMemory(reg_bx,reg_dx);
|
||||||
if (!reg_bx) { reg_ah=0x89;break; }
|
|
||||||
Bit16u handle;
|
|
||||||
EMM_Allocate(reg_bx*4,&handle);
|
|
||||||
if (handle) {
|
|
||||||
reg_ah=0;
|
|
||||||
reg_dx=handle;
|
|
||||||
} else { reg_ah=0x88; }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x44: /* Map Memory */
|
|
||||||
{
|
|
||||||
if (reg_al>3) { reg_ah=0x8b;break; }
|
|
||||||
HostOff pagestart=memory+EMM_Handles[reg_dx].phys_base+reg_bx*16*1024;
|
|
||||||
ems_entries[reg_al].relocate=pagestart;
|
|
||||||
reg_ah=0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 0x45: /* Release handle and free pages */
|
|
||||||
EMM_Free(reg_dx);
|
|
||||||
reg_ah=0;
|
|
||||||
break;
|
|
||||||
case 0x46: /* Get EMM Version */
|
|
||||||
reg_ah=0;
|
|
||||||
reg_al=0x32; //Only 3.2 support for now
|
|
||||||
break;
|
break;
|
||||||
case 0x47: /* Save Mapping Context */
|
case 0x44: /* Map Expanded Memory Page */
|
||||||
LOG_ERROR("EMS:47:Save Mapping Context not supported");
|
reg_ah=EMM_MapPage(reg_al,reg_dx,reg_bx);
|
||||||
reg_ah=0x8c;
|
break;
|
||||||
|
case 0x45: /* Release handle and free pages */
|
||||||
|
reg_ah=EMM_ReleaseMemory(reg_dx);
|
||||||
|
break;
|
||||||
|
case 0x46: /* Get EMM Version */
|
||||||
|
reg_ah=EMM_NO_ERROR;
|
||||||
|
reg_al=EMM_VERSION;
|
||||||
|
break;
|
||||||
|
case 0x47: /* Save Page Map */
|
||||||
|
reg_ah=EMM_SavePageMap(reg_dx);
|
||||||
|
break;
|
||||||
|
case 0x48: /* Restore Page Map */
|
||||||
|
reg_ah=EMM_RestorePageMap(reg_dx);
|
||||||
|
break;
|
||||||
|
case 0x4b: /* Get Handle Count */
|
||||||
|
reg_bx=0;
|
||||||
|
for (i=0;i<EMM_MAX_HANDLES;i++) if (emm_handles[i].first_page!=NULL_PAGE) reg_bx++;
|
||||||
|
reg_ah=EMM_NO_ERROR;
|
||||||
|
break;
|
||||||
|
case 0x4c: /* Get Pages for one Handle */
|
||||||
|
/* Check for valid handle */
|
||||||
|
if (reg_bx>=EMM_MAX_HANDLES || emm_handles[reg_bx].first_page==NULL_PAGE) {reg_ah=EMM_INVALID_HANDLE;break;}
|
||||||
|
reg_bx=emm_handles[reg_dx].pages;
|
||||||
|
reg_ah=EMM_NO_ERROR;
|
||||||
|
break;
|
||||||
|
case 0x4d: /* Get Pages for all Handles */
|
||||||
|
reg_ah=EMM_GetPagesForAllHandles(SegPhys(es)+reg_di,reg_bx);
|
||||||
|
break;
|
||||||
|
case 0x4e: /*Save/Restore Page Map */
|
||||||
|
LOG_WARN("Save/resetore %d",reg_al);
|
||||||
|
switch (reg_al) {
|
||||||
|
case 0x00: /* Save Page Map */
|
||||||
|
MEM_BlockWrite(SegPhys(es)+reg_di,emm_mappings,sizeof(emm_mappings));
|
||||||
|
reg_ah=EMM_NO_ERROR;
|
||||||
|
break;
|
||||||
|
case 0x01: /* Restore Page Map */
|
||||||
|
MEM_BlockRead(SegPhys(ds)+reg_si,emm_mappings,sizeof(emm_mappings));
|
||||||
|
reg_ah=EMM_RestoreMappingTable();
|
||||||
|
break;
|
||||||
|
case 0x02: /* Save and Restore Page Map */
|
||||||
|
MEM_BlockWrite(SegPhys(es)+reg_di,emm_mappings,sizeof(emm_mappings));
|
||||||
|
MEM_BlockRead(SegPhys(ds)+reg_si,emm_mappings,sizeof(emm_mappings));
|
||||||
|
reg_ah=EMM_RestoreMappingTable();
|
||||||
|
break;
|
||||||
|
case 0x03: /* Get Page Map Array Size */
|
||||||
|
reg_al=sizeof(emm_mappings);
|
||||||
|
reg_ah=EMM_NO_ERROR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al);
|
||||||
|
reg_ah=EMM_FUNC_NOSUP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x50: // Map/Unmap multiple handle pages
|
||||||
|
reg_ah = EMM_NO_ERROR;
|
||||||
|
switch (reg_al) {
|
||||||
|
case 0x00: // use physical page numbers
|
||||||
|
{ PhysPt data = SegPhys(ds)+reg_si;
|
||||||
|
for (int i=0; i<reg_cx; i++) {
|
||||||
|
Bit16u logPage = mem_readw(data); data+=2;
|
||||||
|
Bit16u physPage = mem_readw(data); data+=2;
|
||||||
|
reg_ah = EMM_MapPage(physPage,reg_dx,logPage);
|
||||||
|
if (reg_ah!=EMM_NO_ERROR) break;
|
||||||
|
};
|
||||||
|
} break;
|
||||||
|
case 0x01: // use segment address
|
||||||
|
{ PhysPt data = SegPhys(ds)+reg_si;
|
||||||
|
for (int i=0; i<reg_cx; i++) {
|
||||||
|
Bit16u logPage = mem_readw(data); data+=2;
|
||||||
|
Bit16u physPage = (mem_readw(data)-EMM_PAGEFRAME)/(0x1000/EMM_MAX_PHYS); data+=2;
|
||||||
|
reg_ah = EMM_MapPage(physPage,reg_dx,logPage);
|
||||||
|
if (reg_ah!=EMM_NO_ERROR) break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x51: /* Reallocate Pages */
|
||||||
|
reg_ah=EMM_ReallocatePages(reg_dx,reg_bx);
|
||||||
|
break;
|
||||||
|
case 0x53: // Set/Get Handlename
|
||||||
|
if (reg_al==0x00) { // Get Name not supported
|
||||||
|
LOG_ERROR("EMS:Get handle name not supported",reg_ah);
|
||||||
|
reg_ah=EMM_FUNC_NOSUP;
|
||||||
|
} else { // Set name, not supported but faked
|
||||||
|
reg_ah=EMM_NO_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x58: // Get mappable physical array address array
|
||||||
|
if (reg_al==0x00) {
|
||||||
|
PhysPt data = SegPhys(es)+reg_di;
|
||||||
|
Bit16u step = 0x1000 / EMM_MAX_PHYS;
|
||||||
|
for (Bit16u i=0; i<EMM_MAX_PHYS; i++) {
|
||||||
|
mem_writew(data,EMM_PAGEFRAME+step*i); data+=2;
|
||||||
|
mem_writew(data,i); data+=2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// Set number of pages
|
||||||
|
reg_cx = EMM_MAX_PHYS;
|
||||||
|
reg_ah = EMM_NO_ERROR;
|
||||||
break;
|
break;
|
||||||
case 0xDE: /* VCPI Functions */
|
case 0xDE: /* VCPI Functions */
|
||||||
LOG_ERROR("VCPI Functions not supported");
|
LOG_ERROR("VCPI Functions not supported");
|
||||||
reg_ah=0x8c;
|
reg_ah=EMM_FUNC_NOSUP;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("EMS:Call %2X not supported",reg_ah);
|
LOG_ERROR("EMS:Call %2X not supported",reg_ah);
|
||||||
reg_ah=0x8c;
|
reg_ah=EMM_FUNC_NOSUP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return CBRET_NONE;
|
return CBRET_NONE;
|
||||||
@ -138,28 +430,34 @@ void EMS_Init(void) {
|
|||||||
call_int67=CALLBACK_Allocate();
|
call_int67=CALLBACK_Allocate();
|
||||||
CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET);
|
CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET);
|
||||||
/* Register the ems device */
|
/* Register the ems device */
|
||||||
DOS_Device * newdev = new device_EMS();
|
DOS_Device * newdev = new device_EMM();
|
||||||
DOS_AddDevice(newdev);
|
DOS_AddDevice(newdev);
|
||||||
/* Setup the page handlers for the page frame */
|
|
||||||
for (Bitu i=0;i<4;i++) {
|
|
||||||
ems_entries[i].base=(PAGEFRAME_SEG<<4)+i*16*1024;
|
|
||||||
ems_entries[i].type=MEMORY_RELOCATE;
|
|
||||||
ems_entries[i].relocate=memory+(PAGEFRAME_SEG<<4)+i*16*1024;
|
|
||||||
/* Place the page handlers in the ems page fram piece of the memory handler*/
|
|
||||||
MEMORY_SetupHandler(((PAGEFRAME_SEG<<4)+i*16*1024)>>12,4,&ems_entries[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Add a little hack so it appears that there is an actual ems device installed */
|
/* Add a little hack so it appears that there is an actual ems device installed */
|
||||||
char * emsname="EMMXXXX0";
|
char * emsname="EMMXXXX0";
|
||||||
Bit16u seg=DOS_GetMemory(2); //We have 32 bytes
|
Bit16u seg=DOS_GetMemory(2); //We have 32 bytes
|
||||||
MEM_BlockWrite(real_phys(seg,0xa),emsname,strlen(emsname)+1);
|
MEM_BlockWrite(PhysMake(seg,0xa),emsname,strlen(emsname)+1);
|
||||||
/* Copy the callback piece into the beginning */
|
/* Copy the callback piece into the beginning, and set the interrupt vector to it*/
|
||||||
char buf[16];
|
char buf[16];
|
||||||
MEM_BlockRead(real_phys(CB_SEG,call_int67<<4),buf,0xa);
|
MEM_BlockRead(PhysMake(CB_SEG,call_int67<<4),buf,0xa);
|
||||||
MEM_BlockWrite(real_phys(seg,0),buf,0xa);
|
MEM_BlockWrite(PhysMake(seg,0),buf,0xa);
|
||||||
|
|
||||||
RealSetVec(0x67,RealMake(seg,0));
|
RealSetVec(0x67,RealMake(seg,0));
|
||||||
|
/* Clear handle and page tables */
|
||||||
|
Bitu i;
|
||||||
|
for (i=0;i<EMM_MAX_PAGES;i++) {
|
||||||
|
emm_pages[i].memory=0;
|
||||||
|
emm_pages[i].handle=NULL_HANDLE;
|
||||||
|
emm_pages[i].next=NULL_PAGE;
|
||||||
|
}
|
||||||
|
for (i=0;i<EMM_MAX_HANDLES;i++) {
|
||||||
|
emm_handles[i].first_page=NULL_PAGE;
|
||||||
|
memset(&emm_handles[i].name,0,9);
|
||||||
|
}
|
||||||
|
for (i=0;i<EMM_MAX_PHYS;i++) {
|
||||||
|
emm_mappings[i].page=NULL_PAGE;
|
||||||
|
emm_mappings[i].handle=NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
@ -54,14 +53,15 @@ static Bitu INT10_Handler(void) {
|
|||||||
LOG_WARN("INT10:04:Ligthpen not supported");
|
LOG_WARN("INT10:04:Ligthpen not supported");
|
||||||
break;
|
break;
|
||||||
case 0x05: /* Set Active Page */
|
case 0x05: /* Set Active Page */
|
||||||
INT10_SetActivePage(reg_al);
|
if (reg_al & 0x80) LOG_DEBUG("Func %x",reg_al);
|
||||||
|
else INT10_SetActivePage(reg_al);
|
||||||
break;
|
break;
|
||||||
case 0x06: /* Scroll Up */
|
case 0x06: /* Scroll Up */
|
||||||
//TODO Graphics mode scroll
|
//TODO Graphics mode scroll
|
||||||
INT10_ScrollUpWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF);
|
INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,-reg_al,reg_bh,0xFF);
|
||||||
break;
|
break;
|
||||||
case 0x07: /* Scroll Down */
|
case 0x07: /* Scroll Down */
|
||||||
INT10_ScrollDownWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF);
|
INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF);
|
||||||
break;
|
break;
|
||||||
case 0x08: /* Read character & attribute at cursor */
|
case 0x08: /* Read character & attribute at cursor */
|
||||||
//TODO Check for GRAPH and then just return
|
//TODO Check for GRAPH and then just return
|
||||||
@ -84,9 +84,7 @@ static Bitu INT10_Handler(void) {
|
|||||||
INT10_GetPixel(reg_cx,reg_dx,reg_bh,®_al);
|
INT10_GetPixel(reg_cx,reg_dx,reg_bh,®_al);
|
||||||
break;
|
break;
|
||||||
case 0x0E: /* Teletype OutPut */
|
case 0x0E: /* Teletype OutPut */
|
||||||
//TODO FIX
|
INT10_TeletypeOutput(reg_al,reg_bl,false,reg_bh);
|
||||||
INT10_TeletypeOutput(reg_al,reg_bl,false,0);
|
|
||||||
// INT10_TeletypeOutput(reg_al,reg_bl,false,reg_bh);
|
|
||||||
break;
|
break;
|
||||||
case 0x0F: /* Get videomode */
|
case 0x0F: /* Get videomode */
|
||||||
reg_bh=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
reg_bh=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
||||||
@ -102,7 +100,7 @@ static Bitu INT10_Handler(void) {
|
|||||||
INT10_SetOverscanBorderColor(reg_bh);
|
INT10_SetOverscanBorderColor(reg_bh);
|
||||||
break;
|
break;
|
||||||
case 0x02: /* SET ALL PALETTE REGISTERS */
|
case 0x02: /* SET ALL PALETTE REGISTERS */
|
||||||
INT10_SetAllPaletteRegisters(real_phys(Segs[es].value,reg_dx));
|
INT10_SetAllPaletteRegisters(SegPhys(es)+reg_dx);
|
||||||
break;
|
break;
|
||||||
case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
|
case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
|
||||||
INT10_ToggleBlinkingBit(reg_bl);
|
INT10_ToggleBlinkingBit(reg_bl);
|
||||||
@ -114,19 +112,19 @@ static Bitu INT10_Handler(void) {
|
|||||||
INT10_GetOverscanBorderColor(®_bh);
|
INT10_GetOverscanBorderColor(®_bh);
|
||||||
break;
|
break;
|
||||||
case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */
|
case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */
|
||||||
INT10_GetAllPaletteRegisters(real_phys(Segs[es].value,reg_dx));
|
INT10_GetAllPaletteRegisters(SegPhys(es)+reg_dx);
|
||||||
break;
|
break;
|
||||||
case 0x10: /* SET INDIVIDUAL DAC REGISTER */
|
case 0x10: /* SET INDIVIDUAL DAC REGISTER */
|
||||||
INT10_SetSingleDacRegister(reg_bl,reg_dh,reg_ch,reg_cl);
|
INT10_SetSingleDacRegister(reg_bl,reg_dh,reg_ch,reg_cl);
|
||||||
break;
|
break;
|
||||||
case 0x12: /* SET BLOCK OF DAC REGISTERS */
|
case 0x12: /* SET BLOCK OF DAC REGISTERS */
|
||||||
INT10_SetDACBlock(reg_bx,reg_cx,real_phys(Segs[es].value,reg_dx));
|
INT10_SetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
|
||||||
break;
|
break;
|
||||||
case 0x15: /* GET INDIVIDUAL DAC REGISTER */
|
case 0x15: /* GET INDIVIDUAL DAC REGISTER */
|
||||||
INT10_GetSingleDacRegister(reg_bl,®_dh,®_ch,®_cl);
|
INT10_GetSingleDacRegister(reg_bl,®_dh,®_ch,®_cl);
|
||||||
break;
|
break;
|
||||||
case 0x17: /* GET BLOCK OF DAC REGISTER */
|
case 0x17: /* GET BLOCK OF DAC REGISTER */
|
||||||
INT10_GetDACBlock(reg_bx,reg_cx,real_phys(Segs[es].value,reg_dx));
|
INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_WARN("INT10:10:Unhandled EGA/VGA Palette Function %2X",reg_al);
|
LOG_WARN("INT10:10:Unhandled EGA/VGA Palette Function %2X",reg_al);
|
||||||
@ -139,7 +137,7 @@ static Bitu INT10_Handler(void) {
|
|||||||
case 0x00: /* interupt 0x1f vector */
|
case 0x00: /* interupt 0x1f vector */
|
||||||
{
|
{
|
||||||
RealPt int_1f=RealGetVec(0x1f);
|
RealPt int_1f=RealGetVec(0x1f);
|
||||||
SetSegment_16(es,RealSeg(int_1f));
|
SegSet16(es,RealSeg(int_1f));
|
||||||
reg_bp=RealOff(int_1f);
|
reg_bp=RealOff(int_1f);
|
||||||
reg_cx=8;
|
reg_cx=8;
|
||||||
}
|
}
|
||||||
@ -147,28 +145,28 @@ static Bitu INT10_Handler(void) {
|
|||||||
case 0x01: /* interupt 0x43 vector */
|
case 0x01: /* interupt 0x43 vector */
|
||||||
{
|
{
|
||||||
RealPt int_43=RealGetVec(0x43);
|
RealPt int_43=RealGetVec(0x43);
|
||||||
SetSegment_16(es,RealSeg(int_43));
|
SegSet16(es,RealSeg(int_43));
|
||||||
reg_bp=RealOff(int_43);
|
reg_bp=RealOff(int_43);
|
||||||
reg_cx=8;
|
reg_cx=8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x02: /* font 8x14 */
|
case 0x02: /* font 8x14 */
|
||||||
SetSegment_16(es,RealSeg(int10_romarea.font_14));
|
SegSet16(es,RealSeg(int10_romarea.font_14));
|
||||||
reg_bp=RealOff(int10_romarea.font_14);
|
reg_bp=RealOff(int10_romarea.font_14);
|
||||||
reg_cx=14;
|
reg_cx=14;
|
||||||
break;
|
break;
|
||||||
case 0x03: /* font 8x8 first 128 */
|
case 0x03: /* font 8x8 first 128 */
|
||||||
SetSegment_16(es,RealSeg(int10_romarea.font_8_first));
|
SegSet16(es,RealSeg(int10_romarea.font_8_first));
|
||||||
reg_bp=RealOff(int10_romarea.font_8_first);
|
reg_bp=RealOff(int10_romarea.font_8_first);
|
||||||
reg_cx=8;
|
reg_cx=8;
|
||||||
break;
|
break;
|
||||||
case 0x04: /* font 8x8 second 128 */
|
case 0x04: /* font 8x8 second 128 */
|
||||||
SetSegment_16(es,RealSeg(int10_romarea.font_8_second));
|
SegSet16(es,RealSeg(int10_romarea.font_8_second));
|
||||||
reg_bp=RealOff(int10_romarea.font_8_second);
|
reg_bp=RealOff(int10_romarea.font_8_second);
|
||||||
reg_cx=8;
|
reg_cx=8;
|
||||||
break;
|
break;
|
||||||
case 0x06: /* font 8x16 */
|
case 0x06: /* font 8x16 */
|
||||||
SetSegment_16(es,RealSeg(int10_romarea.font_16));
|
SegSet16(es,RealSeg(int10_romarea.font_16));
|
||||||
reg_bp=RealOff(int10_romarea.font_16);
|
reg_bp=RealOff(int10_romarea.font_16);
|
||||||
reg_cx=16;
|
reg_cx=16;
|
||||||
break;
|
break;
|
||||||
@ -196,7 +194,7 @@ static Bitu INT10_Handler(void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x13: /* Write String */
|
case 0x13: /* Write String */
|
||||||
INT10_WriteString(reg_dh,reg_dl,reg_al,reg_bl,real_phys(Segs[es].value,reg_bp),reg_cx,reg_bh);
|
INT10_WriteString(reg_dh,reg_dl,reg_al,reg_bl,SegPhys(es)+reg_bp,reg_cx,reg_bh);
|
||||||
break;
|
break;
|
||||||
case 0x1A: /* Display Combination */
|
case 0x1A: /* Display Combination */
|
||||||
if (reg_al==0) {
|
if (reg_al==0) {
|
||||||
@ -214,7 +212,7 @@ static Bitu INT10_Handler(void) {
|
|||||||
case 0x1B: /* functionality State Information */
|
case 0x1B: /* functionality State Information */
|
||||||
switch (reg_bx) {
|
switch (reg_bx) {
|
||||||
case 0x0000:
|
case 0x0000:
|
||||||
INT10_GetFuncStateInformation(Segs[es].value,reg_di);
|
INT10_GetFuncStateInformation(SegPhys(es)+reg_di);
|
||||||
reg_al=0x1B;
|
reg_al=0x1B;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -262,7 +260,6 @@ static void INT10_InitVGA(void) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void INT10_StartUp(void) {
|
void INT10_StartUp(void) {
|
||||||
|
|
||||||
INT10_InitVGA();
|
INT10_InitVGA();
|
||||||
/* Setup the INT 10 vector */
|
/* Setup the INT 10 vector */
|
||||||
call_10=CALLBACK_Allocate();
|
call_10=CALLBACK_Allocate();
|
||||||
|
@ -102,11 +102,15 @@
|
|||||||
#define PLANAR4 0x05
|
#define PLANAR4 0x05
|
||||||
#define LINEAR8 0x06
|
#define LINEAR8 0x06
|
||||||
|
|
||||||
// for SVGA
|
// for Tandy
|
||||||
#define LINEAR15 0x07
|
|
||||||
#define LINEAR16 0x08
|
#define TANDY16 0x0A
|
||||||
#define LINEAR24 0x09
|
|
||||||
#define LINEAR32 0x0
|
|
||||||
|
#define LINEAR15 0x10
|
||||||
|
#define LINEAR16 0x11
|
||||||
|
#define LINEAR24 0x12
|
||||||
|
#define LINEAR32 0x13
|
||||||
|
|
||||||
|
|
||||||
#define SCREEN_SIZE(x,y) (((x*y*2)|0x00ff)+1)
|
#define SCREEN_SIZE(x,y) (((x*y*2)|0x00ff)+1)
|
||||||
@ -167,19 +171,16 @@ inline Bit8u CURSOR_POS_ROW(Bit8u page) {
|
|||||||
|
|
||||||
void INT10_SetVideoMode(Bit8u mode);
|
void INT10_SetVideoMode(Bit8u mode);
|
||||||
|
|
||||||
void INT10_ScrollUpWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page);
|
void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page);
|
||||||
void INT10_ScrollDownWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page);
|
|
||||||
|
|
||||||
|
|
||||||
void INT10_SetActivePage(Bit8u page);
|
void INT10_SetActivePage(Bit8u page);
|
||||||
void INT10_GetFuncStateInformation(Bit16u seg,Bit16u off);
|
void INT10_GetFuncStateInformation(PhysPt save);
|
||||||
|
|
||||||
|
|
||||||
void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page);
|
void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page);
|
||||||
void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page);
|
void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page);
|
||||||
void INT10_ReadCharAttr(Bit16u * result,Bit8u page);
|
void INT10_ReadCharAttr(Bit16u * result,Bit8u page);
|
||||||
void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr);
|
void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr);
|
||||||
void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysOff string,Bit16u count,Bit8u page);
|
void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page);
|
||||||
|
|
||||||
/* Graphics Stuff */
|
/* Graphics Stuff */
|
||||||
void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color);
|
void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color);
|
||||||
@ -189,15 +190,15 @@ VGAMODES * GetCurrentMode(void);
|
|||||||
/* Palette Group */
|
/* Palette Group */
|
||||||
void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val);
|
void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val);
|
||||||
void INT10_SetOverscanBorderColor(Bit8u val);
|
void INT10_SetOverscanBorderColor(Bit8u val);
|
||||||
void INT10_SetAllPaletteRegisters(PhysOff data);
|
void INT10_SetAllPaletteRegisters(PhysPt data);
|
||||||
void INT10_ToggleBlinkingBit(Bit8u state);
|
void INT10_ToggleBlinkingBit(Bit8u state);
|
||||||
void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val);
|
void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val);
|
||||||
void INT10_GetOverscanBorderColor(Bit8u * val);
|
void INT10_GetOverscanBorderColor(Bit8u * val);
|
||||||
void INT10_GetAllPaletteRegisters(PhysOff data);
|
void INT10_GetAllPaletteRegisters(PhysPt data);
|
||||||
void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue);
|
void INT10_SetSingleDacRegister(Bit8u index,Bit8u red,Bit8u green,Bit8u blue);
|
||||||
void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue);
|
void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * blue);
|
||||||
void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysOff data);
|
void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data);
|
||||||
void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysOff data);
|
void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data);
|
||||||
|
|
||||||
|
|
||||||
/* Sup Groups */
|
/* Sup Groups */
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Character displaying moving functions */
|
/* Character displaying moving functions */
|
||||||
|
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
@ -25,185 +24,143 @@
|
|||||||
#include "inout.h"
|
#include "inout.h"
|
||||||
#include "int10.h"
|
#include "int10.h"
|
||||||
|
|
||||||
|
static INLINE void PLANAR4_CopyRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) {
|
||||||
|
PhysPt src,dest;Bitu copy;
|
||||||
|
dest=base+(curmode->twidth*rnew)*curmode->cheight+cleft;
|
||||||
|
src=base+(curmode->twidth*rold)*curmode->cheight+cleft;
|
||||||
|
Bitu nextline=curmode->twidth;
|
||||||
|
/* Setup registers correctly */
|
||||||
|
IO_Write(0x3ce,5);IO_Write(0x3cf,1); /* Memory transfer mode */
|
||||||
|
IO_Write(0x3c4,2);IO_Write(0x3c5,0xf); /* Enable all Write planes */
|
||||||
|
/* Do some copying */
|
||||||
|
Bitu rowsize=(cright-cleft);
|
||||||
|
copy=curmode->cheight;
|
||||||
|
for (;copy>0;copy--) {
|
||||||
|
for (Bitu x=0;x<rowsize;x++) mem_writeb(dest+x,mem_readb(src+x));
|
||||||
|
dest+=nextline;src+=nextline;
|
||||||
|
|
||||||
void INT10_ScrollDownWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page) {
|
}
|
||||||
|
/* Restore registers */
|
||||||
|
IO_Write(0x3ce,5);IO_Write(0x3cf,0); /* Normal transfer mode */
|
||||||
|
}
|
||||||
|
|
||||||
// Bit8u mode;
|
|
||||||
Bit16u fill=( (attr << 8) | ' ');
|
static INLINE void TEXT_CopyRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) {
|
||||||
|
PhysPt src,dest;
|
||||||
|
src=base+(rold*curmode->twidth+cleft)*2;
|
||||||
|
dest=base+(rnew*curmode->twidth+cleft)*2;
|
||||||
|
MEM_BlockCopy(dest,src,(cright-cleft)*2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void PLANAR4_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
|
||||||
|
/* Set Bitmask / Color / Full Set Reset */
|
||||||
|
IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff);
|
||||||
|
IO_Write(0x3ce,0x0);IO_Write(0x3cf,attr);
|
||||||
|
IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf);
|
||||||
|
IO_Write(0x3ce,5);IO_Write(0x3cf,0); /* Normal transfer mode */
|
||||||
|
/* Write some bytes */
|
||||||
|
PhysPt dest;
|
||||||
|
dest=base+(curmode->twidth*row)*curmode->cheight+cleft;
|
||||||
|
Bitu nextline=curmode->twidth;
|
||||||
|
Bitu copy=curmode->cheight; Bitu rowsize=(cright-cleft);
|
||||||
|
for (;copy>0;copy--) {
|
||||||
|
for (Bitu x=0;x<rowsize;x++) mem_writeb(dest+x,0xff);
|
||||||
|
dest+=nextline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE void TEXT_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
|
||||||
|
/* Do some filing */
|
||||||
|
PhysPt dest;
|
||||||
|
dest=base+(row*curmode->twidth+cleft)*2;
|
||||||
|
Bit16u fill=(attr<<8)+' ';
|
||||||
|
for (Bit8u x=0;x<(cright-cleft);x++) {
|
||||||
|
mem_writew(dest,fill);
|
||||||
|
dest+=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page) {
|
||||||
|
|
||||||
|
/* Do some range checking */
|
||||||
BIOS_NCOLS;BIOS_NROWS;
|
BIOS_NCOLS;BIOS_NROWS;
|
||||||
|
|
||||||
if(rul>rlr) return;
|
if(rul>rlr) return;
|
||||||
if(cul>clr) return;
|
if(cul>clr) return;
|
||||||
if(rlr>=nrows) rlr=(Bit8u)nrows-1;
|
if(rlr>=nrows) rlr=(Bit8u)nrows-1;
|
||||||
if(clr>=ncols) clr=(Bit8u)ncols-1;
|
if(clr>=ncols) clr=(Bit8u)ncols-1;
|
||||||
|
clr++;
|
||||||
// Get the current page
|
/* Get the correct page */
|
||||||
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
||||||
|
VGAMODES * curmode=GetCurrentMode();
|
||||||
|
PhysPt base=PhysMake(curmode->sstart,curmode->slength*page);
|
||||||
|
|
||||||
/* Get this from active video mode */
|
/* See how much lines need to be copies */
|
||||||
Bit16u textseg=0xb800;
|
Bit8u start,end;Bits next;
|
||||||
PhysOff start=real_phys(textseg,ncols*nrows*2*page);
|
/* Copy some lines */
|
||||||
|
if (nlines>0) {
|
||||||
|
start=rlr-nlines+1;
|
||||||
|
end=cul;
|
||||||
|
next=-1;
|
||||||
|
} else if (nlines<0) {
|
||||||
|
start=cul-nlines-1;
|
||||||
|
end=clr;
|
||||||
|
next=1;
|
||||||
|
} else {
|
||||||
|
nlines=rlr-rul+1;
|
||||||
|
goto filling;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
start+=next;
|
||||||
|
switch (curmode->memmodel) {
|
||||||
|
case MTEXT:
|
||||||
|
case CTEXT:
|
||||||
|
TEXT_CopyRow(curmode,cul,clr,start,start+nlines,base);break;
|
||||||
|
case PLANAR4:
|
||||||
|
PLANAR4_CopyRow(curmode,cul,clr,start,start+nlines,base);break;
|
||||||
|
|
||||||
Bit32u dcol=clr-cul+1;
|
}
|
||||||
Bit32u drow=rlr-rul+1;
|
} while (start!=end);
|
||||||
|
/* Fill some lines */
|
||||||
Bit32u tocopy;
|
filling:
|
||||||
PhysOff dest=start+((rlr*ncols)+cul)*2;
|
if (nlines>0) {
|
||||||
PhysOff src = 0;/* for gcc */
|
start=rul;
|
||||||
if (nlines==0) {
|
} else {
|
||||||
nlines=(Bit8u)nrows;
|
nlines-=nlines;
|
||||||
}
|
start=rlr-nlines;
|
||||||
if (nlines>=drow) {
|
|
||||||
tocopy=0;
|
|
||||||
} else {
|
|
||||||
tocopy=drow-nlines;
|
|
||||||
src=start+(((rul+tocopy-1)*ncols)+cul)*2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Bit32u y=0;y<drow;y++) {
|
|
||||||
if (tocopy) {
|
|
||||||
for(Bit32u x=0;x<dcol;x++) {
|
|
||||||
mem_writew(dest,mem_readw(src));
|
|
||||||
src+=2;
|
|
||||||
dest+=2;
|
|
||||||
}
|
|
||||||
src-=(ncols+dcol)*2;
|
|
||||||
dest-=(ncols+dcol)*2;
|
|
||||||
tocopy--;
|
|
||||||
} else {
|
|
||||||
for(Bit32u x=0;x<dcol;x++) {
|
|
||||||
mem_writew(dest,fill);
|
|
||||||
dest+=2;
|
|
||||||
}
|
|
||||||
dest-=(ncols+dcol)*2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
for (;nlines>0;nlines--) {
|
||||||
|
switch (curmode->memmodel) {
|
||||||
|
case MTEXT:
|
||||||
|
case CTEXT:
|
||||||
|
TEXT_FillRow(curmode,cul,clr,start,base,attr);break;
|
||||||
|
case PLANAR4:
|
||||||
|
PLANAR4_FillRow(curmode,cul,clr,start,base,attr);break;
|
||||||
|
}
|
||||||
|
start++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void INT10_ScrollUpWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8u nlines,Bit8u attr,Bit8u page) {
|
|
||||||
|
|
||||||
// Bit8u mode;
|
|
||||||
Bit16u fill=( (attr << 8) | ' ');
|
|
||||||
BIOS_NCOLS;BIOS_NROWS;
|
|
||||||
|
|
||||||
if(rlr>nrows) rlr=(Bit8u)nrows;
|
|
||||||
if(clr>ncols) clr=(Bit8u)ncols;
|
|
||||||
|
|
||||||
if(rul>rlr) return;
|
|
||||||
if(cul>clr) return;
|
|
||||||
|
|
||||||
VGAMODES * curmode=GetCurrentMode();
|
|
||||||
switch (curmode->memmodel) {
|
|
||||||
case CGA:
|
|
||||||
{
|
|
||||||
if (nlines==0) {
|
|
||||||
/* Clear Screen that we can */
|
|
||||||
PhysOff dest=real_phys(0xb800,0);
|
|
||||||
for (Bit32u tel=0;tel<0x4000;tel++) {
|
|
||||||
mem_writew(dest,0x0000);
|
|
||||||
dest+=2;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG_WARN("INT10:Scroll in CGA Mode");
|
|
||||||
}
|
|
||||||
case MTEXT:
|
|
||||||
case CTEXT:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_ERROR("INT10:Scroll on non supported graphics mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current page
|
|
||||||
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
|
||||||
|
|
||||||
/* Get this from active video mode */
|
|
||||||
Bit16u textseg=0xb800;
|
|
||||||
PhysOff start=real_phys(textseg,ncols*nrows*2*page);
|
|
||||||
|
|
||||||
Bit32u dcol=clr-cul+1;
|
|
||||||
Bit32u drow=rlr-rul+1;
|
|
||||||
|
|
||||||
Bit32u tocopy;
|
|
||||||
PhysOff dest=start+((rul*ncols)+cul)*2;
|
|
||||||
PhysOff src;
|
|
||||||
if (nlines==0) {
|
|
||||||
nlines=(Bit8u)nrows;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nlines>=drow) {
|
|
||||||
tocopy=0;
|
|
||||||
} else {
|
|
||||||
tocopy=drow-nlines;
|
|
||||||
src=start+(((rul+nlines)*ncols)+cul)*2;
|
|
||||||
}
|
|
||||||
for (Bit32u y=0;y<drow;y++) {
|
|
||||||
if (tocopy) {
|
|
||||||
for (Bit32u x=0;x<dcol;x++) {
|
|
||||||
mem_writew(dest,mem_readw(src));
|
|
||||||
src+=2;
|
|
||||||
dest+=2;
|
|
||||||
}
|
|
||||||
src+=(ncols-dcol)*2;
|
|
||||||
dest+=(ncols-dcol)*2;
|
|
||||||
tocopy--;
|
|
||||||
} else {
|
|
||||||
for(Bit32u x=0;x<dcol;x++) {
|
|
||||||
mem_writew(dest,fill);
|
|
||||||
dest+=2;
|
|
||||||
}
|
|
||||||
dest+=(ncols-dcol)*2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void INT10_SetActivePage(Bit8u page) {
|
void INT10_SetActivePage(Bit8u page) {
|
||||||
|
|
||||||
Bit16u mem_address;
|
Bit16u mem_address;
|
||||||
Bit16u vid_address;
|
|
||||||
Bit8u cur_col=0 ,cur_row=0 ;
|
Bit8u cur_col=0 ,cur_row=0 ;
|
||||||
|
|
||||||
VGAMODES * curmode=GetCurrentMode();
|
VGAMODES * curmode=GetCurrentMode();
|
||||||
if (curmode==0) return;
|
if (curmode==0) return;
|
||||||
if (page>7) return;
|
if (page>7) return;
|
||||||
switch (curmode->memmodel) {
|
mem_address=page*curmode->slength;
|
||||||
case MTEXT:
|
/* Write the new page start */
|
||||||
case CTEXT:{
|
|
||||||
BIOS_NCOLS;BIOS_NROWS;
|
|
||||||
cur_col=CURSOR_POS_COL(page);
|
|
||||||
cur_row=CURSOR_POS_ROW(page);
|
|
||||||
vid_address=SCREEN_IO_START(ncols,nrows,page);
|
|
||||||
mem_address=SCREEN_MEM_START(ncols,nrows,page);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CGA:{
|
|
||||||
vid_address=0;
|
|
||||||
mem_address=0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PLANAR4:{
|
|
||||||
mem_address=0;
|
|
||||||
vid_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
vid_address=0;
|
|
||||||
mem_address=0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Calculate the address knowing nbcols nbrows and page num
|
|
||||||
real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address);
|
real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address);
|
||||||
|
if (curmode->svgamode<8) mem_address>>=1;
|
||||||
|
|
||||||
// CRTC regs 0x0c and 0x0d
|
|
||||||
|
/* Write the new start address in vgahardware */
|
||||||
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0c);
|
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0c);
|
||||||
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(vid_address&0xff00)>>8);
|
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(mem_address&0xff00)>>8);
|
||||||
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0d);
|
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0d);
|
||||||
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,vid_address&0x00ff);
|
IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,mem_address&0x00ff);
|
||||||
|
|
||||||
// And change the BIOS page
|
// And change the BIOS page
|
||||||
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
|
real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page);
|
||||||
@ -265,14 +222,14 @@ INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u at
|
|||||||
break;
|
break;
|
||||||
case GRAPH:
|
case GRAPH:
|
||||||
{
|
{
|
||||||
/* Split this up for certain graphics modes, since in PLANAR4 especially this is sooo slow */
|
|
||||||
/* Amount of lines */
|
/* Amount of lines */
|
||||||
Bit8u * fontdata;
|
Bit8u * fontdata;
|
||||||
Bit16u x,y;
|
Bit16u x,y;
|
||||||
switch (curmode->cheight) {
|
switch (curmode->cheight) {
|
||||||
case 8:
|
case 8:
|
||||||
// fontdata=&int10_font_08[chr*8];
|
// fontdata=&int10_font_08[chr*8];
|
||||||
fontdata=Real2Host(RealGetVec(0x43))+chr*8;
|
if (chr<128) fontdata=Real2Host(RealGetVec(0x43))+chr*8;
|
||||||
|
else fontdata=Real2Host(RealGetVec(0x1F))+(chr-128)*8;
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
fontdata=&int10_font_14[chr*14];
|
fontdata=&int10_font_14[chr*14];
|
||||||
@ -311,9 +268,15 @@ void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr)
|
|||||||
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
||||||
Bit8u cur_row=CURSOR_POS_ROW(page);
|
Bit8u cur_row=CURSOR_POS_ROW(page);
|
||||||
Bit8u cur_col=CURSOR_POS_COL(page);
|
Bit8u cur_col=CURSOR_POS_COL(page);
|
||||||
|
BIOS_NCOLS;BIOS_NROWS;
|
||||||
while (count>0) {
|
while (count>0) {
|
||||||
WriteChar(cur_col,cur_row,page,chr,attr,showattr);
|
WriteChar(cur_col,cur_row,page,chr,attr,showattr);
|
||||||
count--;
|
count--;
|
||||||
|
cur_col++;
|
||||||
|
if(cur_col==ncols) {
|
||||||
|
cur_col=0;
|
||||||
|
cur_row++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,14 +319,14 @@ void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page) {
|
|||||||
}
|
}
|
||||||
// Do we need to scroll ?
|
// Do we need to scroll ?
|
||||||
if(cur_row==nrows) {
|
if(cur_row==nrows) {
|
||||||
INT10_ScrollUpWindow(0,0,nrows-1,ncols-1,1,0x07,page);
|
INT10_ScrollWindow(0,0,nrows-1,ncols-1,-1,0x07,page);
|
||||||
cur_row--;
|
cur_row--;
|
||||||
}
|
}
|
||||||
// Set the cursor for the page
|
// Set the cursor for the page
|
||||||
INT10_SetCursorPos(cur_row,cur_col,page);
|
INT10_SetCursorPos(cur_row,cur_col,page);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysOff string,Bit16u count,Bit8u page) {
|
void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page) {
|
||||||
|
|
||||||
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
|
||||||
BIOS_NCOLS;BIOS_NROWS;
|
BIOS_NCOLS;BIOS_NROWS;
|
||||||
|
@ -67,7 +67,8 @@ void INT10_SetupRomMemory(void) {
|
|||||||
for (i=0;i<0x10;i++) {
|
for (i=0;i<0x10;i++) {
|
||||||
real_writeb(0xC000,segoff++,static_functionality[i]);
|
real_writeb(0xC000,segoff++,static_functionality[i]);
|
||||||
}
|
}
|
||||||
|
MEM_BlockWrite(PhysMake(0xf000,0xfa6e),int10_font_08,128*8);
|
||||||
|
RealSetVec(0x1F,int10_romarea.font_8_second);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined (_MSC_VER)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
struct Dynamic_Functionality {
|
struct Dynamic_Functionality {
|
||||||
RealPt static_table; /* 00h DWORD address of static functionality table */
|
RealPt static_table; /* 00h DWORD address of static functionality table */
|
||||||
Bit8u cur_mode; /* 04h BYTE video mode in effect */
|
Bit8u cur_mode; /* 04h BYTE video mode in effect */
|
||||||
@ -68,15 +70,19 @@ struct Dynamic_Functionality {
|
|||||||
7 reserved
|
7 reserved
|
||||||
*/
|
*/
|
||||||
Bit8u reserved2[13]; /* 33h 13 BYTEs reserved (00h) */
|
Bit8u reserved2[13]; /* 33h 13 BYTEs reserved (00h) */
|
||||||
};
|
}
|
||||||
|
#if defined (_MSC_VER)
|
||||||
|
;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
#else
|
||||||
|
__attribute__ ((packed));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void INT10_GetFuncStateInformation(PhysPt save) {
|
||||||
|
|
||||||
void INT10_GetFuncStateInformation(Bit16u seg,Bit16u off) {
|
|
||||||
|
|
||||||
PhysOff save=Real2Phys(RealMake(seg,off));
|
|
||||||
/* set static state pointer */
|
/* set static state pointer */
|
||||||
mem_writed(save,int10_romarea.static_state);
|
mem_writed(save,int10_romarea.static_state);
|
||||||
/* Copy BIOS Segment areas */
|
/* Copy BIOS Segment areas */
|
||||||
|
@ -34,13 +34,14 @@ VGAMODES vga_modes[MODE_MAX+1]=
|
|||||||
{0x05, 0xFFFF, GRAPH, CGA, 1, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01},
|
{0x05, 0xFFFF, GRAPH, CGA, 1, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01},
|
||||||
{0x06, 0xFFFF, GRAPH, CGA, 1, 1, 640, 200, 80, 25, 8, 8, 0xB800, 0x1000, 0x63, 0xFF, 0x03, 0x02, 0x02, 0x03, 0x01},
|
{0x06, 0xFFFF, GRAPH, CGA, 1, 1, 640, 200, 80, 25, 8, 8, 0xB800, 0x1000, 0x63, 0xFF, 0x03, 0x02, 0x02, 0x03, 0x01},
|
||||||
{0x07, 0xFFFF, TEXT, MTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB000, 0x1000, 0x66, 0xFF, 0x04, 0x03, 0x03, 0x01, 0x00},
|
{0x07, 0xFFFF, TEXT, MTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB000, 0x1000, 0x66, 0xFF, 0x04, 0x03, 0x03, 0x01, 0x00},
|
||||||
{0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01},
|
|
||||||
{0x0E, 0xFFFF, GRAPH, PLANAR4, 4, 4, 640, 200, 80, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x06, 0x04, 0x04, 0x05, 0x01},
|
{0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x2000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01},
|
||||||
{0x0F, 0xFFFF, GRAPH, PLANAR2, 2, 2, 640, 350, 80, 25, 8, 14, 0xA000, 0x0000, 0xa2, 0xFF, 0x07, 0x05, 0x04, 0x05, 0x00},
|
{0x0E, 0xFFFF, GRAPH, PLANAR4, 4, 4, 640, 200, 80, 25, 8, 8, 0xA000, 0x4000, 0x63, 0xFF, 0x06, 0x04, 0x04, 0x05, 0x01},
|
||||||
{0x10, 0xFFFF, GRAPH, PLANAR4, 2, 4, 640, 350, 80, 25, 8, 14, 0xA000, 0x0000, 0xa3, 0xFF, 0x07, 0x06, 0x04, 0x05, 0x02},
|
{0x0F, 0xFFFF, GRAPH, PLANAR2, 2, 2, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa2, 0xFF, 0x07, 0x05, 0x04, 0x05, 0x00},
|
||||||
{0x11, 0xFFFF, GRAPH, PLANAR1, 1, 1, 640, 480, 80, 30, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x08, 0x07, 0x04, 0x05, 0x02},
|
{0x10, 0xFFFF, GRAPH, PLANAR4, 2, 4, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa3, 0xFF, 0x07, 0x06, 0x04, 0x05, 0x02},
|
||||||
{0x12, 0xFFFF, GRAPH, PLANAR4, 1, 4, 640, 480, 80, 30, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x08, 0x06, 0x04, 0x05, 0x02},
|
{0x11, 0xFFFF, GRAPH, PLANAR1, 1, 1, 640, 480, 80, 30, 8, 16, 0xA000, 0xA000, 0xe3, 0xFF, 0x08, 0x07, 0x04, 0x05, 0x02},
|
||||||
{0x13, 0xFFFF, GRAPH, LINEAR8, 1, 8, 320, 200, 40, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x09, 0x08, 0x05, 0x06, 0x03}
|
{0x12, 0xFFFF, GRAPH, PLANAR4, 1, 4, 640, 480, 80, 30, 8, 16, 0xA000, 0xA000, 0xe3, 0xFF, 0x08, 0x06, 0x04, 0x05, 0x02},
|
||||||
|
{0x13, 0xFFFF, GRAPH, LINEAR8, 1, 8, 320, 200, 40, 25, 8, 8, 0xA000, 0xFA00, 0x63, 0xFF, 0x09, 0x08, 0x05, 0x06, 0x03}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* CRTC */
|
/* CRTC */
|
||||||
@ -348,18 +349,18 @@ void INT10_SetVideoMode(Bit8u mode) {
|
|||||||
Bit32u tel;
|
Bit32u tel;
|
||||||
if(clearmem) {
|
if(clearmem) {
|
||||||
if(vga_modes[line].type==TEXT) {
|
if(vga_modes[line].type==TEXT) {
|
||||||
PhysOff dest=real_phys(vga_modes[line].sstart,0);
|
PhysPt dest=PhysMake(vga_modes[line].sstart,0);
|
||||||
for (tel=0;tel<0x4000;tel++) {
|
for (tel=0;tel<0x4000;tel++) {
|
||||||
mem_writew(dest,0x0720);
|
mem_writew(dest,0x0720);
|
||||||
dest+=2;
|
dest+=2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PhysOff dest=real_phys(0xb800,0);
|
PhysPt dest=PhysMake(0xb800,0);
|
||||||
for (tel=0;tel<0x4000;tel++) {
|
for (tel=0;tel<0x4000;tel++) {
|
||||||
mem_writew(dest,0x0000);
|
mem_writew(dest,0x0000);
|
||||||
dest+=2;
|
dest+=2;
|
||||||
}
|
}
|
||||||
dest=real_phys(0xa000,0);
|
dest=PhysMake(0xa000,0);
|
||||||
for (tel=0;tel<0x8000;tel++) {
|
for (tel=0;tel<0x8000;tel++) {
|
||||||
mem_writew(dest,0x0000);
|
mem_writew(dest,0x0000);
|
||||||
dest+=2;
|
dest+=2;
|
||||||
@ -396,8 +397,5 @@ void INT10_SetVideoMode(Bit8u mode) {
|
|||||||
// Set active page 0
|
// Set active page 0
|
||||||
INT10_SetActivePage(0);
|
INT10_SetActivePage(0);
|
||||||
/* Set some interrupt vectors */
|
/* Set some interrupt vectors */
|
||||||
//TODO set 0x43 to the correct font height font
|
|
||||||
RealSetVec(0x43,int10_romarea.font_8_first);
|
RealSetVec(0x43,int10_romarea.font_8_first);
|
||||||
RealSetVec(0x1F,int10_romarea.font_8_second);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -38,7 +38,7 @@ void INT10_SetOverscanBorderColor(Bit8u val) {
|
|||||||
IO_Write(VGAREG_ACTL_WRITE_DATA,val);
|
IO_Write(VGAREG_ACTL_WRITE_DATA,val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INT10_SetAllPaletteRegisters(PhysOff data) {
|
void INT10_SetAllPaletteRegisters(PhysPt data) {
|
||||||
IO_Read(VGAREG_ACTL_RESET);
|
IO_Read(VGAREG_ACTL_RESET);
|
||||||
// First the colors
|
// First the colors
|
||||||
for(Bit8u i=0;i<0x10;i++) {
|
for(Bit8u i=0;i<0x10;i++) {
|
||||||
@ -80,7 +80,7 @@ void INT10_GetOverscanBorderColor(Bit8u * val) {
|
|||||||
*val=IO_Read(VGAREG_ACTL_READ_DATA);
|
*val=IO_Read(VGAREG_ACTL_READ_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INT10_GetAllPaletteRegisters(PhysOff data) {
|
void INT10_GetAllPaletteRegisters(PhysPt data) {
|
||||||
IO_Read(VGAREG_ACTL_RESET);
|
IO_Read(VGAREG_ACTL_RESET);
|
||||||
// First the colors
|
// First the colors
|
||||||
for(Bit8u i=0;i<0x10;i++) {
|
for(Bit8u i=0;i<0x10;i++) {
|
||||||
@ -107,7 +107,7 @@ void INT10_GetSingleDacRegister(Bit8u index,Bit8u * red,Bit8u * green,Bit8u * bl
|
|||||||
*blue=IO_Read(VGAREG_DAC_DATA);
|
*blue=IO_Read(VGAREG_DAC_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysOff data) {
|
void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysPt data) {
|
||||||
IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index);
|
IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index);
|
||||||
for (;count>0;count--) {
|
for (;count>0;count--) {
|
||||||
IO_Write(VGAREG_DAC_DATA,mem_readb(data++));
|
IO_Write(VGAREG_DAC_DATA,mem_readb(data++));
|
||||||
@ -116,7 +116,7 @@ void INT10_SetDACBlock(Bit16u index,Bit16u count,PhysOff data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysOff data) {
|
void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data) {
|
||||||
IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index);
|
IO_Write(VGAREG_DAC_WRITE_ADDRESS,(Bit8u)index);
|
||||||
for (;count>0;count--) {
|
for (;count>0;count--) {
|
||||||
mem_writeb(data++,IO_Read(VGAREG_DAC_DATA));
|
mem_writeb(data++,IO_Read(VGAREG_DAC_DATA));
|
||||||
|
@ -54,7 +54,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
|
|||||||
//Perhaps also set mode 1
|
//Perhaps also set mode 1
|
||||||
/* Calculate where the pixel is in video memory */
|
/* Calculate where the pixel is in video memory */
|
||||||
Bit16u base_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page;
|
Bit16u base_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page;
|
||||||
PhysOff off=0xa0000+base_address+((y*curmode->swidth+x)>>3);
|
PhysPt off=0xa0000+base_address+((y*curmode->swidth+x)>>3);
|
||||||
/* Bitmask and set/reset should do the rest */
|
/* Bitmask and set/reset should do the rest */
|
||||||
mem_readb(off);
|
mem_readb(off);
|
||||||
mem_writeb(off,0xff);
|
mem_writeb(off,0xff);
|
||||||
|
@ -150,7 +150,7 @@ static void mouse_reset(void) {
|
|||||||
mouse.max_y=199;
|
mouse.max_y=199;
|
||||||
mouse.range_x=639;
|
mouse.range_x=639;
|
||||||
mouse.range_y=199;
|
mouse.range_y=199;
|
||||||
mouse.x=320;
|
mouse.x=0; // civ wont work otherwise
|
||||||
mouse.y=100;
|
mouse.y=100;
|
||||||
mouse.events=0;
|
mouse.events=0;
|
||||||
mouse.mickey_x=0;
|
mouse.mickey_x=0;
|
||||||
@ -196,6 +196,18 @@ static Bitu INT33_Handler(void) {
|
|||||||
mouse.times_pressed[but]=0;
|
mouse.times_pressed[but]=0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0x06: /* Return Button Release Data */
|
||||||
|
{
|
||||||
|
Bit16u but=reg_bx;
|
||||||
|
reg_ax=mouse.buttons;
|
||||||
|
reg_cx=mouse.last_released_x[but];
|
||||||
|
mouse.last_released_x[but]=0;
|
||||||
|
reg_dx=mouse.last_released_y[but];
|
||||||
|
mouse.last_released_y[but]=0;
|
||||||
|
reg_bx=mouse.times_released[but];
|
||||||
|
mouse.times_released[but]=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 0x07: /* Define horizontal cursor range */
|
case 0x07: /* Define horizontal cursor range */
|
||||||
mouse.min_x=reg_cx;
|
mouse.min_x=reg_cx;
|
||||||
mouse.max_x=reg_dx;
|
mouse.max_x=reg_dx;
|
||||||
@ -215,7 +227,7 @@ static Bitu INT33_Handler(void) {
|
|||||||
break;
|
break;
|
||||||
case 0x0c: /* Define interrupt subroutine parameters */
|
case 0x0c: /* Define interrupt subroutine parameters */
|
||||||
mouse.sub_mask=reg_cx;
|
mouse.sub_mask=reg_cx;
|
||||||
mouse.sub_seg=Segs[es].value;
|
mouse.sub_seg=SegValue(es);
|
||||||
mouse.sub_ofs=reg_dx;
|
mouse.sub_ofs=reg_dx;
|
||||||
break;
|
break;
|
||||||
case 0x0f: /* Define mickey/pixel rate */
|
case 0x0f: /* Define mickey/pixel rate */
|
||||||
@ -227,6 +239,19 @@ static Bitu INT33_Handler(void) {
|
|||||||
mouse.mickey_x=0;
|
mouse.mickey_x=0;
|
||||||
mouse.mickey_y=0;
|
mouse.mickey_y=0;
|
||||||
break;
|
break;
|
||||||
|
case 0x14: /* Exchange event-handler */
|
||||||
|
{ Bit16u oldSeg = mouse.sub_seg;
|
||||||
|
Bit16u oldOfs = mouse.sub_ofs;
|
||||||
|
Bit16u oldMask= mouse.sub_mask;
|
||||||
|
// Set new values
|
||||||
|
mouse.sub_mask= reg_cx;
|
||||||
|
mouse.sub_seg = SegValue(es);
|
||||||
|
mouse.sub_ofs = reg_dx;
|
||||||
|
// Return old values
|
||||||
|
reg_cx = oldMask;
|
||||||
|
reg_dx = oldOfs;
|
||||||
|
SegSet16(es,oldSeg);
|
||||||
|
}; break;
|
||||||
case 0x1c: /* Set interrupt rate */
|
case 0x1c: /* Set interrupt rate */
|
||||||
/* Can't really set a rate this is host determined */
|
/* Can't really set a rate this is host determined */
|
||||||
break;
|
break;
|
||||||
@ -252,8 +277,11 @@ static Bitu INT74_Handler(void) {
|
|||||||
/* Check for an active Interrupt Handler that will get called */
|
/* Check for an active Interrupt Handler that will get called */
|
||||||
if (mouse.sub_mask & mouse.event_queue[mouse.events].type) {
|
if (mouse.sub_mask & mouse.event_queue[mouse.events].type) {
|
||||||
/* Save lot's of registers */
|
/* Save lot's of registers */
|
||||||
Bit16u oldax,oldbx,oldcx,olddx,oldsi,olddi;
|
Bit32u oldeax,oldebx,oldecx,oldedx,oldesi,oldedi,oldebp,oldesp;
|
||||||
oldax=reg_ax;oldbx=reg_bx;oldcx=reg_cx;olddx=reg_dx;oldsi=reg_si;olddi=reg_di;
|
Bit16u oldds,oldes,oldss;
|
||||||
|
oldeax=reg_eax;oldebx=reg_ebx;oldecx=reg_ecx;oldedx=reg_edx;
|
||||||
|
oldesi=reg_esi;oldedi=reg_edi;oldebp=reg_ebp;oldesp=reg_esp;
|
||||||
|
oldds=SegValue(ds); oldes=SegValue(es); oldss=SegValue(ss); // Save segments
|
||||||
reg_ax=mouse.event_queue[mouse.events].type;
|
reg_ax=mouse.event_queue[mouse.events].type;
|
||||||
reg_bx=mouse.event_queue[mouse.events].buttons;
|
reg_bx=mouse.event_queue[mouse.events].buttons;
|
||||||
reg_cx=POS_X;
|
reg_cx=POS_X;
|
||||||
@ -265,7 +293,10 @@ static Bitu INT74_Handler(void) {
|
|||||||
mouse.mickey_y=0;
|
mouse.mickey_y=0;
|
||||||
}
|
}
|
||||||
CALLBACK_RunRealFar(mouse.sub_seg,mouse.sub_ofs);
|
CALLBACK_RunRealFar(mouse.sub_seg,mouse.sub_ofs);
|
||||||
reg_ax=oldax;reg_bx=oldbx;reg_cx=oldcx;reg_dx=olddx;reg_si=oldsi;reg_di=olddi;
|
reg_eax=oldeax;reg_ebx=oldebx;reg_ecx=oldecx;reg_edx=oldedx;
|
||||||
|
reg_esi=oldesi;reg_edi=oldedi;reg_ebp=oldebp;reg_esp=oldesp;
|
||||||
|
SegSet16(ds,oldds); SegSet16(es,oldes); SegSet16(ss,oldss); // Save segments
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IO_Write(0xa0,0x20);
|
IO_Write(0xa0,0x20);
|
||||||
|
341
src/ints/xms.cpp
341
src/ints/xms.cpp
@ -16,6 +16,7 @@
|
|||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "callback.h"
|
#include "callback.h"
|
||||||
@ -24,37 +25,50 @@
|
|||||||
#include "dos_system.h"
|
#include "dos_system.h"
|
||||||
|
|
||||||
|
|
||||||
#define XMS_VERSION 0x0300 /* version 3.00 */
|
#define XMS_HANDLES 50 /* 50 XMS Memory Blocks */
|
||||||
#define XMS_DRIVER_VERSION 0x0301 /* my driver version 3.01 */
|
#define XMS_VERSION 0x0300 /* version 3.00 */
|
||||||
|
#define XMS_DRIVER_VERSION 0x0301 /* my driver version 3.01 */
|
||||||
|
|
||||||
#define XMS_GET_VERSION 0x00
|
#define XMS_GET_VERSION 0x00
|
||||||
#define XMS_ALLOCATE_HIGH_MEMORY 0x01
|
#define XMS_ALLOCATE_HIGH_MEMORY 0x01
|
||||||
#define XMS_FREE_HIGH_MEMORY 0x02
|
#define XMS_FREE_HIGH_MEMORY 0x02
|
||||||
#define XMS_GLOBAL_ENABLE_A20 0x03
|
#define XMS_GLOBAL_ENABLE_A20 0x03
|
||||||
#define XMS_GLOBAL_DISABLE_A20 0x04
|
#define XMS_GLOBAL_DISABLE_A20 0x04
|
||||||
#define XMS_LOCAL_ENABLE_A20 0x05
|
#define XMS_LOCAL_ENABLE_A20 0x05
|
||||||
#define XMS_LOCAL_DISABLE_A20 0x06
|
#define XMS_LOCAL_DISABLE_A20 0x06
|
||||||
#define XMS_QUERY_A20 0x07
|
#define XMS_QUERY_A20 0x07
|
||||||
#define XMS_QUERY_FREE_EXTENDED_MEMORY 0x08
|
#define XMS_QUERY_FREE_EXTENDED_MEMORY 0x08
|
||||||
#define XMS_ALLOCATE_EXTENDED_MEMORY 0x09
|
#define XMS_ALLOCATE_EXTENDED_MEMORY 0x09
|
||||||
#define XMS_FREE_EXTENDED_MEMORY 0x0a
|
#define XMS_FREE_EXTENDED_MEMORY 0x0a
|
||||||
#define XMS_MOVE_EXTENDED_MEMORY_BLOCK 0x0b
|
#define XMS_MOVE_EXTENDED_MEMORY_BLOCK 0x0b
|
||||||
#define XMS_LOCK_EXTENDED_MEMORY_BLOCK 0x0c
|
#define XMS_LOCK_EXTENDED_MEMORY_BLOCK 0x0c
|
||||||
#define XMS_UNLOCK_EXTENDED_MEMORY_BLOCK 0x0d
|
#define XMS_UNLOCK_EXTENDED_MEMORY_BLOCK 0x0d
|
||||||
#define XMS_GET_EMB_HANDLE_INFORMATION 0x0e
|
#define XMS_GET_EMB_HANDLE_INFORMATION 0x0e
|
||||||
#define XMS_RESIZE_EXTENDED_MEMORY_BLOCK 0x0f
|
#define XMS_RESIZE_EXTENDED_MEMORY_BLOCK 0x0f
|
||||||
#define XMS_ALLOCATE_UMB 0x10
|
#define XMS_ALLOCATE_UMB 0x10
|
||||||
#define XMS_DEALLOCATE_UMB 0x11
|
#define XMS_DEALLOCATE_UMB 0x11
|
||||||
|
|
||||||
#define HIGH_MEMORY_IN_USE 0x92
|
#define HIGH_MEMORY_IN_USE 0x92
|
||||||
#define HIGH_MEMORY_NOT_ALLOCATED 0x93
|
#define HIGH_MEMORY_NOT_ALLOCATED 0x93
|
||||||
#define XMS_OUT_OF_SPACE 0xa0
|
#define XMS_OUT_OF_SPACE 0xa0
|
||||||
#define XMS_INVALID_HANDLE 0xa2
|
#define XMS_OUT_OF_HANDLES 0xa1
|
||||||
|
#define XMS_INVALID_HANDLE 0xa2
|
||||||
|
|
||||||
|
struct XMS_Block {
|
||||||
|
Bit16u prev,next;
|
||||||
|
Bit16u size; /* Size in kb's */
|
||||||
|
PhysPt phys;
|
||||||
|
Bit8u locked;
|
||||||
|
void * data;
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
|
|
||||||
static Bit16u call_xms;
|
static Bit16u call_xms;
|
||||||
static RealPt xms_callback;
|
static RealPt xms_callback;
|
||||||
|
|
||||||
|
static XMS_Block xms_handles[XMS_HANDLES];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool multiplex_xms(void) {
|
static bool multiplex_xms(void) {
|
||||||
switch (reg_ax) {
|
switch (reg_ax) {
|
||||||
@ -62,7 +76,7 @@ static bool multiplex_xms(void) {
|
|||||||
reg_al=0x80;
|
reg_al=0x80;
|
||||||
return true;
|
return true;
|
||||||
case 0x4310: /* XMS handler seg:offset */
|
case 0x4310: /* XMS handler seg:offset */
|
||||||
SetSegment_16(es,RealSeg(xms_callback));
|
SegSet16(es,RealSeg(xms_callback));
|
||||||
reg_bx=RealOff(xms_callback);
|
reg_bx=RealOff(xms_callback);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -70,51 +84,29 @@ static bool multiplex_xms(void) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined (_MSC_VER)
|
#pragma pack (push,1)
|
||||||
#pragma pack(1)
|
|
||||||
#endif
|
|
||||||
struct XMS_MemMove{
|
struct XMS_MemMove{
|
||||||
Bit32u length;
|
Bit32u length;
|
||||||
Bit16u src_handle;
|
Bit16u src_handle;
|
||||||
RealPt src_offset;
|
union {
|
||||||
|
RealPt realpt;
|
||||||
|
Bit32u offset;
|
||||||
|
} src;
|
||||||
Bit16u dest_handle;
|
Bit16u dest_handle;
|
||||||
RealPt dest_offset;
|
union {
|
||||||
}
|
RealPt realpt;
|
||||||
#if defined (_MSC_VER)
|
Bit32u offset;
|
||||||
;
|
} dest;
|
||||||
#pragma pack()
|
|
||||||
#else
|
|
||||||
__attribute__ ((packed));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void XMS_MoveBlock(PhysOff block,Bit8u * result) {
|
|
||||||
XMS_MemMove moveblock;
|
|
||||||
//TODO Will not work on other endian, probably base it on a class would be nice
|
|
||||||
MEM_BlockRead(block,(Bit8u *)&moveblock,sizeof(XMS_MemMove));
|
|
||||||
HostOff src;
|
|
||||||
PhysOff dest;
|
|
||||||
if (moveblock.src_handle) {
|
|
||||||
src=memory+EMM_Handles[moveblock.src_handle].phys_base+moveblock.src_offset;
|
|
||||||
} else {
|
|
||||||
src=Real2Host(moveblock.src_offset);
|
|
||||||
}
|
|
||||||
if (moveblock.dest_handle) {
|
|
||||||
dest=EMM_Handles[moveblock.dest_handle].phys_base+moveblock.dest_offset;
|
|
||||||
} else {
|
|
||||||
dest=Real2Phys(moveblock.dest_offset);
|
|
||||||
}
|
|
||||||
//memcpy((void *)dest,(void *)src,moveblock.length);
|
|
||||||
MEM_BlockWrite(dest,src,moveblock.length);
|
|
||||||
*result=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
} GCC_ATTRIBUTE(packed);
|
||||||
|
#pragma pack (pop)
|
||||||
|
|
||||||
Bitu XMS_Handler(void) {
|
Bitu XMS_Handler(void) {
|
||||||
switch (reg_ah) {
|
switch (reg_ah) {
|
||||||
case XMS_GET_VERSION: /* 00 */
|
case XMS_GET_VERSION: /* 00 */
|
||||||
reg_ax=XMS_VERSION;
|
reg_ax=XMS_VERSION;
|
||||||
reg_bx=XMS_DRIVER_VERSION;
|
reg_bx=XMS_DRIVER_VERSION;
|
||||||
reg_dx=0; //TODO HMA Maybe
|
reg_dx=0; /* No we don't have HMA */
|
||||||
break;
|
break;
|
||||||
case XMS_ALLOCATE_HIGH_MEMORY: /* 01 */
|
case XMS_ALLOCATE_HIGH_MEMORY: /* 01 */
|
||||||
case XMS_FREE_HIGH_MEMORY: /* 02 */
|
case XMS_FREE_HIGH_MEMORY: /* 02 */
|
||||||
@ -125,42 +117,198 @@ Bitu XMS_Handler(void) {
|
|||||||
case XMS_QUERY_A20: /* 07 */
|
case XMS_QUERY_A20: /* 07 */
|
||||||
LOG_WARN("XMS:Unhandled call %2X",reg_ah);break;
|
LOG_WARN("XMS:Unhandled call %2X",reg_ah);break;
|
||||||
case XMS_QUERY_FREE_EXTENDED_MEMORY: /* 08 */
|
case XMS_QUERY_FREE_EXTENDED_MEMORY: /* 08 */
|
||||||
EMM_GetFree(®_ax,®_dx);
|
/* Scan the tree for free memory and find largest free block */
|
||||||
reg_ax<<=2;reg_dx<<=2;
|
{
|
||||||
reg_bl=0;
|
Bit16u index=1;reg_ax=0;reg_dx=0;
|
||||||
break;
|
while (xms_handles[index].active) {
|
||||||
case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */
|
if (!xms_handles[index].data) {
|
||||||
EMM_Allocate(PAGES(reg_dx*1024),®_dx);
|
if(xms_handles[index].size>reg_ax) reg_ax=xms_handles[index].size;
|
||||||
if (reg_dx) reg_ax=1;
|
reg_dx+=xms_handles[index].size;
|
||||||
else { reg_ax=0;reg_bl=0xb0; }
|
}
|
||||||
break;
|
if (xms_handles[index].next<XMS_HANDLES) index=xms_handles[index].next;
|
||||||
case XMS_FREE_EXTENDED_MEMORY: /* 0a */
|
else break;
|
||||||
EMM_Free(reg_dx);
|
}
|
||||||
reg_ax=1;
|
if (!reg_dx) reg_bl=XMS_OUT_OF_SPACE;
|
||||||
break;
|
reg_bl=0;
|
||||||
|
|
||||||
case XMS_MOVE_EXTENDED_MEMORY_BLOCK: /* 0b */
|
|
||||||
XMS_MoveBlock(real_phys(Segs[ds].value,reg_si),®_bl);
|
|
||||||
if (reg_bl) reg_ax=0;
|
|
||||||
else reg_ax=1;
|
|
||||||
break;
|
|
||||||
case XMS_LOCK_EXTENDED_MEMORY_BLOCK: /* 0c */
|
|
||||||
if ((!EMM_Handles[reg_dx].active) || (EMM_Handles[reg_dx].free)) {
|
|
||||||
reg_ax=0;
|
|
||||||
reg_bl=0xa2; /* Invalid block */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
reg_ax=1;
|
case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */
|
||||||
reg_bx=(Bit16u)((EMM_Handles[reg_dx].phys_base) & 0xffff);
|
{
|
||||||
reg_dx=(Bit16u)((EMM_Handles[reg_dx].phys_base >> 16) & 0xffff);
|
Bit16u index=1;
|
||||||
|
/* First make reg_dx a multiple of PAGE_KB */
|
||||||
|
if (reg_dx & (PAGE_KB-1)) reg_dx=(reg_dx&(~(PAGE_KB-1)))+PAGE_KB;
|
||||||
|
while (xms_handles[index].active) {
|
||||||
|
/* Find a free block, check if there's enough size */
|
||||||
|
if (!xms_handles[index].data && xms_handles[index].size>=reg_dx) {
|
||||||
|
/* Check if block is bigger than request */
|
||||||
|
if (xms_handles[index].size>reg_dx) {
|
||||||
|
/* Split Block, find new handle and split up memory */
|
||||||
|
Bit16u new_index=1;
|
||||||
|
while (new_index<XMS_HANDLES) {
|
||||||
|
if (!xms_handles[new_index].active) goto foundnew;
|
||||||
|
new_index++;
|
||||||
|
}
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=XMS_OUT_OF_HANDLES;
|
||||||
|
reg_dx=0;
|
||||||
|
return CBRET_NONE;
|
||||||
|
foundnew:
|
||||||
|
xms_handles[new_index].next=xms_handles[index].next;
|
||||||
|
xms_handles[new_index].prev=index;
|
||||||
|
xms_handles[index].next=new_index;
|
||||||
|
xms_handles[index].locked=0;
|
||||||
|
xms_handles[new_index].active=true;
|
||||||
|
xms_handles[new_index].data=0;
|
||||||
|
xms_handles[new_index].locked=0;
|
||||||
|
xms_handles[new_index].size=xms_handles[index].size-reg_dx;
|
||||||
|
xms_handles[new_index].phys=xms_handles[index].phys+reg_dx*1024;
|
||||||
|
xms_handles[index].size=reg_dx;
|
||||||
|
}
|
||||||
|
/* Use the data from handle index to allocate the actual memory */
|
||||||
|
reg_dx=index;
|
||||||
|
reg_ax=1;reg_bl=0;
|
||||||
|
xms_handles[index].data=malloc(xms_handles[index].size*1024);
|
||||||
|
if (!xms_handles[index].data) E_Exit("XMS:Out of memory???");
|
||||||
|
/* Now Setup the memory mapping for this range */
|
||||||
|
MEM_SetupMapping(PAGE_COUNT(xms_handles[index].phys),PAGE_COUNT(xms_handles[index].size*1024),xms_handles[index].data);
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
/* Not a free block or too small advance to next one if possible */
|
||||||
|
if (xms_handles[index].next) index=xms_handles[index].next;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
/* Found no good blocks give some errors */
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=XMS_OUT_OF_SPACE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XMS_FREE_EXTENDED_MEMORY: /* 0a */
|
||||||
|
{
|
||||||
|
/* Check for a valid handle */
|
||||||
|
if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=XMS_INVALID_HANDLE;
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
/* Remove the mapping to the memory */
|
||||||
|
MEM_ClearMapping(PAGE_COUNT(xms_handles[reg_dx].phys),PAGE_COUNT(xms_handles[reg_dx].size*1024));
|
||||||
|
/* Free the memory in the block and merge the blocks previous and next block */
|
||||||
|
Bit16u prev=xms_handles[reg_dx].prev;
|
||||||
|
Bit16u next=xms_handles[reg_dx].next;
|
||||||
|
free(xms_handles[reg_dx].data);
|
||||||
|
xms_handles[reg_dx].data=0;
|
||||||
|
if ((next<XMS_HANDLES) && !xms_handles[next].data) {
|
||||||
|
xms_handles[next].active=false;
|
||||||
|
xms_handles[reg_dx].size+=xms_handles[next].size;
|
||||||
|
xms_handles[reg_dx].next=xms_handles[next].next;
|
||||||
|
next=xms_handles[reg_dx].next;
|
||||||
|
if (next<XMS_HANDLES) xms_handles[next].prev=reg_dx;
|
||||||
|
}
|
||||||
|
if ((prev<XMS_HANDLES) && !xms_handles[prev].data) {
|
||||||
|
xms_handles[reg_dx].active=false;
|
||||||
|
xms_handles[prev].size+=xms_handles[reg_dx].size;
|
||||||
|
next=xms_handles[reg_dx].next;
|
||||||
|
xms_handles[prev].next=next;
|
||||||
|
if (next<XMS_HANDLES) xms_handles[next].prev=prev;
|
||||||
|
}
|
||||||
|
reg_ax=1;reg_bl=0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
case XMS_MOVE_EXTENDED_MEMORY_BLOCK: /* 0b */
|
||||||
|
{
|
||||||
|
PhysPt bpt=SegPhys(ds)+reg_si;
|
||||||
|
XMS_MemMove block;
|
||||||
|
/* Fill the block with mem_read's and shit */
|
||||||
|
block.length=mem_readd(bpt+offsetof(XMS_MemMove,length));
|
||||||
|
block.src_handle=mem_readw(bpt+offsetof(XMS_MemMove,src_handle));
|
||||||
|
block.src.offset=mem_readd(bpt+offsetof(XMS_MemMove,src.offset));
|
||||||
|
block.dest_handle=mem_readw(bpt+offsetof(XMS_MemMove,dest_handle));
|
||||||
|
block.dest.offset=mem_readd(bpt+offsetof(XMS_MemMove,dest.offset));
|
||||||
|
PhysPt src,dest;
|
||||||
|
if (block.src_handle) {
|
||||||
|
if ((block.src_handle>=XMS_HANDLES) || !xms_handles[block.src_handle].active ||!xms_handles[block.src_handle].data) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=0xa3; /* Src Handle invalid */
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
if (block.src.offset>=(xms_handles[block.src_handle].size*1024U)) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=0xa4; /* Src Offset invalid */
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
if (block.length>xms_handles[block.src_handle].size*1024U-block.src.offset) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=0xa7; /* Length invalid */
|
||||||
|
return CBRET_NONE;
|
||||||
|
|
||||||
|
}
|
||||||
|
src=xms_handles[block.src_handle].phys+block.src.offset;
|
||||||
|
} else {
|
||||||
|
src=Real2Phys(block.src.realpt);
|
||||||
|
}
|
||||||
|
if (block.dest_handle) {
|
||||||
|
if ((block.dest_handle>=XMS_HANDLES) || !xms_handles[block.dest_handle].active ||!xms_handles[block.dest_handle].data) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=0xa3; /* Dest Handle invalid */
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
if (block.dest.offset>=(xms_handles[block.dest_handle].size*1024U)) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=0xa4; /* Dest Offset invalid */
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
if (block.length>xms_handles[block.dest_handle].size*1024U-block.dest.offset) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=0xa7; /* Length invalid */
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
dest=xms_handles[block.dest_handle].phys+block.dest.offset;
|
||||||
|
} else {
|
||||||
|
dest=Real2Phys(block.dest.realpt);
|
||||||
|
}
|
||||||
|
MEM_BlockCopy(dest,src,block.length);
|
||||||
|
reg_ax=1;reg_bl=0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case XMS_LOCK_EXTENDED_MEMORY_BLOCK: /* 0c */
|
||||||
|
{
|
||||||
|
/* Check for a valid handle */
|
||||||
|
if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=XMS_INVALID_HANDLE;
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
if (xms_handles[reg_dx].locked<255) xms_handles[reg_dx].locked++;
|
||||||
|
reg_bx=(Bit16u)(xms_handles[reg_dx].phys & 0xFFFF);
|
||||||
|
reg_dx=(Bit16u)(xms_handles[reg_dx].phys>>16);
|
||||||
|
reg_ax=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case XMS_UNLOCK_EXTENDED_MEMORY_BLOCK: /* 0d */
|
case XMS_UNLOCK_EXTENDED_MEMORY_BLOCK: /* 0d */
|
||||||
reg_ax=1;
|
/* Check for a valid handle */
|
||||||
|
if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=XMS_INVALID_HANDLE;
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
if (xms_handles[reg_dx].locked) xms_handles[reg_dx].locked--;
|
||||||
|
reg_ax=1;reg_bl=0;
|
||||||
break;
|
break;
|
||||||
case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */
|
case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */
|
||||||
LOG_WARN("XMS:Unhandled call %2X",reg_ah);break;
|
/* Check for a valid handle */
|
||||||
|
if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) {
|
||||||
|
reg_ax=0;
|
||||||
|
reg_bl=XMS_INVALID_HANDLE;
|
||||||
|
return CBRET_NONE;
|
||||||
|
}
|
||||||
|
reg_bh=xms_handles[reg_dx].locked;
|
||||||
|
/* Find available blocks */
|
||||||
|
reg_bx=0;{ for (Bitu i=0;i<XMS_HANDLES;i++) if (!xms_handles[i].data) reg_bx++;}
|
||||||
|
reg_dx=xms_handles[reg_dx].size;
|
||||||
|
break;
|
||||||
case XMS_RESIZE_EXTENDED_MEMORY_BLOCK: /* 0f */
|
case XMS_RESIZE_EXTENDED_MEMORY_BLOCK: /* 0f */
|
||||||
LOG_WARN("XMS:Unhandled call %2X",reg_ah);break;
|
LOG_WARN("XMS:Unhandled call %2X",reg_ah);
|
||||||
|
break;
|
||||||
case XMS_ALLOCATE_UMB: /* 10 */
|
case XMS_ALLOCATE_UMB: /* 10 */
|
||||||
reg_ax=0;
|
reg_ax=0;
|
||||||
reg_bl=0xb1; //No UMB Available
|
reg_bl=0xb1; //No UMB Available
|
||||||
@ -181,5 +329,22 @@ void XMS_Init(void) {
|
|||||||
call_xms=CALLBACK_Allocate();
|
call_xms=CALLBACK_Allocate();
|
||||||
CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF);
|
CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF);
|
||||||
xms_callback=CALLBACK_RealPointer(call_xms);
|
xms_callback=CALLBACK_RealPointer(call_xms);
|
||||||
|
/* Setup the handler table */
|
||||||
|
Bitu i;
|
||||||
|
for (i=0;i<XMS_HANDLES;i++) {
|
||||||
|
xms_handles[i].active=false;
|
||||||
|
xms_handles[i].data=0;
|
||||||
|
xms_handles[i].next=0xffff;
|
||||||
|
xms_handles[i].prev=0xffff;
|
||||||
|
xms_handles[i].size=0;
|
||||||
|
xms_handles[i].locked=0;
|
||||||
|
}
|
||||||
|
/* Disable the 0 handle */
|
||||||
|
xms_handles[0].active=true;
|
||||||
|
xms_handles[0].data=(void *)0xFFFFFFFF;
|
||||||
|
/* Setup the 1st handle */
|
||||||
|
xms_handles[1].active=true;
|
||||||
|
xms_handles[1].phys=1088*1024; /* right behind the hma area */
|
||||||
|
xms_handles[1].size=C_MEM_XMS_SIZE*1024-64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ static void LoadMessageFile(char * fname) {
|
|||||||
FILE * mfile=fopen(fname,"rb");
|
FILE * mfile=fopen(fname,"rb");
|
||||||
/* This should never happen and since other modules depend on this use a normal printf */
|
/* This should never happen and since other modules depend on this use a normal printf */
|
||||||
if (!mfile) {
|
if (!mfile) {
|
||||||
E_Exit("MSG:Can't load messages",fname);
|
E_Exit("MSG:Can't load messages: %s",fname);
|
||||||
}
|
}
|
||||||
char linein[LINE_IN_MAXLEN];
|
char linein[LINE_IN_MAXLEN];
|
||||||
char name[LINE_IN_MAXLEN];
|
char name[LINE_IN_MAXLEN];
|
||||||
|
@ -60,9 +60,9 @@ static Bitu PROGRAMS_Handler(void) {
|
|||||||
/* First get the current psp */
|
/* First get the current psp */
|
||||||
PROGRAM_Info * info=new PROGRAM_Info;
|
PROGRAM_Info * info=new PROGRAM_Info;
|
||||||
info->psp_seg=dos.psp;
|
info->psp_seg=dos.psp;
|
||||||
MEM_BlockRead(real_phys(dos.psp,0),&info->psp_copy,sizeof(PSP));
|
MEM_BlockRead(PhysMake(dos.psp,0),&info->psp_copy,sizeof(PSP));
|
||||||
/* Get the file name cmd_line 0 */
|
/* Get the file name cmd_line 0 */
|
||||||
PhysOff envblock=real_phys(info->psp_copy.environment,0);
|
PhysPt envblock=PhysMake(info->psp_copy.environment,0);
|
||||||
do {} while (mem_readw(envblock++));
|
do {} while (mem_readw(envblock++));
|
||||||
envblock+=3;
|
envblock+=3;
|
||||||
MEM_StrCopy(envblock,info->full_name,32);
|
MEM_StrCopy(envblock,info->full_name,32);
|
||||||
@ -107,7 +107,7 @@ char * Program::GetEnvStr(char * env_str) {
|
|||||||
/* Walk through the internal environment and see for a match */
|
/* Walk through the internal environment and see for a match */
|
||||||
/* Taking some short cuts here to not fuck around with memory structure */
|
/* Taking some short cuts here to not fuck around with memory structure */
|
||||||
|
|
||||||
char * envstart=(char *)real_host(prog_info->psp_copy.environment,0);
|
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
|
||||||
size_t len=strlen(env_str);
|
size_t len=strlen(env_str);
|
||||||
while (*envstart) {
|
while (*envstart) {
|
||||||
if (strncasecmp(env_str,envstart,len)==0 && envstart[len]=='=') {
|
if (strncasecmp(env_str,envstart,len)==0 && envstart[len]=='=') {
|
||||||
@ -119,7 +119,7 @@ char * Program::GetEnvStr(char * env_str) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
char * Program::GetEnvNum(Bit32u num) {
|
char * Program::GetEnvNum(Bit32u num) {
|
||||||
char * envstart=(char *)real_host(prog_info->psp_copy.environment,0);
|
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
|
||||||
while (*envstart) {
|
while (*envstart) {
|
||||||
if (!num) return envstart;
|
if (!num) return envstart;
|
||||||
envstart+=strlen(envstart)+1;
|
envstart+=strlen(envstart)+1;
|
||||||
@ -129,7 +129,7 @@ char * Program::GetEnvNum(Bit32u num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bit32u Program::GetEnvCount(void) {
|
Bit32u Program::GetEnvCount(void) {
|
||||||
char * envstart=(char *)real_host(prog_info->psp_copy.environment,0);
|
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
|
||||||
Bit32u num=0;
|
Bit32u num=0;
|
||||||
while (*envstart) {
|
while (*envstart) {
|
||||||
envstart+=strlen(envstart)+1;
|
envstart+=strlen(envstart)+1;
|
||||||
@ -139,13 +139,13 @@ Bit32u Program::GetEnvCount(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Program::SetEnv(char * env_entry,char * new_string) {
|
bool Program::SetEnv(char * env_entry,char * new_string) {
|
||||||
MCB * env_mcb=(MCB *)real_host(prog_info->psp_copy.environment-1,0);
|
MCB * env_mcb=(MCB *)HostMake(prog_info->psp_copy.environment-1,0);
|
||||||
upcase(env_entry);
|
upcase(env_entry);
|
||||||
Bit32u env_size=env_mcb->size*16;
|
Bit32u env_size=env_mcb->size*16;
|
||||||
if (!env_size) E_Exit("SHELL:Illegal environment size");
|
if (!env_size) E_Exit("SHELL:Illegal environment size");
|
||||||
/* First try to find the old entry */
|
/* First try to find the old entry */
|
||||||
size_t len=strlen(env_entry);
|
size_t len=strlen(env_entry);
|
||||||
char * envstart=(char *)real_host(prog_info->psp_copy.environment,0);
|
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
|
||||||
while (*envstart) {
|
while (*envstart) {
|
||||||
if (strncasecmp(env_entry,envstart,len)==0 && envstart[len]=='=') {
|
if (strncasecmp(env_entry,envstart,len)==0 && envstart[len]=='=') {
|
||||||
/* Now remove this entry */
|
/* Now remove this entry */
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "dosbox.h"
|
#include "dosbox.h"
|
||||||
#include "support.h"
|
#include "support.h"
|
||||||
|
#include "video.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ripped some source from freedos for this one.
|
Ripped some source from freedos for this one.
|
||||||
@ -82,38 +82,49 @@ char *trim(char *str) {
|
|||||||
return ltrim(str);
|
return ltrim(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wildcmp(char *wild, char *string) {
|
bool wildcmp(char *wild, char *string)
|
||||||
char *cp, *mp;
|
{
|
||||||
while ((*string) && (*wild != '*')) {
|
// special case - Everything goes through
|
||||||
if ((*wild != *string) && (*wild != '?')) {
|
if (strcmp(wild,"*")==0) return true;
|
||||||
return false;
|
|
||||||
}
|
while (*wild) {
|
||||||
wild++;
|
if (*wild=='*') {
|
||||||
string++;
|
// Any other chars after that ?
|
||||||
}
|
if ((wild[1]!=0) && (wild[1]!='.')) {
|
||||||
|
// search string
|
||||||
while (*string) {
|
while ((*string) && (*string!='.')) {
|
||||||
if (*wild == '*') {
|
// thats the char ? then exit
|
||||||
if (!*++wild) {
|
if (toupper(*string)==toupper(wild[1])) break;
|
||||||
return true;
|
string++;
|
||||||
|
};
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// skip to extension or end
|
||||||
|
while (*string && (*string!='.')) string++;
|
||||||
}
|
}
|
||||||
mp = wild;
|
wild++;
|
||||||
cp = string+1;
|
|
||||||
} else if ((*wild == *string) || (*wild == '?')) {
|
} else if (*string=='.') {
|
||||||
|
// only valid : '?' & '*'
|
||||||
|
while (*wild && (*wild!='.')) {
|
||||||
|
if ((*wild!='?') && (*wild!='*')) return false;
|
||||||
|
wild++;
|
||||||
|
}
|
||||||
|
if (*wild) wild++;
|
||||||
|
string++;
|
||||||
|
|
||||||
|
} else if ((*wild!='?') && (toupper(*string)!=toupper(*wild))) {
|
||||||
|
// no match
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else {
|
||||||
wild++;
|
wild++;
|
||||||
string++;
|
string++;
|
||||||
} else {
|
|
||||||
wild = mp;
|
|
||||||
string = cp++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (*wild == '*') {
|
|
||||||
wild++;
|
|
||||||
}
|
|
||||||
return !*wild;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return ((*string==0) && (*wild==0));
|
||||||
|
};
|
||||||
|
|
||||||
bool ScanCMDBool(char * cmd,char * check) {
|
bool ScanCMDBool(char * cmd,char * check) {
|
||||||
char * scan=cmd;size_t c_len=strlen(check);
|
char * scan=cmd;size_t c_len=strlen(check);
|
||||||
@ -197,7 +208,7 @@ void S_Warn(char * format,...) {
|
|||||||
va_start(msg,format);
|
va_start(msg,format);
|
||||||
vsprintf(buf,format,msg);
|
vsprintf(buf,format,msg);
|
||||||
va_end(msg);
|
va_end(msg);
|
||||||
#ifdef C_DEBUG
|
#if C_DEBUG
|
||||||
DEBUG_ShowMsg(buf);
|
DEBUG_ShowMsg(buf);
|
||||||
#else
|
#else
|
||||||
GFX_ShowMsg(buf);
|
GFX_ShowMsg(buf);
|
||||||
@ -219,6 +230,7 @@ void E_Exit(char * format,...) {
|
|||||||
printf(buf);
|
printf(buf);
|
||||||
printf("Press ENTER to stop\n");
|
printf("Press ENTER to stop\n");
|
||||||
fgetc(stdin);
|
fgetc(stdin);
|
||||||
exit(2);
|
GFX_Stop();
|
||||||
|
exit(2);
|
||||||
|
|
||||||
};
|
};
|
@ -1,5 +1,6 @@
|
|||||||
#define INLINE __forceinline
|
#define INLINE __forceinline
|
||||||
|
|
||||||
#define VERSION "0.50"
|
#define VERSION "0.55"
|
||||||
|
|
||||||
|
#define GCC_ATTRIBUTE(x) /* attribute not supported */
|
||||||
|
|
||||||
/* Euhm */
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "shell_inc.h"
|
#include "shell_inc.h"
|
||||||
|
|
||||||
Bitu call_shellstop;
|
Bitu call_shellstop;
|
||||||
@ -139,13 +140,16 @@ void SHELL_Init() {
|
|||||||
/* Now call up the shell for the first time */
|
/* Now call up the shell for the first time */
|
||||||
Bit16u psp_seg=DOS_GetMemory(16);
|
Bit16u psp_seg=DOS_GetMemory(16);
|
||||||
Bit16u env_seg=DOS_GetMemory(1+(4096/16));
|
Bit16u env_seg=DOS_GetMemory(1+(4096/16));
|
||||||
|
Bit16u stack_seg=DOS_GetMemory(2048/16);
|
||||||
|
SegSet16(ss,stack_seg);
|
||||||
|
reg_sp=2046;
|
||||||
/* Setup a fake MCB for the environment */
|
/* Setup a fake MCB for the environment */
|
||||||
MCB * env_mcb=(MCB *)real_host(env_seg,0);
|
MCB * env_mcb=(MCB *)HostMake(env_seg,0);
|
||||||
env_mcb->psp_segment=psp_seg;
|
env_mcb->psp_segment=psp_seg;
|
||||||
env_mcb->size=4096/16;
|
env_mcb->size=4096/16;
|
||||||
real_writed(env_seg+1,0,0);
|
real_writed(env_seg+1,0,0);
|
||||||
|
|
||||||
PSP * psp=(PSP *)real_host(psp_seg,0);
|
PSP * psp=(PSP *)HostMake(psp_seg,0);
|
||||||
Bit32u i;
|
Bit32u i;
|
||||||
for (i=0;i<20;i++) psp->files[i]=0xff;
|
for (i=0;i<20;i++) psp->files[i]=0xff;
|
||||||
psp->files[STDIN]=DOS_FindDevice("CON");
|
psp->files[STDIN]=DOS_FindDevice("CON");
|
||||||
@ -158,15 +162,16 @@ void SHELL_Init() {
|
|||||||
psp->file_table=RealMake(psp_seg,offsetof(PSP,files));
|
psp->file_table=RealMake(psp_seg,offsetof(PSP,files));
|
||||||
/* Save old DTA in psp */
|
/* Save old DTA in psp */
|
||||||
psp->dta=dos.dta;
|
psp->dta=dos.dta;
|
||||||
|
/* Set the environment and clear it */
|
||||||
psp->environment=env_seg+1;
|
psp->environment=env_seg+1;
|
||||||
|
mem_writew(Real2Phys(RealMake(env_seg+1,0)),0);
|
||||||
/* Setup internal DOS Variables */
|
/* Setup internal DOS Variables */
|
||||||
dos.dta=RealMake(psp_seg,0x80);
|
dos.dta=RealMake(psp_seg,0x80);
|
||||||
dos.psp=psp_seg;
|
dos.psp=psp_seg;
|
||||||
PROGRAM_Info info;
|
PROGRAM_Info info;
|
||||||
strcpy(info.full_name,"Z:\\COMMAND.COM");
|
strcpy(info.full_name,"Z:\\COMMAND.COM");
|
||||||
info.psp_seg=psp_seg;
|
info.psp_seg=psp_seg;
|
||||||
MEM_BlockRead(real_phys(dos.psp,0),&info.psp_copy,sizeof(PSP));
|
MEM_BlockRead(PhysMake(dos.psp,0),&info.psp_copy,sizeof(PSP));
|
||||||
char line[256];
|
char line[256];
|
||||||
strcpy(line,"/INIT Z:\\AUTOEXEC.BAT");
|
strcpy(line,"/INIT Z:\\AUTOEXEC.BAT");
|
||||||
info.cmd_line=line;
|
info.cmd_line=line;
|
||||||
|
@ -53,6 +53,7 @@ void DOS_Shell::DoCommand(char * line) {
|
|||||||
while (*line) {
|
while (*line) {
|
||||||
if (*line==32) break;
|
if (*line==32) break;
|
||||||
if (*line=='/') break;
|
if (*line=='/') break;
|
||||||
|
if ((*line=='.') && (*(line+1)=='.')) break;
|
||||||
*cmd_write++=*line++;
|
*cmd_write++=*line++;
|
||||||
}
|
}
|
||||||
*cmd_write=0;
|
*cmd_write=0;
|
||||||
@ -113,7 +114,7 @@ void DOS_Shell::CMD_EXIT(char * args) {
|
|||||||
void DOS_Shell::CMD_CHDIR(char * args) {
|
void DOS_Shell::CMD_CHDIR(char * args) {
|
||||||
if (!*args) {
|
if (!*args) {
|
||||||
Bit8u drive=DOS_GetDefaultDrive()+'A';
|
Bit8u drive=DOS_GetDefaultDrive()+'A';
|
||||||
Bit8u dir[DOS_PATHLENGTH];
|
char dir[DOS_PATHLENGTH];
|
||||||
DOS_GetCurrentDir(0,dir);
|
DOS_GetCurrentDir(0,dir);
|
||||||
WriteOut("%c:\\%s\n",drive,dir);
|
WriteOut("%c:\\%s\n",drive,dir);
|
||||||
}
|
}
|
||||||
@ -185,7 +186,7 @@ void DOS_Shell::CMD_DIR(char * args) {
|
|||||||
if (strlen(args)==0) args="*.*";
|
if (strlen(args)==0) args="*.*";
|
||||||
|
|
||||||
/* Make a full path in the args */
|
/* Make a full path in the args */
|
||||||
if (!DOS_Canonicalize(args,(Bit8u*)path)) {
|
if (!DOS_Canonicalize(args,path)) {
|
||||||
WriteOut(MSG_Get("SHELL_CMD_DIR_PATH_ERROR"));
|
WriteOut(MSG_Get("SHELL_CMD_DIR_PATH_ERROR"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
void DOS_Shell::ShowPrompt(void) {
|
void DOS_Shell::ShowPrompt(void) {
|
||||||
Bit8u drive=DOS_GetDefaultDrive()+'A';
|
Bit8u drive=DOS_GetDefaultDrive()+'A';
|
||||||
Bit8u dir[DOS_PATHLENGTH];
|
char dir[DOS_PATHLENGTH];
|
||||||
DOS_GetCurrentDir(0,dir);
|
DOS_GetCurrentDir(0,dir);
|
||||||
WriteOut("%c:\\%s>",drive,dir);
|
WriteOut("%c:\\%s>",drive,dir);
|
||||||
}
|
}
|
||||||
@ -138,36 +138,46 @@ void DOS_Shell::Execute(char * name,char * args) {
|
|||||||
/* Check for a full name */
|
/* Check for a full name */
|
||||||
fullname=Which(name);
|
fullname=Which(name);
|
||||||
if (!fullname) {
|
if (!fullname) {
|
||||||
WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"));
|
WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (strcasecmp(strrchr(fullname, '.'), ".bat") == 0) {
|
if (strcasecmp(strrchr(fullname, '.'), ".bat") == 0) {
|
||||||
/* Run the .bat file */
|
/* Run the .bat file */
|
||||||
bf=new BatchFile(this,fullname,args);
|
bf=new BatchFile(this,fullname,args);
|
||||||
} else {
|
} else {
|
||||||
/* Run the .exe or .com file */
|
/* Run the .exe or .com file from the shell */
|
||||||
ParamBlock block;
|
/* Allocate some stack space for tables in physical memory */
|
||||||
|
reg_sp-=0x200;
|
||||||
|
//Add Parameter block
|
||||||
|
DOS_ParamBlock block(SegPhys(ss)+reg_sp);
|
||||||
|
//Add a filename
|
||||||
|
RealPt file_name=RealMakeSeg(ss,reg_sp+0x20);
|
||||||
|
MEM_BlockWrite(Real2Phys(file_name),fullname,strlen(fullname)+1);
|
||||||
/* Fill the command line */
|
/* Fill the command line */
|
||||||
CommandTail cmd;
|
CommandTail cmd;
|
||||||
if (strlen(args)>126) args[126]=0;
|
if (strlen(args)>126) args[126]=0;
|
||||||
cmd.count=strlen(args);
|
cmd.count=strlen(args);
|
||||||
memcpy(cmd.buffer,args,strlen(args));
|
memcpy(cmd.buffer,args,strlen(args));
|
||||||
cmd.buffer[strlen(args)]=0xd;
|
cmd.buffer[strlen(args)]=0xd;
|
||||||
|
MEM_BlockWrite(PhysMake(prog_info->psp_seg,128),&cmd,128);
|
||||||
|
|
||||||
MEM_BlockWrite(real_phys(prog_info->psp_seg,128),&cmd,128);
|
block.InitExec(RealMake(prog_info->psp_seg,128));
|
||||||
block.exec.cmdtail=RealMake(prog_info->psp_seg,128);
|
|
||||||
block.exec.envseg=0;
|
|
||||||
block.exec.fcb1=0;
|
|
||||||
block.exec.fcb2=0;
|
|
||||||
/* Save CS:IP to some point where i can return them from */
|
/* Save CS:IP to some point where i can return them from */
|
||||||
RealPt newcsip;
|
RealPt newcsip;
|
||||||
newcsip=CALLBACK_RealPointer(call_shellstop);
|
newcsip=CALLBACK_RealPointer(call_shellstop);
|
||||||
SetSegment_16(cs,RealSeg(newcsip));
|
SegSet16(cs,RealSeg(newcsip));
|
||||||
reg_ip=RealOff(newcsip);
|
reg_ip=RealOff(newcsip);
|
||||||
|
/* Start up a dos execute interrupt */
|
||||||
DOS_Execute(fullname,&block,0);
|
reg_ax=0x4b00;
|
||||||
DOSBOX_RunMachine();
|
//Filename pointer
|
||||||
Bit16u blah=0;
|
SegSet16(ds,SegValue(ss));
|
||||||
|
reg_dx=RealOff(file_name);
|
||||||
|
//Paramblock
|
||||||
|
SegSet16(es,SegValue(ss));
|
||||||
|
reg_bx=reg_sp;
|
||||||
|
flags.intf=false;
|
||||||
|
CALLBACK_RunRealInt(0x21);
|
||||||
|
reg_sp+=0x200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ RSC=rc.exe
|
|||||||
# PROP Ignore_Export_Lib 0
|
# PROP Ignore_Export_Lib 0
|
||||||
# PROP Target_Dir ""
|
# PROP Target_Dir ""
|
||||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||||
# ADD CPP /nologo /G6 /MD /W3 /GX /O1 /Op /Ob2 /I "../include" /I "../src/platform/visualc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FAs /FD /QxMi /bQipo /c
|
# ADD CPP /nologo /G6 /MD /W3 /GX /O1 /Op /Ob2 /I "../include" /I "../src/platform/visualc" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FAs /FR /FD /QxMi /bQipo /c
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
BSC32=bscmake.exe
|
BSC32=bscmake.exe
|
||||||
@ -507,7 +507,11 @@ SOURCE=..\src\fpu\fpu.cpp
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\src\fpu\fpu_load.h
|
SOURCE=..\src\fpu\fpu_instructions.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\src\fpu\fpu_types.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "visualc"
|
# Begin Group "visualc"
|
||||||
@ -576,6 +580,10 @@ SOURCE=..\include\dosbox.h
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\include\fpu.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\include\hardware.h
|
SOURCE=..\include\hardware.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
@ -631,9 +639,5 @@ SOURCE=..\include\support.h
|
|||||||
SOURCE=..\include\timer.h
|
SOURCE=..\include\timer.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\shit.txt
|
|
||||||
# End Source File
|
|
||||||
# End Target
|
# End Target
|
||||||
# End Project
|
# End Project
|
||||||
|
Loading…
Reference in New Issue
Block a user