1
0
Fork 0

First CVS upload.

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@80
This commit is contained in:
Sjoerd van der Berg 2002-07-27 13:08:48 +00:00
parent 7d1ca9bdd4
commit 42e5d0b779
158 changed files with 42940 additions and 0 deletions

8
AUTHORS Normal file
View file

@ -0,0 +1,8 @@
The DOSBox Team
---------------
Sjoerd v.d. Berg <harekiet@zophar.net>
Peter Veenstra <qbix79@users.sourceforge.net>

340
COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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 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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

3
ChangeLog Normal file
View file

@ -0,0 +1,3 @@
- fixed the errors/warnings in prefix_66.h and prefix_66_of.h (decimal too large becomming unsigned).

36
INSTALL Normal file
View file

@ -0,0 +1,36 @@
First of all if you are running a non-x86 machine this will not work,
code only works for big-endian machines for now :)
Things needed for compilation.
SDL
The Simple DirectMedia Library available at http://www.libsdl.org
Curses
If you want to enable the debugger you need a curses library.
ncurses should be installed on just about every unix distro.
For win32 get pdcurses at http://pdcurses.sourceforge.net
If you want compile from the CVS under a unix system, you'll also need
automake, autoconf. Should be available at http://www.gnu.org
For building on unix systems.
If you are building from the cvs run ./autogen.sh first before doing the following.
1. ./configure
2. Check settings.h for some setup options.
3. make
Check the src subdir for the binary and dosbox.lang file.
These 2 files should be in the same dir if you want to run dosbox.
Compiling on FreeBSD might be a problem since SDL has no joystick support there.
To get around this edit sdlmain.cpp to enable some #define.
Let's hope someday the sdl people will just report 0 joysticks in freebsd or get it working some other way :)
Build instructions for VC++6
Open the workspace in the visualc subdir and build from there.
Copy the src/dosbox.lang file to the same dir as your executable.

7
Makefile.am Normal file
View file

@ -0,0 +1,7 @@
# Main Makefile for DOSBox
EXTRA_DIST = settings.h autogen.sh
SUBDIRS = src include visualc

23
NEWS Normal file
View file

@ -0,0 +1,23 @@
0.50:
-added F3 to repeat the last typed command.
-made it possible to change the shellmessages(dosshell). so
you can costumize it.(dosbox.lang)
-changed cpu core.
-Fixed a lot of errors with the keyboard: shift-f1 and
alt-f1 now works.
-Fixed some division errors.
-made a plugin system.
-added a lot of real 386 mode instructions.
-made it possible to resize the screen.
-Mayor source cleanup/reorganisation.
-Complete rewrite of the graphics routines. Should make it
possible to implement more fancy things like 2xsai,interpolation.
-changed the sound playback.
-Changed the vga drawing to only draw on memory changes, instead
of drawing an entire frame.
-fixes to the soundblaster/dma code should be able to play 4-bit
adpcm compressed sounds.
-added the correct time to dir.
-bugfixes to batch-file handling.
-Lot's of small bugfixes.(Dune1&2,wolf3d, many more).
-Released the source.

93
README Normal file
View file

@ -0,0 +1,93 @@
DOSBox v0.50
Usage:
======
With the new internal shell I've changed the command line a bit, so let's just give some
examples of what you can do now.
dosbox
With nothing on the command line you'll end up on the internal drive and from there you
can mount directories as drives.
dosbox [filename/directory]
If dosbox detects a directory it'll mount that as c:\ and then start the shell.
If dosbox doesn't detect a directory it'll assume you mean an executable this can be
.bat .com .exe. Doesn't need to have extension included. Then it'll strip the directory
from the filename and mount that as c:\ and then run the file.
You can also add commands to be executed before the main program starts. Or you can use them
to start the program.
To add commands use the -c command line switch.
For example
dosbox c:\atlantis\atlantis.exe -c "MOUNT D C:\SAVES" "SET TEST=blah"
This would mount c:\atlanis as c:\ and run atlantis.exe from that directory but before it
does that it would first mount C:\SAVES as the D drive and set the environment variable test to blah.
Dragging files or directories onto the DOSBox executable should also work.
Internal Programs:
==================
MOUNT
Program to mount local directories as drives inside DOSBox.
HWSET
Utility to setup the emulated hardware running inside DOSBox, only working for emulated sound cards.
UPCASE <Linux Version only>
Utility to convert all files subdirectories of a local directory into upcase so DOSBox can use that directory
for mounting. This tool can be quite dangerous if used unproperly. You have been warned.
To get more information about how to use one these programs use the the /? command line switch.
Special Keys:
=============
ALT-ENTER Go full screen and back.
CTRL-F10 Capture/Release the mouse.
CTRL-F11 Slowdown emulation.
CTRL-F12 Speedup emulation.
System requirements:
====================
Fast machine my guess would be pentium-2 400+ to get decent emulation
of games written for an 286 machine.
FAQ:
====
1.Q: I've got a Z instead of a C at the prompt.
A: In DOSBox you can mount directories as drives
in win32: mount c D:\ would give you an C in DOSBox which points
at D:\ in win32
in linux: mount c /home/username would give you and C in DOSBox
which points at /home/username in Linux
2.Q: The window is too small.
A: When you mouse touches the edges of the DOSBox screen you can click and drag it to
the size you prefer.
3. Check the site/forum.
Building your own Version DOSBox:
=================================
Dowload the source.
Check the INSTALL in the source distribution.
Special Thanks:
===============
Vlad R. of the vdmsound project for excellent sound blaster info.
Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator.
The Bochs and DOSemu projects which I used for information.
Freedos for ideas in making my shell.
Contact:
========
Harekiet harekiet@zophar.net
http://dosbox.zophar.net

8
THANKS Normal file
View file

@ -0,0 +1,8 @@
We would like to thank:
Vlad R. of the vdmsound project for excellent sound blaster info.
Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator.
The Bochs and DOSemu projects which I used for information.
Freedos for ideas in making my shell.
All the people who submitted a bug.

1
VERSION Normal file
View file

@ -0,0 +1 @@
0.50

161
acinclude.m4 Normal file
View file

