First CVS upload.
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@80
This commit is contained in:
parent
7d1ca9bdd4
commit
42e5d0b779
158 changed files with 42940 additions and 0 deletions
8
AUTHORS
Normal file
8
AUTHORS
Normal 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
340
COPYING
Normal 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
3
ChangeLog
Normal 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
36
INSTALL
Normal 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
7
Makefile.am
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Main Makefile for DOSBox
|
||||
|
||||
EXTRA_DIST = settings.h autogen.sh
|
||||
SUBDIRS = src include visualc
|
||||
|
||||
|
||||
|
23
NEWS
Normal file
23
NEWS
Normal 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
93
README
Normal 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
8
THANKS
Normal 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
1
VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
0.50
|
161
acinclude.m4
Normal file
161
acinclude.m4
Normal 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, µ) != 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
1368
config.guess
vendored
Normal file
File diff suppressed because it is too large
Load diff
61
configure.in
Normal file
61
configure.in
Normal 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
29
include/Makefile.am
Normal 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
120
include/bios.h
Normal 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
56
include/callback.h
Normal 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
99
include/cpu.h
Normal 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
54
include/cross.h
Normal 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
24
include/debug.h
Normal 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
24
include/dma.h
Normal 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
275
include/dos_inc.h
Normal 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
105
include/dos_system.h
Normal 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
63
include/dosbox.h
Normal 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
1
include/fpu.h
Normal file
|
@ -0,0 +1 @@
|
|||
|
44
include/hardware.h
Normal file
44
include/hardware.h
Normal 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
48
include/inout.h
Normal 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
25
include/joystick.h
Normal 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
54
include/keyboard.h
Normal 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
206
include/mem.h
Normal 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
42
include/mixer.h
Normal 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
180
include/modules.h
Normal 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
28
include/mouse.h
Normal 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
44
include/pic.h
Normal 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
58
include/programs.h
Normal 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
114
include/regs.h
Normal 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
25
include/render.h
Normal 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
43
include/setup.h
Normal 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
63
include/support.h
Normal 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
53
include/timer.h
Normal 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
50
include/video.h
Normal 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
32
scripts/ega-switch.pl
Normal 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
25
scripts/font-switch.pl
Normal 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
26
settings.h.cvs
Normal 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
10
src/Makefile.am
Normal 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
5
src/cpu/Makefile.am
Normal 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
171
src/cpu/callback.cpp
Normal 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
3
src/cpu/core_16/Makefile.am
Normal file
3
src/cpu/core_16/Makefile.am
Normal 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
76
src/cpu/core_16/helpers.h
Normal 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);}
|
593
src/cpu/core_16/instructions.h
Normal file
593
src/cpu/core_16/instructions.h
Normal 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
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
469
src/cpu/core_16/prefix_66.h
Normal 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;
|
||||
}
|
||||
|
||||
|
124
src/cpu/core_16/prefix_66_of.h
Normal file
124
src/cpu/core_16/prefix_66_of.h
Normal 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
188
src/cpu/core_16/prefix_of.h
Normal 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
20
src/cpu/core_16/start.h
Normal 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
19
src/cpu/core_16/stop.h
Normal 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
191
src/cpu/core_16/support.h
Normal 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
283
src/cpu/core_16/table_ea.h
Normal 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
185
src/cpu/cpu.cpp
Normal 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
582
src/cpu/flags.cpp
Normal 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
210
src/cpu/modrm.cpp
Normal 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[]=
|
||||
{
|
||||
®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al,
|
||||
®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,
|
||||
®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,
|
||||
®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,
|
||||
®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,
|
||||
®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,
|
||||
®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,
|
||||
®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,
|
||||
|
||||
®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al,
|
||||
®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,
|
||||
®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,
|
||||
®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,
|
||||
®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,
|
||||
®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,
|
||||
®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,
|
||||
®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,
|
||||
|
||||
®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al,
|
||||
®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,
|
||||
®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,
|
||||
®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,
|
||||
®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,
|
||||
®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,
|
||||
®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,
|
||||
®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,
|
||||
|
||||
®_al,®_al,®_al,®_al,®_al,®_al,®_al,®_al,
|
||||
®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,®_cl,
|
||||
®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,®_dl,
|
||||
®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,®_bl,
|
||||
®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,®_ah,
|
||||
®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,®_ch,
|
||||
®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,®_dh,
|
||||
®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh,®_bh
|
||||
};
|
||||
|
||||
Bit16u * lookupRMregw[]={
|
||||
®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,
|
||||
®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,
|
||||
®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,
|
||||
®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,
|
||||
®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,
|
||||
®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,
|
||||
®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si,
|
||||
®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di,
|
||||
|
||||
®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,
|
||||
®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,
|
||||
®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,
|
||||
®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,
|
||||
®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,
|
||||
®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,
|
||||
®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si,
|
||||
®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di,
|
||||
|
||||
®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,
|
||||
®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,
|
||||
®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,
|
||||
®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,
|
||||
®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,
|
||||
®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,
|
||||
®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si,
|
||||
®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di,
|
||||
|
||||
®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,®_ax,
|
||||
®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,®_cx,
|
||||
®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,®_dx,
|
||||
®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,®_bx,
|
||||
®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,®_sp,
|
||||
®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,®_bp,
|
||||
®_si,®_si,®_si,®_si,®_si,®_si,®_si,®_si,
|
||||
®_di,®_di,®_di,®_di,®_di,®_di,®_di,®_di
|
||||
};
|
||||
|
||||
Bit32u * lookupRMregd[256]={
|
||||
®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,
|
||||
®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,
|
||||
®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,
|
||||
®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,
|
||||
®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,
|
||||
®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,
|
||||
®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,
|
||||
®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,
|
||||
|
||||
®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,
|
||||
®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,
|
||||
®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,
|
||||
®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,
|
||||
®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,
|
||||
®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,
|
||||
®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,
|
||||
®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,
|
||||
|
||||
®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,
|
||||
®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,
|
||||
®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,
|
||||
®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,
|
||||
®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,
|
||||
®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,
|
||||
®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,
|
||||
®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,
|
||||
|
||||
®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,®_eax,
|
||||
®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,®_ecx,
|
||||
®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,®_edx,
|
||||
®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,®_ebx,
|
||||
®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,®_esp,
|
||||
®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,®_ebp,
|
||||
®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,®_esi,
|
||||
®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_edi,®_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,
|
||||
®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
|
||||
®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
|
||||
®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
|
||||
®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
|
||||
®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
|
||||
®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
|
||||
®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_bh,
|
||||
®_al,®_cl,®_dl,®_bl,®_ah,®_ch,®_dh,®_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,
|
||||
®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
|
||||
®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
|
||||
®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
|
||||
®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
|
||||
®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
|
||||
®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
|
||||
®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_di,
|
||||
®_ax,®_cx,®_dx,®_bx,®_sp,®_bp,®_si,®_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,
|
||||
®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
|
||||
®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
|
||||
®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
|
||||
®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
|
||||
®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
|
||||
®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
|
||||
®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi,
|
||||
®_eax,®_ecx,®_edx,®_ebx,®_esp,®_ebp,®_esi,®_edi
|
||||
};
|
||||
|
||||
|
76
src/cpu/modrm.h
Normal file
76
src/cpu/modrm.h
Normal 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
120
src/cpu/slow_16.cpp
Normal 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
5
src/debug/Makefile.am
Normal 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
257
src/debug/debug.cpp
Normal 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
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
130
src/debug/debug_gui.cpp
Normal 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
52
src/debug/debug_inc.h
Normal 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
74
src/debug/debug_win32.cpp
Normal 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
191
src/debug/disasm_tables.h
Normal 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
7
src/dos/Makefile.am
Normal 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
105
src/dos/dev_con.h
Normal 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
790
src/dos/dos.cpp
Normal 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,®_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,§ors,&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,®_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,®_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,®_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,®_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
181
src/dos/dos_classes.cpp
Normal 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
77
src/dos/dos_devices.cpp
Normal 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
439
src/dos/dos_execute.cpp
Normal 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
614
src/dos/dos_files.cpp
Normal 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
60
src/dos/dos_ioctl.cpp
Normal 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
162
src/dos/dos_memory.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright (C) 2002 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#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
69
src/dos/dos_misc.cpp
Normal 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
210
src/dos/dos_programs.cpp
Normal 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
54
src/dos/dos_tables.cpp
Normal 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
277
src/dos/drive_local.cpp
Normal 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
205
src/dos/drive_virtual.cpp
Normal 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
31
src/dos/drives.cpp
Normal 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
71
src/dos/drives.h
Normal 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
297
src/dosbox.cpp
Normal 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
75
src/dosbox.lang
Normal 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
4
src/fpu/Makefile.am
Normal 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
62
src/fpu/fpu.cpp
Normal 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
21
src/fpu/fpu_load.h
Normal 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
5
src/gui/Makefile.am
Normal 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
160
src/gui/render.cpp
Normal 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
513
src/gui/sdlmain.cpp
Normal 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
11
src/hardware/Makefile.am
Normal 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
224
src/hardware/adlib.cpp
Normal 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
225
src/hardware/dma.cpp
Normal 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
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
1878
src/hardware/fmopl.c
Normal file
File diff suppressed because it is too large
Load diff
191
src/hardware/fmopl.h
Normal file
191
src/hardware/fmopl.h
Normal 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
2562
src/hardware/font-switch.h
Normal file
File diff suppressed because it is too large
Load diff
256
src/hardware/gameblaster.cpp
Normal file
256
src/hardware/gameblaster.cpp
Normal 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
Loading…
Add table
Reference in a new issue