@ -0,0 +1,161 @@
dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
dnl
AC_DEFUN(AM_PATH_SDL,
[dnl
dnl Get the cflags and libraries from the sdl-config script
dnl
AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)],
sdl_prefix="$withval", sdl_prefix="")
AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)],
sdl_exec_prefix="$withval", sdl_exec_prefix="")
AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program],
, enable_sdltest=yes)
if test x$sdl_exec_prefix != x ; then
sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix"
if test x${SDL_CONFIG+set} != xset ; then
SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config
fi
fi
if test x$sdl_prefix != x ; then
sdl_args="$sdl_args --prefix=$sdl_prefix"
if test x${SDL_CONFIG+set} != xset ; then
SDL_CONFIG=$sdl_prefix/bin/sdl-config
fi
fi
AC_PATH_PROG(SDL_CONFIG, sdl-config, no)
min_sdl_version=ifelse([$1], ,0.11.0,$1)
AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
no_sdl=""
if test "$SDL_CONFIG" = "no" ; then
no_sdl=yes
else
SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags`
SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs`
sdl_major_version=`$SDL_CONFIG $sdl_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
if test "x$enable_sdltest" = "xyes" ; then
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
dnl
dnl Now check if the installed SDL is sufficiently new. (Also sanity
dnl checks the results of sdl-config to some extent
dnl
rm -f conf.sdltest
AC_TRY_RUN([
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SDL.h"
char*
my_strdup (char *str)
{
char *new_str;
if (str)
{
new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char));
strcpy (new_str, str);
}
else
new_str = NULL;
return new_str;
}
int main (int argc, char *argv[])
{
int major, minor, micro;
char *tmp_version;
/* This hangs on some systems (?)
system ("touch conf.sdltest");
*/
{ FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); }
/* HP/UX 9 (%@#!) writes to sscanf strings */
tmp_version = my_strdup("$min_sdl_version");
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
printf("%s, bad version string\n", "$min_sdl_version");
exit(1);
}
if (($sdl_major_version > major) ||
(($sdl_major_version == major) && ($sdl_minor_version > minor)) ||
(($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro)))
{
return 0;
}
else
{
printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version);
printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro);
printf("*** best to upgrade to the required version.\n");
printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n");
printf("*** to point to the correct copy of sdl-config, and remove the file\n");
printf("*** config.cache before re-running configure\n");
return 1;
}
}
],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
if test "x$no_sdl" = x ; then
AC_MSG_RESULT(yes)
ifelse([$2], , :, [$2])
else
AC_MSG_RESULT(no)
if test "$SDL_CONFIG" = "no" ; then
echo "*** The sdl-config script installed by SDL could not be found"
echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in"
echo "*** your path, or set the SDL_CONFIG environment variable to the"
echo "*** full path to sdl-config."
else
if test -f conf.sdltest ; then
:
else
echo "*** Could not run SDL test program, checking why..."
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS"
AC_TRY_LINK([
#include <stdio.h>
#include "SDL.h"
], [ return 0; ],
[ echo "*** The test program compiled, but did not run. This usually means"
echo "*** that the run-time linker is not finding SDL or finding the wrong"
echo "*** version of SDL. If it is not finding SDL, you'll need to set your"
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
echo "*** to the installed location Also, make sure you have run ldconfig if that"
echo "*** is required on your system"
echo "***"
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means SDL was incorrectly installed"
echo "*** or that you have moved SDL since it was installed. In the latter case, you"
echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
LIBS="$ac_save_LIBS"
fi
fi
SDL_CFLAGS=""
SDL_LIBS=""
ifelse([$3], , :, [$3])
fi
AC_SUBST(SDL_CFLAGS)
AC_SUBST(SDL_LIBS)
rm -f conf.sdltest
])

1368
config.guess vendored Normal file

File diff suppressed because it is too large Load diff

61
configure.in Normal file
View file

@ -0,0 +1,61 @@
dnl Init.
AC_INIT(dosbox,0.50)
AC_CONFIG_SRCDIR(README)
dnl Detect the canonical host and target build environment
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
dnl Setup for automake
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)
dnl Checks for programs.
AC_PROG_MAKE_SET
AC_PROG_CC
AC_PROG_CPP
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_RANLIB
dnl Check for SDL
SDL_VERSION=1.2.0
AM_PATH_SDL($SDL_VERSION,
:,
AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
)
LIBS="$LIBS $SDL_LIBS"
CXXFLAGS="$CXXFLAGS $SDL_CFLAGS"
dnl Checks for header files.
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_STRUCT_TM
dnl Checks for library functions.
#Always include the standard include dir in all makefiless
AC_OUTPUT([
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
])

29
include/Makefile.am Normal file
View file

@ -0,0 +1,29 @@
noinst_HEADERS = \
bios.h \
callback.h \
cpu.h \
cross.h \
debug.h \
dma.h \
dos_inc.h \
dos_system.h \
dosbox.h \
fpu.h \
hardware.h \
inout.h \
joystick.h \
keyboard.h \
mem.h \
mixer.h \
modules.h \
mouse.h \
pic.h \
programs.h \
render.h \
regs.h \
render.h \
setup.h \
support.h \
timer.h \
video.h

120
include/bios.h Normal file
View file

@ -0,0 +1,120 @@
/*
* 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 BIOS_BASE_ADDRESS_COM1 0x400
#define BIOS_BASE_ADDRESS_COM2 0x402
#define BIOS_BASE_ADDRESS_COM3 0x404
#define BIOS_BASE_ADDRESS_COM4 0x406
#define BIOS_ADDRESS_LPT1 0x408
#define BIOS_ADDRESS_LPT2 0x40a
#define BIOS_ADDRESS_LPT3 0x40c
/* 0x40e is reserved */
#define BIOS_CONFIGURATION 0x410
/* 0x412 is reserved */
#define BIOS_MEMORY_SIZE 0x413
/* #define bios_expansion_memory_size (*(unsigned int *) 0x415) */
#define BIOS_KEYBOARD_STATE 0x417
#define BIOS_KEYBOARD_FLAGS1 BIOS_KEYBOARD_STATE
#define BIOS_KEYBOARD_FLAGS2 0x418
#define BIOS_KEYBOARD_TOKEN 0x419
/* used for keyboard input with Alt-Number */
#define BIOS_KEYBOARD_BUFFER_HEAD 0x41a
#define BIOS_KEYBOARD_BUFFER_TAIL 0x41c
#define BIOS_KEYBOARD_BUFFER 0x41e
/* #define bios_keyboard_buffer (*(unsigned int *) 0x41e) */
#define BIOS_DRIVE_ACTIVE 0x43e
#define BIOS_DRIVE_RUNNING 0x43f
#define BIOS_MOTOR_NACHLAUFZEIT 0x440
#define BIOS_DISK_STATUS 0x441
/* #define bios_fdc_result_buffer (*(unsigned short *) 0x442) */
#define BIOS_VIDEO_MODE 0x449
#define BIOS_SCREEN_COLUMNS 0x44a
#define BIOS_VIDEO_MEMORY_USED 0x44c
#define BIOS_VIDEO_MEMORY_ADDRESS 0x44e
#define BIOS_VIDEO_CURSOR_POS 0x450
#define BIOS_CURSOR_SHAPE 0x460
#define BIOS_CURSOR_LAST_LINE 0x460
#define BIOS_CURSOR_FIRST_LINE 0x461
#define BIOS_CURRENT_SCREEN_PAGE 0x462
#define BIOS_VIDEO_PORT 0x463
#define BIOS_VDU_CONTROL 0x465
#define BIOS_VDU_COLOR_REGISTER 0x466
/* 0x467-0x468 is reserved */
#define BIOS_TIMER 0x46c
#define BIOS_24_HOURS_FLAG 0x470
#define BIOS_KEYBOARD_FLAGS 0x471
#define BIOS_CTRL_ALT_DEL_FLAG 0x472
#define BIOS_HARDDISK_COUNT 0x475
/* 0x474, 0x476, 0x477 is reserved */
#define BIOS_LPT1_TIMEOUT 0x478
#define BIOS_LPT2_TIMEOUT 0x479
#define BIOS_LPT3_TIMEOUT 0x47a
/* 0x47b is reserved */
#define BIOS_COM1_TIMEOUT 0x47c
#define BIOS_COM2_TIMEOUT 0x47d
/* 0x47e is reserved */
/* 0x47f-0x4ff is unknow for me */
#define BIOS_KEYBOARD_BUFFER_START 0x480
#define BIOS_KEYBOARD_BUFFER_END 0x482
#define BIOS_ROWS_ON_SCREEN_MINUS_1 0x484
#define BIOS_FONT_HEIGHT 0x485
#define BIOS_VIDEO_INFO_0 0x487
#define BIOS_VIDEO_INFO_1 0x488
#define BIOS_VIDEO_INFO_2 0x489
#define BIOS_VIDEO_COMBO 0x48a
#define BIOS_KEYBOARD_FLAGS3 0x496
#define BIOS_KEYBOARD_LEDS 0x497
#define BIOS_PRINT_SCREEN_FLAG 0x500
#define BIOS_VIDEO_SAVEPTR 0x4a8
/* The Section handling Bios Disk Access */
#define BIOS_MAX_DISK 10
class BIOS_Disk {
public:
virtual Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0;
virtual Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0;
};
class imageDisk : public BIOS_Disk {
public:
Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data);
Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data);
imageDisk(char * file);
private:
Bit16u sector_size;
Bit16u heads,cylinders,sectors;
Bit8u * image;
};
void char_out(Bit8u chr,Bit32u att,Bit8u page);
void INT10_StartUp(void);
void INT16_StartUp(void);
void INT2A_StartUp(void);
void INT2F_StartUp(void);
void INT33_StartUp(void);
void INT13_StartUp(void);

56
include/callback.h Normal file
View file

@ -0,0 +1,56 @@
/*
* 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 __CALLBACK_H
#define __CALLBACK_H
#include <mem.h>
typedef Bitu (*CallBack_Handler)(void);
extern CallBack_Handler CallBack_Handlers[];
enum { CB_RETF,CB_IRET };
#define CB_MAX 1024
#define CB_SEG 0xC800
enum {
CBRET_NONE=0,CBRET_STOP=1
};
extern Bit8u lastint;
INLINE RealPt CALLBACK_RealPointer(Bitu callback) {
return RealMake(CB_SEG,callback << 4);
}
Bitu CALLBACK_Allocate();
void CALLBACK_Idle(void);
void CALLBACK_RunRealInt(Bit8u intnum);
void CALLBACK_RunRealFar(Bit16u seg,Bit16u off);
bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type);
bool CALLBACK_Free(Bitu callback);
void CALLBACK_SCF(bool val);
void CALLBACK_SZF(bool val);
#endif

99
include/cpu.h Normal file
View file

@ -0,0 +1,99 @@
/*
* 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 __CPU_H
#define __CPU_H
#include <dosbox.h>
#include <regs.h>
#include <mem.h>
/* Some common Defines */
/* A CPU Handler */
typedef Bitu (CPU_Decoder)(Bitu count);
extern CPU_Decoder * cpudecoder;
extern Bit32u cpu_cycles;
extern Bit32u hoever;
//CPU Stuff
void SetCPU16bit();
void SetSegment_16(Bit32u seg,Bit16u val);
//Types of Flag changing instructions
enum {
t_ADDb=0,t_ADDw,t_ADDd,
t_ORb,t_ORw,t_ORd,
t_ADCb,t_ADCw,t_ADCd,
t_SBBb,t_SBBw,t_SBBd,
t_ANDb,t_ANDw,t_ANDd,
t_SUBb,t_SUBw,t_SUBd,
t_XORb,t_XORw,t_XORd,
t_CMPb,t_CMPw,t_CMPd,
t_INCb,t_INCw,t_INCd,
t_DECb,t_DECw,t_DECd,
t_TESTb,t_TESTw,t_TESTd,
t_SHLb,t_SHLw,t_SHLd,
t_SHRb,t_SHRw,t_SHRd,
t_SARb,t_SARw,t_SARd,
t_ROLb,t_ROLw,t_ROLd,
t_RORb,t_RORw,t_RORd,
t_RCLb,t_RCLw,t_RCLd,
t_RCRb,t_RCRw,t_RCRd,
t_NEGb,t_NEGw,t_NEGd,
t_CF,t_ZF,
t_DSHLw,t_DSHLd,
t_DSHRw,t_DSHRd,
t_MUL,t_DIV,
t_UNKNOWN,
t_NOTDONE,
};
enum { rep_NONE,rep_Z,rep_NZ };
void Interrupt(Bit8u num);
//Flag Handling
bool get_CF(void);
bool get_AF(void);
bool get_ZF(void);
bool get_SF(void);
bool get_OF(void);
bool get_PF(void);
Bit8u get_Flags8(void);
#define LoadCF flags.cf=get_CF();
#define LoadZF flags.zf=get_ZF();
#define LoadSF flags.sf=get_SF();
#define LoadOF flags.of=get_OF();
//The opcode handlers
void FPU_ESC0_Normal(Bitu rm);
void FPU_ESC0_EA(Bitu func,PhysPt ea);
#endif

54
include/cross.h Normal file
View file

@ -0,0 +1,54 @@
/*
* 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 _CROSS_H
#define _CROSS_H
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#if defined (_MSC_VER) /* MS Visual C++ */
#include <direct.h>
#include <io.h>
#else /* LINUX */
#include <dirent.h>
#include <unistd.h>
#endif
#define CROSS_LEN 512 /* Maximum filename size */
#if defined (_MSC_VER) /* MS Visual C++ */
#define CROSS_FILENAME(blah)
#define CROSS_FILESPLIT '\\'
#define F_OK 0
#else
#define CROSS_FILENAME(blah) strreplace(blah,'\\','/')
#define CROSS_FILESPLIT '/'
#endif
#define CROSS_NONE 0
#define CROSS_FILE 1
#define CROSS_DIR 2
extern const char * dosbox_datadir;
#endif

24
include/debug.h Normal file
View file

@ -0,0 +1,24 @@
/*
* 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.
*/
void DEBUG_DrawScreen(void);
bool DEBUG_BreakPoint(void);
void DEBUG_Enable(void);
extern Bitu cycle_count;

24
include/dma.h Normal file
View file

@ -0,0 +1,24 @@
/*
* 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.
*/
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);
void DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count);

275
include/dos_inc.h Normal file
View file

@ -0,0 +1,275 @@
/*
* 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 DOS_H_
#define DOS_H_
#include <dos_system.h>
#include <mem.h>
#pragma pack(1)
struct CommandTail{
Bit8u count; /* number of bytes returned */
char buffer[127]; /* the buffer itself */
};
struct PSP {
Bit8u exit[2]; /* CP/M-like exit poimt */
Bit16u mem_size; /* memory size in paragraphs */
Bit8u fill_1; /* single char fill */
/* CPM Stuff dunno what this is*/
//TODO Add some checks for people using this i think
Bit8u far_call; /* far call opcode */
RealPt cpm_entry; /* CPM Service Request address*/
RealPt int_22; /* Terminate Address */
RealPt int_23; /* Break Address */
RealPt int_24; /* Critical Error Address */
Bit16u psp_parent; /* Parent PSP Segment */
Bit8u files[20]; /* File Table - 0xff is unused */
Bit16u environment; /* Segment of evironment table */
RealPt stack; /* SS:SP Save point for int 0x21 calls */
Bit16u max_files; /* Maximum open files */
RealPt file_table; /* Pointer to File Table PSP:0x18 */
RealPt prev_psp; /* Pointer to previous PSP */
RealPt dta; /* Pointer to current Process DTA */
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 fill_3[45]; /* This has some blocks with FCB info */
CommandTail cmdtail;
};
struct ParamBlock {
union {
struct {
Bit16u loadseg;
Bit16u relocation;
} overlay;
struct {
Bit16u envseg;
RealPt cmdtail;
RealPt fcb1;
RealPt fcb2;
RealPt initsssp;
RealPt initcsip;
} exec;
};
};
struct MCB {
Bit8u type;
Bit16u psp_segment;
Bit16u size;
Bit8u unused[3];
Bit8u filename[8];
};
struct FCB {
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 {
Bit16u year;
Bit8u month;
Bit8u day;
};
struct DOS_Version {
Bit8u major,minor,revision;
};
struct DOS_Block {
DOS_Date date;
DOS_Version version;
Bit16u firstMCB;
Bit16u errorcode;
Bit16u psp;
Bit16u env;
RealPt cpmentry;
RealPt dta;
Bit8u return_code,return_mode;
bool verify;
bool breakcheck;
struct {
RealPt indosflag;
} tables;
};
enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
#define DOS_FILES 50
#define DOS_DRIVES 26
/* internal Dos Tables */
extern DOS_Block dos;
extern DOS_File * Files[DOS_FILES];
extern DOS_Drive * Drives[DOS_DRIVES];
void DOS_SetError(Bit16u code);
/* File Handling Routines */
enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDNUL=4,STDPRN=5};
enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE};
/* Routines for File Class */
void DOS_SetupFiles (void);
bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount);
bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount);
bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type);
bool DOS_CloseFile(Bit16u handle);
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry);
/* Routines for Drive Class */
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry);
bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry);
bool DOS_UnlinkFile(char * name);
bool DOS_FindFirst(char *search,Bit16u attr);
bool DOS_FindNext(void);
bool DOS_Canonicalize(char * small,Bit8u * big);
bool DOS_CreateTempFile(char * name,Bit16u * entry);
bool DOS_FileExists(char * name);
/* Drive Handing Routines */
Bit8u DOS_GetDefaultDrive(void);
void DOS_SetDefaultDrive(Bit8u drive);
bool DOS_SetDrive(Bit8u drive);
bool DOS_GetCurrentDir(Bit8u drive,Bit8u * buffer);
bool DOS_ChangeDir(char * dir);
bool DOS_MakeDir(char * dir);
bool DOS_RemoveDir(char * dir);
bool DOS_Rename(char * oldname,char * newname);
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
bool DOS_GetFileAttr(char * name,Bit16u * attr);
/* IOCTL Stuff */
bool DOS_IOCTL(Bit8u call,Bit16u entry);
bool DOS_GetSTDINStatus();
Bit8u DOS_FindDevice(char * name);
void DOS_SetupDevices(void);
/* Execute and new process creation */
bool DOS_NewPSP(Bit16u pspseg);
bool DOS_Execute(char * name,ParamBlock * block,Bit8u flags);
bool DOS_Terminate(bool tsr);
/* Memory Handling Routines */
void DOS_SetupMemory(void);
bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks);
bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks);
bool DOS_FreeMemory(Bit16u segment);
void DOS_FreeProcessMemory(Bit16u pspseg);
Bit16u DOS_GetMemory(Bit16u pages);
/* Extra DOS Interrupts */
void DOS_SetupMisc(void);
/* The DOS Tables */
void DOS_SetupTables(void);
/* Internal DOS Setup Programs */
void DOS_SetupPrograms(void);
INLINE Bit16u long2para(Bit32u size) {
if (size>0xFFFF0) return 0xffff;
if (size&0xf) return (Bit16u)((size>>4)+1);
else return (Bit16u)(size>>4);
};
INLINE Bit8u RealHandle(Bit16u handle) {
PSP * psp=(PSP *)real_off(dos.psp,0);
if (handle>=psp->max_files) return DOS_FILES;
return mem_readb(Real2Phys(psp->file_table)+handle);
};
/* Dos Error Codes */
#define DOSERR_NONE 0
#define DOSERR_FUNCTION_NUMBER_INVALID 1
#define DOSERR_FILE_NOT_FOUND 2
#define DOSERR_PATH_NOT_FOUND 3
#define DOSERR_TOO_MANY_OPEN_FILES 4
#define DOSERR_ACCESS_DENIED 5
#define DOSERR_INVALID_HANDLE 6
#define DOSERR_MCB_DESTROYED 7
#define DOSERR_INSUFFICIENT_MEMORY 8
#define DOSERR_MB_ADDRESS_INVALID 9
#define DOSERR_ENVIRONMENT_INVALID 10
#define DOSERR_FORMAT_INVALID 11
#define DOSERR_ACCESS_CODE_INVALID 12
#define DOSERR_DATA_INVALID 13
#define DOSERR_RESERVED 14
#define DOSERR_FIXUP_OVERFLOW 14
#define DOSERR_INVALID_DRIVE 15
#define DOSERR_REMOVE_CURRENT_DIRECTORY 16
#define DOSERR_NOT_SAME_DEVICE 17
#define DOSERR_NO_MORE_FILES 18
/* Remains some classes used to access certain things */
class DOS_FCB {
public:
DOS_FCB(PhysPt pt){
off=pt;
}
DOS_FCB(Bit16u seg, Bit16u offset){
off=Real2Phys(RealMake(seg,offset));
}
void Set_drive(Bit8u a);
void Set_filename(char* a); //writes an the first 8 bytes of a as the filename
void Set_ext(char* a);
void Set_current_block(Bit16u a);
void Set_record_size(Bit16u a);
void Set_filesize(Bit32u a);
void Set_date(Bit16u a);
void Set_time(Bit16u a);
// others nog yet handled
Bit8u Get_drive(void);
void Get_filename(char* a);
void Get_ext(char* a);
Bit16u Get_current_block(void);
Bit16u Get_record_size(void);
Bit32u Get_filesize(void);
Bit16u Get_date(void);
Bit16u Get_time(void);
private:
PhysPt off;
};
#endif

105
include/dos_system.h Normal file
View file

@ -0,0 +1,105 @@
/*
* 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 DOSSYSTEM_H_
#define DOSSYSTEM_H_
#include <dosbox.h>
#define DOS_NAMELENGTH 12
#define DOS_DIRDEPTH 16
#define DOS_PATHLENGTH (DOS_DIRDEPTH+1)*(DOS_NAMELENGTH+2)
#define DOS_TEMPSIZE 1024
enum {
DOS_ATTR_READ_ONLY= 0x01,
DOS_ATTR_HIDDEN= 0x02,
DOS_ATTR_SYSTEM= 0x04,
DOS_ATTR_VOLUME= 0x08,
DOS_ATTR_DIRECTORY= 0x10,
DOS_ATTR_ARCHIVE= 0x20
};
#pragma pack (1)
struct DTA_FindBlock {
Bit8u sdrive; /* The Drive the search is taking place */
Bit16u sattr; /* The attributes that need to be found */
Bit8u fill[18];
Bit8u attr;
Bit16u time;
Bit16u date;
Bit32u size;
char name[DOS_NAMELENGTH];
};
#pragma pack ()
class DOS_File {
public:
virtual bool Read(Bit8u * data,Bit16u * size)=0;
virtual bool Write(Bit8u * data,Bit16u * size)=0;
virtual bool Seek(Bit32u * pos,Bit32u type)=0;
virtual bool Close()=0;
virtual Bit16u GetInformation(void)=0;
Bit8u type;Bit32u flags;
/* Some Device Specific Stuff */
};
class DOS_Device : public DOS_File {
public:
/* Some Device Specific Stuff */
char * name;
Bit8u fhandle;
};
class DOS_Drive {
public:
DOS_Drive();
virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags)=0;
virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes)=0;
virtual bool FileUnlink(char * name)=0;
virtual bool RemoveDir(char * dir)=0;
virtual bool MakeDir(char * dir)=0;
virtual bool TestDir(char * dir)=0;
virtual bool FindFirst(char * search,DTA_FindBlock * dta)=0;
virtual bool FindNext(DTA_FindBlock * dta)=0;
virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
virtual bool Rename(char * oldname,char * newname)=0;
virtual bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free)=0;
char * GetInfo(void);
char curdir[DOS_PATHLENGTH];
char info[256];
};
enum { OPEN_READ=0,OPEN_WRITE=1,OPEN_READWRITE=2 };
enum { DOS_SEEK_SET=0,DOS_SEEK_CUR=1,DOS_SEEK_END=2};
/*
A multiplex handler should read the registers to check what function is being called
If the handler returns false dos will stop checking other handlers
*/
typedef bool (MultiplexHandler)(void);
void DOS_AddMultiplexHandler(MultiplexHandler * handler);
void DOS_AddDevice(DOS_Device * adddev);
void VFILE_Register(char * name,Bit8u * data,Bit32u size);
#endif

63
include/dosbox.h Normal file
View file

@ -0,0 +1,63 @@
/*
* 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.
*/
#if !defined __DOSBOX_H
#define __DOSBOX_H
typedef unsigned char Bit8u;
typedef signed char Bit8s;
typedef unsigned short Bit16u;
typedef signed short Bit16s;
typedef unsigned long Bit32u;
typedef signed long Bit32s;
#if defined(_MSC_VER)
typedef unsigned __int64 Bit64u;
typedef signed __int64 Bit64s;
#else
typedef unsigned long long int Bit64u;
typedef signed long long int Bit64s;
#endif
typedef unsigned int Bitu;
typedef signed int Bits;
#include <stddef.h>
void E_Exit(char * message,...);
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);
void DOSBOX_RunMachine();
void DOSBOX_SetLoop(LoopHandler * handler);
void DOSBOX_Init(int argc, char* argv[]);
void DOSBOX_StartUp(void);
#endif

1
include/fpu.h Normal file
View file

@ -0,0 +1 @@

44
include/hardware.h Normal file
View file

@ -0,0 +1,44 @@
/*
* 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 _HARDWARE_H_
#define _HARDWARE_H_
#include <programs.h>
#include <support.h>
#include <stdio.h>
typedef void (* HW_OutputHandler)(char * towrite);
typedef void (* HW_InputHandler)(char * line);
struct HWBlock {
char * dev_name; /* 8 characters max dev name */
char * full_name; /* 60 characters full name */
char * help;
HW_InputHandler get_input;
HW_OutputHandler show_status; /* Supplied with a string to display 50 chars of status info in */
HWBlock * next;
};
void HW_Register(HWBlock * block);
#endif

48
include/inout.h Normal file
View file

@ -0,0 +1,48 @@
/*
* 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.
*/
typedef Bit8u (IO_ReadHandler)(Bit32u port);
typedef void (IO_WriteHandler)(Bit32u port,Bit8u value);
#define IO_MAX 1024
struct IO_ReadBlock{
IO_ReadHandler * handler;
char * name;
};
struct IO_WriteBlock{
IO_WriteHandler * handler;
char * name;
};
extern IO_ReadBlock IO_ReadTable[IO_MAX];
extern IO_WriteBlock IO_WriteTable[IO_MAX];
void IO_Write(Bitu num,Bit8u val);
Bit8u IO_Read(Bitu num);
void IO_RegisterReadHandler(Bit32u port,IO_ReadHandler * handler,char * name);
void IO_RegisterWriteHandler(Bit32u port,IO_WriteHandler * handler,char * name);
void IO_FreeReadHandler(Bit32u port);
void IO_FreeWriteHandler(Bit32u port);

25
include/joystick.h Normal file
View file

@ -0,0 +1,25 @@
/*
* 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.
*/
void JOYSTICK_Enable(Bitu which,bool enabled);
void JOYSTICK_Button(Bitu which,Bitu num,bool pressed);
void JOYSTICK_Move_X(Bitu which,float x);
void JOYSTICK_Move_Y(Bitu which,float y);

54
include/keyboard.h Normal file
View file

@ -0,0 +1,54 @@
/*
* 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.
*/
typedef void(KEYBOARD_EventHandler)(void);
void KEYBOARD_AddCode(Bit8u code);
void KEYBOARD_AddKey(Bitu keytype,bool pressed);
void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler);
#define ALT_PRESSED 0x1
#define CTRL_PRESSED 0x2
#define SHIFT_PRESSED 0x4
enum {
KBD_1, KBD_2, KBD_3, KBD_4, KBD_5, KBD_6, KBD_7, KBD_8, KBD_9, KBD_0,
KBD_q, KBD_w, KBD_e, KBD_r, KBD_t, KBD_y, KBD_u, KBD_i, KBD_o, KBD_p,
KBD_a, KBD_s, KBD_d, KBD_f, KBD_g, KBD_h, KBD_j, KBD_k, KBD_l, KBD_z,
KBD_x, KBD_c, KBD_v, KBD_b, KBD_n, KBD_m,
KBD_f1, KBD_f2, KBD_f3, KBD_f4, KBD_f5, KBD_f6, KBD_f7, KBD_f8, KBD_f9, KBD_f10,KBD_f11,KBD_f12,
/*Now the weirder keys */
KBD_esc,KBD_tab,KBD_backspace,KBD_enter,KBD_space,
KBD_leftalt,KBD_rightalt,KBD_leftctrl,KBD_rightctrl,KBD_leftshift,KBD_rightshift,
KBD_capslock,KBD_scrolllock,KBD_numlock,
KBD_grave,KBD_minus,KBD_equals,KBD_backslash,KBD_leftbracket,KBD_rightbracket,
KBD_semicolon,KBD_quote,KBD_period,KBD_comma,KBD_slash,
KBD_insert,KBD_home,KBD_pageup,KBD_delete,KBD_end,KBD_pagedown,
KBD_left,KBD_up,KBD_down,KBD_right,
KBD_kp1,KBD_kp2,KBD_kp3,KBD_kp4,KBD_kp5,KBD_kp6,KBD_kp7,KBD_kp8,KBD_kp9,KBD_kp0,
KBD_kpslash,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod,
KBD_LAST
};

206
include/mem.h Normal file
View file

@ -0,0 +1,206 @@
/*
* 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.
*/
#if !defined __MEM_H
#define __MEM_H
#include <dosbox.h>
enum { MEMORY_HANDLER=1,MEMORY_RELOCATE=2};
#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 PhysPt;
typedef Bit8u * HostPt;
typedef Bit32u RealPt;
struct PageEntry {
Bit8u type;
PhysPt base; /* Used to calculate relative offset */
struct {
MEMORY_WriteHandler * write;
MEMORY_ReadHandler * read;
} handler;
HostPt relocate; /* This points to host machine address */
};
struct EMM_Handle {
Bit16u next;
Bit16u size; /* Size in pages */
PhysPt phys_base;
HostPt host_base;
bool active;
bool free;
};
INLINE Bit16u PAGES(Bit32u bytes) {
if ((bytes & 4095) == 0) return (Bit16u)(bytes>>12);
return (Bit16u)(1+(bytes>>12));
}
extern Bit8u * memory;
extern EMM_Handle EMM_Handles[];
extern PageEntry * PageEntries[]; /* Number of pages */
bool MEMORY_TestSpecial(PhysPt off);
void MEMORY_SetupHandler(Bit32u page,Bit32u extra,PageEntry * handler);
void MEMORY_ResetHandler(Bit32u page,Bit32u pages);
void EMM_GetFree(Bit16u * maxblock,Bit16u * total);
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
Working on big or little endian machines
*/
INLINE Bit8u readb(HostPt off) {
return *(Bit8u *)off;
};
INLINE Bit16u readw(HostPt off) {
return *(Bit16u *)off;
};
INLINE Bit32u readd(HostPt off) {
return *(Bit32u *)off;
};
INLINE void writeb(HostPt off,Bit8u val) {
*(Bit8u *)(off)=val;
};
INLINE void writew(HostPt off,Bit16u val) {
*(Bit16u *)(off)=val;
};
INLINE void writed(HostPt off,Bit32u val) {
*(Bit32u *)(off)=val;
};
/* The Folowing six functions are slower but they recognize the paged memory system */
//TODO maybe make em inline to go a bit faster
Bit8u mem_readb(PhysPt pt);
Bit16u mem_readw(PhysPt pt);
Bit32u mem_readd(PhysPt pt);
void mem_writeb(PhysPt pt,Bit8u val);
void mem_writew(PhysPt pt,Bit16u val);
void mem_writed(PhysPt pt,Bit32u val);
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 */
INLINE HostPt real_off(Bit16u seg,Bit32u off) {
return memory+(seg<<4)+off;
};
INLINE HostPt real_host(Bit16u seg,Bit32u off) {
return memory+(seg<<4)+off;
};
INLINE PhysPt real_phys(Bit16u seg,Bit32u off) {
return (seg<<4)+off;
};
INLINE Bit8u real_readb(Bit16u seg,Bit16u off) {
return mem_readb((seg<<4)+off);
}
INLINE Bit16u real_readw(Bit16u seg,Bit16u off) {
return mem_readw((seg<<4)+off);
}
INLINE Bit32u real_readd(Bit16u seg,Bit16u 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) {
mem_writeb(((seg<<4)+off),val);
}
INLINE void real_writew(Bit16u seg,Bit16u off,Bit16u val) {
mem_writew(((seg<<4)+off),val);
}
INLINE void real_writed(Bit16u seg,Bit16u off,Bit32u val) {
mem_writed(((seg<<4)+off),val);
}
//#define real_writeb(seg,off,val) mem_writeb((((seg)<<4)+(off)),val)
//#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 Bit16u RealSeg(RealPt pt) {
return (Bit16u)(pt>>16);
}
INLINE Bit16u RealOff(RealPt pt) {
return (Bit16u)(pt&0xffff);
}
INLINE PhysPt Real2Phys(RealPt pt) {
return (RealSeg(pt)<<4) +RealOff(pt);
}
INLINE HostPt Real2Host(RealPt pt) {
return memory+(RealSeg(pt)<<4) +RealOff(pt);
}
INLINE RealPt RealMake(Bit16u seg,Bit16u off) {
return (seg<<16)+off;
}
INLINE void RealSetVec(Bit8u vec,RealPt pt) {
mem_writed(vec<<2,pt);
}
INLINE RealPt RealGetVec(Bit8u vec) {
return mem_readd(vec<<2);
}
#endif

42
include/mixer.h Normal file
View file

@ -0,0 +1,42 @@
/*
* 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.
*/
typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len);
#define MIXER_8MONO 0
#define MIXER_8STEREO 1
#define MIXER_16MONO 2
#define MIXER_16STEREO 3
#define MAX_AUDIO ((1<<(16-1))-1)
#define MIN_AUDIO -(1<<(16-1))
struct MIXER_Channel;
MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * name);
void MIXER_SetVolume(MIXER_Channel * chan,Bit8u vol);
void MIXER_SetFreq(MIXER_Channel * chan,Bit32u freq);
void MIXER_SetMode(MIXER_Channel * chan,Bit8u mode);
void MIXER_Enable(MIXER_Channel * chan,bool enable);
void PCSPEAKER_Enable(bool enable);
void PCSPEAKER_SetFreq(Bit32u freq);

180
include/modules.h Normal file
View file

@ -0,0 +1,180 @@
/* Standard data types used */
typedef unsigned char Bit8u;
typedef signed char Bit8s;
typedef unsigned short Bit16u;
typedef signed short Bit16s;
typedef unsigned long Bit32u;
typedef signed long Bit32s;
#if defined(_MSC_VER)
typedef unsigned __int64 Bit64u;
typedef signed __int64 Bit64s;
#else
typedef unsigned long long int Bit64u;
typedef signed long long int Bit64s;
#endif
/* Setting up pointers to all subfunctions */
#ifdef MODULE_WANT_IO_READ
typedef Bit8u (* IO_ReadHandler)(Bit32u port);
static void (* IO_RegisterReadHandler)(Bit32u port,IO_ReadHandler handler,char * name);
static void (* IO_FreeReadHandler)(Bit32u port);
#endif
#ifdef MODULE_WANT_IO_WRITE
typedef void (* IO_WriteHandler)(Bit32u port,Bit8u value);
static void (* IO_RegisterWriteHandler)(Bit32u port,IO_WriteHandler handler,char * name);
static void (* IO_FreeWriteHandler)(Bit32u port);
#endif
#ifdef MODULE_WANT_IRQ_EOI
typedef void (* IRQ_EOIHandler)(void);
static void (* IRQ_RegisterEOIHandler)(Bit32u irq,IRQ_EOIHandler handler,char * name);
static void (* IRQ_FreeEOIHandler)(Bit32u irq);
#endif
#ifdef MODULE_WANT_IRQ
static void (* IRQ_Activate)(Bit32u irq);
static void (* IRQ_Deactivate)(Bit32u irq);
#endif
#ifdef MODULE_WANT_TIMER
typedef void (* TIMER_MicroHandler)(void);
static void (* TIMER_RegisterMicroHandler)(TIMER_MicroHandler handler,Bit32u micro);
#endif
#ifdef MODULE_WANT_TIMER_TICK
typedef void (* TIMER_TickHandler)(Bit32u ticks);
static void (* TIMER_RegisterTickHandler)(TIMER_TickHandler handler);
#endif
/*
4 8-bit and 4 16-bit channels you can read data from
16-bit reads are word sized
*/
#ifdef MODULE_WANT_DMA_READ
static void (* DMA_8_Read)(Bit32u chan,Bit8u * data,Bit16u size);
static void (* DMA_16_Read)(Bit32u chan,Bit8u * data,Bit16u size);
#endif
/*
4 8-bit and 4 16-bit channels you can write data from
16-bit writes are word sized
*/
#ifdef MODULE_WANT_DMA_READ
static void (* DMA_8_Write)(Bit32u chan,Bit8u * data,Bit16u size);
static void (* DMA_16_Write)(Bit32u chan,Bit8u * data,Bit16u size);
#endif
#ifdef MODULE_WANT_MIXER
/* The len here means the amount of samples needed not the buffersize it needed to fill */
typedef void (* MIXER_MixHandler)(Bit8u * sampdate,Bit32u len);
/* Different types if modes a mixer channel can work in */
#define MIXER_8MONO 0
#define MIXER_8STEREO 1
#define MIXER_16MONO 2
#define MIXER_16STEREO 3
struct MIXER_Channel;
#define MAX_AUDIO ((1<<(16-1))-1)
#define MIN_AUDIO -(1<<(16-1))
MIXER_Channel *(* MIXER_AddChannel)(MIXER_MixHandler handler,Bit32u freq,char * name);
void (* MIXER_SetVolume)(MIXER_Channel * chan,Bit8u vol);
void (* MIXER_SetFreq)(MIXER_Channel * chan,Bit32u freq);
void (* MIXER_SetMode)(MIXER_Channel * chan,Bit8u mode);
void (* MIXER_Enable)(MIXER_Channel * chan,bool enable);
#endif
typedef bool (* MODULE_FindHandler)(char * name,void * * function);
typedef char *(* MODULE_StartHandler)(MODULE_FindHandler find_handler);
#define MODULE_START_PROC "ModuleStart"
#ifdef MODULE_START_FUNCTION
#include <stdio.h>
#define GET_FUNCTION(a) \
if (!find_handler(#a ,(void * *) &a)) { \
return "Can't find requested function"; \
};
#if defined (WIN32)
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
extern "C" {
__declspec(dllexport)
#endif
char * ModuleStart (MODULE_FindHandler find_handler) {
#ifdef MODULE_WANT_IRQ_EOI
GET_FUNCTION(IRQ_RegisterEOIHandler);
GET_FUNCTION(IRQ_FreeEOIHandler);
#endif
#ifdef MODULE_WANT_IRQ
GET_FUNCTION(IRQ_Activate);
GET_FUNCTION(IRQ_Deactivate);
#endif
#ifdef MODULE_WANT_IO_READ
GET_FUNCTION(IO_RegisterReadHandler);
GET_FUNCTION(IO_FreeReadHandler);
#endif
#ifdef MODULE_WANT_IO_WRITE
GET_FUNCTION(IO_RegisterWriteHandler);
GET_FUNCTION(IO_FreeWriteHandler);
#endif
#ifdef MODULE_WANT_TIMER
GET_FUNCTION(TIMER_RegisterMicroHandler);
#endif
#ifdef MODULE_WANT_TIMER_TICKS
GET_FUNCTION(TIMER_RegisterTickHandler);
#endif
#ifdef MODULE_WANT_DMA_READ
GET_FUNCTION(DMA_8_Read);
GET_FUNCTION(DMA_16_Read);
#endif
#ifdef MODULE_WANT_DMA_WRITE
GET_FUNCTION(DMA_8_Write);
GET_FUNCTION(DMA_16_Write);
#endif
#ifdef MODULE_WANT_MIXER
GET_FUNCTION(MIXER_AddChannel);
GET_FUNCTION(MIXER_SetVolume);
GET_FUNCTION(MIXER_SetFreq);
GET_FUNCTION(MIXER_SetMode);
GET_FUNCTION(MIXER_Enable);
#endif
return MODULE_START_FUNCTION;
}
#if defined (WIN32)
}
#endif
#endif

28
include/mouse.h Normal file
View file

@ -0,0 +1,28 @@
/*
* 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.
*/
void Mouse_ShowCursor(void);
void Mouse_HideCursor(void);
void Mouse_CursorMoved(float x,float y);
void Mouse_CursorSet(float x,float y);
void Mouse_ButtonPressed(Bit8u button);
void Mouse_ButtonReleased(Bit8u button);

44
include/pic.h Normal file
View file

@ -0,0 +1,44 @@
/*
* 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 __PIC_H
#define __PIC_H
typedef void (PIC_EOIHandler) (void);
typedef void (PIC_Function)(void);
extern Bit32u PIC_IRQCheck;
void PIC_ActivateIRQ(Bit32u irq);
void PIC_DeActivateIRQ(Bit32u irq);
void PIC_runIRQs(void);
void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name);
void PIC_FreeIRQ(Bit32u irq);
bool PIC_IRQActive(Bit32u irq);
/* A Queued function should never queue itself again this will go horribly wrong */
void PIC_QueueFunction(PIC_Function * function);
#endif

58
include/programs.h Normal file
View file

@ -0,0 +1,58 @@
/*
* 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 __PROGRAM_H
#define __PROGRAM_H
#include <dosbox.h>
#include <dos_inc.h>
char * MSG_Get(char * msg);
struct PROGRAM_Info {
Bit16u psp_seg;
PSP psp_copy;
char full_name[32]; //Enough space for programs only on the z:\ drive
char * cmd_line;
};
typedef void (PROGRAMS_Main)(PROGRAM_Info * info);
void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main);
class Program {
public:
Program(PROGRAM_Info * program_info);
virtual void Run(void)=0;
char * GetEnvStr(char * env_entry);
char * GetEnvNum(Bit32u num);
Bit32u GetEnvCount(void);
bool SetEnv(char * env_entry,char * new_string);
void WriteOut(char * format,...); /* Write to standard output */
PROGRAM_Info * prog_info;
};
void SHELL_AddAutoexec(char * line,...);
#endif

114
include/regs.h Normal file
View file

@ -0,0 +1,114 @@
/*
* 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.
*/
#if !defined __REGS_H
#define __REGS_H
#include <mem.h>
struct Flag_Info {
union {
Bit8u b;
Bit16u w;
Bit32u d;
} var1,var2,result;
Bitu type;
Bitu prev_type;
bool cf,sf,pf,af,zf,of,df,tf,intf;
bool nt;
Bit8u io;
bool oldcf;
};
struct Segment {
Bit16u value;
bool special; /* Signal for pointing to special memory */
HostPt host; /* The address of start in host memory */
PhysPt phys; /* The phyiscal address start in emulated machine */
};
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 {
union {
Bit32u d;
Bit16u w;
struct {
Bit8u l,h;
}b;
} ax,bx,cx,dx,si,di,sp,bp,ip;
};
extern CPU_Regs cpu_regs;
#define reg_al cpu_regs.ax.b.l
//extern Bit8u & reg_al=cpu_regs.ax.b.l;
#define reg_ah cpu_regs.ax.b.h
#define reg_ax cpu_regs.ax.w
#define reg_eax cpu_regs.ax.d
#define reg_bl cpu_regs.bx.b.l
#define reg_bh cpu_regs.bx.b.h
#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
#define reg_cx cpu_regs.cx.w
#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
#define reg_esi cpu_regs.si.d
#define reg_di cpu_regs.di.w
#define reg_edi cpu_regs.di.d
#define reg_sp cpu_regs.sp.w
#define reg_esp cpu_regs.sp.d
#define reg_bp cpu_regs.bp.w
#define reg_ebp cpu_regs.bp.d
#define reg_ip cpu_regs.ip.w
#define reg_eip cpu_regs.ip.d
#endif

25
include/render.h Normal file
View file

@ -0,0 +1,25 @@
/*
* 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.
*/
typedef void RENDER_Handler(Bit8u * * data);
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags, RENDER_Handler * handler);
void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue);

43
include/setup.h Normal file
View file

@ -0,0 +1,43 @@
/*
* 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 _SETUP_H_
#define _SETUP_H_
#include <cross.h>
enum { S_STRING,S_HEX,S_INT,S_BOOL};
typedef char *(String_Handler)(char * input);
typedef char *(Hex_Handler)(Bitu * input);
typedef char *(Int_Handler)(Bits * input);
typedef char *(Bool_Handler)(bool input);
class Setup {
private:
int argc;
char * * argv;
};
extern char dosbox_basedir[CROSS_LEN];
#endif

63
include/support.h Normal file
View file

@ -0,0 +1,63 @@
/*
* 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.
*/
#if !defined __SUPPORT_H
#define __SUPPORT_H
#include <dosbox.h>
#include <string.h>
#include <ctype.h>
#if defined (_MSC_VER) /* MS Visual C++ */
#define strcasecmp(a,b) stricmp(a,b)
#define strncasecmp(a,b,n) _strnicmp(a,b,n)
// if (stricmp(name,devices[index]->name)==0) return index;
#else
//if (strcasecmp(name,devices[index]->name)==0) return index;
//#define nocasestrcmp(a,b) stricmp(a,b)
#endif
void strreplace(char * str,char o,char n);
char *ltrim(char *str);
void rtrim(char * const str);
char *trim(char *str);
bool wildcmp(char *wild, char *string);
bool ScanCMDBool(char * cmd,char * check);
char * ScanCMDRemain(char * cmd);
bool ScanCMDHex(char * cmd,char * check,Bits * result);
char * StripWord(char * cmd);
INLINE char * upcase(char * str) {
char * oldstr=str;
while (*str) *str++=toupper(*str);
return oldstr;
}
INLINE char * lowcase(char * str) {
char * oldstr=str;
while (*str) *str++=tolower(*str);
return oldstr;
}
#endif

53
include/timer.h Normal file
View file

@ -0,0 +1,53 @@
/*
* 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 _TIMER_H_
#define _TIMER_H_
/* underlying clock rate in HZ */
#include <SDL/SDL.h>
extern Bit32u LastTicks;
#define GetTicks() SDL_GetTicks()
typedef void (*TIMER_TickHandler)(Bitu ticks);
typedef void (*TIMER_MicroHandler)(void);
typedef void (*TIMER_DelayHandler)(void);
typedef void TIMER_Block;
/* Register a function that gets called everytime if 1 or more ticks pass */
TIMER_Block * TIMER_RegisterTickHandler(TIMER_TickHandler handler);
/* Register a function to be called every x microseconds */
TIMER_Block * TIMER_RegisterMicroHandler(TIMER_MicroHandler handler,Bitu micro);
/* Register a function to be called once after x microseconds */
TIMER_Block * TIMER_RegisterDelayHandler(TIMER_DelayHandler handler,Bitu delay);
/* Set the microseconds value to a new value */
void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro);
/* This function should be called very often to support very high res timers
Although with the new timer code it doesn't matter that much */
void TIMER_CheckPIT(void);
/* This will add ms ticks to support the timer handlers */
void TIMER_AddTicks(Bit32u ticks);
#endif

50
include/video.h Normal file
View file

@ -0,0 +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 __VIDEO_H
#define __VIDEO_H
typedef void (GFX_DrawHandler)(Bit8u * vidstart);
/* Used to reply to the renderer what size to set */
typedef void (GFX_ResizeHandler)(Bitu * width,Bitu * height);
struct GFX_PalEntry {
Bit8u r;
Bit8u g;
Bit8u b;
Bit8u unused;
};
struct GFX_Info {
Bitu width,height,bpp,pitch;
};
extern GFX_Info gfx_info;
void GFX_Events(void);
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries);
void GFX_SetDrawHandler(GFX_DrawHandler * handler);
void GFX_Resize(Bitu width,Bitu height,Bitu bpp,GFX_ResizeHandler * resize);
void GFX_Start(void);
void GFX_Stop(void);
void GFX_SwitchFullScreen(void);
#endif

32
scripts/ega-switch.pl Normal file
View file

@ -0,0 +1,32 @@
#!/usr/bin/perl
use integer;
open (THEFILE,'>','../src/hardware/ega-switch.h')
or die "Can't open my file $!";
print THEFILE "switch (bit_mask) {\n";
for ($i = 0; $i < 256; $i++) {
print THEFILE "\tcase $i:\n";
$b=128;
$add=0;
do {
if ($i & $b) {
print THEFILE "\t{\n";
print THEFILE "\t\tBit8u color=0;\n";
print THEFILE "\t\tif (pixels.b[0] & $b) color|=1;\n";
print THEFILE "\t\tif (pixels.b[1] & $b) color|=2;\n";
print THEFILE "\t\tif (pixels.b[2] & $b) color|=4;\n";
print THEFILE "\t\tif (pixels.b[3] & $b) color|=8;\n";
print THEFILE "\t\t*(write_pixels+$add)=color;\n";
print THEFILE "\t\t*(write_pixels+$add+512*1024)=color;\n";
print THEFILE "\t}\n";
}
$b=$b >> 1;
$add=$add+1;
} until ($b == 0);
print THEFILE "\tbreak;\n";
}
print THEFILE "}\n";
close (THEFILE);

25
scripts/font-switch.pl Normal file
View file

@ -0,0 +1,25 @@
#!/usr/bin/perl
use integer;
open (THEFILE,'>','../src/hardware/font-switch.h')
or die "Can't open my file $!";
print THEFILE "switch (bit_mask) {\n";
for ($i = 0; $i < 256; $i++) {
print THEFILE "\tcase $i:\n";
$b=128;
$add=0;
do {
if ($i & $b) {
print THEFILE "\t\t*(draw+$add)=fg;\n";
} else {
print THEFILE "\t\t*(draw+$add)=bg;\n";
}
$b=$b >> 1;
$add=$add+1;
} until ($b == 0);
print THEFILE "\tbreak;\n";
}
print THEFILE "}\n";
close (THEFILE);

26
settings.h.cvs Normal file
View file

@ -0,0 +1,26 @@
/* Enable the debugger */
//#define C_DEBUG
/* Enable logging of debug information */
//#define C_LOGGING
/* Use multi threading to speed up things on multi cpu's, also gives a nice frame-skipping effect :) */
#define C_THREADED
/* Enable debugging for several modules, requires C_LOGGING */
#define DEBUG_SBLASTER /* SoundBlaster Debugging*/
#define DEBUG_DMA /* DMA Debugging */
#define DEBUG_DOS /* DOS Debugging */
#define LOG_MSG S_Warn
#ifdef C_LOGGING
#define LOG_DEBUG S_Warn
#define LOG_WARN S_Warn
#define LOG_ERROR S_Warn
#else
#define LOG_DEBUG
#define LOG_WARN
#define LOG_ERROR
#endif

10
src/Makefile.am Normal file
View file

@ -0,0 +1,10 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
SUBDIRS = cpu debug dos fpu gui hardware ints misc shell platform
bin_PROGRAMS = dosbox
dosbox_SOURCES = dosbox.cpp
dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \
ints/libints.a misc/libmisc.a shell/libshell.a -lcurses
EXTRA_DIST = dosbox.lang

5
src/cpu/Makefile.am Normal file
View file

@ -0,0 +1,5 @@
SUBDIRS = core_16
AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcpu.a
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp

171
src/cpu/callback.cpp Normal file
View file

@ -0,0 +1,171 @@
/*
* 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 <stdlib.h>
#include <stdio.h>
#include "dosbox.h"
#include "callback.h"
#include "mem.h"
#include "cpu.h"
/* CallBack are located at 0xC800:0
And they are 16 bytes each and you can define them to behave in certain ways like a
far return or and IRET
*/
CallBack_Handler CallBack_Handlers[CB_MAX];
static Bitu call_runint16,call_idle,call_default,call_runfar16;
static Bitu illegal_handler(void) {
E_Exit("Illegal CallBack Called");
return 1;
}
Bitu CALLBACK_Allocate(void) {
for (Bitu i=0;(i<CB_MAX);i++) {
if (CallBack_Handlers[i]==&illegal_handler) {
CallBack_Handlers[i]=0;
return i;
}
}
E_Exit("CALLBACK:Can't allocate handler.");
return 0;
}
void CALLBACK_Idle(void) {
/* this makes the cpu execute instructions to handle irq's and then come back */
Bit16u oldcs=Segs[cs].value;
Bit32u oldeip=reg_eip;
SetSegment_16(cs,CB_SEG);
reg_eip=call_idle<<4;
DOSBOX_RunMachine();
reg_eip=oldeip;
SetSegment_16(cs,oldcs);
}
static Bitu default_handler(void) {
LOG_WARN("Illegal Unhandled Interrupt Called %d",lastint);
return CBRET_NONE;
};
static Bitu stop_handler(void) {
return CBRET_STOP;
};
void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) {
real_writew((Bit16u)CB_SEG,(call_runfar16<<4)+1,off);
real_writew((Bit16u)CB_SEG,(call_runfar16<<4)+3,seg);
Bit32u oldeip=reg_eip;
Bit16u oldcs=Segs[cs].value;
reg_eip=call_runfar16<<4;
SetSegment_16(cs,CB_SEG);
DOSBOX_RunMachine();
reg_eip=oldeip;
SetSegment_16(cs,oldcs);
}
void CALLBACK_RunRealInt(Bit8u intnum) {
real_writeb((Bit16u)CB_SEG,(call_runint16<<4)+1,intnum);
Bit32u oldeip=reg_eip;
Bit16u oldcs=Segs[cs].value;
reg_eip=call_runint16<<4;
SetSegment_16(cs,CB_SEG);
DOSBOX_RunMachine();
reg_eip=oldeip;
SetSegment_16(cs,oldcs);
}
void CALLBACK_SZF(bool val) {
Bit16u tempf=real_readw(Segs[ss].value,reg_sp+4) & 0xFFBF;
Bit16u newZF=(val==true) << 6;
real_writew(Segs[ss].value,reg_sp+4,(tempf | newZF));
};
void CALLBACK_SCF(bool val) {
Bit16u tempf=real_readw(Segs[ss].value,reg_sp+4) & 0xFFFE;
Bit16u newCF=(val==true);
real_writew(Segs[ss].value,reg_sp+4,(tempf | newCF));
};
bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type) {
if (callback>=CB_MAX) return false;
switch (type) {
case CB_RETF:
real_writeb((Bit16u)CB_SEG,(callback<<4),(Bit8u)0xFE); //GRP 4
real_writeb((Bit16u)CB_SEG,(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction
real_writew((Bit16u)CB_SEG,(callback<<4)+2,callback); //The immediate word
real_writeb((Bit16u)CB_SEG,(callback<<4)+4,(Bit8u)0xCB); //A RETF Instruction
break;
case CB_IRET:
real_writeb((Bit16u)CB_SEG,(callback<<4),(Bit8u)0xFE); //GRP 4
real_writeb((Bit16u)CB_SEG,(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction
real_writew((Bit16u)CB_SEG,(callback<<4)+2,callback); //The immediate word
real_writeb((Bit16u)CB_SEG,(callback<<4)+4,(Bit8u)0xCF); //An IRET Instruction
break;
default:
E_Exit("CALLBACK:Setup:Illegal type %d",type);
}
CallBack_Handlers[callback]=handler;
return true;
}
void CALLBACK_Init(void) {
Bitu i;
for (i=0;i<CB_MAX;i++) {
CallBack_Handlers[i]=&illegal_handler;
}
/* Setup the Software interrupt handler */
call_runint16=CALLBACK_Allocate();
CallBack_Handlers[call_runint16]=stop_handler;
real_writeb((Bit16u)CB_SEG,(call_runint16<<4),0xCD);
real_writeb((Bit16u)CB_SEG,(call_runint16<<4)+2,0xFE);
real_writeb((Bit16u)CB_SEG,(call_runint16<<4)+3,0x38);
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 */
call_idle=CALLBACK_Allocate();
CallBack_Handlers[call_idle]=stop_handler;
for (i=0;i<=11;i++) real_writeb((Bit16u)CB_SEG,(call_idle<<4)+i,0x90);
real_writeb((Bit16u)CB_SEG,(call_idle<<4)+12,0xFE);
real_writeb((Bit16u)CB_SEG,(call_idle<<4)+13,0x38);
real_writew((Bit16u)CB_SEG,(call_idle<<4)+14,call_idle);
/* Setup all Interrupt to point to the default handler */
call_default=CALLBACK_Allocate();
CALLBACK_Setup(call_default,&default_handler,CB_IRET);
for (i=0;i<256;i++) {
real_writed(0,i*4,CALLBACK_RealPointer(call_default));
}
}

View file

@ -0,0 +1,3 @@
noinst_HEADERS = helpers.h instructions.h main.h prefix_66.h prefix_of.h start.h stop.h support.h table_ea.h \
prefix_66_of.h

76
src/cpu/core_16/helpers.h Normal file
View file

@ -0,0 +1,76 @@
/*
* 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 GetEAa \
EAPoint eaa=(*lookupEATable)[rm]();
#define GetRMEAa \
GetRM; \
GetEAa;
#define RMEbGb(inst) \
{ \
GetRMrb; \
if (rm >= 0xc0 ) {GetEArb;inst(*earb,*rmrb,LoadRb,SaveRb);} \
else {GetEAa;inst(eaa,*rmrb,LoadMb,SaveMb);} \
}
#define RMGbEb(inst) \
{ \
GetRMrb; \
if (rm >= 0xc0 ) {GetEArb;inst(*rmrb,*earb,LoadRb,SaveRb);} \
else {GetEAa;inst(*rmrb,LoadMb(eaa),LoadRb,SaveRb);} \
}
#define RMEwGw(inst) \
{ \
GetRMrw; \
if (rm >= 0xc0 ) {GetEArw;inst(*earw,*rmrw,LoadRw,SaveRw);} \
else {GetEAa;inst(eaa,*rmrw,LoadMw,SaveMw);} \
}
#define RMGwEw(inst) \
{ \
GetRMrw; \
if (rm >= 0xc0 ) {GetEArw;inst(*rmrw,*earw,LoadRw,SaveRw);} \
else {GetEAa;inst(*rmrw,LoadMw(eaa),LoadRw,SaveRw);} \
}
#define RMEdGd(inst) \
{ \
GetRMrd; \
if (rm >= 0xc0 ) {GetEArd;inst(*eard,*rmrd,LoadRd,SaveRd);} \
else {GetEAa;inst(eaa,*rmrd,LoadMd,SaveMd);} \
}
#define RMGdEd(inst) \
{ \
GetRMrd; \
if (rm >= 0xc0 ) {GetEArd;inst(*rmrd,*eard,LoadRd,SaveRd);} \
else {GetEAa;inst(*rmrd,LoadMd(eaa),LoadRd,SaveRd);} \
}
#define ALIb(inst) \
{ inst(reg_al,Fetchb(),LoadRb,SaveRb)}
#define AXIw(inst) \
{ inst(reg_ax,Fetchw(),LoadRw,SaveRw);}
#define EAXId(inst) \
{ inst(reg_eax,Fetchd(),LoadRd,SaveRd);}

View file

@ -0,0 +1,593 @@
/*
* 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.
*/
/* Jumps */
/*
Could perhaps do some things with 8 and 16 bit operations like shifts, doing them in 32 bit regs
*/
#define JumpSIb(blah) \
if (blah) { \
ADDIPFAST(Fetchbs()); \
} else { \
ADDIPFAST(1); \
}
#define JumpSIw(blah) \
if (blah) { \
ADDIPFAST(Fetchws()); \
} else { \
ADDIPFAST(2); \
}
#define INTERRUPT(blah) \
{ \
Bit8u new_num=blah; \
SAVEIP; \
Interrupt(new_num); \
LOADIP; \
}
/* All Byte genereal instructions */
#define ADDB(op1,op2,load,save) \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b+flags.var2.b; \
save(op1,flags.result.b); \
flags.type=t_ADDb;
#define ADCB(op1,op2,load,save) \
flags.oldcf=get_CF(); \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b+flags.var2.b+flags.oldcf; \
save(op1,flags.result.b); \
flags.type=t_ADCb;
#define SBBB(op1,op2,load,save) \
flags.oldcf=get_CF(); \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b-(flags.var2.b+flags.oldcf); \
save(op1,flags.result.b); \
flags.type=t_SBBb;
#define SUBB(op1,op2,load,save) \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b-flags.var2.b; \
save(op1,flags.result.b); \
flags.type=t_SUBb;
#define ORB(op1,op2,load,save) \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b | flags.var2.b; \
save(op1,flags.result.b); \
flags.type=t_ORb;
#define XORB(op1,op2,load,save) \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b ^ flags.var2.b; \
save(op1,flags.result.b); \
flags.type=t_XORb;
#define ANDB(op1,op2,load,save) \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b & flags.var2.b; \
save(op1,flags.result.b); \
flags.type=t_ANDb;
#define CMPB(op1,op2,load,save) \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b-flags.var2.b; \
flags.type=t_CMPb;
#define TESTB(op1,op2,load,save) \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b & flags.var2.b; \
flags.type=t_TESTb;
/* All Word General instructions */
#define ADDW(op1,op2,load,save) \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w+flags.var2.w; \
save(op1,flags.result.w); \
flags.type=t_ADDw;
#define ADCW(op1,op2,load,save) \
flags.oldcf=get_CF(); \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w+flags.var2.w+flags.oldcf; \
save(op1,flags.result.w); \
flags.type=t_ADCw;
#define SBBW(op1,op2,load,save) \
flags.oldcf=get_CF(); \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w-(flags.var2.w+flags.oldcf); \
save(op1,flags.result.w); \
flags.type=t_SBBw;
#define SUBW(op1,op2,load,save) \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w-flags.var2.w; \
save(op1,flags.result.w); \
flags.type=t_SUBw;
#define ORW(op1,op2,load,save) \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w | flags.var2.w; \
save(op1,flags.result.w); \
flags.type=t_ORw;
#define XORW(op1,op2,load,save) \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w ^ flags.var2.w; \
save(op1,flags.result.w); \
flags.type=t_XORw;
#define ANDW(op1,op2,load,save) \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w & flags.var2.w; \
save(op1,flags.result.w); \
flags.type=t_ANDw;
#define CMPW(op1,op2,load,save) \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w-flags.var2.w; \
flags.type=t_CMPw;
#define TESTW(op1,op2,load,save) \
flags.var1.w=load(op1);flags.var2.w=op2; \
flags.result.w=flags.var1.w & flags.var2.w; \
flags.type=t_TESTw;
/* All DWORD General Instructions */
#define ADDD(op1,op2,load,save) \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d+flags.var2.d; \
save(op1,flags.result.d); \
flags.type=t_ADDd;
#define ADCD(op1,op2,load,save) \
flags.oldcf=get_CF(); \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d+flags.var2.d+flags.oldcf; \
save(op1,flags.result.d); \
flags.type=t_ADCd;
#define SBBD(op1,op2,load,save) \
flags.oldcf=get_CF(); \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d-(flags.var2.d+flags.oldcf); \
save(op1,flags.result.d); \
flags.type=t_SBBd;
#define SUBD(op1,op2,load,save) \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d-flags.var2.d; \
save(op1,flags.result.d); \
flags.type=t_SUBd;
#define ORD(op1,op2,load,save) \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d | flags.var2.d; \
save(op1,flags.result.d); \
flags.type=t_ORd;
#define XORD(op1,op2,load,save) \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d ^ flags.var2.d; \
save(op1,flags.result.d); \
flags.type=t_XORd;
#define ANDD(op1,op2,load,save) \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d & flags.var2.d; \
save(op1,flags.result.d); \
flags.type=t_ANDd;
#define CMPD(op1,op2,load,save) \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d-flags.var2.d; \
flags.type=t_CMPd;
#define TESTD(op1,op2,load,save) \
flags.var1.d=load(op1);flags.var2.d=op2; \
flags.result.d=flags.var1.d & flags.var2.d; \
flags.type=t_TESTd;
#define INCB(op1,load,save) \
LoadCF;flags.result.b=load(op1)+1; \
save(op1,flags.result.b); \
flags.type=t_INCb; \
#define INCW(op1,load,save) \
LoadCF;flags.result.w=load(op1)+1; \
save(op1,flags.result.w); \
flags.type=t_INCw;
#define INCD(op1,load,save) \
LoadCF;flags.result.d=load(op1)+1; \
save(op1,flags.result.d); \
flags.type=t_INCd;
#define DECB(op1,load,save) \
LoadCF;flags.result.b=load(op1)-1; \
save(op1,flags.result.b); \
flags.type=t_DECb;
#define DECW(op1,load,save) \
LoadCF;flags.result.w=load(op1)-1; \
save(op1,flags.result.w); \
flags.type=t_DECw;
#define DECD(op1,load,save) \
LoadCF;flags.result.d=load(op1)-1; \
save(op1,flags.result.d); \
flags.type=t_DECd;
#define NOTDONE \
SUBIP(1);E_Exit("CPU:Opcode %2X Unhandled",Fetchb());
#define NOTDONE66 \
SUBIP(1);E_Exit("CPU:Opcode 66:%2X Unhandled",Fetchb());
//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
#define ROLB(op1,op2,load,save) \
if (!(op2&0x07)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.var1.b=load(op1);flags.var2.b=op2&0x07; \
flags.result.b=(flags.var1.b << flags.var2.b) | \
(flags.var1.b >> (8-flags.var2.b)); \
save(op1,flags.result.b); \
flags.type=t_ROLb;
#define ROLW(op1,op2,load,save) \
if (!(op2&0x0F)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.var1.w=load(op1);flags.var2.b=op2&0x0F; \
flags.result.w=(flags.var1.w << flags.var2.b) | \
(flags.var1.w >> (16-flags.var2.b)); \
save(op1,flags.result.w); \
flags.type=t_ROLw;
#define ROLD(op1,op2,load,save) \
if (!(op2&0x0F)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.var1.d=load(op1);flags.var2.b=op2&0x0F; \
flags.result.d=(flags.var1.d << flags.var2.b) | \
(flags.var1.d >> (32-flags.var2.b)); \
save(op1,flags.result.d); \
flags.type=t_ROLd;
#define RORB(op1,op2,load,save) \
if (!(op2&0x07)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.var1.b=load(op1);flags.var2.b=op2&0x07; \
flags.result.b=(flags.var1.b >> flags.var2.b) | \
(flags.var1.b << (8-flags.var2.b)); \
save(op1,flags.result.b); \
flags.type=t_RORb;
#define RORW(op1,op2,load,save) \
if (!(op2&0x0F)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.var1.w=load(op1);flags.var2.b=op2&0x0F; \
flags.result.w=(flags.var1.w >> flags.var2.b) | \
(flags.var1.w << (16-flags.var2.b)); \
save(op1,flags.result.w); \
flags.type=t_RORw;
#define RORD(op1,op2,load,save) \
if (!(op2&0x0F)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.var1.d=load(op1);flags.var2.b=op2&0x0F; \
flags.result.d=(flags.var1.d >> flags.var2.b) | \
(flags.var1.d << (32-flags.var2.b)); \
save(op1,flags.result.d); \
flags.type=t_RORd;
#define RCLB(op1,op2,load,save) \
if (!(op2%9)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.cf=get_CF();flags.type=t_RCLb; \
flags.var1.b=load(op1);flags.var2.b=op2%9; \
flags.result.b=(flags.var1.b << flags.var2.b) | \
(flags.cf << (flags.var2.b-1)) | \
(flags.var1.b >> (9-flags.var2.b)); \
save(op1,flags.result.b);
#define RCLW(op1,op2,load,save) \
if (!(op2%17)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.cf=get_CF();flags.type=t_RCLw; \
flags.var1.w=load(op1);flags.var2.b=op2%17; \
flags.result.w=(flags.var1.w << flags.var2.b) | \
(flags.cf << (flags.var2.b-1)) | \
(flags.var1.w >> (17-flags.var2.b)); \
save(op1,flags.result.w);
#define RCLD(op1,op2,load,save) \
if (!op2) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.cf=get_CF();flags.type=t_RCLd; \
flags.var1.d=load(op1);flags.var2.b=op2; \
if (flags.var2.b==1) { \
flags.result.d=flags.var1.d << 1 | flags.cf; \
} else { \
flags.result.d=(flags.var1.d << flags.var2.b) | \
(flags.cf << (flags.var2.b-1)) | \
(flags.var1.d >> (33-flags.var2.b)); \
} \
save(op1,flags.result.d);
#define RCRB(op1,op2,load,save) \
if (!(op2%9)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.cf=get_CF();flags.type=t_RCRb; \
flags.var1.b=load(op1);flags.var2.b=op2%9; \
flags.result.b=(flags.var1.b >> flags.var2.b) | \
(flags.cf << (8-flags.var2.b)) | \
(flags.var1.b << (9-flags.var2.b)); \
save(op1,flags.result.b);
#define RCRW(op1,op2,load,save) \
if (!(op2%17)) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.cf=get_CF();flags.type=t_RCRw; \
flags.var1.w=load(op1);flags.var2.b=op2%17; \
flags.result.w=(flags.var1.w >> flags.var2.b) | \
(flags.cf << (16-flags.var2.b)) | \
(flags.var1.w << (17-flags.var2.b)); \
save(op1,flags.result.w);
#define RCRD(op1,op2,load,save) \
if (!op2) break; \
flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \
flags.cf=get_CF();flags.type=t_RCRd; \
flags.var1.d=load(op1);flags.var2.b=op2; \
if (flags.var2.b==1) { \
flags.result.d=flags.var1.d >> 1 | flags.cf << 31; \
} else { \
flags.result.d=(flags.var1.d >> flags.var2.b) | \
(flags.cf << (32-flags.var2.b)) | \
(flags.var1.d << (33-flags.var2.b)); \
} \
save(op1,flags.result.d);
#define SHLB(op1,op2,load,save) \
if (!op2) break; \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b << flags.var2.b; \
save(op1,flags.result.b); \
flags.type=t_SHLb;
#define SHLW(op1,op2,load,save) \
if (!op2) break; \
flags.var1.w=load(op1);flags.var2.b=op2; \
flags.result.w=flags.var1.w << flags.var2.b; \
save(op1,flags.result.w); \
flags.type=t_SHLw;
#define SHLD(op1,op2,load,save) \
if (!op2) break; \
flags.var1.d=load(op1);flags.var2.b=op2; \
flags.result.d=flags.var1.d << flags.var2.b; \
save(op1,flags.result.d); \
flags.type=t_SHLd;
#define SHRB(op1,op2,load,save) \
if (!op2) break; \
flags.var1.b=load(op1);flags.var2.b=op2; \
flags.result.b=flags.var1.b >> flags.var2.b; \
save(op1,flags.result.b); \
flags.type=t_SHRb;
#define SHRW(op1,op2,load,save) \
if (!op2) break; \
flags.var1.w=load(op1);flags.var2.b=op2; \
flags.result.w=flags.var1.w >> flags.var2.b; \
save(op1,flags.result.w); \
flags.type=t_SHRw;
#define SHRD(op1,op2,load,save) \
if (!op2) break; \
flags.var1.d=load(op1);flags.var2.b=op2; \
flags.result.d=flags.var1.d >> flags.var2.b; \
save(op1,flags.result.d); \
flags.type=t_SHRd;
#define SARB(op1,op2,load,save) \
if (!op2) break; \
flags.var1.b=load(op1);flags.var2.b=op2; \
if (flags.var2.b>8) flags.var2.b=8; \
if (flags.var1.b & 0x80) { \
flags.result.b=(flags.var1.b >> flags.var2.b)| \
(0xff << (8 - flags.var2.b)); \
} else { \
flags.result.b=flags.var1.b >> flags.var2.b; \
} \
save(op1,flags.result.b); \
flags.type=t_SARb;
#define SARW(op1,op2,load,save) \
if (!op2) break; \
flags.var1.w=load(op1);flags.var2.b=op2; \
if (flags.var2.b>16) flags.var2.b=16; \
if (flags.var1.w & 0x8000) { \
flags.result.w=(flags.var1.w >> flags.var2.b)| \
(0xffff << (16 - flags.var2.b)); \
} else { \
flags.result.w=flags.var1.w >> flags.var2.b; \
} \
save(op1,flags.result.w); \
flags.type=t_SARw;
#define SARD(op1,op2,load,save) \
if (!op2) break; \
flags.var1.d=load(op1);flags.var2.b=op2; \
if (flags.var1.d & 0x80000000) { \
flags.result.d=(flags.var1.d >> flags.var2.b)| \
(0xffffffff << (32 - flags.var2.b)); \
} else { \
flags.result.d=flags.var1.d >> flags.var2.b; \
} \
save(op1,flags.result.d); \
flags.type=t_SARd;
#define GRP2B(blah) \
{ \
GetRM; \
if (rm >= 0xc0) { \
GetEArb; \
Bit8u val=blah & 0x1f; \
switch (rm&0x38) { \
case 0x00:ROLB(*earb,val,LoadRb,SaveRb);break; \
case 0x08:RORB(*earb,val,LoadRb,SaveRb);break; \
case 0x10:RCLB(*earb,val,LoadRb,SaveRb);break; \
case 0x18:RCRB(*earb,val,LoadRb,SaveRb);break; \
case 0x20:/* SHL and SAL are the same */ \
case 0x30:SHLB(*earb,val,LoadRb,SaveRb);break; \
case 0x28:SHRB(*earb,val,LoadRb,SaveRb);break; \
case 0x38:SARB(*earb,val,LoadRb,SaveRb);break; \
} \
} else { \
GetEAa; \
Bit8u val=blah & 0x1f; \
switch (rm & 0x38) { \
case 0x00:ROLB(eaa,val,LoadMb,SaveMb);break; \
case 0x08:RORB(eaa,val,LoadMb,SaveMb);break; \
case 0x10:RCLB(eaa,val,LoadMb,SaveMb);break; \
case 0x18:RCRB(eaa,val,LoadMb,SaveMb);break; \
case 0x20:/* SHL and SAL are the same */ \
case 0x30:SHLB(eaa,val,LoadMb,SaveMb);break; \
case 0x28:SHRB(eaa,val,LoadMb,SaveMb);break; \
case 0x38:SARB(eaa,val,LoadMb,SaveMb);break; \
} \
} \
}
#define GRP2W(blah) \
{ \
GetRM; \
if (rm >= 0xc0) { \
GetEArw; \
Bit8u val=blah & 0x1f; \
switch (rm&0x38) { \
case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break; \
case 0x08:RORW(*earw,val,LoadRw,SaveRw);break; \
case 0x10:RCLW(*earw,val,LoadRw,SaveRw);break; \
case 0x18:RCRW(*earw,val,LoadRw,SaveRw);break; \
case 0x20:/* SHL and SAL are the same */ \
case 0x30:SHLW(*earw,val,LoadRw,SaveRw);break; \
case 0x28:SHRW(*earw,val,LoadRw,SaveRw);break; \
case 0x38:SARW(*earw,val,LoadRw,SaveRw);break; \
} \
} else { \
GetEAa; \
Bit8u val=blah & 0x1f; \
switch (rm & 0x38) { \
case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break; \
case 0x08:RORW(eaa,val,LoadMw,SaveMw);break; \
case 0x10:RCLW(eaa,val,LoadMw,SaveMw);break; \
case 0x18:RCRW(eaa,val,LoadMw,SaveMw);break; \
case 0x20:/* SHL and SAL are the same */ \
case 0x30:SHLW(eaa,val,LoadMw,SaveMw);break; \
case 0x28:SHRW(eaa,val,LoadMw,SaveMw);break; \
case 0x38:SARW(eaa,val,LoadMw,SaveMw);break; \
} \
} \
}
#define GRP2D(blah) \
{ \
GetRM; \
if (rm >= 0xc0) { \
GetEArd; \
Bit8u val=blah & 0x1f; \
switch (rm&0x38) { \
case 0x00:ROLD(*eard,val,LoadRd,SaveRd);break; \
case 0x08:RORD(*eard,val,LoadRd,SaveRd);break; \
case 0x10:RCLD(*eard,val,LoadRd,SaveRd);break; \
case 0x18:RCRD(*eard,val,LoadRd,SaveRd);break; \
case 0x20:/* SHL and SAL are the same */ \
case 0x30:SHLD(*eard,val,LoadRd,SaveRd);break; \
case 0x28:SHRD(*eard,val,LoadRd,SaveRd);break; \
case 0x38:SARD(*eard,val,LoadRd,SaveRd);break; \
} \
} else { \
GetEAa; \
Bit8u val=blah & 0x1f; \
switch (rm & 0x38) { \
case 0x00:ROLD(eaa,val,LoadMd,SaveMd);break; \
case 0x08:RORD(eaa,val,LoadMd,SaveMd);break; \
case 0x10:RCLD(eaa,val,LoadMd,SaveMd);break; \
case 0x18:RCRD(eaa,val,LoadMd,SaveMd);break; \
case 0x20:/* SHL and SAL are the same */ \
case 0x30:SHLD(eaa,val,LoadMd,SaveMd);break; \
case 0x28:SHRD(eaa,val,LoadMd,SaveMd);break; \
case 0x38:SARD(eaa,val,LoadMd,SaveMd);break; \
} \
} \
}
/* let's hope bochs has it correct with the higher than 16 shifts */
#define DSHLW(op1,op2,op3,load,save) \
flags.var1.d=(load(op1)<<16)|op2;flags.var2.b=op3; \
Bit32u tempd=flags.var1.d << flags.var2.b; \
if (flags.var2.b>16) tempd |= (op2 << (flags.var2.b - 16)); \
flags.result.w=(Bit16u)(tempd >> 16); \
save(op1,flags.result.w); \
flags.type=t_DSHLw;
#define DSHLD(op1,op2,op3,load,save) \
flags.var1.d=load(op1);flags.var2.b=op3; \
flags.result.d=(flags.var1.d << flags.var2.b) | (op2 >> (32-flags.var2.b)); \
save(op1,flags.result.d); \
flags.type=t_DSHLd;
#define DSHRW(op1,op2,op3,load,save) \
flags.var1.d=(load(op1)<<16)|op2;flags.var2.b=op3; \
Bit32u tempd=flags.var1.d >> flags.var2.b; \
if (flags.var2.b>16) tempd |= (op2 << (32-flags.var2.b )); \
flags.result.w=(Bit16u)(tempd); \
save(op1,flags.result.w); \
flags.type=t_DSHRw;
#define DSHRD(op1,op2,op3,load,save) \
flags.var1.d=load(op1);flags.var2.b=op3; \
flags.result.d=(flags.var1.d >> flags.var2.b) | (op2 << (32-flags.var2.b)); \
save(op1,flags.result.d); \
flags.type=t_DSHRd;

1488
src/cpu/core_16/main.h Normal file

File diff suppressed because it is too large Load diff

469
src/cpu/core_16/prefix_66.h Normal file
View file

@ -0,0 +1,469 @@
/*
* 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.
*/
restart_66:
switch(Fetchb()) {
case 0x01: /* ADD Ed,Gd */
RMEdGd(ADDD);break;
case 0x03: /* ADD Gd,Ed */
RMGdEd(ADDD);break;
case 0x05: /* ADD EAX,Id */
EAXId(ADDD);break;
case 0x09: /* OR Ew,Gw */
RMEdGd(ORD);break;
case 0x0b: /* OR Gd,Ed */
RMGdEd(ORD);break;
case 0x0d: /* OR EAX,Id */
EAXId(ORD);break;
case 0x0f: /* 2 Byte opcodes */
#include "prefix_66_of.h"
break;
case 0x11: /* ADC Ed,Gd */
RMEdGd(ADCD);break;
case 0x13: /* ADC Gd,Ed */
RMGdEd(ADCD);break;
case 0x15: /* ADC EAX,Id */
EAXId(ADCD);break;
case 0x19: /* SBB Ed,Gd */
RMEdGd(SBBD);break;
case 0x1b: /* SBB Gd,Ed */
RMGdEd(SBBD);break;
case 0x1d: /* SBB EAX,Id */
EAXId(SBBD);break;
case 0x21: /* AND Ed,Gd */
RMEdGd(ANDD);break;
case 0x23: /* AND Gd,Ed */
RMGdEd(ANDD);break;
case 0x25: /* AND EAX,Id */
EAXId(ANDD);break;
case 0x29: /* SUB Ed,Gd */
RMEdGd(SUBD);break;
case 0x2b: /* SUB Gd,Ed */
RMGdEd(SUBD);break;
case 0x2d: /* SUB EAX,Id */
EAXId(SUBD);break;
case 0x31: /* XOR Ed,Gd */
RMEdGd(XORD);break;
case 0x33: /* XOR Gd,Ed */
RMGdEd(XORD);break;
case 0x35: /* XOR EAX,Id */
EAXId(XORD);break;
case 0x39: /* CMP Ed,Gd */
RMEdGd(CMPD);break;
case 0x3b: /* CMP Gd,Ed */
RMGdEd(CMPD);break;
case 0x3d: /* CMP EAX,Id */
EAXId(CMPD);break;
case 0x26: /* SEG ES: */
SegPrefix_66(es);break;
case 0x2e: /* SEG CS: */
SegPrefix_66(cs);break;
case 0x36: /* SEG SS: */
SegPrefix_66(ss);break;
case 0x3e: /* SEG DS: */
SegPrefix_66(ds);break;
case 0x40: /* INC EAX */
INCD(reg_eax,LoadRd,SaveRd);break;
case 0x41: /* INC ECX */
INCD(reg_ecx,LoadRd,SaveRd);break;
case 0x42: /* INC EDX */
INCD(reg_edx,LoadRd,SaveRd);break;
case 0x43: /* INC EBX */
INCD(reg_ebx,LoadRd,SaveRd);break;
case 0x44: /* INC ESP */
INCD(reg_esp,LoadRd,SaveRd);break;
case 0x45: /* INC EBP */
INCD(reg_ebp,LoadRd,SaveRd);break;
case 0x46: /* INC ESI */
INCD(reg_esi,LoadRd,SaveRd);break;
case 0x47: /* INC EDI */
INCD(reg_edi,LoadRd,SaveRd);break;
case 0x48: /* DEC EAX */
DECD(reg_eax,LoadRd,SaveRd);break;
case 0x49: /* DEC ECX */
DECD(reg_ecx,LoadRd,SaveRd);break;
case 0x4a: /* DEC EDX */
DECD(reg_edx,LoadRd,SaveRd);break;
case 0x4b: /* DEC EBX */
DECD(reg_ebx,LoadRd,SaveRd);break;
case 0x4c: /* DEC ESP */
DECD(reg_esp,LoadRd,SaveRd);break;
case 0x4d: /* DEC EBP */
DECD(reg_ebp,LoadRd,SaveRd);break;
case 0x4e: /* DEC ESI */
DECD(reg_esi,LoadRd,SaveRd);break;
case 0x4f: /* DEC EDI */
DECD(reg_edi,LoadRd,SaveRd);break;
case 0x50: /* PUSH EAX */
Push_32(reg_eax);break;
case 0x51: /* PUSH ECX */
Push_32(reg_ecx);break;
case 0x52: /* PUSH EDX */
Push_32(reg_edx);break;
case 0x53: /* PUSH EBX */
Push_32(reg_ebx);break;
case 0x54: /* PUSH ESP */
Push_32(reg_esp);break;
case 0x55: /* PUSH EBP */
Push_32(reg_ebp);break;
case 0x56: /* PUSH ESI */
Push_32(reg_esi);break;
case 0x57: /* PUSH EDI */
Push_32(reg_edi);break;
case 0x58: /* POP EAX */
reg_eax=Pop_32();break;
case 0x59: /* POP ECX */
reg_ecx=Pop_32();break;
case 0x5a: /* POP EDX */
reg_edx=Pop_32();break;
case 0x5b: /* POP EBX */
reg_ebx=Pop_32();break;
case 0x5c: /* POP ESP */
reg_esp=Pop_32();break;
case 0x5d: /* POP EBP */
reg_ebp=Pop_32();break;
case 0x5e: /* POP ESI */
reg_esi=Pop_32();break;
case 0x5f: /* POP EDI */
reg_edi=Pop_32();break;
case 0x60: /* PUSHAD */
Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx);
Push_32(reg_esp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi);
break;
case 0x61: /* POPAD */
reg_edi=Pop_32();reg_edi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP
reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
break;
case 0x68: /* PUSH Id */
Push_32(Fetchd());break;
case 0x69: /* IMUL Gd,Ed,Id */
{
GetRMrd;
Bit64s res;
if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*eards) * (Bit64s)Fetchds();}
else {GetEAa;res=(Bit64s)LoadMds(eaa) * (Bit64s)Fetchds();}
*rmrd=(Bit32s)(res);
flags.type=t_MUL;
if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;}
else {flags.cf=true;flags.of=true;}
break;
};
case 0x6a: /* PUSH Ib */
Push_32(Fetchbs());break;
case 0x81: /* Grpl Ed,Id */
{
GetRM;
if (rm>= 0xc0) {
GetEArd;Bit32u id=Fetchd();
switch (rm & 0x38) {
case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break;
case 0x08: ORD(*eard,id,LoadRd,SaveRd);break;
case 0x10:ADCD(*eard,id,LoadRd,SaveRd);break;
case 0x18:SBBD(*eard,id,LoadRd,SaveRd);break;
case 0x20:ANDD(*eard,id,LoadRd,SaveRd);break;
case 0x28:SUBD(*eard,id,LoadRd,SaveRd);break;
case 0x30:XORD(*eard,id,LoadRd,SaveRd);break;
case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break;
}
} else {
GetEAa;Bit32u id=Fetchb();
switch (rm & 0x38) {
case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break;
case 0x08: ORD(eaa,id,LoadMd,SaveMd);break;
case 0x10:ADCD(eaa,id,LoadMd,SaveMd);break;
case 0x18:SBBD(eaa,id,LoadMd,SaveMd);break;
case 0x20:ANDD(eaa,id,LoadMd,SaveMd);break;
case 0x28:SUBD(eaa,id,LoadMd,SaveMd);break;
case 0x30:XORD(eaa,id,LoadMd,SaveMd);break;
case 0x38:CMPD(eaa,id,LoadMd,SaveMd);break;
}
}
}
break;
case 0x83: /* Grpl Ed,Ix */
{
GetRM;
if (rm>= 0xc0) {
GetEArd;Bit32u id=(Bit32s)Fetchbs();
switch (rm & 0x38) {
case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break;
case 0x08: ORD(*eard,id,LoadRd,SaveRd);break;
case 0x10:ADCD(*eard,id,LoadRd,SaveRd);break;
case 0x18:SBBD(*eard,id,LoadRd,SaveRd);break;
case 0x20:ANDD(*eard,id,LoadRd,SaveRd);break;
case 0x28:SUBD(*eard,id,LoadRd,SaveRd);break;
case 0x30:XORD(*eard,id,LoadRd,SaveRd);break;
case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break;
}
} else {
GetEAa;Bit32u id=(Bit32s)Fetchbs();
switch (rm & 0x38) {
case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break;
case 0x08: ORD(eaa,id,LoadMd,SaveMd);break;
case 0x10:ADCD(eaa,id,LoadMd,SaveMd);break;
case 0x18:SBBD(eaa,id,LoadMd,SaveMd);break;
case 0x20:ANDD(eaa,id,LoadMd,SaveMd);break;
case 0x28:SUBD(eaa,id,LoadMd,SaveMd);break;
case 0x30:XORD(eaa,id,LoadMd,SaveMd);break;
case 0x38:CMPD(eaa,id,LoadMd,SaveMd);break;
}
}
}
break;
case 0x8f: /* POP Ed */
{
GetRM;
if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();}
else {GetEAa;SaveMd(eaa,Pop_32());}
break;
}
case 0x89: /* MOV Ed,Gd */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArd;*eard=*rmrd;}
else {GetEAa;SaveMd(eaa,*rmrd);}
break;
}
case 0x99: /* CDQ */
if (reg_eax & 0x80000000) reg_edx=0xffffffff;
else reg_edx=0;
break;
case 0x8b: /* MOV Gd,Ed */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;}
else {GetEAa;*rmrd=LoadMd(eaa);}
break;
}
case 0x8c:
LOG_WARN("CPU:66:8c looped back");
break;
case 0x9c: /* PUSHFD */
{
Bit32u pflags=
(get_CF() << 0) | (get_PF() << 2) | (get_AF() << 4) |
(get_ZF() << 6) | (get_SF() << 7) | (flags.tf << 8) |
(flags.intf << 9) |(flags.df << 10) | (get_OF() << 11) |
(flags.io << 12) | (flags.nt <<14);
Push_32(pflags);
break;
}
case 0x9d: /* POPFD */
{
Save_Flagsw((Bit16u)(Pop_32()&0xffff));
break;
}
case 0xa1: /* MOV EAX,Ow */
if (segprefix_on) {
reg_eax=LoadMd(segprefix_base+Fetchw());
SegPrefixReset;
} else {
reg_eax=LoadMd(SegBase(ds)+Fetchw());
}
break;
case 0xa3: /* MOV Ow,EAX */
if (segprefix_on) {
SaveMd((segprefix_base+Fetchw()),reg_eax);
SegPrefixReset;
} else {
SaveMd((SegBase(ds)+Fetchw()),reg_eax);
}
break;
case 0xa5: /* MOVSD */
{
stringSI;stringDI;SaveMd(to,LoadMd(from));
if (flags.df) { reg_si-=4;reg_di-=4; }
else { reg_si+=4;reg_di+=4;}
}
break;
case 0xab: /* STOSD */
{
stringDI;
SaveMd(to,reg_eax);
if (flags.df) { reg_di-=4; }
else {reg_di+=4;}
break;
}
case 0xad: /* LODSD */
{
stringSI;
reg_eax=LoadMd(from);
if (flags.df) { reg_si-=4;}
else {reg_si+=4;}
break;
}
case 0xaf: /* SCASD */
{
stringDI;
CMPD(reg_eax,LoadMd(to),LoadRd,0);
if (flags.df) { reg_di-=4; }
else {reg_di+=4;}
break;
}
case 0xb8: /* MOV EAX,Id */
reg_eax=Fetchd();break;
case 0xb9: /* MOV ECX,Id */
reg_ecx=Fetchd();break;
case 0xba: /* MOV EDX,Iw */
reg_edx=Fetchd();break;
case 0xbb: /* MOV EBX,Id */
reg_ebx=Fetchd();break;
case 0xbc: /* MOV ESP,Id */
reg_esp=Fetchd();break;
case 0xbd: /* MOV EBP.Id */
reg_ebp=Fetchd();break;
case 0xbe: /* MOV ESI,Id */
reg_esi=Fetchd();break;
case 0xbf: /* MOV EDI,Id */
reg_edi=Fetchd();break;
case 0xc1: /* GRP2 Ed,Ib */
GRP2D(Fetchb());break;
case 0xc7: /* MOV Ed,Id */
{
GetRM;
if (rm>0xc0) {GetEArd;*eard=Fetchd();}
else {GetEAa;SaveMd(eaa,Fetchd());}
break;
}
case 0xd1: /* GRP2 Ed,1 */
GRP2D(1);break;
case 0xd3: /* GRP2 Ed,CL */
GRP2D(reg_cl);break;
case 0xf7: /* GRP3 Ed(,Id) */
{
union { Bit64u u;Bit64s s;} temp;
union {Bit64u u;Bit64s s;} quotient;
GetRM;
switch (rm & 0x38) {
case 0x00: /* TEST Ed,Id */
case 0x08: /* TEST Ed,Id Undocumented*/
{
if (rm >= 0xc0 ) {GetEArd;TESTD(*eard,Fetchd(),LoadRd,SaveRd);}
else {GetEAa;TESTD(eaa,Fetchd(),LoadMd,SaveMd);}
break;
}
case 0x10: /* NOT Ed */
{
if (rm >= 0xc0 ) {GetEArd;*eard=~*eard;}
else {GetEAa;SaveMd(eaa,~LoadMd(eaa));}
break;
}
case 0x18: /* NEG Ed */
{
flags.type=t_NEGd;
if (rm >= 0xc0 ) {
GetEArd;flags.var1.d=*eard;flags.result.d=0-flags.var1.d;
*eard=flags.result.d;
} else {
GetEAa;flags.var1.d=LoadMd(eaa);flags.result.d=0-flags.var1.d;
SaveMd(eaa,flags.result.d);
}
break;
}
case 0x20: /* MUL EAX,Ed */
{
flags.type=t_MUL;
if (rm >= 0xc0 ) {GetEArd;temp.u=(Bit64s)reg_eax * (Bit64u)(*eard);}
else {GetEAa;temp.u=(Bit64u)reg_eax * (Bit64u)LoadMd(eaa);}
reg_eax=(Bit32u)(temp.u & 0xffffffff);reg_eax=(Bit32u)(temp.u >> 32);
flags.cf=flags.of=(reg_edx !=0);
break;
}
case 0x28: /* IMUL EAX,Ed */
{
flags.type=t_MUL;
if (rm >= 0xc0 ) {GetEArd;temp.s=(Bit64s)reg_eax * (Bit64s)(*eards);}
else {GetEAa;temp.s=(Bit64s)reg_eax * (Bit64s)LoadMds(eaa);}
reg_eax=Bit32u(temp.u & 0xffffffff);reg_edx=(Bit32u)(temp.u >> 32);
if ( (reg_edx==0xffffffff) && (reg_eax & 0x80000000) ) {
flags.cf=flags.of=false;
} else if ( (reg_edx==0x00000000) && (reg_eax<0x80000000) ) {
flags.cf=flags.of=false;
} else {
flags.cf=flags.of=true;
}
break;
}
case 0x30: /* DIV Ed */
{
// flags.type=t_DIV;
Bit32u val;
if (rm >= 0xc0 ) {GetEArd;val=*eard;}
else {GetEAa;val=LoadMd(eaa);}
if (val==0) {Interrupt(0);break;}
temp.u=(((Bit64u)reg_edx)<<32)|reg_eax;
quotient.u=temp.u/val;
reg_edx=(Bit32u)(temp.u % val);
reg_eax=(Bit32u)(quotient.u & 0xffffffff);
if (quotient.u>0xffffffff)
Interrupt(0);
break;
}
case 0x38: /* IDIV Ed */
{
// flags.type=t_DIV;
Bit32s val;
if (rm >= 0xc0 ) {GetEArd;val=*eards;}
else {GetEAa;val=LoadMds(eaa);}
if (val==0) {Interrupt(0);break;}
temp.s=(((Bit64u)reg_edx)<<32)|reg_eax;
quotient.s=(temp.s/val);
reg_edx=(Bit32s)(temp.s % val);
reg_eax=(Bit32s)(quotient.s);
if (quotient.s!=(Bit32s)reg_eax)
Interrupt(0);
break;
}
}
break;
}
case 0xff: /* Group 5 */
{
GetRM;
switch (rm & 0x38) {
case 0x00: /* INC Ew */
flags.cf=get_CF();flags.type=t_INCd;
if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard+=1;}
else {GetEAa;flags.result.d=LoadMd(eaa)+1;SaveMd(eaa,flags.result.d);}
break;
case 0x08: /* DEC Ew */
flags.cf=get_CF();flags.type=t_DECd;
if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard-=1;}
else {GetEAa;flags.result.d=LoadMd(eaa)-1;SaveMd(eaa,flags.result.d);}
break;
case 0x30: /* Push Ed */
if (rm >= 0xc0 ) {GetEArd;Push_32(*eard);}
else {GetEAa;Push_32(LoadMd(eaa));}
break;
default:
E_Exit("CPU:66:GRP5:Illegal call %2X",rm & 0x38);
break;
}
break;
}
default:
NOTDONE66;
}

View file

@ -0,0 +1,124 @@
/*
* 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.
*/
switch (Fetchb()) {
case 0xa4: /* SHLD Ed,Gd,Ib */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArd;DSHLD(*eard,*rmrd,Fetchb(),LoadRd,SaveRd);}
else {GetEAa;DSHLD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);}
break;
}
case 0xac: /* SHRD Ed,Gd,Ib */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArd;DSHRD(*eard,*rmrd,Fetchb(),LoadRd,SaveRd);}
else {GetEAa;DSHRD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);}
break;
}
case 0xb6: /* MOVZX Gd,Eb */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;}
else {GetEAa;*rmrd=LoadMb(eaa);}
break;
}
case 0xaf: /* IMUL Gd,Ed */
{
GetRMrd;
Bit64s res;
if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*rmrd) * (Bit64s)(*eards);}
else {GetEAa;res=(Bit64s)(*rmrd) * (Bit64s)LoadMds(eaa);}
*rmrd=(Bit32s)(res);
flags.type=t_MUL;
if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;}
else {flags.cf=true;flags.of=true;}
break;
};
case 0xb7: /* MOVXZ Gd,Ew */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArw;*rmrd=*earw;}
else {GetEAa;*rmrd=LoadMw(eaa);}
break;
}
case 0xba: /* GRP8 Ed,Ib */
{
GetRM;
if (rm >= 0xc0 ) {
GetEArd;
Bit32u mask=1 << (Fetchb() & 31);
flags.cf=(*eard & mask)>0;
switch (rm & 0x38) {
case 0x20: /* BT */
break;
case 0x28: /* BTS */
*eard|=mask;
break;
case 0x30: /* BTR */
*eard&=~mask;
break;
case 0x38: /* BTC */
if (flags.cf) *eard&=~mask;
else *eard|=mask;
break;
}
} else {
GetEAa;Bit32u old=LoadMd(eaa);
Bit32u mask=1 << (Fetchb() & 31);
flags.cf=(old & mask)>0;
switch (rm & 0x38) {
case 0x20: /* BT */
break;
case 0x28: /* BTS */
SaveMd(eaa,old|mask);
break;
case 0x30: /* BTR */
SaveMd(eaa,old & ~mask);
break;
case 0x38: /* BTC */
if (flags.cf) old&=~mask;
else old|=mask;
SaveMd(eaa,old);
break;
}
}
if (flags.type!=t_CF) flags.prev_type=flags.type;
flags.type=t_CF;
break;
}
case 0xbe: /* MOVSX Gd,Eb */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArb;*rmrd=*earbs;}
else {GetEAa;*rmrd=LoadMbs(eaa);}
break;
}
case 0xbf: /* MOVSX Gd,Ew */
{
GetRMrd;
if (rm >= 0xc0 ) {GetEArw;*rmrd=*earws;}
else {GetEAa;*rmrd=LoadMws(eaa);}
break;
}
default:
SUBIP(1);
E_Exit("CPU:Opcode 66:0F:%2X Unhandled",Fetchb());
}

188
src/cpu/core_16/prefix_of.h Normal file
View file

@ -0,0 +1,188 @@
/*
* 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.
*/
switch(Fetchb()) {
case 0x01: /* GRP 7 */
{
GetRM;
switch (rm & 0x38) {
case 0x20: /* SMSW */
/* Let's seriously fake this call */
if (rm>0xc0) {GetEArw;*earw=0;}
else {GetEAa;SaveMw(eaa,0);}
break;
default:
E_Exit("CPU:GRP7:Illegal call %2X",rm);
}
}
break;
case 0x80: /* JO */
JumpSIw(get_OF());break;
case 0x81: /* JNO */
JumpSIw(!get_OF());break;
case 0x82: /* JB */
JumpSIw(get_CF());break;
case 0x83: /* JNB */
JumpSIw(!get_CF());break;
case 0x84: /* JZ */
JumpSIw(get_ZF());break;
case 0x85: /* JNZ */
JumpSIw(!get_ZF()); break;
case 0x86: /* JBE */
JumpSIw(get_CF() || get_ZF());break;
case 0x87: /* JNBE */
JumpSIw(!get_CF() && !get_ZF());break;
case 0x88: /* JS */
JumpSIw(get_SF());break;
case 0x89: /* JNS */
JumpSIw(!get_SF());break;
case 0x8a: /* JP */
JumpSIw(get_PF());break;
case 0x8b: /* JNP */
JumpSIw(!get_PF());break;
case 0x8c: /* JL */
JumpSIw(get_SF() != get_OF());break;
case 0x8d: /* JNL */
JumpSIw(get_SF() == get_OF());break;
case 0x8e: /* JLE */
JumpSIw(get_ZF() || (get_SF() != get_OF()));break;
case 0x8f: /* JNLE */
JumpSIw((get_SF() == get_OF()) && !get_ZF());break;
case 0xa0: /* PUSH FS */
Push_16(Segs[fs].value);break;
case 0xa1: /* POP FS */
SetSegment_16(fs,Pop_16());break;
case 0xa4: /* SHLD Ew,Gw,Ib */
{
GetRMrw;
if (rm >= 0xc0 ) {GetEArw;DSHLW(*earw,*rmrw,Fetchb(),LoadRw,SaveRw);}
else {GetEAa;DSHLW(eaa,*rmrw,Fetchb(),LoadMw,SaveMw);}
break;
}
case 0xa5: /* SHLD Ew,Gw,CL */
{
GetRMrw;
if (rm >= 0xc0 ) {GetEArw;DSHLW(*earw,*rmrw,reg_cl,LoadRw,SaveRw);}
else {GetEAa;DSHLW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);}
break;
}
case 0xa8: /* PUSH GS */
Push_16(Segs[gs].value);break;
case 0xa9: /* POP GS */
SetSegment_16(gs,Pop_16());break;
case 0xac: /* SHRD Ew,Gw,Ib */
{
GetRMrw;
if (rm >= 0xc0 ) {GetEArw;DSHRW(*earw,*rmrw,Fetchb(),LoadRw,SaveRw);}
else {GetEAa;DSHRW(eaa,*rmrw,Fetchb(),LoadMw,SaveMw);}
break;
}
case 0xad: /* SHRD Ew,Gw,CL */
{
GetRMrw;
if (rm >= 0xc0 ) {GetEArw;DSHRW(*earw,*rmrw,reg_cl,LoadRw,SaveRw);}
else {GetEAa;DSHRW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);}
break;
}
case 0xaf: /* IMUL Gw,Ew */
{
GetRMrw;
Bit32s res;
if (rm >= 0xc0 ) {GetEArw;res=(Bit32s)(*rmrw) * (Bit32s)(*earws);}
else {GetEAa;res=(Bit32s)(*rmrw) *(Bit32s)LoadMws(eaa);}
*rmrw=res & 0xFFFF;
flags.type=t_MUL;
if ((res> -32768) && (res<32767)) {flags.cf=false;flags.of=false;}
else {flags.cf=true;flags.of=true;}
break;
}
case 0xb4: /* LFS */
{
GetRMrw;GetEAa;
*rmrw=LoadMw(eaa);SetSegment_16(fs,LoadMw(eaa+2));
break;
}
case 0xb5: /* LGS */
{
GetRMrw;GetEAa;
*rmrw=LoadMw(eaa);SetSegment_16(gs,LoadMw(eaa+2));
break;
}
case 0xb6: /* MOVZX Gw,Eb */
{
GetRMrw;
if (rm >= 0xc0 ) {GetEArb;*rmrw=*earb;}
else {GetEAa;*rmrw=LoadMb(eaa);}
break;
}
case 0xba: /* GRP8 Ew,Ib */
{
GetRM;
if (rm >= 0xc0 ) {
GetEArw;
Bit16u mask=1 << (Fetchb() & 15);
flags.cf=(*earw & mask)>0;
switch (rm & 0x38) {
case 0x20: /* BT */
break;
case 0x28: /* BTS */
*earw|=mask;
break;
case 0x30: /* BTR */
*earw&=~mask;
break;
case 0x38: /* BTC */
if (flags.cf) *earw&=~mask;
else *earw|=mask;
break;
}
} else {
GetEAa;Bit16u old=LoadMw(eaa);
Bit16u mask=1 << (Fetchb() & 15);
flags.cf=(old & mask)>0;
switch (rm & 0x38) {
case 0x20: /* BT */
break;
case 0x28: /* BTS */
SaveMw(eaa,old|mask);
break;
case 0x30: /* BTR */
SaveMw(eaa,old & ~mask);
break;
case 0x38: /* BTC */
if (flags.cf) old&=~mask;
else old|=mask;
SaveMw(eaa,old);
break;
}
}
if (flags.type!=t_CF) flags.prev_type=flags.type;
flags.type=t_CF;
break;
}
case 0xbe: /* MOVSX Gw,Eb */
{
GetRMrw;
if (rm >= 0xc0 ) {GetEArb;*rmrw=*earbs;}
else {GetEAa;*rmrw=LoadMbs(eaa);}
break;
}
default:
SUBIP(1);
E_Exit("CPU:Opcode 0F:%2X Unhandled",Fetchb());
}

20
src/cpu/core_16/start.h Normal file
View file

@ -0,0 +1,20 @@
/*
* 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.
*/
/* Setup the CS:IP and SS:SP Pointers */
LOADIP;

19
src/cpu/core_16/stop.h Normal file
View file

@ -0,0 +1,19 @@
/*
* 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.
*/
SAVEIP;

191
src/cpu/core_16/support.h Normal file
View file

@ -0,0 +1,191 @@
/*
* 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.
*/
EAPoint IPPoint;
#define SUBIP(a) IPPoint-=a
#define SETIP(a) IPPoint=SegBase(cs)+a
#define GETIP (Bit16u)(IPPoint-SegBase(cs))
#define SAVEIP reg_ip=GETIP
#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) {
// Bit16u oldip=(IPPoint-SegBase(cs));
// oldip+=add;
// IPPoint=SegBase(cs)+oldip;
IPPoint=SegBase(cs)+((Bit16u)(((Bit16u)(IPPoint-SegBase(cs)))+(Bit16u)add));
}
static INLINE void ADDIPFAST(Bit16s blah) {
IPPoint+=blah;
}
#define ERRORRETURN(a) { error_ret=a;goto errorreturn; }
static INLINE Bit8u Fetchb() {
Bit8u temp=LoadMb(IPPoint);
IPPoint+=1;
return temp;
}
static INLINE Bit16u Fetchw() {
Bit16u temp=LoadMw(IPPoint);
IPPoint+=2;
return temp;
}
static INLINE Bit32u Fetchd() {
Bit32u temp=LoadMd(IPPoint);
IPPoint+=4;
return temp;
}
static INLINE Bit8s Fetchbs() {
return Fetchb();
}
static INLINE Bit16s Fetchws() {
return Fetchw();
}
static INLINE Bit32s Fetchds() {
return Fetchd();
}
static INLINE void Push_16(Bit16u blah) {
reg_sp-=2;
SaveMw(SegBase(ss)+reg_sp,blah);
};
static INLINE void Push_32(Bit32u blah) {
reg_sp-=4;
SaveMd(SegBase(ss)+reg_sp,blah);
};
static INLINE Bit16u Pop_16() {
Bit16u temp=LoadMw(SegBase(ss)+reg_sp);
reg_sp+=2;
return temp;
};
static INLINE Bit32u Pop_32() {
Bit32u temp=LoadMd(SegBase(ss)+reg_sp);
reg_sp+=4;
return temp;
};
#define stringDI \
EAPoint to; \
to=SegBase(es)+reg_di
#define stringSI \
EAPoint from; \
if (segprefix_on) { \
from=(segprefix_base+reg_si); \
SegPrefixReset; \
} else { \
from=SegBase(ds)+reg_si; \
}
#include "helpers.h"
#include "table_ea.h"
#include "../modrm.h"
#include "instructions.h"
static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) {
bool again;
do {
again=false;
Bit8u repcode=Fetchb();
switch (repcode) {
case 0x26: /* ES Prefix */
again=true;
from=SegBase(es);
break;
case 0x2e: /* CS Prefix */
again=true;
from=SegBase(cs);
break;
case 0x36: /* SS Prefix */
again=true;
from=SegBase(ss);
break;
case 0x3e: /* DS Prefix */
again=true;
from=SegBase(ds);
break;
case 0xa5: /* REP MOVSD */
for (;reg_cx>0;reg_cx--) {
SaveMd(to+reg_di,LoadMd(from+reg_si));
reg_di+=direct*4;
reg_si+=direct*4;
}
break;
case 0xab: /* REP STOSW */
for (;reg_cx>0;reg_cx--) {
SaveMd(to+reg_di,reg_eax);
reg_di+=direct*4;
}
break;
default:
E_Exit("CPU:Opcode 66:Illegal REP prefix %2X",repcode);
}
} while (again);
}
//flags.io and nt shouldn't be compiled for 386
#define Save_Flagsw(FLAGW) \
{ \
flags.type=t_UNKNOWN; \
flags.cf =(FLAGW & 0x001)>0;flags.pf =(FLAGW & 0x004)>0; \
flags.af =(FLAGW & 0x010)>0;flags.zf =(FLAGW & 0x040)>0; \
flags.sf =(FLAGW & 0x080)>0;flags.tf =(FLAGW & 0x100)>0; \
flags.intf =(FLAGW & 0x200)>0; \
flags.df =(FLAGW & 0x400)>0;flags.of =(FLAGW & 0x800)>0; \
flags.io =(FLAGW >> 12) & 0x03; \
flags.nt =(FLAGW & 0x4000)>0; \
if (flags.intf && PIC_IRQCheck) { \
SAVEIP; \
PIC_runIRQs(); \
LOADIP; \
} \
if (flags.tf) E_Exit("CPU:Trap Flag not supported"); \
}
// if (flags.tf) { \
// cpudecoder=CPU_Real_16_Slow_Decode_Special; \
// return CBRET_NONE; \
// } \

283
src/cpu/core_16/table_ea.h Normal file
View file

@ -0,0 +1,283 @@
/*
* 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.
*/
/* Some variables for EA Loolkup */
typedef EAPoint (*GetEATable[256])(void);
static GetEATable * lookupEATable;
static EAPoint segprefix_base;
static bool segprefix_on=false;
#define SegPrefix(blah) \
segprefix_base=SegBase(blah); \
segprefix_on=true; \
lookupEATable=&GetEA_16_s; \
goto restart; \
#define SegPrefix_66(blah) \
segprefix_base=SegBase(blah); \
segprefix_on=true; \
lookupEATable=&GetEA_16_s; \
goto restart_66; \
#define SegPrefixReset \
segprefix_on=false;lookupEATable=&GetEA_16_n;
/* The MOD/RM Decoder for EA for this decoder's addressing modes */
static EAPoint EA_16_00_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); }
static EAPoint EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); }
static EAPoint EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); }
static EAPoint EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); }
static EAPoint EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); }
static EAPoint EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); }
static EAPoint EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());}
static EAPoint EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); }
static EAPoint EA_16_40_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
static EAPoint EA_16_41_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
static EAPoint EA_16_42_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
static EAPoint EA_16_43_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
static EAPoint EA_16_44_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchbs()); }
static EAPoint EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); }
static EAPoint EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); }
static EAPoint EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchbs()); }
static EAPoint EA_16_80_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
static EAPoint EA_16_81_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
static EAPoint EA_16_82_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
static EAPoint EA_16_83_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
static EAPoint EA_16_84_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchws()); }
static EAPoint EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); }
static EAPoint EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); }
static EAPoint EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); }
static GetEATable GetEA_16_n={
/* 00 */
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
/* 01 */
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
/* 10 */
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
/* 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
};
#define prefixed(val) EAPoint ret=segprefix_base+val;SegPrefixReset;return ret;
static EAPoint EA_16_00_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) }
static EAPoint EA_16_01_s(void) { prefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) }
static EAPoint EA_16_02_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_si)) }
static EAPoint EA_16_03_s(void) { prefixed((Bit16u)(reg_bp+(Bit16s)reg_di)) }
static EAPoint EA_16_04_s(void) { prefixed((Bit16u)(reg_si)) }
static EAPoint EA_16_05_s(void) { prefixed((Bit16u)(reg_di)) }
static EAPoint EA_16_06_s(void) { prefixed((Bit16u)(Fetchw())) }
static EAPoint EA_16_07_s(void) { prefixed((Bit16u)(reg_bx)) }
static EAPoint EA_16_40_s(void) { prefixed((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_42_s(void) { prefixed((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_44_s(void) { prefixed((Bit16u)(reg_si+Fetchbs())) }
static EAPoint EA_16_45_s(void) { prefixed((Bit16u)(reg_di+Fetchbs())) }
static EAPoint EA_16_46_s(void) { prefixed((Bit16u)(reg_bp+Fetchbs())) }
static EAPoint EA_16_47_s(void) { prefixed((Bit16u)(reg_bx+Fetchbs())) }
static EAPoint EA_16_80_s(void) { prefixed((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_82_s(void) { prefixed((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_84_s(void) { prefixed((Bit16u)(reg_si+Fetchws())) }
static EAPoint EA_16_85_s(void) { prefixed((Bit16u)(reg_di+Fetchws())) }
static EAPoint EA_16_86_s(void) { prefixed((Bit16u)(reg_bp+Fetchws())) }
static EAPoint EA_16_87_s(void) { prefixed((Bit16u)(reg_bx+Fetchws())) }
static GetEATable GetEA_16_s={
/* 00 */
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
/* 01 */
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
/* 10 */
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_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
};
INLINE EAPoint Sib(Bitu mode) {
Bit8u sib=Fetchb();
EAPoint base;
switch (sib&7) {
case 0: /* EAX Base */
base=SegBase(ds)+reg_eax;break;
case 1: /* ECX Base */
base=SegBase(ds)+reg_ecx;break;
case 2: /* EDX Base */
base=SegBase(ds)+reg_edx;break;
case 3: /* EBX Base */
base=SegBase(ds)+reg_ebx;break;
case 4: /* ESP Base */
base=SegBase(ds)+reg_esp;break;
case 5: /* #1 Base */
if (!mode) {
base=SegBase(ds)+Fetchd();break;
} else {
base=SegBase(ss)+reg_ebp;break;
}
case 6: /* ESI Base */
base=SegBase(ds)+reg_esi;break;
case 7: /* EDI Base */
base=SegBase(ds)+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;
};
return base;
};
static EAPoint EA_32_00_n(void) { return SegBase(ds)+reg_eax; }
static EAPoint EA_32_01_n(void) { return SegBase(ds)+reg_ecx; }
static EAPoint EA_32_02_n(void) { return SegBase(ds)+reg_edx; }
static EAPoint EA_32_03_n(void) { return SegBase(ds)+reg_ebx; }
static EAPoint EA_32_04_n(void) { return Sib(0);}
static EAPoint EA_32_05_n(void) { return SegBase(ds)+Fetchd(); }
static EAPoint EA_32_06_n(void) { return SegBase(ss)+reg_esi; }
static EAPoint EA_32_07_n(void) { return SegBase(ds)+reg_edi; }
static EAPoint EA_32_40_n(void) { return SegBase(ds)+reg_eax+Fetchbs(); }
static EAPoint EA_32_41_n(void) { return SegBase(ds)+reg_ecx+Fetchbs(); }
static EAPoint EA_32_42_n(void) { return SegBase(ds)+reg_edx+Fetchbs(); }
static EAPoint EA_32_43_n(void) { return SegBase(ds)+reg_ebx+Fetchbs(); }
static EAPoint EA_32_44_n(void) { return Sib(1)+Fetchbs();}
static EAPoint EA_32_45_n(void) { return SegBase(ss)+reg_ebp+Fetchbs(); }
static EAPoint EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); }
static EAPoint EA_32_47_n(void) { return SegBase(ds)+reg_edi+Fetchbs(); }
static EAPoint EA_32_80_n(void) { return SegBase(ds)+reg_eax+Fetchds(); }
static EAPoint EA_32_81_n(void) { return SegBase(ds)+reg_ecx+Fetchds(); }
static EAPoint EA_32_82_n(void) { return SegBase(ds)+reg_edx+Fetchds(); }
static EAPoint EA_32_83_n(void) { return SegBase(ds)+reg_ebx+Fetchds(); }
static EAPoint EA_32_84_n(void) { return Sib(2)+Fetchds();}
static EAPoint EA_32_85_n(void) { return SegBase(ss)+reg_ebp+Fetchds(); }
static EAPoint EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); }
static EAPoint EA_32_87_n(void) { return SegBase(ds)+reg_edi+Fetchds(); }
static GetEATable GetEA_32_n={
/* 00 */
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
/* 01 */
EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
/* 10 */
EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
/* 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
};

185
src/cpu/cpu.cpp Normal file
View file

@ -0,0 +1,185 @@
/*
* 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 "cpu.h"
#include "memory.h"
#include "debug.h"
#include "keyboard.h"
//Regs regs;
Flag_Info flags;
CPU_Regs cpu_regs;
Segment Segs[6];
Bit32u cpu_cycles;
CPU_Decoder * cpudecoder;
static void CPU_CycleIncrease(void) {
Bit32u old_cycles=cpu_cycles;
cpu_cycles=(Bit32u)(cpu_cycles*1.2);
if (cpu_cycles==old_cycles) cpu_cycles++;
LOG_MSG("CPU:%d cycles",cpu_cycles);
}
static void CPU_CycleDecrease(void) {
cpu_cycles=(Bit32u)(cpu_cycles/1.2);
if (!cpu_cycles) cpu_cycles=1;
LOG_MSG("CPU:%d cycles",cpu_cycles);
}
Bit8u lastint;
void Interrupt(Bit8u num) {
lastint=num;
//DEBUG THINGIE to check fucked ints
switch (num) {
case 0x00:
LOG_WARN("Divide Error");
break;
case 0x06:
break;
case 0x07:
LOG_WARN("Co Processor Exception");
break;
case 0x08:
case 0x09:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x16:
case 0x15:
case 0x1A:
case 0x17:
case 0x1C:
case 0x21:
case 0x2a:
case 0x2f:
case 0x33:
case 0x67:
case 0x74:
break;
case 0xcd:
E_Exit("Call to interrupt 0xCD this is BAD");
case 0x03:
#ifdef C_DEBUG
if (DEBUG_BreakPoint()) return;
#endif
break;
case 0x05:
LOG_MSG("CPU:Out Of Bounds interrupt");
break;
default:
// LOG_WARN("Call to unsupported INT %02X call %02X",num,reg_ah);
break;
};
/* Check for 16-bit or 32-bit and then setup everything for the interrupt to start */
Bit16u pflags;
pflags=
(get_CF() << 0) |
(get_PF() << 2) |
(get_AF() << 4) |
(get_ZF() << 6) |
(get_SF() << 7) |
(flags.tf << 8) |
(flags.intf << 9) |
(flags.df << 10) |
(get_OF() << 11) |
(flags.io << 12) |
(flags.nt <<14);
flags.intf=false;
flags.tf=false;
/* Save everything on a 16-bit stack */
reg_sp-=2;
mem_writew(Segs[ss].phys+reg_sp,pflags);
reg_sp-=2;
mem_writew(Segs[ss].phys+reg_sp,Segs[cs].value);
reg_sp-=2;
mem_writew(Segs[ss].phys+reg_sp,reg_ip);
/* Get the new CS:IP from vector table */
Bit16u newip=mem_readw(num << 2);
Bit16u newcs=mem_readw((num <<2)+2);
SetSegment_16(cs,newcs);
reg_ip=newip;
}
void CPU_Real_16_Slow_Start(void);
void SetCPU16bit()
{
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) {
reg_eax=0;
reg_ebx=0;
reg_ecx=0;
reg_edx=0;
reg_edi=0;
reg_esi=0;
reg_ebp=0;
reg_esp=0;
SetSegment_16(cs,0);
SetSegment_16(ds,0);
SetSegment_16(es,0);
SetSegment_16(fs,0);
SetSegment_16(gs,0);
SetSegment_16(ss,0);
reg_eip=0;
flags.type=t_UNKNOWN;
flags.af=0;
flags.cf=0;
flags.cf=0;
flags.sf=0;
flags.zf=0;
flags.intf=true;
flags.nt=0;
flags.io=0;
SetCPU16bit();
cpu_cycles=2000;
KEYBOARD_AddEvent(KBD_f11,CTRL_PRESSED,CPU_CycleDecrease);
KEYBOARD_AddEvent(KBD_f12,CTRL_PRESSED,CPU_CycleIncrease);
reg_al=0;
reg_ah=0;
}

582
src/cpu/flags.cpp Normal file
View file

@ -0,0 +1,582 @@
/*
* 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.
*/
/*
Lazy flag system was designed after the same kind of system used in Bochs.
Probably still some bugs left in here.
*/
#include "dosbox.h"
#include "cpu.h"
#include "pic.h"
/* CF Carry Flag -- Set on high-order bit carry or borrow; cleared
otherwise.
*/
bool get_CF(void) {
switch (flags.type) {
case t_UNKNOWN:
case t_CF:
case t_INCb:
case t_INCw:
case t_INCd:
case t_DECb:
case t_DECw:
case t_DECd:
case t_MUL:
return flags.cf;
break;
case t_ADDb:
return (flags.result.b<flags.var1.b);
case t_ADDw:
return (flags.result.w<flags.var1.w);
case t_ADDd:
return (flags.result.d<flags.var1.d);
case t_ADCb:
return (flags.result.b < flags.var1.b) || (flags.oldcf && (flags.result.b == flags.var1.b));
case t_ADCw:
return (flags.result.w < flags.var1.w) || (flags.oldcf && (flags.result.w == flags.var1.w));
case t_ADCd:
return (flags.result.d < flags.var1.d) || (flags.oldcf && (flags.result.d == flags.var1.d));
case t_SBBb:
return (flags.var1.b < flags.result.b) || (flags.oldcf && (flags.var2.b==0xff));
case t_SBBw:
return (flags.var1.w < flags.result.w) || (flags.oldcf && (flags.var2.w==0xffff));
case t_SBBd:
return (flags.var1.d < flags.result.d) || (flags.oldcf && (flags.var2.d==0xffffffff));
case t_SUBb:
case t_CMPb:
return (flags.var1.b<flags.var2.b);
case t_SUBw:
case t_CMPw:
return (flags.var1.w<flags.var2.w);
case t_SUBd:
case t_CMPd:
return (flags.var1.d<flags.var2.d);
case t_SHLb:
if (flags.var2.b>=8) return false;
else return (flags.var1.b >> (8-flags.var2.b)) & 1;
case t_SHLw:
if (flags.var2.b>=16) return false;
else return (flags.var1.w >> (16-flags.var2.b)) & 1;
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 */
return (flags.var1.d >> (32 - flags.var2.b)) & 0x01;
case t_DSHLd:
return (flags.var1.d >> (32 - flags.var2.b)) & 0x01;
case t_SHRb:
return (flags.var1.b >> (flags.var2.b - 1)) & 0x01;
case t_SHRw:
return (flags.var1.w >> (flags.var2.b - 1)) & 0x01;
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 */
return (flags.var1.d >> (flags.var2.b - 1)) & 0x01;
case t_DSHRd:
return (flags.var1.d >> (flags.var2.b - 1)) & 0x01;
case t_NEGb:
return (flags.var1.b!=0);
case t_NEGw:
return (flags.var1.w!=0);
case t_NEGd:
return (flags.var1.d!=0);
case t_ROLb:
return (flags.result.b & 1)>0;
case t_ROLw:
return (flags.result.w & 1)>0;
case t_ROLd:
return (flags.result.d & 1)>0;
case t_RORb:
return (flags.result.b & 0x80)>0;
case t_RORw:
return (flags.result.w & 0x8000)>0;
case t_RORd:
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_ORw:
case t_ORd:
case t_ANDb:
case t_ANDw:
case t_ANDd:
case t_XORb:
case t_XORw:
case t_XORd:
case t_TESTb:
case t_TESTw:
case t_TESTd:
case t_DIV:
return false;
default:
E_Exit("get_CF Unknown %d",flags.type);
}
return 0;
}
/* AF Adjust flag -- Set on carry from or borrow to the low order
four bits of AL; cleared otherwise. Used for decimal
arithmetic.
*/
bool get_AF(void) {
Bitu type=flags.type;
again:
switch (type) {
case t_UNKNOWN:
case t_ROLb:
case t_RORb:
case t_RCLb:
case t_RCRb:
case t_ROLw:
case t_RORw:
case t_RCLw:
case t_RCRw:
case t_ROLd:
case t_RORd:
case t_RCLd:
case t_RCRd:
return flags.af;
case t_CF:
type=flags.prev_type;
goto again;
case t_ADDb:
case t_ADCb:
case t_SBBb:
case t_SUBb:
case t_CMPb:
return (((flags.var1.b ^ flags.var2.b) ^ flags.result.b) & 0x10)>0;
case t_ADDw:
case t_ADCw:
case t_SBBw:
case t_SUBw:
case t_CMPw:
return (((flags.var1.w ^ flags.var2.w) ^ flags.result.w) & 0x10)>0;
case t_ADCd:
case t_ADDd:
case t_SBBd:
case t_SUBd:
case t_CMPd:
return (((flags.var1.d ^ flags.var2.d) ^ flags.result.d) & 0x10)>0;
case t_INCb:
return (flags.result.b & 0x0f) == 0;
case t_INCw:
return (flags.result.w & 0x0f) == 0;
case t_INCd:
return (flags.result.d & 0x0f) == 0;
case t_DECb:
return (flags.result.b & 0x0f) == 0x0f;
case t_DECw:
return (flags.result.w & 0x0f) == 0x0f;
case t_DECd:
return (flags.result.d & 0x0f) == 0x0f;
case t_NEGb:
return (flags.var1.b & 0x0f) > 0;
case t_NEGw:
return (flags.var1.w & 0x0f) > 0;
case t_NEGd:
return (flags.var1.d & 0x0f) > 0;
case t_ORb:
case t_ORw:
case t_ORd:
case t_ANDb:
case t_ANDw:
case t_ANDd:
case t_XORb:
case t_XORw:
case t_XORd:
case t_TESTb:
case t_TESTw:
case t_TESTd:
case t_SHLb:
case t_SHLw:
case t_SHLd:
case t_SHRb:
case t_SHRw:
case t_SHRd:
case t_SARb:
case t_SARw:
case t_DSHLw:
case t_DSHLd:
case t_DSHRw:
case t_DSHRd:
case t_DIV:
case t_MUL:
return false; /* undefined */
default:
E_Exit("get_AF Unknown %d",flags.type);
}
return 0;
}
/* ZF Zero Flag -- Set if result is zero; cleared otherwise.
*/
bool get_ZF(void) {
Bitu type=flags.type;
again:
switch (type) {
case t_UNKNOWN:
case t_ROLb:
case t_RORb:
case t_RCLb:
case t_RCRb:
case t_ROLw:
case t_RORw:
case t_RCLw:
case t_RCRw:
case t_ROLd:
case t_RORd:
case t_RCLd:
case t_RCRd:
return flags.zf;
case t_CF:
type=flags.prev_type;
goto again;
case t_ADDb:
case t_ORb:
case t_ADCb:
case t_SBBb:
case t_ANDb:
case t_XORb:
case t_SUBb:
case t_CMPb:
case t_INCb:
case t_DECb:
case t_TESTb:
case t_SHLb:
case t_SHRb:
case t_SARb:
case t_NEGb:
return (flags.result.b==0);
case t_ADDw:
case t_ORw:
case t_ADCw:
case t_SBBw:
case t_ANDw:
case t_XORw:
case t_SUBw:
case t_CMPw:
case t_INCw:
case t_DECw:
case t_TESTw:
case t_SHLw:
case t_SHRw:
case t_SARw:
case t_DSHLw:
case t_DSHRw:
case t_NEGw:
return (flags.result.w==0);
case t_ADDd:
case t_ORd:
case t_ADCd:
case t_SBBd:
case t_ANDd:
case t_XORd:
case t_SUBd:
case t_CMPd:
case t_INCd:
case t_DECd:
case t_TESTd:
case t_SHLd:
case t_SHRd:
case t_SARd:
case t_DSHLd:
case t_DSHRd:
case t_NEGd:
return (flags.result.d==0);
case t_DIV:
case t_MUL:
return false;
default:
E_Exit("get_ZF Unknown %d",flags.type);
}
return false;
}
/* SF Sign Flag -- Set equal to high-order bit of result (0 is
positive, 1 if negative).
*/
bool get_SF(void) {
Bitu type=flags.type;
again:
switch (type) {
case t_UNKNOWN:
case t_ROLb:
case t_RORb:
case t_RCLb:
case t_RCRb:
case t_ROLw:
case t_RORw:
case t_RCLw:
case t_RCRw:
case t_ROLd:
case t_RORd:
case t_RCLd:
case t_RCRd:
return flags.sf;
case t_CF:
type=flags.prev_type;
goto again;
case t_ADDb:
case t_ORb:
case t_ADCb:
case t_SBBb:
case t_ANDb:
case t_XORb:
case t_SUBb:
case t_CMPb:
case t_INCb:
case t_DECb:
case t_TESTb:
case t_SHLb:
case t_SHRb:
case t_SARb:
case t_NEGb:
return (flags.result.b>=0x80);
case t_ADDw:
case t_ORw:
case t_ADCw:
case t_SBBw:
case t_ANDw:
case t_XORw:
case t_SUBw:
case t_CMPw:
case t_INCw:
case t_DECw:
case t_TESTw:
case t_SHLw:
case t_SHRw:
case t_SARw:
case t_DSHLw:
case t_DSHRw:
case t_NEGw:
return (flags.result.w>=0x8000);
case t_ADDd:
case t_ORd:
case t_ADCd:
case t_SBBd:
case t_ANDd:
case t_XORd:
case t_SUBd:
case t_CMPd:
case t_INCd:
case t_DECd:
case t_TESTd:
case t_SHLd:
case t_SHRd:
case t_SARd:
case t_DSHLd:
case t_DSHRd:
case t_NEGd:
return (flags.result.d>=0x80000000);
case t_DIV:
case t_MUL:
return false;
default:
E_Exit("get_SF Unkown %d",flags.type);
}
return false;
}
bool get_OF(void) {
Bit8u var1b7, var2b7, resultb7;
Bit16u var1w15, var2w15, resultw15;
Bit32u var1d31, var2d31, resultd31;
Bitu type=flags.type;
again:
switch (type) {
case t_UNKNOWN:
case t_MUL:
return flags.of;
case t_CF:
type=flags.prev_type;
goto again;
case t_ADDb:
case t_ADCb:
// return (((flags.result.b) ^ (flags.var2.b)) & ((flags.result.b) ^ (flags.var1.b)) & 0x80)>0;
var1b7 = flags.var1.b & 0x80;
var2b7 = flags.var2.b & 0x80;
resultb7 = flags.result.b & 0x80;
return (var1b7 == var2b7) && (resultb7 ^ var2b7);
case t_ADDw:
case t_ADCw:
// return (((flags.result.w) ^ (flags.var2.w)) & ((flags.result.w) ^ (flags.var1.w)) & 0x8000)>0;
var1w15 = flags.var1.w & 0x8000;
var2w15 = flags.var2.w & 0x8000;
resultw15 = flags.result.w & 0x8000;
return (var1w15 == var2w15) && (resultw15 ^ var2w15);
case t_ADDd:
case t_ADCd:
//TODO fix dword Overflow
var1d31 = flags.var1.d & 0x8000;
var2d31 = flags.var2.d & 0x8000;
resultd31 = flags.result.d & 0x8000;
return (var1d31 == var2d31) && (resultd31 ^ var2d31);
case t_SBBb:
case t_SUBb:
case t_CMPb:
// return (((flags.var1.b) ^ (flags.var2.b)) & ((flags.var1.b) ^ (flags.result.b)) & 0x80)>0;
var1b7 = flags.var1.b & 0x80;
var2b7 = flags.var2.b & 0x80;
resultb7 = flags.result.b & 0x80;
return (var1b7 ^ var2b7) && (var1b7 ^ resultb7);
case t_SBBw:
case t_SUBw:
case t_CMPw:
// return (((flags.var1.w) ^ (flags.var2.w)) & ((flags.var1.w) ^ (flags.result.w)) & 0x8000)>0;
var1w15 = flags.var1.w & 0x8000;
var2w15 = flags.var2.w & 0x8000;
resultw15 = flags.result.w & 0x8000;
return (var1w15 ^ var2w15) && (var1w15 ^ resultw15);
case t_SBBd:
case t_SUBd:
case t_CMPd:
var1d31 = flags.var1.d & 0x8000;
var2d31 = flags.var2.d & 0x8000;
resultd31 = flags.result.d & 0x8000;
return (var1d31 ^ var2d31) && (var1d31 ^ resultd31);
case t_INCb:
return (flags.result.b == 0x80);
case t_INCw:
return (flags.result.w == 0x8000);
case t_INCd:
return (flags.result.d == 0x80000000);
case t_DECb:
return (flags.result.b == 0x7f);
case t_DECw:
return (flags.result.w == 0x7fff);
case t_DECd:
return (flags.result.d == 0x7fffffff);
case t_NEGb:
return (flags.var1.b == 0x80);
case t_NEGw:
return (flags.var1.w == 0x8000);
case t_NEGd:
return (flags.var1.d == 0x80000000);
case t_ROLb:
case t_RORb:
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_RORw:
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_RORd:
case t_RCLd:
case t_RCRd:
case t_SHLd:
case t_DSHLd:
if (flags.var2.b==1) return ((flags.var1.d ^ flags.result.d) & 0x80000000) >0;
break;
case t_SHRb:
if (flags.var2.b==1) return (flags.var1.b >= 0x80);
break;
case t_SHRw:
case t_DSHRw: //TODO
if (flags.var2.b==1) return (flags.var1.w >= 0x8000);
break;
case t_SHRd:
case t_DSHRd: //TODO
if (flags.var2.b==1) return (flags.var1.d >= 0x80000000);
break;
case t_SARb:
case t_SARw:
case t_SARd:
case t_ORb:
case t_ORw:
case t_ORd:
case t_ANDb:
case t_ANDw:
case t_ANDd:
case t_XORb:
case t_XORw:
case t_XORd:
case t_TESTb:
case t_TESTw:
case t_TESTd:
case t_DIV:
return false;
default:
E_Exit("get_OF Unkown %d",flags.type);
}
return false;
}
static bool parity_lookup[256] = {
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
};
bool get_PF(void) {
switch (flags.type) {
case t_UNKNOWN:
return flags.pf;
default:
return (parity_lookup[flags.result.b]);;
};
return false;
}

210
src/cpu/modrm.cpp Normal file
View file

@ -0,0 +1,210 @@
/*
* 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 "cpu.h"
Bit8u * lookupRMregb[]=
{
&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,
&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,
&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,
&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,
&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,
&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,
&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,
&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,
&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,
&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,
&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,
&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,
&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,
&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,
&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,
&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,
&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,
&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,
&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,
&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,
&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,
&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,
&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,
&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,
&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,
&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,
&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,
&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,
&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,
&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,
&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,
&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh
};
Bit16u * lookupRMregw[]={
&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,
&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,
&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,
&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,
&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,
&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,
&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,
&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,
&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,
&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,
&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,
&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,
&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,
&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,
&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,
&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,
&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,
&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,
&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,
&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,
&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,
&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,
&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,
&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,
&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,
&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,
&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,
&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,
&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,
&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,
&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,
&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di
};
Bit32u * lookupRMregd[256]={
&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,
&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,
&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,
&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,
&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,
&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,
&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,
&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,
&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,
&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,
&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,
&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,
&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,
&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,
&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,
&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,
&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,
&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,
&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,
&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,
&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,
&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,
&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,
&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,
&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,
&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,
&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,
&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,
&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,
&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,
&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,
&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi
};
Bit8u * lookupRMEAregb[256]={
/* 12 lines of 16*0 should give nice errors when used */
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, 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, 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,
&reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
&reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
&reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
&reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
&reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
&reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
&reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
&reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh
};
Bit16u * lookupRMEAregw[256]={
/* 12 lines of 16*0 should give nice errors when used */
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, 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, 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,
&reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
&reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
&reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
&reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
&reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
&reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
&reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
&reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di
};
Bit32u * lookupRMEAregd[256]={
/* 12 lines of 16*0 should give nice errors when used */
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, 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, 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,
&reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
&reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
&reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
&reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
&reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
&reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
&reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
&reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi
};

76
src/cpu/modrm.h Normal file
View file

@ -0,0 +1,76 @@
/*
* 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.
*/
extern Bit8u * lookupRMregb[];
extern Bit16u * lookupRMregw[];
extern Bit32u * lookupRMregd[];
extern Bit8u * lookupRMEAregb[256];
extern Bit16u * lookupRMEAregw[256];
extern Bit32u * lookupRMEAregd[256];
#define GetRM \
Bit8u rm=Fetchb();
#define Getrb \
Bit8u * rmrb; \
rmrb=lookupRMregb[rm];
#define Getrw \
Bit16u * rmrw; \
rmrw=lookupRMregw[rm];
#define Getrd \
Bit32u * rmrd; \
rmrd=lookupRMregd[rm];
#define GetRMrb \
GetRM; \
Getrb;
#define GetRMrw \
GetRM; \
Getrw;
#define GetRMrd \
GetRM; \
Getrd;
#define GetEArb \
union { \
Bit8u * earb; \
Bit8s * earbs; \
}; \
earb=lookupRMEAregb[rm];
#define GetEArw \
union { \
Bit16u * earw; \
Bit16s * earws; \
}; \
earw=lookupRMEAregw[rm];
#define GetEArd \
union { \
Bit32u * eard; \
Bit32s * eards; \
}; \
eard=lookupRMEAregd[rm];

120
src/cpu/slow_16.cpp Normal file
View file

@ -0,0 +1,120 @@
/*
* 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 "mem.h"
#include "cpu.h"
#include "inout.h"
#include "callback.h"
#include "pic.h"
#include "fpu.h"
typedef PhysPt EAPoint;
#define SegBase(seg) Segs[seg].phys
#define LoadMb(off) mem_readb(off)
#define LoadMw(off) mem_readw(off)
#define LoadMd(off) mem_readd(off)
#define LoadMbs(off) (Bit8s)(LoadMb(off))
#define LoadMws(off) (Bit16s)(LoadMw(off))
#define LoadMds(off) (Bit32s)(LoadMd(off))
#define SaveMb(off,val) mem_writeb(off,val)
#define SaveMw(off,val) mem_writew(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 LoadRw(reg) reg
#define LoadRd(reg) reg
#define SaveRb(reg,val) reg=val
#define SaveRw(reg,val) reg=val
#define SaveRd(reg,val) reg=val
extern Bitu cycle_count;
#define CPU_386
//TODO Change name
#define FULLFLAGS
#include "core_16/support.h"
static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count);
static Bitu CPU_Real_16_Slow_Decode(Bitu count) {
#include "core_16/start.h"
while (count) {
#ifdef C_DEBUG
cycle_count++;
#endif
count--;
#include "core_16/main.h"
}
#include "core_16/stop.h"
return CBRET_NONE;
}
static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count) {
while (count>0) {
if (flags.tf) {
Interrupt(3);
cpudecoder=&CPU_Real_16_Slow_Decode;
return CBRET_NONE;
}
CPU_Real_16_Slow_Decode(1);
if (!flags.tf) {
cpudecoder=&CPU_Real_16_Slow_Decode;
return CBRET_NONE;
};
count--;
}
return CBRET_NONE;
}
void CPU_Real_16_Slow_Start(void) {
lookupEATable=&GetEA_16_n;
segprefix_base=0;
segprefix_on=false;
cpudecoder=&CPU_Real_16_Slow_Decode;
};

5
src/debug/Makefile.am Normal file
View file

@ -0,0 +1,5 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
EXTRA_DIST = debug_win32.cpp
noinst_LIBRARIES = libdebug.a
libdebug_a_SOURCES = debug.cpp debug_gui.cpp debug_disasm.cpp debug_inc.h disasm_tables.h

257
src/debug/debug.cpp Normal file
View file

@ -0,0 +1,257 @@
/*
* 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 <string.h>
#include <list>
#include "dosbox.h"
#ifdef C_DEBUG
#include "debug.h"
#include "cpu.h"
#include "video.h"
#include "pic.h"
#include "keyboard.h"
#include "cpu.h"
#include "callback.h"
#include "inout.h"
#include "mixer.h"
#include "debug_inc.h"
#ifdef WIN32
void WIN32_Console();
#endif
static struct {
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
} oldregs;
static Segment oldsegs[6];
static Flag_Info oldflags;
DBGBlock dbg;
static char input_line[256];
static Bitu input_count;
Bitu cycle_count;
static bool debugging;
static void SetColor(bool test) {
if (test) {
if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));}
} else {
if (has_colors()) { wattrset(dbg.win_reg,0);}
}
}
enum { BKPNT_REALMODE,BKPNT_PHYSICAL };
struct BreakPoint {
PhysPt location;
Bit8u olddata;
Bit16u seg;
Bit16u off_16;
Bit32u off_32;
Bit8u type;
bool enabled;
bool active;
};
static std::list<struct BreakPoint> BPoints;
static void DrawRegisters(void) {
/* Main Registers */
SetColor(reg_eax!=oldregs.eax);oldregs.eax=reg_eax;mvwprintw (dbg.win_reg,0,4,"%08X",reg_eax);
SetColor(reg_ebx!=oldregs.ebx);oldregs.ebx=reg_ebx;mvwprintw (dbg.win_reg,1,4,"%08X",reg_ebx);
SetColor(reg_ecx!=oldregs.ecx);oldregs.ecx=reg_ecx;mvwprintw (dbg.win_reg,2,4,"%08X",reg_ecx);
SetColor(reg_edx!=oldregs.edx);oldregs.edx=reg_edx;mvwprintw (dbg.win_reg,3,4,"%08X",reg_edx);
SetColor(reg_esi!=oldregs.esi);oldregs.esi=reg_esi;mvwprintw (dbg.win_reg,0,18,"%08X",reg_esi);
SetColor(reg_edi!=oldregs.edi);oldregs.edi=reg_edi;mvwprintw (dbg.win_reg,1,18,"%08X",reg_edi);
SetColor(reg_ebp!=oldregs.ebp);oldregs.ebp=reg_ebp;mvwprintw (dbg.win_reg,2,18,"%08X",reg_ebp);
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(Segs[ds].value!=oldsegs[ds].value);oldsegs[ds].value=Segs[ds].value;mvwprintw (dbg.win_reg,0,31,"%04X",Segs[ds].value);
SetColor(Segs[es].value!=oldsegs[es].value);oldsegs[es].value=Segs[es].value;mvwprintw (dbg.win_reg,0,41,"%04X",Segs[es].value);
SetColor(Segs[fs].value!=oldsegs[fs].value);oldsegs[fs].value=Segs[fs].value;mvwprintw (dbg.win_reg,0,51,"%04X",Segs[fs].value);
SetColor(Segs[gs].value!=oldsegs[gs].value);oldsegs[gs].value=Segs[gs].value;mvwprintw (dbg.win_reg,0,61,"%04X",Segs[gs].value);
SetColor(Segs[ss].value!=oldsegs[ss].value);oldsegs[ss].value=Segs[ss].value;mvwprintw (dbg.win_reg,0,71,"%04X",Segs[ss].value);
SetColor(Segs[cs].value!=oldsegs[cs].value);oldsegs[cs].value=Segs[cs].value;mvwprintw (dbg.win_reg,1,31,"%04X",Segs[cs].value);
/*Individual flags*/
flags.cf=get_CF();SetColor(flags.cf!=oldflags.cf);oldflags.cf=flags.cf;mvwprintw (dbg.win_reg,1,53,"%01X",flags.cf);
flags.zf=get_ZF();SetColor(flags.zf!=oldflags.zf);oldflags.zf=flags.zf;mvwprintw (dbg.win_reg,1,56,"%01X",flags.zf);
flags.sf=get_SF();SetColor(flags.sf!=oldflags.sf);oldflags.sf=flags.sf;mvwprintw (dbg.win_reg,1,59,"%01X",flags.sf);
flags.of=get_OF();SetColor(flags.of!=oldflags.of);oldflags.of=flags.of;mvwprintw (dbg.win_reg,1,62,"%01X",flags.of);
flags.af=get_AF();SetColor(flags.af!=oldflags.af);oldflags.af=flags.af;mvwprintw (dbg.win_reg,1,65,"%01X",flags.af);
flags.pf=get_PF();SetColor(flags.pf!=oldflags.pf);oldflags.pf=flags.pf;mvwprintw (dbg.win_reg,1,68,"%01X",flags.pf);
SetColor(flags.df!=oldflags.df);oldflags.df=flags.df;mvwprintw (dbg.win_reg,1,71,"%01X",flags.df);
SetColor(flags.intf!=oldflags.intf);oldflags.intf=flags.intf;mvwprintw (dbg.win_reg,1,74,"%01X",flags.intf);
SetColor(flags.tf!=oldflags.tf);oldflags.tf=flags.tf;mvwprintw (dbg.win_reg,1,77,"%01X",flags.tf);
wattrset(dbg.win_reg,0);
mvwprintw(dbg.win_reg,3,60,"%d ",cycle_count);
wrefresh(dbg.win_reg);
};
static void DrawCode(void) {
PhysPt start=Segs[cs].phys+reg_eip;
char dline[200];Bitu size;Bitu c;
for (Bit32u i=0;i<10;i++) {
size=DasmI386(dline, start, reg_eip, false);
mvwprintw(dbg.win_code,i,0,"%02X:%04X ",Segs[cs].value,(start-Segs[cs].phys));
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,' ');
waddstr(dbg.win_code,dline);
for (c=30-strlen(dline);c>0;c--) waddch(dbg.win_code,' ');
start+=size;
}
wrefresh(dbg.win_code);
}
/* This clears all breakpoints by replacing their 0xcc by the original byte */
static void ClearBreakPoints(void) {
// for (Bit32u i=0;i<MAX_BREAKPOINT;i++) {
// if (bpoints[i].active && bpoints[i].enabled) {
// mem_writeb(bpoints[i].location,bpoints[i].olddata);
// }
// }
}
static void SetBreakPoints(void) {
// for (Bit32u i=0;i<MAX_BREAKPOINT;i++) {
// if (bpoints[i].active && bpoints[i].enabled) {
// bpoints[i].olddata=mem_readb(bpoints[i].location);
// mem_writeb(bpoints[i].location,0xcc);
// }
// }
}
static void AddBreakPoint(PhysPt off) {
}
bool DEBUG_BreakPoint(void) {
/* First get the phyiscal address and check for a set breakpoint */
PhysPt where=real_phys(Segs[cs].value,reg_ip-1);
bool found=false;
std::list<BreakPoint>::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;
ClearBreakPoints();
DEBUG_Enable();
SetBreakPoints();
return false;
}
Bit32u DEBUG_CheckKeys(void) {
int key=getch();
Bit32u ret=0;
if (key>0) {
switch (key) {
case '1':
ret=(*cpudecoder)(100);
break;
case '2':
ret=(*cpudecoder)(500);
break;
case '3':
ret=(*cpudecoder)(1000);
break;
case '4':
ret=(*cpudecoder)(5000);
break;
case '5':
ret=(*cpudecoder)(10000);
break;
case 'q':
ret=(*cpudecoder)(5);
break;
default:
ret=(*cpudecoder)(1);
};
DEBUG_DrawScreen();
}
return ret;
};
Bitu DEBUG_Loop(void) {
//TODO Disable sound
GFX_Events();
PIC_runIRQs();
return DEBUG_CheckKeys();
}
void DEBUG_Enable(void) {
DEBUG_DrawScreen();
debugging=true;
DOSBOX_SetLoop(&DEBUG_Loop);
}
void DEBUG_DrawScreen(void) {
DrawRegisters();
DrawCode();
}
static void DEBUG_RaiseTimerIrq(void) {
PIC_ActivateIRQ(0);
}
void DEBUG_Init(void) {
#ifdef WIN32
WIN32_Console();
#endif
memset((void *)&dbg,0,sizeof(dbg));
debugging=false;
dbg.active_win=3;
input_count=0;
/* Start the Debug Gui */
DBGUI_StartUp();
DEBUG_DrawScreen();
/* Add some keyhandlers */
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable);
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
/* Clear the breakpoint list */
}
#endif

1112
src/debug/debug_disasm.cpp Normal file

File diff suppressed because it is too large Load diff

130
src/debug/debug_gui.cpp Normal file
View file

@ -0,0 +1,130 @@
/*
* 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"
#ifdef C_DEBUG
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <curses.h>
#include <string.h>
#include "regs.h"
#include "debug.h"
#include "debug_inc.h"
void DEBUG_ShowMsg(char * msg) {
char buf[1024];
strcpy(buf,msg);
strcat(buf,"\n");
waddstr(dbg.win_out,buf);
wprintw(dbg.win_out," %d\n",cycle_count);
wrefresh(dbg.win_out);
}
static void Draw_RegisterLayout(void) {
mvwaddstr(dbg.win_reg,0,0,"EAX=");
mvwaddstr(dbg.win_reg,1,0,"EBX=");
mvwaddstr(dbg.win_reg,2,0,"ECX=");
mvwaddstr(dbg.win_reg,3,0,"EDX=");
mvwaddstr(dbg.win_reg,0,14,"ESI=");
mvwaddstr(dbg.win_reg,1,14,"EDI=");
mvwaddstr(dbg.win_reg,2,14,"EBP=");
mvwaddstr(dbg.win_reg,3,14,"ESP=");
mvwaddstr(dbg.win_reg,0,28,"DS=");
mvwaddstr(dbg.win_reg,0,38,"ES=");
mvwaddstr(dbg.win_reg,0,48,"FS=");
mvwaddstr(dbg.win_reg,0,58,"GS=");
mvwaddstr(dbg.win_reg,0,68,"SS=");
mvwaddstr(dbg.win_reg,1,28,"CS=");
mvwaddstr(dbg.win_reg,1,38,"EIP=");
mvwaddstr(dbg.win_reg,1,52,"C Z S O A P D I T ");
}
static void DrawBars(void) {
if (has_colors()) {
attrset(COLOR_PAIR(PAIR_BLACK_BLUE));
}
/* Show the Register bar */
mvaddstr(dbg.win_reg->_begy-1,0,"---[F1](Register Overview)---");
/* Show the Data Overview bar perhaps with more special stuff in the end */
mvaddstr(dbg.win_data->_begy-1,0,"---[F2](Data Overview)---");
/* Show the Code Overview perhaps with special stuff in bar too */
mvaddstr(dbg.win_code->_begy-1,0,"---[F3](Code Overview)---");
/* Show the Output OverView */
mvaddstr(dbg.win_out->_begy-1,0,"---[F4](OutPut/Input)---");
attrset(0);
}
static void MakeSubWindows(void) {
/* The Std output win should go in bottem */
/* Make all the subwindows */
int outy=1;
/* The Register window */
dbg.win_reg=subwin(dbg.win_main,4,dbg.win_main->_maxx,outy,0);
outy+=5;
/* The Data Window */
dbg.win_data=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0);
outy+=11;
/* The Code Window */
dbg.win_code=subwin(dbg.win_main,10,dbg.win_main->_maxx,outy,0);
outy+=11;
/* The output Window */
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;
scrollok(dbg.win_out,TRUE);
DrawBars();
Draw_RegisterLayout();
refresh();
}
static void MakePairs(void) {
init_pair(PAIR_BLACK_BLUE, COLOR_BLACK, COLOR_CYAN);
init_pair(PAIR_BYELLOW_BLACK, COLOR_YELLOW /*| FOREGROUND_INTENSITY */, COLOR_BLACK);
}
void DBGUI_StartUp(void) {
/* Start the main window */
dbg.win_main=initscr();
cbreak(); /* take input chars one at a time, no wait for \n */
noecho(); /* don't echo input */
nodelay(dbg.win_main,true);
keypad(dbg.win_main,true);
cycle_count=0;
MakePairs();
MakeSubWindows();
}
#endif

52
src/debug/debug_inc.h Normal file
View file

@ -0,0 +1,52 @@
/*
* 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.
*/
/* Local Debug Function */
#include <curses.h>
#include "mem.h"
#define PAIR_BLACK_BLUE 1
#define PAIR_BYELLOW_BLACK 2
void DBGUI_StartUp(void);
struct DBGBlock {
WINDOW * win_main; /* The Main Window */
WINDOW * win_reg; /* Register Window */
WINDOW * win_data; /* Data Output window */
WINDOW * win_code; /* Disassembly/Debug point Window */
WINDOW * win_out; /* Text Output Window */
Bit32u active_win; /* Current active window */
Bit32u input_y;
};
struct DASMLine {
Bit32u pc;
char dasm[80];
PhysPt ea;
Bit16u easeg;
Bit32u eaoff;
};
extern DBGBlock dbg;
/* Local Debug Stuff */
Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32);

74
src/debug/debug_win32.cpp Normal file
View file

@ -0,0 +1,74 @@
/*
* 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 <windows.h>
#include <stdio.h>
#include <stdarg.h>
/*
Have to remember where i ripped this code sometime ago.
*/
static void ResizeConsole( HANDLE hConsole, SHORT xSize, SHORT ySize ) {
CONSOLE_SCREEN_BUFFER_INFO csbi; // Hold Current Console Buffer Info
BOOL bSuccess;
SMALL_RECT srWindowRect; // Hold the New Console Size
COORD coordScreen;
bSuccess = GetConsoleScreenBufferInfo( hConsole, &csbi );
// Get the Largest Size we can size the Console Window to
coordScreen = GetLargestConsoleWindowSize( hConsole );
// Define the New Console Window Size and Scroll Position
srWindowRect.Right = (SHORT)(min(xSize, coordScreen.X) - 1);
srWindowRect.Bottom = (SHORT)(min(ySize, coordScreen.Y) - 1);
srWindowRect.Left = srWindowRect.Top = (SHORT)0;
// Define the New Console Buffer Size
coordScreen.X = xSize;
coordScreen.Y = ySize;
// If the Current Buffer is Larger than what we want, Resize the
// Console Window First, then the Buffer
if( (DWORD)csbi.dwSize.X * csbi.dwSize.Y > (DWORD) xSize * ySize)
{
bSuccess = SetConsoleWindowInfo( hConsole, TRUE, &srWindowRect );
bSuccess = SetConsoleScreenBufferSize( hConsole, coordScreen );
}
// If the Current Buffer is Smaller than what we want, Resize the
// Buffer First, then the Console Window
if( (DWORD)csbi.dwSize.X * csbi.dwSize.Y < (DWORD) xSize * ySize )
{
bSuccess = SetConsoleScreenBufferSize( hConsole, coordScreen );
bSuccess = SetConsoleWindowInfo( hConsole, TRUE, &srWindowRect );
}
// If the Current Buffer *is* the Size we want, Don't do anything!
return;
}
void WIN32_Console() {
ResizeConsole(GetStdHandle(STD_OUTPUT_HANDLE),80,50);
}

191
src/debug/disasm_tables.h Normal file
View file

@ -0,0 +1,191 @@
/*
* 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.
*/
char * RegTable_16[8]= {"ax","cx","dx","bx","sp","bp","si","di"};
char * RegTable_8[8]= {"al","cl","dl","bl","ah","ch","dh","bh"};
char * SegTable[8]= {"es","cs","ss","ds","fs","gs","iseg","iseg"};
#define MAX_INFO 3
enum {
Eb,Ev,Ew,Ep,
Gb,Gv,
Rb,Rw,Rv,
Ob,Ov,
Sw,
Mp,
Ib,Ibs,Iw,Iv,Ap,
Jb,Jv,
Bd,Bw,
XBnd,Xlea,
/* specials */
b2,p_es,p_ss,p_cs,p_ds,p_fs,p_gs,p_size,p_addr,p_rep,
s_ax,s_cx,s_dx,s_bx,s_sp,s_bp,s_si,s_di,
s_al,s_cl,s_dl,s_bl,s_ah,s_ch,s_dh,s_bh,
s_1,
Cj,
G1,G2,G3b,G3v,G4,G5,
no=0xff
};
enum {
s_jo, s_jno, s_jc, s_jnc, s_je, s_jne, s_jbe, s_jnbe,
s_js, s_jns, s_jp, s_jnp, s_jl, s_jnl, s_jle, s_jnle
};
struct Dentry {
char * start;
Bit8u info[MAX_INFO];
};
static char * G1_Table[8]={"add ","or ","adc ","sbb ","and ","sub ","xor ","cmp "};
static char * G2_Table[8]={"rol ","ror ","rcl ","rcr ","shl ","shr ","sal ","sar "};
static Dentry G3b_Table[8]={
"test ",Eb,Ib,no,
"test ",Eb,Ib,no,
"not ",Eb,no,no,
"neg ",Eb,no,no,
"mul al,",Eb,no,no,
"imul al,",Eb,no,no,
"div ax,",Eb,no,no,
"idiv ax,",Eb,no,no
};
static Dentry G3v_Table[8]={
"test ",Ev,Iv,no,
"test ",Ev,Iv,no,
"not ",Ev,no,no,
"neg ",Ev,no,no,
"mul ax,",Ev,no,no,
"imul ax,",Ev,no,no,
"div dx:ax,",Ev,no,no,
"idiv dx:ax,",Ev,no,no
};
static char * G4_Table[8]={
"inc ",
"dec ",
"illegal",
"illegal",
"illegal",
"illegal",
"illegal",
"illegal"
};
static Dentry G5_Table[8]={
"inc ",Ev,no,no,
"dec ",Ev,no,no,
"call ",Ev,no,no,
"call ",Ep,no,no,
"jmp ",Ev,no,no,
"jmp ",Ep,no,no,
"push ,",Ev,no,no,
"illegal",no,no,no
};
static Dentry DTable[256]={
/* 0 */
"add ",Eb,Gb,no, "add ",Ev,Gv,no, "add ",Gb,Eb,no, "add ",Gv,Ev,no,
"add ",s_al,Ib,no, "add ",s_ax,Iv,no, "push es",no,no,no, "pop es",no,no,no,
"or ",Eb,Gb,no, "or ",Ev,Gv,no, "or ",Gb,Eb,no, "or ",Gv,Ev,no,
"or ",s_al,Ib,no, "or ",s_ax,Iv,no, "push cs",no,no,no, "",b2,no,no,
/* 1 */
"adc ",Eb,Gb,no, "adc ",Ev,Gv,no, "adc ",Gb,Eb,no, "adc ",Gv,Ev,no,
"adc ",s_al,Ib,no, "adc ",s_ax,Iv,no, "push ss",no,no,no, "pop ss",no,no,no,
"sbb ",Eb,Gb,no, "sbb ",Ev,Gv,no, "sbb ",Gb,Eb,no, "sbb ",Gv,Ev,no,
"sbb ",s_al,Ib,no, "sbb ",s_ax,Iv,no, "push ds",no,no,no, "pop ds",no,no,no,
/* 2 */
"and ",Eb,Gb,no, "and ",Ev,Gv,no, "and ",Gb,Eb,no, "and ",Gv,Ev,no,
"and ",s_al,Ib,no, "and ",s_ax,Iv,no, "",p_es,no,no, "daa",no,no,no,
"sub ",Eb,Gb,no, "sub ",Ev,Gv,no, "sub ",Gb,Eb,no, "sub ",Gv,Ev,no,
"sub ",s_al,Ib,no, "sub ",s_ax,Iv,no, "",p_ss,no,no, "das",no,no,no,
/* 3 */
"xor ",Eb,Gb,no, "xor ",Ev,Gv,no, "xor ",Gb,Eb,no, "xor ",Gv,Ev,no,
"xor ",s_al,Ib,no, "xor ",s_ax,Iv,no, "",p_ss,no,no, "aaa",no,no,no,
"cmp ",Eb,Gb,no, "cmp ",Ev,Gv,no, "cmp ",Gb,Eb,no, "cmp ",Gv,Ev,no,
"cmp ",s_al,Ib,no, "cmp ",s_ax,Iv,no, "",p_ds,no,no, "aas",no,no,no,
/* 4 */
"inc ",s_ax,no,no, "inc ",s_cx,no,no, "inc ",s_dx,no,no, "inc ",s_bx,no,no,
"inc ",s_sp,no,no, "inc ",s_bp,no,no, "inc ",s_si,no,no, "inc ",s_di,no,no,
"dec ",s_ax,no,no, "dec ",s_cx,no,no, "dec ",s_dx,no,no, "dec ",s_bx,no,no,
"dec ",s_sp,no,no, "dec ",s_bp,no,no, "dec ",s_si,no,no, "dec ",s_di,no,no,
/* 5 */
"push ",s_ax,no,no, "push ",s_cx,no,no, "push ",s_dx,no,no, "push ",s_bx,no,no,
"push ",s_sp,no,no, "push ",s_bp,no,no, "push ",s_si,no,no, "push ",s_di,no,no,
"pop ",s_ax,no,no, "pop ",s_cx,no,no, "pop ",s_dx,no,no, "pop ",s_bx,no,no,
"pop ",s_sp,no,no, "pop ",s_bp,no,no, "pop ",s_si,no,no, "pop ",s_di,no,no,
/* 6 */
"pusha",Bd,no,no, "popa",Bd,no,no, "bound",XBnd,no,no, "arpl",Ew,Rw,no,
"",p_fs,no,no, "",p_gs,no,no, "",p_size,no,no, "",p_addr,no,no,
"push ",Iv,no,no, "imul ",Gv,Ev,Iv, "push ",Ibs,no,no, "imul ",Gv,Ev,Ib,
"insb",no,no,no, "ins",Bw,no,no, "oustb",no,no,no, "outs",Bw,no,no,
/* 7 */
"jo ",Cj,s_jo,no, "jno ",Cj,s_jno,no, "jc ",Cj,s_jc,no, "jnc ",Cj,s_jnc,no,
"je ",Cj,s_je,no, "jne ",Cj,s_jne,no, "jbe ",Cj,s_jbe,no, "jnbe ",Cj,s_jnbe,no,
"js ",Cj,s_js,no, "jns ",Cj,s_jns,no, "jp ",Cj,s_jp,no, "jnp ",Cj,s_jnp,no,
"jl ",Cj,s_jl,no, "jnl ",Cj,s_jnl,no, "jle ",Cj,s_jle,no, "jnle ",Cj,s_jnle,no,
/* 8 */
"",G1,Eb,Ib, "",G1,Ev,Iv, "",G1,Eb,Ib, "",G1,Ev,Ibs,
"test ",Eb,Gb,no, "test ",Ev,Gv,no, "xchg ",Eb,Gb,no, "xchg ",Ev,Gv,no,
"mov ",Eb,Gb,no, "mov ",Ev,Gv,no, "mov ",Gb,Eb,no, "mov ",Gv,Ev,no,
"mov ",Ew,Sw,no, "lea ",Gv,Xlea,no, "mov ",Sw,Ew,no, "pop ",Ev,no,no,
/* 9 */
"nop",no,no,no, "xchg ",s_ax,s_cx,no,"xchg ",s_ax,s_dx,no,"xchg ",s_ax,s_bx,no,
"xchg ",s_ax,s_sp,no,"xchg ",s_ax,s_bp,no,"xchg ",s_ax,s_si,no,"xchg ",s_ax,s_di,no,
"cbw",no,no,no, "cwd",no,no,no, "call ",Ap,no,no, "fwait",no,no,no,
"pushf",Bd,no,no, "popf",Bd,no,no, "sahf",no,no,no, "lahf",no,no,no,
/* a */
"mov ",s_al,Ob,no, "mov ",s_ax,Ov,no, "mov ",Ob,s_al,no, "mov ",Ov,s_ax,no,
"movsb",no,no,no, "movs",Bw,no,no, "cmpsb",no,no,no, "cmps",Bw,no,no,
"test ",s_al,Ib,no, "test ",s_ax,Iv,no, "stosb",no,no,no, "stos",Bw,no,no,
"lodsb",no,no,no, "lods",Bw,no,no, "scasb",no,no,no, "scas",Bw,no,no,
/* b */
"mov ",s_al,Ib,no, "mov ",s_cl,Ib,no, "mov ",s_dl,Ib,no, "mov ",s_bl,Ib,no,
"mov ",s_ah,Ib,no, "mov ",s_ch,Ib,no, "mov ",s_dh,Ib,no, "mov ",s_bh,Ib,no,
"mov ",s_ax,Iv,no, "mov ",s_cx,Iv,no, "mov ",s_dx,Iv,no, "mov ",s_bx,Iv,no,
"mov ",s_sp,Iv,no, "mov ",s_bp,Iv,no, "mov ",s_si,Iv,no, "mov ",s_di,Iv,no,
/* c */
"",G2,Eb,Ib, "",G2,Ev,Ib, "ret ",Iw,no,no, "ret",no,no,no,
"les ",Gv,Mp,no, "lds ",Gv,Mp,no, "mov ",Eb,Ib,no, "mov ",Ev,Iv,no,
"enter ",Iw,Ib,no, "leave",no,no,no, "retf ",Iw,no,no, "retf",no,no,no,
"int 03",no,no,no, "int ",Ib,no,no, "into",no,no,no, "iret",Bd,no,no,
/* d */
"",G2,Eb,s_1, "",G2,Ev,s_1, "",G2,Eb,s_cl, "",G2,Ev,s_cl,
"aam",no,no,no, "aad",no,no,no, "setalc",no,no,no, "xlat",no,no,no,
"esc 0",Ib,no,no, "esc 1",Ib,no,no, "esc 2",Ib,no,no, "esc 3",Ib,no,no,
"esc 4",Ib,no,no, "esc 5",Ib,no,no, "esc 6",Ib,no,no, "esc 7",Ib,no,no,
/* e */
"loopne ",Jb,no,no, "loope ",Jb,no,no, "loop ",Jb,no,no, "jcxz ",Jb,no,no,
"in ",s_al,Ib,no, "in ",s_ax,Ib,no, "out ",Ib,s_al,no, "out ",Ib,s_ax,no,
"call ",Jv,no,no, "jmp ",Jv,no,no, "jmp",Ap,no,no, "jmp ",Jb,no,no,
"in ",s_al,s_dx,no, "in ",s_ax,s_dx,no, "out ",s_dx,s_al,no,"out ",s_dx,s_ax,no,
/* f */
"lock",no,no,no, "cb ",Iw,no,no, "repne ",p_rep,no,no,"repe ",p_rep,no,no,
"hlt",no,no,no, "cmc",no,no,no, "",G3b,no,no, "",G3v,no,no,
"clc",no,no,no, "stc",no,no,no, "cli",no,no,no, "sti",no,no,no,
"cld",no,no,no, "std",no,no,no, "",G4,Eb,no, "",G5,no,no,
};

7
src/dos/Makefile.am Normal file
View file

@ -0,0 +1,7 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libdos.a
libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \
dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \
drives.cpp drives.h drive_virtual.cpp drive_local.cpp \
dev_con.h

105
src/dos/dev_con.h Normal file
View file

@ -0,0 +1,105 @@
/*
* 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.
*/
class device_CON : public DOS_Device {
public:
device_CON();
bool Read(Bit8u * data,Bit16u * size);
bool Write(Bit8u * data,Bit16u * size);
bool Seek(Bit32u * pos,Bit32u type);
bool Close();
Bit16u GetInformation(void);
private:
Bit8u cache;
};
bool device_CON::Read(Bit8u * data,Bit16u * size) {
Bit16u oldax=reg_ax;
Bit16u count=0;
if ((cache) && (*size)) {
data[count++]=cache;
cache=0;
}
while (*size>count) {
reg_ah=0;
CALLBACK_RunRealInt(0x16);
switch(reg_al) {
case 13:
data[count++]=0x0D;
// if (*size>count) data[count++]=0x0A;
// else cache=0x0A;
*size=count;
reg_ax=oldax;
return true;
default:
data[count++]=reg_al;
break;
case 0:
data[count++]=reg_al;
if (*size>count) data[count++]=reg_ah;
else cache=reg_ah;
break;
}
}
*size=count;
reg_ax=oldax;
return true;
}
extern void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page);
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;
while (*size>count) {
/*
reg_al=data[count];
reg_ah=0x0e;
reg_bx=0x0007;
CALLBACK_RunRealInt(0x10);
*/
INT10_TeletypeOutput(data[count],7,false,0);
count++;
}
*size=count;
// reg_ax=oldax;reg_bx=oldbx;
return true;
}
bool device_CON::Seek(Bit32u * pos,Bit32u type) {
return false;
}
bool device_CON::Close() {
return false;
}
Bit16u device_CON::GetInformation(void) {
Bit16u head=mem_readw(BIOS_KEYBOARD_BUFFER_HEAD);
Bit16u tail=mem_readw(BIOS_KEYBOARD_BUFFER_TAIL);
if ((head==tail) && !cache) return 0x80D3; /* No Key Available */
return 0x8093; /* Key Available */
};
device_CON::device_CON() {
name="CON";
cache=0;
}

790
src/dos/dos.cpp Normal file
View file

@ -0,0 +1,790 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "dosbox.h"
#include "bios.h"
#include "mem.h"
#include "callback.h"
#include "regs.h"
#include "dos_inc.h"
DOS_Block dos;
static Bit8u dos_copybuf[0x10000];
static Bitu call_20,call_21,call_theend;
void DOS_SetError(Bit16u code) {
dos.errorcode=code;
};
#define DOSNAMEBUF 256
static Bitu DOS_21Handler(void) {
//TODO KEYBOARD Check for break
char name1[DOSNAMEBUF+1];
char name2[DOSNAMEBUF+1];
switch (reg_ah) {
case 0x00: /* Terminate Program */
E_Exit("DOS:Unhandled call %02X",reg_ah);
break;
case 0x01: /* Read character from STDIN, with echo */
{
Bit8u c;Bit16u n=1;
DOS_ReadFile(STDIN,&c,&n);
reg_al=c;
DOS_WriteFile(STDOUT,&c,&n);
}
break;
case 0x02: /* Write character to STDOUT */
{
Bit8u c=reg_dl;Bit16u n=1;
DOS_WriteFile(STDOUT,&c,&n);
}
break;
case 0x03: /* Read character from STDAUX */
case 0x04: /* Write Character to STDAUX */
case 0x05: /* Write Character to PRINTER */
E_Exit("DOS:Unhandled call %02X",reg_ah);
break;
case 0x06: /* Direct Console Output / Input */
switch (reg_dl) {
case 0xFF: /* Input */
{
//TODO Make this better according to standards
if (!DOS_GetSTDINStatus()) {
CALLBACK_SZF(true);
break;
}
Bit8u c;Bit16u n=1;
DOS_ReadFile(STDIN,&c,&n);
reg_al=c;
CALLBACK_SZF(false);
break;
}
default:
{
Bit8u c=reg_dl;Bit16u n=1;
DOS_WriteFile(STDOUT,&c,&n);
}
break;
};
break;
case 0x07: /* Character Input, without echo */
{
Bit8u c;Bit16u n=1;
DOS_ReadFile (STDIN,&c,&n);
reg_al=c;
break;
};
case 0x08: /* Direct Character Input, without echo */
{
Bit8u c;Bit16u n=1;
DOS_ReadFile (STDIN,&c,&n);
reg_al=c;
break;
};
case 0x09: /* Write string to STDOUT */
{
Bit8u c;Bit16u n=1;
PhysPt buf=real_phys(Segs[ds].value,reg_dx);
while ((c=mem_readb(buf++))!='$') {
DOS_WriteFile(STDOUT,&c,&n);
}
}
break;
case 0x0a: /* Buffered Input */
{
//TODO ADD Break checkin in STDIN but can't care that much for it
PhysPt data=real_phys(Segs[ds].value,reg_dx);
Bit8u free=mem_readb(data);
Bit8u read=0;Bit8u c;Bit16u n=1;
if (!free) break;
while (read<free) {
DOS_ReadFile(STDIN,&c,&n);
DOS_WriteFile(STDOUT,&c,&n);
if (c==13) {
DOS_ReadFile(STDIN,&c,&n);
break;
}
mem_writeb(data+read+2,c);
read++;
};
mem_writeb(data+1,read);
break;
};
case 0x0b: /* Get STDIN Status */
if (DOS_GetSTDINStatus()) reg_al=0xff;
else reg_al=0;
break;
case 0x0c: /* Flush Buffer and read STDIN call */
{
switch (reg_al) {
case 0x1:
case 0x6:
case 0x7:
case 0x8:
case 0xa:
{
Bit8u oldah=reg_ah;
reg_ah=reg_al;
DOS_21Handler();
reg_ah=oldah;
}
break;
default:
LOG_ERROR("DOS:0C:Illegal Flush STDIN Buffer call %d",reg_al);
break;
}
}
break;
//TODO Find out the values for when reg_al!=0
//TODO Hope this doesn't do anything special
case 0x0d: /* Disk Reset */
//Sure let's reset a virtual disk
break;
case 0x0e: /* Select Default Drive */
DOS_SetDefaultDrive(reg_dl);
reg_al=26;
break;
case 0x0f: /* Open File using FCB */
case 0x10: /* Close File using FCB */
case 0x11: /* Find First Matching File using FCB */
case 0x12: /* Find Next Matching File using FCB */
case 0x13: /* Delete File using FCB */
case 0x14: /* Sequential read from FCB */
case 0x15: /* Sequential write to FCB */
case 0x16: /* Create or truncate file using FCB */
case 0x17: /* Rename file using FCB */
case 0x21: /* Read random record from FCB */
case 0x22: /* Write random record to FCB */
case 0x23: /* Get file size for FCB */
case 0x24: /* Set Random Record number for FCB */
case 0x27: /* Random block read from FCB */
case 0x28: /* Random Block read to FCB */
LOG_ERROR("DOS:Unhandled call %02X, FCB Stuff",reg_ah);
reg_al=0xff; /* FCB Calls FAIL */
CALLBACK_SCF(true);
break;
case 0x29: /* Parse filename into FCB */
//TODO Give errors for unsupported functions
{
MEM_StrCopy(real_phys(Segs[ds].value,reg_si),name1,DOSNAMEBUF);
/* only detect the call program use to detect the existence of a harddisk */
if ((strlen((char *)name1)==2) && (name1[1]==':')) {
Bit8u drive=toupper(name1[0])-'A';
if (Drives[drive]) reg_al=0;
else reg_al=0xff;
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 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x20: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x6b: /* NULL Function */
case 0x61: /* UNUSED */
reg_al=0;
break;
case 0x19: /* Get current default drive */
reg_al=DOS_GetDefaultDrive();
break;
case 0x1a: /* Set Disk Transfer Area Address */
//TODO find out what a DTA does
dos.dta=RealMake(Segs[ds].value,reg_dx);
break;
case 0x1c: /* Get allocation info for specific drive */
LOG_DEBUG("DOS: Allocation Info call not supported correctly");
SetSegment_16(ds,0xf000);
reg_bx=0;
real_writeb(0xf000,0,0);
reg_al=0x7f;
reg_cx=0x200;
reg_dx=0x1000;
break; /* TODO maybe but hardly think a game needs this */
case 0x1b: /* Get allocation info for default drive */
LOG_DEBUG("DOS: Allocation Info call not supported correctly");
SetSegment_16(ds,0xf000);
reg_bx=0;
real_writeb(0xf000,0,0);
reg_al=0x7f;
reg_cx=0x200;
reg_dx=0x1000;
break;
case 0x1f: /* Get drive parameter block for default drive */
case 0x32: /* Get drive parameter block for specific drive */
E_Exit("DOS:Unhandled call %02X",reg_ah);
break; /* TODO maybe but hardly think a game needs this */
case 0x25: /* Set Interrupt Vector */
RealSetVec(reg_al,RealMake(Segs[ds].value,reg_dx));
break;
case 0x26: /* Create new PSP */
DOS_NewPSP(reg_dx);
break;
case 0x2a: /* Get System Date */
reg_al=0; /* It's always sunday TODO find that correct formula */
reg_cx=dos.date.year;
reg_dh=dos.date.month;
reg_dl=dos.date.day;
break;
case 0x2b: /* Set System Date */
//TODO Check for months with less then 31 days
if (reg_cx<1980) { reg_al=0xff;break;}
if ((reg_dh>12) || (reg_dh==0)) { reg_al=0xff;break;}
if ((reg_dl>31) || (reg_dl==0)) { reg_al=0xff;break;}
dos.date.year=reg_cx;
dos.date.month=reg_dh;
dos.date.day=reg_dl;
reg_al=0;
break;
case 0x2c: /* Get System Time */
//TODO Get time through bios calls date is fixed
{
Bit32u ticks=mem_readd(BIOS_TIMER);
Bit32u seconds=(ticks*10)/182;
reg_ch=(Bit8u)(seconds/3600);
reg_cl=(Bit8u)(seconds % 3600)/60;
reg_dh=(Bit8u)(seconds % 60);
reg_dl=(Bit8u)(ticks % 19)*5;
}
break;
case 0x2d: /* Set System Time */
LOG_DEBUG("DOS:Set System Time not supported");
reg_al=0; /* Noone is changing system time */
break;
case 0x2e: /* Set Verify flag */
dos.verify=(reg_al==1);
break;
case 0x2f: /* Get Disk Transfer Area */
SetSegment_16(es,RealSeg(dos.dta));
reg_bx=RealOff(dos.dta);
break;
case 0x30: /* Get DOS Version */
if (reg_al==0) reg_bh=0xFF; /* Fake Microsoft DOS */
if (reg_al==1) reg_bh=0x10; /* DOS is in HMA */
reg_al=dos.version.major;
reg_ah=dos.version.minor;
break;
case 0x31: /* Terminate and stay resident */
//TODO First get normal files executing
DOS_ResizeMemory(dos.psp,&reg_dx);
if (DOS_Terminate(true)) {
dos.return_code=reg_al;
dos.return_mode=RETURN_TSR;
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x33: /* Extended Break Checking */
switch (reg_al) {
case 0:reg_dl=dos.breakcheck;break; /* Get the breakcheck flag */
case 1:dos.breakcheck=(reg_dl>0);break; /* Set the breakcheck flag */
case 2:{bool old=dos.breakcheck;dos.breakcheck=(reg_dl>0);reg_dl=old;}break;
case 5:reg_dl=3;break; /* Always boot from c: :) */
case 6: /* Get true version number */
reg_bl=dos.version.major;
reg_bh=dos.version.minor;
reg_dl=dos.version.revision;
reg_dh=0x10; /* Dos in HMA */
break;
default:
E_Exit("DOS:Illegal 0x33 Call %2X",reg_al);
}
break;
case 0x34: /* Get INDos Flag */
SetSegment_16(es,RealSeg(dos.tables.indosflag));
reg_bx=RealOff(dos.tables.indosflag);
break;
case 0x35: /* Get interrupt vector */
reg_bx=real_readw(0,((Bit16u)reg_al)*4);
SetSegment_16(es,real_readw(0,((Bit16u)reg_al)*4+2));
break;
case 0x36: /* Get Free Disk Space */
{
Bit16u bytes,sectors,clusters,free;
if (DOS_GetFreeDiskSpace(reg_dl,&bytes,&sectors,&clusters,&free)) {
reg_ax=sectors;
reg_bx=free;
reg_cx=bytes;
reg_dx=clusters;
} else {
reg_ax=0xffff;
}
}
break;
case 0x37: /* Get/Set Switch char Get/Set Availdev thing */
//TODO Give errors for these functions to see if anyone actually uses this shit-
switch (reg_al) {
case 0:
reg_al=0;reg_dl=0x2f;break; /* always return '/' like dos 5.0+ */
case 1:
reg_al=0;break;
case 2:
reg_al=0;reg_dl=0x2f;break;
case 3:
reg_al=0;break;
};
LOG_DEBUG("DOS:0x37:Call for not supported switchchar");
break;
case 0x38: /* Set Country Code */
LOG_DEBUG("DOS:Setting country code not supported");
CALLBACK_SCF(true);
break;
if (reg_al==0) { /* Get country specidic information */
} else { /* Set country code */
}
break;
case 0x39: /* MKDIR Create directory */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_MakeDir(name1)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x3a: /* RMDIR Remove directory */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_RemoveDir(name1)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x3b: /* CHDIR Set current directory */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_ChangeDir(name1)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x3c: /* CREATE Create of truncate file */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_CreateFile(name1,reg_cx,&reg_ax)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x3d: /* OPEN Open existing file */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_OpenFile(name1,reg_al,&reg_ax)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x3e: /* CLOSE Close file */
if (DOS_CloseFile(reg_bx)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x3f: /* READ Read from file or device */
{
Bit16u toread=reg_cx;
if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) {
MEM_BlockWrite(real_phys(Segs[ds].value,reg_dx),dos_copybuf,toread);
reg_ax=toread;
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
}
case 0x40: /* WRITE Write to file or device */
{
Bit16u towrite=reg_cx;
MEM_BlockRead(real_phys(Segs[ds].value,reg_dx),dos_copybuf,towrite);
if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) {
reg_ax=towrite;
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
};
case 0x41: /* UNLINK Delete file */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_UnlinkFile(name1)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x42: /* LSEEK Set current file position */
{
Bit32u pos=(reg_cx<<16) + reg_dx;
if (DOS_SeekFile(reg_bx,&pos,reg_al)) {
reg_dx=(Bit16u)(pos >> 16);
reg_ax=(Bit16u)(pos & 0xFFFF);
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
}
case 0x43: /* Get/Set file attributes */
//TODO FIX THIS HACK
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
switch (reg_al)
case 0x00: /* Get */
{
if (DOS_GetFileAttr(name1,&reg_cx)) {
CALLBACK_SCF(false);
} else {
CALLBACK_SCF(true);
reg_ax=dos.errorcode;
}
break;
case 0x01: /* Set */
LOG_DEBUG("DOS:Set File Attributes for %s not supported",name1);
CALLBACK_SCF(false);
break;
default:
E_Exit("DOS:0x43:Illegal subfunction %2X",reg_al);
}
break;
case 0x44: /* IOCTL Functions */
if (DOS_IOCTL(reg_al,reg_bx)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x45: /* DUP Duplicate file handle */
if (DOS_DuplicateEntry(reg_bx,&reg_ax)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x46: /* DUP2,FORCEDUP Force duplicate file handle */
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break;
case 0x47: /* CWD Get current directory */
//TODO Memory
if (DOS_GetCurrentDir(reg_dl,real_off(Segs[ds].value,reg_si))) {
reg_ax=0x0100;
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x48: /* Allocate memory */
{
Bit16u size=reg_bx;Bit16u seg;
if (DOS_AllocateMemory(&seg,&size)) {
reg_ax=seg;
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
reg_bx=size;
CALLBACK_SCF(true);
}
break;
}
case 0x49: /* Free memory */
if (DOS_FreeMemory(Segs[es].value)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x4a: /* Resize memory block */
{
Bit16u size=reg_bx;
if (DOS_ResizeMemory(Segs[es].value,&size)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
reg_bx=size;
CALLBACK_SCF(true);
}
break;
}
case 0x4b: /* EXEC Load and/or execute program */
{
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_Execute(name1,(ParamBlock *)real_off(Segs[es].value,reg_bx),reg_al)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
}
break;
//TODO Check for use of execution state AL=5
case 0x4c: /* EXIT Terminate with return code */
{
if (DOS_Terminate(false)) {
dos.return_code=reg_al;
dos.return_mode=RETURN_EXIT;
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
}
case 0x4d: /* Get Return code */
reg_al=dos.return_code;
reg_ah=dos.return_mode;
break;
case 0x4e: /* FINDFIRST Find first matching file */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_FindFirst(name1,reg_cx)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
};
break;
case 0x4f: /* FINDNEXT Find next matching file */
if (DOS_FindNext()) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
};
break;
case 0x50: /* Set current PSP */
dos.psp=reg_bx;
break;
case 0x51: /* Get current PSP */
reg_bx=dos.psp;
break;
case 0x52: /* Get list of lists */
SetSegment_16(es,0);
reg_bx=0;
LOG_ERROR("Call is made for list of lists not supported let's hope for the best");
break;
//TODO Think hard how shit this is gonna be
//And will any game ever use this :)
case 0x53: /* Translate BIOS parameter block to drive parameter block */
//YEAH RIGHT
case 0x54: /* Get verify flag */
case 0x55: /* Create Child PSP*/
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break;
case 0x56: /* RENAME Rename file */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
MEM_StrCopy(real_phys(Segs[es].value,reg_di),name2,DOSNAMEBUF);
if (DOS_Rename(name1,name2)) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x57: /* Get/Set File's Date and Time */
reg_cx=0;
reg_dx=0;
LOG_DEBUG("DOS:57:Getting/Setting File Date is faked",reg_ah);
break;
case 0x58: /* Get/Set Memory allocation strategy */
LOG_DEBUG("DOS:58:Not Supported Set//Get memory allocation");
break;
case 0x59: /* Get Extended error information */
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break;
case 0x5a: /* Create temporary file */
{
Bit16u handle;
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_CreateTempFile(name1,&handle)) {
reg_ax=handle;
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
}
break;
case 0x5b: /* Create new file */
{
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
Bit16u handle;
if (DOS_OpenFile(name1,0,&handle)) {
DOS_CloseFile(handle);
DOS_SetError(DOSERR_ACCESS_DENIED);
reg_ax=dos.errorcode;
CALLBACK_SCF(false);
break;
}
if (DOS_CreateFile(name1,reg_cx,&handle)) {
reg_ax=handle;
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
}
case 0x5c: /* FLOCK File region locking */
case 0x5d: /* Network Functions */
case 0x5e: /* More Network Functions */
case 0x5f: /* And Even More Network Functions */
E_Exit("DOS:Unhandled call %02X",reg_ah);
break;
case 0x60: /* Canonicalize filename or path */
MEM_StrCopy(real_phys(Segs[ds].value,reg_dx),name1,DOSNAMEBUF);
if (DOS_Canonicalize(name1,real_off(Segs[es].value,reg_di))) {
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
break;
case 0x62: /* Get Current PSP Address */
reg_bx=dos.psp;
break;
case 0x63: /* Weirdo double byte stuff */
reg_al=0xff;
LOG_WARN("DOS:0x63:Doubly byte characters not supported");
break;
case 0x64: /* Set device driver lookahead flag */
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break;
case 0x65: /* Get extented country information and a lot of other useless shit*/
/* Todo maybe fully support this for now we set it standard for USA */
{
LOG_DEBUG("DOS:65:Extended country information call");
Bit8u * data=real_off(Segs[es].value,reg_di);
switch (reg_al) {
case 1:
real_writeb(Segs[es].value,reg_di,reg_al);
real_writew(Segs[es].value,reg_di+1,4);
real_writew(Segs[es].value,reg_di+3,1);
real_writew(Segs[es].value,reg_di+5,37);
reg_cx=4;
CALLBACK_SCF(false);
break;
default:
E_Exit("DOS:0x65:Unhandled country information call %2X",reg_al);
};
break;
}
case 0x66: /* Get/Set global code page table */
if (reg_al==1) {
LOG_DEBUG("Getting global code page table");
reg_bx=reg_dx=437;
CALLBACK_SCF(false);
break;
}
LOG_ERROR("DOS:Setting code page table is not supported");
break;
case 0x67: /* Set handle countr */
/* Weird call to increase amount of file handles needs to allocate memory if >20 */
LOG_DEBUG("DOS:67:Set Handle Count not working");
CALLBACK_SCF(false);
break;
case 0x68: /* FFLUSH Commit file */
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break;
case 0x69: /* Get/Set disk serial number */
{
Bit8u * temp=real_off(Segs[ds].value,reg_dx);
switch(reg_al) {
case 0x00: /* Get */
LOG_DEBUG("DOS:Get Disk serial number");
CALLBACK_SCF(true);
break;
case 0x01:
LOG_DEBUG("DOS:Set Disk serial number");
default:
E_Exit("DOS:Illegal Get Serial Number call %2X",reg_al);
}
break;
}
case 0x6c: /* Extended Open/Create */
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break;
case 0x71: /* Unknown probably 4dos detection */
reg_ax=0x7100;
CALLBACK_SCF(true);
LOG_WARN("DOS:Windows long file name support call %2X",reg_al);
break;
case 0xE0:
LOG_DEBUG("DOS:E0:Unhandled, what should this call do?");
break;
default:
E_Exit("DOS:Unhandled call %02X",reg_ah);
break;
};
return CBRET_NONE;
/* That's it now let's get it working */
};
static Bitu DOS_20Handler(void) {
reg_ax=0x4c00;
DOS_21Handler();
return CBRET_NONE;
}
void DOS_Init(void) {
call_20=CALLBACK_Allocate();
CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET);
RealSetVec(0x20,CALLBACK_RealPointer(call_20));
call_21=CALLBACK_Allocate();
CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET);
RealSetVec(0x21,CALLBACK_RealPointer(call_21));
DOS_SetupFiles(); /* Setup system File tables */
DOS_SetupDevices(); /* Setup dos devices */
DOS_SetupMemory(); /* Setup first MCB */
DOS_SetupTables();
DOS_SetupPrograms();
DOS_SetupMisc(); /* Some additional dos interrupts */
DOS_SetDefaultDrive(25);
/* Execute the file that should be */
dos.version.major=5;
dos.version.minor=0;
// DOS_RunProgram(startname);
};

181
src/dos/dos_classes.cpp Normal file
View file

@ -0,0 +1,181 @@
/*
* 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 <string.h>
#include <stdlib.h>
#include "dosbox.h"
#include "mem.h"
#include "dos_inc.h"
/*
Work in progress, making classes for handling certain internal memory structures in dos
This should make it somewhat easier for porting to other endian machines and make
dos work a bit easier.
*/
struct sPSP {
Bit8u exit[2]; /* CP/M-like exit poimt */
Bit16u next_seg; /* Segment of first byte beyond memory allocated or program */
Bit8u fill_1; /* single char fill */
/* CPM Stuff dunno what this is*/
//TODO Add some checks for people using this i think
Bit8u far_call; /* far call opcode */
RealPt cpm_entry; /* CPM Service Request address*/
RealPt int_22; /* Terminate Address */
RealPt int_23; /* Break Address */
RealPt int_24; /* Critical Error Address */
Bit16u psp_parent; /* Parent PSP Segment */
Bit8u files[20]; /* File Table - 0xff is unused */
Bit16u environment; /* Segment of evironment table */
RealPt stack; /* SS:SP Save point for int 0x21 calls */
Bit16u max_files; /* Maximum open files */
RealPt file_table; /* Pointer to File Table PSP:0x18 */
RealPt prev_psp; /* Pointer to previous PSP */
RealPt dta; /* Pointer to current Process DTA */
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 fill_3[45]; /* This has some blocks with FCB info */
CommandTail cmdtail;
};
class DOS_PSP {
public:
DOS_PSP(Bit16u segment);
void MakeNew(Bit16u env,Bit16u memsize);
Bit16u base_seg;
private:
PhysPt off;
};
DOS_PSP::DOS_PSP(Bit16u segment) {
base_seg=segment;
off=Real2Phys(RealMake(segment,0));
};
void DOS_PSP::MakeNew(Bit16u env,Bit16u next_para) {
Bitu i;
for (i=0;i<256;i++) mem_writeb(off+i,0);
/* Standard blocks */
mem_writeb(off+offsetof(sPSP,exit[0]),0xcd);
mem_writeb(off+offsetof(sPSP,exit[1]),0x20);
mem_writeb(off+offsetof(sPSP,service[0]),0xcd);
mem_writeb(off+offsetof(sPSP,service[1]),0x21);
mem_writeb(off+offsetof(sPSP,service[2]),0xcb);
mem_writew(off+offsetof(sPSP,next_seg),next_para);
// mem_writew(off+offsetof(sPSP,psp_parent),dos.psp->base_seg);
/* Setup initial file table */
mem_writed(off+offsetof(sPSP,int_22),RealGetVec(0x22));
mem_writed(off+offsetof(sPSP,int_23),RealGetVec(0x23));
mem_writed(off+offsetof(sPSP,int_24),RealGetVec(0x24));
#if 0
newpsp->mem_size=prevpsp->mem_size;
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
}
void DOS_FCB::Set_drive(Bit8u a){
mem_writeb(off+offsetof(FCB,drive),a);
}
void DOS_FCB::Set_filename(char * a){
MEM_BlockWrite(off+offsetof(FCB,filename),a,8);
}
void DOS_FCB::Set_ext(char * a) {
MEM_BlockWrite(off+offsetof(FCB,ext),a,3);
}
void DOS_FCB::Set_current_block(Bit16u a){
mem_writew(off+offsetof(FCB,current_block),a);
}
void DOS_FCB::Set_record_size(Bit16u a){
mem_writew(off+offsetof(FCB,record_size),a);
}
void DOS_FCB::Set_filesize(Bit32u a){
mem_writed(off+offsetof(FCB,filesize),a);
}
void DOS_FCB::Set_date(Bit16u a){
mem_writew(off+offsetof(FCB,date),a);
}
void DOS_FCB::Set_time(Bit16u a){
mem_writew(off+offsetof(FCB,time),a);
}
Bit8u DOS_FCB::Get_drive(void){
return mem_readb(off+offsetof(FCB,drive));
}
void DOS_FCB::Get_filename(char * a){
MEM_BlockRead(off+offsetof(FCB,filename),a,8);
}
void DOS_FCB::Get_ext(char * a){
MEM_BlockRead(off+offsetof(FCB,ext),a,3);
}
Bit16u DOS_FCB::Get_current_block(void){
return mem_readw(off+offsetof(FCB,current_block));
}
Bit16u DOS_FCB::Get_record_size(void){
return mem_readw(off+offsetof(FCB,record_size));
}
Bit32u DOS_FCB::Get_filesize(void){
return mem_readd(off+offsetof(FCB,filesize));
}
Bit16u DOS_FCB::Get_date(void){
return mem_readw(off+offsetof(FCB,date));
}
Bit16u DOS_FCB::Get_time(void){
return mem_readw(off+offsetof(FCB,time));
}

77
src/dos/dos_devices.cpp Normal file
View file

@ -0,0 +1,77 @@
/*
* 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 <string.h>
#include "dosbox.h"
#include "callback.h"
#include "cpu.h"
#include "mem.h"
#include "bios.h"
#include "dos_inc.h"
#include "support.h"
#define MAX_DEVICES 10
/* Include all the devices */
#include "dev_con.h"
static DOS_Device * devices[MAX_DEVICES];
static Bit32u device_count;
Bit8u DOS_FindDevice(char * name) {
/* loop through devices */
Bit8u index=0;
while (index<device_count) {
if (devices[index]) {
if (strcasecmp(name,devices[index]->name)==0) return index;
}
index++;
}
return 255;
}
void DOS_AddDevice(DOS_Device * adddev) {
//TODO Give the Device a real handler in low memory that responds to calls
if (device_count<MAX_DEVICES) {
devices[device_count]=adddev;
device_count++;
/* Add the device in the main file Table */
Bit8u handle=DOS_FILES;Bit8u i;
for (i=0;i<DOS_FILES;i++) {
if (!Files[i]) {
handle=i;
Files[i]=adddev;
break;
}
}
if (handle==DOS_FILES) E_Exit("DOS:Not enough file handles for device");
adddev->fhandle=handle;
} else {
E_Exit("DOS:Too many devices added");
}
}
void DOS_SetupDevices(void) {
device_count=0;
DOS_Device * newdev;
newdev=new device_CON();
DOS_AddDevice(newdev);
}

439
src/dos/dos_execute.cpp Normal file
View file

@ -0,0 +1,439 @@
/*
* 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 <string.h>
#include "dosbox.h"
#include "mem.h"
#include "dos_inc.h"
#include "cpu.h"
#pragma pack(1)
struct EXE_Header {
Bit16u signature; /* EXE Signature MZ or ZM */
Bit16u extrabytes; /* Bytes on the last page */
Bit16u pages; /* Pages in file */
Bit16u relocations; /* Relocations in file */
Bit16u headersize; /* Paragraphs in header */
Bit16u minmemory; /* Minimum amount of memory */
Bit16u maxmemory; /* Maximum amount of memory */
Bit16u initSS;
Bit16u initSP;
Bit16u checksum;
Bit16u initIP;
Bit16u initCS;
Bit16u reloctable;
Bit16u overlay;
};
#pragma pack()
#define MAGIC1 0x5a4d
#define MAGIC2 0x4d5a
#define MAXENV 32768u
#define ENV_KEEPFREE 83 /* keep unallocated by environment variables */
/* The '65' added to nEnvSize does not cover the additional stuff:
+ 2 bytes: number of strings
+ 80 bytes: maximum absolute filename
+ 1 byte: '\0'
-- 1999/04/21 ska */
#define LOADNGO 0
#define LOAD 1
#define OVERLAY 3
bool DOS_Terminate(bool tsr) {
PSP * psp=(PSP *)real_off(dos.psp,0);
if (!tsr) {
/* Free Files owned by process */
for (Bit16u i=0;i<psp->max_files;i++) {
DOS_CloseFile(i);
}
DOS_FreeProcessMemory(dos.psp);
};
dos.psp=psp->psp_parent;
PSP * oldpsp=(PSP *)real_off(dos.psp,0);
/* Restore the DTA */
dos.dta=psp->dta;
/* Restore the old CS:IP from int 22h */
RealPt old22;
old22=RealGetVec(0x22);
SetSegment_16(cs,RealSeg(old22));
reg_ip=RealOff(old22);
/* Restore the SS:SP to the previous one */
SetSegment_16(ss,RealSeg(oldpsp->stack));
reg_sp=RealOff(oldpsp->stack);
/* Restore interrupt 22,23,24 */
RealSetVec(0x22,psp->int_22);
RealSetVec(0x23,psp->int_23);
RealSetVec(0x24,psp->int_24);
return true;
}
static bool MakeEnv(char * name,Bit16u * segment) {
/* If segment to copy environment is 0 copy the caller's environment */
PSP * psp=(PSP *)real_off(dos.psp,0);
Bit8u * envread,*envwrite;
Bit16u envsize=1;
bool parentenv=true;
if (*segment==0) {
if (!psp->environment) parentenv=false; //environment seg=0
envread=real_off(psp->environment,0);
} else {
if (!*segment) parentenv=false; //environment seg=0
envread=real_off(*segment,0);
}
//TODO Make a good DOS first psp
if (parentenv) {
for (envsize=0; ;envsize++) {
if (envsize>=MAXENV - ENV_KEEPFREE) {
DOS_SetError(DOSERR_ENVIRONMENT_INVALID);
return false;
}
if (readw(envread+envsize)==0) break;
}
envsize += 2; /* account for trailing \0\0 */
}
Bit16u size=long2para(envsize+ENV_KEEPFREE);
if (!DOS_AllocateMemory(segment,&size)) return false;
envwrite=real_off(*segment,0);
if (parentenv) {
bmemcpy(envwrite,envread,envsize);
envwrite+=envsize;
} else {
*envwrite++=0;
}
*((Bit16u *) envwrite)=1;
envwrite+=2;
//TODO put the filename here
return DOS_Canonicalize(name,envwrite);
};
bool DOS_NewPSP(Bit16u pspseg) {
PSP * newpsp=(PSP *)real_off(pspseg,0);
PSP * prevpsp=(PSP *)real_off(dos.psp,0);
memset((void *)newpsp,0,sizeof(PSP));
newpsp->exit[0]=0xcd;newpsp->exit[1]=0x20;
newpsp->service[0]=0xcd;newpsp->service[0]=0x21;newpsp->service[0]=0xcb;
newpsp->mem_size=prevpsp->mem_size;
newpsp->environment=0;
newpsp->int_22=RealGetVec(0x22);
newpsp->int_23=RealGetVec(0x23);
newpsp->int_24=RealGetVec(0x24);
newpsp->psp_parent=dos.psp;
newpsp->prev_psp=0xFFFFFFFF;
Bit32u i;
Bit8u * prevfile=Real2Host(prevpsp->file_table);
for (i=0;i<20;i++) newpsp->files[i]=prevfile[i];
newpsp->max_files=20;
newpsp->file_table=RealMake(pspseg,offsetof(PSP,files));
/* Save the old DTA in this psp */
newpsp->dta=dos.dta;
/* Setup the DTA */
dos.dta=RealMake(pspseg,0x80);
return true;
};
static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
PSP * psp=(PSP *)real_off(pspseg,0);
/* Fix the PSP index of this MCB */
MCB * pspmcb=(MCB *)real_off(pspseg-1,0);
pspmcb->psp_segment=pspseg;
MCB * envmcb=(MCB *)real_off(envseg-1,0);
envmcb->psp_segment=pspseg;
memset((void *)psp,0,sizeof(PSP));
Bit32u i;
psp->exit[0]=0xcd;psp->exit[1]=0x20;
psp->mem_size=memsize+pspseg;
psp->environment=envseg;
psp->int_22=RealGetVec(0x22);
psp->int_23=RealGetVec(0x23);
psp->int_24=RealGetVec(0x24);
psp->service[0]=0xcd;psp->service[0]=0x21;psp->service[0]=0xcb;
psp->psp_parent=dos.psp;
psp->prev_psp=RealMake(dos.psp,0);
for (i=0;i<20;i++) psp->files[i]=0xff;
psp->files[STDIN]=DOS_FindDevice("CON");
psp->files[STDOUT]=DOS_FindDevice("CON");
psp->files[STDERR]=DOS_FindDevice("CON");
psp->files[STDAUX]=DOS_FindDevice("CON");
psp->files[STDNUL]=DOS_FindDevice("CON");
psp->files[STDPRN]=DOS_FindDevice("CON");
psp->max_files=20;
psp->file_table=RealMake(pspseg,offsetof(PSP,files));
/* Save old DTA in psp */
psp->dta=dos.dta;
/* Setup the DTA */
dos.dta=RealMake(pspseg,0x80);
}
static void SetupCMDLine(Bit16u pspseg,ParamBlock * block) {
PSP * psp=(PSP *)real_off(pspseg,0);
if (block->exec.cmdtail) {
memcpy((void *)&psp->cmdtail,(void *)Real2Host(block->exec.cmdtail),128);
} else {
char temp[]="";
psp->cmdtail.count=strlen(temp);
strcpy((char *)&psp->cmdtail.buffer,temp);
psp->cmdtail.buffer[0]=0x0d;
}
}
static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) {
Bit16u fhandle;
Bit16u size;Bit16u readsize;
Bit16u envseg,comseg;
Bit32u pos;
PSP * callpsp=(PSP *)real_off(dos.psp,0);
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
if (flag!=OVERLAY) {
/* Allocate a new Environment */
envseg=block->exec.envseg;
if (!MakeEnv(name,&envseg)) return false;
/* Allocate max memory for COM file and PSP */
size=0xffff;
DOS_AllocateMemory(&comseg,&size);
//TODO Errors check for minimun of 64kb in pages
if (Bit32u(size <<4)<0x1000) {
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
}
DOS_AllocateMemory(&comseg,&size);
} else {
comseg=block->overlay.loadseg;
}
/* Memory allocated now load the program */
/* Now copy the File into allocated memory */
pos=0;
DOS_SeekFile(fhandle,&pos,0);
readsize=0xffff-256;
if (flag==OVERLAY) {
DOS_ReadFile(fhandle,real_host(comseg,0),&readsize);
} else {
DOS_ReadFile(fhandle,real_host(comseg,256),&readsize);
}
DOS_CloseFile(fhandle);
if (flag==OVERLAY) /* Everything what should be done for Overlays */
return true;
SetupPSP(comseg,size,envseg);
SetupCMDLine(comseg,block);
/* Setup termination Address */
RealSetVec(0x22,RealMake(Segs[cs].value,reg_ip));
/* Everything setup somewhat setup CS:IP and SS:SP */
/* First save the SS:SP of program that called execute */
callpsp->stack=RealMake(Segs[ss].value,reg_sp);
/* Clear out first Stack entry to point to int 20h at psp:0 */
real_writew(comseg,0xfffe,0);
dos.psp=comseg;
switch (flag) {
case LOADNGO:
SetSegment_16(cs,comseg);
SetSegment_16(ss,comseg);
SetSegment_16(ds,comseg);
SetSegment_16(es,comseg);
flags.intf=true;
reg_ip=0x100;
reg_sp=0xFFFE;
reg_ax=0;
reg_bx=reg_cx=reg_dx=reg_si=reg_di=reg_bp=0;
return true;
case LOAD:
block->exec.initsssp=RealMake(comseg,0xfffe);
block->exec.initcsip=RealMake(comseg,0x100);
return true;
}
return false;
}
static bool EXE_Load(char * name,ParamBlock * block,Bit8u flag) {
EXE_Header header;
Bit16u fhandle;Bit32u i;
Bit16u size,minsize,maxsize,freesize;Bit16u readsize;
Bit16u envseg,pspseg,exeseg;
Bit32u imagesize,headersize;
PSP * callpsp=(PSP *)real_off(dos.psp,0);
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
if (flag!=OVERLAY) {
/* Allocate a new Environment */
envseg=block->exec.envseg;
if (!MakeEnv(name,&envseg)) return false;
};
/* First Read the EXE Header */
readsize=sizeof(EXE_Header);
DOS_ReadFile(fhandle,(Bit8u*)&header,&readsize);
/* Calculate the size of the image to load */
headersize=header.headersize*16;
imagesize=header.pages*512-headersize;
if (flag!=OVERLAY) {
minsize=long2para(imagesize+(header.minmemory<<4)+256);
if (header.maxmemory!=0) maxsize=long2para(imagesize+(header.maxmemory<<4)+256);
else maxsize=0xffff;
freesize=0xffff;
/* Check for enough free memory */
DOS_AllocateMemory(&exeseg,&freesize);
if (minsize>freesize) {
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
}
if (maxsize>freesize) {
size=freesize;
} else size=maxsize;
if ((header.minmemory|header.maxmemory)==0) {
size=freesize;
E_Exit("Special case exe header max and min=0");
}
if (!DOS_AllocateMemory(&pspseg,&size)) {
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
}
SetupPSP(pspseg,size,envseg);
SetupCMDLine(pspseg,block);
exeseg=pspseg+16;
} else {
/* For OVERLAY */
exeseg=block->overlay.loadseg;
}
/* Load the image in 32k blocks */
DOS_SeekFile(fhandle,&headersize,0);
Bit8u * imageoff=real_off(exeseg,0);
//TODO File size checking and remove size
// Remove psp size
// imagesize=256;
// Maybe remove final page and add last bytes on page
if (header.extrabytes) {
imagesize-=512;
imagesize+=header.extrabytes;
};
while (imagesize>0x7FFF) {
readsize=0x8000;
DOS_ReadFile(fhandle,imageoff,&readsize);
if (readsize!=0x8000) {
E_Exit("Illegal header");
}
imageoff+=0x8000;
imagesize-=0x8000;
}
if (imagesize>0) {
readsize=(Bit16u) imagesize;
DOS_ReadFile(fhandle,imageoff,&readsize);
}
headersize=header.reloctable;
DOS_SeekFile(fhandle,&headersize,0);
RealPt reloc;
for (i=0;i<header.relocations;i++) {
readsize=4;
DOS_ReadFile(fhandle,(Bit8u *)&reloc,&readsize);
PhysPt address=Real2Phys(RealMake(RealSeg(reloc)+exeseg,RealOff(reloc)));
Bit16u change=mem_readw(address);
if (flag==OVERLAY) {
change+=block->overlay.relocation;
} else {
change+=exeseg;
};
mem_writew(address,change);
};
DOS_CloseFile(fhandle);
if (flag==OVERLAY) return true;
/* Setup termination Address */
RealSetVec(0x22,RealMake(Segs[cs].value,reg_ip));
/* Start up the actual EXE if we need to */
//TODO check for load and return
callpsp->stack=RealMake(Segs[ss].value,reg_sp);
dos.psp=pspseg;
SetSegment_16(cs,exeseg+header.initCS);
SetSegment_16(ss,exeseg+header.initSS);
SetSegment_16(ds,pspseg);
SetSegment_16(es,pspseg);
reg_ip=header.initIP;
reg_sp=header.initSP;
reg_ax=0;
reg_bx=reg_cx=reg_dx=reg_si=reg_di=reg_bp=0;
flags.intf=true;
return true;
};
bool DOS_Execute(char * name,ParamBlock * block,Bit8u flags) {
EXE_Header head;
Bit16u fhandle;
Bit16u size;
bool iscom=false;
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
size=sizeof(EXE_Header);
if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&size)) {
DOS_CloseFile(fhandle);
return false;
}
if (!DOS_CloseFile(fhandle)) return false;
if (size<sizeof(EXE_Header)) iscom=true;
if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true;
if (iscom) {
return COM_Load(name,block,flags);
} else {
return EXE_Load(name,block,flags);
}
}

614
src/dos/dos_files.cpp Normal file
View file

@ -0,0 +1,614 @@
/*
* 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 <string.h>
#include <stdlib.h>
#include "dosbox.h"
#include "mem.h"
#include "cpu.h"
#include "dos_inc.h"
#include "drives.h"
#define DOS_FILESTART 4
DOS_File * Files[DOS_FILES];
DOS_Drive * Drives[DOS_DRIVES];
static Bit8u CurrentDrive=2; //Init on C:
Bit8u DOS_GetDefaultDrive(void) {
return CurrentDrive;
}
void DOS_SetDefaultDrive(Bit8u drive) {
CurrentDrive=drive;
}
bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
//TODO Hope this is ok :)
char upname[DOS_PATHLENGTH];
Bit32u r=0;Bit32u w=0;Bit32u namestart=0;
bool hasdrive=false;
*drive=CurrentDrive;
char tempdir[DOS_NAMELENGTH];
//TODO Maybe check for illegal characters
while (name[r]!=0 && (r<DOS_PATHLENGTH)) {
Bit8u c=name[r++];
if ((c>='a') && (c<='z')) {upname[w++]=c-32;continue;}
if ((c>='A') && (c<='Z')) {upname[w++]=c;continue;}
if ((c>='0') && (c<='9')) {upname[w++]=c;continue;}
switch (c) {
case ':':
if (hasdrive) { DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; }
else hasdrive=true;
if ((upname[0]>='A') && (upname[0]<='Z')) {
*drive=upname[0]-'A';
w=0;
} else {
DOS_SetError(DOSERR_PATH_NOT_FOUND);return false;
}
break;
case '/':
upname[w++]='\\';
break;
case ' ':
break;
case '\\': case '$': case '#': case '@': case '(': case ')':
case '!': case '%': case '{': case '}': case '`': case '~':
case '_': case '-': case '.': case '*': case '?': case '&':
upname[w++]=c;
break;
default:
DOS_SetError(DOSERR_PATH_NOT_FOUND);return false;
break;
}
}
upname[w]=0;
/* This should get us an upcase filename and no incorrect chars */
/* Now parse the new file name to make the final filename */
if ((*drive>=26)) {
DOS_SetError(DOSERR_INVALID_DRIVE);return false;
};
if (!Drives[*drive]) {
DOS_SetError(DOSERR_INVALID_DRIVE);return false;
};
if (upname[0]!='\\') strcpy(fullname,Drives[*drive]->curdir);
else fullname[0]=0;
Bit32u lastdir=0;Bit32u t=0;
while (fullname[t]!=0) {
if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t;
t++;
};
r=0;w=0;
tempdir[0]=0;
bool stop=false;
while (!stop) {
if (upname[r]==0) stop=true;
if ((upname[r]=='\\') || (upname[r]==0)){
tempdir[w]=0;
if (tempdir[0]==0) { w=0;r++;continue;}
if (strcmp(tempdir,".")==0) {
tempdir[0]=0;
w=0;r++;
continue;
}
if (strcmp(tempdir,"..")==0) {
fullname[lastdir]=0;
Bit32u t=0;lastdir=0;
while (fullname[t]!=0) {
if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t;
t++;
}
tempdir[0]=0;
w=0;r++;
continue;
}
lastdir=strlen(fullname);
//TODO Maybe another check for correct type because of .... stuff
if (lastdir!=0) strcat(fullname,"\\");
strcat(fullname,tempdir);
tempdir[0]=0;
w=0;r++;
continue;
}
tempdir[w++]=upname[r++];
}
return true;
}
bool DOS_GetCurrentDir(Bit8u drive,Bit8u * buffer) {
if (drive==0) drive=DOS_GetDefaultDrive();
else drive--;
if ((drive>DOS_DRIVES) || (!Drives[drive])) {
DOS_SetError(DOSERR_INVALID_DRIVE);
return false;
}
strcpy((char *) buffer,Drives[drive]->curdir);
return true;
}
bool DOS_ChangeDir(char * dir) {
Bit8u drive;char fulldir[DOS_PATHLENGTH];
if (!DOS_MakeName(dir,fulldir,&drive)) return false;
if (Drives[drive]->TestDir(fulldir)) {
strcpy(Drives[drive]->curdir,fulldir);
return true;
} else {
DOS_SetError(DOSERR_PATH_NOT_FOUND);
}
return false;
}
bool DOS_MakeDir(char * dir) {
Bit8u drive;char fulldir[DOS_PATHLENGTH];
if (!DOS_MakeName(dir,fulldir,&drive)) return false;
return Drives[drive]->MakeDir(fulldir);
}
bool DOS_RemoveDir(char * dir) {
Bit8u drive;char fulldir[DOS_PATHLENGTH];
if (!DOS_MakeName(dir,fulldir,&drive)) return false;
return Drives[drive]->RemoveDir(fulldir);
}
bool DOS_Rename(char * oldname,char * newname) {
Bit8u driveold;char fullold[DOS_PATHLENGTH];
Bit8u drivenew;char fullnew[DOS_PATHLENGTH];
if (!DOS_MakeName(oldname,fullold,&driveold)) return false;
if (!DOS_MakeName(newname,fullnew,&drivenew)) return false;
//TODO Test for different drives maybe
if (Drives[drivenew]->Rename(fullold,fullnew)) return true;
DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false;
};
bool DOS_FindFirst(char * search,Bit16u attr) {
Bit8u drive;char fullsearch[DOS_PATHLENGTH];
if (!DOS_MakeName(search,fullsearch,&drive)) return false;
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
dtablock->sattr=attr | DOS_ATTR_ARCHIVE;
dtablock->sdrive=drive;
return Drives[drive]->FindFirst(fullsearch,dtablock);
};
bool DOS_FindNext(void) {
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
return Drives[dtablock->sdrive]->FindNext(dtablock);
};
bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount) {
Bit32u handle=RealHandle(entry);
if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
if (!Files[handle]) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
//TODO maybe another code :)
/*
if (!(Files[handle]->flags & OPEN_READ)) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
}
*/
Bit16u toread=*amount;
bool ret=Files[handle]->Read(data,&toread);
*amount=toread;
return ret;
};
bool DOS_WriteFile(Bit16u entry,Bit8u * data,Bit16u * amount) {
Bit32u handle=RealHandle(entry);
if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
if (!Files[handle]) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
//TODO maybe another code :)
/*
if (!(Files[handle]->flags & OPEN_WRITE)) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
}
*/
Bit16u towrite=*amount;
bool ret=Files[handle]->Write(data,&towrite);
*amount=towrite;
return ret;
};
bool DOS_SeekFile(Bit16u entry,Bit32u * pos,Bit32u type) {
Bit32u handle=RealHandle(entry);
if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
if (!Files[handle]) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
return Files[handle]->Seek(pos,type);
};
bool DOS_CloseFile(Bit16u entry) {
Bit32u handle=RealHandle(entry);
if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
if (!Files[handle]) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
//TODO Figure this out with devices :)
PSP * psp=(PSP *)real_off(dos.psp,0);
Bit8u * table=Real2Host(psp->file_table);
table[entry]=0xFF;
/* Devices won't allow themselves to be closed or killed */
if (Files[handle]->Close()) {
delete Files[handle];
Files[handle]=0;
}
return true;
}
bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
char fullname[DOS_PATHLENGTH];Bit8u drive;
PSP * psp=(PSP *)real_off(dos.psp,0);
if (!DOS_MakeName(name,fullname,&drive)) return false;
/* Check for a free file handle */
Bit8u handle=DOS_FILES;Bit8u i;
for (i=0;i<DOS_FILES;i++) {
if (!Files[i]) {
handle=i;
break;
}
}
if (handle==DOS_FILES) {
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
return false;
}
/* We have a position in the main table now find one in the psp table */
Bit8u * table=Real2Host(psp->file_table);
*entry=0xff;
for (i=0;i<psp->max_files;i++) {
if (table[i]==0xFF) {
*entry=i;
break;
}
}
if (*entry==0xff) {
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
return false;
}
bool foundit=Drives[drive]->FileCreate(&Files[handle],fullname,attributes);
if (foundit) {
table[*entry]=handle;
return true;
} else {
return false;
}
}
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
/* First check for devices */
PSP * psp=(PSP *)real_off(dos.psp,0);
Bit8u handle=DOS_FindDevice((char *)name);
bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i;
if (handle!=255) {
device=true;
} else {
/* First check if the name is correct */
if (!DOS_MakeName(name,fullname,&drive)) return false;
/* Check for a free file handle */
for (i=0;i<DOS_FILES;i++) {
if (!Files[i]) {
handle=i;
break;
}
}
if (handle==255) {
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
return false;
}
}
/* We have a position in the main table now find one in the psp table */
Bit8u * table=Real2Host(psp->file_table);
*entry=0xff;
for (i=0;i<psp->max_files;i++) {
if (table[i]==0xFF) {
*entry=i;
break;
}
}
if (*entry==0xff) {
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
return false;
}
bool exists=false;
if (!device) exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags);
if (exists || device ) {
table[*entry]=handle;
return true;
} else {
DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false;
}
}
bool DOS_UnlinkFile(char * name) {
char fullname[DOS_PATHLENGTH];Bit8u drive;
if (!DOS_MakeName(name,fullname,&drive)) return false;
return Drives[drive]->FileUnlink(fullname);
}
bool DOS_GetFileAttr(char * name,Bit16u * attr) {
char fullname[DOS_PATHLENGTH];Bit8u drive;
if (!DOS_MakeName(name,fullname,&drive)) return false;
if (Drives[drive]->GetFileAttr(fullname,attr)) {
return true;
} else {
DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false;
}
}
bool DOS_Canonicalize(char * name,Bit8u * big) {
//TODO Add Better support for devices and shit but will it be needed i doubt it :)
Bit8u drive;
char fullname[DOS_PATHLENGTH];
if (!DOS_MakeName(name,fullname,&drive)) return false;
big[0]=drive+'A';
big[1]=':';
big[2]='\\';
strcpy((char *)&big[3],fullname);
return true;
};
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) {
if (drive==0) drive=DOS_GetDefaultDrive();
else drive--;
if ((drive>DOS_DRIVES) || (!Drives[drive])) {
DOS_SetError(DOSERR_INVALID_DRIVE);
return false;
}
return Drives[drive]->FreeSpace(bytes,sectors,clusters,free);
}
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) {
Bit8u handle=RealHandle(entry);
if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
if (!Files[handle]) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
PSP * psp=(PSP *)real_off(dos.psp,0);
Bit8u * table=Real2Host(psp->file_table);
*newentry=0xff;
for (Bit16u i=0;i<psp->max_files;i++) {
if (table[i]==0xFF) {
*newentry=i;
break;
}
}
if (*newentry==0xff) {
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
return false;
}
table[*newentry]=handle;
return true;
};
bool DOS_CreateTempFile(char * name,Bit16u * entry) {
/* First add random crap to the end of the name and try to open */
/* Todo maybe check for euhm existence of the path name */
char * tempname;
tempname=name+strlen(name);
do {
Bit32u i;
for (i=0;i<8;i++) {
tempname[i]=(rand()%26)+'A';
}
tempname[8]='.';
for (i=9;i<12;i++) {
tempname[i]=(rand()%26)+'A';
}
tempname[13]=0;
} while (!DOS_CreateFile(name,0,entry));
return true;
}
#if 0
void FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){
char naam[15];
Bit8u drive=fcb->Get_drive();
if(drive!=0){
naam[0]=(drive-1)+'A';
naam[1]=':';
naam[2]='\0';}
else{
naam[0]='\0';
};
char temp[9];
fcb->Get_filename(temp);
temp[9]='.';
strncat(naam,temp,9);
char ext[3];
fcb->Get_ext(ext);
if(drive!=0) {
strncat(&naam[11],ext,3);
naam[14]='\0';
}else{
strncat(&naam[9],ext,3);
naam[12]='\0';
};
DOS_MakeName(naam,outname, outdrive);
return;
}
bool DOS_FCBOpen(Bit16u seg,Bit16u offset) {
DOS_FCB fcb(seg,offset);
Bit8u drive;
char fullname[DOS_PATHLENGTH];
FCB_MakeName (&fcb, fullname, &drive);
if(DOS_FileExists(fullname)==false) return false;
struct stat stat_block;
stat(fullname, &stat_block);
fcb.Set_filesize((Bit32u)stat_block.st_size);
Bit16u constant =0;
fcb.Set_current_block(constant);
constant=0x80;
fcb.Set_record_size(constant);
struct tm *time;
time=localtime(&stat_block.st_mtime);
constant=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */
fcb->Set_time(constant);
constant=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
fcb->Set_date(constant);
fcb->Set_drive(drive +1);
return true;
}
bool FCB_Close(void)
{ return true;}
bool FCB_FindFirst(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[drive]->FindFirst(fullname,dtablock)==false) return false;
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;
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;
}
#endif
bool DOS_FileExists(char * name) {
Bit16u handle;
if (DOS_OpenFile(name,0,&handle)) {
DOS_CloseFile(handle);
return true;
}
return false;
}
bool DOS_SetDrive(Bit8u drive) {
if (Drives[drive]) {
DOS_SetDefaultDrive(drive);
return true;
} else {
return false;
}
};
void DOS_SetupFiles (void) {
/* Setup the File Handles */
Bit32u i;
for (i=0;i<DOS_FILES;i++) {
Files[i]=0;
}
/* Setup the Virtual Disk System */
for (i=0;i<DOS_DRIVES;i++) {
Drives[i]=0;
}
Drives[25]=new Virtual_Drive();
}

60
src/dos/dos_ioctl.cpp Normal file
View file

@ -0,0 +1,60 @@
/*
* 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 <string.h>
#include "dosbox.h"
#include "callback.h"
#include "mem.h"
#include "cpu.h"
#include "dos_inc.h"
#define MAX_DEVICE 20
static DOS_File * dos_devices[MAX_DEVICE];
bool DOS_IOCTL(Bit8u call,Bit16u entry) {
Bit32u handle=RealHandle(entry);
if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
if (!Files[handle]) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
switch(reg_al) {
case 0x00: /* Get Device Information */
reg_dx=Files[handle]->GetInformation();
return true;
case 0x07: /* Get Output Status */
LOG_DEBUG("DOS:IOCTL:07:Fakes output status is ready for handle %d",handle);
reg_al=0xff;
return true;
default:
LOG_ERROR("DOS:IOCTL Call %2X Handle %2X unhandled",reg_al,handle);
return false;
};
return false;
};
bool DOS_GetSTDINStatus(void) {
Bit32u handle=RealHandle(STDIN);
if (Files[handle]->GetInformation() & 64) return false;
return true;
};

162
src/dos/dos_memory.cpp Normal file
View 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.
*/
#include "dosbox.h"
#include "mem.h"
#include "dos_inc.h"
#define MEM_START 0x60 //First Segment that DOS can use
//#define MEM_START 4000 //First Segment that DOS can use
static void DOS_CompressMemory(void) {
MCB * pmcb;MCB * pmcbnext;
Bit16u mcb_segment;
mcb_segment=dos.firstMCB;
pmcb=(MCB *)real_off(mcb_segment,0);
while (pmcb->type!=0x5a) {
pmcbnext=pmcbnext=(MCB *)real_off(mcb_segment+pmcb->size+1,0);
if ((pmcb->psp_segment==0) && (pmcbnext->psp_segment==0)) {
pmcb->size+=pmcbnext->size+1;
pmcb->type=pmcbnext->type;
} else {
mcb_segment+=pmcb->size+1;
pmcb=(MCB *)real_off(mcb_segment,0);
}
}
}
void DOS_FreeProcessMemory(Bit16u pspseg) {
MCB * pmcb;
Bit16u mcb_segment=dos.firstMCB;
pmcb=(MCB *)real_off(mcb_segment,0);
while (true) {
if (pmcb->psp_segment==pspseg) {
pmcb->psp_segment=MCB_FREE;
}
mcb_segment+=pmcb->size+1;
if (pmcb->type==0x5a) break;
pmcb=(MCB *)real_off(mcb_segment,0);
}
DOS_CompressMemory();
};
bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
MCB * pmcb;MCB * pmcbnext;
Bit16u bigsize=0;Bit16u mcb_segment;
bool stop=false;mcb_segment=dos.firstMCB;
DOS_CompressMemory();
while(!stop) {
pmcb=(MCB *)real_off(mcb_segment,0);
if (pmcb->psp_segment==0) {
/* Check for enough free memory in current block */
if (pmcb->size<(*blocks)) {
if (bigsize<pmcb->size) {
bigsize=pmcb->size;
}
} else if (pmcb->size==*blocks) {
pmcb->psp_segment=dos.psp;
*segment=mcb_segment+1;
return true;
} else {
/* If so allocate it */
pmcbnext=(MCB *)real_off(mcb_segment+*blocks+1,0);
pmcbnext->psp_segment=MCB_FREE;
pmcbnext->type=pmcb->type;
pmcbnext->size=pmcb->size-*blocks-1;
pmcb->size=*blocks;
pmcb->type=0x4D;
pmcb->psp_segment=dos.psp;
//TODO Filename
*segment=mcb_segment+1;
return true;
}
}
/* Onward to the next MCB if there is one */
if (pmcb->type==0x5a) {
*blocks=bigsize;
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
return false;
}
mcb_segment+=pmcb->size+1;
}
return false;
};
bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
DOS_CompressMemory();
MCB * pmcb,* pmcbnext,* pmcbnew;
pmcb=(MCB *)real_off(segment-1,0);
pmcbnext=(MCB *)real_off(segment+pmcb->size,0);
Bit16u total=pmcb->size;
if (pmcb->type!=0x5a) {
if (pmcbnext->psp_segment==MCB_FREE) {
total+=pmcbnext->size+1;
}
};
if (*blocks<total) {
if (pmcb->type!=0x5a) {
pmcb->type=pmcbnext->type;
}
pmcb->size=*blocks;
pmcbnew=(MCB *)real_off(segment+*blocks,0);
pmcbnew->size=total-*blocks-1;
pmcbnew->type=pmcb->type;
pmcbnew->psp_segment=MCB_FREE;
pmcb->type=0x4D;
return true;
}
if (*blocks==total) {
if (pmcb->type!=0x5a) {
pmcb->type=pmcbnext->type;
}
pmcb->size=*blocks;
return true;
}
*blocks=total;
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
return false;
};
bool DOS_FreeMemory(Bit16u segment) {
//TODO Check if allowed to free this segment
MCB * pmcb;
pmcb=(MCB *)real_off(segment-1,0);
pmcb->psp_segment=MCB_FREE;
DOS_CompressMemory();
return true;
}
void DOS_SetupMemory(void) {
//TODO Maybe allocate some memory for dos transfer buffers
//Although i could use bios regions for that for max free low memory
MCB * mcb=(MCB *) real_off(MEM_START,0);
mcb->psp_segment=MCB_FREE; //Free
mcb->size=0x9FFE - MEM_START;
mcb->type=0x5a; //Last Block
dos.firstMCB=MEM_START;
}

69
src/dos/dos_misc.cpp Normal file
View file

@ -0,0 +1,69 @@
/*
* 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 "callback.h"
#include "mem.h"
#include "regs.h"
#include "dos_inc.h"
static Bitu call_int2f,call_int2a;
struct MultiplexBlock {
MultiplexHandler * handler;
MultiplexBlock * next;
};
static MultiplexBlock * first_multiplex;
void DOS_AddMultiplexHandler(MultiplexHandler * handler) {
MultiplexBlock * new_multiplex=new(MultiplexBlock);
new_multiplex->next=first_multiplex;
new_multiplex->handler=handler;
first_multiplex=new_multiplex;
}
static Bitu INT2F_Handler(void) {
MultiplexBlock * loop_multiplex=first_multiplex;
while (loop_multiplex) {
if ((*loop_multiplex->handler)()) return CBRET_NONE;
loop_multiplex=loop_multiplex->next;
}
LOG_WARN("DOS:Multiplex Unhandled call %4X",reg_ax);
return CBRET_NONE;
};
static Bitu INT2A_Handler(void) {
return CBRET_NONE;
};
void DOS_SetupMisc(void) {
/* Setup the dos multiplex interrupt */
first_multiplex=0;
call_int2f=CALLBACK_Allocate();
CALLBACK_Setup(call_int2f,&INT2F_Handler,CB_IRET);
RealSetVec(0x2f,CALLBACK_RealPointer(call_int2f));
/* Setup the dos network interrupt */
call_int2a=CALLBACK_Allocate();
CALLBACK_Setup(call_int2a,&INT2A_Handler,CB_IRET);
RealSetVec(0x2A<<2,CALLBACK_RealPointer(call_int2a));
};

210
src/dos/dos_programs.cpp Normal file
View file

@ -0,0 +1,210 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "programs.h"
#include "support.h"
#include "drives.h"
#include "cross.h"
class MOUNT : public Program {
public:
MOUNT(PROGRAM_Info * program_info);
void Run(void);
};
MOUNT::MOUNT(PROGRAM_Info * info):Program(info) {
}
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;
}
char drive;
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) {
WriteOut("Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n");
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);
}
static void MOUNT_ProgramStart(PROGRAM_Info * info) {
MOUNT * tempmount=new MOUNT(info);
tempmount->Run();
delete tempmount;
}
class MEM : public Program {
public:
MEM(PROGRAM_Info * program_info);
void Run(void);
};
MEM::MEM(PROGRAM_Info * info):Program(info) {
}
void MEM::Run(void) {
}
static void MEM_ProgramStart(PROGRAM_Info * info) {
MEM mem(info);
mem.Run();
}
#if !defined (WIN32) /* Unix */
class UPCASE : public Program {
public:
UPCASE(PROGRAM_Info * program_info);
void Run(void);
void upcasedir(char * directory);
};
UPCASE::UPCASE(PROGRAM_Info * info):Program(info) {
}
void UPCASE::upcasedir(char * directory) {
DIR * sdir;
char fullname[512];
char newname[512];
struct dirent *tempdata;
struct stat finfo;
if(!(sdir=opendir(directory))) {
WriteOut("Failed to open directory %s\n",directory);
return;
}
WriteOut("Scanning directory %s\n",fullname);
while (tempdata=readdir(sdir)) {
if (strcmp(tempdata->d_name,".")==0) continue;
if (strcmp(tempdata->d_name,"..")==0) continue;
strcpy(fullname,directory);
strcat(fullname,"/");
strcat(fullname,tempdata->d_name);
strcpy(newname,directory);
strcat(newname,"/");
upcase(tempdata->d_name);
strcat(newname,tempdata->d_name);
WriteOut("Renaming %s to %s\n",fullname,newname);
rename(fullname,newname);
stat(fullname,&finfo);
if(S_ISDIR(finfo.st_mode)) {
upcasedir(fullname);
}
}
closedir(sdir);
}
void UPCASE::Run(void) {
/* First check if the directory exists */
struct stat info;
WriteOut("UPCASE 0.1 Directory case convertor.\n");
if (!strlen(prog_info->cmd_line)) {
WriteOut("Usage UPCASE [local directory]\n");
WriteOut("This tool will convert all files and subdirectories in a directory.\n");
WriteOut("Be VERY sure this directory contains only dos related material.\n");
WriteOut("Otherwise you might horribly screw up your filesystem.\n");
return;
}
if (stat(prog_info->cmd_line,&info)) {
WriteOut("%s doesn't exist\n",prog_info->cmd_line);
return;
}
if(!S_ISDIR(info.st_mode)) {
WriteOut("%s isn't a directory\n",prog_info->cmd_line);
return;
}
WriteOut("Converting the wrong directories can be very harmfull, please be carefull.\n");
WriteOut("Are you really really sure you want to convert %s to upcase?Y/N\n",prog_info->cmd_line);
Bit8u key;Bit16u n=1;
DOS_ReadFile(STDIN,&key,&n);
if (toupper(key)=='Y') {
upcasedir(prog_info->cmd_line);
} else {
WriteOut("Okay better not do it.\n");
}
}
static void UPCASE_ProgramStart(PROGRAM_Info * info) {
UPCASE * tempUPCASE=new UPCASE(info);
tempUPCASE->Run();
delete tempUPCASE;
}
#endif
void DOS_SetupPrograms(void) {
PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart);
// PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart); /*next release */
#if !defined (WIN32) /* Unix */
PROGRAMS_MakeFile("UPCASE.COM",UPCASE_ProgramStart);
#endif
}

54
src/dos/dos_tables.cpp Normal file
View file

@ -0,0 +1,54 @@
/*
* 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 "mem.h"
#include "dos_inc.h"
#pragma pack(1)
struct DOS_TableCase {
Bit16u size;
Bit8u chars[256];
};
#pragma pack()
RealPt DOS_TableUpCase;
RealPt DOS_TableLowCase;
static Bit16u dos_memseg=0xd000;
Bit16u DOS_GetMemory(Bit16u pages) {
if (pages+dos_memseg>=0xe000) {
E_Exit("DOS:Not enough memory for internal tables");
}
Bit16u page=dos_memseg;
dos_memseg+=pages;
return page;
}
void DOS_SetupTables(void) {
dos.tables.indosflag=RealMake(DOS_GetMemory(1),0);
mem_writeb(Real2Phys(dos.tables.indosflag),0);
};

277
src/dos/drive_local.cpp Normal file
View file

@ -0,0 +1,277 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include "dosbox.h"
#include "dos_system.h"
#include "drives.h"
#include "support.h"
#include "cross.h"
class localFile : public DOS_File {
public:
localFile(FILE * handle,Bit16u devinfo);
bool Read(Bit8u * data,Bit16u * size);
bool Write(Bit8u * data,Bit16u * size);
bool Seek(Bit32u * pos,Bit32u type);
bool Close();
Bit16u GetInformation(void);
private:
FILE * fhandle;
Bit16u info;
};
bool localDrive:: FileCreate(DOS_File * * file,char * name,Bit16u attributes) {
//TODO Maybe care for attributes but not likely
char newname[512];
strcpy(newname,basedir);
strcat(newname,name);
CROSS_FILENAME(newname);
FILE * hand=fopen(newname,"wb+");
if (!hand) return false;
/* Make the 16 bit device information */
*file=new localFile(hand,0x202);
return true;
};
bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
char * type;
switch (flags) {
case OPEN_READ:type="rb";break;
case OPEN_WRITE:type="rb+";break;
case OPEN_READWRITE:type="rb+";break;
default:
//TODO FIX IT
type="rb+";
// return false;
};
char newname[512];
strcpy(newname,basedir);
strcat(newname,name);
CROSS_FILENAME(newname);
FILE * hand=fopen(newname,type);
Bit32u err=errno;
if (!hand) return false;
*file=new localFile(hand,0x202);
return true;
};
bool localDrive::FileUnlink(char * name) {
char newname[512];
strcpy(newname,basedir);
strcat(newname,name);
CROSS_FILENAME(newname);
if (!unlink(newname)) return true;
return false;
};
bool localDrive::FindFirst(char * search,DTA_FindBlock * dta) {
//TODO Find some way for lowcase and highcase drives oneday
char name[512];
strcpy(name,basedir);
strcat(name,search);
CROSS_FILENAME(name);
char * last=strrchr(name, CROSS_FILESPLIT);
*last=0;
last++;
/* Check the wildcard string for an extension */
strcpy(wild_name,last);
wild_ext=strrchr(wild_name,'.');
if (wild_ext) {
*wild_ext++=0;
}
strcpy(directory,name);
/* make sure / is last sign */
if (pdir) closedir(pdir);
if(directory[(strlen(directory)-1)]!=CROSS_FILESPLIT) strcat(directory, "/");
if((pdir=opendir(directory))==NULL) return false;
return FindNext(dta);
}
bool localDrive::FindNext(DTA_FindBlock * dta) {
Bit8u tempattr=0;
struct dirent *tempdata;
struct stat stat_block;
char werkbuffer[512];
if(pdir==NULL){
return false;
};
start:
if((tempdata=readdir(pdir))==NULL) {
closedir(pdir);
pdir=NULL;
return false;
}
strcpy(werkbuffer,tempdata->d_name);
if (wild_ext) {
char * ext=strrchr(werkbuffer,'.');
if (!ext) ext="*";
else *ext++=0;
if(!wildcmp(wild_ext,ext)) goto start;
}
if(!wildcmp(wild_name,werkbuffer)) goto start;
werkbuffer[0]='\0';
strcpy(werkbuffer,directory);
strcat(werkbuffer,tempdata->d_name);
if(stat(werkbuffer,&stat_block)!=0){
/*nu is er iets fout!*/ exit(1);
}
if(S_ISDIR(stat_block.st_mode)) tempattr=DOS_ATTR_DIRECTORY;
else tempattr=DOS_ATTR_ARCHIVE;
if(!(dta->sattr & tempattr)) goto start;
/*file is oke so filldtablok */
if(strlen(tempdata->d_name)<=DOS_NAMELENGTH) strcpy(dta->name,upcase(tempdata->d_name));
dta->attr=tempattr;
dta->size=(Bit32u) stat_block.st_size;
struct tm *time;
time=localtime(&stat_block.st_mtime);
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);
return true;
}
bool localDrive::GetFileAttr(char * name,Bit16u * attr) {
char newname[512];
strcpy(newname,basedir);
strcat(newname,name);
CROSS_FILENAME(newname);
FILE * hand=fopen(newname,"rb");
if (hand) {
fclose(hand);
*attr=DOS_ATTR_ARCHIVE;
return true;
}
*attr=0;
return false;
};
bool localDrive::MakeDir(char * dir) {
char newdir[512];
strcpy(newdir,basedir);
strcat(newdir,dir);
CROSS_FILENAME(newdir);
#if defined (WIN32) /* MS Visual C++ */
int temp=mkdir(newdir);
#else
int temp=mkdir(newdir,0);
#endif
return (temp==0);
}
bool localDrive::RemoveDir(char * dir) {
char newdir[512];
strcpy(newdir,basedir);
strcat(newdir,dir);
int temp=rmdir(newdir);
return (temp==0);
}
bool localDrive::TestDir(char * dir) {
char newdir[512];
strcpy(newdir,basedir);
strcat(newdir,dir);
int temp=access(newdir,F_OK);
return (temp==0);
}
bool localDrive::Rename(char * oldname,char * newname) {
char newold[512];
strcpy(newold,basedir);
strcat(newold,oldname);
CROSS_FILENAME(newold);
char newnew[512];
strcpy(newnew,basedir);
strcat(newnew,newnew);
CROSS_FILENAME(newname);
int temp=rename(newold,newnew);
return (temp==0);
};
bool localDrive::FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) {
/* Always report 100 mb free should be enough */
/* Total size is always 1 gb */
*bytes=512;
*sectors=127;
*clusters=16513;
*free=1700;
return true;
};
localDrive::localDrive(char * startdir) {
strcpy(basedir,startdir);
sprintf(info,"local directory %s",startdir);
pdir=NULL;
}
bool localFile::Read(Bit8u * data,Bit16u * size) {
*size=fread(data,1,*size,fhandle);
return true;
};
bool localFile::Write(Bit8u * data,Bit16u * size) {
*size=fwrite(data,1,*size,fhandle);
return true;
}
bool localFile::Seek(Bit32u * pos,Bit32u type) {
int seektype;
switch (type) {
case DOS_SEEK_SET:seektype=SEEK_SET;break;
case DOS_SEEK_CUR:seektype=SEEK_CUR;break;
case DOS_SEEK_END:seektype=SEEK_END;break;
default:
//TODO Give some doserrorcode;
return false;//ERROR
}
fpos_t temppos;
int ret=fseek(fhandle,*pos,seektype);
fgetpos(fhandle,&temppos);
//TODO Hope we don't encouter files with 64 bits size
Bit32u * fake_pos=(Bit32u*)&temppos;
*pos=*fake_pos;
return true;
}
bool localFile::Close() {
fclose(fhandle);
return true;
}
Bit16u localFile::GetInformation(void) {
return info;
}
localFile::localFile(FILE * handle,Bit16u devinfo) {
fhandle=handle;
info=devinfo;
}

205
src/dos/drive_virtual.cpp Normal file
View file

@ -0,0 +1,205 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dosbox.h"
#include "dos_system.h"
#include "drives.h"
#include "support.h"
struct VFILE_Block {
char * name;
Bit8u * data;
Bit32u size;
VFILE_Block * next;
};
static VFILE_Block * first_file;
void VFILE_Register(char * name,Bit8u * data,Bit32u size) {
VFILE_Block * new_file=new VFILE_Block;
new_file->name=name;
new_file->data=data;
new_file->size=size;
new_file->next=first_file;
first_file=new_file;
}
class Virtual_File : public DOS_File {
public:
Virtual_File(Bit8u * in_data,Bit32u in_size);
bool Read(Bit8u * data,Bit16u * size);
bool Write(Bit8u * data,Bit16u * size);
bool Seek(Bit32u * pos,Bit32u type);
bool Close();
Bit16u GetInformation(void);
private:
Bit32u file_size;
Bit32u file_pos;
Bit8u * file_data;
};
Virtual_File::Virtual_File(Bit8u * in_data,Bit32u in_size) {
file_size=in_size;
file_data=in_data;
file_pos=0;
}
bool Virtual_File::Read(Bit8u * data,Bit16u * size) {
Bit32u left=file_size-file_pos;
if (left<=*size) {
memcpy(data,&file_data[file_pos],left);
*size=(Bit16u)left;
} else {
memcpy(data,&file_data[file_pos],*size);
}
file_pos+=*size;
return true;
};
bool Virtual_File::Write(Bit8u * data,Bit16u * size){
/* Not really writeable */
return false;
};
bool Virtual_File::Seek(Bit32u * new_pos,Bit32u type){
switch (type) {
case DOS_SEEK_SET:
if (*new_pos<=file_size) file_pos=*new_pos;
else return false;
break;
case DOS_SEEK_CUR:
if ((*new_pos+file_pos)<=file_size) file_pos=*new_pos+file_pos;
else return false;
break;
case DOS_SEEK_END:
if (*new_pos<=file_size) file_pos=file_size-*new_pos;
else return false;
break;
}
*new_pos=file_pos;
return true;
};
bool Virtual_File::Close(){
return true;
};
Bit16u Virtual_File::GetInformation(void) {
return 0;
}
Virtual_Drive::Virtual_Drive() {
strcpy(info,"Internal Virtual Drive");
search_file=0;
}
bool Virtual_Drive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
/* Scan through the internal list of files */
VFILE_Block * cur_file=first_file;
while (cur_file) {
if (strcasecmp(name,cur_file->name)==0) {
/* We have a match */
*file=new Virtual_File(cur_file->data,cur_file->size);
return true;
}
cur_file=cur_file->next;
}
return false;
}
bool Virtual_Drive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) {
return false;
}
bool Virtual_Drive::FileUnlink(char * name) {
return false;
}
bool Virtual_Drive::RemoveDir(char * dir) {
return false;
}
bool Virtual_Drive::MakeDir(char * dir) {
return false;
}
bool Virtual_Drive::TestDir(char * dir) {
return false;
}
static void FillDTABlock(DTA_FindBlock * dta,VFILE_Block * fill_file) {
strcpy(dta->name,fill_file->name);
dta->size=fill_file->size;
dta->attr=DOS_ATTR_ARCHIVE;
dta->time=2;
dta->date=6;
}
bool Virtual_Drive::FindFirst(char * search,DTA_FindBlock * dta) {
search_file=first_file;
strcpy(search_string,search);
while (search_file) {
if (wildcmp(search_string,search_file->name)) {
FillDTABlock(dta,search_file);
search_file=search_file->next;
return true;
}
search_file=search_file->next;
}
return false;
}
bool Virtual_Drive::FindNext(DTA_FindBlock * dta) {
while (search_file) {
if (wildcmp(search_string,search_file->name)) {
FillDTABlock(dta,search_file);
search_file=search_file->next;
return true;
}
search_file=search_file->next;
}
return false;
}
bool Virtual_Drive::GetFileAttr(char * name,Bit16u * attr) {
return false;
}
bool Virtual_Drive::Rename(char * oldname,char * newname) {
return false;
}
bool Virtual_Drive::FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) {
/* Always report 100 mb free should be enough */
/* Total size is always 1 gb */
*bytes=512;
*sectors=127;
*clusters=16513;
*free=00;
return true;
}

31
src/dos/drives.cpp Normal file
View file

@ -0,0 +1,31 @@
/*
* 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 "dos_system.h"
#include "drives.h"
DOS_Drive::DOS_Drive() {
curdir[0]=0;
info[0]=0;
}
char * DOS_Drive::GetInfo(void) {
return info;
}

71
src/dos/drives.h Normal file
View file

@ -0,0 +1,71 @@
/*
* 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 _DRIVES_H__
#define _DRIVES_H__
#include <sys/types.h>
#include <dirent.h>
class localDrive : public DOS_Drive {
public:
localDrive(char * startdir);
bool FileOpen(DOS_File * * file,char * name,Bit32u flags);
bool FileCreate(DOS_File * * file,char * name,Bit16u attributes);
bool FileUnlink(char * name);
bool RemoveDir(char * dir);
bool MakeDir(char * dir);
bool TestDir(char * dir);
bool FindFirst(char * search,DTA_FindBlock * dta);
bool FindNext(DTA_FindBlock * dta);
bool GetFileAttr(char * name,Bit16u * attr);
bool Rename(char * oldname,char * newname);
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
private:
bool FillDTABlock(DTA_FindBlock * dta);
char basedir[512];
char directory[512];
char wild_name[15];
char * wild_ext;
DIR *pdir;
};
struct VFILE_Block;
class Virtual_Drive: public DOS_Drive {
public:
Virtual_Drive();
bool FileOpen(DOS_File * * file,char * name,Bit32u flags);
bool FileCreate(DOS_File * * file,char * name,Bit16u attributes);
bool FileUnlink(char * name);
bool RemoveDir(char * dir);
bool MakeDir(char * dir);
bool TestDir(char * dir);
bool FindFirst(char * search,DTA_FindBlock * dta);
bool FindNext(DTA_FindBlock * dta);
bool GetFileAttr(char * name,Bit16u * attr);
bool Rename(char * oldname,char * newname);
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
private:
VFILE_Block * search_file;
char search_string[255];
};
#endif

297
src/dosbox.cpp Normal file
View file

@ -0,0 +1,297 @@
/*
* 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 <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "dosbox.h"
#include "debug.h"
#include "cpu.h"
#include "video.h"
#include "pic.h"
#include "cpu.h"
#include "callback.h"
#include "inout.h"
#include "mixer.h"
#include "timer.h"
#include "dos_inc.h"
#include "setup.h"
#include "cross.h"
#include "programs.h"
char dosbox_basedir[CROSS_LEN];
#if 0
int main(int argc, char* argv[]) {
/* Strip out the dosbox startup directory */
/* Handle the command line for new stuff to add to autoexec.bat */
int argl=1;
if (argc>1) {
if (*argv[1]!='-') {
struct stat test;
if (stat(argv[1],&test)) {
E_Exit("%s Doesn't exist",argv[1]);
}
/* Not a switch so a normal directory/file */
if (test.st_mode & S_IFDIR) {
SHELL_AddAutoexec("MOUNT C %s",argv[1]);
SHELL_AddAutoexec("C:");
} else {
char * name=strrchr(argv[1],CROSS_FILESPLIT);
if (!name) E_Exit("This is weird %s",argv[1]);
*name++=0;
if (access(argv[1],F_OK)) E_Exit("Illegal Directory %s",argv[1]);
SHELL_AddAutoexec("MOUNT C %s",argv[1]);
SHELL_AddAutoexec("C:");
SHELL_AddAutoexec(name);
}
argl++;
}
}
bool sw_c=false;
while (argl<argc) {
if (*argv[argl]=='-') {
sw_c=false;
if (strcmp(argv[argl],"-c")==0) sw_c=true;
else E_Exit("Illegal switch %s",argv[argl]);
argl++;
continue;
}
SHELL_AddAutoexec(argv[argl]);
if (sw_c) {
}
argl++;
}
SysShutDown();
SDL_Quit();
return 0;
}
#endif
//The whole load of startups for all the subfunctions
void MSG_Init(void);
void MEM_Init(void);
void VGA_Init(void);
void CALLBACK_Init();
void DOS_Init();
void RENDER_Init(void);
void CPU_Init();
void FPU_Init();
void IO_Init(void);
void DMA_Init(void);
void MIXER_Init(void);
void HARDWARE_Init(void);
void KEYBOARD_Init(void); //TODO This should setup INT 16 too but ok ;)
void JOYSTICK_Init(void);
void MOUSE_Init(void);
void SBLASTER_Init(void);
void ADLIB_Init(void);
void PCSPEAKER_Init(void);
void TANDY_Init(void);
void CMS_Init(void);
void PIC_Init(void);
void TIMER_Init(void);
void BIOS_Init(void);
void DEBUG_Init(void);
void PLUGIN_Init(void);
/* Dos Internal mostly */
void EMS_Init(void);
void XMS_Init(void);
void PROGRAMS_Init(void);
void SHELL_Init(void);
void CALLBACK_ShutDown(void);
void PIC_ShutDown(void);
void KEYBOARD_ShutDown(void);
void CPU_ShutDown(void);
void VGA_ShutDown(void);
void BIOS_ShutDown(void);
void MEMORY_ShutDown(void);
Bit32u LastTicks;
static LoopHandler * loop;
static Bitu Normal_Loop(void) {
Bit32u new_ticks;
new_ticks=GetTicks();
if (new_ticks>LastTicks) {
Bit32u ticks=new_ticks-LastTicks;
if (ticks>20) ticks=20;
LastTicks=new_ticks;
TIMER_AddTicks(ticks);
}
TIMER_CheckPIT();
GFX_Events();
PIC_runIRQs();
return (*cpudecoder)(cpu_cycles);
};
static Bitu Speed_Loop(void) {
Bit32u new_ticks;
new_ticks=GetTicks();
Bitu ret=0;
Bitu cycles=1;
if (new_ticks>LastTicks) {
Bit32u ticks=new_ticks-LastTicks;
if (ticks>20) ticks=20;
// if (ticks>3) LOG_DEBUG("Ticks %d",ticks);
LastTicks=new_ticks;
TIMER_AddTicks(ticks);
cycles+=cpu_cycles*ticks;
}
TIMER_CheckPIT();
GFX_Events();
PIC_runIRQs();
return (*cpudecoder)(cycles);
}
void DOSBOX_SetLoop(LoopHandler * handler) {
loop=handler;
}
void DOSBOX_RunMachine(void){
Bitu ret;
do {
ret=(*loop)();
} while (!ret);
}
static void InitSystems(void) {
MSG_Init();
MEM_Init();
IO_Init();
CALLBACK_Init();
PROGRAMS_Init();
HARDWARE_Init();
TIMER_Init();
CPU_Init();
FPU_Init();
MIXER_Init();
#ifdef C_DEBUG
DEBUG_Init();
#endif
//Start up individual hardware
DMA_Init();
PIC_Init();
VGA_Init();
KEYBOARD_Init();
MOUSE_Init();
JOYSTICK_Init();
SBLASTER_Init();
TANDY_Init();
PCSPEAKER_Init();
ADLIB_Init();
CMS_Init();
PLUGIN_Init();
/* Most of teh interrupt handlers */
BIOS_Init();
DOS_Init();
EMS_Init(); //Needs dos first
XMS_Init(); //Needs dos first
/* Setup the normal system loop */
LastTicks=GetTicks();
DOSBOX_SetLoop(&Normal_Loop);
// DOSBOX_SetLoop(&Speed_Loop);
}
void DOSBOX_Init(int argc, char* argv[]) {
/* Find the base directory */
strcpy(dosbox_basedir,argv[0]);
char * last=strrchr(dosbox_basedir,CROSS_FILESPLIT); //if windowsversion fails:
if (!last) E_Exit("Can't find basedir %s", argv[0]);
*++last=0;
/* Parse the command line with a setup function */
int argl=1;
if (argc>1) {
if (*argv[1]!='-') {
struct stat test;
if (stat(argv[1],&test)) {
E_Exit("%s Doesn't exist",argv[1]);
}
/* Not a switch so a normal directory/file */
if (test.st_mode & S_IFDIR) {
SHELL_AddAutoexec("MOUNT C %s",argv[1]);
SHELL_AddAutoexec("C:");
} else {
char * name=strrchr(argv[1],CROSS_FILESPLIT);
if (!name) E_Exit("This is weird %s",argv[1]);
*name++=0;
if (access(argv[1],F_OK)) E_Exit("Illegal Directory %s",argv[1]);
SHELL_AddAutoexec("MOUNT C %s",argv[1]);
SHELL_AddAutoexec("C:");
SHELL_AddAutoexec(name);
}
argl++;
}
}
bool sw_c=false;
while (argl<argc) {
if (*argv[argl]=='-') {
sw_c=false;
if (strcmp(argv[argl],"-c")==0) sw_c=true;
else E_Exit("Illegal switch %s",argv[argl]);
argl++;
continue;
}
SHELL_AddAutoexec(argv[argl]);
if (sw_c) {
}
argl++;
}
InitSystems();
}
void DOSBOX_StartUp(void) {
SHELL_AddAutoexec("SET PATH=Z:\\");
SHELL_AddAutoexec("SET COMSPEC=Z:\\COMMAND.COM");
SHELL_Init();
};

75
src/dosbox.lang Normal file
View file

@ -0,0 +1,75 @@
:SHELL_CMD_HELP
supported commands are:
.
:SHELL_ILLEGAL_SWITCH
Illegal switch: %s
.
:SHELL_CMD_ECHO_ON
ECHO is on
.
:SHELL_CMD_ECHO_OFF
ECHO is off
.
:SHELL_CMD_CHDIR_ERROR
Unable to change to: %s
.
:SHELL_CMD_MKDIR_ERROR
Unable to make: %s
.
:SHELL_CMD_RMDIR_ERROR
Unable to remove: %s
.
:SHELL_SYNTAXERROR
The syntax of the command is incorrect
.
:SHELL_CMD_SET_NOT_SET
Environment variable %s not defined
.
:SHELL_CMD_SET_OUT_OF_SPACE
Not enough environment space left
.
:SHELL_CMD_IF_EXIST_MISSING_FILENAME
IF EXIST: Missing filename
.
:SHELL_CMD_IF_ERRORLEVEL_MISSING_NUMBER
IF ERRORLEVEL: Missing number
.
:SHELL_CMD_IF_ERRORLEVEL_INVALID_NUMBER
IF ERRORLEVEL: Invalid number
.
:SHELL_CMD_GOTO_MISSING_LABEL
No label supplied to GOTO command
.
:SHELL_CMD_GOTO_LABEL_NOT_FOUND
Label %s not found
.
:SHELL_CMD_FILE_NOT_FOUND
File %s not found
.
:SHELL_CMD_DIR_INTRO
Directory of %s
.
:SHELL_CMD_DIR_PATH_ERROR
Illegal Path
.
:SHELL_CMD_DIR_BYTES_USED
%16d File(s) %16s Bytes
.
:SHELL_CMD_DIR_BYTES_FREE
%16d Dir(s) %16s Bytes free
.
:SHELL_STARTUP
DOSBox Shell v0.35
For Help and supported commands type: HELP
For information about the hardware setup manager type: HWSET /?
HAVE FUN!
The DOSBox Team
.
:SHELL_EXECUTE_DRIVE_NOT_FOUND
Drive %c does not exist!
.
:SHELL_EXECUTE_ILLEGAL_COMMAND
Illegal command
.

4
src/fpu/Makefile.am Normal file
View file

@ -0,0 +1,4 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libfpu.a
libfpu_a_SOURCES = fpu.cpp fpu_load.h

62
src/fpu/fpu.cpp Normal file
View file

@ -0,0 +1,62 @@
/*
* 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 <math.h>
#include <float.h>
#include "mem.h"
#include "dosbox.h"
typedef PhysPt EAPoint;
#define LoadMb(off) mem_readb(off)
#define LoadMw(off) mem_readw(off)
#define LoadMd(off) mem_readd(off)
#define LoadMbs(off) (Bit8s)(LoadMb(off))
#define LoadMws(off) (Bit16s)(LoadMw(off))
#define LoadMds(off) (Bit32s)(LoadMd(off))
#define SaveMb(off,val) mem_writeb(off,val)
#define SaveMw(off,val) mem_writew(off,val)
#define SaveMd(off,val) mem_writed(off,val)
typedef long double FPUREG;
#include "fpu_load.h"
void FPU_ESC0_EA(Bitu rm,PhysPt addr) {
}
void FPU_ESC0_Normal(Bitu rm) {
}
void FPU_Init(void) {
}

21
src/fpu/fpu_load.h Normal file
View file

@ -0,0 +1,21 @@
/*
* 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);
}

5
src/gui/Makefile.am Normal file
View file

@ -0,0 +1,5 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libgui.a
libgui_a_SOURCES = sdlmain.cpp render.cpp

160
src/gui/render.cpp Normal file
View file

@ -0,0 +1,160 @@
/*
* 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 "video.h"
#include "render.h"
#define MAX_RES 2048
struct PalData {
struct {
Bit8u red;
Bit8u green;
Bit8u blue;
Bit8u unused;
} rgb[256];
Bitu first;
Bitu last;
};
static struct {
struct {
Bitu width;
Bitu height;
Bitu bpp;
Bitu pitch;
float ratio;
} src;
Bitu flags;
RENDER_Handler * handler;
Bitu stretch_x[MAX_RES];
Bitu stretch_y[MAX_RES];
PalData pal;
bool remake;
bool enlarge;
} render;
/* This could go kinda bad with multiple threads */
static void Check_Palette(void) {
if (render.pal.first>render.pal.last) return;
GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]);
render.pal.first=256;
render.pal.last=0;
}
static void MakeTables(void) {
//The stretching tables
Bitu i;Bit32u c,a;
c=0;a=(render.src.width<<16)/gfx_info.width;
for (i=0;i<gfx_info.width;i++) {
render.stretch_x[i]=c>> 16;
c=(c&0xffff)+a;
}
c=0;a=(render.src.height<<16)/gfx_info.height;
for (i=0;i<gfx_info.height;i++) {
render.stretch_y[i]=(c>> 16)*render.src.pitch;
c=(c&0xffff)+a;
}
}
static void Draw_8_Normal(Bit8u * src_data,Bit8u * dst_data) {
for (Bitu y=0;y<gfx_info.height;y++) {
Bit8u * line_src=src_data;
Bit8u * line_dest=dst_data;
for (Bitu x=0;x<gfx_info.width;x++) {
*line_dest++=*line_src;
line_src+=render.stretch_x[x];
}
src_data+=render.stretch_y[y];
dst_data+=gfx_info.pitch;
}
}
void RENDER_Draw(Bit8u * bitdata) {
Bit8u * src_data;
Check_Palette();
if (render.remake) {
MakeTables();
render.remake=false;
}
render.handler(&src_data);
Draw_8_Normal(src_data,bitdata);
}
void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) {
render.pal.rgb[entry].red=red;
render.pal.rgb[entry].green=green;
render.pal.rgb[entry].blue=blue;
if (render.pal.first>entry) render.pal.first=entry;
if (render.pal.last<entry) render.pal.last=entry;
}
static void RENDER_Resize(Bitu * width,Bitu * height) {
/* Calculate the new size the window should be */
if (!*width && !*height) {
/* Special command to reset any resizing for fullscreen */
*width=render.src.width;
*height=render.src.height;
} else {
if ((*width/render.src.ratio)<*height) *height=(Bitu)(*width/render.src.ratio);
else *width=(Bitu)(*height*render.src.ratio);
}
render.remake=true;
}
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags, RENDER_Handler * handler) {
if (!width) return;
if (!height) return;
GFX_Stop();
render.src.width=width;
render.src.height=height;
render.src.bpp=bpp;
render.src.ratio=ratio;
render.src.pitch=pitch;
render.handler=handler;
switch (bpp) {
case 8:
GFX_Resize(width,height,bpp,&RENDER_Resize);
GFX_SetDrawHandler(RENDER_Draw);
break;
default:
E_Exit("RENDER:Illegal bpp %d",bpp);
};
/* Setup the internal render structures to correctly render this screen */
MakeTables();
GFX_Start();
}
void RENDER_Init(void) {
render.pal.first=256;
render.pal.last=0;
render.enlarge=false;
}

513
src/gui/sdlmain.cpp Normal file
View file

@ -0,0 +1,513 @@
/*
* 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 <string.h>
#include <stdio.h>
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include "dosbox.h"
#include "video.h"
#include "keyboard.h"
#include "mouse.h"
#include "joystick.h"
#include "pic.h"
#include "timer.h"
//#define DISABLE_JOYSTICK
struct SDL_Block {
bool active; //If this isn't set don't draw
Bitu width;
Bitu height;
Bitu bpp;
GFX_DrawHandler * draw;
GFX_ResizeHandler * resize;
bool mouse_grabbed;
bool full_screen;
SDL_Thread * thread;
SDL_mutex * mutex;
SDL_Surface * surface;
SDL_Joystick * joy;
SDL_Color pal[256];
};
static SDL_Block sdl;
GFX_Info gfx_info;
static void RestorePalette(void) {
if (sdl.bpp!=8) return;
/* Use some other way of doing this */
if (sdl.full_screen) {
if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,sdl.pal,0,256)) {
E_Exit("SDL:Can't set palette");
}
} else {
if (!SDL_SetPalette(sdl.surface,SDL_LOGPAL,sdl.pal,0,256)) {
E_Exit("SDL:Can't set palette");
}
}
return;
}
/* Reset the screen with current values in the sdl structure */
static void ResetScreen(void) {
if (sdl.full_screen) {
/* First get the original resolution */
sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN|SDL_DOUBLEBUF);
} else {
sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_SWSURFACE|SDL_RESIZABLE);
}
if (sdl.surface==0) {
E_Exit("SDL:Would be nice if I could get a surface.");
}
SDL_WM_SetCaption(VERSION,VERSION);
/* also fill up gfx_info structure */
gfx_info.width=sdl.width;
gfx_info.height=sdl.height;
gfx_info.bpp=sdl.bpp;
gfx_info.pitch=sdl.surface->pitch;
RestorePalette();
}
void GFX_Resize(Bitu width,Bitu height,Bitu bpp,GFX_ResizeHandler * resize) {
GFX_Stop();
sdl.width=width;
sdl.height=height;
sdl.bpp=bpp;
sdl.resize=resize;
ResetScreen();
GFX_Start();
}
static void CaptureMouse() {
sdl.mouse_grabbed=!sdl.mouse_grabbed;
if (sdl.mouse_grabbed) {
SDL_WM_GrabInput(SDL_GRAB_ON);
SDL_ShowCursor(SDL_DISABLE);
} else {
SDL_WM_GrabInput(SDL_GRAB_OFF);
SDL_ShowCursor(SDL_ENABLE);
}
}
static void SwitchFullScreen(void) {
GFX_Stop();
sdl.full_screen=!sdl.full_screen;
if (sdl.full_screen) {
if (sdl.resize) {
sdl.width=0;sdl.height=0;
(*sdl.resize)(&sdl.width,&sdl.height);
}
}
ResetScreen();
GFX_Start();
}
static void GFX_Redraw() {
#ifdef C_THREADED
if (SDL_mutexP(sdl.mutex)) {
E_Exit("Can't Lock Mutex");
};
#endif
if (sdl.active) {
SDL_LockSurface(sdl.surface );
if (sdl.surface->pixels && sdl.draw) (*sdl.draw)((Bit8u *)sdl.surface->pixels);
SDL_UnlockSurface(sdl.surface );
if (sdl.full_screen) SDL_Flip(sdl.surface);
else SDL_UpdateRect(sdl.surface,0,0,0,0);
};
#ifdef C_THREADED
if (SDL_mutexV(sdl.mutex)) {
E_Exit("Can't Release Mutex");
}
#endif
}
static int SDLGFX_Thread(void * data) {
do {
GFX_Redraw();
SDL_Delay(1000/70);
} while (true);
return 1;
}
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) {
/* I should probably not change the GFX_PalEntry :) */
#ifdef C_THREADED
if (SDL_mutexP(sdl.mutex)) {
E_Exit("SDL:Can't Lock Mutex");
};
#endif
if (sdl.full_screen) {
if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,(SDL_Color *)entries,start,count)) {
E_Exit("SDL:Can't set palette");
}
} else {
if (!SDL_SetPalette(sdl.surface,SDL_LOGPAL,(SDL_Color *)entries,start,count)) {
E_Exit("SDL:Can't set palette");
}
}
/* Copy palette entries into some internal back up table */
#ifdef C_THREADED
if (SDL_mutexV(sdl.mutex)) {
E_Exit("SDL:Can't Release Mutex");
}
#endif
memcpy(&sdl.pal[start],entries,count*sizeof(SDL_Color));
}
void GFX_SetDrawHandler(GFX_DrawHandler * handler) {
sdl.draw=handler;
}
void GFX_Stop() {
#ifdef C_THREADED
SDL_mutexP(sdl.mutex);
#endif
sdl.active=false;
#ifdef C_THREADED
SDL_mutexV(sdl.mutex);
#endif
}
void GFX_Start() {
sdl.active=true;
}
void GFX_StartUp() {
sdl.active=false;
sdl.full_screen=false;
sdl.draw=0;
#ifdef C_THREADED
sdl.mutex=SDL_CreateMutex();
sdl.thread = SDL_CreateThread(&SDLGFX_Thread,0);
#else
TIMER_RegisterMicroHandler(GFX_Redraw,1000000/70);
#endif
GFX_Resize(640,400,8,0);
SDL_EnableKeyRepeat(250,30);
/* Get some Keybinds */
KEYBOARD_AddEvent(KBD_f9,CTRL_PRESSED,SwitchFullScreen);
KEYBOARD_AddEvent(KBD_f10,CTRL_PRESSED,CaptureMouse);
KEYBOARD_AddEvent(KBD_enter,ALT_PRESSED,SwitchFullScreen);
}
void GFX_ShutDown() {
if (sdl.full_screen) SwitchFullScreen();
if (sdl.mouse_grabbed) CaptureMouse();
GFX_Stop();
}
static void HandleKey(SDL_KeyboardEvent * key) {
Bit32u code;
switch (key->keysym.sym) {
case SDLK_1:code=KBD_1;break;
case SDLK_2:code=KBD_2;break;
case SDLK_3:code=KBD_3;break;
case SDLK_4:code=KBD_4;break;
case SDLK_5:code=KBD_5;break;
case SDLK_6:code=KBD_6;break;
case SDLK_7:code=KBD_7;break;
case SDLK_8:code=KBD_8;break;
case SDLK_9:code=KBD_9;break;
case SDLK_0:code=KBD_0;break;
case SDLK_q:code=KBD_q;break;
case SDLK_w:code=KBD_w;break;
case SDLK_e:code=KBD_e;break;
case SDLK_r:code=KBD_r;break;
case SDLK_t:code=KBD_t;break;
case SDLK_y:code=KBD_y;break;
case SDLK_u:code=KBD_u;break;
case SDLK_i:code=KBD_i;break;
case SDLK_o:code=KBD_o;break;
case SDLK_p:code=KBD_p;break;
case SDLK_a:code=KBD_a;break;
case SDLK_s:code=KBD_s;break;
case SDLK_d:code=KBD_d;break;
case SDLK_f:code=KBD_f;break;
case SDLK_g:code=KBD_g;break;
case SDLK_h:code=KBD_h;break;
case SDLK_j:code=KBD_j;break;
case SDLK_k:code=KBD_k;break;
case SDLK_l:code=KBD_l;break;
case SDLK_z:code=KBD_z;break;
case SDLK_x:code=KBD_x;break;
case SDLK_c:code=KBD_c;break;
case SDLK_v:code=KBD_v;break;
case SDLK_b:code=KBD_b;break;
case SDLK_n:code=KBD_n;break;
case SDLK_m:code=KBD_m;break;
case SDLK_F1:code=KBD_f1;break;
case SDLK_F2:code=KBD_f2;break;
case SDLK_F3:code=KBD_f3;break;
case SDLK_F4:code=KBD_f4;break;
case SDLK_F5:code=KBD_f5;break;
case SDLK_F6:code=KBD_f6;break;
case SDLK_F7:code=KBD_f7;break;
case SDLK_F8:code=KBD_f8;break;
case SDLK_F9:code=KBD_f9;break;
case SDLK_F10:code=KBD_f10;break;
case SDLK_F11:code=KBD_f11;break;
case SDLK_F12:code=KBD_f12;break;
// KBD_esc,KBD_tab,KBD_backspace,KBD_enter,KBD_space,
case SDLK_ESCAPE:code=KBD_esc;break;
case SDLK_TAB:code=KBD_tab;break;
case SDLK_BACKSPACE:code=KBD_backspace;break;
case SDLK_RETURN:code=KBD_enter;break;
case SDLK_SPACE:code=KBD_space;break;
case SDLK_LALT:code=KBD_leftalt;break;
case SDLK_RALT:code=KBD_rightalt;break;
case SDLK_LCTRL:code=KBD_leftctrl;break;
case SDLK_RCTRL:code=KBD_rightctrl;break;
case SDLK_LSHIFT:code=KBD_leftshift;break;
case SDLK_RSHIFT:code=KBD_rightshift;break;
case SDLK_CAPSLOCK:code=KBD_capslock;break;
case SDLK_SCROLLOCK:code=KBD_scrolllock;break;
case SDLK_NUMLOCK:code=KBD_numlock;break;
case SDLK_BACKQUOTE:code=KBD_grave;break;
case SDLK_MINUS:code=KBD_minus;break;
case SDLK_EQUALS:code=KBD_equals;break;
case SDLK_BACKSLASH:code=KBD_backslash;break;
case SDLK_LEFTBRACKET:code=KBD_leftbracket;break;
case SDLK_RIGHTBRACKET:code=KBD_rightbracket;break;
case SDLK_SEMICOLON:code=KBD_semicolon;break;
case SDLK_QUOTE:code=KBD_quote;break;
case SDLK_PERIOD:code=KBD_period;break;
case SDLK_COMMA:code=KBD_comma;break;
case SDLK_SLASH:code=KBD_slash;break;
case SDLK_INSERT:code=KBD_insert;break;
case SDLK_HOME:code=KBD_home;break;
case SDLK_PAGEUP:code=KBD_pageup;break;
case SDLK_DELETE:code=KBD_delete;break;
case SDLK_END:code=KBD_end;break;
case SDLK_PAGEDOWN:code=KBD_pagedown;break;
case SDLK_LEFT:code=KBD_left;break;
case SDLK_UP:code=KBD_up;break;
case SDLK_DOWN:code=KBD_down;break;
case SDLK_RIGHT:code=KBD_right;break;
case SDLK_KP1:code=KBD_kp1;break;
case SDLK_KP2:code=KBD_kp2;break;
case SDLK_KP3:code=KBD_kp3;break;
case SDLK_KP4:code=KBD_kp4;break;
case SDLK_KP5:code=KBD_kp5;break;
case SDLK_KP6:code=KBD_kp6;break;
case SDLK_KP7:code=KBD_kp7;break;
case SDLK_KP8:code=KBD_kp8;break;
case SDLK_KP9:code=KBD_kp9;break;
case SDLK_KP0:code=KBD_kp0;break;
case SDLK_KP_DIVIDE:code=KBD_kpslash;break;
case SDLK_KP_MULTIPLY:code=KBD_kpmultiply;break;
case SDLK_KP_MINUS:code=KBD_kpminus;break;
case SDLK_KP_PLUS:code=KBD_kpplus;break;
case SDLK_KP_ENTER:code=KBD_kpenter;break;
case SDLK_KP_PERIOD:code=KBD_kpperiod;break;
// case SDLK_:code=key_;break;
/* Special Keys */
default:
//TODO maybe give warning for keypress unknown
return;
}
KEYBOARD_AddKey(code,(key->state==SDL_PRESSED));
}
static void HandleMouseMotion(SDL_MouseMotionEvent * motion) {
if (!sdl.mouse_grabbed) {
Mouse_CursorSet((float)motion->x/(float)sdl.width,(float)motion->y/(float)sdl.height);
} else {
Mouse_CursorMoved((float)motion->xrel/(float)sdl.width,(float)motion->yrel/(float)sdl.height);
}
}
static void HandleMouseButton(SDL_MouseButtonEvent * button) {
switch (button->state) {
case SDL_PRESSED:
switch (button->button) {
case SDL_BUTTON_LEFT:
Mouse_ButtonPressed(0);
break;
case SDL_BUTTON_RIGHT:
Mouse_ButtonPressed(1);
break;
case SDL_BUTTON_MIDDLE:
Mouse_ButtonPressed(2);
break;
}
break;
case SDL_RELEASED:
switch (button->button) {
case SDL_BUTTON_LEFT:
Mouse_ButtonReleased(0);
break;
case SDL_BUTTON_RIGHT:
Mouse_ButtonReleased(1);
break;
case SDL_BUTTON_MIDDLE:
Mouse_ButtonReleased(2);
break;
}
break;
}
}
static void HandleJoystickAxis(SDL_JoyAxisEvent * jaxis) {
switch (jaxis->axis) {
case 0:
JOYSTICK_Move_X(0,(float)(jaxis->value/32768.0));
break;
case 1:
JOYSTICK_Move_Y(0,(float)(jaxis->value/32768.0));
break;
}
}
static void HandleJoystickButton(SDL_JoyButtonEvent * jbutton) {
bool state;
state=jbutton->type==SDL_JOYBUTTONDOWN;
if (jbutton->button<2) {
JOYSTICK_Button(0,jbutton->button,state);
}
}
static void HandleVideoResize(SDL_ResizeEvent * resize) {
Bitu width,height;
width=resize->w;
height=resize->h;
if (sdl.resize) {
GFX_Stop();
(*sdl.resize)(&width,&height);
sdl.width=width;
sdl.height=height;
ResetScreen();
GFX_Start();
}
}
void GFX_Events() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_KEYDOWN:
case SDL_KEYUP:
HandleKey(&event.key);
break;
case SDL_MOUSEMOTION:
HandleMouseMotion(&event.motion);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
HandleMouseButton(&event.button);
break;
case SDL_JOYAXISMOTION:
HandleJoystickAxis(&event.jaxis);
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
HandleJoystickButton(&event.jbutton);
break;
case SDL_VIDEORESIZE:
HandleVideoResize(&event.resize);
break;
case SDL_QUIT:
E_Exit("Closed the SDL Window");
break;
}
}
}
#if 0
void E_Exit(char * format,...) {
char buf[1024];
va_list msg;
strcpy(buf,"EXIT:");
va_start(msg,format);
vsprintf(buf+strlen(buf),format,msg);
va_end(msg);
waddstr(dbg.win_out,buf);
wprintw(dbg.win_out," %d\n",cycle_count);
wrefresh(dbg.win_out);
throw ((Bitu)1);
}
#endif
void GFX_ShowMsg(char * msg) {
char buf[1024];
strcpy(buf,msg);
strcat(buf,"\n");
printf(buf);
};
int main(int argc, char* argv[]) {
try {
if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER
#ifndef DISABLE_JOYSTICK
|SDL_INIT_JOYSTICK
#endif
) < 0 ) {
E_Exit("Can't init SDL");
}
GFX_StartUp();
/* Init all the dosbox subsystems */
DOSBOX_Init(argc,argv);
/* Start the systems that SDL should provide */
#ifndef DISABLE_JOYSTICK
if (SDL_NumJoysticks()>0) {
SDL_JoystickEventState(SDL_ENABLE);
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));
JOYSTICK_Enable(0,true);
#endif
}
/* Start dosbox up */
DOSBOX_StartUp();
}
catch (Bitu e) {
LOG_MSG("Exit to error %d",e);
}
GFX_Stop();
return 0;
};

11
src/hardware/Makefile.am Normal file
View file

@ -0,0 +1,11 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
EXTRA_DIST = fmopl.c fmopl.h
noinst_LIBRARIES = libhardware.a
libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \
memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \
vga.cpp vga.h vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_fonts.cpp vga_gfx.cpp \
vga_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h

224
src/hardware/adlib.cpp Normal file
View file

@ -0,0 +1,224 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include <math.h>
#include "dosbox.h"
#include "inout.h"
#include "mixer.h"
#include "timer.h"
#include "hardware.h"
/*
Thanks to vdmsound for nice simple way to implement this
*/
namespace MAME {
/* Defines */
# define logerror(x)
/* Disable recurring warnings */
#pragma warning ( disable : 4018 )
#pragma warning ( disable : 4244 )
/* Bring in Tatsuyuki Satoh's OPL emulation */
#define HAS_YM3812 1
#include "fmopl.c"
}
struct OPLTimer_t {
bool isEnabled;
bool isMasked;
bool isOverflowed;
Bit32u count;
Bit32u base;
};
static OPLTimer_t timer1,timer2;
static MAME::FM_OPL * myopl;
static Bit8u regsel;
#define OPL_INTERNAL_FREQ 3600000 // The OPL operates at 3.6MHz
static MIXER_Channel * adlib_chan;
static void ADLIB_CallBack(Bit8u *stream, Bit32u len) {
/* Check for size to update and check for 1 ms updates to the opl registers */
/* Calculate teh machine ms we are at now */
/* update 1 ms of data */
MAME::YM3812UpdateOne(myopl,(MAME::INT16 *)stream,len);
}
static Bit8u read_p388(Bit32u port) {
Bit8u ret=0;
Bit32u new_ticks=GetTicks();
if (timer1.isEnabled) {
if ((new_ticks-timer1.base)>timer1.count) {
timer1.isOverflowed=true;
timer1.base=new_ticks;
}
if (timer1.isOverflowed || !timer1.isMasked) {
ret|=0xc0;
}
}
if (timer2.isEnabled) {
if ((new_ticks-timer2.base)>timer2.count) {
timer2.isOverflowed=true;
timer2.base=new_ticks;
}
if (timer2.isOverflowed || !timer2.isMasked) {
ret|=0xA0;
}
}
return ret;
}
static void write_p388(Bit32u port,Bit8u val) {
regsel=val;
}
static void write_p389(Bit32u port,Bit8u val) {
switch (regsel) {
case 0x02: /* Timer 1 */
timer1.count=(val*80/1000);
return;
case 0x03: /* Timer 2 */
timer2.count=(val*320/1000);
return;
case 0x04: /* IRQ clear / mask and Timer enable */
if (val&0x80) {
timer1.isOverflowed=false;
timer2.isOverflowed=false;
return;
}
if (val&0x40) {
timer1.isMasked=true;
} else {
timer1.isMasked=false;
timer1.isEnabled=((val&1)>0);
timer1.base=GetTicks();
}
if (val&0x20) {
timer2.isMasked=true;
} else {
timer2.isMasked=false;
timer2.isEnabled=((val&2)>0);
timer2.base=GetTicks();
}
return;
default: /* Normal OPL call queue it */
MAME::OPLWriteReg(myopl,regsel,val);
}
}
static HWBlock hw_adlib;
static bool adlib_enabled;
static void ADLIB_Enable(bool enable) {
if (enable) {
adlib_enabled=true;
MIXER_Enable(adlib_chan,true);
IO_RegisterWriteHandler(0x388,write_p388,"ADLIB Register select");
IO_RegisterWriteHandler(0x389,write_p389,"ADLIB Data Write");
IO_RegisterReadHandler(0x388,read_p388,"ADLIB Status");
IO_RegisterWriteHandler(0x220,write_p388,"ADLIB Register select");
IO_RegisterWriteHandler(0x221,write_p389,"ADLIB Data Write");
IO_RegisterReadHandler(0x220,read_p388,"ADLIB Status");
} else {
adlib_enabled=false;
MIXER_Enable(adlib_chan,false);
IO_FreeWriteHandler(0x220);
IO_FreeWriteHandler(0x221);
IO_FreeReadHandler(0x220);
IO_FreeWriteHandler(0x388);
IO_FreeWriteHandler(0x389);
IO_FreeReadHandler(0x388);
}
}
static void ADLIB_InputHandler(char * line) {
bool s_off=ScanCMDBool(line,"OFF");
bool s_on=ScanCMDBool(line,"ON");
char * rem=ScanCMDRemain(line);
if (rem) {
sprintf(line,"Illegal Switch");
return;
}
if (s_on && s_off) {
sprintf(line,"Can't use /ON and /OFF at the same time");
return;
}
if (s_on) {
ADLIB_Enable(true);
sprintf(line,"Adlib has been enabled");
return;
}
if (s_off) {
ADLIB_Enable(false);
sprintf(line,"Adlib has been disabled");
return;
}
return;
}
static void ADLIB_OutputHandler (char * towrite) {
if(adlib_enabled) {
sprintf(towrite,"IO %X",0x388);
} else {
sprintf(towrite,"Disabled");
}
};
void ADLIB_Init(void) {
timer1.isMasked=true;
timer1.base=0;
timer1.count=0;
timer1.isEnabled=false;
timer1.isOverflowed=false;
timer2.isMasked=true;
timer2.base=0;
timer2.count=0;
timer2.isEnabled=false;
timer2.isOverflowed=false;
#define ADLIB_FREQ 22050
myopl=MAME::OPLCreate(0,OPL_INTERNAL_FREQ,ADLIB_FREQ);
adlib_chan=MIXER_AddChannel(ADLIB_CallBack,ADLIB_FREQ,"ADLIB");
MIXER_SetMode(adlib_chan,MIXER_16MONO);
hw_adlib.dev_name="ADLIB";
hw_adlib.full_name="Adlib FM Synthesizer";
hw_adlib.next=0;
hw_adlib.help="/ON Enables Adlib\n/OFF Disables Adlib\n";
hw_adlib.get_input=ADLIB_InputHandler;
hw_adlib.show_status=ADLIB_OutputHandler;
HW_Register(&hw_adlib);
ADLIB_Enable(true);
};

225
src/hardware/dma.cpp Normal file
View file

@ -0,0 +1,225 @@
/*
* 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.
*/
/*
Based the port handling from the bochs dma code.
*/
/*
Still need to implement reads from dma ports :)
Perhaps sometime also implement dma writes.
DMA transfer that get setup with a size 0 are also done wrong should be 0x10000 probably.
*/
#include <string.h>
#include "dosbox.h"
#include "mem.h"
#include "inout.h"
#include "dma.h"
#ifdef DEBUG_DMA
#define DMA_DEBUG LOG_DEBUG
#else
#define DMA_DEBUG
#endif
#define DMA_MODE_DEMAND 0
#define DMA_MODE_SINGLE 1
#define DMA_MODE_BLOCK 2
#define DMA_MODE_CASCADE 3
struct DMA_CHANNEL {
struct {
Bit8u mode_type;
Bit8u address_decrement;
Bit8u autoinit_enable;
Bit8u transfer_type;
} mode;
Bit16u base_address;
Bit16u base_count;
Bit16u current_address;
Bit32u current_count;
Bit8u page;
bool masked;
HostPt host_address;
bool addr_changed;
};
struct DMA_CONTROLLER {
bool flipflop;
Bit8u status_reg;
Bit8u command_reg;
DMA_CHANNEL chan[4];
};
static DMA_CONTROLLER dma[2];
static void write_dma(Bit32u port,Bit8u val) {
/* only use first dma for now */
DMA_CONTROLLER * cont=&dma[0];
DMA_CHANNEL * chan=&cont->chan[port>>1];
switch (port) {
case 0x00:case 0x02:case 0x04:case 0x06:
if (cont->flipflop) {
chan->base_address=val;
} else {
chan->base_address|=(val<<8);
}
cont->flipflop=!cont->flipflop;
chan->addr_changed=true;
break;
case 0x01:case 0x03:case 0x05:case 0x07:
if (cont->flipflop) {
chan->base_count=val;
} else {
chan->base_count|=(val<<8);
}
cont->flipflop=!cont->flipflop;
chan->addr_changed=true;
break;
case 0x08: /* Command Register */
if (val != 4) LOG_WARN("DMA1:Illegal command %2X",val);
cont->command_reg=val;
break;
case 0x09: /* Request Register */
if (val&4) {
/* Set Request bit */
} else {
Bitu channel = val & 0x03;
cont->status_reg &= ~(1 << (channel+4));
}
break;
case 0x0a: /* single mask bit register */
chan->masked=(val & 4)>0;
break;
case 0x0b: /* mode register */
chan->mode.mode_type = (val >> 6) & 0x03;
chan->mode.address_decrement = (val >> 5) & 0x01;
chan->mode.autoinit_enable = (val >> 4) & 0x01;
chan->mode.transfer_type = (val >> 2) & 0x03;
if (chan->mode.address_decrement) {
LOG_WARN("DMA:Address Decrease not supported yet");
}
break;
case 0x0c: /* Clear Flip/Flip */
cont->flipflop=true;
break;
};
};
static Bit8u channelindex[7] = {2, 3, 1, 0, 0, 0, 0};
void write_dma_page(Bit32u port,Bit8u val) {
switch (port) {
case 0x81: /* dma0 page register, channel 2 */
case 0x82: /* dma0 page register, channel 3 */
case 0x83: /* dma0 page register, channel 1 */
case 0x87: /* dma0 page register, channel 0 */
Bitu channel = channelindex[port - 0x81];
dma[0].chan[channel].page=val;
dma[0].chan[channel].addr_changed=true;
break;
}
}
void DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
DMA_CHANNEL * chan=&dma[0].chan[dmachan];
/* DMA always does autoinit should work under normal situations */
if (chan->addr_changed) {
/* Calculate the new starting position for dma read*/
chan->addr_changed=false;
chan->host_address=memory+(chan->page << 16)+chan->base_address;
chan->current_count=chan->base_count+1;
chan->current_address=chan->base_address;
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) {
memcpy(buffer,chan->host_address,count);
chan->host_address+=count;
chan->current_address+=count;
chan->current_count-=count;
return;
} else {
/* Copy remaining piece of first buffer */
memcpy(buffer,chan->host_address,chan->current_count);
buffer+=chan->current_count;
count-=(Bit16u)chan->current_count;
/* Autoinit reset the dma channel */
chan->host_address=memory+(chan->page << 16)+chan->base_address;
chan->current_count=chan->base_count+1;
chan->current_address=chan->base_address;
/* Copy the rest of the buffer */
memcpy(buffer,chan->host_address,count);
chan->host_address+=count;
chan->current_address+=count;
chan->current_count-=count;
return;
}
};
void 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;
};
void DMA_16_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
}
void DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
}
void DMA_Init(void) {
for (Bit32u i=0;i<0x10;i++) {
IO_RegisterWriteHandler(i,write_dma,"DMA1");
}
IO_RegisterWriteHandler(0x81,write_dma_page,"DMA Pages");
IO_RegisterWriteHandler(0x82,write_dma_page,"DMA Pages");
IO_RegisterWriteHandler(0x83,write_dma_page,"DMA Pages");
IO_RegisterWriteHandler(0x87,write_dma_page,"DMA Pages");
}

9730
src/hardware/ega-switch.h Normal file

File diff suppressed because it is too large Load diff

1878
src/hardware/fmopl.c Normal file

File diff suppressed because it is too large Load diff

191
src/hardware/fmopl.h Normal file
View file

@ -0,0 +1,191 @@
#ifndef __FMOPL_H_
#define __FMOPL_H_
/* --- select emulation chips --- */
#define BUILD_YM3812 (HAS_YM3812)
#define BUILD_YM3526 (HAS_YM3526)
#define BUILD_Y8950 (HAS_Y8950)
/* --- system optimize --- */
/* select bit size of output : 8 or 16 */
#define OPL_SAMPLE_BITS 16
/* compiler dependence */
#ifndef OSD_CPU_H
#define OSD_CPU_H
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
#endif
#if (OPL_SAMPLE_BITS==16)
typedef INT16 OPLSAMPLE;
#endif
#if (OPL_SAMPLE_BITS==8)
typedef unsigned char OPLSAMPLE;
#endif
#if BUILD_Y8950
#include "ymdeltat.h"
#endif
typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
typedef void (*OPL_IRQHANDLER)(int param,int irq);
typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
/* !!!!! here is private section , do not access there member direct !!!!! */
#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
#define OPL_TYPE_IO 0x08 /* I/O port */
/* Saving is necessary for member of the 'R' mark for suspend/resume */
/* ---------- OPL slot ---------- */
typedef struct fm_opl_slot {
const UINT32 *AR; /* attack rate tab :&eg_table[AR<<2]*/
const UINT32 *DR; /* decay rate tab :&eg_table[DR<<2]*/
const UINT32 *RR; /* release rate tab:&eg_table[RR<<2]*/
UINT8 KSR; /* key scale rate */
UINT8 ARval; /* current AR */
UINT8 ksl; /* keyscale level */
UINT8 ksr; /* key scale rate :kcode>>KSR */
UINT8 mul; /* multiple :ML_TABLE[ML] */
/* Phase Generator */
UINT32 Cnt; /* frequency count */
UINT32 Incr; /* frequency step */
/* Envelope Generator */
UINT8 eg_type; /* percussive/non-percussive mode */
UINT8 state; /* phase type */
UINT32 TL; /* total level :TL << 3 */
INT32 TLL; /* adjusted now TL */
INT32 volume; /* envelope counter */
UINT32 sl; /* sustain level :SL_TABLE[SL] */
UINT32 delta_ar; /* envelope step for Attack */
UINT32 delta_dr; /* envelope step for Decay */
UINT32 delta_rr; /* envelope step for Release */
UINT32 key; /* 0 = KEY OFF, >0 = KEY ON */
/* LFO */
UINT32 AMmask; /* LFO Amplitude Modulation enable mask */
UINT8 vib; /* LFO Phase Modulation enable flag (active high)*/
/* waveform select */
unsigned int *wavetable;
}OPL_SLOT;
/* ---------- OPL one of channel ---------- */
typedef struct fm_opl_channel {
OPL_SLOT SLOT[2];
UINT8 FB; /* feedback shift value */
INT32 *connect1; /* slot1 output pointer */
INT32 op1_out[2]; /* slot1 output for feedback */
/* phase generator state */
UINT32 block_fnum; /* block+fnum */
UINT32 fc; /* Freq. Increment base */
UINT32 ksl_base; /* KeyScaleLevel Base step */
UINT8 kcode; /* key code (for key scaling) */
UINT8 CON; /* connection (algorithm) type */
} OPL_CH;
/* OPL state */
typedef struct fm_opl_f {
/* FM channel slots */
OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels */
UINT8 rhythm; /* Rhythm mode */
UINT32 eg_tab[16+64+16]; /* EG rate table: 16 (dummy) + 64 rates + 16 RKS */
UINT32 fn_tab[1024]; /* fnumber -> increment counter */
/* LFO */
UINT8 lfo_am_depth;
UINT8 lfo_pm_depth_range;
UINT32 lfo_am_cnt;
UINT32 lfo_am_inc;
UINT32 lfo_pm_cnt;
UINT32 lfo_pm_inc;
UINT32 noise_rng; /* 23 bit noise shift register */
UINT32 noise_p; /* current noise 'phase' */
UINT32 noise_f; /* current noise period */
UINT8 wavesel; /* waveform select enable flag */
int T[2]; /* timer counters */
UINT8 st[2]; /* timer enable */
#if BUILD_Y8950
/* Delta-T ADPCM unit (Y8950) */
YM_DELTAT *deltat;
/* Keyboard / I/O interface unit*/
UINT8 portDirection;
UINT8 portLatch;
OPL_PORTHANDLER_R porthandler_r;
OPL_PORTHANDLER_W porthandler_w;
int port_param;
OPL_PORTHANDLER_R keyboardhandler_r;
OPL_PORTHANDLER_W keyboardhandler_w;
int keyboard_param;
#endif
/* external event callback handlers */
OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
int TimerParam; /* TIMER parameter */
OPL_IRQHANDLER IRQHandler; /* IRQ handler */
int IRQParam; /* IRQ parameter */
OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
int UpdateParam; /* stream update parameter */
UINT8 type; /* chip type */
UINT8 address; /* address register */
UINT8 status; /* status flag */
UINT8 statusmask; /* status mask */
UINT8 mode; /* Reg.08 : CSM,notesel,etc. */
int clock; /* master clock (Hz) */
int rate; /* sampling rate (Hz) */
double freqbase; /* frequency base */
double TimerBase; /* Timer base time (==sampling time)*/
} FM_OPL;
/* ---------- Generic interface section ---------- */
#define OPL_TYPE_YM3526 (0)
#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
FM_OPL *OPLCreate(int type, int clock, int rate);
void OPLDestroy(FM_OPL *OPL);
void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
/* Y8950 port handlers */
void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
void OPLResetChip(FM_OPL *OPL);
int OPLWrite(FM_OPL *OPL,int a,int v);
unsigned char OPLRead(FM_OPL *OPL,int a);
int OPLTimerOver(FM_OPL *OPL,int c);
/* YM3626/YM3812 local section */
void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
#endif

2562
src/hardware/font-switch.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,256 @@
/*
* 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 <math.h>
#include "dosbox.h"
#include "inout.h"
#include "mixer.h"
#include "mem.h"
#include "hardware.h"
#define CMS_RATE 22050
#define CMS_VOLUME 6000
#define FREQ_SHIFT 16
#define SIN_ENT 1024
#define SIN_MAX (SIN_ENT << FREQ_SHIFT)
#ifndef PI
#define PI 3.14159265358979323846
#endif
struct CMS {
struct {
Bit32u freq_pos;
Bit32u freq_add;
Bit16s * vol_left;
Bit16s * vol_right;
Bit8u octave;
Bit8u freq;
} chan[6];
struct {
Bit32u freq_pos;
Bit32u freq_add;
Bit32u random_val;
} noise[2];
Bit8u voice_enabled;
Bit8u noise_enabled;
Bit8u reg;
};
static Bit32u freq_table[256][8];
static Bit32u noise_freq[3];
static Bit16s vol_table[16];
static Bit16s sin_table[16][SIN_ENT];
static MIXER_Channel * cms_chan;
static CMS cms_block[2];
static void write_cms(Bit32u port,Bit8u val) {
Bit32u sel=(port>>1)&1;
CMS * cms=&cms_block[sel];
switch (port & 1) {
case 1: /* Register Select */
cms->reg=val;
break;
case 0: /* Write Register */
switch (cms->reg) {
case 0x00: case 0x01: case 0x02: /* Volume Select */
case 0x03: case 0x04: case 0x05:
cms->chan[cms->reg].vol_left=sin_table[val & 0xf];
cms->chan[cms->reg].vol_right=sin_table[(val>>4) & 0xf];
break;
case 0x08: case 0x09: case 0x0a: /* Frequency Select */
case 0x0b: case 0x0c: case 0x0d:
{
Bit8u chan=cms->reg-0x08;
cms->chan[chan].freq=val;
/* Get a new entry in the freq table */
cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave];
break;
}
case 0x10: case 0x11: case 0x12: /* Octave Select */
{
Bit8u chan=(cms->reg-0x10)*2;
cms->chan[chan].octave=val&7;
cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave];
chan++;
cms->chan[chan].octave=(val>>4)&7;
cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave];
}
break;
case 0x14: /* Frequency enable */
cms->voice_enabled=val;
//TODO Check for enabling of speaker maybe
break;
case 0x15: /* Noise Enable */
cms->noise_enabled=val;
//TODO Check for enabling of speaker maybe
break;
case 0x16: /* Noise generator setup */
cms->noise[0].freq_add=noise_freq[val & 3];
cms->noise[1].freq_add=noise_freq[(val>>4) & 3];
break;
default:
LOG_ERROR("CMS %d:Illegal register %X2 Selected for write",sel,cms->reg);
break;
};
break;
}
};
static void CMS_CallBack(Bit8u * stream,Bit32u len) {
/* Generate the CMS wave */
/* Generate 12 channels of sound data this could be nice */
for (Bit32u l=0;l<len;l++) {
register Bit32s left,right;
left=right=0;
for (int c=0;c<2;c++) {
CMS * cms=&cms_block[c];
Bit8u use_voice=1;
for (int chan=0;chan<6;chan++) {
if (cms->noise_enabled & use_voice) {
} else if (cms->voice_enabled & use_voice) {
int pos=cms->chan[chan].freq_pos>>FREQ_SHIFT;
left+=cms->chan[chan].vol_left[pos];
right+=cms->chan[chan].vol_right[pos];
cms->chan[chan].freq_pos+=cms->chan[chan].freq_add;
if (cms->chan[chan].freq_pos>=SIN_MAX)
cms->chan[chan].freq_pos-=SIN_MAX;
}
use_voice<<=1;
}
}
if (left>MAX_AUDIO) *(Bit16s *)stream=MAX_AUDIO;
else if (left<MIN_AUDIO) *(Bit16s *)stream=MIN_AUDIO;
else *(Bit16s *)stream=(Bit16s)left;
stream+=2;
if (right>MAX_AUDIO) *(Bit16s *)stream=MAX_AUDIO;
else if (right<MIN_AUDIO) *(Bit16s *)stream=MIN_AUDIO;
else *(Bit16s *)stream=(Bit16s)right;
stream+=2;
}
}
static HWBlock hw_cms;
static bool cms_enabled;
static void CMS_Enable(bool enable) {
if (enable) {
cms_enabled=true;
MIXER_Enable(cms_chan,true);
IO_RegisterWriteHandler(0x220,write_cms,"CMS");
IO_RegisterWriteHandler(0x221,write_cms,"CMS");
IO_RegisterWriteHandler(0x222,write_cms,"CMS");
IO_RegisterWriteHandler(0x223,write_cms,"CMS");
} else {
cms_enabled=false;
MIXER_Enable(cms_chan,false);
IO_FreeWriteHandler(0x220);
IO_FreeWriteHandler(0x221);
IO_FreeWriteHandler(0x222);
IO_FreeWriteHandler(0x223);
}
}
static void CMS_InputHandler(char * line) {
bool s_off=ScanCMDBool(line,"OFF");
bool s_on=ScanCMDBool(line,"ON");
char * rem=ScanCMDRemain(line);
if (rem) {
sprintf(line,"Illegal Switch");
return;
}
if (s_on && s_off) {
sprintf(line,"Can't use /ON and /OFF at the same time");
return;
}
if (s_on) {
CMS_Enable(true);
sprintf(line,"Creative Music System has been enabled");
return;
}
if (s_off) {
CMS_Enable(false);
sprintf(line,"Creative Music System has been disabled");
return;
}
return;
}
static void CMS_OutputHandler (char * towrite) {
if(cms_enabled) {
sprintf(towrite,"IO %X",0x220);
} else {
sprintf(towrite,"Disabled");
}
};
void CMS_Init(void) {
Bits i;
/* Register the Mixer CallBack */
cms_chan=MIXER_AddChannel(CMS_CallBack,CMS_RATE,"CMS");
MIXER_SetMode(cms_chan,MIXER_16STEREO);
MIXER_Enable(cms_chan,false);
/* Register with the hardware setup tool */
hw_cms.dev_name="CMS";
hw_cms.full_name="Creative Music System";
hw_cms.next=0;
hw_cms.help="/ON Enables CMS\n/OFF Disables CMS\n";
hw_cms.get_input=CMS_InputHandler;
hw_cms.show_status=CMS_OutputHandler;
HW_Register(&hw_cms);
CMS_Enable(false);
/* Make the frequency/octave table */
double log_start=log10(27.34375);
double log_add=(log10(54.609375)-log10(27.34375))/256;
for (i=0;i<256;i++) {
double freq=pow(10,log_start);
for (int k=0;k<8;k++) {
freq_table[i][k]=(Bit32u)((double)SIN_MAX/(CMS_RATE/freq));
freq*=2;
}
log_start+=log_add;
}
// noise_freq[0]=(Bit32u)(FREQ_MAX/((float)CMS_RATE/(float)28000));
// noise_freq[1]=(Bit32u)(FREQ_MAX/((float)CMS_RATE/(float)14000));
// noise_freq[2]=(Bit32u)(FREQ_MAX/((float)CMS_RATE/(float)6800));
for (int s=0;s<SIN_ENT;s++) {
double out=sin( (2*PI/SIN_ENT)*s)*CMS_VOLUME;
for (i=15;i>=0;i--) {
sin_table[i][s]=(Bit16s)out;
// out /= (float)1.258925412; /* = 10 ^ (2/20) = 2dB */
out /= 1.1;
}
}
}

Some files were not shown because too many files have changed in this diff Show more