DOSBox 0.62

This commit is contained in:
Carl.Kenner 2009-05-02 22:02:15 +00:00
parent a0ed243c23
commit 6a0c0c74c0
204 changed files with 25683 additions and 25101 deletions

View File

@ -1,9 +1,8 @@
The DOSBox Team
---------------
Sjoerd v.d. Berg <harekiet@zophar.net>
Sjoerd v.d. Berg <harekiet@users.sourceforge.net>
Peter Veenstra <qbix79@users.sourceforge.net>
Felix Jakschitsch <yot@users.sourceforge.net>
Ulf Wohlers <finsterr@users.sourceforge.net>
Tommy Frössman <fanskapet@php-coders.net>
Tommy Frössman <fanskapet@sidvicious.se>
Dean Beeler <canadacow@users.sourceforge.net>

View File

@ -1,3 +1,65 @@
0.62
- Added blinking support in the shell and some color fixes.
- Fixed commandline parsing when .bat files involved (fixes -exit)
- Fixed issues with tabs in commandline not being processed correctly.
- Cleaned/improved shutdown sequence.
- Added some more bios functions (wait and delay functions).
- Made our XMS driver conform the specs better. (c2woody)
- Added support for some more ems functions.
- Added intelligent mpu401 emulation. (Srecko)
- Added soundblaster 16 emulation.
- Rewrote GUS emulation to sound more authentic.
- Improved pc speaker emulation.
- Added an internal (programmable) mixer.
- Added support a few soundblaster/adlib detection routines.
- Fixed lot's of bugs related to DMA transfers.
- Added interpolating prebuffering mixer routines.
- Added recording of OPL commands and raw midi.
- Fixed some bugs with the wave recording.
- Changed sensitivity settings of the mouse.
- Added ps2 mouse-emulation in bios interrupts (c2woody).
- Fixed some bugs with mouse emulation limits.
- Fixed a bug with an unterminated string in the drivelabel.
- Changed file search routines a bit to be more compatible.
- Added support for attribute-searching with fcb's.
- Added basic SDA.
- Added TPA and DIB.
- Added Lot's of missing dos tables (c2woody).
- Changed psp and dta functions to use dta.
- Returned filename in ds:dx in create-random-file (c2woody).
- Fixed a bug with date and time used on open files.
- Some mscdex fixes.
- Added the -version switch, which makes dosbox report its version.
- Added a keymapper.
- Added basic IPX emulation.
- Added cdrom iso support and floppy images support.
- Added the possibity to boot another dos version.
- Added Serial passthrough support (win32 only).
- Added the possibility to pause dosbox.
- Changed OpenGL so that it is initialized only when used.
- Make dosbox run at higher priority when active and lower when inactive.
- Added direct draw output support (win32 only).
- Added current running program to title bar.
- Rewrote video emulation to support new scalers.
- Added new graphics scalers like advmame3x,tv2x.
- Added a support for a few anti-debugger tricks.
- Improved the handling of the tab-key.
- Improved support for the numeric keyboard.
- Fixed a few cpu opcodes.
- Added cpu core simple (for lowerend machines)
- Fixed some nasty bugs in the dynamic cpu core.
- Added a few (rarely used) fpu opcodes.
- Fixed various issues with GCC 3.4.
- Many internal timer improvements (PIT and PIC).
- Added some more PIC commands (c2woody).
- Added BCD counting to the timers.
- Fix some vesa functions.
- Add some basic support for 132x25 and 132x45 textmodes.
- Improved Tandy emulation a lot.
- Lowered cpu usage when dosbox is idle.
- Allow virtualisation of some basic IO-ports (c2woody).
0.61
- Added a beta dynamic cpu for x86 hosts (very unstable)
- Added opengl and hardware overlay display output

View File

@ -3,5 +3,6 @@
EXTRA_DIST = autogen.sh
SUBDIRS = src include visualc docs visualc_net
docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = README NEWS THANKS AUTHORS

View File

@ -134,12 +134,17 @@ target_vendor = @target_vendor@
EXTRA_DIST = autogen.sh
SUBDIRS = src include visualc docs visualc_net
docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = README NEWS THANKS AUTHORS
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
DATA = $(doc_DATA)
RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
ps-recursive install-info-recursive uninstall-info-recursive \
@ -189,6 +194,24 @@ $(srcdir)/config.h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4)
distclean-hdr:
-rm -f config.h stamp-h1
uninstall-info-am:
docDATA_INSTALL = $(INSTALL_DATA)
install-docDATA: $(doc_DATA)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(docdir)
@list='$(doc_DATA)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " $(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f"; \
$(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f; \
done
uninstall-docDATA:
@$(NORMAL_UNINSTALL)
@list='$(doc_DATA)'; for p in $$list; do \
f="`echo $$p | sed -e 's|^.*/||'`"; \
echo " rm -f $(DESTDIR)$(docdir)/$$f"; \
rm -f $(DESTDIR)$(docdir)/$$f; \
done
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
@ -446,9 +469,10 @@ distcleancheck: distclean
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile config.h
all-am: Makefile $(DATA) config.h
installdirs: installdirs-recursive
installdirs-am:
$(mkinstalldirs) $(DESTDIR)$(docdir)
install: install-recursive
install-exec: install-exec-recursive
@ -491,7 +515,7 @@ info: info-recursive
info-am:
install-data-am:
install-data-am: install-docDATA
install-exec-am:
@ -519,7 +543,7 @@ ps: ps-recursive
ps-am:
uninstall-am: uninstall-info-am
uninstall-am: uninstall-docDATA uninstall-info-am
uninstall-info: uninstall-info-recursive
@ -529,16 +553,17 @@ uninstall-info: uninstall-info-recursive
distclean-hdr distclean-recursive distclean-tags distcleancheck \
distdir distuninstallcheck dvi dvi-am dvi-recursive info \
info-am info-recursive install install-am install-data \
install-data-am install-data-recursive install-exec \
install-exec-am install-exec-recursive install-info \
install-info-am install-info-recursive install-man \
install-data-am install-data-recursive install-docDATA \
install-exec install-exec-am install-exec-recursive \
install-info install-info-am install-info-recursive install-man \
install-recursive install-strip installcheck installcheck-am \
installdirs installdirs-am installdirs-recursive \
maintainer-clean maintainer-clean-generic \
maintainer-clean-recursive mostlyclean mostlyclean-generic \
mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \
ps-recursive tags tags-recursive uninstall uninstall-am \
uninstall-info-am uninstall-info-recursive uninstall-recursive
uninstall-docDATA uninstall-info-am uninstall-info-recursive \
uninstall-recursive
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.

61
NEWS
View File

@ -1,3 +1,64 @@
0.62
- Added blinking support in the shell and some color fixes.
- Fixed commandline parsing when .bat files involved (fixes -exit)
- Fixed issues with tabs in commandline not being processed correctly.
- Cleaned/improved shutdown sequence.
- Added some more bios functions (wait and delay functions).
- Made our XMS driver conform the specs better. (c2woody)
- Added support for some more ems functions.
- Added intelligent mpu401 emulation. (Srecko)
- Added soundblaster 16 emulation.
- Rewrote GUS emulation to sound more authentic.
- Improved pc speaker emulation.
- Added an internal (programmable) mixer.
- Added support a few soundblaster/adlib detection routines.
- Fixed lot's of bugs related to DMA transfers.
- Added interpolating prebuffering mixer routines.
- Added recording of OPL commands and raw midi.
- Fixed some bugs with the wave recording.
- Changed sensitivity settings of the mouse.
- Added ps2 mouse-emulation in bios interrupts (c2woody).
- Fixed some bugs with mouse emulation limits.
- Fixed a bug with an unterminated string in the drivelabel.
- Changed file search routines a bit to be more compatible.
- Added support for attribute-searching with fcb's.
- Added basic SDA.
- Added TPA and DIB.
- Added Lot's of missing dos tables (c2woody).
- Changed psp and dta functions to use dta.
- Returned filename in ds:dx in create-random-file (c2woody).
- Fixed a bug with date and time used on open files.
- Some mscdex fixes.
- Added the -version switch, which makes dosbox report its version.
- Added a keymapper.
- Added basic IPX emulation.
- Added cdrom iso support and floppy images support.
- Added the possibity to boot another dos version.
- Added Serial passthrough support (win32 only).
- Added the possibility to pause dosbox.
- Changed OpenGL so that it is initialized only when used.
- Make dosbox run at higher priority when active and lower when inactive.
- Added direct draw output support (win32 only).
- Added current running program to title bar.
- Rewrote video emulation to support new scalers.
- Added new graphics scalers like advmame3x,tv2x.
- Added a support for a few anti-debugger tricks.
- Improved the handling of the tab-key.
- Improved support for the numeric keyboard.
- Fixed a few cpu opcodes.
- Added cpu core simple (for lowerend machines)
- Fixed some nasty bugs in the dynamic cpu core.
- Added a few (rarely used) fpu opcodes.
- Fixed various issues with GCC 3.4.
- Many internal timer improvements (PIT and PIC).
- Added some more PIC commands (c2woody).
- Added BCD counting to the timers.
- Fix some vesa functions.
- Add some basic support for 132x25 and 132x45 textmodes.
- Improved Tandy emulation a lot.
- Lowered cpu usage when dosbox is idle.
- Allow virtualisation of some basic IO-ports (c2woody).
0.61
- Added a beta dynamic cpu for x86 hosts (very unstable)
- Added opengl and hardware overlay display output

605
README
View File

@ -1,4 +1,5 @@
DOSBox v0.61
DOSBox v0.62
=====
NOTE:
@ -6,7 +7,7 @@ NOTE:
While we hope that, one day, DOSBox will run virtually all programs
ever made for the PC...we are not there yet. At present, DOSBox run on a high-
end machine will roughly be the equivalent of a lowend 486 PC. While the 0.60
end machine will roughly be the equivalent of a 486 PC. The 0.60
release has added support for "protected mode" allowing for more complex and
recent programs, but note that this support is early in development and
nowhere near as complete as the support for 386 real-mode games (or
@ -14,12 +15,180 @@ earlier). Also note that "protected mode" games need substantially more
resources and may require a much faster processor for you to run it properly
in DOSBox.
======
Usage:
INDEX:
======
1. Quickstart
2. FAQ
3. Usage
4. Internal Programs
5. Special Keys
6. Keymapper
7. System Requirements
8. To run resource-demanding games
9. The config file
10. The language file
11. Building your own version of DOSBox
12. Special thanks
13. Contact
==============
1. Quickstart:
==============
Type INTRO in DOSBox. That's it.
=======
2. FAQ:
=======
Some Frequently Asked Questions:
Q: I've got a Z instead of a C at the prompt.
Q: My CD-ROM doesn't work.
Q: The mouse doesn't work.
Q: The sound stutters.
Q: I can't type \ or : in DOSBox.
Q: The game/application can't find its CD-ROM.
Q: The game/application runs much too slow!
Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ.
Q: What sound hardware does DOSBox presently emulate?
Q: I've got a Z instead of a C at the prompt.
A: You have to make your directories available as drives in DOSBox by using
the "mount" command. For example, in Windows "mount C D:\" would give
you a C in DOSBox which points at your Windows D:\ drive.
In Linux, "mount c /home/username" would give you a C in DOSBox
which points at /home/username in Linux.
Q: My CD-ROM doesn't work.
A: To mount your cdrom in DOSBox you have to specify some additional options
when mounting the cdrom.
To enable the most basic cdrom support:
- mount d f:\ -t cdrom
To enable low-level SDL-support:
- mount d f:\ -t cdrom -usecd 0
To enable low-level ioctl-support(win2k/xp/linux):
- mount d f:\ -t cdrom -usecd 0 -ioctl
To enable low-level aspi-support (win98 with aspi-layer installed):
- mount d f:\ -t cdrom -usecd 0 -apsi
In the commands: - d driveletter you in DOSBox
- f:\ location of cdrom on your PC.
- 0 The number of the cdrom drive, reported by mount -cd
See also the question: The game/application can't find its CD-ROM.
Q: The mouse doesn't work.
A: Normally DOSBox detects the mouse being used by a game. If you click on
the screen then it should get locked and work.
Sometimes the DOSBox mouse detection doesn't work with certain games. You
might have to force to lock the mouse then with ctrl-F10.
Q: The sound stutters.
A: You're using too much cpu power to keep DOSBox running at the current speed.
You can either lower the cycles or skip frames or get a faster machine.
You can also increase the prebuffer in the configfile
Q: I can't type \ or : in DOSBox.
A: This is a known problem. It only occurs if your keyboard layout isn't US.
Some possible fixes:
1. Switch your keyboard layout.
2. Use / instead.
3. Add the commands you want to execute to dosbox.conf
4. Start the keymapper (CTRL-F1 or add -startmapper switch to dosbox)
5. for \ try the keys around "enter". For ":" try shift and the keys between
"enter" and "l" (US keyboard layout).
6. Use keyb.com for FreeDOS (http://projects.freedos.net/keyb/).
Q: The game/application can't find its CD-ROM.
A: Be sure to mount the CD-ROM with -t cdrom switch. Also try adding the
correct label (-label LABEL). To enable more low-level CD-ROM support add
the following switch to mount: -usecd #, where # is the number of your
CD-ROM drive reported by mount -cd. If you run Win32 you can specify -ioctl
or -aspi. Look at the description elsewhere in this document for their
meaning.
Q: The game/application runs much too slow!
A: Look at the section "To run resource-demanding games" for more information.
Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ.
A: This is possible! Just create a config file: config -writeconf dosbox.conf .
Start your favourite editor and look at all the settings present. To
start DOSBox with your new settings: dosbox -conf dosbox.conf
Q: What sound hardware does DOSBox presently emulate?
A: DOSBox emulates several legacy sound devices:
- Internal PC speaker
This emulation includes both the tone generator and several forms of
digital sound output through the internal speaker.
- Creative CMS/Gameblaster
The is the first card released by Creative Labs(R). The default
configuration places it on port 0x220. It should be noted that enabling
this with the Adlib emulation may result in conflicts.
- Tandy 3 voice
The emulation of this sound hardware is complete with the exception of
the noise channel, which is not very well documented and as such is only
a best guess as to the sound's accuracy.
- Adlib
Borrowed from MAME, this emulation is almost perfect and includes the
Adlib's ability to almost play digitized sound.
- SoundBlaster Pro
Coupled with the Adlib, DOSBox provides Soundblaster Pro level 8-bit
stereo sound.
- Disney Soundsource
Using the printer port, this sound device outputs digital sound only.
- Gravis Ultrasound
The emulation of this hardware is nearly complete, though the MIDI
capabilities have been left out since an MPU-401 has been
emulated in other code.
- MPU-401
A MIDI passthrough interface is also emulated. This method of sound
output will only work when used with a General Midi or MT-32 device.
Q: Great README, but I still don't get it.
A: While unlikely, this seems to happen. A look at "The Newbie's
pictorial guide to DOSBox" located at
http://vogons.zetafleet.com/viewforum.php?f=39 might help you.
For more questions read the remainder of this README and/or check
the site/forum:
http://dosbox.sourceforge.net
=========
3. Usage:
=========
An overview of the commandline options you can give to DOSBox:
dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile]
[-lang languagefile] [-machine machinetype] [-noconsole]
[-startmapper]
dosbox -version
name
If "name" is a directory it'll mount that as the C: drive.
@ -43,13 +212,19 @@ dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile]
Start dosbox using the language string specified in "languagefile".
-noconsole (Windows Only)
Start dosbox without showing the console window, output will
Start dosbox without showing the console window. Output will
be redirected to stdout.txt and stderr.txt
-machine machinetype
Setup dosbox to emulate a specific type of machine. Valid choices are:
auto,hercules,cga,tandy,vga.
hercules, cga, tandy, vga (default).
-startmapper
Enter the keymapper directly on startup. Useful for people with
keyboard problems.
-version
output version information and exit. Useful for frontends.
Note: If a name/command/configfile/languagefile contains a space in it, put
the whole name/command/configfile/languagefile between quotes("example").
@ -64,16 +239,16 @@ In Windows you can also drag directories/files onto the dosbox executable.
==================
Internal Programs:
==================
=====================
4. Internal Programs:
=====================
DOSBox supports most of the DOS commands found in command.com.
In addition, the following commands are available:
MOUNT "Emulated Drive letter" "Real Drive or Directory"
[-t type] [-aspi] [-ioctl] [-usecd number] [-size drivesize]
[-label drivelabel]
[-label drivelabel] [-freesize sizemb]
MOUNT -cd
Program to mount local directories as drives inside DOSBox.
@ -91,7 +266,11 @@ MOUNT -cd
floppy, cdrom.
-size drivesize
Sets the size of the drive.
Sets the size of the drive.
-freesize sizemb
Sets the amount of free space available on a drive in MB's. This
is a more simple version of -size.
-label drivelabel
Sets the name of the drive to "drivelabel". Needed on some
@ -104,7 +283,7 @@ MOUNT -cd
-ioctl
Forces to use ioctl commands. Only valid if mounting a cdrom under
windows which support them (Win2000/XP/NT).
a Windows OS which support them (Win2000/XP/NT).
-usecd number
Forces to use SDL cdrom support for drive number.
@ -118,11 +297,11 @@ MOUNT -cd
Basically, MOUNT allows you to connect real hardware to DOSBox's "emulated"
PC. So MOUNT C C:\ tells DOSBox to use your real C: drive as drive C: in
DosBox. It also allows you to change the drive's letter identification for
DOSBox. It also allows you to change the drive's letter identification for
programs that demand specific drive letters.
For example: Touche: Adventures of The Fifth Musketeer must be run on your C:
drive. Using DOSBox and it's mount command, you can trick into thinking it
drive. Using DOSBox and its mount command, you can trick into thinking it
is on C drive while placing it where you want it. For example, if the game
were in D:\TOUCHE, you can use the command MOUNT C D:\ would allow you to
run Touche from the D drive.
@ -131,14 +310,16 @@ MOUNT -cd
General MOUNT Examples:
1. To mount c:\floppy as a floppy :
mount a c:\floppy -t floppy
2. To mount system cdrom drive E as cdrom drive D in dosbox:
2. To mount system cdrom drive E as cdrom drive D in DOSBox:
mount d e:\ -t cdrom
3. To mount system cdrom drive at mountpoint /media/cdrom as cdrom drive D
in dosbox:
mount d /media/cdrom -t cdrom -usecd 0
4. To mount a drive with 870 mb free diskspace (rarely needed! experts only):
4. To mount a drive with 870 mb free diskspace (simple version):
mount c d:\ -freesize 870
5. To mount a drive with 870 mb free diskspace (experts only, full control):
mount c d:\ -size 4025,127,16513,1700
5. To mount /home/dos/dosgames as drive C in DOSBox:
6. To mount /home/dos/dosgames as drive C in DOSBox:
mount c /home/dos/dosgames
MEM
@ -173,31 +354,272 @@ Examples:
3. To free previous allocated memory :
loadfix -f
RESCAN
Make DOSBox reread the directory structure. Useful if you changed something
on a mounted drive outside of DOSBox.
MIXER
Makes DOSBox display its current volume settings.
You can change this way:
mixer channel left:right [/NOSHOW]
channel
Can be one of the following: MASTER, DISNEY, SPKR, GUS, SB, FM.
left:right
The volume levels in percentages. If you put a D in front it will be
in deciBell (example mixer gus d-10).
/NOSHOW
Prevents DOSBox from showing the result if you set one
of the volume levels.
IMGMOUNT
A utility to mount disk images and CD-ROM images in DOSBox.
IMGMOUNT DRIVE [imagefile] -t [image_type] -fs [image_format]
-size [sectorsbytesize, sectorsperhead, heads, cylinders]
imagefile
location of the image files to mount in DOSBox. Path is relative to
a mount point already inside DOSBox. CD-ROM images can be mounted
directly as well (path on the host).
-t
The following are valid image types:
floppy: Specifies a floppy image or images. DOSBox will automatically
identify the disk geometry ( 360K, 1.2MB, 720K, 1.44MB, etc).
iso: Specifies a CD-ROM iso image. The geometry is automatic and
set for this size. This can be an iso or a cue/bin.
hdd: Specifies a harddrive image. The proper CHS geometry
must be set for this to work.
-fs
The following are valid file system formats:
iso: Specifies the ISO 9660 CD-ROM format.
fat: Specifies the image uses the FAT file system. DOSBox will attempt
to mount this image as a drive in DOSBox and make the files
available from inside DOSBox.
none: DOSBox will make no attempt to read the file system on the disk.
This is useful if one needs to format it or one wants to boot
off of the disk using the BOOT command. When using the "none"
filesystem, one must specify the drive number (2 or 3,
where 2 = master, 3 = slave) rather than a drive letter.
For example, to mount a 70MB image as the slave drive device,
one would type:
"imgmount 3 d:\test.img -size 512,63,16,142 -fs none"
(without the quotes) Compare this with a mount to read the
drive in DOSBox, which would read as:
"imgmount e: d:\test.img -size 512,63,16,142"
-size
The Cylinders, Heads and Sectors specification of the drive.
Required to mount hard drive images.
An example of CD-ROM images:
1a. mount c /tmp
1b. imgmount d c:\myiso.iso -t iso
or (which also works):
2. imgmount d /tmp/myiso.iso -t iso
BOOT
Boot will start floppy images or hard disk images independent of the
operating system emulation offered by DOSBox. This will allow you to play
booter floppies or boot to other operating systems inside DOSBox.
BOOT [diskimg1.img diskimg2.img .. diskimgN.img] [-l driveletter]
diskimgN.img
This can be any number of floppy disk images one wants mounted after
DOSBox boots the specified drive letter.
To swap between images, one hits CTRL+F4 to swap out the current disk
and swap in the next disk in the list. Once the last disk in the list is
swapped out, the list loops back to the beginning.
[-l driveletter]
This parameter allows one to specify the drive to boot from.
The default is the A drive, the floppy drive. One can also boot off of
a hard drive image mounted as master by specifying "-l C"
without the quotes, or the drive as slave by specifying "-l D"
IPX
You need to enable IPX networking in the configuration file of DOSBox.
All of the IPX networking is managed through the internal DOSBox program
IPXNET. For help on the IPX networking from inside DOSBox, type
"IPXNET HELP" (without quotes) and the program will list out the commands
and relevant documentation.
With regard to actually setting up a network, one system needs to be
the server. To set this up, in a DOSBox session, one should type
"IPXNET STARTSERVER" (without the quotes). The server DOSBox session will
automatically add itself to the virtual IPX network. In turn, for every
other computer that should be part of the virtual IPX network,
you'll need to type "IPXNET CONNECT <computer host name or IP>".
For example, if your server is at bob.dosbox.com,
you would type "IPXNET CONNECT bob.dosbox.com" on every non-server system.
The following is an IPXNET command reference:
IPXNET CONNECT
IPXNET CONNECT opens a connection to an IPX tunneling server
running on another DOSBox session. The "address" parameter specifies
the IP address or host name of the server computer. One can also
specify the UDP port to use. By default IPXNET uses port 213, the
assigned IANA port for IPX tunneling, for its connection.
The syntax for IPXNET CONNECT is:
IPXNET CONNECT address <port>
IPXNET DISCONNECT
IPXNET DISCONNECT closes the connection to the IPX tunneling server.
The syntax for IPXNET DISCONNECT is:
IPXNET DISCONNECT
IPXNET STARTSERVER
IPXNET STARTSERVER starts and IPX tunneling server on this DOSBox
session. By default, the server will accept connections on UDP port
213, though this can be changed. Once the server is started, DOSBox
will automatically start a client connection to the IPX tunneling server.
The syntax for IPXNET STARTSERVER is:
IPXNET STARTSERVER <port>
IPXNET STOPSERVER
IPXNET STOPSERVER stops the IPX tunneling server running on this DOSBox
session. Care should be taken to ensure that all other connections have
terminated as well since stopping the server may cause lockups on other
machines still using the IPX tunneling server.
The syntax for IPXNET STOPSERVER is:
IPXNET STOPSERVER
IPXNET PING
IPXNET PING broadcasts a ping request through the IPX tunneled network.
In response, all other connected computers will respond to the ping
and report the time it took to receive and send the ping message.
The syntax for IPXNET PING is:
IPXNET PING
IPXNET STATUS
IPXNET STATUS reports the current state of this DOSBox's sessions
IPX tunneling network. For a list of the computers connected to the
network use the IPXNET PING command.
The syntax for IPXNET STATUS is:
IPXNET STATUS
For more information use the /? command line switch with the programs.
=============
Special Keys:
=============
================
5. Special Keys:
================
ALT-ENTER Go full screen and back.
CTRL-F5 Save a screenshot.
CTRL-F6 Start/Stop recording sound output to a wave file.
CTRL-F7 Decrease frameskip.
CTRL-F8 Increase frameskip.
CTRL-F1 Start the keymapper.
CTRL-F4 Swap mounted disk-image (Only used with imgmount).
CTRL-F5 Save a screenshot.
CTRL-F6 Start/Stop recording sound output to a wave file.
CTRL-ALT-F7 Start/Stop recording of OPL commands.
CTRL-ALT-F8 Start/Stop the recording of raw MIDI commands.
CTRL-F7 Decrease frameskip.
CTRL-F8 Increase frameskip.
CTRL-F9 Kill dosbox.
CTRL-F10 Capture/Release the mouse.
CTRL-F11 Slow down emulation (Decrease DOSBox Cycles).
CTRL-F12 Speed up emulation (Increase DOSox Cycles).
These are the default keybindings. They can be changed in the keymapper.
NOTE: Once you increase your DOSBox cycles beyond your computer's maximum
capacity, it will produce the same effect as slowing down the emulation.
This maximum will vary from computer to computer, there is no standard.
====================
System requirements:
====================
=============
6. Keymapper:
=============
When you start the keymapper (either with CTRL-F1 or -startmapper as a
commandline argument) you are presented with a virtual keyboard.
This virtual keyboard corresponds with the keys DOSBox will report to its
applications. If you click on a key with your mouse, you can see in the
lowerleft corner which key on your keyboard corresponds with it.
Event: EVENT
BIND: BIND
Add Del
mod1 hold Next
mod2
mod3
EVENT
The key DOSBox will report to the applications being emulated.
BIND
The key on your keyboard (as reported by SDL) which is connected to the
EVENT.
mod1,2,3
Modfiers. These are keys you need to have pressed as well, while pressing
BIND. mod1 = CTRL and mod2 = ALT. These are generally only used when you
want to change the special keys of DOSBox.
Add
Add a new BIND to this EVENT. Basicly add a key from your keyboard which
will produce the key EVENT in DOSBox.
Del
Delete the BIND to this EVENT. If an EVENT has no BINDS than it's not
possible to type this key in DOSBox.
Next
Cycle through the list of keys(BINDS) which map to this EVENT.
Example:
Q1. You want to have the X on your keyboard to type a Z in DOSBox.
A. With your mouse click on the Z on the keyboard mapper. Click "Add".
Now press the X key on your keyboard.
Q2. If you click "Next" a few times you will notice that the Z on your
keyboard also produces an Z in DOSBox.
A. Therefore select the Z again and click "Next" till you have the Z on
your keyboard. Now click "Del".
Q3. If you try it out in DOSBox you will notice that pressing X makes ZX
appear.
A. The X on your keyboard is still mapped to the X as well! Click on
the X in the keyboard mapper and search with "Next" till you find the
mapped key X. Click "Del".
If you change the default mapping you can save your changes by pressing
"Save". DOSBox will save the mapping to location specified in the configfile
(mapperfile=mapper.txt). At startup DOSBox will load your mapperfile if it's
present in the configfile.
=======================
7. System requirements:
=======================
Fast machine. My guess would be pentium-2 400+ to get decent emulation
of games written for an 286 machine.
@ -206,9 +628,10 @@ them to run fast though!! Be sure to read the next section on how to speed
it up somewhat.
================================
To run resource-demanding games:
================================
===================================
8. To run resource-demanding games:
===================================
DOSBox emulates the CPU, the sound and graphic cards, and some other
stuff, all at the same time. You can overclock DOSBox by using CTRL+F12, but
@ -236,109 +659,31 @@ You can also try to disable the sound through the setup utility of the game
to further reduce load on your CPU.
====
FAQ:
====
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 a C in DOSBox which points
at D:\ in win32.
In linux: mount c /home/username would give you a C in DOSBox
which points at /home/username in Linux.
Q: The mouse doesn't work.
A: Normally dosbox detects the mouse being used by a game. If you click on
the screen then it should get locked and work.
Sometimes the dosbox mouse detection doesn't work with certain games. You
might have to force to lock the mouse then with ctrl-F10.
Q: The sound stutters.
A: You're using too much cpu power to keep dosbox running at the current speed.
You can either lower the cycles or skip frames or get a faster machine.
Q: I can't type \ in DOSBox.
A: This is a known problem. It only occurs if your keyboard layout isn't US.
Some possible fixes:
1. Switch your keyboard layout.
2. Use / instead.
3. Add the commands you want to execute in dosbox.conf
Q: The game/application can't find its CD-ROM.
A: Be sure to mount the CD-ROM with -t cdrom switch. Also try adding the cor-
rect label (-label LABEL). To enable more low-level cdrom support add
the following switch to mount: -usecd #, where # is the number of your
CD-ROM drive reported by mount -cd. If you run Win32 you can specify -ioctl
or -aspi. Look at the description elsewhere in this document for their
meaning.
Q: The game/application runs much too slow!
A: Look at the section "To run resource-demanding games" for more information.
Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ.
A: This is possible! Just create a config file: config -writeconf dosbox.conf .
Startup your favourite editor and look at all the settings present. To
start DOSBox with your new settings: dosbox -conf dosbox.conf
Q: What sound hardware does DosBox presently emulate?
A: DosBox emulates several legacy sound devices:
- Internal PC speaker
This emulation includes both the tone generator and several forms of digital
sound output through the internal speaker.
- Creative CMS/Gameblaster
The is the first card released by Creative Labs(R). The default configuration places
it on port 0x220. It should be noted that enabling this with the Adlib emulation may
result in conflicts.
- Tandy 3 voice
The emulation of this sound hardware is complete with the exception of the noise channel,
which is not very well documented and as such is only a best guess as to the sound's accuracy.
- Adlib
Borrowed from MAME, this emulation is almost perfect and includes the Adlib's ability to almost
play digitized sound.
- SoundBlaster Pro
Coupled with the Adlib, DosBox provides Soundblaster Pro level 8-bit stereo sound.
- Disney Soundsource
Using the printer port, this sound device outputs digital sound only.
- Gravis Ultrasound
The emulation of this hardware is nearly complete, though the MIDI capabilities have been left
out since an MPU-401 has been emulated in other code.
- MPU-401
A MIDI passthrough interface is also emulated. This method of sound output will only work when
used with a General Midi or MT-32 device.
Q: Great README, but I still don't get it.
A: While unlikely this seems to happen. Maybe a look at "The Newbie's
pictorial guide to dosbox" located at
http://vogons.zetafleet.com/viewforum.php?f=39 might help you.
For more questions check the site/forum:
http://dosbox.sourceforge.net
================
The Config File:
================
===================
9. The Config File:
===================
A config file can be generated by CONFIG.COM, which can be found on the
internal dosbox Z: drive when you start up dosbox. Look in the internal
programs section of the readme for usage of CONFIG.COM.
You can edit the generated configfile to customize DOSBox.
The file is divided into several sections (the names have [] around it).
Some sections have options which you can set.
# and % indicate comment-lines.
The generated configfile contains the current settings. You can alter them and
start DOSBox with the -conf switch to load the file and use these settings.
DOSBox will if no configfile is specified with the -conf switch look in the
current directory for dosbox.conf. Then it will look for ~/.dosboxrc (linux),
~\dosbox.conf (win32) or "~/Library/Preferences/DOSBox Preferences" (MACOSX).
If no configfile is specified with the -conf switch, DOSBox will look in the
current directory for dosbox.conf. Then it will look for ~/.dosboxrc (Linux),
~\dosbox.conf (Win32) or "~/Library/Preferences/DOSBox Preferences" (MACOSX).
==================
The Language File:
==================
======================
10. The Language File:
======================
A language file can be generated by CONFIG.COM.
Read it and you will hopefully understand how to change it.
@ -347,16 +692,19 @@ or you can setup the filename in the config file in the [dosbox] section.
There's a language= entry that can be changed with the filename.
====================================
Building your own version of DOSBox:
====================================
========================================
11. Building your own version of DOSBox:
========================================
Download the source.
Check the INSTALL in the source distribution.
===============
Special Thanks:
===============
===================
12. 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.
@ -366,9 +714,12 @@ Pierre-Yves G
Colin Snover for hosting our forum.
The Beta Testers.
========
Contact:
========
Harekiet harekiet@zophar.net
============
13. Contact:
============
See the site:
http://dosbox.sourceforge.net
for an emailaddress (The Crew-page).

View File

@ -1,7 +1,7 @@
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,
AC_DEFUN([AM_PATH_SDL],
[dnl
dnl Get the cflags and libraries from the sdl-config script
dnl
@ -174,7 +174,7 @@ dnl
dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified,
dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result.
dnl
AC_DEFUN(AM_PATH_ALSA,
AC_DEFUN([AM_PATH_ALSA],
[dnl Save the original CFLAGS, LDFLAGS, and LIBS
alsa_save_CFLAGS="$CFLAGS"
alsa_save_LDFLAGS="$LDFLAGS"
@ -305,7 +305,7 @@ AC_SUBST(ALSA_LIBS)
AH_TOP([
/*
* Copyright (C) 2002-2003 The DOSBox Team
* Copyright (C) 2002-2004 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
@ -331,4 +331,49 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE
#define GCC_ATTRIBUTE(x) /* attribute not supported */
#endif])
AH_BOTTOM([
typedef double Real64;
#if SIZEOF_UNSIGNED_CHAR != 1
# error "sizeof (unsigned char) != 1"
#else
typedef unsigned char Bit8u;
typedef signed char Bit8s;
#endif
#if SIZEOF_UNSIGNED_SHORT != 2
# error "sizeof (unsigned short) != 2"
#else
typedef unsigned short Bit16u;
typedef signed short Bit16s;
#endif
#if SIZEOF_UNSIGNED_INT == 4
typedef unsigned int Bit32u;
typedef signed int Bit32s;
#elif SIZEOF_UNSIGNED_LONG == 4
typedef unsigned long Bit32u;
typedef signed long Bit32s;
#else
# error "can't find sizeof(type) of 4 bytes!"
#endif
#if SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long Bit64u;
typedef signed long Bit64s;
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
typedef unsigned long long Bit64u;
typedef signed long long Bit64s;
#else
# error "can't find data type of 8 bytes"
#endif
#if SIZEOF_INT_P == 4
typedef Bit32u Bitu;
typedef Bit32s Bits;
#else
typedef Bit64u Bitu;
typedef Bit64s Bits;
#endif
])

51
aclocal.m4 vendored
View File

@ -14,7 +14,7 @@
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,
AC_DEFUN([AM_PATH_SDL],
[dnl
dnl Get the cflags and libraries from the sdl-config script
dnl
@ -187,7 +187,7 @@ dnl
dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified,
dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result.
dnl
AC_DEFUN(AM_PATH_ALSA,
AC_DEFUN([AM_PATH_ALSA],
[dnl Save the original CFLAGS, LDFLAGS, and LIBS
alsa_save_CFLAGS="$CFLAGS"
alsa_save_LDFLAGS="$LDFLAGS"
@ -318,7 +318,7 @@ AC_SUBST(ALSA_LIBS)
AH_TOP([
/*
* Copyright (C) 2002-2003 The DOSBox Team
* Copyright (C) 2002-2004 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
@ -344,7 +344,52 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE
#define GCC_ATTRIBUTE(x) /* attribute not supported */
#endif])
AH_BOTTOM([
typedef double Real64;
#if SIZEOF_UNSIGNED_CHAR != 1
# error "sizeof (unsigned char) != 1"
#else
typedef unsigned char Bit8u;
typedef signed char Bit8s;
#endif
#if SIZEOF_UNSIGNED_SHORT != 2
# error "sizeof (unsigned short) != 2"
#else
typedef unsigned short Bit16u;
typedef signed short Bit16s;
#endif
#if SIZEOF_UNSIGNED_INT == 4
typedef unsigned int Bit32u;
typedef signed int Bit32s;
#elif SIZEOF_UNSIGNED_LONG == 4
typedef unsigned long Bit32u;
typedef signed long Bit32s;
#else
# error "can't find sizeof(type) of 4 bytes!"
#endif
#if SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long Bit64u;
typedef signed long Bit64s;
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
typedef unsigned long long Bit64u;
typedef signed long long Bit64s;
#else
# error "can't find data type of 8 bytes"
#endif
#if SIZEOF_INT_P == 4
typedef Bit32u Bitu;
typedef Bit32s Bits;
#else
typedef Bit64u Bitu;
typedef Bit64s Bits;
#endif
])
# Do all the work for Automake. -*- Autoconf -*-

769
config.guess vendored

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
/*
* Copyright (C) 2002-2003 The DOSBox Team
* Copyright (C) 2002-2004 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
@ -26,6 +26,9 @@
/* Define to 1 to enable internal debugger, requires libcurses */
#undef C_DEBUG
/* Define to 1 if you want serial passthrough support (Win32 only). */
#undef C_DIRECTSERIAL
/* Define to 1 to use x86 dynamic cpu core */
#undef C_DYNAMIC_X86
@ -41,12 +44,21 @@
/* The type of cpu this host has */
#undef C_HOSTCPU
/* Define to 1 to enable IPX over Internet networking, requires SDL_net */
#undef C_IPX
/* Define to 1 to enable internal modem support, requires SDL_net */
#undef C_MODEM
/* Define to 1 to use opengl display output support */
#undef C_OPENGL
/* Define to 1 to enable SDL_sound support */
#undef C_SDL_SOUND
/* Define to 1 if you have setpriority support */
#undef C_SET_PRIORITY
/* Define to 1 to enable screenshots, requires libpng */
#undef C_SSHOT
@ -59,6 +71,9 @@
/* Define to 1 to use ALSA for MIDI */
#undef HAVE_ALSA
/* Define to 1 if you have the <ddraw.h> header file. */
#undef HAVE_DDRAW_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
@ -113,6 +128,24 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of a `int *', as computed by sizeof. */
#undef SIZEOF_INT_P
/* The size of a `unsigned char', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_CHAR
/* The size of a `unsigned int', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_INT
/* The size of a `unsigned long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG
/* The size of a `unsigned long long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG_LONG
/* The size of a `unsigned short', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_SHORT
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
@ -145,3 +178,50 @@
#else
#define GCC_ATTRIBUTE(x) /* attribute not supported */
#endif
typedef double Real64;
#if SIZEOF_UNSIGNED_CHAR != 1
# error "sizeof (unsigned char) != 1"
#else
typedef unsigned char Bit8u;
typedef signed char Bit8s;
#endif
#if SIZEOF_UNSIGNED_SHORT != 2
# error "sizeof (unsigned short) != 2"
#else
typedef unsigned short Bit16u;
typedef signed short Bit16s;
#endif
#if SIZEOF_UNSIGNED_INT == 4
typedef unsigned int Bit32u;
typedef signed int Bit32s;
#elif SIZEOF_UNSIGNED_LONG == 4
typedef unsigned long Bit32u;
typedef signed long Bit32s;
#else
# error "can't find sizeof(type) of 4 bytes!"
#endif
#if SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long Bit64u;
typedef signed long Bit64s;
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
typedef unsigned long long Bit64u;
typedef signed long long Bit64s;
#else
# error "can't find data type of 8 bytes"
#endif
#if SIZEOF_INT_P == 4
typedef Bit32u Bitu;
typedef Bit32s Bits;
#else
typedef Bit64u Bitu;
typedef Bit64s Bits;
#endif

57
config.sub vendored
View File

@ -1,9 +1,9 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
timestamp='2004-01-05'
timestamp='2004-06-24'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@ -70,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
@ -145,7 +145,7 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis)
-apple | -axis | -knuth | -cray)
os=
basic_machine=$1
;;
@ -237,7 +237,7 @@ case $basic_machine in
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| m32r | m68000 | m68k | m88k | mcore \
| m32r | m32rle | m68000 | m68k | m88k | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@ -262,7 +262,7 @@ case $basic_machine in
| pyramid \
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
| strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
@ -300,7 +300,7 @@ case $basic_machine in
| avr-* \
| bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | cydra-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
@ -308,7 +308,7 @@ case $basic_machine in
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| m32r-* \
| m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
@ -326,8 +326,9 @@ case $basic_machine in
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| msp430-* \
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
@ -336,7 +337,7 @@ case $basic_machine in
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
@ -363,6 +364,9 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
@ -442,12 +446,24 @@ case $basic_machine in
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16c)
basic_machine=cr16c-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
@ -648,10 +664,6 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
mmix*)
basic_machine=mmix-knuth
os=-mmixware
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
@ -732,10 +744,6 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
nv1)
basic_machine=nv1-cray
os=-unicosmp
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@ -1048,6 +1056,9 @@ case $basic_machine in
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
@ -1070,7 +1081,7 @@ case $basic_machine in
sh64)
basic_machine=sh64-unknown
;;
sparc | sparcv9 | sparcv9b)
sparc | sparcv8 | sparcv9 | sparcv9b)
basic_machine=sparc-sun
;;
cydra)
@ -1143,8 +1154,9 @@ case $os in
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
@ -1362,6 +1374,9 @@ case $basic_machine in
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;

2961
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
dnl Init.
AC_INIT(dosbox,0.61)
AC_INIT(dosbox,0.62)
AC_PREREQ(2.50)
AC_CONFIG_SRCDIR(README)
@ -26,7 +26,7 @@ AM_PATH_SDL($SDL_VERSION,
AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
)
LIBS="$LIBS $SDL_LIBS"
CXXFLAGS="$CXXFLAGS $SDL_CFLAGS"
CPPFLAGS="$CPPFLAGS $SDL_CFLAGS"
dnl Checks for header files.
@ -35,7 +35,12 @@ AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_STRUCT_TM
AC_CHECK_SIZEOF(unsigned char)
AC_CHECK_SIZEOF(unsigned short)
AC_CHECK_SIZEOF(unsigned int)
AC_CHECK_SIZEOF(unsigned long)
AC_CHECK_SIZEOF(unsigned long long)
AC_CHECK_SIZEOF(int *)
AC_MSG_CHECKING(if environ can be included)
AC_TRY_LINK([#include <unistd.h>
@ -143,13 +148,15 @@ else
fi
AH_TEMPLATE(C_MODEM,[Define to 1 to enable internal modem support, requires SDL_net])
AC_CHECK_HEADER(SDL/SDL_net.h,have_sdl_net_h=yes,)
AH_TEMPLATE(C_IPX,[Define to 1 to enable IPX over Internet networking, requires SDL_net])
AC_CHECK_HEADER(SDL_net.h,have_sdl_net_h=yes,)
AC_CHECK_LIB(SDL_net, SDLNet_Init, have_sdl_net_lib=yes, , )
if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then
LIBS="$LIBS -lSDL_net"
AC_DEFINE(C_MODEM,1)
AC_DEFINE(C_IPX,1)
else
AC_MSG_WARN([Can't find SDL_net, internal modem disabled])
AC_MSG_WARN([Can't find SDL_net, internal modem and ipx disabled])
fi
AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support])
@ -170,10 +177,32 @@ else
AC_MSG_RESULT(no)
fi
AH_TEMPLATE(C_SDL_SOUND,[Define to 1 to enable SDL_sound support])
AC_CHECK_HEADER(SDL/SDL_sound.h,have_SDL_sound_h=yes,)
AC_CHECK_LIB(SDL_sound, Sound_Init, have_SDL_sound_lib=yes,,)
if test x$have_SDL_sound_h = xyes -a x$have_SDL_sound_lib = xyes ; then
LIBS="$LIBS -lSDL_sound"
AC_DEFINE(C_SDL_SOUND,1)
else
AC_MSG_WARN([Can't find libSDL_sound, libSDL_sound support disabled])
fi
AH_TEMPLATE(C_SET_PRIORITY,[Define to 1 if you have setpriority support])
AC_MSG_CHECKING(for setpriority support)
AC_LINK_IFELSE([
#include <sys/resource.h>
int main(int argc,char * argv[]) {
return setpriority (PRIO_PROCESS, 0,PRIO_MIN+PRIO_MAX);
};
],AC_MSG_RESULT(yes);AC_DEFINE(C_SET_PRIORITY,1),AC_MSG_RESULT(no))
dnl Some host detection and actions for them
case "$target" in
*-*-cygwin* | *-*-mingw32*)
LIBS="$LIBS -lwinmm"
AC_CHECK_HEADERS(ddraw.h)
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32 only).])
;;
*-*-darwin*)
dnl We have a problem here: both MacOS X and Darwin report

View File

@ -1,16 +1,20 @@
.\" Hey, EMACS: -*- nroff -*-
.TH DOSBOX 1 "October 5, 2003"
.TH DOSBOX 1 "Sept 23, 2004"
.\" Please adjust this date whenever revising the manpage.
.SH NAME
dosbox \- an x86/DOS emulator with sound/graphics
.SH SYNOPSIS
.B dosbox
.B [\-fullscreen]
.B [\-startmapper]
.BI "[\-conf " configfile ]
.BI "[\-lang " langfile ]
.B [file]
.BI "[\-c " command ]
.B [\-exit]
.BI "[\-machine " machinetype ]
.LP
.B dosbox -version
.SH DESCRIPTION
This manual page briefly documents
.BR "dosbox" ", an x86/DOS emulator."
@ -22,6 +26,9 @@ A summary of options is included below.
.B \-fullscreen
.RB "Start " dosbox " in fullscreen mode."
.TP
.B \-startmapper
.RB "Start the internal keymapper on startup of " dosbox ". You can use it to change the keys " dosbox " uses."
.TP
.BI \-c " command"
.RI "Runs the specified " command " before running "
.BR file .
@ -38,6 +45,13 @@ A summary of options is included below.
.TP
.B \-exit
.BR dosbox " will exit after running the program specified by " file .
.TP
.BI \-machine " machinetype
.RB "Setup " dosbox " to emulate a specific type of machine."
.RI "Valid choices are: " "hercules, cga, tandy, vga(default)".
.TP
.B \-version
Output version information and exit. Useful for frontends.
.SH "INTERNAL COMMANDS"
.B dosbox
supports most of the DOS commands found in command.com. In addition, the
@ -46,7 +60,7 @@ following extra commands are available:
.BI "MOUNT [\-t " type "] [\-size " size ]
.I driveletter sourcedirectory
.B [\-aspi] [\-ioctl]
.BI "[\-usecd " number "] [\-label " drivelabel ]
.BI "[\-usecd " number "] [\-label " drivelabel "] [\-freesize " freesize ]
.LP
.B MOUNT \-cd
.LP
@ -63,7 +77,11 @@ The local directory you want to have inside dosbox.
Type of the mounted directory. Supported are: dir (standard), floppy, cdrom.
.TP
.BI \-size " drivesize"
Sets the size of the drive.
Sets the size of the drive. See the examples in the README for details.
.TP
.BI \-freesize " freesize"
Sets the amount of free space available on a drive in MB's. This is a more
.RB "simple version of " \-size .
.TP
.BI \-label " drivelabel"
.RI "Sets the name of the drive to " drivelabel ". Needed on some"
@ -123,6 +141,30 @@ The amount of memory to eat up (in kb). Example -32, -64 or -128
.B \-f
Frees all memory eaten up by loadfix.
.RE
.TP
.B IMGMOUNT
.LP
.RB "A utility to mount disk images and CD-ROM images in " DOSBox .
.TP
.RB "Read the " README " of " DOSBox " for the full and correct syntax."
.RE
.TP
.B BOOT
.LP
.RB "Boot will start floppy images or hard disk images independent of the operating system emulation offered by " DOSBox ". This will allow you to play booter floppies or boot to other operating systems inside "DOSBox .
.TP
.RB "Read the " README " of " DOSBox " for the full and correct syntax."
.RE
.TP
.B IPX
.LP
.RB "You need to enable IPX networking in the configuration file of "DOSBox .
.RB "All of the IPX networking is managed through the internal " DOSBox " program
.BR IPXNET ". For help on the IPX networking from inside " DOSBox ", type"
.BR "IPXNET HELP" " and the program will list out the commands and relevant documentation."
.TP
.RB "Read the " README " of " DOSBox " for the full and correct syntax."
.RE
.SH FILES
Configuration and language files use a format similar to Windows .ini files. If a file named
.BR dosbox.conf " is found in the current directory, it will be automatically loaded."
@ -130,10 +172,18 @@ Configuration and language files use a format similar to Windows .ini files. If
.TP 12m
.IP ALT\-ENTER
Go full screen and back.
.IP CTRL\-F1
Start the keymapper.
.IP CTRL\-F4
Swap mounted disk-image (Only used with imgmount).
.IP CTRL\-F5
Save a screenshot.
.IP CTRL\-F6
Start/Stop recording sound output to a wave file.
.IP CTRL\-ALT\-F7
Start/Stop recording of OPL commands.
.IP CTRL\-ALT\-F8
Start/Stop the recording of raw MIDI commands.
.IP CTRL\-F7
Decrease frameskip.
.IP CTRL\-F8
@ -147,8 +197,9 @@ Slow down emulation (Increase DOSBox Cycles).
.IP CTRL\-F12
Speed up emulation (Decrease DOSBox Cycles).
.PP
.B "Note: "
Once you increase your DOSBox cycles beyond your computer's maximum
These are the default keybindings. They can be changed in the keymapper.
.PP
.BR "Note: " "Once you increase your " DOSBox " cycles beyond your computer's maximum
capacity, it will produce the same effect as slowing down the emulation.
This maximum will vary from computer to computer, there is no standard.
.SH "SYSTEM REQUIREMENTS"

View File

@ -12,8 +12,11 @@ fpu.h \
hardware.h \
inout.h \
joystick.h \
ipx.h \
ipxserver.h \
keyboard.h \
logging.h \
mapper.h \
mem.h \
mixer.h \
modules.h \

View File

@ -143,8 +143,11 @@ fpu.h \
hardware.h \
inout.h \
joystick.h \
ipx.h \
ipxserver.h \
keyboard.h \
logging.h \
mapper.h \
mem.h \
mixer.h \
modules.h \

View File

@ -9,13 +9,16 @@
* 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.
* 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.
*/
#ifndef _BIOS_H_
#define _BIOS_H_
#define BIOS_BASE_ADDRESS_COM1 0x400
#define BIOS_BASE_ADDRESS_COM2 0x402
#define BIOS_BASE_ADDRESS_COM3 0x404
@ -88,6 +91,8 @@
#define BIOS_WAIT_FLAG_POINTER 0x498
#define BIOS_WAIT_FLAG_COUNT 0x49c
#define BIOS_WAIT_FLAG_ACTIVE 0x4a0
#define BIOS_WAIT_FLAG_TEMP 0x4a1
#define BIOS_PRINT_SCREEN_FLAG 0x500
@ -96,23 +101,57 @@
/* 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;
struct diskGeo {
Bit32u ksize; /* Size in kilobytes */
Bit16u secttrack; /* Sectors per track */
Bit16u headscyl; /* Heads per cylinder */
Bit16u cylcount; /* Cylinders per side */
Bit16u biosval; /* Type to return from BIOS */
};
class imageDisk : public BIOS_Disk {
extern diskGeo DiskGeometryList[];
#include <stdio.h>
#include "mem.h"
#include "dos_inc.h"
class imageDisk {
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;
Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
Bit8u Write_AbsoluteSector(Bit32u sectnum, void * data);
void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
void Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize);
Bit8u GetBiosType(void);
Bit32u getSectSize(void);
imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
~imageDisk() { if(diskimg != NULL) { fclose(diskimg); } };
bool hardDrive;
bool active;
FILE *diskimg;
Bit8u diskname[512];
Bit8u floppytype;
Bit32u sector_size;
Bit32u heads,cylinders,sectors;
};
void updateDPT(void);
#define MAX_HDD_IMAGES 2
extern imageDisk *imageDiskList[2 + MAX_HDD_IMAGES];
extern imageDisk *diskSwap[20];
extern Bits swapPosition;
extern Bit16u imgDTASeg; /* Real memory location of temporary DTA pointer for fat image disk access */
extern RealPt imgDTAPtr; /* Real memory location of temporary DTA pointer for fat image disk access */
extern DOS_DTA *imgDTA;
void swapInDisks(void);
void swapInNextDisk(void);
void BIOS_ZeroExtendedSize(void);
void char_out(Bit8u chr,Bit32u att,Bit8u page);
@ -123,4 +162,4 @@ void INT2F_StartUp(void);
void INT33_StartUp(void);
void INT13_StartUp(void);
#endif

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -35,6 +35,7 @@ extern CPU_Decoder * cpudecoder;
Bits CPU_Core_Normal_Run(void);
Bits CPU_Core_Normal_Trap_Run(void);
Bits CPU_Core_Simple_Run(void);
Bits CPU_Core_Full_Run(void);
Bits CPU_Core_Dyn_X86_Run(void);
@ -52,7 +53,6 @@ void CPU_SLDT(Bitu & selector);
void CPU_SIDT(Bitu & limit,Bitu & base);
void CPU_SGDT(Bitu & limit,Bitu & base);
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel);
void CPU_LAR(Bitu selector,Bitu & ar);
void CPU_LSL(Bitu selector,Bitu & limit);
@ -61,35 +61,44 @@ bool CPU_SET_CRX(Bitu cr,Bitu value);
Bitu CPU_GET_CRX(Bitu cr);
void CPU_SMSW(Bitu & word);
bool CPU_LMSW(Bitu word);
Bitu CPU_LMSW(Bitu word);
void CPU_VERR(Bitu selector);
void CPU_VERW(Bitu selector);
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen=0);
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen=0);
void CPU_RET(bool use32,Bitu bytes,Bitu opLen=0);
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
void CPU_RET(bool use32,Bitu bytes,Bitu oldeip);
void CPU_IRET(bool use32,Bitu oldeip);
void CPU_HLT(Bitu oldeip);
bool CPU_POPF(Bitu use32);
bool CPU_PUSHF(Bitu use32);
bool CPU_CLI(void);
bool CPU_STI(void);
bool CPU_IO_Exception(Bitu port,Bitu size);
void CPU_RunException(void);
void CPU_ENTER(bool use32,Bitu bytes,Bitu level);
#define CPU_INT_SOFTWARE 0x1
#define CPU_INT_EXCEPTION 0x2
#define CPU_INT_HAS_ERROR 0x4
void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen=0);
void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip);
INLINE void CPU_HW_Interrupt(Bitu num) {
CPU_Interrupt(num,0);
CPU_Interrupt(num,0,reg_eip);
}
INLINE void CPU_SW_Interrupt(Bitu num,Bitu OpLen) {
CPU_Interrupt(num,CPU_INT_SOFTWARE,OpLen);
INLINE void CPU_SW_Interrupt(Bitu num,Bitu oldeip) {
CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip);
}
bool CPU_PrepareException(Bitu which,Bitu error);
void CPU_Exception(Bitu which,Bitu error=0);
void CPU_StartException(void);
void CPU_SetupException(Bitu which,Bitu error=0);
void CPU_IRET(bool use32);
bool CPU_SetSegGeneral(SegNames seg,Bitu value);
void CPU_HLT(Bitu opLen);
bool CPU_PopSeg(SegNames seg,bool use32);
void CPU_CPUID(void);
Bitu CPU_Pop16(void);
@ -407,5 +416,6 @@ INLINE void CPU_SetFlagsw(Bitu word) {
CPU_SetFlags(word,mask);
};
#endif

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: cross.h,v 1.7 2004/02/02 19:22:23 qbix79 Exp $ */
/* $Id: cross.h,v 1.11 2004/09/16 21:46:03 qbix79 Exp $ */
#ifndef _CROSS_H
#define _CROSS_H
@ -29,6 +29,8 @@
#include <direct.h>
#include <io.h>
#define LONGTYPE(a) a##i64
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#else /* LINUX / GCC */
#include <dirent.h>
#include <unistd.h>
@ -39,7 +41,7 @@
#if defined (WIN32) /* Win 32 */
#define CROSS_FILENAME(blah) {if(blah && *blah && (blah[strlen(blah)-1] == '\\')) strcat(blah,".");}
#define CROSS_FILENAME(blah)
#define CROSS_FILESPLIT '\\'
#define F_OK 0
#else

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,187 +9,85 @@
* 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.
* 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.
*/
/* $Id: dma.h,v 1.9 2004/01/10 14:03:33 qbix79 Exp $ */
/* $Id: dma.h,v 1.12 2004/08/04 09:12:50 qbix79 Exp $ */
#ifndef __DMA_H
#define __DMA_H
#include "mem.h"
enum DMAEvent {
DMA_REACHED_TC,
DMA_MASKED,
DMA_UNMASKED,
DMA_TRANSFEREND
};
#define DMA_MODE_DEMAND 0
#define DMA_MODE_SINGLE 1
#define DMA_MODE_BLOCK 2
#define DMA_MODE_CASCADE 3
#define DMA_BASEADDR 0
#define DMA_TRANSCOUNT 1
#define DMA_PAGEREG 2
#define DMA_CMDREG 0
#define DMA_MODEREG 1
#define DMA_CLEARREG 2
#define DMA_DMACREG 3
#define DMA_CLRMASKREG 4
#define DMA_SINGLEREG 5
#define DMA_WRITEALLREG 6
static Bit8u ChannelPorts [3][8] = { 0x00, 0x02, 0x04, 0x06, 0xff, 0xc4, 0xc8, 0xcc,
0x01, 0x03, 0x05, 0x07, 0xff, 0xc6, 0xca, 0xce,
0x87, 0x83, 0x81, 0x82, 0xff, 0x8b, 0x89, 0x8a };
static Bit8u ControllerPorts [2][7] = { 0x08, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0xf,
0xd0, 0xd6, 0xd8, 0xda, 0xdc, 0xd4, 0xde };
typedef void (* DMA_EnableCallBack)(bool enable);
typedef void (* DMA_NewCallBack)(void *useChannel, bool tc);
void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback);
void DMA_CheckEnabled(void * usechan);
Bitu DMA_8_Read(Bitu channel,Bit8u * buffer,Bitu count);
Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count);
Bitu DMA_16_Read(Bitu channel,Bit8u * buffer,Bitu count);
Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count);
extern Bit8u read_dmaB(Bit32u port);
extern Bit16u read_dmaW(Bit32u port);
extern void write_dmaB(Bit32u port,Bit8u val);
extern void write_dmaW(Bit32u port,Bit16u val);
class DmaChannel;
typedef void (* DMA_CallBack)(DmaChannel * chan,DMAEvent event);
class DmaController {
public:
bool flipflop;
Bit8u ctrlnum;
Bit8u chanbase;
public:
DmaController(Bit8u num) {
int i;
for(i=0;i<7;i++) {
IO_RegisterReadBHandler(ControllerPorts[num][i],read_dmaB);
IO_RegisterReadWHandler(ControllerPorts[num][i],read_dmaW);
IO_RegisterWriteBHandler(ControllerPorts[num][i],write_dmaB);
IO_RegisterWriteWHandler(ControllerPorts[num][i],write_dmaW);
}
flipflop = true;
flipflop = false;
ctrlnum = num;
chanbase = num * 4;
}
Bit16u portRead(Bit32u port, bool eightbit);
void portWrite(Bit32u port, Bit16u val, bool eightbit);
};
class DmaChannel {
public:
Bit8u channum;
Bit32u pagebase;
Bit16u baseaddr;
Bit16u current_addr;
Bit16u pageaddr;
PhysPt physaddr;
PhysPt curraddr;
Bit32s transcnt;
Bit32s currcnt;
DmaController *myController;
bool DMA16;
bool addr_changed;
public:
Bit8u dmamode;
bool dir;
Bit16u curraddr;
Bit16u basecnt;
Bit16u currcnt;
Bit8u channum;
Bit8u pagenum;
Bit8u DMA16;
bool increment;
bool autoinit;
Bit8u trantype;
bool masked;
bool enabled;
DMA_EnableCallBack enable_callback;
DMA_NewCallBack newcallback;
bool tcount;
DMA_CallBack callback;
DmaChannel(Bit8u num, DmaController *useController, bool sb) {
int i;
masked = true;
enabled = false;
enable_callback = NULL;
newcallback = NULL;
if(num == 4) return;
addr_changed=false;
for(i=0;i<3;i++) {
IO_RegisterReadBHandler(ChannelPorts[i][num],read_dmaB);
IO_RegisterReadWHandler(ChannelPorts[i][num],read_dmaW);
IO_RegisterWriteBHandler(ChannelPorts[i][num],write_dmaB);
IO_RegisterWriteWHandler(ChannelPorts[i][num],write_dmaW);
}
myController = useController;
channum = num;
DMA16 = sb;
baseaddr = 0;
pageaddr = 0;
physaddr = 0;
curraddr = 0;
transcnt = 0;
currcnt = 0;
dir = false;
autoinit = false;
DmaChannel(Bit8u num, bool dma16);
void DoCallBack(DMAEvent event) {
if (callback) (*callback)(this,event);
}
void RegisterCallback(DMA_NewCallBack useCallBack) { newcallback = useCallBack; }
void reset(void) {
addr_changed=false;
curraddr = physaddr;
currcnt = transcnt+1;
current_addr = baseaddr;
//LOG(LOG_DMA,LOG_NORMAL)("Setup at address %X:%X count %X",pageaddr,baseaddr,currcnt);
void SetMask(bool _mask) {
masked=_mask;
DoCallBack(masked ? DMA_MASKED : DMA_UNMASKED);
}
void MakeCallback(bool tc) {
if (newcallback != NULL) {
if(tc) {
(*newcallback)(this, true);
} else {
if ((enabled) && (!masked) && (transcnt!=0)) {
(*newcallback)(this, false);
}
}
}
void Register_Callback(DMA_CallBack _cb) {
callback = _cb;
SetMask(masked);
}
Bit32u Read(Bit32s requestsize, Bit8u * buffer);
Bit32u Write(Bit32s requestsize, Bit8u * buffer);
void calcPhys(void);
Bit16u portRead(Bit32u port, bool eightbit);
void portWrite(Bit32u port, Bit16u val, bool eightbit);
// Notify channel when mask changes
void Notify(void);
void ReachedTC(void) {
tcount=true;
DoCallBack(DMA_REACHED_TC);
}
void SetPage(Bit8u val) {
pagenum=val;
pagebase=(pagenum >> DMA16) << (16+DMA16);
}
Bitu Read(Bitu size, Bit8u * buffer);
Bitu Write(Bitu size, Bit8u * buffer);
};
extern DmaChannel *DmaChannels[8];
extern DmaController *DmaControllers[2];
#endif

View File

@ -9,13 +9,15 @@
* 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.
* 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.
*/
/* $Id: dos_inc.h,v 1.48 2004/08/04 09:12:50 qbix79 Exp $ */
#ifndef DOS_H_
#define DOS_H_
@ -43,27 +45,25 @@ 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;
Bit8u current_drive;
bool verify;
bool breakcheck;
bool echo; // if set to true dev_con::read will echo input
struct {
RealPt indosflag;
RealPt mediaid;
RealPt tempdta;
} tables;
};
#ifdef _MSC_VER
#pragma pack (1)
#endif
union bootSector {
struct entries {
Bit8u jump[3];
Bit8u oem_name[8];
Bit16u bytesect;
Bit8u sectclust;
Bit16u reserve_sect;
Bit8u misc[496];
} bootdata;
Bit8u rawdata[512];
} GCC_ATTRIBUTE(packed);
#ifdef _MSC_VER
#pragma pack ()
#endif
enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
@ -72,7 +72,7 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
#define DOS_DRIVES 26
/* internal Dos Tables */
extern DOS_Block dos;
extern DOS_File * Files[DOS_FILES];
extern DOS_Drive * Drives[DOS_DRIVES];
extern Bit8u dos_copybuf[0x10000];
@ -100,7 +100,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry);
bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status);
bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry);
bool DOS_UnlinkFile(char * name);
bool DOS_FindFirst(char *search,Bit16u attr);
bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false);
bool DOS_FindNext(void);
bool DOS_Canonicalize(char * name,char * big);
bool DOS_CreateTempFile(char * name,Bit16u * entry);
@ -208,30 +208,26 @@ INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) {
/* Remains some classes used to access certain things */
#define sGet(s,m) GetIt(((s *)0)->m,(PhysPt)&(((s *)0)->m))
#define sSave(s,m,val) SaveIt(((s *)0)->m,(PhysPt)&(((s *)0)->m),val)
#define sOffset(s,m) ((char*)&(((s*)NULL)->m)-(char*)NULL)
#define sGet(s,m) GetIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m))
#define sSave(s,m,val) SaveIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m),val)
class MemStruct {
public:
INLINE Bit8u GetIt(Bit8u&,PhysPt addr) {
return mem_readb(pt+addr);
INLINE Bitu GetIt(Bitu size,PhysPt addr) {
switch (size) {
case 1:return mem_readb(pt+addr);
case 2:return mem_readw(pt+addr);
case 4:return mem_readd(pt+addr);
}
return 0;
}
INLINE Bit16u GetIt(Bit16u&,PhysPt addr) {
return mem_readw(pt+addr);
}
INLINE Bit32u GetIt(Bit32u&,PhysPt addr) {
return mem_readd(pt+addr);
}
INLINE void SaveIt(Bit8u&,PhysPt addr,Bit8u val) {
mem_writeb(pt+addr,val);
}
INLINE void SaveIt(Bit16u&,PhysPt addr,Bit16u val) {
mem_writew(pt+addr,val);
}
INLINE void SaveIt(Bit32u&,PhysPt addr,Bit32u val) {
mem_writed(pt+addr,val);
INLINE void SaveIt(Bitu size,PhysPt addr,Bitu val) {
switch (size) {
case 1:mem_writeb(pt+addr,val);break;
case 2:mem_writew(pt+addr,val);break;
case 4:mem_writed(pt+addr,val);break;
}
}
INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);}
INLINE void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);}
@ -252,8 +248,6 @@ public:
void RestoreVectors (void);
void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); };
Bit16u GetSize (void) { return sGet(sPSP,next_seg); };
void SetDTA (RealPt ptdta) { sSave(sPSP,dta,ptdta); };
RealPt GetDTA (void) { return sGet(sPSP,dta); };
void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); };
Bit16u GetEnvironment (void) { return sGet(sPSP,environment); };
Bit16u GetSegment (void) { return seg; };
@ -291,8 +285,11 @@ private:
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 interim_flag;
Bit8u truename_flag;
Bit16u nn_flags;
Bit16u dos_version;
Bit8u fill_2[14]; /* Lot's of unused stuff i can't care aboue */
Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */
Bit8u fill_3[9]; /* This has some blocks with FCB info */
Bit8u fcb1[16]; /* first FCB */
@ -343,25 +340,50 @@ public:
void SetFirstMCB(Bit16u _first_mcb);
void SetfirstFileTable(RealPt _first_table);
void SetBuffers(Bit16u x,Bit16u y);
void SetCurDirStruct(Bit32u _curdirstruct);
void SetFCBTable(Bit32u _fcbtable);
void SetDeviceChainStart(Bit32u _devchain);
void SetDiskInfoBuffer(Bit32u _dinfobuf);
RealPt GetPointer (void);
#ifdef _MSC_VER
#pragma pack(1)
#endif
struct sDIB {
Bit8u stuff1[22]; // -0x18 some stuff, hopefully never used....
Bit16u firstMCB; // -0x2 first memory control block
RealPt firstDPB; // 0x00 first drive parameter block
Bit16u regCXfrom5e; // -0x18 CX from last int21/ah=5e
Bit16u countLRUcache; // -0x16 LRU counter for FCB caching
Bit16u countLRUopens; // -0x14 LRU counter for FCB openings
Bit8u stuff[6]; // -0x12 some stuff, hopefully never used....
Bit16u sharingCount; // -0x0c sharing retry count
Bit16u sharingDelay; // -0x0a sharing retry delay
RealPt diskBufPtr; // -0x08 pointer to disk buffer
Bit16u ptrCONinput; // -0x04 pointer to con input
Bit16u firstMCB; // -0x02 first memory control block
RealPt firstDPB; // 0x00 first drive parameter block
RealPt firstFileTable; // 0x04 first system file table
RealPt activeClock; // 0x08 active clock device header
RealPt activeCon; // 0x0c active console device header
RealPt activeCon; // 0x0c active console device header
Bit16u maxSectorLength; // 0x10 maximum bytes per sector of any block device;
RealPt discInfoBuffer; // 0x12 pointer to disc info buffer
RealPt diskInfoBuffer; // 0x12 pointer to disk info buffer
RealPt curDirStructure; // 0x16 pointer to current array of directory structure
RealPt fcbTable; // 0x1a pointer to system FCB table
Bit8u stuff2[0x21]; // 0x1e more stuff
Bit16u buffers_x; // x in BUFFERS x,y
Bit16u buffers_y; // y in BUFFERS x,y
RealPt fcbTable; // 0x1a pointer to system FCB table
Bit16u protFCBs; // 0x1e protected fcbs
Bit8u blockDevices; // 0x20 installed block devices
Bit8u lastdrive; // 0x21 lastdrive
Bit32u nulNextDriver; // 0x22 NUL driver next pointer
Bit16u nulAttributes; // 0x26 NUL driver aattributes
Bit32u nulStrategy; // 0x28 NUL driver strategy routine
Bit8u nulString[8]; // 0x2c NUL driver name string
Bit8u joindedDrives; // 0x34 joined drives
Bit16u specialCodeSeg; // 0x35 special code segment
RealPt setverPtr; // 0x37 pointer to setver
Bit16u a20FixOfs; // 0x3b a20 fix routine offset
Bit16u pspLastIfHMA; // 0x3d psp of last program (if dos in hma)
Bit16u buffers_x; // 0x3f x in BUFFERS x,y
Bit16u buffers_y; // 0x41 y in BUFFERS x,y
Bit8u bootDrive; // 0x43 boot drive
Bit8u useDwordMov; // 0x44 use dword moves
Bit16u extendedSize; // 0x45 size of extended memory
// some more stuff, hopefully never used.
} GCC_ATTRIBUTE(packed);
#ifdef _MSC_VER
@ -389,9 +411,9 @@ private:
#endif
struct sDTA {
Bit8u sdrive; /* The Drive the search is taking place */
Bit8u sattr; /* The Attributes that need to be found */
Bit8u sname[8]; /* The Search pattern for the filename */
Bit8u sext[3]; /* The Search pattern for the extenstion */
Bit8u sattr; /* The Attributes that need to be found */
Bit16u dirID; /* custom: dir-search ID for multiple searches at the same time */
Bit8u fill[6];
Bit8u attr;
@ -422,6 +444,8 @@ public:
void SetRandom(Bit32u _random);
Bit8u GetDrive(void);
bool Extended(void);
void GetAttr(Bit8u & attr);
void SetAttr(Bit8u attr);
private:
bool extended;
PhysPt real_pt;
@ -438,8 +462,11 @@ private:
Bit16u date;
Bit16u time;
/* Reserved Block should be 8 bytes */
Bit8u sft_entries;
Bit8u share_attributes;
Bit8u extra_info;
Bit8u file_handle;
Bit8u reserved[7];
Bit8u reserved[4];
/* end */
Bit8u cur_rec; /* Current record in current block */
Bit32u rndm; /* Current relative record number */
@ -476,10 +503,78 @@ private:
#endif
};
extern DOS_InfoBlock dos_infoblock;;
extern Bit16u sdaseg;
#define DOS_SDA_SEG sdaseg
#define DOS_SDA_OFS 0
class DOS_SDA : public MemStruct {
public:
DOS_SDA(Bit16u _seg,Bit16u _offs) { SetPt(_seg,_offs); }
void Init();
void SetDrive(Bit8u _drive) { sSave(sSDA,current_drive, _drive); }
void SetDTA(Bit32u _dta) { sSave(sSDA,current_dta, _dta); }
void SetPSP(Bit16u _psp) { sSave(sSDA,current_psp, _psp); }
Bit8u GetDrive(void) { return sGet(sSDA,current_drive); }
Bit16u GetPSP(void) { return sGet(sSDA,current_psp); }
Bit32u GetDTA(void) { return sGet(sSDA,current_dta); }
private:
#ifdef _MSC_VER
#pragma pack (1)
#endif
struct sSDA {
Bit8u crit_error_flag; /* 0x00 Critical Error Flag */
Bit8u inDOS_flag; /* 0x01 InDOS flag (count of active INT 21 calls) */
Bit8u drive_crit_error; /* 0x02 Drive on which current critical error occurred or FFh */
Bit8u locus_of_last_error; /* 0x03 locus of last error */
Bit16u extended_error_code; /* 0x04 extended error code of last error */
Bit8u suggested_action; /* 0x06 suggested action for last error */
Bit8u error_class; /* 0x07 class of last error*/
Bit32u last_error_pointer; /* 0x08 ES:DI pointer for last error */
Bit32u current_dta; /* 0x0C current DTA (Disk Transfer Address) */
Bit16u current_psp; /* 0x10 current PSP */
Bit16u sp_int_23; /* 0x12 stores SP across an INT 23 */
Bit16u return_code; /* 0x14 return code from last process termination (zerod after reading with AH=4Dh) */
Bit8u current_drive; /* 0x16 current drive */
Bit8u extended_break_flag; /* 0x17 extended break flag */
Bit8u fill[2]; /* 0x18 flag: code page switching || flag: copy of previous byte in case of INT 24 Abort*/
} GCC_ATTRIBUTE(packed);
#ifdef _MSC_VER
#pragma pack()
#endif
};
extern DOS_InfoBlock dos_infoblock;
struct DOS_Block {
DOS_Date date;
DOS_Version version;
Bit16u firstMCB;
Bit16u errorcode;
Bit16u psp(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetPSP();};
void psp(Bit16u _seg){ DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetPSP(_seg);};
Bit16u env;
RealPt cpmentry;
RealPt dta(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDTA();};
void dta(RealPt _dta){DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDTA(_dta);};
Bit8u return_code,return_mode;
Bit8u current_drive;
bool verify;
bool breakcheck;
bool echo; // if set to true dev_con::read will echo input
struct {
RealPt mediaid;
RealPt tempdta;
RealPt dcbs;
} tables;
};
extern DOS_Block dos;
INLINE Bit8u RealHandle(Bit16u handle) {
DOS_PSP psp(dos.psp);
DOS_PSP psp(dos.psp());
return psp.GetFileHandle(handle);
}

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: dos_system.h,v 1.20 2004/01/12 20:25:57 finsterr Exp $ */
/* $Id: dos_system.h,v 1.24 2004/08/04 09:12:50 qbix79 Exp $ */
#ifndef DOSSYSTEM_H_
#define DOSSYSTEM_H_
@ -54,7 +54,7 @@ class DOS_DTA;
class DOS_File {
public:
DOS_File():flags(0) { name=0; refCtr = 0; };
virtual ~DOS_File(){};
virtual ~DOS_File(){if(name) delete [] name;};
virtual bool Read(Bit8u * data,Bit16u * size)=0;
virtual bool Write(Bit8u * data,Bit16u * size)=0;
virtual bool Seek(Bit32u * pos,Bit32u type)=0;
@ -66,6 +66,7 @@ public:
virtual bool IsName(const char* _name) { if (!name) return false; return strcmp(name,_name)==0; };
virtual void AddRef() { refCtr++; };
virtual Bits RemoveRef() { return --refCtr; };
virtual bool UpdateDateTimeFromHost() { return true; }
Bit8u type;
Bit32u flags;
Bit16u time;
@ -85,8 +86,8 @@ public:
Bit8u fhandle;
};
#define MAX_OPENDIRS 16
#define MAX_OPENDIRS 2048
//Can be high as it's only storage (16 bit variable)
class DOS_Drive_Cache {
public:
DOS_Drive_Cache (void);
@ -104,7 +105,7 @@ public:
char* GetExpandName (const char* path);
bool GetShortName (const char* fullname, char* shortname);
bool FindFirst (char* path, Bitu dtaAddress, Bitu& id);
bool FindFirst (char* path, Bitu& id);
bool FindNext (Bitu id, char* &result);
void CacheOut (const char* path, bool ignoreLastDir = false);
@ -119,21 +120,19 @@ public:
public:
CFileInfo(void) {
orgname[0] = shortname[0] = 0;
nextEntry = shortNr = compareCount = 0;
nextEntry = shortNr = 0;
isDir = false;
}
~CFileInfo(void) {
for (Bit32u i=0; i<fileList.size(); i++) delete fileList[i];
fileList.clear();
longNameList.clear();
compareCount = 0;
};
char orgname [CROSS_LEN];
char shortname [DOS_NAMELENGTH_ASCII];
bool isDir;
Bitu nextEntry;
Bitu shortNr;
Bitu compareCount;
// contents
std::vector<CFileInfo*> fileList;
std::vector<CFileInfo*> longNameList;
@ -142,18 +141,18 @@ public:
private:
bool RemoveTrailingDot (char* shortname);
Bits GetLongName (CFileInfo* info, char* shortname);
Bits GetLongName (CFileInfo* info, char* shortname);
void CreateShortName (CFileInfo* dir, CFileInfo* info);
Bit16u CreateShortNameID (CFileInfo* dir, const char* name);
int CompareShortname (const char* compareName, const char* shortName);
bool SetResult (CFileInfo* dir, char * &result, Bit16u entryNr);
bool IsCachedIn (CFileInfo* dir);
CFileInfo* FindDirInfo (const char* path, char* expandedPath);
int CompareShortname (const char* compareName, const char* shortName);
bool SetResult (CFileInfo* dir, char * &result, Bit16u entryNr);
bool IsCachedIn (CFileInfo* dir);
CFileInfo* FindDirInfo (const char* path, char* expandedPath);
bool RemoveSpaces (char* str);
bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id);
void CreateEntry (CFileInfo* dir, const char* name);
Bit16u GetFreeID (CFileInfo* dir);
void Clear (void);
bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id);
void CreateEntry (CFileInfo* dir, const char* name);
Bit16u GetFreeID (CFileInfo* dir);
void Clear (void);
CFileInfo* dirBase;
char dirPath [CROSS_LEN];
@ -169,6 +168,7 @@ private:
char dirSearchName [MAX_OPENDIRS];
bool free [MAX_OPENDIRS];
CFileInfo* dirFindFirst [MAX_OPENDIRS];
Bitu nextFreeFindFirst;
char label [CROSS_LEN];
};
@ -217,7 +217,7 @@ public:
virtual bool RemoveDir(char * _dir)=0;
virtual bool MakeDir(char * _dir)=0;
virtual bool TestDir(char * _dir)=0;
virtual bool FindFirst(char * _dir,DOS_DTA & dta)=0;
virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false)=0;
virtual bool FindNext(DOS_DTA & dta)=0;
virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
virtual bool Rename(char * oldname,char * newname)=0;

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -24,25 +24,6 @@ void E_Exit(char * message,...);
void MSG_Add(const char*,const char*); //add messages to the internal langaugefile
const char* MSG_Get(char const *); //get messages from the internal langaugafile
/* The internal types */
typedef unsigned char Bit8u;
typedef signed char Bit8s;
typedef unsigned short Bit16u;
typedef signed short Bit16s;
typedef unsigned long Bit32u;
typedef signed long Bit32s;
typedef double Real64;
#if defined(_MSC_VER)
typedef unsigned __int64 Bit64u;
typedef signed __int64 Bit64s;
#else
typedef unsigned long long Bit64u;
typedef signed long long Bit64s;
#endif
typedef unsigned int Bitu;
typedef signed int Bits;
#include <stddef.h>
#include "config.h"
@ -63,11 +44,11 @@ enum MachineType {
MCH_HERC,
MCH_CGA,
MCH_TANDY,
MCH_VGA,
MCH_AUTO
MCH_VGA
};
extern MachineType machine;
extern bool SDLNetInited;
#ifndef __LOGGING_H_
#include "logging.h"

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -19,7 +19,17 @@
#ifndef _HARDWARE_H_
#define _HARDWARE_H_
#include <stdio.h>
class Section;
enum OPL_Mode {
OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3
};
void OPL_Init(Section* sec,Bitu base,OPL_Mode mode,Bitu rate);
void CMS_Init(Section* sec,Bitu base,Bitu rate);
extern Bit8u adlib_commandreg;
FILE * OpenCaptureFile(const char * type,const char * ext);
#endif

View File

@ -9,37 +9,51 @@
* 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.
* 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.
*/
typedef Bit8u (IO_ReadBHandler)(Bit32u port);
typedef Bit16u (IO_ReadWHandler)(Bit32u port);
typedef Bit32u (IO_ReadDHandler)(Bit32u port);
typedef void (IO_WriteBHandler)(Bit32u port,Bit8u value);
typedef void (IO_WriteWHandler)(Bit32u port,Bit16u value);
typedef void (IO_WriteDHandler)(Bit32u port,Bit32u value);
#define IO_MAX (64*1024+3)
void IO_RegisterReadBHandler(Bitu port,IO_ReadBHandler * handler);
void IO_RegisterReadWHandler(Bitu port,IO_ReadWHandler * handler);
void IO_RegisterReadDHandler(Bitu port,IO_ReadDHandler * handler);
#define IO_MB 0x1
#define IO_MW 0x2
#define IO_MD 0x4
#define IO_MA (IO_MB | IO_MW | IO_MD )
void IO_RegisterWriteBHandler(Bitu port,IO_WriteBHandler * handler);
void IO_RegisterWriteWHandler(Bitu port,IO_WriteWHandler * handler);
void IO_RegisterWriteDHandler(Bitu port,IO_WriteDHandler * handler);
typedef Bitu IO_ReadHandler(Bitu port,Bitu iolen);
typedef void IO_WriteHandler(Bitu port,Bitu val,Bitu iolen);
void IO_FreeReadHandler(Bitu port);
void IO_FreeWriteHandler(Bitu port);
extern IO_WriteHandler * io_writehandlers[3][IO_MAX];
extern IO_ReadHandler * io_readhandlers[3][IO_MAX];
void IO_WriteB(Bitu port,Bit8u val);
Bit8u IO_ReadB(Bitu port);
void IO_WriteW(Bitu port,Bit16u val);
Bit16u IO_ReadW(Bitu port);
void IO_WriteD(Bitu port,Bit32u val);
Bit32u IO_ReadD(Bitu port);
void IO_RegisterReadHandler(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range=1);
void IO_RegisterWriteHandler(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range=1);
void IO_FreeReadHandler(Bitu port,Bitu mask,Bitu range=0);
void IO_FreeWriteHandler(Bitu port,Bitu mask,Bitu range=0);
INLINE void IO_WriteB(Bitu port,Bitu val) {
io_writehandlers[0][port](port,val,1);
};
INLINE void IO_WriteW(Bitu port,Bitu val) {
io_writehandlers[1][port](port,val,2);
};
INLINE void IO_WriteD(Bitu port,Bitu val) {
io_writehandlers[2][port](port,val,4);
};
INLINE Bitu IO_ReadB(Bitu port) {
return io_readhandlers[0][port](port,1);
}
INLINE Bitu IO_ReadW(Bitu port) {
return io_readhandlers[1][port](port,2);
}
INLINE Bitu IO_ReadD(Bitu port) {
return io_readhandlers[2][port](port,4);
}
INLINE void IO_Write(Bitu port,Bit8u val) {
IO_WriteB(port,val);
@ -48,11 +62,4 @@ INLINE Bit8u IO_Read(Bitu port){
return IO_ReadB(port);
}
INLINE void IO_RegisterReadHandler(Bitu port,IO_ReadBHandler * handler,char * name) {
IO_RegisterReadBHandler(port,handler);
}
INLINE void IO_RegisterWriteHandler(Bitu port,IO_WriteBHandler * handler,char * name) {
IO_RegisterWriteBHandler(port,handler);
}

92
include/ipx.h Normal file
View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2002-2004 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 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 _IPX_H_
#define _IPX_H_
// In Use Flag codes
#define USEFLAG_AVAILABLE 0x00
#define USEFLAG_AESTEMP 0xe0
#define USEFLAG_IPXCRIT 0xf8
#define USEFLAG_SPXLISTEN 0xf9
#define USEFLAG_PROCESSING 0xfa
#define USEFLAG_HOLDING 0xfb
#define USEFLAG_AESWAITING 0xfc
#define USEFLAG_AESCOUNT 0xfd
#define USEFLAG_LISTENING 0xfe
#define USEFLAG_SENDING 0xff
// Completion codes
#define COMP_SUCCESS 0x00
#define COMP_REMOTETERM 0xec
#define COMP_DISCONNECT 0xed
#define COMP_INVALIDID 0xee
#define COMP_SPXTABLEFULL 0xef
#define COMP_EVENTNOTCANCELED 0xf9
#define COMP_NOCONNECTION 0xfa
#define COMP_CANCELLED 0xfc
#define COMP_MALFORMED 0xfd
#define COMP_UNDELIVERABLE 0xfe
#define COMP_HARDWAREERROR 0xff
#ifdef _MSC_VER
#pragma pack(1)
#endif
// For Uint8 type
#include "SDL_net.h"
struct PackedIP {
Uint32 host;
Uint16 port;
} GCC_ATTRIBUTE(packed);
struct nodeType {
Uint8 node[6];
}GCC_ATTRIBUTE(packed) ;
struct IPXHeader {
Uint8 checkSum[2];
Uint8 length[2];
Uint8 transControl; // Transport control
Uint8 pType; // Packet type
struct transport {
Uint8 network[4];
union addrtype {
nodeType byNode;
PackedIP byIP ;
} GCC_ATTRIBUTE(packed) addr;
Uint8 socket[2];
} dest, src;
} GCC_ATTRIBUTE(packed);
// The following routines may not be needed on all systems. On my build of SDL the IPaddress structure is 8 octects
// and therefore screws up my IPXheader structure since it needs to be packed.
void UnpackIP(PackedIP ipPack, IPaddress * ipAddr);
void PackIP(IPaddress ipAddr, PackedIP *ipPack);
#ifdef _MSC_VER
#pragma pack()
#endif
#endif

50
include/ipxserver.h Normal file
View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2002-2004 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 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 _IPXSERVER_H_
#define _IPXSERVER_H_
#if C_IPX
#include "SDL_net.h"
struct packetBuffer {
Bit8u buffer[1024];
Bit16s packetSize; // Packet size remaining in read
Bit16s packetRead; // Bytes read of total packet
bool inPacket; // In packet reception flag
bool connected; // Connected flag
bool waitsize;
};
#define SOCKETTABLESIZE 16
#define IPXBUFFERSIZE 1024
#define CONVIP(hostvar) hostvar & 0xff, (hostvar >> 8) & 0xff, (hostvar >> 16) & 0xff, (hostvar >> 24) & 0xff
#define CONVIPX(hostvar) hostvar[0], hostvar[1], hostvar[2], hostvar[3], hostvar[4], hostvar[5]
void IPX_StopServer();
bool IPX_StartServer(Bit16u portnum);
bool IPX_isConnectedToServer(Bits tableNum, IPaddress ** ptrAddr);
Bit8u packetCRC(Bit8u *buffer, Bit16u bufSize);
#endif
#endif

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -20,6 +20,7 @@
#define _KEYBOARD_H_
enum KBD_KEYS {
KBD_NONE,
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,
@ -35,25 +36,17 @@ enum KBD_KEYS {
KBD_grave,KBD_minus,KBD_equals,KBD_backslash,KBD_leftbracket,KBD_rightbracket,
KBD_semicolon,KBD_quote,KBD_period,KBD_comma,KBD_slash,
KBD_printscreen,KBD_pause,
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_kpdivide,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod,
KBD_LAST
};
typedef void(KEYBOARD_EventHandler)(void);
void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler);
void KEYBOARD_AddKey(KBD_KEYS key,Bitu ascii,Bitu mod,bool pressed);
void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod);
#define KBD_MOD_ALT 0x1
#define KBD_MOD_CTRL 0x2
#define KBD_MOD_SHIFT 0x4
void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed);
#endif

40
include/mapper.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2002-2004 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 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 MAPPER_H_
#define MAPPER_H_
enum MapKeys {
MK_f1,MK_f2,MK_f3,MK_f4,MK_f5,MK_f6,MK_f7,MK_f8,MK_f9,MK_f10,MK_f11,MK_f12,
MK_return,MK_kpminus,MK_scrolllock,MK_printscreen,MK_pause,
};
typedef void (MAPPER_Handler)(void);
void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char * eventname,char * buttonname);
void MAPPER_Init(void);
void MAPPER_StartUp(Section * sec);
void MAPPER_Run(void);
#define MMOD1 0x1
#define MMOD2 0x2
#endif

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -20,8 +20,6 @@
#define __MEM_H
#include <dosbox.h>
#define bmemcpy(mem1,mem2,size) memcpy((void *)mem1,(void *)mem2,size)
typedef Bit32u PhysPt;
typedef Bit8u * HostPt;
typedef Bit32u RealPt;
@ -30,6 +28,8 @@ typedef Bit32s MemHandle;
#define MEM_PAGESIZE 4096
extern HostPt MemBase;
bool MEM_A20_Enabled(void);
void MEM_A20_Enable(bool enable);
@ -123,9 +123,25 @@ void mem_writeb(PhysPt pt,Bit8u val);
void mem_writew(PhysPt pt,Bit16u val);
void mem_writed(PhysPt pt,Bit32u val);
void phys_writeb(PhysPt addr,Bit8u val);
void phys_writew(PhysPt addr,Bit16u val);
void phys_writed(PhysPt addr,Bit32u val);
INLINE void phys_writeb(PhysPt addr,Bit8u val) {
host_writeb(MemBase+addr,val);
}
INLINE void phys_writew(PhysPt addr,Bit16u val){
host_writew(MemBase+addr,val);
}
INLINE void phys_writed(PhysPt addr,Bit32u val){
host_writed(MemBase+addr,val);
}
INLINE Bit8u phys_readb(PhysPt addr) {
return host_readb(MemBase+addr);
}
INLINE Bit16u phys_readw(PhysPt addr){
return host_readw(MemBase+addr);
}
INLINE Bit32u phys_readd(PhysPt addr){
return host_readd(MemBase+addr);
}
/* These don't check for alignment, better be sure it's correct */

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -17,25 +17,54 @@
*/
typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len);
typedef void (*MIXER_Handler)(Bitu len);
#define MIXER_8MONO 0
#define MIXER_8STEREO 1
#define MIXER_16MONO 2
#define MIXER_16STEREO 3
enum BlahModes {
MIXER_8MONO,MIXER_8STEREO,
MIXER_16MONO,MIXER_16STEREO
};
enum MixerModes {
M_8M,M_8S,
M_16M,M_16S,
};
#define MIXER_BUFSIZE (16*1024)
#define MIXER_BUFMASK (MIXER_BUFSIZE-1)
extern Bit8u MixTemp[MIXER_BUFSIZE];
#define MAX_AUDIO ((1<<(16-1))-1)
#define MIN_AUDIO -(1<<(16-1))
class MixerChannel {
public:
void SetVolume(float _left,float _right);
void UpdateVolume(void);
void SetFreq(Bitu _freq);
void Mix(Bitu _needed);
void AddSilence(void); //Fill up until needed
template<bool _8bit,bool stereo>
void AddSamples(Bitu len,void * data);
void AddSamples_m8(Bitu len,Bit8u * data);
void AddSamples_s8(Bitu len,Bit8u * data);
void AddSamples_m16(Bitu len,Bit16s * data);
void AddSamples_s16(Bitu len,Bit16s * data);
void AddStretched(Bitu len,Bit16s * data); //Strech block up into needed data
void FillUp(void);
void Enable(bool _yesno);
MIXER_Handler handler;
float volmain[2];
Bit32s volmul[2];
Bitu freq_add,freq_index;
Bitu done,needed;
Bits last[2];
char * name;
bool enabled;
MixerChannel * next;
};
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);
MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,char * name);
MixerChannel * MIXER_FindChannel(const char * name);
/* PC Speakers functions, tightly related to the timer functions */

View File

@ -9,16 +9,23 @@
* 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.
* 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.
*/
/* $Id: mouse.h,v 1.7 2004/08/04 09:12:51 qbix79 Exp $ */
#ifndef _MOUSE_H_
#define _MOUSE_H_
void Mouse_ShowCursor(void);
void Mouse_HideCursor(void);
void Mouse_SetPS2State(bool use);
void Mouse_ChangePS2Callback(Bit16u pseg, Bit16u pofs);
void Mouse_CursorMoved(float x,float y);
void Mouse_CursorSet(float x,float y);
@ -28,3 +35,5 @@ void Mouse_ButtonReleased(Bit8u button);
void Mouse_AutoLock(bool enable);
void Mouse_NewVideoMode(void);
#endif

View File

@ -9,16 +9,19 @@
* 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.
* 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.
*/
/* $Id: paging.h,v 1.11 2004/09/07 18:21:51 qbix79 Exp $ */
#ifndef _PAGING_H_
#define _PAGING_H_
#include "dosbox.h"
#include "mem.h"
class PageDirectory;
@ -70,13 +73,10 @@ bool PAGING_MakePhysPage(Bitu & page);
void MEM_SetLFB(Bitu _page,Bitu _pages,HostPt _pt);
void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler);
Bit32u MEM_PhysReadD(Bitu addr);
#pragma pack(1)
typedef struct {
#ifdef _MSC_VER
#pragma pack (1)
#endif
struct X86_PageEntryBlock{
Bit32u p:1;
Bit32u wr:1;
Bit32u us:1;
@ -88,8 +88,11 @@ typedef struct {
Bit32u g:1;
Bit32u avl:3;
Bit32u base:20;
} X86_PageEntryBlock GCC_ATTRIBUTE(packed);
#pragma pack()
} GCC_ATTRIBUTE(packed);
#ifdef _MSC_VER
#pragma pack ()
#endif
union X86PageEntry {
Bit32u load;

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -26,41 +26,36 @@ extern Bits CPU_CycleLeft;
extern Bits CPU_CycleMax;
typedef void (PIC_EOIHandler) (void);
typedef void (* PIC_EventHandler)(void);
typedef void (* PIC_EventHandler)(Bitu val);
#define PIC_MAXIRQ 15
#define PIC_NOIRQ 0xFF
extern Bitu PIC_IRQCheck;
extern Bitu PIC_IRQActive;
extern Bitu PIC_Ticks;
INLINE Bitu PIC_Index(void) {
return ((CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)*1000)/CPU_CycleMax;
INLINE float PIC_TickIndex(void) {
return (CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)/(float)CPU_CycleMax;
}
INLINE Bits PIC_MakeCycles(Bitu amount) {
return (CPU_CycleMax*amount)/1000;
INLINE Bits PIC_MakeCycles(double amount) {
return (Bits)(CPU_CycleMax*amount);
}
INLINE Bit64u PIC_MicroCount(void) {
return PIC_Ticks*1000+PIC_Index();
INLINE double PIC_FullIndex(void) {
return PIC_Ticks+PIC_TickIndex();
}
void PIC_ActivateIRQ(Bitu irq);
void PIC_DeActivateIRQ(Bitu irq);
void PIC_runIRQs(void);
void PIC_RegisterIRQ(Bitu irq,PIC_EOIHandler handler,char * name);
void PIC_FreeIRQ(Bitu irq);
bool PIC_RunQueue(void);
void PIC_AddEvent(PIC_EventHandler handler,Bitu delay);
//Delay in milliseconds
void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val=0);
void PIC_RemoveEvents(PIC_EventHandler handler);
void PIC_SetIRQMask(Bitu irq, bool masked);

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -19,22 +19,14 @@
#ifndef __RENDER_H
#define __RENDER_H
enum RENDER_Operation {
OP_None,
OP_Shot,
OP_Normal2x,
OP_AdvMame2x,
};
typedef void (* RENDER_Line_Handler)(const Bit8u * src);
typedef void (* RENDER_Line_Handler)(Bit8u * src);
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh);
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,bool dblw,bool dblh);
bool RENDER_StartUpdate(void);
void RENDER_EndUpdate(void);
void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue);
extern RENDER_Line_Handler RENDER_DrawLine;
extern Bit8u * RENDER_TempLine;
#endif

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -19,118 +19,137 @@
#if !defined __SERIALPORT_H
#define __SERIALPORT_H
#include <dosbox.h>
#include <assert.h>
#include "dosbox.h"
//If it's too high you overflow terminal clients buffers i think
#define FIFO_SIZE (1024)
#define QUEUE_SIZE 1024
// Serial port interface //
#define M_CTS 0x01
#define M_DSR 0x02
#define M_RI 0x04
#define M_DCD 0x08
#define MS_CTS 0x01
#define MS_DSR 0x02
#define MS_RI 0x04
#define MS_DCD 0x08
enum INT_TYPES {
INT_MS,
INT_TX,
INT_RX,
INT_RX_FIFO,
INT_LS,
INT_NONE,
#define MC_DTR 0x1
#define MC_RTS 0x2
class CFifo {
public:
CFifo(Bitu _size) {
size=_size;
pos=used=0;
data=new Bit8u[size];
}
~CFifo() {
delete[] data;
}
INLINE Bitu left(void) {
return size-used;
}
INLINE Bitu inuse(void) {
return used;
}
void clear(void) {
used=pos=0;
}
bool isFull() {
return (used >= size);
}
void addb(Bit8u _val) {
assert(used<size);
Bitu where=pos+used;
if (where>=size) where-=size;
data[where]=_val;
used++;
}
void adds(Bit8u * _str,Bitu _len) {
assert((used+_len)<=size);
Bitu where=pos+used;
used+=_len;
while (_len--) {
if (where>=size) where-=size;
data[where++]=*_str++;
}
}
Bit8u getb(void) {
if (!used) return data[pos];
Bitu where=pos;
if (++pos>=size) pos-=size;
used--;
return data[where];
}
void gets(Bit8u * _str,Bitu _len) {
assert(used>=_len);
used-=_len;
while (_len--) {
*_str++=data[pos];
if (++pos>=size) pos-=size;
}
}
private:
Bit8u * data;
Bitu size,pos,used;
};
typedef void MControl_Handler(Bitu mc);
class CSerial {
public:
CSerial() {
}
// Constructor takes base port (0x3f0, 0x2f0, 0x2e0, etc.), IRQ, and initial bps //
CSerial (Bit16u initbase, Bit8u initirq, Bit32u initbps);
virtual ~CSerial();
// External port functions for IOHandlers //
void write_port(Bit32u port, Bit8u val);
Bit8u read_port(Bit32u port);
void write_reg(Bitu reg, Bitu val);
Bitu read_reg(Bitu reg);
static void write_serial(Bit32u port,Bit8u val);
static Bit8u read_serial(Bit32u port);
void SetMCHandler(MControl_Handler * mcontrol);
/* Allow the modem to change the modem status bits */
void setmodemstatus(Bit8u status);
Bit8u getmodemstatus(void);
Bit8u getlinestatus(void);
void SetModemStatus(Bit8u status);
virtual bool CanRecv(void)=0;
virtual bool CanSend(void)=0;
virtual void Send(Bit8u val)=0;
virtual Bit8u Recv(Bit8u val)=0;
virtual void Timer(void);
void checkint(void);
void raiseint(INT_TYPES type);
void lowerint(INT_TYPES type);
/* Access to the receive fifo */
Bitu rx_free();
void rx_addb(Bit8u byte);
void rx_adds(Bit8u * data,Bitu size);
Bitu rx_size();
Bit8u rx_readb(void);
Bitu base;
Bitu irq;
Bitu bps;
Bit8u mctrl;
/* Access to the transmit fifo */
Bitu tx_free();
void tx_addb(Bit8u byte);
Bitu tx_size();
Bit8u tx_readb(void);
// These variables maintain the status of the serial port
Bit16u base;
Bit16u irq;
Bit32u bps;
bool FIFOenabled;
Bit16u FIFOsize;
CFifo *rqueue;
CFifo *tqueue;
private:
void setdivisor(Bit8u dmsb, Bit8u dlsb);
void checkforirq(void);
struct {
Bitu used;
Bitu pos;
Bit8u data[FIFO_SIZE];
} rx_fifo,tx_fifo;
struct {
Bitu requested;
Bitu enabled;
INT_TYPES active;
} ints;
Bitu rx_lastread;
Bit8u irq_pending;
void UpdateBaudrate(void);
bool FIFOenabled;
Bit8u FIFOsize;
bool dotxint;
Bit8u scratch;
Bit8u dlab;
Bit8u divisor_lsb;
Bit8u divisor_msb;
Bit8u wordlen;
Bit8u dtr;
Bit8u rts;
Bit8u out1;
Bit8u out2;
Bit8u local_loopback;
Bit8u linectrl;
Bit8u intid;
Bit8u ierval;
Bit8u iir;
Bit8u ier;
Bit8u mstatus;
Bit8u txval;
Bit8u timeout;
MControl_Handler * mc_handler;
char remotestr[4096];
Bit8u linectrl;
Bit8u errors;
};
// This function returns the CSerial objects for ports 1-4 //
CSerial *getComport(Bitu portnum);
#include <list>
typedef std::list<CSerial *> CSerialList;
typedef std::list<CSerial *>::iterator CSerial_it;
extern CSerialList seriallist;
#endif

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: setup.h,v 1.15 2004/01/29 09:26:43 qbix79 Exp $ */
/* $Id: setup.h,v 1.16 2004/08/04 09:12:51 qbix79 Exp $ */
#ifndef _SETUP_H_
#define _SETUP_H_

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: shell.h,v 1.2 2004/01/10 14:03:33 qbix79 Exp $ */
/* $Id: shell.h,v 1.7 2004/09/09 18:36:50 qbix79 Exp $ */
#ifndef SHELL_H_
#define SHELL_H_
@ -57,9 +57,7 @@ public:
};
class DOS_Shell : public Program {
private:
std::list<std::string> l_history, l_completion;
char *completion_start;
@ -102,6 +100,8 @@ public:
void CMD_PAUSE(char * args);
void CMD_SUBST(char* args);
void CMD_LOADHIGH(char* args);
void CMD_CHOICE(char * args);
void CMD_ATTRIB(char * args);
/* The shell's variables */
Bit16u input_handle;
BatchFile * bf;
@ -117,15 +117,12 @@ struct SHELL_Cmd {
const char * help; /* String with command help */
};
static inline void StripSpaces(char*&args)
{
while(*args && (*args == ' '))
static inline void StripSpaces(char*&args) {
while(*args && ((*args == ' ') || (*args == '\t')))
args++;
}
static inline char* ExpandDot(char*args, char* buffer)
{
static inline char* ExpandDot(char*args, char* buffer) {
if(*args=='.')
{
if(*(args+1)==0)
@ -139,11 +136,11 @@ static inline char* ExpandDot(char*args, char* buffer)
buffer[1]=0;
strcat(buffer,args);
return buffer;
}
} else
strcpy (buffer, args);
}
else strcpy(buffer,args);
return buffer;
}
#endif

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -19,11 +19,11 @@
#if !defined __SUPPORT_H
#define __SUPPORT_H
#include <dosbox.h>
#include <string.h>
#include <ctype.h>
#include "dosbox.h"
#if defined (_MSC_VER) /* MS Visual C++ */
#define strcasecmp(a,b) stricmp(a,b)
#define strncasecmp(a,b,n) _strnicmp(a,b,n)
@ -39,13 +39,16 @@
void strreplace(char * str,char o,char n);
char *ltrim(char *str);
void rtrim(char * const str);
char *trim(char *str);
char *rtrim(char *str);
char *trim(char * str);
bool ScanCMDBool(char * cmd,char * check);
char * ScanCMDRemain(char * cmd);
bool ScanCMDHex(char * cmd,char * check,Bits * result);
char * StripWord(char * cmd);
char * StripWord(char *&cmd);
bool IsDecWord(char * word);
bool IsHexWord(char * word);
Bits ConvDecWord(char * word);
Bits ConvHexWord(char * word);
INLINE char * upcase(char * str) {
for (char* idx = str; *idx ; idx++) *idx = toupper(*idx);

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -25,19 +25,11 @@
#define GetTicks() SDL_GetTicks()
typedef void (*TIMER_TickHandler)(Bitu ticks);
typedef void (*TIMER_MicroHandler)(void);
typedef void TIMER_Block;
typedef void (*TIMER_TickHandler)(void);
/* 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);
/* Set the microseconds value to a new value */
void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro);
void TIMER_AddTickHandler(TIMER_TickHandler handler);
void TIMER_DelTickHandler(TIMER_TickHandler handler);
/* This will add 1 milliscond to all timers */
void TIMER_AddTick(void);

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -23,13 +23,13 @@
#include "dosbox.h"
enum VGAModes {
M_TEXT2,M_TEXT16,
M_HERC,
M_CGA2,M_CGA4,M_CGA16,
M_TANDY16,
M_EGA2,M_EGA4,M_EGA16,
M_CGA2,M_CGA4,
M_EGA16,
M_VGA,
M_LIN8,
M_TEXT,
M_HERC_GFX,M_HERC_TEXT,
M_CGA16,M_TANDY2,M_TANDY4,M_TANDY16,M_TANDY_TEXT,
M_ERROR,
};
@ -60,9 +60,7 @@ typedef struct {
/* Some other screen related variables */
Bitu line_compare;
bool chained; /* Enable or Disabled Chain 4 Mode */
bool blinking; /* Attribute bit 7 is blinking */
/* Pixel Scrolling */
Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */
@ -91,10 +89,8 @@ typedef struct {
typedef struct {
bool resizing;
bool drawing;
Bitu width;
Bitu height;
Bitu pitch;
Bitu blocks;
Bitu panning;
Bitu address;
@ -102,49 +98,62 @@ typedef struct {
Bitu address_line_total;
Bitu address_line;
Bitu lines_total;
Bitu lines_left;
Bitu lines_done;
Bitu lines_scaled;
Bitu split_line;
Bitu parts_total;
Bitu parts_lines;
Bitu parts_left;
struct {
Bitu vtotal;
Bitu vstart;
Bitu vend;
Bitu htotal;
Bitu hstart;
Bitu hend;
Bitu parts;
} micro;
Bitu scaleh;
float vtotal;
float vstart;
float vend;
float htotal;
float hstart;
float hend;
float parts;
} delay;
bool double_scan;
bool double_scan_active;
Bit8u font_height;
bool doublewidth,doubleheight;
Bit8u font[64*1024];
Bitu font1_start;
Bitu font2_start;
Bit8u * font_tables[2];
Bitu blinking;
struct {
Bitu address;
Bit8u sline,eline;
Bit8u count,delay;
Bit8u enabled;
} cursor;
} VGA_Draw;
typedef struct {
Bit8u curmode;
Bit16u originx, originy;
Bit8u fstackpos, bstackpos;
Bit8u forestack[3];
Bit8u backstack[3];
Bit16u startaddr;
Bit8u posx, posy;
Bit8u mc[64][64];
} VGA_HWCURSOR;
typedef struct {
Bit8u bank;
Bit8u reg_lock1;
Bit8u reg_lock2;
Bit8u reg_31;
Bit8u reg_35;
Bit8u reg_40; // 8415/A functionality register
Bit8u reg_43;
Bit8u reg_45; // Hardware graphics cursor
Bit8u reg_58;
Bit8u reg_51;
Bit8u reg_55;
Bit8u ex_hor_overflow;
Bit8u ex_ver_overflow;
Bit16u la_window;
Bit8u misc_control_2;
Bit8u ext_mem_ctrl;
struct {
Bit8u r;
Bit8u n;
@ -154,6 +163,7 @@ typedef struct {
Bit8u lock;
Bit8u cmd;
} pll;
VGA_HWCURSOR hgc;
} VGA_S3;
typedef struct {
@ -162,18 +172,28 @@ typedef struct {
} VGA_HERC;
typedef struct {
Bit8u mode_control;
Bit8u color_select;
} VGA_CGA;
Bit8u index;
Bit8u htotal;
Bit8u hdend;
Bit8u hsyncp;
Bit8u hsyncw;
Bit8u vtotal;
Bit8u vdend;
Bit8u vadjust;
Bit8u vsyncp;
Bit8u vsyncw;
Bit8u max_scanline;
} VGA_OTHER;
typedef struct {
Bit8u mode_control;
Bit8u color_select;
Bit8u mem_bank;
Bit8u disp_bank;
Bit8u reg_index;
Bit8u mode_control1;
Bit8u gfx_control;
Bit8u palette_mask;
Bit8u border_color;
Bit8u mode_control2;
} VGA_TANDY;
typedef struct {
@ -256,7 +276,6 @@ typedef struct {
Bit8u read_index;
Bitu first_changed;
RGBEntry rgb[0x100];
Bit8u attr[16];
} VGA_Dac;
union VGA_Latch {
@ -285,8 +304,8 @@ typedef struct {
VGA_Latch latch;
VGA_S3 s3;
VGA_HERC herc;
VGA_CGA cga;
VGA_TANDY tandy;
VGA_OTHER other;
VGA_Memory mem;
} VGA_Type;
@ -294,12 +313,15 @@ typedef struct {
/* Functions for different resolutions */
void VGA_SetMode(VGAModes mode);
void VGA_DetermineMode(void);
void VGA_SetupHandlers(void);
void VGA_StartResize(void);
void VGA_SetupDrawing(void);
void VGA_SetupDrawing(Bitu val);
void VGA_CheckScanLength(void);
/* Some DAC/Attribute functions */
void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal);
void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue);
void VGA_ATTR_SetPalette(Bit8u index,Bit8u val);
/* The VGA Subfunction startups */
@ -310,6 +332,8 @@ void VGA_SetupCRTC(void);
void VGA_SetupMisc(void);
void VGA_SetupGFX(void);
void VGA_SetupSEQ(void);
void VGA_SetupOther(void);
void VGA_SetupXGA(void);
/* Some Support Functions */
void VGA_SetClock(Bitu which,Bitu target);
@ -317,6 +341,8 @@ void VGA_DACSetEntirePalette(void);
void VGA_StartRetrace(void);
void VGA_StartUpdateLFB(void);
void VGA_SetBlinking(Bitu enabled);
void VGA_SetCGA2Table(Bit8u val0,Bit8u val1);
void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3);
extern VGA_Type vga;

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -28,21 +28,43 @@ struct GFX_PalEntry {
Bit8u unused;
};
#define GFX_HASSCALING 0x0001
#define GFX_HASCONVERT 0x0002
#define CAN_8 0x0001
#define CAN_16 0x0002
#define CAN_32 0x0004
#define CAN_ALL (CAN_8|CAN_16|CAN_32)
#define LOVE_8 0x0010
#define LOVE_16 0x0020
#define LOVE_32 0x0040
#define NEED_RGB 0x0100
#define DONT_ASPECT 0x0200
#define HAVE_SCALING 0x1000
enum GFX_Modes {
GFX_8,GFX_15,GFX_16,GFX_32,GFX_NONE,
};
void GFX_Events(void);
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries);
Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags);
Bitu GFX_GetBestMode(Bitu flags);
Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue);
void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack cb_reset);
GFX_Modes GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_ResetCallBack cb_reset);
void GFX_ResetScreen(void);
void GFX_Start(void);
void GFX_Stop(void);
void GFX_SwitchFullScreen(void);
bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch);
void GFX_EndUpdate(void);
/* Mouse related */
void GFX_CaptureMouse(void);
extern bool mouselocked; //true if mouse is confined to window
#endif

View File

@ -3,5 +3,5 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcpu.a
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \
paging.cpp lazyflags.h core_normal.cpp \
paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \
core_dyn_x86.cpp

View File

@ -134,7 +134,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcpu.a
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \
paging.cpp lazyflags.h core_normal.cpp \
paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \
core_dyn_x86.cpp
subdir = src/cpu
@ -148,7 +148,8 @@ libcpu_a_AR = $(AR) cru
libcpu_a_LIBADD =
am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \
modrm.$(OBJEXT) core_full.$(OBJEXT) paging.$(OBJEXT) \
core_normal.$(OBJEXT) core_dyn_x86.$(OBJEXT)
core_normal.$(OBJEXT) core_simple.$(OBJEXT) \
core_dyn_x86.$(OBJEXT)
libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@ -157,8 +158,9 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/callback.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/core_dyn_x86.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/core_full.Po ./$(DEPDIR)/core_normal.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/cpu.Po ./$(DEPDIR)/flags.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/modrm.Po ./$(DEPDIR)/paging.Po
@AMDEP_TRUE@ ./$(DEPDIR)/core_simple.Po ./$(DEPDIR)/cpu.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/flags.Po ./$(DEPDIR)/modrm.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/paging.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
@ -208,6 +210,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dyn_x86.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_full.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_normal.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_simple.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flags.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modrm.Po@am__quote@

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: callback.cpp,v 1.19 2004/01/07 20:23:48 qbix79 Exp $ */
/* $Id: callback.cpp,v 1.22 2004/08/29 11:22:37 qbix79 Exp $ */
#include <stdlib.h>
#include <stdio.h>
@ -67,8 +67,7 @@ void CALLBACK_Idle(void) {
reg_eip=oldeip;
SegSet16(cs,oldcs);
SETFLAGBIT(IF,oldIF);
if (CPU_CycleLeft<300) CPU_CycleLeft=1;
else CPU_CycleLeft-=300;
if (CPU_Cycles>0) CPU_Cycles=0;
}
static Bitu default_handler(void) {
@ -204,12 +203,14 @@ void CALLBACK_Init(Section* sec) {
/* Setup the Stop Handler */
call_stop=CALLBACK_Allocate();
CallBack_Handlers[call_stop]=stop_handler;
CALLBACK_SetDescription(call_stop,"stop");
phys_writeb(CB_BASE+(call_stop<<4)+0,0xFE);
phys_writeb(CB_BASE+(call_stop<<4)+1,0x38);
phys_writew(CB_BASE+(call_stop<<4)+2,call_stop);
/* Setup the idle handler */
call_idle=CALLBACK_Allocate();
CallBack_Handlers[call_idle]=stop_handler;
CALLBACK_SetDescription(call_idle,"idle");
for (i=0;i<=11;i++) phys_writeb(CB_BASE+(call_idle<<4)+i,0x90);
phys_writeb(CB_BASE+(call_idle<<4)+12,0xFE);
phys_writeb(CB_BASE+(call_idle<<4)+13,0x38);
@ -217,7 +218,7 @@ void CALLBACK_Init(Section* sec) {
/* Setup all Interrupt to point to the default handler */
call_default=CALLBACK_Allocate();
CALLBACK_Setup(call_default,&default_handler,CB_IRET);
CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default");
/* Only setup default handler for first half of interrupt table */
for (i=0;i<0x40;i++) {
real_writed(0,i*4,CALLBACK_RealPointer(call_default));

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -33,10 +33,11 @@
#include "paging.h"
#include "inout.h"
#define CACHE_TOTAL (1024*1024*2)
#define CACHE_TOTAL (512*1024)
#define CACHE_MAXSIZE (4096)
#define CACHE_BLOCKS (50*1024)
#define CACHE_BLOCKS (32*1024)
#define CACHE_ALIGN (16)
#define CACHE_PAGES (128)
#define DYN_HASH_SHIFT (4)
#define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT)
#define DYN_LINKS (16)
@ -68,8 +69,8 @@ enum DualOps {
DOP_SUB,DOP_SBB,
DOP_CMP,DOP_XOR,
DOP_AND,DOP_OR,
DOP_MOV,
DOP_TEST,
DOP_MOV,
DOP_XCHG,
};
@ -77,7 +78,7 @@ enum ShiftOps {
SHIFT_ROL,SHIFT_ROR,
SHIFT_RCL,SHIFT_RCR,
SHIFT_SHL,SHIFT_SHR,
SHIFT_SAR,
SHIFT_SAL,SHIFT_SAR,
};
enum BranchTypes {
@ -87,19 +88,15 @@ enum BranchTypes {
BR_L,BR_NL,BR_LE,BR_NLE
};
enum BlockType {
BT_Free=0,
BT_Normal,
BT_SingleLink,
BT_DualLink,
BT_CheckFlags,
};
enum BlockReturn {
BR_Normal=0,
BR_Cycles,
BR_Link1,BR_Link2,
BR_Opcode,
#if (C_DEBUG)
BR_OpcodeFull,
#endif
BR_CallBack,
};
@ -153,28 +150,23 @@ struct DynState {
DynReg regs[G_MAX];
};
static void dyn_releaseregs(void) {
for (Bitu i=0;i<G_MAX;i++) gen_releasereg(&DynRegs[i]);
}
static void dyn_load_flags(void) {
/* Load the host flags with emulated flags */
gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(FLAGS));
gen_dop_word_imm(DOP_AND,true,DREG(TMPW),FMASK_TEST);
gen_load_flags(DREG(TMPW));
gen_releasereg(DREG(TMPW));
static void dyn_flags_host_to_gen(void) {
gen_dop_word(DOP_MOV,true,DREG(EXIT),DREG(FLAGS));
gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST);
gen_load_flags(DREG(EXIT));
gen_releasereg(DREG(EXIT));
gen_releasereg(DREG(FLAGS));
}
static void dyn_save_flags(bool stored=false) {
/* Store the host flags back in emulated ones */
gen_save_flags(DREG(EXIT),stored);
static void dyn_flags_gen_to_host(void) {
gen_save_flags(DREG(EXIT));
gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST);
gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FMASK_TEST);
gen_dop_word(DOP_OR,true,DREG(FLAGS),DREG(EXIT)); //flags are marked for save
gen_releasereg(DREG(EXIT));
gen_releasereg(DREG(FLAGS));
}
static void dyn_savestate(DynState * state) {
for (Bitu i=0;i<G_MAX;i++) {
state->regs[i].flags=DynRegs[i].flags;
@ -201,80 +193,61 @@ Bits CPU_Core_Dyn_X86_Run(void) {
restart_core:
PhysPt ip_point=SegPhys(cs)+reg_eip;
Bitu ip_page=ip_point>>12;
mem_readb(ip_point); //Init whatever page we are in
PageHandler * handler=paging.tlb.handler[ip_page];
CodePageHandler * chandler=0;
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
if (handler->flags & PFLAG_HASCODE) {
/* Find correct Dynamic Block to run */
chandler=(CodePageHandler *)handler;
findblock:;
CacheBlock * block=chandler->FindCacheBlock(ip_point&4095);
if (!block) {
cache.block.running=0;
block=CreateCacheBlock(ip_point,cpu.code.big,128);
// DYN_LOG("Created block size %x type %d",block->cache.size,block->type);
chandler->AddCacheBlock(block);
if (block->page.end>=4096) {
DYN_LOG("block crosses page boundary");
}
}
run_block:
BlockReturn ret=gen_runcode(block->cache.start);
switch (ret) {
case BR_Normal:
/* Maybe check if we staying in the same page? */
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
goto restart_core;
case BR_Cycles:
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
return CBRET_NONE;
case BR_CallBack:
return core_dyn.callback;
case BR_Opcode:
CPU_CycleLeft+=CPU_Cycles;
CPU_Cycles=1;
return CPU_Core_Normal_Run();
case BR_Link1:
case BR_Link2:
{
Bitu temp_ip=SegPhys(cs)+reg_eip;
Bitu temp_page=temp_ip >> 12;
CodePageHandler * temp_handler=(CodePageHandler *)paging.tlb.handler[temp_page];
if (temp_handler->flags & PFLAG_HASCODE) {
block=temp_handler->FindCacheBlock(temp_ip & 4095);
if (!block) goto restart_core;
cache_linkblocks(cache.block.running,block,ret==BR_Link2);
goto run_block;
}
}
goto restart_core;
}
} else {
if (handler->flags & PFLAG_NOCODE) {
LOG_MSG("DYNX86:Can't run code in this page");
return CPU_Core_Normal_Run();
}
Bitu phys_page=ip_page;
if (!PAGING_MakePhysPage(phys_page)) {
LOG_MSG("DYNX86:Can't find physpage");
return CPU_Core_Normal_Run();
}
chandler=new CodePageHandler(handler);
MEM_SetPageHandler(phys_page,1,chandler); //Setup the handler
PAGING_UnlinkPages(ip_page,1);
goto findblock;
CodePageHandler * chandler=MakeCodePage(ip_page);
if (!chandler) return CPU_Core_Normal_Run();
/* Find correct Dynamic Block to run */
CacheBlock * block=chandler->FindCacheBlock(ip_point&4095);
if (!block) {
block=CreateCacheBlock(chandler,ip_point,32);
}
return 0;
run_block:
cache.block.running=0;
BlockReturn ret=gen_runcode(block->cache.start);
switch (ret) {
case BR_Normal:
/* Maybe check if we staying in the same page? */
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
goto restart_core;
case BR_Cycles:
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
return CBRET_NONE;
case BR_CallBack:
return core_dyn.callback;
case BR_Opcode:
CPU_CycleLeft+=CPU_Cycles;
CPU_Cycles=1;
return CPU_Core_Normal_Run();
#if (C_DEBUG)
case BR_OpcodeFull:
CPU_CycleLeft+=CPU_Cycles;
CPU_Cycles=1;
return CPU_Core_Full_Run();
#endif
case BR_Link1:
case BR_Link2:
{
Bitu temp_ip=SegPhys(cs)+reg_eip;
Bitu temp_page=temp_ip >> 12;
CodePageHandler * temp_handler=(CodePageHandler *)paging.tlb.handler[temp_page];
if (temp_handler->flags & PFLAG_HASCODE) {
block=temp_handler->FindCacheBlock(temp_ip & 4095);
if (!block) goto restart_core;
cache.block.running->LinkTo(ret==BR_Link2,block);
goto run_block;
}
}
goto restart_core;
}
return 0;
}
void CPU_Core_Dyn_X86_Init(void) {
Bits i;
/* Setup the global registers and their flags */

View File

@ -1,28 +1,34 @@
struct CacheBlock {
class CacheBlock {
public:
void Clear(void);
void LinkTo(Bitu index,CacheBlock * toblock) {
assert(toblock);
link[index].to=toblock;
link[index].next=toblock->link[index].from;
toblock->link[index].from=this;
}
struct {
Bit16s start,end; //Where the page is the original code
Bitu first,last;
Bit16u start,end; //Where the page is the original code
CodePageHandler * handler; //Page containing this code
} page;
struct {
Bit8u * start; //Where in the cache are we
Bitu size;
CacheBlock * next;
} cache;
BlockType type;
CodePageHandler * code_page; //Page containing this code
CacheBlock * page_link; //For code crossing a page boundary
struct {
Bitu index;
CacheBlock * next;
} hash;
CacheBlock * list_next;
struct {
CacheBlock * to[2];
CacheBlock * from[DYN_LINKS];
Bitu index;
} link;
CacheBlock * links[2];
CacheBlock * to;
CacheBlock * next;
CacheBlock * from;
} link[2];
CacheBlock * crossblock;
};
class CacheBlock;
static struct {
struct {
CacheBlock * first;
@ -31,96 +37,124 @@ static struct {
CacheBlock * running;
} block;
Bit8u * pos;
CacheBlock linkblocks[2];
CodePageHandler * free_pages;
CodePageHandler * used_pages;
CodePageHandler * last_page;
} cache;
static Bit8u cache_code_link_blocks[2][16];
static Bit8u cache_code[CACHE_TOTAL+CACHE_MAXSIZE];
static CacheBlock cache_blocks[CACHE_BLOCKS];
static void cache_resetblock(CacheBlock * block);
static CacheBlock link_blocks[2];
class CodePageHandler :public PageHandler {
public:
CodePageHandler(PageHandler * _old_pagehandler) {
CodePageHandler() {}
void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
phys_page=_phys_page;
old_pagehandler=_old_pagehandler;
flags=old_pagehandler->flags|PFLAG_HASCODE;
flags&=~PFLAG_WRITEABLE;
active_blocks=0;
active_count=16;
memset(&hash_map,0,sizeof(hash_map));
memset(&write_map,0,sizeof(write_map));
}
void InvalidateRange(Bits start,Bits end) {
Bits maps=start>>DYN_HASH_SHIFT;
Bits map=maps;
Bits count=write_map[maps];
while (map>=0 && count>0) {
CacheBlock * block=hash_map[map];
CacheBlock * * where=&hash_map[map];
void InvalidateRange(Bitu start,Bitu end) {
Bits index=1+(start>>DYN_HASH_SHIFT);
while (index>=0) {
Bitu map=0;
for (Bitu count=start;count<=end;count++) map+=write_map[count];
if (!map) return;
CacheBlock * block=hash_map[index];
while (block) {
CacheBlock * nextblock=block->hash.next;
if (start<=block->page.end && end>=block->page.start) {
for (Bitu i=block->page.first;i<=block->page.last;i++) write_map[i]--;
block->code_page=0; //Else resetblock will do double work
count--;
if (block==cache.block.running) LOG_MSG("Writing to current block");
cache_resetblock(block);
*where=nextblock;
} else {
where=&block->hash.next;
}
if (start<=block->page.end && end>=block->page.start)
block->Clear();
block=nextblock;
}
map--;
index--;
}
}
void writeb(PhysPt addr,Bitu val){
if (val!=host_readb(hostmem+(addr&4095))) {
InvalidateRange(addr&4095,addr&4095);
host_writeb(hostmem+(addr&4095),val);
}
addr&=4095;
host_writeb(hostmem+addr,val);
if (!*(Bit8u*)&write_map[addr]) {
if (active_blocks) return;
active_count--;
if (!active_count) Release();
} else InvalidateRange(addr,addr);
}
void writew(PhysPt addr,Bitu val){
if (val!=host_readw(hostmem+(addr&4095))) {
InvalidateRange(addr&4095,(addr&4095)+1);
host_writew(hostmem+(addr&4095),val);
}
addr&=4095;
host_writew(hostmem+addr,val);
if (!*(Bit16u*)&write_map[addr]) {
if (active_blocks) return;
active_count--;
if (!active_count) Release();
} else InvalidateRange(addr,addr+1);
}
void writed(PhysPt addr,Bitu val){
if (val!=host_readd(hostmem+(addr&4095))) {
InvalidateRange(addr&4095,(addr&4095)+3);
host_writed(hostmem+(addr&4095),val);
}
addr&=4095;
host_writed(hostmem+addr,val);
if (!*(Bit32u*)&write_map[addr]) {
if (active_blocks) return;
active_count--;
if (!active_count) Release();
} else InvalidateRange(addr,addr+3);
}
void AddCacheBlock(CacheBlock * block) {
Bit16u first,last;
if (block->page.start<0) first=0;
else first=block->page.start>>DYN_HASH_SHIFT;
block->hash.next=hash_map[first];
hash_map[first]=block;
if (block->page.end>=4096) last=DYN_PAGE_HASH-1;
else last=block->page.end>>DYN_HASH_SHIFT;
block->page.first=first;
block->page.last=last;
for (;first<=last;first++) {
write_map[first]++;
}
block->code_page=this;
Bitu index=1+(block->page.start>>DYN_HASH_SHIFT);
block->hash.next=hash_map[index];
block->hash.index=index;
hash_map[index]=block;
block->page.handler=this;
active_blocks++;
}
void AddCrossBlock(CacheBlock * block) {
block->hash.next=hash_map[0];
block->hash.index=0;
hash_map[0]=block;
block->page.handler=this;
active_blocks++;
}
void DelCacheBlock(CacheBlock * block) {
CacheBlock * * where=&hash_map[block->page.first];
while (*where) {
if (*where==block) {
*where=block->hash.next;
break;
}
active_blocks--;
active_count=16;
CacheBlock * * where=&hash_map[block->hash.index];
while (*where!=block) {
where=&((*where)->hash.next);
//Will crash if a block isn't found, which should never happen.
}
for (Bitu i=block->page.first;i<=block->page.last;i++) {
write_map[i]--;
*where=block->hash.next;
for (Bitu i=block->page.start;i<=block->page.end;i++) {
if (write_map[i]) write_map[i]--;
}
}
void Release(void) {
MEM_SetPageHandler(phys_page,1,old_pagehandler);
PAGING_ClearTLB();
if (prev) prev->next=next;
else cache.used_pages=next;
if (next) next->prev=prev;
else cache.last_page=prev;
next=cache.free_pages;
cache.free_pages=this;
prev=0;
}
void ClearRelease(void) {
for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) {
CacheBlock * block=hash_map[index];
while (block) {
CacheBlock * nextblock=block->hash.next;
block->page.handler=0; //No need, full clear
block->Clear();
block=nextblock;
}
}
Release();
}
CacheBlock * FindCacheBlock(Bitu start) {
CacheBlock * block=hash_map[start>>DYN_HASH_SHIFT];
CacheBlock * block=hash_map[1+(start>>DYN_HASH_SHIFT)];
while (block) {
if (block->page.start==start) return block;
block=block->hash.next;
@ -131,133 +165,153 @@ public:
hostmem=old_pagehandler->GetHostPt(phys_page);
return hostmem;
}
public:
Bit8u write_map[4096];
CodePageHandler * next, * prev;
private:
PageHandler * old_pagehandler;
CacheBlock * hash_map[DYN_PAGE_HASH];
Bit8u write_map[DYN_PAGE_HASH];
CacheBlock * hash_map[1+DYN_PAGE_HASH];
Bitu active_blocks;
Bitu active_count;
HostPt hostmem;
Bitu phys_page;
};
static CodePageHandler * MakeCodePage(Bitu lin_page) {
mem_readb(lin_page << 12); //Ensure page contains memory
PageHandler * handler=paging.tlb.handler[lin_page];
if (handler->flags & PFLAG_HASCODE) return ( CodePageHandler *)handler;
if (handler->flags & PFLAG_NOCODE) {
LOG_MSG("DYNX86:Can't run code in this page");
return 0;
}
Bitu phys_page=lin_page;
if (!PAGING_MakePhysPage(phys_page)) {
LOG_MSG("DYNX86:Can't find physpage");
return 0;
}
/* Find a free CodePage */
if (!cache.free_pages) {
cache.used_pages->ClearRelease();
}
CodePageHandler * cpagehandler=cache.free_pages;
cache.free_pages=cache.free_pages->next;
cpagehandler->prev=cache.last_page;
cpagehandler->next=0;
if (cache.last_page) cache.last_page->next=cpagehandler;
cache.last_page=cpagehandler;
if (!cache.used_pages) cache.used_pages=cpagehandler;
cpagehandler->SetupAt(phys_page,handler);
MEM_SetPageHandler(phys_page,1,cpagehandler);
PAGING_UnlinkPages(lin_page,1);
return cpagehandler;
}
static INLINE void cache_addunsedblock(CacheBlock * block) {
block->list_next=cache.block.free;
block->cache.next=cache.block.free;
cache.block.free=block;
}
static CacheBlock * cache_getblock(void) {
CacheBlock * ret=cache.block.free;
if (!ret) E_Exit("Ran out of CacheBlocks" );
cache.block.free=ret->list_next;
cache.block.free=ret->cache.next;
ret->cache.next=0;
return ret;
}
static INLINE void cache_clearlinkfrom(CacheBlock * block,CacheBlock * from) {
for (Bitu i=0;i<DYN_LINKS;i++) {
if (block->link.from[i]==from) block->link.from[i]=0;
void CacheBlock::Clear(void) {
Bitu ind;
/* Check if this is not a cross page block */
if (hash.index) for (ind=0;ind<2;ind++) {
CacheBlock * fromlink=link[ind].from;
link[ind].from=0;
while (fromlink) {
CacheBlock * nextlink=fromlink->link[ind].next;
fromlink->link[ind].next=0;
fromlink->link[ind].to=&link_blocks[ind];
fromlink=nextlink;
}
if (link[ind].to!=&link_blocks[ind]) {
CacheBlock * * wherelink=&link[ind].to->link[ind].from;
while (*wherelink!=this) {
wherelink=&(*wherelink)->link[ind].next;
}
*wherelink=(*wherelink)->link[ind].next;
}
} else
cache_addunsedblock(this);
if (crossblock) {
crossblock->crossblock=0;
crossblock->Clear();
crossblock=0;
}
if (page.handler) {
page.handler->DelCacheBlock(this);
page.handler=0;
}
}
static INLINE void cache_clearlinkto(CacheBlock * block,CacheBlock * to) {
if (block->link.to[0]==to) block->link.to[0]=&cache.linkblocks[0];
if (block->link.to[1]==to) block->link.to[1]=&cache.linkblocks[1];
}
static void cache_linkblocks(CacheBlock * from,CacheBlock * to,Bitu link) {
from->link.to[link]=to;
CacheBlock * clear=to->link.from[to->link.index];
if (clear) {
DYN_LOG("backlink buffer full");
cache_clearlinkto(to->link.from[to->link.index],to);
}
to->link.from[to->link.index]=from;
to->link.index++;
if (to->link.index>=DYN_LINKS) to->link.index=0;
}
static void cache_resetblock(CacheBlock * block) {
Bits i;
DYN_LOG("Resetted block");
block->type=BT_Free;
/* Clear all links to this block from other blocks */
for (i=0;i<DYN_LINKS;i++) {
if (block->link.from[i]) cache_clearlinkto(block->link.from[i],block);
block->link.from[i]=0;
}
/* Clear all links from this block to other blocks */
if (block->link.to[0]!=&cache.linkblocks[0]) {
cache_clearlinkfrom(block->link.to[0],block);
block->link.to[0]=&cache.linkblocks[0];
}
if (block->link.to[1]!=&cache.linkblocks[1]) {
cache_clearlinkfrom(block->link.to[1],block);
block->link.to[1]=&cache.linkblocks[1];
}
block->link.index=0;
if (block->code_page) block->code_page->DelCacheBlock(block);
}
static CacheBlock * cache_openblock(void) {
CacheBlock * block=cache.block.active;
/* check for enough space in this block */
Bitu size=block->cache.size;
CacheBlock * nextblock=block->list_next;
CacheBlock * nextblock=block->cache.next;
if (block->page.handler)
block->Clear();
while (size<CACHE_MAXSIZE) {
if (!nextblock) goto skipresize;
if (!nextblock)
goto skipresize;
size+=nextblock->cache.size;
CacheBlock * tempblock=nextblock->list_next;
if (nextblock->type!=BT_Free) cache_resetblock(nextblock);
CacheBlock * tempblock=nextblock->cache.next;
if (nextblock->page.handler)
nextblock->Clear();
cache_addunsedblock(nextblock);
nextblock=tempblock;
}
skipresize:
block->cache.size=size;
block->list_next=nextblock;
block->cache.next=nextblock;
cache.pos=block->cache.start;
return block;
}
static void cache_closeblock(BlockType type) {
static void cache_closeblock(void) {
CacheBlock * block=cache.block.active;
/* Setup some structures in the block determined by type */
block->type=type;
switch (type) {
case BT_Normal:
break;
case BT_SingleLink:
block->link.to[0]=&cache.linkblocks[0];
break;
case BT_DualLink:
block->link.to[0]=&cache.linkblocks[0];
block->link.to[1]=&cache.linkblocks[1];
break;
}
block->link[0].to=&link_blocks[0];
block->link[1].to=&link_blocks[1];
block->link[0].from=0;
block->link[1].from=0;
block->link[0].next=0;
block->link[1].next=0;
/* Close the block with correct alignments */
Bitu written=cache.pos-block->cache.start;
if (written>block->cache.size) {
if (!block->list_next) {
if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun");
} else E_Exit("CacheBlock overrun");
if (!block->cache.next) {
if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size);
} else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size);
} else {
Bitu new_size;
Bitu left=block->cache.size-written;
/* Smaller than cache align then don't bother to resize */
if (left>CACHE_ALIGN) {
new_size=((written-1)|(CACHE_ALIGN-1))+1;
} else new_size=block->cache.size;
CacheBlock * newblock=cache_getblock();
newblock->cache.start=block->cache.start+new_size;
newblock->cache.size=block->cache.size-new_size;
newblock->list_next=block->list_next;
newblock->type=BT_Free;
block->cache.size=new_size;
block->list_next=newblock;
CacheBlock * newblock=cache_getblock();
newblock->cache.start=block->cache.start+new_size;
newblock->cache.size=block->cache.size-new_size;
newblock->cache.next=block->cache.next;
block->cache.next=newblock;
block->cache.size=new_size;
}
}
/* Advance the active block pointer */
if (!block->list_next) {
DYN_LOG("Cache full restarting");
if (!block->cache.next) {
// LOG_MSG("Cache full restarting");
cache.block.active=cache.block.first;
} else {
cache.block.active=block->list_next;
cache.block.active=block->cache.next;
}
}
@ -283,20 +337,29 @@ static void cache_init(void) {
memset(&cache_blocks,0,sizeof(cache_blocks));
cache.block.free=&cache_blocks[0];
for (i=0;i<CACHE_BLOCKS-1;i++) {
cache_blocks[i].list_next=&cache_blocks[i+1];
cache_blocks[i].link.to[0]=&cache.linkblocks[0];
cache_blocks[i].link.to[1]=&cache.linkblocks[1];
cache_blocks[i].link[0].to=(CacheBlock *)1;
cache_blocks[i].link[1].to=(CacheBlock *)1;
cache_blocks[i].cache.next=&cache_blocks[i+1];
}
CacheBlock * block=cache_getblock();
cache.block.first=block;
cache.block.active=block;
block->cache.start=&cache_code[0];
block->cache.size=CACHE_TOTAL;
block->list_next=0; //Last block in the list
block->cache.next=0; //Last block in the list
cache.pos=&cache_code_link_blocks[0][0];
cache.linkblocks[0].cache.start=cache.pos;
link_blocks[0].cache.start=cache.pos;
gen_return(BR_Link1);
cache.pos=&cache_code_link_blocks[1][0];
cache.linkblocks[1].cache.start=cache.pos;
link_blocks[1].cache.start=cache.pos;
gen_return(BR_Link2);
}
cache.free_pages=0;
cache.last_page=0;
cache.used_pages=0;
/* Setup the code pages */
for (i=0;i<CACHE_PAGES-1;i++) {
CodePageHandler * newpage=new CodePageHandler();
newpage->next=cache.free_pages;
cache.free_pages=newpage;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,57 +1,57 @@
static Bitu dyn_helper_divb(Bit8u val) {
if (!val) return 1;
static bool dyn_helper_divb(Bit8u val) {
if (!val) return CPU_PrepareException(0,0);
Bitu quo=reg_ax / val;
reg_ah=(Bit8u)(reg_ax % val);
reg_al=(Bit8u)quo;
if (quo>0xff) return 1;
return 0;
if (quo>0xff) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_idivb(Bit8s val) {
if (!val) return 1;
static bool dyn_helper_idivb(Bit8s val) {
if (!val) return CPU_PrepareException(0,0);
Bits quo=(Bit16s)reg_ax / val;
reg_ah=(Bit8s)((Bit16s)reg_ax % val);
reg_al=(Bit8s)quo;
if (quo!=(Bit8s)reg_al) return 1;
return 0;
if (quo!=(Bit8s)reg_al) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_divw(Bit16u val) {
if (!val) return 1;
static bool dyn_helper_divw(Bit16u val) {
if (!val) return CPU_PrepareException(0,0);
Bitu num=(reg_dx<<16)|reg_ax;
Bitu quo=num/val;
reg_dx=(Bit16u)(num % val);
reg_ax=(Bit16u)quo;
if (quo!=reg_ax) return 1;
return 0;
if (quo!=reg_ax) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_idivw(Bit16s val) {
if (!val) return 1;
static bool dyn_helper_idivw(Bit16s val) {
if (!val) return CPU_PrepareException(0,0);
Bits num=(reg_dx<<16)|reg_ax;
Bits quo=num/val;
reg_dx=(Bit16s)(num % val);
reg_ax=(Bit16s)quo;
if (quo!=(Bit16s)reg_ax) return 1;
return 0;
if (quo!=(Bit16s)reg_ax) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_divd(Bit32u val) {
if (!val) return 1;
static bool dyn_helper_divd(Bit32u val) {
if (!val) return CPU_PrepareException(0,0);
Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax;
Bit64u quo=num/val;
reg_edx=(Bit32u)(num % val);
reg_eax=(Bit32u)quo;
if (quo!=(Bit64u)reg_eax) return 1;
return 0;
if (quo!=(Bit64u)reg_eax) return CPU_PrepareException(0,0);
return false;
}
static Bitu dyn_helper_idivd(Bit32s val) {
if (!val) return 1;
static bool dyn_helper_idivd(Bit32s val) {
if (!val) return CPU_PrepareException(0,0);
Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax;
Bit64s quo=num/val;
reg_edx=(Bit32s)(num % val);
reg_eax=(Bit32s)(quo);
if (quo!=(Bit64s)((Bit32s)reg_eax)) return 1;
return 0;
if (quo!=(Bit64s)((Bit32s)reg_eax)) return CPU_PrepareException(0,0);
return false;
}

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -32,8 +32,8 @@ static void gen_init(void);
#define X86_REG_MASK(_REG_) (1 << X86_REG_ ## _REG_)
static struct {
bool flagsactive;
Bitu last_used;
Bitu stored_flags;
GenReg * regs[X86_REGS];
} x86gen;
@ -98,13 +98,13 @@ static BlockReturn gen_runcode(Bit8u * code) {
push edi
mov ebx,[reg_flags]
and ebx,FMASK_TEST
push offset(return_address)
push ebx
popfd
call eax
jmp eax
/* Restore the flags */
pushfd
return_address:
/* return here with flags in ecx */
and dword ptr [reg_flags],~FMASK_TEST
pop ecx
and ecx,FMASK_TEST
or [reg_flags],ecx
pop edi
@ -114,23 +114,19 @@ static BlockReturn gen_runcode(Bit8u * code) {
mov [retval],eax
}
#else
register Bit32u tempflags=reg_flags & FMASK_TEST;
__asm__ volatile (
"movl %1,%%esi \n"
"andl %2,%%esi \n"
"pushl %%ebp \n"
"pushl %%esi \n"
"popfl \n"
"calll *%4 \n"
"popl %%ebp \n"
"pushfl \n"
"andl %3,(%1) \n"
"popl %%esi \n"
"andl %2,%%esi \n"
"orl %%esi,(%1) \n"
:"=a" (retval)
:"m" (reg_flags), "n" (FMASK_TEST),"n" (~FMASK_TEST),"r" (code)
:"%ecx","%edx","%ebx","%edi","%esi","cc","memory"
"pushl %%ebp \n"
"pushl $(run_return_adress) \n"
"pushl %2 \n"
"jmp *%3 \n"
"run_return_adress: \n"
"popl %%ebp \n"
:"=a" (retval), "=c" (tempflags)
:"r" (tempflags),"r" (code)
:"%edx","%ebx","%edi","%esi","cc","memory"
);
reg_flags=(reg_flags & ~FMASK_TEST) | (tempflags & FMASK_TEST);
#endif
return retval;
}
@ -232,28 +228,23 @@ static void gen_synchreg(DynReg * dnew,DynReg * dsynch) {
}
}
static void gen_storeflags(void) {
if (!x86gen.stored_flags) {
cache_addb(0x9c); //PUSHFD
static void gen_needflags(void) {
if (!x86gen.flagsactive) {
x86gen.flagsactive=true;
cache_addb(0x9d); //POPFD
}
x86gen.stored_flags++;
}
static void gen_restoreflags(bool noreduce=false) {
if (noreduce) {
cache_addb(0x9d);
return;
static void gen_protectflags(void) {
if (x86gen.flagsactive) {
x86gen.flagsactive=false;
cache_addb(0x9c); //PUSHFD
}
if (x86gen.stored_flags) {
x86gen.stored_flags--;
if (!x86gen.stored_flags)
cache_addb(0x9d); //POPFD
} else IllegalOption();
}
static void gen_reinit(void) {
x86gen.last_used=0;
x86gen.stored_flags=0;
x86gen.flagsactive=false;
for (Bitu i=0;i<X86_REGS;i++) {
x86gen.regs[i]->dynreg=0;
}
@ -483,55 +474,32 @@ static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) {
dr1->flags|=DYNFLG_CHANGED;
}
static void gen_shift_byte(ShiftOps op,DynReg * drecx,DynReg * dr1,Bit8u di1) {
static void gen_shift_byte_cl(Bitu op,DynReg * dr1,Bit8u di1,DynReg * drecx) {
ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
GenReg * gr1=FindDynReg(dr1);
switch (op) {
case SHIFT_ROL:cache_addw(0xc0d2+((gr1->index+di1)<<8));break;
case SHIFT_ROR:cache_addw(0xc8d2+((gr1->index+di1)<<8));break;
case SHIFT_RCL:cache_addw(0xd0d2+((gr1->index+di1)<<8));break;
case SHIFT_RCR:cache_addw(0xd8d2+((gr1->index+di1)<<8));break;
case SHIFT_SHL:cache_addw(0xe0d2+((gr1->index+di1)<<8));break;
case SHIFT_SHR:cache_addw(0xe8d2+((gr1->index+di1)<<8));break;
case SHIFT_SAR:cache_addw(0xf8d2+((gr1->index+di1)<<8));break;
default:
IllegalOption();
}
cache_addw(0xc0d2+(((Bit16u)op) << 11)+ ((gr1->index+di1)<<8));
dr1->flags|=DYNFLG_CHANGED;
}
static void gen_shift_word(ShiftOps op,DynReg * drecx,bool dword,DynReg * dr1) {
ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) {
GenReg * gr1=FindDynReg(dr1);
if (!dword) cache_addb(0x66);
switch (op) {
case SHIFT_ROL:cache_addw(0xc0d3+((gr1->index)<<8));break;
case SHIFT_ROR:cache_addw(0xc8d3+((gr1->index)<<8));break;
case SHIFT_RCL:cache_addw(0xd0d3+((gr1->index)<<8));break;
case SHIFT_RCR:cache_addw(0xd8d3+((gr1->index)<<8));break;
case SHIFT_SHL:cache_addw(0xe0d3+((gr1->index)<<8));break;
case SHIFT_SHR:cache_addw(0xe8d3+((gr1->index)<<8));break;
case SHIFT_SAR:cache_addw(0xf8d3+((gr1->index)<<8));break;
default:
IllegalOption();
}
cache_addw(0xc0c0+(((Bit16u)op) << 11) + ((gr1->index+di1)<<8));
cache_addb(imm);
dr1->flags|=DYNFLG_CHANGED;
}
static void gen_shift_word_imm(ShiftOps op,bool dword,DynReg * dr1,Bit8u imm) {
static void gen_shift_word_cl(Bitu op,bool dword,DynReg * dr1,DynReg * drecx) {
ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
GenReg * gr1=FindDynReg(dr1);
if (!dword) cache_addb(0x66);
switch (op) {
case SHIFT_ROL:cache_addw(0xc0c1+((gr1->index)<<8));break;
case SHIFT_ROR:cache_addw(0xc8c1+((gr1->index)<<8));break;
case SHIFT_RCL:cache_addw(0xd0c1+((gr1->index)<<8));break;
case SHIFT_RCR:cache_addw(0xd8c1+((gr1->index)<<8));break;
case SHIFT_SHL:cache_addw(0xe0c1+((gr1->index)<<8));break;
case SHIFT_SHR:cache_addw(0xe8c1+((gr1->index)<<8));break;
case SHIFT_SAR:cache_addw(0xf8c1+((gr1->index)<<8));break;
default:
IllegalOption();
}
cache_addw(0xc0d3+(((Bit16u)op) << 11) + ((gr1->index)<<8));
dr1->flags|=DYNFLG_CHANGED;
}
static void gen_shift_word_imm(Bitu op,bool dword,DynReg * dr1,Bit8u imm) {
GenReg * gr1=FindDynReg(dr1);
if (!dword) cache_addb(0x66);
cache_addw(0xc0c1+(((Bit16u)op) << 11) + ((gr1->index)<<8));
cache_addb(imm);
dr1->flags|=DYNFLG_CHANGED;
}
@ -604,7 +572,7 @@ static void gen_call_function(void * func,char * ops,...) {
x86gen.regs[X86_REG_EAX]->Clear();
x86gen.regs[X86_REG_EAX]->notusable=true;;
/* Save the flags */
gen_storeflags();
gen_protectflags();
/* Scan for the amount of params */
if (ops) {
va_list params;
@ -704,7 +672,6 @@ static void gen_call_function(void * func,char * ops,...) {
}
dynreg->flags|=DYNFLG_CHANGED;
}
gen_restoreflags();
/* Restore EAX registers to be used again */
x86gen.regs[X86_REG_EAX]->notusable=false;
}
@ -717,6 +684,11 @@ static Bit8u * gen_create_branch(BranchTypes type) {
}
static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) {
#if C_DEBUG
Bits len=from-data;
if (len<0) len=-len;
if (len>126) LOG_MSG("BIg jump %d",len);
#endif
*data=(from-data-1);
}
@ -747,17 +719,20 @@ static void gen_jmp_ptr(void * ptr,Bits imm=0) {
}
}
static void gen_save_flags(DynReg * dynreg,bool stored) {
static void gen_save_flags(DynReg * dynreg) {
if (x86gen.flagsactive) IllegalOption();
GenReg * genreg=FindDynReg(dynreg);
if (!stored) cache_addb(0x9c); //Pushfd
cache_addb(0x58+genreg->index); //POP 32 REG
cache_addb(0x8b); //MOV REG,[esp]
cache_addw(0x2404+(genreg->index << 3));
dynreg->flags|=DYNFLG_CHANGED;
}
static void gen_load_flags(DynReg * dynreg) {
if (x86gen.flagsactive) IllegalOption();
cache_addw(0xc483); //ADD ESP,4
cache_addb(0x4);
GenReg * genreg=FindDynReg(dynreg);
cache_addb(0x50+genreg->index); //PUSH 32
cache_addb(0x9d); //POPFD
}
static void gen_save_host_direct(void * data,Bits imm) {
@ -781,9 +756,11 @@ static void gen_load_host(void * data,DynReg * dr1,Bitu size) {
}
static void gen_return(BlockReturn retcode) {
cache_addb(0xb8);
gen_protectflags();
cache_addb(0x59); //POP ECX, the flags
cache_addb(0xb8); //MOV EAX, retcode
cache_addd(retcode);
cache_addb(0xc3);
cache_addb(0xc3); //RET
}
static void gen_init(void) {

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -30,7 +30,7 @@ static void dyn_string(STRING_OP op) {
DynReg * si_base=decode.segprefix ? decode.segprefix : DREG(DS);
DynReg * di_base=DREG(ES);
DynReg * tmp_reg;bool usesi;bool usedi;
gen_storeflags();
gen_protectflags();
if (decode.rep) {
gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);
gen_releasereg(DREG(CYCLES));
@ -149,9 +149,8 @@ static void dyn_string(STRING_OP op) {
gen_releasereg(DREG(CYCLES));
dyn_savestate(&cycle_state);
Bit8u * cycle_branch=gen_create_branch(BR_NLE);
gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start);
dyn_releaseregs();
gen_restoreflags(true);
gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start);
dyn_save_critical_regs();
gen_return(BR_Cycles);
gen_fill_branch(cycle_branch);
dyn_loadstate(&cycle_state);
@ -161,5 +160,4 @@ static void dyn_string(STRING_OP op) {
gen_fill_jump(rep_ecx_jmp);
}
gen_releasereg(DREG(TMPW));
gen_restoreflags();
}

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -54,47 +54,28 @@ typedef PhysPt EAPoint;
#include "core_full/optable.h"
#include "instructions.h"
#define LEAVECORE \
SaveIP(); \
FillFlags();
#define EXCEPTION(blah) \
{ \
Bit8u new_num=blah; \
IPPoint=inst.opcode_start; \
LEAVECORE; \
CPU_Exception(new_num,0); \
LoadIP(); \
goto nextopcode; \
continue; \
}
Bits CPU_Core_Full_Run(void) {
FullData inst;
restart_core:
if (!cpu.code.big) {
inst.start_prefix=0x0;;
inst.start_entry=0x0;
} else {
inst.start_prefix=PREFIX_ADDR;
inst.start_entry=0x200;
}
EAPoint IPPoint;
LoadIP();
lflags.type=t_UNKNOWN;
while (CPU_Cycles-->0) {
#if C_DEBUG
cycle_count++;
#if C_HEAVY_DEBUG
SaveIP();
if (DEBUG_HeavyIsBreakpoint()) {
LEAVECORE;
FillFlags();
return debugCallback;
};
#endif
#endif
inst.opcode_start=IPPoint;
inst.entry=inst.start_entry;
inst.prefix=inst.start_prefix;
LoadIP();
inst.entry=cpu.code.big*0x200;
inst.prefix=cpu.code.big;
restartopcode:
inst.entry=(inst.entry & 0xffffff00) | Fetchb();
inst.code=OpCodeTable[inst.entry];
@ -102,9 +83,13 @@ restartopcode:
#include "core_full/op.h"
#include "core_full/save.h"
nextopcode:;
SaveIP();
continue;
illegalopcode:
LOG_MSG("Illegal opcode");
CPU_Exception(0x6,0);
}
exit_core:
LEAVECORE;
FillFlags();
return CBRET_NONE;
}

View File

@ -144,18 +144,12 @@ l_M_Ed:
inst.op1.d=SegValue((SegNames)inst.rm_index);
break;
case M_Efw:
if (inst.rm>=0xC0) {
LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw ");
goto nextopcode;
}
if (inst.rm>=0xc0) goto illegalopcode;
inst.op1.d=LoadMw(inst.rm_eaa);
inst.op2.d=LoadMw(inst.rm_eaa+2);
break;
case M_Efd:
if (inst.rm>=0xc0) {
LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw ");
goto nextopcode;
}
if (inst.rm>=0xc0) goto illegalopcode;
inst.op1.d=LoadMd(inst.rm_eaa);
inst.op2.d=LoadMw(inst.rm_eaa+4);
break;
@ -183,8 +177,6 @@ l_M_Ed:
inst.op2.d=1;
inst.code=Groups[inst.code.op][inst.rm_index];
goto l_MODRMswitch;
/* Should continue with normal handler afterwards */
case 0:
break;
default:
@ -246,9 +238,6 @@ l_M_Ed:
case L_REGd:
inst.op1.d=reg_32(inst.code.extra);
break;
case L_FLG:
inst.op1.d = FillFlags();
break;
case L_SEG:
inst.op1.d=SegValue((SegNames)inst.code.extra);
break;
@ -282,10 +271,10 @@ l_M_Ed:
inst.repz=true;
goto restartopcode;
case L_PREOP:
inst.entry=inst.start_entry ^ 0x200;
inst.entry=(cpu.code.big ^1) * 0x200;
goto restartopcode;
case L_PREADD:
inst.prefix^=PREFIX_ADDR;
inst.prefix=(inst.prefix & ~1) | (cpu.code.big ^ 1);
goto restartopcode;
case L_VAL:
inst.op1.d=inst.code.extra;
@ -295,41 +284,40 @@ l_M_Ed:
inst.op1.d=4;
break;
case D_IRETw:
LEAVECORE;
CPU_IRET(false);
FillFlags();
CPU_IRET(false,GetIP());
if (GETFLAG(IF) && PIC_IRQCheck) {
return CBRET_NONE;
}
goto restart_core;
continue;
case D_IRETd:
LEAVECORE;
CPU_IRET(true);
if (GETFLAG(IF) && PIC_IRQCheck) {
FillFlags();
CPU_IRET(true,GetIP());
if (GETFLAG(IF) && PIC_IRQCheck)
return CBRET_NONE;
}
goto restart_core;
continue;
case D_RETFwIw:
{
Bitu words=Fetchw();
LEAVECORE;
CPU_RET(false,words);
goto restart_core;
FillFlags();
CPU_RET(false,words,GetIP());
continue;
}
case D_RETFw:
LEAVECORE;
CPU_RET(false,0);
goto restart_core;
FillFlags();
CPU_RET(false,0,GetIP());
continue;
case D_RETFdIw:
{
Bitu words=Fetchw();
LEAVECORE;
CPU_RET(true,words);
goto restart_core;
FillFlags();
CPU_RET(true,words,GetIP());
continue;
}
case D_RETFd:
LEAVECORE;
CPU_RET(true,0);
goto restart_core;
FillFlags();
CPU_RET(true,0,GetIP());
continue;
/* Direct operations */
case L_STRING:
#include "string.h"
@ -357,18 +345,10 @@ l_M_Ed:
reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
goto nextopcode;
case D_POPSEGw:
if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_16())) {
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=2;
CPU_StartException();goto restart_core;
}
if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException();
goto nextopcode;
case D_POPSEGd:
if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_32())) {
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=4;
CPU_StartException();goto restart_core;
}
if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException();
goto nextopcode;
case D_SETALC:
reg_al = get_CF() ? 0xFF : 0;
@ -403,14 +383,10 @@ l_M_Ed:
else reg_edx=0;
goto nextopcode;
case D_CLI:
SETFLAGBIT(IF,false);
if (CPU_CLI()) RunException();
goto nextopcode;
case D_STI:
SETFLAGBIT(IF,true);
if (GETFLAG(IF) && PIC_IRQCheck) {
LEAVECORE;
return CBRET_NONE;
}
if (CPU_STI()) RunException();
goto nextopcode;
case D_STC:
FillFlags();SETFLAGBIT(CF,true);
@ -430,71 +406,40 @@ l_M_Ed:
SETFLAGBIT(DF,true);
cpu.direction=-1;
goto nextopcode;
case D_PUSHF:
FillFlags();
if (CPU_PUSHF(inst.code.extra)) RunException();
goto nextopcode;
case D_POPF:
if (CPU_POPF(inst.code.extra)) RunException();
lflags.type=t_UNKNOWN;
if (GETFLAG(IF) && PIC_IRQCheck) {
SaveIP();
return CBRET_NONE;
}
goto nextopcode;
case D_SAHF:
SETFLAGSb(reg_ah);
goto nextopcode;
case D_LAHF:
FillFlags();
reg_ah=reg_flags&0xff;
goto nextopcode;
case D_WAIT:
case D_NOP:
goto nextopcode;
case D_ENTERw:
{
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
Bitu frame_ptr=reg_esp-2;
if (cpu.stack.big) {
reg_esp-=2;
mem_writew(SegBase(ss)+reg_esp,reg_bp);
for (Bitu i=1;i<level;i++) {
reg_ebp-=2;reg_esp-=2;
mem_writew(SegBase(ss)+reg_esp,mem_readw(SegBase(ss)+reg_ebp));
}
if (level) {
reg_esp-=2;
mem_writew(SegBase(ss)+reg_esp,(Bit16u)frame_ptr);
}
reg_esp-=bytes;
} else {
reg_sp-=2;
mem_writew(SegBase(ss)+reg_sp,reg_bp);
for (Bitu i=1;i<level;i++) {
reg_bp-=2;reg_sp-=2;
mem_writew(SegBase(ss)+reg_sp,mem_readw(SegBase(ss)+reg_bp));
}
if (level) {
reg_sp-=2;
mem_writew(SegBase(ss)+reg_sp,(Bit16u)frame_ptr);
}
reg_sp-=bytes;
}
reg_bp=frame_ptr;
Bitu bytes=Fetchw();
Bitu level=Fetchb();
CPU_ENTER(false,bytes,level);
goto nextopcode;
}
case D_ENTERd:
{
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
Bitu frame_ptr=reg_esp-4;
if (cpu.stack.big) {
reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,reg_ebp);
for (Bitu i=1;i<level;i++) {
reg_ebp-=4;reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,mem_readd(SegBase(ss)+reg_ebp));
}
if (level) {
reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,(Bit32u)frame_ptr);
}
reg_esp-=bytes;
} else {
reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,reg_ebp);
for (Bitu i=1;i<level;i++) {
reg_bp-=4;reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,mem_readd(SegBase(ss)+reg_bp));
}
if (level) {
reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,(Bit32u)frame_ptr);
}
reg_sp-=bytes;
}
reg_ebp=frame_ptr;
Bitu bytes=Fetchw();
Bitu level=Fetchb();
CPU_ENTER(true,bytes,level);
goto nextopcode;
}
case D_LEAVEw:
@ -523,14 +468,14 @@ l_M_Ed:
CPU_CPUID();
goto nextopcode;
case D_HLT:
LEAVECORE;
CPU_HLT(IPPoint-inst.opcode_start);
FillFlags();
CPU_HLT(GetIP());
return CBRET_NONE;
case D_CLTS:
//TODO Really clear it sometime
goto nextopcode;
default:
LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %X",inst.code.load,inst.entry);
break;
goto illegalopcode;
}

View File

@ -1,6 +1,12 @@
#define SaveIP() reg_eip=(Bit32u)(IPPoint-SegBase(cs));
#define LoadIP() IPPoint=SegBase(cs)+reg_eip;
#define SaveIP() reg_eip=(Bit32u)(inst.cseip-SegBase(cs));
#define LoadIP() inst.cseip=SegBase(cs)+reg_eip;
#define GetIP() (inst.cseip-SegBase(cs))
#define RunException() { \
FillFlags(); \
CPU_Exception(cpu.exception.which,cpu.exception.error); \
continue; \
}
static INLINE Bit8u the_Fetchb(EAPoint & loc) {
Bit8u temp=LoadMb(loc);
@ -19,42 +25,16 @@ static INLINE Bit32u the_Fetchd(EAPoint & loc) {
return temp;
}
#define Fetchb() the_Fetchb(IPPoint)
#define Fetchw() the_Fetchw(IPPoint)
#define Fetchd() the_Fetchd(IPPoint)
#define Fetchb() the_Fetchb(inst.cseip)
#define Fetchw() the_Fetchw(inst.cseip)
#define Fetchd() the_Fetchd(inst.cseip)
#define Fetchbs() (Bit8s)the_Fetchb(IPPoint)
#define Fetchws() (Bit16s)the_Fetchw(IPPoint)
#define Fetchds() (Bit32s)the_Fetchd(IPPoint)
#if 0
static INLINE void Push_16(Bit16u blah) {
reg_esp-=2;
SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
}
static INLINE void Push_32(Bit32u blah) {
reg_esp-=4;
SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
}
static INLINE Bit16u Pop_16(void) {
Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask));
reg_esp+=2;
return temp;
}
static INLINE Bit32u Pop_32(void) {
Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask));
reg_esp+=4;
return temp;
}
#else
#define Fetchbs() (Bit8s)the_Fetchb(inst.cseip)
#define Fetchws() (Bit16s)the_Fetchw(inst.cseip)
#define Fetchds() (Bit32s)the_Fetchd(inst.cseip)
#define Push_16 CPU_Push16
#define Push_32 CPU_Push32
#define Pop_16 CPU_Pop16
#define Pop_32 CPU_Pop32
#endif

View File

@ -322,51 +322,57 @@ switch (inst.code.op) {
Push_32(reg_eip);
break;
case O_CALLFw:
LEAVECORE;
CPU_CALL(false,inst.op2.d,inst.op1.d);
goto restart_core;
FillFlags();
CPU_CALL(false,inst.op2.d,inst.op1.d,GetIP());
continue;
case O_CALLFd:
LEAVECORE;
CPU_CALL(true,inst.op2.d,inst.op1.d);
goto restart_core;
FillFlags();
CPU_CALL(true,inst.op2.d,inst.op1.d,GetIP());
continue;
case O_JMPFw:
LEAVECORE;
CPU_JMP(false,inst.op2.d,inst.op1.d);
goto restart_core;
FillFlags();
CPU_JMP(false,inst.op2.d,inst.op1.d,GetIP());
continue;
case O_JMPFd:
LEAVECORE;
CPU_JMP(true,inst.op2.d,inst.op1.d);
goto restart_core;
FillFlags();
CPU_JMP(true,inst.op2.d,inst.op1.d,GetIP());
continue;
case O_INT:
LEAVECORE;
FillFlags();
#if C_DEBUG
if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint())
return debugCallback;
else if (DEBUG_IntBreakpoint(inst.op1.b))
return debugCallback;
#endif
CPU_SW_Interrupt(inst.op1.b,IPPoint-inst.opcode_start);
goto restart_core;
CPU_SW_Interrupt(inst.op1.b,GetIP());
continue;
case O_INb:
if (CPU_IO_Exception(inst.op1.d,1)) RunException();
reg_al=IO_ReadB(inst.op1.d);
goto nextopcode;
case O_INw:
if (CPU_IO_Exception(inst.op1.d,2)) RunException();
reg_ax=IO_ReadW(inst.op1.d);
goto nextopcode;
case O_INd:
if (CPU_IO_Exception(inst.op1.d,4)) RunException();
reg_eax=IO_ReadD(inst.op1.d);
goto nextopcode;
case O_OUTb:
if (CPU_IO_Exception(inst.op1.d,1)) RunException();
IO_WriteB(inst.op1.d,reg_al);
goto nextopcode;
case O_OUTw:
if (CPU_IO_Exception(inst.op1.d,2)) RunException();
IO_WriteW(inst.op1.d,reg_ax);
goto nextopcode;
case O_OUTd:
if (CPU_IO_Exception(inst.op1.d,4)) RunException();
IO_WriteD(inst.op1.d,reg_eax);
goto nextopcode;
case O_CBACK:
LEAVECORE;
FillFlags();SaveIP();
return inst.op1.d;
case O_GRP6w:
case O_GRP6d:
@ -458,19 +464,22 @@ switch (inst.code.op) {
case O_LAR:
{
FillFlags();
Bitu ar;CPU_LAR(inst.op1.d,ar);
Bitu ar=inst.op2.d;
CPU_LAR(inst.op1.w,ar);
inst.op1.d=(Bit32u)ar;
}
break;
case O_LSL:
{
FillFlags();
Bitu limit;CPU_LSL(inst.op1.d,limit);
Bitu limit=inst.op2.d;
CPU_LSL(inst.op1.w,limit);
inst.op1.d=(Bit32u)limit;
}
break;
case O_ARPL:
{
if ((reg_flags & FLAG_VM) || !cpu.pmode) goto illegalopcode;
FillFlags();
Bitu new_sel=inst.op1.d;
CPU_ARPL(new_sel,inst.op2.d);

View File

@ -110,8 +110,9 @@ static OpCode OpCodeTable[1024]={
/* 0x98 - 0x9f */
{D_CBW ,0 ,0 ,0 },{D_CWD ,0 ,0 ,0 },
{L_Ifw ,O_CALLFw ,0 ,0 },{D_WAIT ,0 ,0 ,0 },
{L_FLG ,0 ,S_PUSHw,0 },{L_POPw ,0 ,S_FLGw ,0 },
{L_REGb ,0 ,S_FLGb ,REGI_AH},{L_FLG ,0 ,S_REGb ,REGI_AH},
{D_PUSHF ,0 ,0 ,0 },{D_POPF ,0 ,0 ,0 },
{D_SAHF ,0 ,0 ,0 },{D_LAHF ,0 ,0 ,0 },
/* 0xa0 - 0xa7 */
{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_AXOP ,0 ,0 },
@ -182,7 +183,7 @@ static OpCode OpCodeTable[1024]={
/* 0x100 - 0x107 */
{L_MODRM ,O_GRP6w ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7w ,S_Ew ,M_Ew },
{L_MODRM ,O_LAR ,S_Gw ,M_Ew },{L_MODRM ,O_LSL ,S_Gw ,M_Ew },
{L_MODRM ,O_LAR ,S_Gw ,M_EwGw },{L_MODRM ,O_LSL ,S_Gw ,M_EwGw },
{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 },
{D_CLTS ,0 ,0 ,0 },{0 ,0 ,0 ,0 },
/* 0x108 - 0x10f */
@ -466,8 +467,8 @@ static OpCode OpCodeTable[1024]={
/* 0x298 - 0x29f */
{D_CWDE ,0 ,0 ,0 },{D_CDQ ,0 ,0 ,0 },
{L_Ifd ,O_CALLFd ,0 ,0 },{D_WAIT ,0 ,0 ,0 },
{L_FLG ,0 ,S_PUSHd,0 },{L_POPd ,0 ,S_FLGd ,0 },
{L_REGb ,0 ,S_FLGb ,REGI_AH},{L_FLG ,0 ,S_REGb ,REGI_AH},
{D_PUSHF ,0 ,0 ,true },{D_POPF ,0 ,0 ,true },
{D_SAHF ,0 ,0 ,0 },{D_LAHF ,0 ,0 ,0 },
/* 0x2a0 - 0x2a7 */
{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_EAXOP ,0 ,0 },
@ -538,7 +539,7 @@ static OpCode OpCodeTable[1024]={
/* 0x300 - 0x307 */
{L_MODRM ,O_GRP6d ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7d ,S_Ew ,M_Ew },
{L_MODRM ,O_LAR ,S_Gd ,M_Ew },{L_MODRM ,O_LSL ,S_Gd ,M_Ew },
{L_MODRM ,O_LAR ,S_Gd ,M_EdGd },{L_MODRM ,O_LSL ,S_Gd ,M_EdGd },
{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 },
{D_CLTS ,0 ,0 ,0 },{0 ,0 ,0 ,0 },
/* 0x308 - 0x30f */

View File

@ -56,29 +56,14 @@ switch (inst.code.save) {
reg_32(inst.code.extra)=inst.op1.d;
break;
case S_SEGm:
if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) {
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);
CPU_StartException();
goto restart_core;
}
if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) RunException();
break;
case S_SEGGw:
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) {
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);
CPU_StartException();
goto restart_core;
}
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) RunException();
reg_16(inst.rm_index)=inst.op1.w;
break;
case S_SEGGd:
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) {
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);
CPU_StartException();
goto restart_core;
}
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) RunException();
reg_32(inst.rm_index)=inst.op1.d;
break;
case S_PUSHw:
@ -94,39 +79,19 @@ switch (inst.code.save) {
SaveIP();
reg_eip+=inst.op1.d;
reg_eip&=0xffff;
LoadIP();
break;
continue;
case S_C_AIPd:
if (!inst.cond) goto nextopcode;
case S_AIPd:
SaveIP();
reg_eip+=inst.op1.d;
LoadIP();
break;
continue;
case S_IPIw:
reg_esp+=Fetchw();
case S_IP:
SaveIP();
reg_eip=inst.op1.d;
LoadIP();
break;
case S_FLGb:
SETFLAGSb(inst.op1.b);
break;
case S_FLGw:
SETFLAGSw(inst.op1.w);
if (GETFLAG(IF) && PIC_IRQCheck) {
SaveIP();
return CBRET_NONE;
}
break;
case S_FLGd:
SETFLAGSd(inst.op1.d);
if (GETFLAG(IF) && PIC_IRQCheck) {
SaveIP();
return CBRET_NONE;
}
break;
continue;
case 0:
break;
default:

View File

@ -28,7 +28,7 @@
count_left=count-CPU_Cycles;
count=CPU_Cycles;
CPU_Cycles=0;
IPPoint=inst.opcode_start; //Reset IP to start of instruction
LoadIP();
} else {
/* Won't interrupt scas and cmps instruction since they can interrupt themselves */
count_left=0;

View File

@ -15,7 +15,7 @@ enum {
L_POPfw,L_POPfd,
L_SEG,
L_FLG,L_INTO,
L_INTO,
L_VAL,
L_PRESEG,
@ -41,6 +41,8 @@ enum {
D_RETFw,D_RETFd,
D_RETFwIw,D_RETFdIw,
D_POPF,D_PUSHF,
D_SAHF,D_LAHF,
D_CPUID,
D_HLT,D_CLTS,
L_ERROR,
@ -113,7 +115,6 @@ enum {
S_AIPw,S_C_AIPw,
S_AIPd,S_C_AIPd,
S_FLGb,S_FLGw,S_FLGd,
S_IP,S_IPIw,
};
@ -155,7 +156,6 @@ struct OpCode {
struct FullData {
Bitu entry;
EAPoint opcode_start;
Bitu rm;
EAPoint rm_eaa;
Bitu rm_off;
@ -163,6 +163,7 @@ struct FullData {
Bitu rm_index;
Bitu rm_mod;
OpCode code;
EAPoint cseip;
union {
Bit8u b;Bit8s bs;
Bit16u w;Bit16s ws;
@ -175,13 +176,11 @@ struct FullData {
Bitu cond;
bool repz;
Bitu prefix;
Bitu start_prefix;
Bitu start_entry;
};
#define PREFIX_NONE 0x0
#define PREFIX_SEG 0x1
#define PREFIX_ADDR 0x2
#define PREFIX_ADDR 0x1
#define PREFIX_SEG 0x2
#define PREFIX_REP 0x4

View File

@ -9,13 +9,14 @@
* 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.
* 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.
*/
#include <stdio.h>
#include "dosbox.h"
#include "mem.h"
@ -30,43 +31,23 @@
#include "debug.h"
#endif
#define SegBase(c) SegPhys(c)
#if (!C_CORE_INLINE)
#define LoadMb(off) mem_readb(off)
#define LoadMw(off) mem_readw(off)
#define LoadMd(off) mem_readd(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)
#else
#include "paging.h"
#define LoadMb(off) mem_readb_inline(off)
#define LoadMw(off) mem_readw_inline(off)
#define LoadMd(off) mem_readd_inline(off)
#define SaveMb(off,val) mem_writeb_inline(off,val)
#define SaveMw(off,val) mem_writew_inline(off,val)
#define SaveMd(off,val) mem_writed_inline(off,val)
#endif
#define LoadMbs(off) (Bit8s)(LoadMb(off))
#define LoadMws(off) (Bit16s)(LoadMw(off))
#define LoadMds(off) (Bit32s)(LoadMd(off))
#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;
#if C_FPU
@ -80,122 +61,129 @@ extern Bitu cycle_count;
#define OPCODE_0F 0x100
#define OPCODE_SIZE 0x200
#define PREFIX_SEG 0x1
#define PREFIX_ADDR 0x2
#define PREFIX_SEG_ADDR (PREFIX_SEG|PREFIX_ADDR)
#define PREFIX_REP 0x4
#define PREFIX_ADDR 0x1
#define PREFIX_REP 0x2
#define TEST_PREFIX_SEG (core.prefixes & PREFIX_SEG)
#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR)
#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP)
#define DO_PREFIX_SEG(_SEG) \
core.prefixes|=PREFIX_SEG; \
core.seg_prefix_base=SegBase(_SEG); \
goto restart_prefix;
BaseDS=SegBase(_SEG); \
BaseSS=SegBase(_SEG); \
goto restart_opcode;
#define DO_PREFIX_ADDR() \
core.prefixes^=PREFIX_ADDR; \
goto restart_prefix;
#define DO_PREFIX_ADDR() \
core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \
(cpu.code.big ^ PREFIX_ADDR); \
core.ea_table=&EATable[(core.prefixes&1) * 256]; \
goto restart_opcode;
#define DO_PREFIX_REP(_ZERO) \
core.prefixes|=PREFIX_REP; \
core.rep_zero=_ZERO; \
goto restart_prefix;
goto restart_opcode;
typedef PhysPt (*GetEATable[256])(void);
typedef PhysPt (*GetEAHandler)(void);
static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff};
static struct {
Bitu opcode_index;
Bitu prefixes;
Bitu index_default;
Bitu prefix_default;
PhysPt op_start;
PhysPt ip_lookup;
PhysPt seg_prefix_base;
PhysPt cseip;
PhysPt base_ds,base_ss;
bool rep_zero;
GetEATable * ea_table;
Bitu prefixes;
GetEAHandler * ea_table;
struct {
bool skip;
} trap;
} core;
#define GETIP (core.cseip-SegBase(cs))
#define SAVEIP reg_eip=GETIP;
#define LOADIP core.cseip=(SegBase(cs)+reg_eip);
#define SegBase(c) SegPhys(c)
#define BaseDS core.base_ds
#define BaseSS core.base_ss
static INLINE Bit8u Fetchb() {
Bit8u temp=LoadMb(core.cseip);
core.cseip+=1;
return temp;
}
static INLINE Bit16u Fetchw() {
Bit16u temp=LoadMw(core.cseip);
core.cseip+=2;
return temp;
}
static INLINE Bit32u Fetchd() {
Bit32u temp=LoadMd(core.cseip);
core.cseip+=4;
return temp;
}
#define Push_16 CPU_Push16
#define Push_32 CPU_Push32
#define Pop_16 CPU_Pop16
#define Pop_32 CPU_Pop32
#include "instructions.h"
#include "core_normal/support.h"
#include "core_normal/string.h"
static GetEATable * EAPrefixTable[8] = {
&GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR,
&GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR,
};
#define CASE_W(_WHICH) \
case (OPCODE_NONE+_WHICH):
#define CASE_D(_WHICH) \
case (OPCODE_SIZE+_WHICH):
#define CASE_B(_WHICH) \
CASE_W(_WHICH) \
CASE_D(_WHICH)
#define CASE_0F_W(_WHICH) \
case ((OPCODE_0F|OPCODE_NONE)+_WHICH):
#define CASE_0F_D(_WHICH) \
case ((OPCODE_0F|OPCODE_SIZE)+_WHICH):
#define CASE_0F_B(_WHICH) \
CASE_0F_W(_WHICH) \
CASE_0F_D(_WHICH)
#define EALookupTable (*(core.ea_table))
#define EALookupTable (core.ea_table)
Bits CPU_Core_Normal_Run(void) {
decode_start:
if (cpu.code.big) {
core.index_default=0x200;
core.prefix_default=PREFIX_ADDR;
} else {
core.index_default=0;
core.prefix_default=0;
}
LOADIP;
lflags.type=t_UNKNOWN;
while (CPU_Cycles-->0) {
core.op_start=core.ip_lookup;
core.opcode_index=core.index_default;
core.prefixes=core.prefix_default;
LOADIP;
core.opcode_index=cpu.code.big*0x200;
core.prefixes=cpu.code.big;
core.ea_table=&EATable[cpu.code.big*256];
BaseDS=SegBase(ds);
BaseSS=SegBase(ss);
#if C_DEBUG
cycle_count++;
#if C_HEAVY_DEBUG
SAVEIP;
if (DEBUG_HeavyIsBreakpoint()) {
LEAVECORE;
FillFlags();
return debugCallback;
};
#endif
cycle_count++;
#endif
restart_prefix:
core.ea_table=EAPrefixTable[core.prefixes];
restart_opcode:
switch (core.opcode_index+Fetchb()) {
#include "core_normal/prefix_none.h"
#include "core_normal/prefix_0f.h"
#include "core_normal/prefix_66.h"
#include "core_normal/prefix_66_0f.h"
default:
ADDIPFAST(-1);
#if C_DEBUG
LOG_MSG("Unhandled code %X",core.opcode_index+Fetchb());
#else
E_Exit("Unhandled CPU opcode");
illegal_opcode:
#if C_DEBUG
{
Bitu len=(GETIP-reg_eip);
LOADIP;
if (len>16) len=16;
char tempcode[16*2+1];char * writecode=tempcode;
for (;len>0;len--) {
sprintf(writecode,"%X",mem_readb(core.cseip++));
writecode+=2;
}
LOG(LOG_CPU,LOG_ERROR)("Illegal/Unhandled opcode %s",tempcode);
}
#endif
CPU_Exception(6,0);
continue;
}
SAVEIP;
}
decode_end:
LEAVECORE;
FillFlags();
return CBRET_NONE;
decode_end:
SAVEIP;
FillFlags();
return CBRET_NONE;
}
@ -206,7 +194,7 @@ Bits CPU_Core_Normal_Trap_Run(void) {
core.trap.skip=false;
Bits ret=CPU_Core_Normal_Run();
if (!core.trap.skip) CPU_SW_Interrupt(1,0);
if (!core.trap.skip) CPU_SW_Interrupt(1,reg_eip);
CPU_Cycles = oldCycles-1;
cpudecoder = &CPU_Core_Normal_Run;

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -141,17 +141,22 @@
} \
}
#define POPSEG(_SEG_,_VAL_,_ESP_CHANGE_) \
if (CPU_SetSegGeneral(_SEG_,_VAL_)) { \
LEAVECORE; \
reg_eip-=(core.ip_lookup-core.op_start);reg_esp-=_ESP_CHANGE_; \
CPU_StartException();goto decode_start; \
}
#define CASE_W(_WHICH) \
case (OPCODE_NONE+_WHICH):
#define LOADSEG(_SEG_,_SEG_VAL_) \
if (CPU_SetSegGeneral(_SEG_,_SEG_VAL_)) { \
LEAVECORE; \
reg_eip-=(core.ip_lookup-core.op_start); \
CPU_StartException();goto decode_start; \
} \
#define CASE_D(_WHICH) \
case (OPCODE_SIZE+_WHICH):
#define CASE_B(_WHICH) \
CASE_W(_WHICH) \
CASE_D(_WHICH)
#define CASE_0F_W(_WHICH) \
case ((OPCODE_0F|OPCODE_NONE)+_WHICH):
#define CASE_0F_D(_WHICH) \
case ((OPCODE_0F|OPCODE_SIZE)+_WHICH):
#define CASE_0F_B(_WHICH) \
CASE_0F_W(_WHICH) \
CASE_0F_D(_WHICH)

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -45,7 +45,7 @@
}
break;
default:
LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which);
goto illegal_opcode;
}
}
break;
@ -77,7 +77,7 @@
break;
case 0x06: /* LMSW */
limit=LoadMw(eaa);
if (!CPU_LMSW(limit)) goto decode_end;
if (CPU_LMSW(limit)) RUNEXCEPTION();
break;
}
} else {
@ -88,11 +88,10 @@
*earw=limit;
break;
case 0x06: /* LMSW */
if (!CPU_LMSW(*earw)) goto decode_end;
if (CPU_LMSW(*earw)) RUNEXCEPTION();
break;
default:
LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which);
break;
goto illegal_opcode;
}
}
}
@ -100,7 +99,7 @@
CASE_0F_W(0x02) /* LAR Gw,Ew */
{
FillFlags();
GetRMrw;Bitu ar;
GetRMrw;Bitu ar=*rmrw;
if (rm >= 0xc0) {
GetEArw;CPU_LAR(*earw,ar);
} else {
@ -112,7 +111,7 @@
CASE_0F_W(0x03) /* LSL Gw,Ew */
{
FillFlags();
GetRMrw;Bitu limit;
GetRMrw;Bitu limit=*rmrw;
if (rm >= 0xc0) {
GetEArw;CPU_LSL(*earw,limit);
} else {
@ -154,11 +153,8 @@
Bitu which=(rm >> 3) & 7;
if (rm >= 0xc0 ) {
GetEArd;
CPU_SET_CRX(which,*eard);
} else {
GetEAa;
LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which);
}
if (CPU_SET_CRX(which,*eard)) RUNEXCEPTION();
} else goto illegal_opcode;
}
break;
CASE_0F_B(0x23) /* MOV DRx,Rd */
@ -241,7 +237,7 @@
CASE_0F_W(0xa0) /* PUSH FS */
Push_16(SegValue(fs));break;
CASE_0F_W(0xa1) /* POP FS */
POPSEG(fs,Pop_16(),2);
if (CPU_PopSeg(fs,false)) RUNEXCEPTION();
break;
CASE_0F_B(0xa2) /* CPUID */
CPU_CPUID();break;
@ -268,7 +264,8 @@
CASE_0F_W(0xa8) /* PUSH GS */
Push_16(SegValue(gs));break;
CASE_0F_W(0xa9) /* POP GS */
POPSEG(gs,Pop_16(),2);break;
if (CPU_PopSeg(gs,false)) RUNEXCEPTION();
break;
CASE_0F_W(0xab) /* BTS Ew,Gw */
{
FillFlags();GetRMrw;
@ -297,7 +294,7 @@
CASE_0F_W(0xb2) /* LSS Ew */
{
GetRMrw;GetEAa;
LOADSEG(ss,LoadMw(eaa+2));
if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION();
*rmrw=LoadMw(eaa);
break;
}
@ -320,14 +317,14 @@
CASE_0F_W(0xb4) /* LFS Ew */
{
GetRMrw;GetEAa;
LOADSEG(fs,LoadMw(eaa+2));
if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION();
*rmrw=LoadMw(eaa);
break;
}
CASE_0F_W(0xb5) /* LGS Ew */
{
GetRMrw;GetEAa;
LOADSEG(gs,LoadMw(eaa+2));
if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION();
*rmrw=LoadMw(eaa);
break;
}

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -25,7 +25,8 @@
CASE_D(0x06) /* PUSH ES */
Push_32(SegValue(es));break;
CASE_D(0x07) /* POP ES */
POPSEG(es,Pop_32(),4);break;
if (CPU_PopSeg(es,true)) RUNEXCEPTION();
break;
CASE_D(0x09) /* OR Ed,Gd */
RMEdGd(ORD);break;
CASE_D(0x0b) /* OR Gd,Ed */
@ -43,7 +44,7 @@
CASE_D(0x16) /* PUSH SS */
Push_32(SegValue(ss));break;
CASE_D(0x17) /* POP SS */
POPSEG(ss,Pop_32(),4);
if (CPU_PopSeg(ss,true)) RUNEXCEPTION();
CPU_Cycles++;
break;
CASE_D(0x19) /* SBB Ed,Gd */
@ -55,7 +56,8 @@
CASE_D(0x1e) /* PUSH DS */
Push_32(SegValue(ds));break;
CASE_D(0x1f) /* POP DS */
POPSEG(ds,Pop_32(),4);break;
if (CPU_PopSeg(ds,true)) RUNEXCEPTION();
break;
CASE_D(0x21) /* AND Ed,Gd */
RMEdGd(ANDD);break;
CASE_D(0x23) /* AND Gd,Ed */
@ -167,6 +169,7 @@
break;
CASE_D(0x63) /* ARPL Ed,Rd */
{
if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode;
FillFlags();
GetRMrw;
if (rm >= 0xc0 ) {
@ -190,6 +193,12 @@
CASE_D(0x6b) /* IMUL Gd,Ed,Ib */
RMGdEdOp3(DIMULD,Fetchbs());
break;
CASE_D(0x6d) /* INSD */
if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION();
DoString(R_INSD);break;
CASE_D(0x6f) /* OUTSD */
if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION();
DoString(R_OUTSD);break;
CASE_D(0x70) /* JO */
JumpCond32_b(TFLG_O);break;
CASE_D(0x71) /* JNO */
@ -332,12 +341,12 @@
CASE_D(0x8d) /* LEA Gd */
{
//Little hack to always use segprefixed version
core.seg_prefix_base=0;
GetRMrd;
BaseDS=BaseSS=0;
if (TEST_PREFIX_ADDR) {
*rmrd=(Bit32u)(*GetEA_SEG_ADDR[rm])();
*rmrd=(Bit32u)(*EATable[256+rm])();
} else {
*rmrd=(Bit32u)(*GetEA_SEG[rm])();
*rmrd=(Bit32u)(*EATable[rm])();
}
break;
}
@ -378,21 +387,17 @@
CASE_D(0x9a) /* CALL FAR Ad */
{
Bit32u newip=Fetchd();Bit16u newcs=Fetchw();
LEAVECORE;
CPU_CALL(true,newcs,newip);
goto decode_start;
FillFlags();
CPU_CALL(true,newcs,newip,GETIP);
continue;
}
CASE_D(0x9c) /* PUSHFD */
FillFlags();
Push_32(reg_flags);
if (CPU_PUSHF(true)) RUNEXCEPTION();
break;
CASE_D(0x9d) /* POPFD */
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) {
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
CPU_Exception(13,0);
goto decode_start;
}
SETFLAGSd(Pop_32())
if (CPU_POPF(true)) RUNEXCEPTION();
lflags.type=t_UNKNOWN;
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
@ -402,7 +407,6 @@
#if CPU_PIC_CHECK
if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
#endif
break;
CASE_D(0xa1) /* MOV EAX,Od */
{
@ -447,25 +451,23 @@
CASE_D(0xc1) /* GRP2 Ed,Ib */
GRP2D(Fetchb());break;
CASE_D(0xc2) /* RETN Iw */
{
Bit16u addsp=Fetchw();
SETIP(Pop_32());reg_esp+=addsp;
break;
}
reg_eip=Pop_32();
reg_esp+=Fetchw();
continue;
CASE_D(0xc3) /* RETN */
SETIP(Pop_32());
break;
reg_eip=Pop_32();
continue;
CASE_D(0xc4) /* LES */
{
GetRMrd;GetEAa;
LOADSEG(es,LoadMw(eaa+4));
if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa);
break;
}
CASE_D(0xc5) /* LDS */
{
GetRMrd;GetEAa;
LOADSEG(ds,LoadMw(eaa+4));
if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa);
break;
}
@ -478,36 +480,11 @@
}
CASE_D(0xc8) /* ENTER Iw,Ib */
{
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
Bitu frame_ptr=reg_esp-4;
if (cpu.stack.big) {
reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,reg_ebp);
for (Bitu i=1;i<level;i++) {
reg_ebp-=4;reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,mem_readd(SegBase(ss)+reg_ebp));
}
if (level) {
reg_esp-=4;
mem_writed(SegBase(ss)+reg_esp,(Bit32u)frame_ptr);
}
reg_esp-=bytes;
} else {
reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,reg_ebp);
for (Bitu i=1;i<level;i++) {
reg_bp-=4;reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,mem_readd(SegBase(ss)+reg_bp));
}
if (level) {
reg_sp-=4;
mem_writed(SegBase(ss)+reg_sp,(Bit32u)frame_ptr);
}
reg_sp-=bytes;
}
reg_ebp=frame_ptr;
break;
Bitu bytes=Fetchw();
Bitu level=Fetchb();
CPU_ENTER(true,bytes,level);
}
break;
CASE_D(0xc9) /* LEAVE */
reg_esp&=~cpu.stack.mask;
reg_esp|=(reg_ebp&cpu.stack.mask);
@ -516,20 +493,20 @@
CASE_D(0xca) /* RETF Iw */
{
Bitu words=Fetchw();
LEAVECORE;
CPU_RET(true,words,core.ip_lookup-core.op_start);
goto decode_start;
FillFlags();
CPU_RET(true,words,GETIP);
continue;
}
CASE_D(0xcb) /* RETF */
{
LEAVECORE;
CPU_RET(true,0,core.ip_lookup-core.op_start);
goto decode_start;
FillFlags();
CPU_RET(true,0,GETIP);
continue;
}
CASE_D(0xcf) /* IRET */
{
LEAVECORE;
CPU_IRET(true);
FillFlags();
CPU_IRET(true,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
@ -539,36 +516,79 @@
#if CPU_PIC_CHECK
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
#endif
//TODO TF check
goto decode_start;
continue;
}
CASE_D(0xd1) /* GRP2 Ed,1 */
GRP2D(1);break;
CASE_D(0xd3) /* GRP2 Ed,CL */
GRP2D(reg_cl);break;
CASE_D(0xe0) /* LOOPNZ */
if (TEST_PREFIX_ADDR) {
JumpCond32_b(--reg_ecx && !get_ZF());
} else {
JumpCond32_b(--reg_cx && !get_ZF());
}
break;
CASE_D(0xe1) /* LOOPZ */
if (TEST_PREFIX_ADDR) {
JumpCond32_b(--reg_ecx && get_ZF());
} else {
JumpCond32_b(--reg_cx && get_ZF());
}
break;
CASE_D(0xe2) /* LOOP */
if (TEST_PREFIX_ADDR) {
JumpCond32_b(--reg_ecx);
} else {
JumpCond32_b(--reg_cx);
}
break;
CASE_D(0xe3) /* JCXZ */
JumpCond32_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR]));
break;
CASE_D(0xe5) /* IN EAX,Ib */
reg_eax=IO_ReadD(Fetchb());
break;
CASE_D(0xe7) /* OUT Ib,EAX */
IO_WriteD(Fetchb(),reg_eax);
break;
CASE_D(0xe8) /* CALL Jd */
{
Bit32s newip=Fetchds();
Push_32((Bit32u)GETIP);
ADDIPd(newip);
{
Bitu port=Fetchb();
if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
reg_eax=IO_ReadD(port);
break;
}
CASE_D(0xe7) /* OUT Ib,EAX */
{
Bitu port=Fetchb();
if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
IO_WriteD(port,reg_eax);
break;
}
CASE_D(0xe8) /* CALL Jd */
{
Bit32s addip=Fetchds();
SAVEIP;
Push_32(reg_eip);
reg_eip+=addip;
continue;
}
CASE_D(0xe9) /* JMP Jd */
ADDIPd(Fetchds());
break;
{
Bit32s addip=Fetchds();
SAVEIP;
reg_eip+=addip;
continue;
}
CASE_D(0xea) /* JMP Ad */
{
Bit32u newip=Fetchd();
Bit16u newcs=Fetchw();
LEAVECORE;
CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start);
goto decode_start;
FillFlags();
CPU_JMP(true,newcs,newip,GETIP);
continue;
}
CASE_D(0xeb) /* JMP Jb */
{
Bit32s addip=Fetchbs();
SAVEIP;
reg_eip+=addip;
continue;
}
CASE_D(0xed) /* IN EAX,DX */
reg_eax=IO_ReadD(reg_dx);
@ -631,31 +651,31 @@
RMEd(DECD);
break;
case 0x02: /* CALL NEAR Ed */
if (rm >= 0xc0 ) {GetEArd;Push_32(GETIP);SETIP(*eard);}
else {GetEAa;Push_32(GETIP);SETIP(LoadMd(eaa));}
break;
if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
else {GetEAa;reg_eip=LoadMd(eaa);}
Push_32(GETIP);
continue;
case 0x03: /* CALL FAR Ed */
{
GetEAa;
Bit32u newip=LoadMd(eaa);
Bit16u newcs=LoadMw(eaa+4);
LEAVECORE;
CPU_CALL(true,newcs,newip);
goto decode_start;
FillFlags();
CPU_CALL(true,newcs,newip,GETIP);
continue;
}
break;
case 0x04: /* JMP NEAR Ed */
if (rm >= 0xc0 ) {GetEArd;SETIP(*eard);}
else {GetEAa;SETIP(LoadMd(eaa));}
break;
if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
else {GetEAa;reg_eip=LoadMd(eaa);}
continue;
case 0x05: /* JMP FAR Ed */
{
GetEAa;
Bit32u newip=LoadMd(eaa);
Bit16u newcs=LoadMw(eaa+4);
LEAVECORE;
CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start);
goto decode_start;
FillFlags();
CPU_JMP(true,newcs,newip,GETIP);
continue;
}
break;
case 0x06: /* Push Ed */

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -101,7 +101,7 @@
CASE_0F_D(0x02) /* LAR Gd,Ed */
{
FillFlags();
GetRMrd;Bitu ar;
GetRMrd;Bitu ar=*rmrd;
if (rm >= 0xc0) {
GetEArw;CPU_LAR(*earw,ar);
} else {
@ -113,7 +113,7 @@
CASE_0F_D(0x03) /* LSL Gd,Ew */
{
FillFlags();
GetRMrd;Bitu limit;
GetRMrd;Bitu limit=*rmrd;
/* Just load 16-bit values for selectors */
if (rm >= 0xc0) {
GetEArw;CPU_LSL(*earw,limit);
@ -159,7 +159,8 @@
CASE_0F_D(0xa0) /* PUSH FS */
Push_32(SegValue(fs));break;
CASE_0F_D(0xa1) /* POP FS */
POPSEG(fs,Pop_32(),4);break;
if (CPU_PopSeg(fs,true)) RUNEXCEPTION();
break;
CASE_0F_D(0xa3) /* BT Ed,Gd */
{
FillFlags();GetRMrd;
@ -183,7 +184,8 @@
CASE_0F_D(0xa8) /* PUSH GS */
Push_32(SegValue(gs));break;
CASE_0F_D(0xa9) /* POP GS */
POPSEG(gs,Pop_32(),4);break;
if (CPU_PopSeg(gs,true)) RUNEXCEPTION();
break;
CASE_0F_D(0xab) /* BTS Ed,Gd */
{
FillFlags();GetRMrd;
@ -215,7 +217,7 @@
CASE_0F_D(0xb2) /* LSS Ed */
{
GetRMrd;GetEAa;
LOADSEG(ss,LoadMw(eaa+4));
if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa);
break;
}
@ -238,14 +240,14 @@
CASE_0F_D(0xb4) /* LFS Ed */
{
GetRMrd;GetEAa;
LOADSEG(fs,LoadMw(eaa+4));
if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa);
break;
}
CASE_0F_D(0xb5) /* LGS Ed */
{
GetRMrd;GetEAa;
LOADSEG(gs,LoadMw(eaa+4));
if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa);
break;
}

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -31,7 +31,8 @@
CASE_W(0x06) /* PUSH ES */
Push_16(SegValue(es));break;
CASE_W(0x07) /* POP ES */
POPSEG(es,Pop_16(),2);break;
if (CPU_PopSeg(es,false)) RUNEXCEPTION();
break;
CASE_B(0x08) /* OR Eb,Gb */
RMEbGb(ORB);break;
CASE_W(0x09) /* OR Ew,Gw */
@ -65,7 +66,7 @@
CASE_W(0x16) /* PUSH SS */
Push_16(SegValue(ss));break;
CASE_W(0x17) /* POP SS */
POPSEG(ss,Pop_16(),2);
if (CPU_PopSeg(ss,false)) RUNEXCEPTION();
CPU_Cycles++; //Always do another instruction
break;
CASE_B(0x18) /* SBB Eb,Gb */
@ -83,7 +84,7 @@
CASE_W(0x1e) /* PUSH DS */
Push_16(SegValue(ds));break;
CASE_W(0x1f) /* POP DS */
POPSEG(ds,Pop_16(),2);
if (CPU_PopSeg(ds,false)) RUNEXCEPTION();
break;
CASE_B(0x20) /* AND Eb,Gb */
RMEbGb(ANDB);break;
@ -237,6 +238,7 @@
break;
CASE_W(0x63) /* ARPL Ew,Rw */
{
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
FillFlags();
GetRMrw;
if (rm >= 0xc0 ) {
@ -255,7 +257,7 @@
CASE_B(0x65) /* SEG GS: */
DO_PREFIX_SEG(gs);break;
CASE_B(0x66) /* Operand Size Prefix */
core.opcode_index=core.index_default^OPCODE_SIZE;
core.opcode_index=(cpu.code.big^0x1)*0x200;
goto restart_opcode;
CASE_B(0x67) /* Address Size Prefix */
DO_PREFIX_ADDR();
@ -271,12 +273,16 @@
RMGwEwOp3(DIMULW,Fetchbs());
break;
CASE_B(0x6c) /* INSB */
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
DoString(R_INSB);break;
CASE_W(0x6d) /* INSW */
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
DoString(R_INSW);break;
CASE_B(0x6e) /* OUTSB */
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
DoString(R_OUTSB);break;
CASE_W(0x6f) /* OUTSW */
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
DoString(R_OUTSW);break;
CASE_W(0x70) /* JO */
JumpCond16_b(TFLG_O);break;
@ -476,12 +482,12 @@
CASE_W(0x8d) /* LEA Gw */
{
//Little hack to always use segprefixed version
core.seg_prefix_base=0;
BaseDS=BaseSS=0;
GetRMrw;
if (TEST_PREFIX_ADDR) {
*rmrw=(Bit16u)(*GetEA_SEG_ADDR[rm])();
*rmrw=(Bit16u)(*EATable[256+rm])();
} else {
*rmrw=(Bit16u)(*GetEA_SEG[rm])();
*rmrw=(Bit16u)(*EATable[rm])();
}
break;
}
@ -497,13 +503,10 @@
case 0x03: /* MOV DS,Ew */
case 0x05: /* MOV GS,Ew */
case 0x04: /* MOV FS,Ew */
LOADSEG((SegNames)which,val);
break;
case 0x01: /* MOV CS,Ew Illegal*/
E_Exit("CPU:Illegal MOV CS Call");
if (CPU_SetSegGeneral((SegNames)which,val)) RUNEXCEPTION();
break;
default:
E_Exit("CPU:8E:Illegal RM Byte");
goto illegal_opcode;
}
break;
}
@ -545,24 +548,20 @@
break;
CASE_W(0x9a) /* CALL Ap */
{
FillFlags();
Bit16u newip=Fetchw();Bit16u newcs=Fetchw();
LEAVECORE;
CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start);
goto decode_start;
CPU_CALL(false,newcs,newip,GETIP);
continue;
}
CASE_B(0x9b) /* WAIT */
break; /* No waiting here */
CASE_W(0x9c) /* PUSHF */
FillFlags();
Push_16(reg_flags);
if (CPU_PUSHF(false)) RUNEXCEPTION();
break;
CASE_W(0x9d) /* POPF */
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) {
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
CPU_Exception(13,0);
goto decode_start;
}
SETFLAGSw(Pop_16());
if (CPU_POPF(false)) RUNEXCEPTION();
lflags.type=t_UNKNOWN;
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
@ -665,25 +664,23 @@
CASE_W(0xc1) /* GRP2 Ew,Ib */
GRP2W(Fetchb());break;
CASE_W(0xc2) /* RETN Iw */
{
Bit16u addsp=Fetchw();
SETIP(Pop_16());reg_esp+=addsp;
break;
}
reg_eip=Pop_16();
reg_esp+=Fetchw();
continue;
CASE_W(0xc3) /* RETN */
SETIP(Pop_16());
break;
reg_eip=Pop_16();
continue;
CASE_W(0xc4) /* LES */
{
GetRMrw;GetEAa;
LOADSEG(es,LoadMw(eaa+2));
if (CPU_SetSegGeneral(es,LoadMw(eaa+2))) RUNEXCEPTION();
*rmrw=LoadMw(eaa);
break;
}
CASE_W(0xc5) /* LDS */
{
GetRMrw;GetEAa;
LOADSEG(ds,LoadMw(eaa+2));
if (CPU_SetSegGeneral(ds,LoadMw(eaa+2))) RUNEXCEPTION();
*rmrw=LoadMw(eaa);
break;
}
@ -703,36 +700,11 @@
}
CASE_W(0xc8) /* ENTER Iw,Ib */
{
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
Bitu frame_ptr=reg_esp-2;
if (cpu.stack.big) {
reg_esp-=2;
mem_writew(SegBase(ss)+reg_esp,reg_bp);
for (Bitu i=1;i<level;i++) {
reg_ebp-=2;reg_esp-=2;
mem_writew(SegBase(ss)+reg_esp,mem_readw(SegBase(ss)+reg_ebp));
}
if (level) {
reg_esp-=2;
mem_writew(SegBase(ss)+reg_esp,(Bit16u)frame_ptr);
}
reg_esp-=bytes;
} else {
reg_sp-=2;
mem_writew(SegBase(ss)+reg_sp,reg_bp);
for (Bitu i=1;i<level;i++) {
reg_bp-=2;reg_sp-=2;
mem_writew(SegBase(ss)+reg_sp,mem_readw(SegBase(ss)+reg_bp));
}
if (level) {
reg_sp-=2;
mem_writew(SegBase(ss)+reg_sp,(Bit16u)frame_ptr);
}
reg_sp-=bytes;
}
reg_bp=frame_ptr;
break;
Bitu bytes=Fetchw();
Bitu level=Fetchb();
CPU_ENTER(false,bytes,level);
}
break;
CASE_W(0xc9) /* LEAVE */
reg_esp&=~cpu.stack.mask;
reg_esp|=(reg_ebp&cpu.stack.mask);
@ -740,58 +712,55 @@
break;
CASE_W(0xca) /* RETF Iw */
{
Bitu words=Fetchw();
LEAVECORE;
CPU_RET(false,words,core.ip_lookup-core.op_start);
goto decode_start;
Bitu words=Fetchw();
FillFlags();
CPU_RET(false,words,GETIP);
continue;
}
CASE_W(0xcb) /* RETF */
LEAVECORE;
CPU_RET(false,0,core.ip_lookup-core.op_start);
goto decode_start;
FillFlags();
CPU_RET(false,0,GETIP);
continue;
CASE_B(0xcc) /* INT3 */
LEAVECORE;
FillFlags();
#if C_DEBUG
if (DEBUG_Breakpoint()) {
if (DEBUG_Breakpoint())
return debugCallback;
}
#endif
CPU_SW_Interrupt(3,(core.ip_lookup-core.op_start));
CPU_SW_Interrupt(3,GETIP);
#if CPU_TRAP_CHECK
core.trap.skip=true;
#endif
goto decode_start;
continue;
CASE_B(0xcd) /* INT Ib */
{
Bit8u num=Fetchb();
LEAVECORE;
FillFlags();
#if C_DEBUG
if (DEBUG_IntBreakpoint(num)) {
return debugCallback;
}
#endif
CPU_SW_Interrupt(num,core.ip_lookup-core.op_start);
CPU_SW_Interrupt(num,GETIP);
#if CPU_TRAP_CHECK
core.trap.skip=true;
#endif
goto decode_start;
continue;
}
break;
CASE_B(0xce) /* INTO */
if (get_OF()) {
LEAVECORE;
CPU_SW_Interrupt(4,core.ip_lookup-core.op_start);
FillFlags();
CPU_SW_Interrupt(4,GETIP);
#if CPU_TRAP_CHECK
core.trap.skip=true;
#endif
goto decode_start;
continue;
}
break;
CASE_W(0xcf) /* IRET */
{
LEAVECORE;
CPU_IRET(false);
FillFlags();
CPU_IRET(false,GETIP);
#if CPU_PIC_CHECK
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
#endif
@ -801,7 +770,7 @@
return CBRET_NONE;
}
#endif
goto decode_start;
continue;
}
CASE_B(0xd0) /* GRP2 Eb,1 */
GRP2B(1);break;
@ -819,18 +788,10 @@
reg_al = get_CF() ? 0xFF : 0;
break;
CASE_B(0xd7) /* XLAT */
if (TEST_PREFIX_SEG) {
if (TEST_PREFIX_ADDR) {
reg_al=LoadMb(core.seg_prefix_base+(Bit32u)(reg_ebx+reg_al));
} else {
reg_al=LoadMb(core.seg_prefix_base+(Bit16u)(reg_bx+reg_al));
}
if (TEST_PREFIX_ADDR) {
reg_al=LoadMb(BaseDS+(Bit32u)(reg_ebx+reg_al));
} else {
if (TEST_PREFIX_ADDR) {
reg_al=LoadMb(SegBase(ds)+(Bit32u)(reg_ebx+reg_al));
} else {
reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
}
reg_al=LoadMb(BaseDS+(Bit16u)(reg_bx+reg_al));
}
break;
#ifdef CPU_FPU
@ -866,84 +827,104 @@
}
break;
#endif
CASE_B(0xe0) /* LOOPNZ */
CASE_W(0xe0) /* LOOPNZ */
if (TEST_PREFIX_ADDR) {
if ((--reg_ecx) && !get_ZF()) ADDIPFAST(Fetchbs());
else ADDIPFAST(1);
JumpCond16_b(--reg_ecx && !get_ZF());
} else {
if ((--reg_cx) && !get_ZF()) ADDIPFAST(Fetchbs());
else ADDIPFAST(1);
JumpCond16_b(--reg_cx && !get_ZF());
}
break;
CASE_B(0xe1) /* LOOPZ */
CASE_W(0xe1) /* LOOPZ */
if (TEST_PREFIX_ADDR) {
if ((--reg_ecx) && get_ZF()) ADDIPFAST(Fetchbs());
else ADDIPFAST(1);
JumpCond16_b(--reg_ecx && get_ZF());
} else {
if ((--reg_cx) && get_ZF()) ADDIPFAST(Fetchbs());
else ADDIPFAST(1);
JumpCond16_b(--reg_cx && get_ZF());
}
break;
CASE_B(0xe2) /* LOOP */
CASE_W(0xe2) /* LOOP */
if (TEST_PREFIX_ADDR) {
if ((--reg_ecx)) ADDIPFAST(Fetchbs());
else ADDIPFAST(1);
JumpCond16_b(--reg_ecx);
} else {
if ((--reg_cx)) ADDIPFAST(Fetchbs());
else ADDIPFAST(1);
JumpCond16_b(--reg_cx);
}
break;
CASE_B(0xe3) /* JCXZ */
{
Bitu test;
if (TEST_PREFIX_ADDR) {
test=reg_ecx;
} else test=reg_cx;
if (!test) ADDIPFAST(Fetchbs());
else ADDIPFAST(1);
CASE_W(0xe3) /* JCXZ */
JumpCond16_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR]));
break;
CASE_B(0xe4) /* IN AL,Ib */
{
Bitu port=Fetchb();
if (CPU_IO_Exception(port,1)) RUNEXCEPTION();
reg_al=IO_ReadB(port);
break;
}
CASE_B(0xe4) /* IN AL,Ib */
reg_al=IO_ReadB(Fetchb());
break;
CASE_W(0xe5) /* IN AX,Ib */
reg_ax=IO_ReadW(Fetchb());
break;
{
Bitu port=Fetchb();
if (CPU_IO_Exception(port,2)) RUNEXCEPTION();
reg_al=IO_ReadW(port);
break;
}
CASE_B(0xe6) /* OUT Ib,AL */
IO_WriteB(Fetchb(),reg_al);
break;
{
Bitu port=Fetchb();
if (CPU_IO_Exception(port,1)) RUNEXCEPTION();
IO_WriteB(port,reg_al);
break;
}
CASE_W(0xe7) /* OUT Ib,AX */
IO_WriteW(Fetchb(),reg_ax);
break;
{
Bitu port=Fetchb();
if (CPU_IO_Exception(port,2)) RUNEXCEPTION();
IO_WriteW(port,reg_ax);
break;
}
CASE_W(0xe8) /* CALL Jw */
{
Bit16s newip=Fetchws();
Push_16((Bit16u)GETIP);
ADDIPw(newip);
break;
Bit16u addip=Fetchws();
SAVEIP;
Push_16(reg_eip);
reg_eip=(Bit16u)(reg_eip+addip);
continue;
}
CASE_W(0xe9) /* JMP Jw */
ADDIPw(Fetchws());
break;
{
Bit16u addip=Fetchws();
SAVEIP;
reg_eip=(Bit16u)(reg_eip+addip);
continue;
}
CASE_W(0xea) /* JMP Ap */
{
Bit16u newip=Fetchw();
Bit16u newcs=Fetchw();
LEAVECORE;
CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start);
goto decode_start;
FillFlags();
CPU_JMP(false,newcs,newip,GETIP);
continue;
}
CASE_W(0xeb) /* JMP Jb */
{
Bit16s addip=Fetchbs();
SAVEIP;
reg_eip=(Bit16u)(reg_eip+addip);
continue;
}
CASE_B(0xeb) /* JMP Jb */
ADDIPFAST(Fetchbs());break;
CASE_B(0xec) /* IN AL,DX */
reg_al=IO_Read(reg_dx);break;
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
reg_al=IO_ReadB(reg_dx);
break;
CASE_W(0xed) /* IN AX,DX */
reg_al=IO_Read(reg_dx);reg_ah=IO_Read(reg_dx+1);
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
reg_ax=IO_ReadW(reg_dx);
break;
CASE_B(0xee) /* OUT DX,AL */
IO_WriteB(reg_dx,reg_al);break;
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
IO_WriteB(reg_dx,reg_al);
break;
CASE_W(0xef) /* OUT DX,AX */
IO_WriteW(reg_dx,reg_ax);break;
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
IO_WriteW(reg_dx,reg_ax);
break;
CASE_B(0xf0) /* LOCK */
LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK");
break;
@ -954,8 +935,8 @@
DO_PREFIX_REP(true);
break;
CASE_B(0xf4) /* HLT */
LEAVECORE;
CPU_HLT(core.ip_lookup-core.op_start);
FillFlags();
CPU_HLT(GETIP);
return CBRET_NONE; //Needs to return for hlt cpu core
CASE_B(0xf5) /* CMC */
FillFlags();
@ -1058,20 +1039,10 @@
SETFLAGBIT(CF,true);
break;
CASE_B(0xfa) /* CLI */
if (cpu.pmode && (GETFLAG_IOPL<cpu.cpl)) {
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
CPU_Exception(13,0);
goto decode_start;
}
SETFLAGBIT(IF,false);
if (CPU_CLI()) RUNEXCEPTION();
break;
CASE_B(0xfb) /* STI */
if (cpu.pmode && !GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) {
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
CPU_Exception(13,0);
goto decode_start;
}
SETFLAGBIT(IF,true);
if (CPU_STI()) RUNEXCEPTION();
#if CPU_PIC_CHECK
if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
#endif
@ -1097,7 +1068,7 @@
case 0x07: /* CallBack */
{
Bitu cb=Fetchw();
LEAVECORE;
FillFlags();SAVEIP;
return cb;
}
default:
@ -1117,31 +1088,32 @@
RMEw(DECW);
break;
case 0x02: /* CALL Ev */
if (rm >= 0xc0 ) {GetEArw;Push_16((Bit16u)GETIP);SETIP(*earw);}
else {GetEAa;Push_16((Bit16u)GETIP);SETIP(LoadMw(eaa));}
break;
if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;}
else {GetEAa;reg_eip=LoadMw(eaa);}
Push_16(GETIP);
continue;
case 0x03: /* CALL Ep */
{
GetEAa;
Bit16u newip=LoadMw(eaa);
Bit16u newcs=LoadMw(eaa+2);
LEAVECORE;
CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start);
goto decode_start;
FillFlags();
CPU_CALL(false,newcs,newip,GETIP);
continue;
}
break;
case 0x04: /* JMP Ev */
if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);}
else {GetEAa;SETIP(LoadMw(eaa));}
break;
if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;}
else {GetEAa;reg_eip=LoadMw(eaa);}
continue;
case 0x05: /* JMP Ep */
{
GetEAa;
Bit16u newip=LoadMw(eaa);
Bit16u newcs=LoadMw(eaa+2);
LEAVECORE;
CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start);
goto decode_start;
FillFlags();
CPU_JMP(false,newcs,newip,GETIP);
continue;
}
break;
case 0x06: /* PUSH Ev */

View File

@ -17,21 +17,13 @@ static void DoString(STRING_OP type) {
Bitu count,count_left;
Bits add_index;
if (TEST_PREFIX_SEG) si_base=core.seg_prefix_base;
else si_base=SegBase(ds);
si_base=BaseDS;
di_base=SegBase(es);
if (TEST_PREFIX_ADDR) {
add_mask=0xFFFFFFFF;
si_index=reg_esi;
di_index=reg_edi;
count=reg_ecx;
} else {
add_mask=0xFFFF;
si_index=reg_si;
di_index=reg_di;
count=reg_cx;
}
if (!(TEST_PREFIX_REP)) {
add_mask=AddrMaskTable[core.prefixes & PREFIX_ADDR];
si_index=reg_esi & add_mask;
di_index=reg_edi & add_mask;
count=reg_ecx & add_mask;
if (!TEST_PREFIX_REP) {
count=1;
} else {
CPU_Cycles++;
@ -40,7 +32,7 @@ static void DoString(STRING_OP type) {
count_left=count-CPU_Cycles;
count=CPU_Cycles;
CPU_Cycles=0;
core.ip_lookup=core.op_start; //Reset IP to start of instruction
LOADIP; //RESET IP to the start
} else {
/* Won't interrupt scas and cmps instruction since they can interrupt themselves */
count_left=0;

View File

@ -9,66 +9,25 @@
* 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.
* 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.
*/
#define SETIP(_a_) (core.ip_lookup=SegBase(cs)+_a_)
#define GETIP (Bit32u)(core.ip_lookup-SegBase(cs))
#define SAVEIP {reg_eip=GETIP;}
#define LOADIP {core.ip_lookup=(SegBase(cs)+reg_eip);}
#define LEAVECORE \
SAVEIP; \
FillFlags();
#define LoadMbs(off) (Bit8s)(LoadMb(off))
#define LoadMws(off) (Bit16s)(LoadMw(off))
#define LoadMds(off) (Bit32s)(LoadMd(off))
static INLINE void ADDIPw(Bits add) {
SAVEIP;
reg_eip=(Bit16u)(reg_eip+add);
LOADIP;
}
#define LoadRb(reg) reg
#define LoadRw(reg) reg
#define LoadRd(reg) reg
static INLINE void ADDIPd(Bits add) {
SAVEIP;
reg_eip=(reg_eip+add);
LOADIP;
}
static INLINE void ADDIPFAST(Bits blah) {
// core.ip_lookup+=blah;
SAVEIP;
reg_eip=(reg_eip+blah);
LOADIP;
}
#define EXCEPTION(blah) \
{ \
Bit8u new_num=blah; \
core.ip_lookup=core.op_start; \
LEAVECORE; \
CPU_Exception(new_num); \
goto decode_start; \
}
static INLINE Bit8u Fetchb() {
Bit8u temp=LoadMb(core.ip_lookup);
core.ip_lookup+=1;
return temp;
}
static INLINE Bit16u Fetchw() {
Bit16u temp=LoadMw(core.ip_lookup);
core.ip_lookup+=2;
return temp;
}
static INLINE Bit32u Fetchd() {
Bit32u temp=LoadMd(core.ip_lookup);
core.ip_lookup+=4;
return temp;
}
#define SaveRb(reg,val) reg=val
#define SaveRw(reg,val) reg=val
#define SaveRd(reg,val) reg=val
static INLINE Bit8s Fetchbs() {
return Fetchb();
@ -81,68 +40,48 @@ static INLINE Bit32s Fetchds() {
return Fetchd();
}
#if 0
static INLINE void Push_16(Bit16u blah) {
reg_esp-=2;
SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
};
#define RUNEXCEPTION() { \
FillFlags(); \
CPU_Exception(cpu.exception.which,cpu.exception.error); \
continue; \
}
static INLINE void Push_32(Bit32u blah) {
reg_esp-=4;
SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
};
static INLINE Bit16u Pop_16() {
Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask));
reg_esp+=2;
return temp;
};
static INLINE Bit32u Pop_32() {
Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask));
reg_esp+=4;
return temp;
};
#else
#define Push_16 CPU_Push16
#define Push_32 CPU_Push32
#define Pop_16 CPU_Pop16
#define Pop_32 CPU_Pop32
#endif
#define EXCEPTION(blah) \
{ \
CPU_Exception(blah); \
continue; \
}
//TODO Could probably make all byte operands fast?
#define JumpCond16_b(blah) \
if (blah) { \
ADDIPw(Fetchbs()); \
} else { \
ADDIPFAST(1); \
}
#define JumpCond16_b(COND) { \
SAVEIP; \
if (COND) reg_ip+=Fetchbs(); \
reg_ip+=1; \
continue; \
}
#define JumpCond32_b(blah) \
if (blah) { \
ADDIPd(Fetchbs()); \
} else { \
ADDIPFAST(1); \
}
#define JumpCond16_w(COND) { \
SAVEIP; \
if (COND) reg_ip+=Fetchws(); \
reg_ip+=2; \
continue; \
}
#define JumpCond16_w(blah) \
if (blah) { \
ADDIPw(Fetchws()); \
} else { \
ADDIPFAST(2); \
}
#define JumpCond32_b(COND) { \
SAVEIP; \
if (COND) reg_eip+=Fetchbs(); \
reg_eip+=1; \
continue; \
}
#define JumpCond32_d(COND) { \
SAVEIP; \
if (COND) reg_eip+=Fetchds(); \
reg_eip+=4; \
continue; \
}
#define JumpCond32_d(blah) \
if (blah) { \
ADDIPd(Fetchds()); \
} else { \
ADDIPFAST(4); \
}
#define SETcc(cc) \
{ \

View File

@ -9,207 +9,137 @@
* 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.
* 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.
*/
typedef PhysPt (*GetEATable[256])(void);
typedef PhysPt (*EA_LookupHandler)(void);
/* The MOD/RM Decoder for EA for this decoder's addressing modes */
static PhysPt EA_16_00_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); }
static PhysPt EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); }
static PhysPt EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); }
static PhysPt EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); }
static PhysPt EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); }
static PhysPt EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); }
static PhysPt EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());}
static PhysPt EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); }
static PhysPt EA_16_00_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si); }
static PhysPt EA_16_01_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di); }
static PhysPt EA_16_02_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si); }
static PhysPt EA_16_03_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di); }
static PhysPt EA_16_04_n(void) { return BaseDS+(Bit16u)(reg_si); }
static PhysPt EA_16_05_n(void) { return BaseDS+(Bit16u)(reg_di); }
static PhysPt EA_16_06_n(void) { return BaseDS+(Bit16u)(Fetchw());}
static PhysPt EA_16_07_n(void) { return BaseDS+(Bit16u)(reg_bx); }
static PhysPt EA_16_40_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_41_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_42_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_43_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_44_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchbs()); }
static PhysPt EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); }
static PhysPt EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); }
static PhysPt EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchbs()); }
static PhysPt EA_16_40_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_41_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_42_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_43_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_44_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchbs()); }
static PhysPt EA_16_45_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchbs()); }
static PhysPt EA_16_46_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchbs()); }
static PhysPt EA_16_47_n(void) { return BaseDS+(Bit16u)(reg_bx+Fetchbs()); }
static PhysPt EA_16_80_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_81_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_82_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_83_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_84_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchws()); }
static PhysPt EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); }
static PhysPt EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); }
static PhysPt EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); }
static GetEATable GetEA_NONE={
/* 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
};
static PhysPt EA_16_00_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si); }
static PhysPt EA_16_01_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di); }
static PhysPt EA_16_02_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si); }
static PhysPt EA_16_03_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di); }
static PhysPt EA_16_04_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si); }
static PhysPt EA_16_05_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di); }
static PhysPt EA_16_06_s(void) { return core.seg_prefix_base+(Bit16u)(Fetchw()); }
static PhysPt EA_16_07_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx); }
static PhysPt EA_16_40_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_41_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_42_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
static PhysPt EA_16_43_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
static PhysPt EA_16_44_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchbs()); }
static PhysPt EA_16_45_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchbs()); }
static PhysPt EA_16_46_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchbs()); }
static PhysPt EA_16_47_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchbs()); }
static PhysPt EA_16_80_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_81_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_82_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_83_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_84_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchws()); }
static PhysPt EA_16_85_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchws()); }
static PhysPt EA_16_86_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchws()); }
static PhysPt EA_16_87_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchws()); }
static GetEATable GetEA_SEG={
/* 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
};
static PhysPt EA_16_80_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_81_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_82_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
static PhysPt EA_16_83_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
static PhysPt EA_16_84_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchws()); }
static PhysPt EA_16_85_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchws()); }
static PhysPt EA_16_86_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchws()); }
static PhysPt EA_16_87_n(void) { return BaseDS+(Bit16u)(reg_bx+Fetchws()); }
static Bit32u SIBZero=0;
static Bit32u * SIBIndex[8]= { &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&SIBZero,&reg_ebp,&reg_esi,&reg_edi };
INLINE PhysPt Sib(Bitu mode) {
static INLINE PhysPt Sib(Bitu mode) {
Bit8u sib=Fetchb();
PhysPt base;
switch (sib&7) {
case 0: /* EAX Base */
base=SegBase(ds)+reg_eax;break;
base=BaseDS+reg_eax;break;
case 1: /* ECX Base */
base=SegBase(ds)+reg_ecx;break;
base=BaseDS+reg_ecx;break;
case 2: /* EDX Base */
base=SegBase(ds)+reg_edx;break;
base=BaseDS+reg_edx;break;
case 3: /* EBX Base */
base=SegBase(ds)+reg_ebx;break;
base=BaseDS+reg_ebx;break;
case 4: /* ESP Base */
base=SegBase(ss)+reg_esp;break;
base=BaseSS+reg_esp;break;
case 5: /* #1 Base */
if (!mode) {
base=SegBase(ds)+Fetchd();break;
base=BaseDS+Fetchd();break;
} else {
base=SegBase(ss)+reg_ebp;break;
base=BaseSS+reg_ebp;break;
}
case 6: /* ESI Base */
base=SegBase(ds)+reg_esi;break;
base=BaseDS+reg_esi;break;
case 7: /* EDI Base */
base=SegBase(ds)+reg_edi;break;
base=BaseDS+reg_edi;break;
}
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
return base;
};
static PhysPt EA_32_00_n(void) { return SegBase(ds)+reg_eax; }
static PhysPt EA_32_01_n(void) { return SegBase(ds)+reg_ecx; }
static PhysPt EA_32_02_n(void) { return SegBase(ds)+reg_edx; }
static PhysPt EA_32_03_n(void) { return SegBase(ds)+reg_ebx; }
static PhysPt EA_32_00_n(void) { return BaseDS+reg_eax; }
static PhysPt EA_32_01_n(void) { return BaseDS+reg_ecx; }
static PhysPt EA_32_02_n(void) { return BaseDS+reg_edx; }
static PhysPt EA_32_03_n(void) { return BaseDS+reg_ebx; }
static PhysPt EA_32_04_n(void) { return Sib(0);}
static PhysPt EA_32_05_n(void) { return SegBase(ds)+Fetchd(); }
static PhysPt EA_32_06_n(void) { return SegBase(ds)+reg_esi; }
static PhysPt EA_32_07_n(void) { return SegBase(ds)+reg_edi; }
static PhysPt EA_32_05_n(void) { return BaseDS+Fetchd(); }
static PhysPt EA_32_06_n(void) { return BaseDS+reg_esi; }
static PhysPt EA_32_07_n(void) { return BaseDS+reg_edi; }
static PhysPt EA_32_40_n(void) { return SegBase(ds)+reg_eax+Fetchbs(); }
static PhysPt EA_32_41_n(void) { return SegBase(ds)+reg_ecx+Fetchbs(); }
static PhysPt EA_32_42_n(void) { return SegBase(ds)+reg_edx+Fetchbs(); }
static PhysPt EA_32_43_n(void) { return SegBase(ds)+reg_ebx+Fetchbs(); }
static PhysPt EA_32_40_n(void) { return BaseDS+reg_eax+Fetchbs(); }
static PhysPt EA_32_41_n(void) { return BaseDS+reg_ecx+Fetchbs(); }
static PhysPt EA_32_42_n(void) { return BaseDS+reg_edx+Fetchbs(); }
static PhysPt EA_32_43_n(void) { return BaseDS+reg_ebx+Fetchbs(); }
static PhysPt EA_32_44_n(void) { PhysPt temp=Sib(1);return temp+Fetchbs();}
//static PhysPt EA_32_44_n(void) { return Sib(1)+Fetchbs();}
static PhysPt EA_32_45_n(void) { return SegBase(ss)+reg_ebp+Fetchbs(); }
static PhysPt EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); }
static PhysPt EA_32_47_n(void) { return SegBase(ds)+reg_edi+Fetchbs(); }
static PhysPt EA_32_45_n(void) { return BaseSS+reg_ebp+Fetchbs(); }
static PhysPt EA_32_46_n(void) { return BaseDS+reg_esi+Fetchbs(); }
static PhysPt EA_32_47_n(void) { return BaseDS+reg_edi+Fetchbs(); }
static PhysPt EA_32_80_n(void) { return SegBase(ds)+reg_eax+Fetchds(); }
static PhysPt EA_32_81_n(void) { return SegBase(ds)+reg_ecx+Fetchds(); }
static PhysPt EA_32_82_n(void) { return SegBase(ds)+reg_edx+Fetchds(); }
static PhysPt EA_32_83_n(void) { return SegBase(ds)+reg_ebx+Fetchds(); }
static PhysPt EA_32_80_n(void) { return BaseDS+reg_eax+Fetchds(); }
static PhysPt EA_32_81_n(void) { return BaseDS+reg_ecx+Fetchds(); }
static PhysPt EA_32_82_n(void) { return BaseDS+reg_edx+Fetchds(); }
static PhysPt EA_32_83_n(void) { return BaseDS+reg_ebx+Fetchds(); }
static PhysPt EA_32_84_n(void) { PhysPt temp=Sib(2);return temp+Fetchds();}
//static PhysPt EA_32_84_n(void) { return Sib(2)+Fetchds();}
static PhysPt EA_32_85_n(void) { return SegBase(ss)+reg_ebp+Fetchds(); }
static PhysPt EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); }
static PhysPt EA_32_87_n(void) { return SegBase(ds)+reg_edi+Fetchds(); }
static PhysPt EA_32_85_n(void) { return BaseSS+reg_ebp+Fetchds(); }
static PhysPt EA_32_86_n(void) { return BaseDS+reg_esi+Fetchds(); }
static PhysPt EA_32_87_n(void) { return BaseDS+reg_edi+Fetchds(); }
static GetEATable GetEA_ADDR={
static GetEAHandler EATable[512]={
/* 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,
/* 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,
@ -244,113 +174,12 @@ static GetEATable GetEA_ADDR={
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
INLINE PhysPt Sib_s(Bitu mode) {
Bit8u sib=Fetchb();
PhysPt base;
switch (sib&7) {
case 0: /* EAX Base */
base=reg_eax;break;
case 1: /* ECX Base */
base=reg_ecx;break;
case 2: /* EDX Base */
base=reg_edx;break;
case 3: /* EBX Base */
base=reg_ebx;break;
case 4: /* ESP Base */
base=reg_esp;break;
case 5: /* #1 Base */
if (!mode) {
base=Fetchd();break;
} else {
base=reg_ebp;break;
}
case 6: /* ESI Base */
base=reg_esi;break;
case 7: /* EDI Base */
base=reg_edi;break;
}
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
return base;
};
static PhysPt EA_32_00_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax); }
static PhysPt EA_32_01_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx); }
static PhysPt EA_32_02_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx); }
static PhysPt EA_32_03_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx); }
static PhysPt EA_32_04_s(void) { return core.seg_prefix_base+(Bit32u)(Sib_s(0));}
static PhysPt EA_32_05_s(void) { return core.seg_prefix_base+(Bit32u)(Fetchd()); }
static PhysPt EA_32_06_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi); }
static PhysPt EA_32_07_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi); }
static PhysPt EA_32_40_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchbs()); }
static PhysPt EA_32_41_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchbs()); }
static PhysPt EA_32_42_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchbs()); }
static PhysPt EA_32_43_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchbs()); }
static PhysPt EA_32_44_s(void) { PhysPt temp=Sib_s(1);return core.seg_prefix_base+(Bit32u)(temp+Fetchbs());}
static PhysPt EA_32_45_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchbs()); }
static PhysPt EA_32_46_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchbs()); }
static PhysPt EA_32_47_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchbs()); }
static PhysPt EA_32_80_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchds()); }
static PhysPt EA_32_81_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchds()); }
static PhysPt EA_32_82_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchds()); }
static PhysPt EA_32_83_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchds()); }
static PhysPt EA_32_84_s(void) { PhysPt temp=Sib_s(2);return core.seg_prefix_base+(Bit32u)(temp+Fetchds());}
static PhysPt EA_32_85_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchds()); }
static PhysPt EA_32_86_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchds()); }
static PhysPt EA_32_87_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchds()); }
static GetEATable GetEA_SEG_ADDR={
/* 00 */
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
/* 01 */
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
/* 10 */
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
/* 11 These are illegal so make em 0 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#define GetEADirect \
PhysPt eaa; \
if (TEST_PREFIX_SEG) { \
if (TEST_PREFIX_ADDR) { \
eaa=core.seg_prefix_base+Fetchd(); \
} else { \
eaa=core.seg_prefix_base+Fetchw(); \
} \
} else { \
if (TEST_PREFIX_ADDR) { \
eaa=SegBase(ds)+Fetchd(); \
} else { \
eaa=SegBase(ds)+Fetchw(); \
} \
}
#define GetEADirect \
PhysPt eaa; \
if (TEST_PREFIX_ADDR) { \
eaa=BaseDS+Fetchd(); \
} else { \
eaa=BaseDS+Fetchw(); \
} \

203
src/cpu/core_simple.cpp Normal file
View File

@ -0,0 +1,203 @@
/*
* Copyright (C) 2002-2004 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 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 "dosbox.h"
#include "mem.h"
#include "cpu.h"
#include "lazyflags.h"
#include "inout.h"
#include "callback.h"
#include "pic.h"
#include "fpu.h"
#if C_DEBUG
#include "debug.h"
#endif
#include "paging.h"
#define SegBase(c) SegPhys(c)
#define LoadMb(off) mem_readb(off)
#define LoadMw(off) mem_readw(off)
#define LoadMd(off) mem_readd(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)
extern Bitu cycle_count;
#if C_FPU
#define CPU_FPU 1 //Enable FPU escape instructions
#endif
#define CPU_PIC_CHECK 1
#define CPU_TRAP_CHECK 1
#define OPCODE_NONE 0x000
#define OPCODE_0F 0x100
#define OPCODE_SIZE 0x200
#define PREFIX_ADDR 0x1
#define PREFIX_REP 0x2
#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR)
#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP)
#define DO_PREFIX_SEG(_SEG) \
BaseDS=SegBase(_SEG); \
BaseSS=SegBase(_SEG); \
goto restart_opcode;
#define DO_PREFIX_ADDR() \
core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \
(cpu.code.big ^ PREFIX_ADDR); \
core.ea_table=&EATable[(core.prefixes&1) * 256]; \
goto restart_opcode;
#define DO_PREFIX_REP(_ZERO) \
core.prefixes|=PREFIX_REP; \
core.rep_zero=_ZERO; \
goto restart_opcode;
typedef PhysPt (*GetEAHandler)(void);
static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff};
static struct {
Bitu opcode_index;
HostPt cseip;
PhysPt base_ds,base_ss;
bool rep_zero;
Bitu prefixes;
GetEAHandler * ea_table;
struct {
bool skip;
} trap;
} core;
#define GETIP (core.cseip-SegBase(cs)-MemBase)
#define SAVEIP reg_eip=GETIP;
#define LOADIP core.cseip=(MemBase+SegBase(cs)+reg_eip);
#define SegBase(c) SegPhys(c)
#define BaseDS core.base_ds
#define BaseSS core.base_ss
static INLINE Bit8u Fetchb() {
Bit8u temp=host_readb(core.cseip);
core.cseip+=1;
return temp;
}
static INLINE Bit16u Fetchw() {
Bit16u temp=host_readw(core.cseip);
core.cseip+=2;
return temp;
}
static INLINE Bit32u Fetchd() {
Bit32u temp=host_readd(core.cseip);
core.cseip+=4;
return temp;
}
#define Push_16 CPU_Push16
#define Push_32 CPU_Push32
#define Pop_16 CPU_Pop16
#define Pop_32 CPU_Pop32
#include "instructions.h"
#include "core_normal/support.h"
#include "core_normal/string.h"
#define EALookupTable (core.ea_table)
Bits CPU_Core_Simple_Run(void) {
while (CPU_Cycles-->0) {
LOADIP;
core.opcode_index=cpu.code.big*0x200;
core.prefixes=cpu.code.big;
core.ea_table=&EATable[cpu.code.big*256];
BaseDS=SegBase(ds);
BaseSS=SegBase(ss);
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) {
FillFlags();
return debugCallback;
};
#endif
cycle_count++;
#endif
restart_opcode:
switch (core.opcode_index+Fetchb()) {
#include "core_normal/prefix_none.h"
#include "core_normal/prefix_0f.h"
#include "core_normal/prefix_66.h"
#include "core_normal/prefix_66_0f.h"
default:
illegal_opcode:
#if C_DEBUG
{
Bitu len=(GETIP-reg_eip);
LOADIP;
if (len>16) len=16;
char tempcode[16*2+1];char * writecode=tempcode;
for (;len>0;len--) {
// sprintf(writecode,"%X",mem_readb(core.cseip++));
writecode+=2;
}
LOG(LOG_CPU,LOG_ERROR)("Illegal/Unhandled opcode %s",tempcode);
}
#endif
CPU_Exception(6,0);
continue;
}
SAVEIP;
}
FillFlags();
return CBRET_NONE;
decode_end:
SAVEIP;
FillFlags();
return CBRET_NONE;
}
Bits CPU_Core_Simple_Trap_Run(void) {
Bits oldCycles = CPU_Cycles;
CPU_Cycles = 1;
core.trap.skip=false;
Bits ret=CPU_Core_Normal_Run();
if (!core.trap.skip) CPU_SW_Interrupt(1,reg_eip);
CPU_Cycles = oldCycles-1;
cpudecoder = &CPU_Core_Normal_Run;
return ret;
}
void CPU_Core_Simple_Init(void) {
}

View File

@ -9,21 +9,21 @@
* 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.
* 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.
*/
/* $Id: cpu.cpp,v 1.53 2004/01/14 17:09:41 harekiet Exp $ */
/* $Id: cpu.cpp,v 1.61 2004/08/23 12:17:29 harekiet Exp $ */
#include <assert.h>
#include "dosbox.h"
#include "cpu.h"
#include "memory.h"
#include "debug.h"
#include "keyboard.h"
#include "mapper.h"
#include "setup.h"
#include "paging.h"
#include "support.h"
@ -46,12 +46,9 @@ Bits CPU_CycleUp = 0;
Bits CPU_CycleDown = 0;
CPU_Decoder * cpudecoder;
static struct {
Bitu which,errorcode;
} exception;
void CPU_Core_Full_Init(void);
void CPU_Core_Normal_Init(void);
void CPU_Core_Simple_Init(void);
void CPU_Core_Dyn_X86_Init(void);
void CPU_Push16(Bitu value) {
@ -91,6 +88,48 @@ void CPU_SetFlags(Bitu word,Bitu mask) {
cpu.direction=1-((reg_flags & FLAG_DF) >> 9);
}
bool CPU_PrepareException(Bitu which,Bitu error) {
cpu.exception.which=which;
cpu.exception.error=error;
return true;
}
bool CPU_CLI(void) {
if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) || (GETFLAG(VM) && (GETFLAG_IOPL<3)))) {
return CPU_PrepareException(13,0);
} else {
SETFLAGBIT(IF,false);
return false;
}
}
bool CPU_STI(void) {
if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) || (GETFLAG(VM) && (GETFLAG_IOPL<3)))) {
return CPU_PrepareException(13,0);
} else {
SETFLAGBIT(IF,true);
return false;
}
}
bool CPU_POPF(Bitu use32) {
if ((reg_flags & FLAG_VM) && (GETFLAG(IOPL)!=FLAG_IOPL))
return CPU_PrepareException(13,0);
if (use32)
CPU_SetFlagsd(CPU_Pop32());
else CPU_SetFlagsw(CPU_Pop16());
return false;
}
bool CPU_PUSHF(Bitu use32) {
if ((reg_flags & FLAG_VM) && (GETFLAG(IOPL)!=FLAG_IOPL))
return CPU_PrepareException(13,0);
if (use32)
CPU_Push32(reg_flags);
else CPU_Push16(reg_flags);
return false;
}
class TaskStateSegment {
public:
TaskStateSegment() {
@ -148,7 +187,7 @@ enum TSwitchType {
TSwitch_JMP,TSwitch_CALL_INT,TSwitch_IRET
};
bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype) {
bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype,Bitu old_eip) {
TaskStateSegment new_tss;
if (!new_tss.SetSelector(new_tss_selector))
E_Exit("Illegal TSS for switch");
@ -163,7 +202,7 @@ bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype) {
Bitu new_ldt;
if (cpu_tss.is386) {
mem_writed(cpu_tss.base+offsetof(TSS_32,eflags),reg_flags);
mem_writed(cpu_tss.base+offsetof(TSS_32,eip),reg_eip);
mem_writed(cpu_tss.base+offsetof(TSS_32,eip),old_eip);
mem_writed(cpu_tss.base+offsetof(TSS_32,eax),reg_eax);
mem_writed(cpu_tss.base+offsetof(TSS_32,ecx),reg_ecx);
@ -268,23 +307,31 @@ doconforming:
return true;
}
void CPU_StartException(void) {
CPU_Interrupt(cpu.exception.which,CPU_INT_EXCEPTION | ((cpu.exception.which>=8) ? CPU_INT_HAS_ERROR : 0));
}
void CPU_SetupException(Bitu which,Bitu error) {
cpu.exception.which=which;
cpu.exception.error=error;
bool CPU_IO_Exception(Bitu port,Bitu size) {
if (cpu.pmode && ((GETFLAG_IOPL<cpu.cpl) || GETFLAG(VM))) {
if (!cpu_tss.is386) goto doexception;
PhysPt where=cpu_tss.base+0x66;
Bitu ofs=mem_readw(where);
if (ofs>cpu_tss.limit) goto doexception;
where=cpu_tss.base+ofs+(port/8);
Bitu map=mem_readw(where);
Bitu mask=(0xffff>>(16-size)) << (port&7);
if (map & mask) goto doexception;
}
return false;
doexception:
LOG_MSG("Exception");
return CPU_PrepareException(13,0);
}
void CPU_Exception(Bitu which,Bitu error ) {
// LOG_MSG("Exception %d CS:%X IP:%X FLAGS:%X",num,SegValue(cs),reg_eip,reg_flags);
CPU_SetupException(which,error);
CPU_StartException();
// LOG_MSG("Exception %d error %x",which,error);
cpu.exception.error=error;
CPU_Interrupt(which,CPU_INT_EXCEPTION | ((which>=8) ? CPU_INT_HAS_ERROR : 0),reg_eip);
}
Bit8u lastint;
void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) {
lastint=num;
#if C_DEBUG
switch (num) {
@ -302,10 +349,10 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
};
#endif
if (!cpu.pmode) {
/* Save everything on a 16-bit stack */
/* Save everything on a 16-bit stack */
CPU_Push16(reg_flags & 0xffff);
CPU_Push16(SegValue(cs));
CPU_Push16(reg_ip);
CPU_Push16(oldeip);
SETFLAGBIT(IF,false);
SETFLAGBIT(TF,false);
/* Get the new CS:IP from vector table */
@ -323,7 +370,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE)) {
// LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12);
if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
reg_eip-=opLen;
CPU_Exception(13,0);
return;
}
@ -332,7 +378,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
//TODO Check for software interrupt and check gate's dpl<cpl
cpu.idt.GetDescriptor(num<<3,gate);
if (type&CPU_INT_SOFTWARE && gate.DPL()<cpu.cpl) {
reg_eip-=opLen;
CPU_Exception(13,num*8+2);
return;
}
@ -345,7 +390,7 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
Bitu gate_off=gate.GetOffset();
cpu.gdt.GetDescriptor(gate_sel,cs_desc);
Bitu cs_dpl=cs_desc.DPL();
if (cs_dpl>cpu.cpl) E_Exit("Interrupt to higher privilege");
if (cs_dpl>cpu.cpl) E_Exit("Interrupt to higher privilege");
switch (cs_desc.Type()) {
case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA:
case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA:
@ -397,12 +442,12 @@ do_interrupt:
if (gate.Type() & 0x8) { /* 32-bit Gate */
CPU_Push32(reg_flags);
CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip);
CPU_Push32(oldeip);
if (type & CPU_INT_HAS_ERROR) CPU_Push32(cpu.exception.error);
} else { /* 16-bit gate */
CPU_Push16(reg_flags & 0xffff);
CPU_Push16(SegValue(cs));
CPU_Push16(reg_ip);
CPU_Push16(oldeip);
if (type & CPU_INT_HAS_ERROR) CPU_Push16(cpu.exception.error);
}
break;
@ -410,7 +455,7 @@ do_interrupt:
E_Exit("INT:Gate Selector points to illegal descriptor with type %x",cs_desc.Type());
}
if (!(gate.Type()&1))
SETFLAGBIT(IF,false);
SETFLAGBIT(IF,false);
SETFLAGBIT(TF,false);
SETFLAGBIT(NT,false);
SETFLAGBIT(VM,false);
@ -422,7 +467,7 @@ do_interrupt:
return;
}
case DESC_TASK_GATE:
CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT);
CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT,oldeip);
if (type & CPU_INT_HAS_ERROR) {
//TODO Be sure about this, seems somewhat unclear
if (cpu_tss.is386) CPU_Push32(cpu.exception.error);
@ -437,7 +482,7 @@ do_interrupt:
return ; // make compiler happy
}
void CPU_IRET(bool use32) {
void CPU_IRET(bool use32,Bitu oldeip) {
if (!cpu.pmode) { /* RealMode IRET */
realmode_iret:
if (use32) {
@ -454,7 +499,6 @@ realmode_iret:
} else { /* Protected mode IRET */
if (reg_flags & FLAG_VM) {
if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
reg_eip--;
CPU_Exception(13,0);
return;
} else goto realmode_iret;
@ -466,7 +510,7 @@ realmode_iret:
if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set");
if (!cpu_tss.IsValid()) E_Exit("TASK Iret without valid TSS");
Bitu back_link=cpu_tss.Get_back();
CPU_SwitchTask(back_link,TSwitch_IRET);
CPU_SwitchTask(back_link,TSwitch_IRET,oldeip);
return;
}
Bitu n_cs_sel,n_eip,n_flags;
@ -506,7 +550,7 @@ realmode_iret:
Bitu n_cs_rpl=n_cs_sel & 3;
Descriptor n_cs_desc;
cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc);
if (n_cs_rpl<cpu.cpl)
if (n_cs_rpl<cpu.cpl)
E_Exit("IRET to lower privilege");
if (n_cs_rpl==cpu.cpl) {
/* Return to same level */
@ -526,6 +570,7 @@ realmode_iret:
cpu.code.big=n_cs_desc.Big()>0;
Segs.val[cs]=n_cs_sel;
reg_eip=n_eip;
CPU_SetFlagsd(n_flags);
LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big);
} else {
@ -545,9 +590,11 @@ realmode_iret:
Segs.phys[cs]=n_cs_desc.GetBase();
cpu.code.big=n_cs_desc.Big()>0;
Segs.val[cs]=n_cs_sel;
CPU_SetFlagsd(n_flags);
cpu.cpl=n_cs_rpl;
reg_eip=n_eip;
CPU_SetFlagsd(n_flags);
Bitu n_ss,n_esp;
if (use32) {
n_esp=CPU_Pop32();
@ -562,14 +609,15 @@ realmode_iret:
} else {
reg_sp=n_esp;
}
//TODO Maybe validate other segments, but why would anyone use them?
LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:X big %d",n_cs_sel,n_eip,cpu.code.big);
LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big);
}
return;
}
}
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip) {
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
if (!use32) {
reg_eip=offset&0xffff;
@ -584,7 +632,6 @@ void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
Descriptor desc;
cpu.gdt.GetDescriptor(selector,desc);
if (!desc.saved.seg.p) {
reg_eip -= opLen;
CPU_Exception(0x0B,selector & 0xfffc);
return;
}
@ -592,8 +639,7 @@ void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA:
case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA:
if (rpl>cpu.cpl) E_Exit("JMP:NC:RPL>CPL");
if (rpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL");
cpu.cpl=desc.DPL();
if (cpu.cpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL");
LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:NC to %X:%X big %d",selector,offset,desc.Big());
goto CODE_jmp;
case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA:
@ -610,7 +656,7 @@ CODE_jmp:
if (desc.DPL()<cpu.cpl) E_Exit("JMP:TSS:dpl<cpl");
if (desc.DPL()<rpl) E_Exit("JMP:TSS:dpl<rpl");
LOG(LOG_CPU,LOG_NORMAL)("JMP:TSS to %X",selector);
CPU_SwitchTask(selector,TSwitch_JMP);
CPU_SwitchTask(selector,TSwitch_JMP,oldeip);
break;
default:
E_Exit("JMP Illegal descriptor type %X",desc.Type());
@ -621,15 +667,15 @@ CODE_jmp:
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip) {
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
if (!use32) {
CPU_Push16(SegValue(cs));
CPU_Push16(reg_ip);
CPU_Push16(oldeip);
reg_eip=offset&0xffff;
} else {
CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip);
CPU_Push32(oldeip);
reg_eip=offset;
}
cpu.code.big=false;
@ -640,7 +686,6 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
Bitu rpl=selector & 3;
cpu.gdt.GetDescriptor(selector,call);
if (!call.saved.seg.p) {
reg_eip -= opLen;
CPU_Exception(0x0B,selector & 0xfffc);
return;
}
@ -659,11 +704,11 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
call_code:
if (!use32) {
CPU_Push16(SegValue(cs));
CPU_Push16(reg_ip);
CPU_Push16(oldeip);
reg_eip=offset & 0xffff;
} else {
CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip);
CPU_Push32(oldeip);
reg_eip=offset;
}
Segs.phys[cs]=call.GetBase();
@ -679,7 +724,6 @@ call_code:
Bitu n_cs_sel=call.GetSelector();
if (!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc)) E_Exit("Call:Gate:Invalid CS selector.");
if (!n_cs_desc.saved.seg.p) {
reg_eip -= opLen;
CPU_Exception(0x0B,selector & 0xfffc);
return;
}
@ -709,19 +753,22 @@ call_code:
if (call.Type()==DESC_386_CALL_GATE) {
CPU_Push32(o_ss); //save old stack
CPU_Push32(o_esp);
for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++)
CPU_Push32(mem_readd(o_stack+i*4));
if (call.saved.gate.paramcount&31)
for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--)
CPU_Push32(mem_readd(o_stack+i*4));
CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip);
CPU_Push32(oldeip);
} else {
CPU_Push16(o_ss); //save old stack
CPU_Push16(o_esp);
for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++)
CPU_Push16(mem_readw(o_stack+i*2));
if (call.saved.gate.paramcount&31)
for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--)
CPU_Push16(mem_readw(o_stack+i*2));
CPU_Push16(SegValue(cs));
CPU_Push16(reg_eip);
CPU_Push16(oldeip);
}
cpu.cpl = n_cs_desc.DPL();
/* Switch to new CS:EIP */
Segs.phys[cs] = n_cs_desc.GetBase();
Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl;
@ -742,7 +789,7 @@ call_gate_same_privilege:
if (call.DPL()<cpu.cpl) E_Exit("CALL:TSS:dpl<cpl");
if (call.DPL()<rpl) E_Exit("CALL:TSS:dpl<rpl");
LOG(LOG_CPU,LOG_NORMAL)("CALL:TSS to %X",selector);
CPU_SwitchTask(selector,TSwitch_CALL_INT);
CPU_SwitchTask(selector,TSwitch_CALL_INT,oldeip);
break;
default:
E_Exit("CALL:Descriptor type %x unsupported",call.Type());
@ -753,7 +800,7 @@ call_gate_same_privilege:
}
void CPU_RET(bool use32,Bitu bytes,Bitu opLen) {
void CPU_RET(bool use32,Bitu bytes,Bitu oldeip) {
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
Bitu new_ip,new_cs;
if (!use32) {
@ -775,11 +822,13 @@ void CPU_RET(bool use32,Bitu bytes,Bitu opLen) {
Descriptor desc;
Bitu rpl=selector & 3;
if (rpl<cpu.cpl) E_Exit("RET to lower privilege");
if (rpl<cpu.cpl) {
CPU_Exception(0x0B,selector & 0xfffc);
return;
}
cpu.gdt.GetDescriptor(selector,desc);
if (!desc.saved.seg.p) {
reg_eip -= opLen;
CPU_Exception(0x0B,selector & 0xfffc);
return;
};
@ -820,7 +869,7 @@ RET_same_level:
return;
} else {
/* Return to outer level */
if (bytes) E_Exit("RETF outeer level with immediate value");
if (bytes) E_Exit("RETF outer level with immediate value");
Bitu n_esp,n_ss;
if (use32) {
n_esp = CPU_Pop32();
@ -830,16 +879,19 @@ RET_same_level:
n_ss = CPU_Pop16();
}
cpu.cpl = rpl;
CPU_SetSegGeneral(ss,n_ss);
if (cpu.stack.big) {
reg_esp = n_esp;
} else {
reg_sp = n_esp;
}
Segs.phys[cs]=desc.GetBase();
cpu.code.big=desc.Big()>0;
Segs.val[cs]=selector;
Segs.val[cs]=(selector&0xfffc) | cpu.cpl;
reg_eip=offset;
// LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL());
return;
}
@ -899,9 +951,8 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
case 0:
{
Bitu changed=cpu.cr0 ^ value;
if (!changed) return true;
if (!changed) return false;
cpu.cr0=value;
//TODO Maybe always first change to core_full for a change to cr0
if (value & CR0_PROTECTION) {
cpu.pmode=true;
LOG(LOG_CPU,LOG_NORMAL)("Protected mode");
@ -911,7 +962,7 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
PAGING_Enable(false);
LOG(LOG_CPU,LOG_NORMAL)("Real mode");
}
return false; //Only changes with next CS change
break;
}
case 2:
paging.cr2=value;
@ -946,11 +997,12 @@ void CPU_SMSW(Bitu & word) {
word=cpu.cr0;
}
bool CPU_LMSW(Bitu word) {
Bitu CPU_LMSW(Bitu word) {
word&=0xf;
if (cpu.cr0 & 1) word|=1;
word|=(cpu.cr0&0xfffffff0);
return CPU_SET_CRX(0,word);
CPU_SET_CRX(0,word);
return false;
}
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
@ -964,8 +1016,11 @@ void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
}
void CPU_LAR(Bitu selector,Bitu & ar) {
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
}
Descriptor desc;Bitu rpl=selector & 3;
ar=0;
if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false);
return;
@ -974,16 +1029,20 @@ void CPU_LAR(Bitu selector,Bitu & ar) {
case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA:
case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA:
break;
case DESC_286_INT_GATE: case DESC_286_TRAP_GATE: {
case DESC_386_INT_GATE: case DESC_386_TRAP_GATE:
SETFLAGBIT(ZF,false);
return;
}
case DESC_LDT:
case DESC_TASK_GATE:
case DESC_286_TSS_A: case DESC_286_TSS_B:
case DESC_286_INT_GATE: case DESC_286_TRAP_GATE:
case DESC_286_CALL_GATE:
case DESC_386_TSS_A: case DESC_386_TSS_B:
case DESC_386_INT_GATE: case DESC_386_TRAP_GATE:
case DESC_386_CALL_GATE:
@ -1008,8 +1067,11 @@ void CPU_LAR(Bitu selector,Bitu & ar) {
}
void CPU_LSL(Bitu selector,Bitu & limit) {
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
}
Descriptor desc;Bitu rpl=selector & 3;
limit=0;
if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false);
return;
@ -1018,7 +1080,7 @@ void CPU_LSL(Bitu selector,Bitu & limit) {
case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA:
case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA:
break;
case DESC_LDT:
case DESC_286_TSS_A:
case DESC_286_TSS_B:
@ -1047,6 +1109,10 @@ void CPU_LSL(Bitu selector,Bitu & limit) {
}
void CPU_VERR(Bitu selector) {
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
}
Descriptor desc;Bitu rpl=selector & 3;
if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false);
@ -1075,6 +1141,10 @@ void CPU_VERR(Bitu selector) {
}
void CPU_VERW(Bitu selector) {
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
}
Descriptor desc;Bitu rpl=selector & 3;
if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false);
@ -1113,13 +1183,11 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) {
if (!desc.saved.seg.p) {
if (seg==ss) E_Exit("CPU_SetSegGeneral: Stack segment not present.");
// Throw Exception 0x0B - Segment not present
CPU_SetupException(0x0B,value & 0xfffc);
return true;
return CPU_PrepareException(0x0B,value & 0xfffc);
} else if (seg==ss) {
// Stack segment loaded with illegal segment ?
if ((desc.saved.seg.type<DESC_DATA_EU_RO_NA) || (desc.saved.seg.type>DESC_DATA_ED_RW_A)) {
CPU_SetupException(0x0D,value & 0xfffc);
return true;
return CPU_PrepareException(0x0D,value & 0xfffc);
}
}
}
@ -1138,6 +1206,14 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) {
}
}
bool CPU_PopSeg(SegNames seg,bool use32) {
Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask));
if (CPU_SetSegGeneral(seg,val)) return true;
Bitu addsp=2 << use32;
reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+addsp)&cpu.stack.mask);
return false;
}
void CPU_CPUID(void) {
switch (reg_eax) {
case 0: /* Vendor ID String and maximum level? */
@ -1168,12 +1244,12 @@ static Bits HLT_Decode(void) {
return 0;
}
void CPU_HLT(Bitu opLen) {
void CPU_HLT(Bitu oldeip) {
if (cpu.cpl) {
reg_eip-=opLen;
CPU_Exception(13,0);
return;
}
reg_eip=oldeip;
CPU_Cycles=0;
cpu.hlt.cs=SegValue(cs);
cpu.hlt.eip=reg_eip;
@ -1182,8 +1258,40 @@ void CPU_HLT(Bitu opLen) {
return;
}
void CPU_ENTER(bool use32,Bitu bytes,Bitu level) {
level&=0x1f;
Bitu sp_index=reg_esp&cpu.stack.mask;
Bitu bp_index=reg_ebp&cpu.stack.mask;
if (!use32) {
sp_index-=2;
mem_writew(SegPhys(ss)+sp_index,reg_bp);
reg_bp=(Bit16u)(reg_esp-2);
if (level) {
for (Bitu i=1;i<level;i++) {
sp_index-=2;bp_index-=2;
mem_writew(SegPhys(ss)+sp_index,mem_readw(SegPhys(ss)+bp_index));
}
sp_index-=2;
mem_writew(SegPhys(ss)+sp_index,reg_bp);
}
} else {
sp_index-=4;
mem_writed(SegPhys(ss)+sp_index,reg_ebp);
reg_ebp=(reg_esp-4);
if (level) {
for (Bitu i=1;i<level;i++) {
sp_index-=4;bp_index-=4;
mem_writed(SegPhys(ss)+sp_index,mem_readd(SegPhys(ss)+bp_index));
}
sp_index-=4;
mem_writed(SegPhys(ss)+sp_index,reg_ebp);
}
}
sp_index-=bytes;
reg_esp=(reg_esp&~cpu.stack.mask)|((sp_index)&cpu.stack.mask);
}
extern void GFX_SetTitle(Bits cycles ,Bits frameskip);
extern void GFX_SetTitle(Bits cycles ,Bits frameskip,bool paused);
static void CPU_CycleIncrease(void) {
Bits old_cycles=CPU_CycleMax;
if(CPU_CycleUp < 100){
@ -1195,7 +1303,7 @@ static void CPU_CycleIncrease(void) {
CPU_CycleLeft=0;CPU_Cycles=0;
if (CPU_CycleMax==old_cycles) CPU_CycleMax++;
LOG_MSG("CPU:%d cycles",CPU_CycleMax);
GFX_SetTitle(CPU_CycleMax,-1);
GFX_SetTitle(CPU_CycleMax,-1,false);
}
static void CPU_CycleDecrease(void) {
@ -1207,10 +1315,9 @@ static void CPU_CycleDecrease(void) {
CPU_CycleLeft=0;CPU_Cycles=0;
if (CPU_CycleMax <= 0) CPU_CycleMax=1;
LOG_MSG("CPU:%d cycles",CPU_CycleMax);
GFX_SetTitle(CPU_CycleMax,-1);
GFX_SetTitle(CPU_CycleMax,-1,false);
}
void CPU_Init(Section* sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
reg_eax=0;
@ -1240,14 +1347,13 @@ void CPU_Init(Section* sec) {
/* Init the cpu cores */
CPU_Core_Normal_Init();
CPU_Core_Simple_Init();
CPU_Core_Full_Init();
#if (C_DYNAMIC_X86)
CPU_Core_Dyn_X86_Init();
#endif
KEYBOARD_AddEvent(KBD_f11,KBD_MOD_CTRL,CPU_CycleDecrease);
KEYBOARD_AddEvent(KBD_f12,KBD_MOD_CTRL,CPU_CycleIncrease);
MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles");
MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles");
CPU_Cycles=0;
CPU_CycleMax=section->Get_int("cycles");;
CPU_CycleUp=section->Get_int("cycleup");
@ -1256,6 +1362,8 @@ void CPU_Init(Section* sec) {
cpudecoder=&CPU_Core_Normal_Run;
if (!strcasecmp(core,"normal")) {
cpudecoder=&CPU_Core_Normal_Run;
} else if (!strcasecmp(core,"simple")) {
cpudecoder=&CPU_Core_Simple_Run;
} else if (!strcasecmp(core,"full")) {
cpudecoder=&CPU_Core_Full_Run;
}
@ -1267,12 +1375,12 @@ void CPU_Init(Section* sec) {
else {
LOG_MSG("CPU:Unknown core type %s, switcing back to normal.",core);
}
CPU_JMP(false,0,0); //Setup the first cpu core
CPU_JMP(false,0,0,0); //Setup the first cpu core
if (!CPU_CycleMax) CPU_CycleMax = 2500;
if(!CPU_CycleUp) CPU_CycleUp = 500;
if(!CPU_CycleDown) CPU_CycleDown = 20;
CPU_CycleLeft=0;
GFX_SetTitle(CPU_CycleMax,-1);
GFX_SetTitle(CPU_CycleMax,-1,false);
}

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -548,7 +548,7 @@
}
#define MULB(op1,load,save) \
lflags.type=t_MUL; \
FillFlags(); \
reg_ax=reg_al*load(op1); \
if (reg_ax & 0xff00) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
@ -558,10 +558,10 @@
#define MULW(op1,load,save) \
{ \
FillFlags(); \
Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \
reg_ax=(Bit16u)(tempu); \
reg_dx=(Bit16u)(tempu >> 16); \
lflags.type=t_MUL; \
if (reg_dx) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
} else { \
@ -571,10 +571,10 @@
#define MULD(op1,load,save) \
{ \
FillFlags(); \
Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \
reg_eax=(Bit32u)(tempu); \
reg_edx=(Bit32u)(tempu >> 32); \
lflags.type=t_MUL; \
if (reg_edx) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
} else { \
@ -651,7 +651,7 @@
#define IMULB(op1,load,save) \
{ \
lflags.type=t_MUL; \
FillFlags(); \
reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \
if ((reg_ax & 0xff80)==0xff80 || \
(reg_ax & 0xff80)==0x0000) { \
@ -664,10 +664,10 @@
#define IMULW(op1,load,save) \
{ \
FillFlags(); \
Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \
reg_ax=(Bit16s)(temps); \
reg_dx=(Bit16s)(temps >> 16); \
lflags.type=t_MUL; \
if (((temps & 0xffff8000)==0xffff8000 || \
(temps & 0xffff8000)==0x0000)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
@ -678,11 +678,11 @@
#define IMULD(op1,load,save) \
{ \
FillFlags(); \
Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \
((Bit64s)((Bit32s)(load(op1)))); \
reg_eax=(Bit32u)(temps); \
reg_edx=(Bit32u)(temps >> 32); \
lflags.type=t_MUL; \
if ((reg_edx==0xffffffff) && \
(reg_eax & 0x80000000) ) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
@ -696,10 +696,10 @@
#define DIMULW(op1,op2,op3,load,save) \
{ \
FillFlags(); \
Bits res; \
res=((Bit16s)op2) * ((Bit16s)op3); \
save(op1,res & 0xffff); \
lflags.type=t_MUL; \
if ((res> -32768) && (res<32767)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
} else { \
@ -709,9 +709,9 @@
#define DIMULD(op1,op2,op3,load,save) \
{ \
FillFlags(); \
Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \
save(op1,(Bit32s)res); \
lflags.type=t_MUL; \
if ((res>-((Bit64s)(2147483647)+1)) && \
(res<(Bit64s)2147483647)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -93,7 +93,7 @@ static Bits PageFaultCore(void) {
if (!pf_queue.used) E_Exit("PF Core without PF");
PF_Entry * entry=&pf_queue.entries[pf_queue.used-1];
X86PageEntry pentry;
pentry.load=MEM_PhysReadD(entry->page_addr);
pentry.load=phys_readd(entry->page_addr);
if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip)
return -1;
return 0;
@ -102,6 +102,8 @@ static Bits PageFaultCore(void) {
Bitu DEBUG_EnableDebugger(void);
#endif
bool first=false;
void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) {
/* Save the state of the cpu cores */
LazyFlags old_lflags;
@ -112,6 +114,8 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) {
paging.cr2=lin_addr;
PF_Entry * entry=&pf_queue.entries[pf_queue.used++];
LOG(LOG_PAGING,LOG_NORMAL)("PageFault at %X type %d queue %d",lin_addr,type,pf_queue.used);
// LOG_MSG("EAX:%04X ECX:%04X EDX:%04X EBX:%04X",reg_eax,reg_ecx,reg_edx,reg_ebx);
// LOG_MSG("CS:%04X EIP:%08X SS:%04x SP:%08X",SegValue(cs),reg_eip,SegValue(ss),reg_esp);
entry->cs=SegValue(cs);
entry->eip=reg_eip;
entry->page_addr=page_addr;
@ -125,10 +129,9 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) {
LOG(LOG_PAGING,LOG_NORMAL)("Left PageFault for %x queue %d",lin_addr,pf_queue.used);
memcpy(&lflags,&old_lflags,sizeof(LazyFlags));
cpudecoder=old_cpudecoder;
// LOG_MSG("SS:%04x SP:%08X",SegValue(ss),reg_esp);
}
void MEM_PhysWriteD(Bitu addr,Bit32u val);
class InitPageHandler : public PageHandler {
public:
InitPageHandler() {flags=PFLAG_INIT|PFLAG_NOCODE;}
@ -164,28 +167,28 @@ public:
Bitu t_index=lin_page & 0x3ff;
Bitu table_addr=(paging.base.page<<12)+d_index*4;
X86PageEntry table;
table.load=MEM_PhysReadD(table_addr);
table.load=phys_readd(table_addr);
if (!table.block.p) {
LOG(LOG_PAGING,LOG_ERROR)("NP Table");
PAGING_PageFault(lin_addr,table_addr,0);
table.load=MEM_PhysReadD(table_addr);
table.load=phys_readd(table_addr);
if (!table.block.p)
E_Exit("Pagefault didn't correct table");
}
table.block.a=table.block.d=1; //Set access/Dirty
MEM_PhysWriteD(table_addr,table.load);
phys_writed(table_addr,table.load);
X86PageEntry entry;
Bitu entry_addr=(table.block.base<<12)+t_index*4;
entry.load=MEM_PhysReadD(entry_addr);
entry.load=phys_readd(entry_addr);
if (!entry.block.p) {
LOG(LOG_PAGING,LOG_ERROR)("NP Page");
PAGING_PageFault(lin_addr,entry_addr,0);
entry.load=MEM_PhysReadD(entry_addr);
entry.load=phys_readd(entry_addr);
if (!entry.block.p)
E_Exit("Pagefault didn't correct page");
}
entry.block.a=entry.block.d=1; //Set access/Dirty
MEM_PhysWriteD(entry_addr,entry.load);
phys_writed(entry_addr,entry.load);
phys_page=entry.block.base;
} else {
if (lin_page<LINK_START) phys_page=mapfirstmb[lin_page];
@ -200,10 +203,10 @@ bool PAGING_MakePhysPage(Bitu & page) {
Bitu d_index=page >> 10;
Bitu t_index=page & 0x3ff;
X86PageEntry table;
table.load=MEM_PhysReadD((paging.base.page<<12)+d_index*4);
table.load=phys_readd((paging.base.page<<12)+d_index*4);
if (!table.block.p) return false;
X86PageEntry entry;
entry.load=MEM_PhysReadD((table.block.base<<12)+t_index*4);
entry.load=phys_readd((table.block.base<<12)+t_index*4);
if (!entry.block.p) return false;
page=entry.block.base;
} else {
@ -251,16 +254,21 @@ void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) {
void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) {
PageHandler * handler=MEM_GetPageHandler(phys_page);
Bitu lin_base=lin_page << 12;
if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE)
E_Exit("Illegal page");
if (paging.links.used>=PAGING_LINKS) {
LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache");
PAGING_ClearTLB();
}
HostPt host_mem=handler->GetHostPt(phys_page);
paging.tlb.phys_page[lin_page]=phys_page;
if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=host_mem-lin_base;
else paging.tlb.read[lin_page]=0;
if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=host_mem-lin_base;
else paging.tlb.write[lin_page]=0;
if (paging.links.used>=PAGING_LINKS) E_Exit("Not enough paging links");
paging.links.entries[paging.links.used++]=lin_page;
paging.tlb.handler[lin_page]=handler;
}
@ -281,7 +289,7 @@ void PAGING_SetDirBase(Bitu cr3) {
paging.base.page=cr3 >> 12;
paging.base.addr=cr3 & ~4095;
LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page);
// LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page);
if (paging.enabled) {
PAGING_ClearTLB();
}
@ -292,9 +300,15 @@ void PAGING_Enable(bool enabled) {
if (paging.enabled==enabled) return;
paging.enabled=enabled;
if (!enabled) {
LOG(LOG_PAGING,LOG_NORMAL)("Disabled");
// LOG(LOG_PAGING,LOG_NORMAL)("Disabled");
} else {
LOG(LOG_PAGING,LOG_NORMAL)("Enabled");
if (cpudecoder==CPU_Core_Simple_Run) {
LOG_MSG("CPU core simple won't run this game,switching to normal");
cpudecoder=CPU_Core_Normal_Run;
CPU_CycleLeft+=CPU_Cycles;
CPU_Cycles=0;
}
// LOG(LOG_PAGING,LOG_NORMAL)("Enabled");
PAGING_SetDirBase(paging.cr3);
}
PAGING_ClearTLB();

View File

@ -9,16 +9,14 @@
* 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.
* 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.
*/
/* $Id: debug.cpp,v 1.52 2004/01/27 14:52:28 qbix79 Exp $ */
#include "programs.h"
/* $Id: debug.cpp,v 1.59 2004/08/31 23:11:35 harekiet Exp $ */
#include <string.h>
#include <list>
@ -26,19 +24,21 @@
#include "dosbox.h"
#if C_DEBUG
#include "debug.h"
#include "cross.h" //snprintf
#include "cpu.h"
#include "video.h"
#include "pic.h"
#include "keyboard.h"
#include "mapper.h"
#include "cpu.h"
#include "callback.h"
#include "inout.h"
#include "mixer.h"
#include "debug_inc.h"
#include "timer.h"
#include "paging.h"
#include "../ints/xms.h"
#include "support.h"
#include "shell.h"
#include "programs.h"
#include "debug_inc.h"
#ifdef WIN32
void WIN32_Console();
@ -53,13 +53,17 @@ int old_cursor_state;
static void DrawCode(void);
static bool DEBUG_Log_Loop(int count);
static void DEBUG_RaiseTimerIrq(void);
static void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num);
static void LogGDT(void);
static void LogLDT(void);
static void LogIDT(void);
static void OutputVecTable(char* filename);
static void DrawVariables(void);
char* AnalyzeInstruction(char* inst, bool saveSelector);
void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num);
Bit32u GetHexValue(char* str, char*& hex);
void LogGDT(void);
void LogLDT(void);
void LogIDT(void);
void OutputVecTable(char* filename);
class DEBUG;
@ -67,6 +71,7 @@ DEBUG* pDebugcom = 0;
bool exitLoop = false;
bool logHeavy = false;
// Heavy Debugging Vars for logging
#if C_HEAVY_DEBUG
static FILE* cpuLogFile = 0;
@ -74,6 +79,8 @@ static bool cpuLog = false;
static int cpuLogCounter = 0;
#endif
static struct {
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
} oldregs;
@ -86,6 +93,8 @@ DBGBlock dbg;
static Bitu input_count;
Bitu cycle_count;
static bool debugging;
static void SetColor(Bitu test) {
if (test) {
if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));}
@ -535,35 +544,26 @@ void CBreakpoint::ShowList(void)
bool DEBUG_Breakpoint(void)
{
/* First get the phyiscal address and check for a set Breakpoint */
// PhysPt where=SegPhys(cs)+reg_eip-1;
PhysPt where=GetAddress(SegValue(cs),reg_eip-1);
if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip-1)) return false;
PhysPt where=GetAddress(SegValue(cs),reg_eip);
if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) return false;
// Found. Breakpoint is valid
reg_eip -= 1;
CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints
// exitLoop = true;
// DEBUG_Enable();
return true;
};
bool DEBUG_IntBreakpoint(Bit8u intNum)
{
/* First get the phyiscal address and check for a set Breakpoint */
// PhysPt where=SegPhys(cs)+reg_eip-2;
PhysPt where=GetAddress(SegValue(cs),reg_eip-2);
PhysPt where=GetAddress(SegValue(cs),reg_eip);
if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false;
// Found. Breakpoint is valid
reg_eip -= 2;
CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints
// exitLoop = true;
// DEBUG_Enable();
return true;
};
static bool StepOver()
{
exitLoop = false;
// PhysPt start=SegPhys(cs)+reg_eip;
PhysPt start=GetAddress(SegValue(cs),reg_eip);
char dline[200];Bitu size;
size=DasmI386(dline, start, reg_eip, cpu.code.big);
@ -581,6 +581,10 @@ static bool StepOver()
bool DEBUG_ExitLoop(void)
{
#if C_HEAVY_DEBUG
DrawVariables();
#endif
if (exitLoop) {
exitLoop = false;
return true;
@ -911,6 +915,30 @@ bool ParseCommand(char* str)
else DEBUG_ShowMsg("DEBUG: Variable list load (%s) : failure",name);
return true;
}
found = strstr(str,"SR ");
if (found) { // Set register value
found+=2;
if (ChangeRegister(found)) DEBUG_ShowMsg("DEBUG: Set Register success.");
else DEBUG_ShowMsg("DEBUG: Set Register failure.");
return true;
}
found = strstr(str,"SM ");
if (found) { // Set memory with following values
found+=3;
Bit16u seg = (Bit16u)GetHexValue(found,found); found++;
Bit32u ofs = GetHexValue(found,found); found++;
Bit16u count = 0;
while (*found) {
while (*found==' ') found++;
if (*found) {
Bit8u value = (Bit8u)GetHexValue(found,found); found++;
mem_writeb(GetAddress(seg,ofs+count),value);
count++;
}
};
DEBUG_ShowMsg("DEBUG: Memory changed.");
return true;
}
found = strstr(str,"BP ");
if (found) { // Add new breakpoint
@ -1025,30 +1053,6 @@ bool ParseCommand(char* str)
return true;
}
#endif
found = strstr(str,"SR ");
if (found) { // Set register value
found+=2;
if (ChangeRegister(found)) DEBUG_ShowMsg("DEBUG: Set Register success.");
else DEBUG_ShowMsg("DEBUG: Set Register failure.");
return true;
}
found = strstr(str,"SM ");
if (found) { // Set memory with following values
found+=3;
Bit16u seg = (Bit16u)GetHexValue(found,found); found++;
Bit32u ofs = GetHexValue(found,found); found++;
Bit16u count = 0;
while (*found) {
while (*found==' ') found++;
if (*found) {
Bit8u value = (Bit8u)GetHexValue(found,found); found++;
mem_writeb(GetAddress(seg,ofs+count),value);
count++;
}
};
DEBUG_ShowMsg("DEBUG: Memory changed.");
return true;
}
found = strstr(str,"INTT ");
if (found) { // Create Cpu log file
found+=4;
@ -1433,6 +1437,7 @@ Bitu DEBUG_Loop(void) {
Bit16u oldCS = SegValue(cs);
Bit32u oldEIP = reg_eip;
PIC_runIRQs();
SDL_Delay(1);
if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) {
CBreakpoint::AddBreakpoint(oldCS,oldEIP,true);
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
@ -1455,13 +1460,14 @@ void DEBUG_DrawScreen(void) {
DrawData();
DrawCode();
DrawRegisters();
DrawVariables();
}
static void DEBUG_RaiseTimerIrq(void) {
PIC_ActivateIRQ(0);
}
void LogGDT(void)
static void LogGDT(void)
{
char out1[512];
Descriptor desc;
@ -1480,7 +1486,7 @@ void LogGDT(void)
};
};
void LogLDT(void)
static void LogLDT(void)
{
char out1[512];
Descriptor desc;
@ -1501,7 +1507,7 @@ void LogLDT(void)
};
};
void LogIDT(void)
static void LogIDT(void)
{
char out1[512];
Descriptor desc;
@ -1681,8 +1687,7 @@ void DEBUG_Init(Section* sec) {
MSG_Add("DEBUG_CONFIGFILE_HELP","Nothing to setup yet!\n");
DEBUG_DrawScreen();
/* Add some keyhandlers */
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable);
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
MAPPER_AddHandler(DEBUG_Enable,MK_pause,0,"debugger","Debugger");
/* Clear the TBreakpoint list */
memset((void*)&codeViewData,0,sizeof(codeViewData));
/* setup debug.com */
@ -1769,7 +1774,7 @@ bool CDebugVar::LoadVars(char* name)
return true;
};
void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num)
static void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num)
{
FILE* f = fopen("MEMDUMP.TXT","wt");
if (!f) {
@ -1796,7 +1801,7 @@ void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num)
DEBUG_ShowMsg("DEBUG: Memory dump success.");
};
void OutputVecTable(char* filename)
static void OutputVecTable(char* filename)
{
FILE* f = fopen(filename, "wt");
if (!f)
@ -1812,6 +1817,35 @@ void OutputVecTable(char* filename)
DEBUG_ShowMsg("DEBUG: Interrupt vector table written to %s.", filename);
}
#define DEBUG_VAR_BUF_LEN 16
static void DrawVariables(void)
{
std::list<CDebugVar*>::iterator i;
CDebugVar *dv;
char buffer[DEBUG_VAR_BUF_LEN];
int idx = 0;
for(i=CDebugVar::varList.begin(); i != CDebugVar::varList.end(); i++, idx++) {
if (idx == 4*3) {
/* too many variables */
break;
}
dv = static_cast<CDebugVar*>(*i);
Bit16u value = mem_readw(dv->GetAdr());
snprintf(buffer,DEBUG_VAR_BUF_LEN, "0x%04x", value);
int y = idx / 3;
int x = (idx % 3) * 26;
mvwprintw(dbg.win_var, y, x, dv->GetName());
mvwprintw(dbg.win_var, y, (x + DEBUG_VAR_BUF_LEN + 1) , buffer);
}
wrefresh(dbg.win_var);
}
#undef DEBUG_VAR_BUF_LEN
// HEAVY DEBUGGING STUFF
#if C_HEAVY_DEBUG
@ -1892,9 +1926,9 @@ bool DEBUG_HeavyIsBreakpoint(void)
}
return false;
};
#endif // HEAVY DEBUG
#endif // DEBUG

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -53,7 +53,7 @@ void DEBUG_ShowMsg(char * format,...) {
va_end(msg);
wprintw(dbg.win_out,"%10d: %s\n",cycle_count,buf);
wrefresh(dbg.win_out);
if(debuglog) fprintf(debuglog,"%10d: %s\n",cycle_count,buf);
if(debuglog) fprintf(debuglog,"%10d: %s\n",cycle_count,buf);
}
void LOG::operator() (char* format, ...){
@ -99,13 +99,15 @@ static void DrawBars(void) {
attrset(COLOR_PAIR(PAIR_BLACK_BLUE));
}
/* Show the Register bar */
mvaddstr(dbg.win_reg->_begy-1,0,"---[F1](Register Overview)---");
mvaddstr(dbg.win_reg->_begy-1,0,"---(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)---");
mvaddstr(dbg.win_data->_begy-1,0,"---(Data Overview)---");
/* Show the Code Overview perhaps with special stuff in bar too */
mvaddstr(dbg.win_code->_begy-1,0,"---[F3](Code Overview)---");
mvaddstr(dbg.win_code->_begy-1,0,"---(Code Overview)---");
/* Show the Variable Overview bar */
mvaddstr(dbg.win_var->_begy-1,0,"---(Variable Overview)---");
/* Show the Output OverView */
mvaddstr(dbg.win_out->_begy-1,0,"---[F4](OutPut/Input)---");
mvaddstr(dbg.win_out->_begy-1,0,"---(OutPut/Input)---");
attrset(0);
}
@ -124,7 +126,10 @@ static void MakeSubWindows(void) {
/* The Code Window */
dbg.win_code=subwin(dbg.win_main,11,dbg.win_main->_maxx,outy,0);
outy+=12;
/* The output Window */
/* The Variable Window */
dbg.win_var=subwin(dbg.win_main,4,dbg.win_main->_maxx,outy,0);
outy+=5;
/* 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);

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -17,6 +17,9 @@
*/
/* Local Debug Function */
/* $Id: debug_inc.h,v 1.8 2004/08/28 12:51:35 qbix79 Exp $ */
#include <curses.h>
#include "mem.h"
@ -34,6 +37,7 @@ struct DBGBlock {
WINDOW * win_reg; /* Register Window */
WINDOW * win_data; /* Data Output window */
WINDOW * win_code; /* Disassembly/Debug point Window */
WINDOW * win_var; /* Variable Window */
WINDOW * win_out; /* Text Output Window */
Bit32u active_win; /* Current active window */
Bit32u input_y;

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -4,6 +4,6 @@ noinst_LIBRARIES = libdos.a
EXTRA_DIST = scsidefs.h wnaspi32.h
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 drive_cache.cpp \
dev_con.h dos_mscdex.cpp \
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
drive_iso.cpp dev_con.h dos_mscdex.cpp \
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp

View File

@ -135,9 +135,9 @@ noinst_LIBRARIES = libdos.a
EXTRA_DIST = scsidefs.h wnaspi32.h
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 drive_cache.cpp \
dev_con.h dos_mscdex.cpp \
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
drive_iso.cpp dev_con.h dos_mscdex.cpp \
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp
subdir = src/dos
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -153,9 +153,10 @@ am_libdos_a_OBJECTS = dos.$(OBJEXT) dos_devices.$(OBJEXT) \
dos_memory.$(OBJEXT) dos_misc.$(OBJEXT) dos_classes.$(OBJEXT) \
dos_programs.$(OBJEXT) dos_tables.$(OBJEXT) drives.$(OBJEXT) \
drive_virtual.$(OBJEXT) drive_local.$(OBJEXT) \
drive_cache.$(OBJEXT) dos_mscdex.$(OBJEXT) cdrom.$(OBJEXT) \
drive_cache.$(OBJEXT) drive_fat.$(OBJEXT) drive_iso.$(OBJEXT) \
dos_mscdex.$(OBJEXT) cdrom.$(OBJEXT) \
cdrom_ioctl_win32.$(OBJEXT) cdrom_aspi_win32.$(OBJEXT) \
cdrom_ioctl_linux.$(OBJEXT)
cdrom_ioctl_linux.$(OBJEXT) cdrom_image.$(OBJEXT)
libdos_a_OBJECTS = $(am_libdos_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@ -163,6 +164,7 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/cdrom.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_aspi_win32.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_image.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_linux.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_win32.Po ./$(DEPDIR)/dos.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/dos_classes.Po \
@ -172,8 +174,8 @@ am__depfiles_maybe = depfiles
@AMDEP_TRUE@ ./$(DEPDIR)/dos_misc.Po ./$(DEPDIR)/dos_mscdex.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/dos_programs.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/dos_tables.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/drive_local.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po ./$(DEPDIR)/drive_fat.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/drive_iso.Po ./$(DEPDIR)/drive_local.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/drive_virtual.Po ./$(DEPDIR)/drives.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@ -215,6 +217,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_aspi_win32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_image.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_linux.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_win32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos.Po@am__quote@
@ -229,6 +232,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_programs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_tables.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_cache.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_fat.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_iso.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_local.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_virtual.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drives.Po@am__quote@

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -21,6 +21,11 @@
// SDL CDROM
// ******************************************************
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "dosbox.h"
#include "SDL.h"
#include "support.h"
#include "cdrom.h"
@ -175,8 +180,13 @@ int CDROM_GetMountType(char* path, int forceCD)
cdName = SDL_CDName(i);
if (strcmp(buffer,cdName)==0) return 0;
};
// TODO: Detect ISO
return 2;
// Detect ISO
struct stat file_stat;
stat(path, &file_stat);
if (S_ISREG(file_stat.st_mode)) return 1;
return 2;
};
// ******************************************************

View File

@ -5,10 +5,17 @@
#define MAX_ASPI_CDROM 5
#include <string.h>
#include <iostream>
#include <vector>
#include "dosbox.h"
#include "mem.h"
#include "mixer.h"
#include "SDL.h"
#include "SDL_thread.h"
#if defined(C_SDL_SOUND)
#include "SDL_sound.h"
#endif
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
@ -46,26 +53,28 @@ public:
virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0;
virtual bool LoadUnloadMedia (bool unload) = 0;
virtual void InitNewMedia (void) {};
};
class CDROM_Interface_SDL : public CDROM_Interface
{
public:
CDROM_Interface_SDL (void);
~CDROM_Interface_SDL (void);
virtual ~CDROM_Interface_SDL(void);
bool SetDevice (char* path, int forceCD);
bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
bool GetAudioStatus (bool& playing, bool& pause);
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume);
bool StopAudio (void);
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; };
bool LoadUnloadMedia (bool unload);
virtual bool SetDevice (char* path, int forceCD);
virtual bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
virtual bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
virtual bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
virtual bool GetAudioStatus (bool& playing, bool& pause);
virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
virtual bool PlayAudioSector (unsigned long start,unsigned long len);
virtual bool PauseAudio (bool resume);
virtual bool StopAudio (void);
virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; };
virtual bool LoadUnloadMedia (bool unload);
private:
bool Open (void);
@ -93,6 +102,106 @@ public:
bool LoadUnloadMedia (bool unload) { return true; };
};
class CDROM_Interface_Image : public CDROM_Interface
{
private:
class TrackFile {
public:
virtual bool read(Bit8u *buffer, int seek, int count) = 0;
virtual int getLength() = 0;
};
class BinaryFile : public TrackFile {
public:
BinaryFile(const char *filename, bool &error);
~BinaryFile();
bool read(Bit8u *buffer, int seek, int count);
int getLength();
private:
BinaryFile();
std::ifstream *file;
};
#if defined(C_SDL_SOUND)
class AudioFile : public TrackFile {
public:
AudioFile(const char *filename, bool &error);
~AudioFile();
bool read(Bit8u *buffer, int seek, int count);
int getLength();
private:
AudioFile();
Sound_Sample *sample;
int lastCount;
int lastSeek;
};
#endif
struct Track {
int number;
int attr;
int start;
int length;
int skip;
int sectorSize;
bool mode2;
TrackFile *file;
};
public:
CDROM_Interface_Image (Bit8u subUnit);
virtual ~CDROM_Interface_Image (void);
void InitNewMedia (void);
bool SetDevice (char* path, int forceCD);
bool GetUPC (unsigned char& attr, char* upc);
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
bool GetAudioStatus (bool& playing, bool& pause);
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume);
bool StopAudio (void);
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
bool LoadUnloadMedia (bool unload);
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
static CDROM_Interface_Image* images[26];
private:
// player
static void CDAudioCallBack(Bitu len);
int GetTrack(int sector);
static struct imagePlayer {
CDROM_Interface_Image *cd;
MixerChannel *channel;
SDL_mutex *mutex;
Bit8u buffer[8192];
int bufLen;
int currFrame;
int targetFrame;
bool isPlaying;
bool isPaused;
} player;
void ClearTracks();
bool LoadIsoFile(char *filename);
bool CanReadPVD(TrackFile *file, int sectorSize, bool mode2);
// cue sheet processing
bool LoadCueSheet(char *cuefile);
bool GetRealFileName(std::string& filename, std::string& pathname);
bool GetCueKeyword(std::string &keyword, std::istream &in);
bool GetCueFrame(int &frames, std::istream &in);
bool GetCueString(std::string &str, std::istream &in);
bool AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap);
static int refCount;
std::vector<Track> tracks;
std::string mcn;
Bit8u subUnit;
};
#if defined (WIN32) /* Win 32 */
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
@ -104,7 +213,7 @@ class CDROM_Interface_Aspi : public CDROM_Interface
{
public:
CDROM_Interface_Aspi (void);
~CDROM_Interface_Aspi (void);
virtual ~CDROM_Interface_Aspi(void);
bool SetDevice (char* path, int forceCD);
@ -151,7 +260,7 @@ class CDROM_Interface_Ioctl : public CDROM_Interface
{
public:
CDROM_Interface_Ioctl (void);
~CDROM_Interface_Ioctl (void);
virtual ~CDROM_Interface_Ioctl(void);
bool SetDevice (char* path, int forceCD);
@ -171,6 +280,7 @@ public:
bool LoadUnloadMedia (bool unload);
void InitNewMedia (void) { Close(); Open(); };
private:
bool Open (void);

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: cdrom_aspi_win32.cpp,v 1.10 2004/01/10 14:03:34 qbix79 Exp $ */
/* $Id: cdrom_aspi_win32.cpp,v 1.12 2004/08/04 09:12:53 qbix79 Exp $ */
#if defined (WIN32)
@ -39,6 +39,19 @@
#include "scsidefs.h"
// always use a buffer of the maximum struct size (like the union of all 'SRB_*' struct types)
// Thanx SaPu
typedef union {
SRB_HAInquiry hainquiry;
SRB_GDEVBlock gdevblock;
SRB_ExecSCSICmd execscsicmd;
SRB_Abort abort;
SRB_BusDeviceReset busdevicereset;
SRB_GetDiskInfo getdiskinfo;
SRB_RescanPort rescanport;
SRB_GetSetTimeouts getsettimeouts;
} ASPI_SRB;
// *****************************************************************
// Windows ASPI functions (should work for all WIN with ASPI layer)
// *****************************************************************
@ -78,34 +91,34 @@ bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize
BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID)
{
SRB_HAInquiry sh;
SRB_GDEVBlock sd;
ASPI_SRB sh;
ASPI_SRB sd;
DWORD d = pGetASPI32SupportInfo();
int cnt = LOBYTE(LOWORD(d));
int i,j,k,max;
for(i=0; i<cnt; i++) {
memset(&sh, 0, sizeof(sh));
sh.SRB_Cmd = SC_HA_INQUIRY;
sh.SRB_HaId = i;
sh.hainquiry.SRB_Cmd = SC_HA_INQUIRY;
sh.hainquiry.SRB_HaId = i;
pSendASPI32Command((LPSRB)&sh);
if (sh.SRB_Status!=SS_COMP) continue;
if (sh.hainquiry.SRB_Status!=SS_COMP) continue;
// Indicates the maximum number of targets the adapter supports
// If the value is not 8 or 16, then it should be assumed max target is 8
max = (int)sh.HA_Unique[3];
max = (int)sh.hainquiry.HA_Unique[3];
if ((max!=8) && (max!=16)) max = 8;
for(j=0; j<max; j++) {
for(k=0; k<8; k++) {
memset(&sd, 0, sizeof(sd));
sd.SRB_Cmd = SC_GET_DEV_TYPE;
sd.SRB_HaId = i;
sd.SRB_Target = j;
sd.SRB_Lun = k;
sd.gdevblock.SRB_Cmd = SC_GET_DEV_TYPE;
sd.gdevblock.SRB_HaId = i;
sd.gdevblock.SRB_Target = j;
sd.gdevblock.SRB_Lun = k;
pSendASPI32Command((LPSRB)&sd);
if (sd.SRB_Status == SS_COMP) {
if (sd.SRB_DeviceType == DTYPE_CDROM) {
if (sd.gdevblock.SRB_Status == SS_COMP) {
if (sd.gdevblock.SRB_DeviceType == DTYPE_CDROM) {
if ((target==j) && (lun==k)) {
LOG(LOG_MISC,LOG_NORMAL)("SCSI: Getting Hardware vendor.");
// "Hardware ID = vendor" match ?
@ -175,23 +188,24 @@ bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase)
bool CDROM_Interface_Aspi::GetVendor(BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer)
{
SRB_ExecSCSICmd srbExec;
ASPI_SRB srbExec;
// SRB_ExecSCSICmd srbExec;
memset ( &srbExec, 0, sizeof ( SRB_ExecSCSICmd ) );
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
srbExec.SRB_Cmd = SC_EXEC_SCSI_CMD ;
srbExec.SRB_HaId = HA_num;
srbExec.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
srbExec.SRB_Target = SCSI_Id;
srbExec.SRB_Lun = SCSI_Lun;
srbExec.SRB_BufLen = 36;
srbExec.SRB_BufPointer = (unsigned char*)szBuffer;
srbExec.SRB_SenseLen = SENSE_LEN;
srbExec.SRB_CDBLen = 6;
srbExec.SRB_PostProc = (LPVOID)hEvent;
srbExec.CDBByte [ 0 ] = SCSI_INQUIRY;
srbExec.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ]
srbExec.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD ;
srbExec.execscsicmd.SRB_HaId = HA_num;
srbExec.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
srbExec.execscsicmd.SRB_Target = SCSI_Id;
srbExec.execscsicmd.SRB_Lun = SCSI_Lun;
srbExec.execscsicmd.SRB_BufLen = 36;
srbExec.execscsicmd.SRB_BufPointer = (unsigned char*)szBuffer;
srbExec.execscsicmd.SRB_SenseLen = SENSE_LEN;
srbExec.execscsicmd.SRB_CDBLen = 6;
srbExec.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
srbExec.execscsicmd.CDBByte [ 0 ] = SCSI_INQUIRY;
srbExec.execscsicmd.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ]
ResetEvent(hEvent);
int dwStatus = pSendASPI32Command ((LPSRB)&srbExec);
@ -201,7 +215,7 @@ bool CDROM_Interface_Aspi::GetVendor(BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, c
// LOG(LOG_MISC|LOG_ERROR,"SCSI: Pending done.");
CloseHandle(hEvent);
if (srbExec.SRB_Status != SS_COMP) {
if (srbExec.execscsicmd.SRB_Status != SS_COMP) {
strcpy (szBuffer, "error" );
return false;
} else {
@ -373,26 +387,28 @@ void CDROM_Interface_Aspi::GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * i
DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
// SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId;
s.SRB_Target = target;
s.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = sizeof(*toc);
s.SRB_BufPointer = (BYTE FAR *)toc;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 0x0A;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_READ_TOC;
s.CDBByte[1] = 0x02; // 0x02 for MSF
s.CDBByte[7] = 0x03;
s.CDBByte[8] = 0x24;
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.execscsicmd.SRB_HaId = haId;
s.execscsicmd.SRB_Target = target;
s.execscsicmd.SRB_Lun = lun;
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.execscsicmd.SRB_BufLen = sizeof(*toc);
s.execscsicmd.SRB_BufPointer = (BYTE FAR *)toc;
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.execscsicmd.SRB_CDBLen = 0x0A;
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.execscsicmd.CDBByte[0] = SCSI_READ_TOC;
s.execscsicmd.CDBByte[1] = 0x02; // 0x02 for MSF
s.execscsicmd.CDBByte[7] = 0x03;
s.execscsicmd.CDBByte[8] = 0x24;
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
@ -401,37 +417,39 @@ DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
CloseHandle(hEvent);
return (s.SRB_Status==SS_COMP);
return (s.execscsicmd.SRB_Status==SS_COMP);
}
bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
// SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId;
s.SRB_Target = target;
s.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0;
s.SRB_BufPointer = 0;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 12;
s.SRB_PostProc = (LPVOID)hEvent;
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.execscsicmd.SRB_HaId = haId;
s.execscsicmd.SRB_Target = target;
s.execscsicmd.SRB_Lun = lun;
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.execscsicmd.SRB_BufLen = 0;
s.execscsicmd.SRB_BufPointer = 0;
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.execscsicmd.SRB_CDBLen = 12;
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_PLAYAUD_12;
s.CDBByte[1] = lun << 5;
s.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF);
s.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF);
s.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF);
s.CDBByte[5] = (unsigned char)((start & 0xFF));
s.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF);
s.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF);
s.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF);
s.CDBByte[9] = (unsigned char)(len & 0xFF);
s.execscsicmd.CDBByte[0] = SCSI_PLAYAUD_12;
s.execscsicmd.CDBByte[1] = lun << 5;
s.execscsicmd.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF);
s.execscsicmd.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF);
s.execscsicmd.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF);
s.execscsicmd.CDBByte[5] = (unsigned char)((start & 0xFF));
s.execscsicmd.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF);
s.execscsicmd.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF);
s.execscsicmd.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF);
s.execscsicmd.CDBByte[9] = (unsigned char)(len & 0xFF);
ResetEvent(hEvent);
@ -441,7 +459,7 @@ bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len
CloseHandle(hEvent);
return s.SRB_Status==SS_COMP;
return s.execscsicmd.SRB_Status==SS_COMP;
}
bool CDROM_Interface_Aspi::StopAudio(void)
@ -451,23 +469,25 @@ bool CDROM_Interface_Aspi::StopAudio(void)
bool CDROM_Interface_Aspi::PauseAudio(bool resume)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
//SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId;
s.SRB_Target = target;
s.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0x00;
s.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 0x0A;
s.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x4B;
s.CDBByte[8] = (unsigned char)resume; // Pause
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.execscsicmd.SRB_HaId = haId;
s.execscsicmd.SRB_Target = target;
s.execscsicmd.SRB_Lun = lun;
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.execscsicmd.SRB_BufLen = 0x00;
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.execscsicmd.SRB_CDBLen = 0x0A;
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.execscsicmd.CDBByte[0] = 0x4B;
s.execscsicmd.CDBByte[8] = (unsigned char)resume; // Pause
ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s);
@ -476,37 +496,39 @@ bool CDROM_Interface_Aspi::PauseAudio(bool resume)
CloseHandle(hEvent);
return (s.SRB_Status==SS_COMP);
return (s.execscsicmd.SRB_Status==SS_COMP);
};
bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
{
SUB_Q_CURRENT_POSITION pos;
SRB_ExecSCSICmd s;DWORD dwStatus;
// SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId;
s.SRB_Target = target;
s.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.execscsicmd.SRB_HaId = haId;
s.execscsicmd.SRB_Target = target;
s.execscsicmd.SRB_Lun = lun;
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = sizeof(pos);
s.SRB_BufPointer = (BYTE FAR *)&pos;
s.SRB_CDBLen = 10;
s.SRB_PostProc = (LPVOID)hEvent;
s.execscsicmd.SRB_BufLen = sizeof(pos);
s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&pos;
s.execscsicmd.SRB_CDBLen = 10;
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_SUBCHANNEL;
s.CDBByte[1] = (lun<<5)|2; // lun & msf
s.CDBByte[2] = 0x40; // subq
s.CDBByte[3] = 0x01; // curr pos info
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.CDBByte[7] = 0; // alloc len
s.CDBByte[8] = sizeof(pos);
s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
s.execscsicmd.CDBByte[2] = 0x40; // subq
s.execscsicmd.CDBByte[3] = 0x01; // curr pos info
s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.execscsicmd.CDBByte[7] = 0; // alloc len
s.execscsicmd.CDBByte[8] = sizeof(pos);
ResetEvent(hEvent);
@ -516,7 +538,7 @@ bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track
CloseHandle(hEvent);
if (s.SRB_Status!=SS_COMP) return false;
if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
attr = (pos.Control<<4) &0xEF;
track = pos.TrackNumber;
@ -534,31 +556,33 @@ bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track
bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
{
SUB_Q_MEDIA_CATALOG_NUMBER upc;
SRB_ExecSCSICmd s;DWORD dwStatus;
ASPI_SRB s;
//SRB_ExecSCSICmd s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId;
s.SRB_Target = target;
s.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.execscsicmd.SRB_HaId = haId;
s.execscsicmd.SRB_Target = target;
s.execscsicmd.SRB_Lun = lun;
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = sizeof(upc);
s.SRB_BufPointer = (BYTE FAR *)&upc;
s.SRB_CDBLen = 10;
s.SRB_PostProc = (LPVOID)hEvent;
s.execscsicmd.SRB_BufLen = sizeof(upc);
s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&upc;
s.execscsicmd.SRB_CDBLen = 10;
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_SUBCHANNEL;
s.CDBByte[1] = (lun<<5)|2; // lun & msf
s.CDBByte[2] = 0x40; // subq
s.CDBByte[3] = 0x02; // get upc
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.CDBByte[7] = 0; // alloc len
s.CDBByte[8] = sizeof(upc);
s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
s.execscsicmd.CDBByte[2] = 0x40; // subq
s.execscsicmd.CDBByte[3] = 0x02; // get upc
s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.execscsicmd.CDBByte[7] = 0; // alloc len
s.execscsicmd.CDBByte[8] = sizeof(upc);
ResetEvent(hEvent);
@ -568,15 +592,14 @@ bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
CloseHandle(hEvent);
if (s.SRB_Status!=SS_COMP) return false;
if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
// attr = (upc.ADR<<4) | upc.Control;
attr = 0;
int pos = 0;
// Convert to mscdex format
// for (int i=0; i<6; i++) upcdata[i] = (upc.MediaCatalog[pos++]<<4)+(upc.MediaCatalog[pos++]&0x0F);
// upcdata[6] = (upc.MediaCatalog[pos++]<<4);
for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i];
for (int i=0; i<7; i++) upcdata[i] = (upc.MediaCatalog[i*2] << 4) | (upc.MediaCatalog[i*2+1] & 0x0F);
return true;
};
@ -586,31 +609,33 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
playing = pause = false;
SUB_Q_HEADER sub;
SRB_ExecSCSICmd s;DWORD dwStatus;
// SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId;
s.SRB_Target = target;
s.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.execscsicmd.SRB_HaId = haId;
s.execscsicmd.SRB_Target = target;
s.execscsicmd.SRB_Lun = lun;
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = sizeof(sub);
s.SRB_BufPointer = (BYTE FAR *)&sub;
s.SRB_CDBLen = 10;
s.SRB_PostProc = (LPVOID)hEvent;
s.execscsicmd.SRB_BufLen = sizeof(sub);
s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&sub;
s.execscsicmd.SRB_CDBLen = 10;
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_SUBCHANNEL;
s.CDBByte[1] = (lun<<5)|2; // lun & msf
s.CDBByte[2] = 0x00; // no subq
s.CDBByte[3] = 0x00; // dont care
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.CDBByte[7] = 0; // alloc len
s.CDBByte[8] = sizeof(sub);
s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
s.execscsicmd.CDBByte[2] = 0x00; // no subq
s.execscsicmd.CDBByte[3] = 0x00; // dont care
s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.execscsicmd.CDBByte[7] = 0; // alloc len
s.execscsicmd.CDBByte[8] = sizeof(sub);
ResetEvent(hEvent);
@ -620,7 +645,7 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
CloseHandle(hEvent);
if (s.SRB_Status!=SS_COMP) return false;
if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
playing = (sub.AudioStatus==0x11);
pause = (sub.AudioStatus==0x12);
@ -630,27 +655,29 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
//SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId;
s.SRB_Target = target;
s.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.execscsicmd.SRB_HaId = haId;
s.execscsicmd.SRB_Target = target;
s.execscsicmd.SRB_Lun = lun;
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = 0;
s.SRB_BufPointer = 0;
s.SRB_CDBLen = 14;
s.SRB_PostProc = (LPVOID)hEvent;
s.execscsicmd.SRB_BufLen = 0;
s.execscsicmd.SRB_BufPointer = 0;
s.execscsicmd.SRB_CDBLen = 6; // 14;
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_LOAD_UN;
s.CDBByte[1] = (lun<<5)|1; // lun & immediate
s.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media
s.execscsicmd.CDBByte[0] = SCSI_LOAD_UN;
s.execscsicmd.CDBByte[1] = (lun<<5)|1; // lun & immediate
s.execscsicmd.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media
ResetEvent(hEvent);
@ -660,7 +687,7 @@ bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
CloseHandle(hEvent);
if (s.SRB_Status!=SS_COMP) return false;
if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
return true;
};
@ -684,7 +711,9 @@ bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaCha
bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
{
SRB_ExecSCSICmd s;DWORD dwStatus;
//SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
@ -693,27 +722,27 @@ bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long se
Bitu buflen = raw?2352*num:2048*num;
Bit8u* bufdata = new Bit8u[buflen];
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId;
s.SRB_Target = target;
s.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN;
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.execscsicmd.SRB_HaId = haId;
s.execscsicmd.SRB_Target = target;
s.execscsicmd.SRB_Lun = lun;
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = buflen;
s.SRB_BufPointer = (BYTE FAR*)bufdata;
s.SRB_CDBLen = 12;
s.SRB_PostProc = (LPVOID)hEvent;
s.execscsicmd.SRB_BufLen = buflen;
s.execscsicmd.SRB_BufPointer = (BYTE FAR*)bufdata;
s.execscsicmd.SRB_CDBLen = 12;
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0xBE;
s.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF);
s.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF);
s.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF);
s.CDBByte[5] = (unsigned char)((sector & 0xFF));
s.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF);
s.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF);
s.CDBByte[8] = (unsigned char) (num & 0xFF);
s.CDBByte[9] = (raw?0xF0:0x10);
s.execscsicmd.CDBByte[0] = 0xBE;
s.execscsicmd.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF);
s.execscsicmd.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF);
s.execscsicmd.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF);
s.execscsicmd.CDBByte[5] = (unsigned char)((sector & 0xFF));
s.execscsicmd.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF);
s.execscsicmd.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF);
s.execscsicmd.CDBByte[8] = (unsigned char) (num & 0xFF);
s.execscsicmd.CDBByte[9] = (raw?0xF0:0x10);
ResetEvent(hEvent);
@ -728,7 +757,7 @@ bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long se
delete[] bufdata;
return (s.SRB_Status==SS_COMP);
return (s.execscsicmd.SRB_Status==SS_COMP);
};
#endif

651
src/dos/cdrom_image.cpp Normal file
View File

@ -0,0 +1,651 @@
/*
* Copyright (C) 2002-2004 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 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.
*/
/* $Id: cdrom_image.cpp,v 1.3 2004/08/23 09:35:15 harekiet Exp $ */
#include <cctype>
#include <cmath>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <limits>
#include <sstream>
#include <vector>
#include <sys/stat.h>
#include "cdrom.h"
#include "drives.h"
#if !defined(WIN32)
#include <libgen.h>
#endif
using namespace std;
#define MAX_LINE_LENGTH 512
#define MAX_FILENAME_LENGTH 256
CDROM_Interface_Image::BinaryFile::BinaryFile(const char *filename, bool &error)
{
file = new ifstream(filename, ios::in | ios::binary);
error = (file == NULL) || (file->fail());
}
CDROM_Interface_Image::BinaryFile::~BinaryFile()
{
delete file;
}
bool CDROM_Interface_Image::BinaryFile::read(Bit8u *buffer, int seek, int count)
{
file->seekg(seek, ios::beg);
file->read((char*)buffer, count);
return !(file->fail());
}
int CDROM_Interface_Image::BinaryFile::getLength()
{
file->seekg(0, ios::end);
int length = file->tellg();
if (file->fail()) return -1;
return length;
}
#if defined(C_SDL_SOUND)
CDROM_Interface_Image::AudioFile::AudioFile(const char *filename, bool &error)
{
Sound_AudioInfo desired = {AUDIO_S16, 2, 44100};
sample = Sound_NewSampleFromFile(filename, &desired, RAW_SECTOR_SIZE);
lastCount = RAW_SECTOR_SIZE;
lastSeek = 0;
error = (sample == NULL);
}
CDROM_Interface_Image::AudioFile::~AudioFile()
{
Sound_FreeSample(sample);
}
bool CDROM_Interface_Image::AudioFile::read(Bit8u *buffer, int seek, int count)
{
if (lastCount != count) {
int success = Sound_SetBufferSize(sample, count);
if (!success) return false;
}
if (lastSeek != (seek - count)) {
int success = Sound_Seek(sample, (int)((double)(seek) / 176.4f));
if (!success) return false;
}
lastSeek = seek;
int bytes = Sound_Decode(sample);
if (bytes < count) {
memcpy(buffer, sample->buffer, bytes);
memset(buffer + bytes, 0, count - bytes);
} else {
memcpy(buffer, sample->buffer, count);
}
return !(sample->flags & SOUND_SAMPLEFLAG_ERROR);
}
int CDROM_Interface_Image::AudioFile::getLength()
{
int time = 1;
int shift = 0;
if (!(sample->flags & SOUND_SAMPLEFLAG_CANSEEK)) return -1;
while (true) {
int success = Sound_Seek(sample, (unsigned int)(shift + time));
if (!success) {
if (time == 1) return lround((double)shift * 176.4f);
shift += time >> 1;
time = 1;
} else {
if (time > ((numeric_limits<int>::max() - shift) / 2)) return -1;
time = time << 1;
}
}
}
#endif
// initialize static members
int CDROM_Interface_Image::refCount = 0;
CDROM_Interface_Image* CDROM_Interface_Image::images[26];
CDROM_Interface_Image::imagePlayer CDROM_Interface_Image::player = {
NULL, NULL, NULL, 0, 0, 0, 0, 0, false, false };
CDROM_Interface_Image::CDROM_Interface_Image(Bit8u subUnit)
{
images[subUnit] = this;
if (refCount == 0) {
#if defined(C_SDL_SOUND)
Sound_Init();
#endif
player.mutex = SDL_CreateMutex();
if (!player.channel) {
player.channel = MIXER_AddChannel(&CDAudioCallBack, 44100, "CDAUDIO");
}
player.channel->Enable(true);
}
refCount++;
}
CDROM_Interface_Image::~CDROM_Interface_Image()
{
refCount--;
if (player.cd == this) player.cd = NULL;
ClearTracks();
if (refCount == 0) {
#if defined(C_SDL_SOUND)
Sound_Quit();
#endif
SDL_DestroyMutex(player.mutex);
player.channel->Enable(false);
}
}
void CDROM_Interface_Image::InitNewMedia()
{
}
bool CDROM_Interface_Image::SetDevice(char* path, int forceCD)
{
if (LoadCueSheet(path)) return true;
if (LoadIsoFile(path)) return true;
// print error message on dosbox console
char buf[MAX_LINE_LENGTH];
snprintf(buf, MAX_LINE_LENGTH, "Could not load image file: %s\n", path);
Bit16u size = strlen(buf);
DOS_WriteFile(STDOUT, (Bit8u*)buf, &size);
return false;
}
bool CDROM_Interface_Image::GetUPC(unsigned char& attr, char* upc)
{
attr = 0;
strcpy(upc, this->mcn.c_str());
return true;
}
bool CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut)
{
stTrack = 1;
end = tracks.size() - 1;
FRAMES_TO_MSF(tracks[tracks.size() - 1].start + 150, &leadOut.min, &leadOut.sec, &leadOut.fr);
return true;
}
bool CDROM_Interface_Image::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr)
{
if (track < 1 || track > tracks.size()) return false;
FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr);
attr = tracks[track - 1].attr;
return true;
}
bool CDROM_Interface_Image::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
{
track = GetTrack(player.currFrame);
if (track < 1) return false;
attr = tracks[track - 1].attr;
index = 1;
FRAMES_TO_MSF(player.currFrame + 150, &absPos.min, &absPos.sec, &absPos.fr);
FRAMES_TO_MSF(player.currFrame - tracks[track - 1].start + 150, &relPos.min, &relPos.sec, &relPos.fr);
return true;
}
bool CDROM_Interface_Image::GetAudioStatus(bool& playing, bool& pause)
{
playing = player.isPlaying;
pause = player.isPaused;
return true;
}
bool CDROM_Interface_Image::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen)
{
mediaPresent = true;
mediaChanged = false;
trayOpen = false;
return true;
}
bool CDROM_Interface_Image::PlayAudioSector(unsigned long start,unsigned long len)
{
SDL_mutexP(player.mutex);
player.cd = this;
player.currFrame = start;
player.targetFrame = start + len;
player.isPlaying = true;
player.isPaused = false;
SDL_mutexV(player.mutex);
return true;
}
bool CDROM_Interface_Image::PauseAudio(bool resume)
{
player.isPaused = !resume;
return true;
}
bool CDROM_Interface_Image::StopAudio(void)
{
player.isPlaying = false;
player.isPaused = false;
return true;
}
bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
{
int sectorSize = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
Bitu buflen = num * sectorSize;
Bit8u* buf = new Bit8u[buflen];
bool success;
for(int i = 0; i < num; i++) {
success = ReadSector(&buf[i * sectorSize], raw, sector);
if (!success) break;
}
MEM_BlockWrite(buffer, buf, buflen);
delete[] buf;
return success;
}
bool CDROM_Interface_Image::LoadUnloadMedia(bool unload)
{
return true;
}
int CDROM_Interface_Image::GetTrack(int sector)
{
vector<Track>::iterator i = tracks.begin();
vector<Track>::iterator end = tracks.end() - 1;
while(i != end) {
Track &curr = *i;
Track &next = *(i + 1);
if (curr.start <= sector && sector < next.start) return curr.number;
i++;
}
return -1;
}
bool CDROM_Interface_Image::ReadSector(Bit8u *buffer, bool raw, unsigned long sector)
{
int track = GetTrack(sector) - 1;
if (track < 0) return false;
int seek = tracks[track].skip + (sector - tracks[track].start) * tracks[track].sectorSize;
int length = (raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE);
if (tracks[track].sectorSize != RAW_SECTOR_SIZE && raw) return false;
if (tracks[track].sectorSize == RAW_SECTOR_SIZE && !tracks[track].mode2 && !raw) seek += 16;
if (tracks[track].mode2 && !raw) seek += 24;
return tracks[track].file->read(buffer, seek, length);
}
void CDROM_Interface_Image::CDAudioCallBack(Bitu len)
{
len *= 4; // 16 bit, stereo
if (!len) return;
if (!player.isPlaying || player.isPaused) {
player.channel->AddSilence();
return;
}
SDL_mutexP(player.mutex);
while (player.bufLen < len) {
bool success;
if (player.targetFrame > player.currFrame)
success = player.cd->ReadSector(&player.buffer[player.bufLen], true, player.currFrame);
else success = false;
if (success) {
player.currFrame++;
player.bufLen += RAW_SECTOR_SIZE;
} else {
memset(&player.buffer[player.bufLen], 0, len - player.bufLen);
player.bufLen = len;
player.isPlaying = false;
}
}
SDL_mutexV(player.mutex);
player.channel->AddSamples_s16(len/4,(Bit16s *)player.buffer);
memmove(player.buffer, &player.buffer[len], player.bufLen - len);
player.bufLen -= len;
}
bool CDROM_Interface_Image::LoadIsoFile(char* filename)
{
tracks.clear();
// data track
Track track = {0, 0, 0, 0, 0, 0, false, NULL};
bool error;
track.file = new BinaryFile(filename, error);
if (error) {
delete track.file;
return false;
}
track.number = 1;
track.attr = 4;
// try to detect iso type
if (CanReadPVD(track.file, COOKED_SECTOR_SIZE, false)) {
track.sectorSize = COOKED_SECTOR_SIZE;
track.mode2 = false;
} else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, false)) {
track.sectorSize = RAW_SECTOR_SIZE;
track.mode2 = false;
} else if (CanReadPVD(track.file, 2336, true)) {
track.sectorSize = 2336;
track.mode2 = true;
} else if (CanReadPVD(track.file, RAW_SECTOR_SIZE, true)) {
track.sectorSize = RAW_SECTOR_SIZE;
track.mode2 = true;
} else return false;
track.length = track.file->getLength() / track.sectorSize;
tracks.push_back(track);
// leadout track
track.number = 2;
track.attr = 0;
track.start = track.length;
track.length = 0;
track.file = NULL;
tracks.push_back(track);
return true;
}
bool CDROM_Interface_Image::CanReadPVD(TrackFile *file, int sectorSize, bool mode2)
{
Bit8u pvd[COOKED_SECTOR_SIZE];
int seek = 16 * sectorSize; // first vd is located at sector 16
if (sectorSize == RAW_SECTOR_SIZE && !mode2) seek += 16;
if (mode2) seek += 24;
file->read(pvd, seek, COOKED_SECTOR_SIZE);
// pvd[0] = descriptor type, pvd[1..5] = standard identifier, pvd[6] = iso version
return (pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1);
}
bool CDROM_Interface_Image::LoadCueSheet(char *cuefile)
{
Track track = {0, 0, 0, 0, 0, 0, false, NULL};
tracks.clear();
int shift = 0;
int currPregap = 0;
int totalPregap = 0;
int prestart = 0;
bool success;
bool canAddTrack = false;
char tmp[MAX_FILENAME_LENGTH]; // dirname can change its argument
strncpy(tmp, cuefile, MAX_FILENAME_LENGTH);
#if defined(WIN32)
string pathname("");
#else
string pathname(dirname(tmp));
#endif
ifstream in;
in.open(cuefile, ios::in);
if (in.fail()) return false;
while(!in.eof()) {
// get next line
char buf[MAX_LINE_LENGTH];
in.getline(buf, MAX_LINE_LENGTH);
if (in.fail() && !in.eof()) return false; // probably a binary file
istringstream line(buf);
string command;
GetCueKeyword(command, line);
if (command == "TRACK") {
if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap);
else success = true;
track.start = 0;
track.skip = 0;
currPregap = 0;
prestart = 0;
line >> track.number;
string type;
GetCueKeyword(type, line);
if (type == "AUDIO") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = 0;
track.mode2 = false;
} else if (type == "MODE1/2048") {
track.sectorSize = COOKED_SECTOR_SIZE;
track.attr = 4;
track.mode2 = false;
} else if (type == "MODE1/2352") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = 4;
track.mode2 = false;
} else if (type == "MODE2/2336") {
track.sectorSize = 2336;
track.attr = 4;
track.mode2 = true;
} else if (type == "MODE2/2352") {
track.sectorSize = RAW_SECTOR_SIZE;
track.attr = 4;
track.mode2 = true;
} else success = false;
canAddTrack = true;
}
else if (command == "INDEX") {
int index;
line >> index;
int frame;
success = GetCueFrame(frame, line);
if (index == 1) track.start = frame;
else if (index == 0) prestart = frame;
// ignore other indices
}
else if (command == "FILE") {
if (canAddTrack) success = AddTrack(track, shift, prestart, totalPregap, currPregap);
else success = true;
canAddTrack = false;
string filename;
GetCueString(filename, line);
GetRealFileName(filename, pathname);
string type;
GetCueKeyword(type, line);
track.file = NULL;
bool error = true;
if (type == "BINARY") {
track.file = new BinaryFile(filename.c_str(), error);
}
#if defined(C_SDL_SOUND)
else if (type == "WAVE" || type == "AIFF" || type == "MP3") {
track.file = new AudioFile(filename.c_str(), error);
}
#endif
if (error) {
delete track.file;
success = false;
}
}
else if (command == "PREGAP") success = GetCueFrame(currPregap, line);
else if (command == "CATALOG") success = GetCueString(mcn, line);
// ignored commands
else if (command == "CDTEXTFILE" || command == "FLAGS" || command == "ISRC"
|| command == "PERFORMER" || command == "POSTGAP" || command == "REM"
|| command == "SONGWRITER" || command == "TITLE" || command == "") success = true;
// failure
else success = false;
if (!success) return false;
}
// add last track
if (!AddTrack(track, shift, prestart, totalPregap, currPregap)) return false;
// add leadout track
track.number++;
track.start = 0;
track.length = 0;
track.file = NULL;
if(!AddTrack(track, shift, 0, totalPregap, 0)) return false;
return true;
}
bool CDROM_Interface_Image::AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap)
{
// frames between index 0(prestart) and 1(curr.start) must be skipped
int skip;
if (prestart > 0) {
if (prestart > curr.start) return false;
skip = curr.start - prestart;
} else skip = 0;
// first track (track number must be 1)
if (tracks.empty()) {
if (curr.number != 1) return false;
curr.skip = skip * curr.sectorSize;
curr.start += currPregap;
totalPregap = currPregap;
tracks.push_back(curr);
return true;
}
Track &prev = *(tracks.end() - 1);
// current track consumes data from the same file as the previous
if (prev.file == curr.file) {
curr.start += shift;
prev.length = curr.start + totalPregap - prev.start - skip;
curr.skip += prev.skip + prev.length * prev.sectorSize + skip * curr.sectorSize;
totalPregap += currPregap;
curr.start += totalPregap;
// current track uses a different file as the previous track
} else {
int tmp = prev.file->getLength() - prev.skip;
prev.length = tmp / prev.sectorSize;
if (tmp % prev.sectorSize != 0) prev.length++; // padding
curr.start += prev.start + prev.length + currPregap;
curr.skip = skip * curr.sectorSize;
shift += prev.start + prev.length;
totalPregap = currPregap;
}
// error checks
if (curr.number <= 1) return false;
if (prev.number + 1 != curr.number) return false;
if (curr.start < prev.start + prev.length) return false;
if (curr.length < 0) return false;
tracks.push_back(curr);
return true;
}
bool CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname)
{
// check if file exists
struct stat test;
if (stat(filename.c_str(), &test) == 0) return true;
// check if file with path relative to cue file exists
#if not defined(WIN32)
string tmpstr(pathname + "/" + filename);
if (stat(tmpstr.c_str(), &test) == 0) {
filename = tmpstr;
return true;
}
#endif
// finally check if file is in a dosbox local drive
char fullname[CROSS_LEN];
char tmp[CROSS_LEN];
strncpy(tmp, filename.c_str(), CROSS_LEN);
Bit8u drive;
if (!DOS_MakeName(tmp, fullname, &drive)) return false;
localDrive *ldp = (localDrive*)Drives[drive];
ldp->GetSystemFilename(tmp, fullname);
if (stat(tmp, &test) == 0) {
filename = tmp;
return true;
}
return false;
}
bool CDROM_Interface_Image::GetCueKeyword(string &keyword, istream &in)
{
in >> keyword;
for(int i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]);
return true;
}
bool CDROM_Interface_Image::GetCueFrame(int &frames, istream &in)
{
string msf;
in >> msf;
int min, sec, fr;
bool success = sscanf(msf.c_str(), "%d:%d:%d", &min, &sec, &fr) == 3;
frames = MSF_TO_FRAMES(min, sec, fr);
return success;
}
bool CDROM_Interface_Image::GetCueString(string &str, istream &in)
{
int pos = in.tellg();
in >> str;
if (str[0] == '\"') {
if (str[str.size() - 1] == '\"') {
str.assign(str, 1, str.size() - 2);
} else {
in.seekg(pos, ios::beg);
char buffer[MAX_FILENAME_LENGTH];
in.getline(buffer, MAX_FILENAME_LENGTH, '\"'); // skip
in.getline(buffer, MAX_FILENAME_LENGTH, '\"');
str = buffer;
}
}
return true;
}
void CDROM_Interface_Image::ClearTracks()
{
vector<Track>::iterator i = tracks.begin();
vector<Track>::iterator end = tracks.end();
TrackFile* last = NULL;
while(i != end) {
Track &curr = *i;
if (curr.file != last) {
delete curr.file;
last = curr.file;
}
i++;
}
tracks.clear();
}

View File

@ -9,7 +9,7 @@
* 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.
* 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

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: cdrom_ioctl_win32.cpp,v 1.10 2004/01/10 14:03:34 qbix79 Exp $ */
/* $Id: cdrom_ioctl_win32.cpp,v 1.11 2004/08/04 09:12:53 qbix79 Exp $ */
#if defined (WIN32)

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: dev_con.h,v 1.16 2004/01/10 14:03:34 qbix79 Exp $ */
/* $Id: dev_con.h,v 1.18 2004/08/26 19:41:20 qbix79 Exp $ */
#include "dos_inc.h"
#include "../ints/int10.h"
@ -31,22 +31,22 @@ public:
bool Write(Bit8u * data,Bit16u * size);
bool Seek(Bit32u * pos,Bit32u type);
bool Close();
void ClearAnsi(void);
void ClearAnsi(void);
Bit16u GetInformation(void);
private:
Bit8u cache;
struct ansi { /* should create a constructor which fills them with the appriorate values */
bool esc;
bool sci;
struct ansi { /* should create a constructor which fills them with the appriorate values */
bool esc;
bool sci;
bool enabled;
Bit8u attr;
Bit8u data[NUMBER_ANSI_DATA];
Bit8u numberofarg;
Bit16u nrows;
Bit16u ncols;
Bit8s savecol;
Bit8s saverow;
} ansi;
Bit8u attr;
Bit8u data[NUMBER_ANSI_DATA];
Bit8u numberofarg;
Bit16u nrows;
Bit16u ncols;
Bit8s savecol;
Bit8s saverow;
} ansi;
};
@ -55,11 +55,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
Bit16u count=0;
if ((cache) && (*size)) {
data[count++]=cache;
if(dos.echo) {
INT10_TeletypeOutput(cache,7);
}
cache=0;
if(dos.echo) INT10_TeletypeOutput(cache,7);
cache=0;
}
while (*size>count) {
reg_ah=0;
@ -68,25 +65,24 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
case 13:
data[count++]=0x0D;
if (*size>count) data[count++]=0x0A; // it's only expanded if there is room for it. (NO cache)
*size=count;
*size=count;
reg_ax=oldax;
if(dos.echo) {
INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible)
INT10_TeletypeOutput(10,7);
}
if(dos.echo) {
INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible)
INT10_TeletypeOutput(10,7);
}
return true;
break;
case 8:
if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS
else if(count) { //Remove data if it exists (extended keys don't go right)
data[count--]=0;
INT10_TeletypeOutput(8,7);
INT10_TeletypeOutput(' ',7);
} else {
continue; //no data read yet so restart whileloop.
}
break;
break;
case 8:
if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS
else if(count) { //Remove data if it exists (extended keys don't go right)
data[count--]=0;
INT10_TeletypeOutput(8,7);
INT10_TeletypeOutput(' ',7);
} else {
continue; //no data read yet so restart whileloop.
}
break;
default:
data[count++]=reg_al;
break;
@ -95,11 +91,10 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
if (*size>count) data[count++]=reg_ah;
else cache=reg_ah;
break;
}
if(dos.echo) { //what to do if *size==1 and character is BS ?????
INT10_TeletypeOutput(reg_al,7);
}
}
if(dos.echo) { //what to do if *size==1 and character is BS ?????
INT10_TeletypeOutput(reg_al,7);
}
}
*size=count;
reg_ax=oldax;
@ -109,243 +104,235 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
bool device_CON::Write(Bit8u * data,Bit16u * size) {
Bit16u count=0;
Bitu i;
Bit8u col,row;
Bitu i;
Bit8u col,row;
Bit8u tempdata;
while (*size>count) {
if (!ansi.esc){
if(data[count]=='\033') {
/*clear the datastructure */
ClearAnsi();
/* start the sequence */
ansi.esc=true;
count++;
continue;
} else {
// pass attribute only if ansi is enabled
while (*size>count) {
if (!ansi.esc){
if(data[count]=='\033') {
/*clear the datastructure */
ClearAnsi();
/* start the sequence */
ansi.esc=true;
count++;
continue;
} else {
/* pass attribute only if ansi is enabled */
INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled);
count++;
continue;
};
};
}
}
if(!ansi.sci){
if(!ansi.sci){
switch(data[count]){
case '[':
ansi.sci=true;
break;
case '7': /* save cursor pos +attr */
case '8': /* restore this (Wonder if this is actually used) */
case 'D':/* scrolling DOWN*/
case 'M':/* scrolling UP*/
default:
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */
ClearAnsi();
break;
}
count++;
continue;
}
/*ansi.esc and ansi.sci are true */
switch(data[count]){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
ansi.data[ansi.numberofarg]=10*ansi.data[ansi.numberofarg]+(data[count]-'0');
break;
case ';': /* till a max of NUMBER_ANSI_DATA */
ansi.numberofarg++;
break;
case 'm': /* SGR */
for(i=0;i<=ansi.numberofarg;i++){
switch(data[count]){
case '[':
ansi.sci=true;
break;
case '7': /* save cursor pos +attr */
case '8': /* restore this (Wonder if this is actually used) */
case 'D':/* scrolling DOWN*/
case 'M':/* scrolling UP*/
default:
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */
ClearAnsi();
break;
}
count++;
continue;
}
/*ansi.esc and ansi.sci are true */
switch(data[count]){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
ansi.data[ansi.numberofarg]=10*ansi.data[ansi.numberofarg]+(data[count]-'0');
break;
case ';': /* till a max of NUMBER_ANSI_DATA */
ansi.numberofarg++;
break;
case 'm': /* SGR */
for(i=0;i<=ansi.numberofarg;i++){
ansi.enabled=true;
switch(ansi.data[i]){
case 0: /* normal */
ansi.attr=0x7;
switch(ansi.data[i]){
case 0: /* normal */
ansi.attr=0x07;//Real ansi does this as well. (should do current defaults)
ansi.enabled=false;
break;
case 1: /* bold mode on*/
ansi.attr|=0x8;
break;
case 4: /* underline */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet");
break;
case 5: /* blinking */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for blinking yet");
break;
case 7: /* reverse */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for reverse yet");
break;
case 30: /* fg color black */
ansi.attr&=0xf8;
ansi.attr|=0x0;
break;
case 31: /* fg color red */
ansi.attr&=0xf8;
ansi.attr|=0x4;
break;
case 32: /* fg color green */
ansi.attr&=0xf8;
ansi.attr|=0x2;
break;
case 33: /* fg color yellow */
ansi.attr&=0xf8;
ansi.attr|=0x6;
break;
case 34: /* fg color blue */
ansi.attr&=0xf8;
ansi.attr|=0x1;
break;
case 35: /* fg color magenta */
ansi.attr&=0xf8;
ansi.attr|=0x5;
break;
case 36: /* fg color cyan */
ansi.attr&=0xf8;
ansi.attr|=0x3;
break;
case 37: /* fg color white */
ansi.attr&=0xf8;
ansi.attr|=0x7;
break;
case 40:
ansi.attr&=0x8f;
ansi.attr|=0x0;
break;
case 41:
ansi.attr&=0x8f;
ansi.attr|=0x40;
break;
case 42:
ansi.attr&=0x8f;
ansi.attr|=0x20;
break;
case 43:
ansi.attr&=0x8f;
ansi.attr|=0x60;
break;
case 44:
ansi.attr&=0x8f;
ansi.attr|=0x10;
break;
case 45:
ansi.attr&=0x8f;
ansi.attr|=0x50;
break;
case 46:
ansi.attr&=0x8f;
ansi.attr|=0x30;
break;
case 47:
ansi.attr&=0x8f;
ansi.attr|=0x70;
break;
default:
break;
break;
case 1: /* bold mode on*/
ansi.attr|=0x08;
break;
case 4: /* underline */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet");
break;
case 5: /* blinking */
ansi.attr|=0x80;
break;
case 7: /* reverse */
ansi.attr=0x70;//Just like real ansi. (should do use current colors reversed)
break;
case 30: /* fg color black */
ansi.attr&=0xf8;
ansi.attr|=0x0;
break;
case 31: /* fg color red */
ansi.attr&=0xf8;
ansi.attr|=0x4;
break;
case 32: /* fg color green */
ansi.attr&=0xf8;
ansi.attr|=0x2;
break;
case 33: /* fg color yellow */
ansi.attr&=0xf8;
ansi.attr|=0x6;
break;
case 34: /* fg color blue */
ansi.attr&=0xf8;
ansi.attr|=0x1;
break;
case 35: /* fg color magenta */
ansi.attr&=0xf8;
ansi.attr|=0x5;
break;
case 36: /* fg color cyan */
ansi.attr&=0xf8;
ansi.attr|=0x3;
break;
case 37: /* fg color white */
ansi.attr&=0xf8;
ansi.attr|=0x7;
break;
case 40:
ansi.attr&=0x8f;
ansi.attr|=0x0;
break;
case 41:
ansi.attr&=0x8f;
ansi.attr|=0x40;
break;
case 42:
ansi.attr&=0x8f;
ansi.attr|=0x20;
break;
case 43:
ansi.attr&=0x8f;
ansi.attr|=0x60;
break;
case 44:
ansi.attr&=0x8f;
ansi.attr|=0x10;
break;
case 45:
ansi.attr&=0x8f;
ansi.attr|=0x50;
break;
case 46:
ansi.attr&=0x8f;
ansi.attr|=0x30;
break;
case 47:
ansi.attr&=0x8f;
ansi.attr|=0x70;
break;
default:
break;
}
}
ClearAnsi();
break;
case 'f':
case 'H':/* Cursor Pos*/
if(ansi.data[0]==0) ansi.data[0]=1;
if(ansi.data[1]==0) ansi.data[1]=1;
INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),0); /*ansi=1 based, int10 is 0 based */
ClearAnsi();
break;
}
}
ClearAnsi();
break;
case 'f':
case 'H':/* Cursor Pos*/
if(ansi.data[0]==0) ansi.data[0]=1;
if(ansi.data[1]==0) ansi.data[1]=1;
INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),0); /*ansi=1 based, int10 is 0 based */
ClearAnsi();
break;
/* cursor up down and forward and backward only change the row or the col not both */
case 'A': /* cursor up*/
col=CURSOR_POS_COL(0) ;
row=CURSOR_POS_ROW(0) ;
case 'A': /* cursor up*/
col=CURSOR_POS_COL(0) ;
row=CURSOR_POS_ROW(0) ;
tempdata = (ansi.data[0]? ansi.data[0] : 1);
if(tempdata > row)
{ row=0; }
else
{ row-=tempdata;}
if(tempdata > row) { row=0; }
else { row-=tempdata;}
INT10_SetCursorPos(row,col,0);
ClearAnsi();
break;
ClearAnsi();
break;
case 'B': /*cursor Down */
col=CURSOR_POS_COL(0) ;
row=CURSOR_POS_ROW(0) ;
row=CURSOR_POS_ROW(0) ;
tempdata = (ansi.data[0]? ansi.data[0] : 1);
if(tempdata + static_cast<Bitu>(row) >= ansi.nrows)
{ row = ansi.nrows - 1;}
else
{ row += tempdata; }
INT10_SetCursorPos(row,col,0);
ClearAnsi();
{ row = ansi.nrows - 1;}
else { row += tempdata; }
INT10_SetCursorPos(row,col,0);
ClearAnsi();
break;
case 'C': /*cursor forward */
col=CURSOR_POS_COL(0);
case 'C': /*cursor forward */
col=CURSOR_POS_COL(0);
row=CURSOR_POS_ROW(0);
tempdata=(ansi.data[0]? ansi.data[0] : 1);
if(tempdata + static_cast<Bitu>(col) >= ansi.ncols)
{ col = ansi.ncols - 1;}
else
{ col += tempdata;}
INT10_SetCursorPos(row,col,0);
ClearAnsi();
break;
case 'D': /*Cursor Backward */
col=CURSOR_POS_COL(0);
row=CURSOR_POS_ROW(0);
tempdata=(ansi.data[0]? ansi.data[0] : 1);
if(tempdata > col)
{col = 0;}
else
{ col -= tempdata;}
INT10_SetCursorPos(row,col,0);
ClearAnsi();
break;
case 'J': /*erase screen and move cursor home*/
if(ansi.data[0]==0) ansi.data[0]=2;
if(ansi.data[0]!=2) {/* only number 2 (the standard one supported) */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported",ansi.data[0]);
break;
}
for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
ClearAnsi();
INT10_SetCursorPos(0,0,0);
break;
case 'h': /* set MODE (if code =7 enable linewrap) */
case 'I': /*RESET MODE */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: set/reset mode called(not supported)");
ClearAnsi();
break;
case 'u': /* Restore Cursor Pos */
INT10_SetCursorPos(ansi.saverow,ansi.savecol,0);
ClearAnsi();
break;
case 's': /* SAVE CURSOR POS */
ansi.savecol=CURSOR_POS_COL(0);
ansi.saverow=CURSOR_POS_ROW(0);
ClearAnsi();
break;
case 'K':/* erase till end of line */
for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
ClearAnsi(); /* maybe set cursor back to starting place ???? */
if(tempdata + static_cast<Bitu>(col) >= ansi.ncols)
{ col = ansi.ncols - 1;}
else { col += tempdata;}
INT10_SetCursorPos(row,col,0);
ClearAnsi();
break;
case 'l':/* (if code =7) disable linewrap */
case 'p':/* reassign keys (needs strings) */
case 'i':/* printer stuff */
default:
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unhandled char %c in esc[",data[count]);
ClearAnsi();
break;
}
count++;
case 'D': /*Cursor Backward */
col=CURSOR_POS_COL(0);
row=CURSOR_POS_ROW(0);
tempdata=(ansi.data[0]? ansi.data[0] : 1);
if(tempdata > col) {col = 0;}
else { col -= tempdata;}
INT10_SetCursorPos(row,col,0);
ClearAnsi();
break;
case 'J': /*erase screen and move cursor home*/
if(ansi.data[0]==0) ansi.data[0]=2;
if(ansi.data[0]!=2) {/* only number 2 (the standard one supported) */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported",ansi.data[0]);
break;
}
for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
ClearAnsi();
INT10_SetCursorPos(0,0,0);
break;
case 'h': /* set MODE (if code =7 enable linewrap) */
case 'I': /*RESET MODE */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: set/reset mode called(not supported)");
ClearAnsi();
break;
case 'u': /* Restore Cursor Pos */
INT10_SetCursorPos(ansi.saverow,ansi.savecol,0);
ClearAnsi();
break;
case 's': /* SAVE CURSOR POS */
ansi.savecol=CURSOR_POS_COL(0);
ansi.saverow=CURSOR_POS_ROW(0);
ClearAnsi();
break;
case 'K':/* erase till end of line */
for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
ClearAnsi(); /* maybe set cursor back to starting place ???? */
break;
case 'l':/* (if code =7) disable linewrap */
case 'p':/* reassign keys (needs strings) */
case 'i':/* printer stuff */
default:
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unhandled char %c in esc[",data[count]);
ClearAnsi();
break;
}
count++;
}
*size=count;
return true;
@ -372,22 +359,18 @@ Bit16u device_CON::GetInformation(void) {
device_CON::device_CON() {
name="CON";
cache=0;
ansi.esc=false;
ansi.sci=false;
ansi.enabled=false;
ansi.attr=0x7;
ansi.numberofarg=0;
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
ansi.saverow=0;
ansi.savecol=0;
ansi.attr=0x7;
ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
ansi.saverow=0;
ansi.savecol=0;
ClearAnsi();
}
void device_CON::ClearAnsi(void){
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
ansi.esc=false;
ansi.sci=false;
ansi.numberofarg=0;
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
ansi.esc=false;
ansi.sci=false;
ansi.numberofarg=0;
}

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: dos.cpp,v 1.65 2004/02/02 11:38:44 qbix79 Exp $ */
/* $Id: dos.cpp,v 1.75 2004/09/21 20:04:55 qbix79 Exp $ */
#include <stdio.h>
#include <stdlib.h>
@ -45,20 +45,20 @@ void DOS_SetError(Bit16u code) {
#define DOSNAMEBUF 256
static Bitu DOS_21Handler(void) {
if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) {
DOS_PSP psp(dos.psp);
psp.SetStack(RealMake(SegValue(ss),reg_sp-20));
DOS_PSP psp(dos.psp());
psp.SetStack(RealMake(SegValue(ss),reg_sp-18));
}
char name1[DOSNAMEBUF+1];
char name2[DOSNAMEBUF+1];
switch (reg_ah) {
case 0x01: /* Read character from STDIN, with echo */
{
Bit8u c;Bit16u n=1;
dos.echo=true;
dos.echo=true;
DOS_ReadFile(STDIN,&c,&n);
reg_al=c;
dos.echo=false;
dos.echo=false;
}
break;
case 0x02: /* Write character to STDOUT */
@ -181,7 +181,7 @@ static Bitu DOS_21Handler(void) {
break;
case 0x10: /* Close File using FCB */
if(DOS_FCBClose(SegValue(ds),reg_dx)){
reg_al=0;
reg_al=0;
}else{
reg_al=0xff;
}
@ -189,7 +189,7 @@ static Bitu DOS_21Handler(void) {
break;
case 0x11: /* Find First Matching File using FCB */
if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){
reg_al=0;
reg_al=0;
}else{
reg_al=0xff;
}
@ -197,7 +197,7 @@ static Bitu DOS_21Handler(void) {
break;
case 0x12: /* Find Next Matching File using FCB */
if(DOS_FCBFindNext(SegValue(ds),reg_dx)){
reg_al=0;
reg_al=0;
}else{
reg_al=0xff;
}
@ -254,29 +254,26 @@ static Bitu DOS_21Handler(void) {
LOG(LOG_FCB,LOG_NORMAL)("DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al);
break;
case 0x29: /* Parse filename into FCB */
{ Bit8u difference;
char string[1024];
MEM_StrCopy(SegPhys(ds)+reg_si,string,1024);
reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference);
reg_si+=difference;
}
{
Bit8u difference;
char string[1024];
MEM_StrCopy(SegPhys(ds)+reg_si,string,1024);
reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference);
reg_si+=difference;
}
LOG(LOG_FCB,LOG_NORMAL)("DOS:29:FCB Parse Filename, result:al=%d",reg_al);
break;
break;
case 0x19: /* Get current default drive */
reg_al=DOS_GetDefaultDrive();
break;
case 0x1a: /* Set Disk Transfer Area Address */
{
dos.dta=RealMakeSeg(ds,reg_dx);
DOS_PSP psp(dos.psp);
psp.SetDTA(dos.dta);
}
dos.dta(RealMakeSeg(ds,reg_dx));
break;
case 0x25: /* Set Interrupt Vector */
RealSetVec(reg_al,RealMakeSeg(ds,reg_dx));
break;
case 0x26: /* Create new PSP */
DOS_NewPSP(reg_dx,DOS_PSP(dos.psp).GetSize());
DOS_NewPSP(reg_dx,DOS_PSP(dos.psp()).GetSize());
break;
case 0x2a: /* Get System Date */
{
@ -319,29 +316,43 @@ static Bitu DOS_21Handler(void) {
dos.verify=(reg_al==1);
break;
case 0x2f: /* Get Disk Transfer Area */
SegSet16(es,RealSeg(dos.dta));
reg_bx=RealOff(dos.dta);
SegSet16(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;
/* Serialnumber */
reg_bl=0x00;
reg_cx=0x0000;
break;
case 0x31: /* Terminate and stay resident */
//TODO First get normal files executing
// Important: This service does not set the carry flag!
DOS_ResizeMemory(dos.psp,&reg_dx);
DOS_ResizeMemory(dos.psp(),&reg_dx);
DOS_Terminate(true);
dos.return_code=reg_al;
dos.return_code=reg_al; //Officially a field in the SDA
dos.return_mode=RETURN_TSR;
break;
case 0x32: /* Get drive parameter block for specific drive */
{ /* Officially a dpb should be returned as well. The disk detection part is implemented */
Bitu drive=reg_dl;if(!drive) drive=dos.current_drive;else drive--;
if(Drives[drive]) {
reg_al=0x00;
LOG(LOG_DOSMISC,LOG_ERROR)("Get drive parameter block.");
} else {
reg_al=0xff;
}
}
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 5:reg_dl=3;break;//TODO should be z /* Always boot from c: :) */
case 6: /* Get true version number */
reg_bl=dos.version.major;
reg_bh=dos.version.minor;
@ -353,8 +364,8 @@ static Bitu DOS_21Handler(void) {
}
break;
case 0x34: /* Get INDos Flag */
SegSet16(es,RealSeg(dos.tables.indosflag));
reg_bx=RealOff(dos.tables.indosflag);
SegSet16(es,DOS_SDA_SEG);
reg_bx=DOS_SDA_OFS + 0x01;
break;
case 0x35: /* Get interrupt vector */
reg_bx=real_readw(0,((Bit16u)reg_al)*4);
@ -363,8 +374,8 @@ static Bitu DOS_21Handler(void) {
case 0x36: /* Get Free Disk Space */
{
Bit16u bytes,clusters,free;
Bit8u sectors;
if (DOS_GetFreeDiskSpace(reg_dl,&bytes,&sectors,&clusters,&free)) {
Bit8u sectors;
if(DOS_GetFreeDiskSpace(reg_dl,&bytes,&sectors,&clusters,&free)) {
reg_ax=sectors;
reg_bx=free;
reg_cx=bytes;
@ -466,7 +477,7 @@ static Bitu DOS_21Handler(void) {
case 0x3f: /* READ Read from file or device */
{
Bit16u toread=reg_cx;
dos.echo=true;
dos.echo=true;
if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) {
MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread);
reg_ax=toread;
@ -475,7 +486,7 @@ static Bitu DOS_21Handler(void) {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
dos.echo=false;
dos.echo=false;
break;
}
case 0x40: /* WRITE Write to file or device */
@ -621,7 +632,7 @@ static Bitu DOS_21Handler(void) {
break;
//TODO Check for use of execution state AL=5
case 0x00:
reg_ax=0x4c00; /* Terminate Program */
reg_ax=0x4c00; /* Terminate Program */
case 0x4c: /* EXIT Terminate with return code */
{
@ -634,7 +645,7 @@ static Bitu DOS_21Handler(void) {
break;
}
case 0x4d: /* Get Return code */
reg_al=dos.return_code;
reg_al=dos.return_code;/* Officially read from SDA and clear when read */
reg_ah=dos.return_mode;
break;
case 0x4e: /* FINDFIRST Find first matching file */
@ -650,17 +661,18 @@ static Bitu DOS_21Handler(void) {
case 0x4f: /* FINDNEXT Find next matching file */
if (DOS_FindNext()) {
CALLBACK_SCF(false);
reg_ax=0xffff; /* Undocumented */
/* reg_ax=0xffff;*/ /* Undocumented */
reg_ax=0; /* Undocumented:Qbix Willy beamish */
} else {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
};
break;
case 0x50: /* Set current PSP */
dos.psp=reg_bx;
dos.psp(reg_bx);
break;
case 0x51: /* Get current PSP */
reg_bx=dos.psp;
reg_bx=dos.psp();
break;
case 0x52: { /* Get list of lists */
RealPt addr=dos_infoblock.GetPointer();
@ -671,14 +683,14 @@ static Bitu DOS_21Handler(void) {
//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 */
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break;
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break;
case 0x54: /* Get verify flag */
reg_al=dos.verify?1:0;
reg_al=dos.verify?1:0;
break;
case 0x55: /* Create Child PSP*/
DOS_ChildPSP(reg_dx,reg_si);
dos.psp = reg_dx;
dos.psp(reg_dx);
break;
case 0x56: /* RENAME Rename file */
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
@ -736,6 +748,7 @@ static Bitu DOS_21Handler(void) {
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
if (DOS_CreateTempFile(name1,&handle)) {
reg_ax=handle;
MEM_BlockWrite(SegPhys(ds)+reg_dx,name1,strlen(name1)+1);
CALLBACK_SCF(false);
} else {
reg_ax=dos.errorcode;
@ -763,6 +776,19 @@ static Bitu DOS_21Handler(void) {
}
break;
}
case 0x5d: /* Network Functions */
if(reg_al == 0x06) {
SegSet16(ds,DOS_SDA_SEG);
reg_si = DOS_SDA_OFS;
reg_cx = 0x80; // swap if in dos
reg_dx = 0x1a; // swap always
LOG(LOG_DOSMISC,LOG_ERROR)("Get SDA, Let's hope for the best!");
}
break;
case 0x5f: /* Network redirection */
reg_ax=0x0001; //Failing it
CALLBACK_SCF(true);
break;
case 0x60: /* Canonicalize filename or path */
MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF);
if (DOS_Canonicalize(name1,name2)) {
@ -774,7 +800,15 @@ static Bitu DOS_21Handler(void) {
}
break;
case 0x62: /* Get Current PSP Address */
reg_bx=dos.psp;
reg_bx=dos.psp();
break;
case 0x63: /* DOUBLE BYTE CHARACTER SET */
if(reg_al == 0) {
SegSet16(ds,RealSeg(dos.tables.dcbs));
reg_si=RealOff(dos.tables.dcbs);
reg_al = 0;
CALLBACK_SCF(false); //undocumented
} else reg_al = 0xff; //Doesn't officially touch carry flag
break;
case 0x64: /* Set device driver lookahead flag */
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
@ -787,10 +821,23 @@ static Bitu DOS_21Handler(void) {
switch (reg_al) {
case 1:
mem_writeb(data,reg_al);
mem_writew(data+1,4);
mem_writew(data+3,1);
mem_writew(data+5,37);
reg_cx=4;
mem_writew(data+0x01,0x1c);
mem_writew(data+0x03,1);
mem_writew(data+0x05,0x01b5);
mem_writew(data+0x07,0x0000); // date format
mem_writeb(data+0x08,0x24); // currency symbol
mem_writew(data+0x0a,0x0000);
mem_writew(data+0x0c,0x0000);
mem_writew(data+0x0e,0x002c); // thousands separator
mem_writew(data+0x10,0x002e); // decimal separator
mem_writew(data+0x12,0x002d); // date separator
mem_writew(data+0x14,0x003a); // time separator
mem_writeb(data+0x16,0x00); // currency format
mem_writeb(data+0x17,0x02); // digits after decimal in currency
mem_writeb(data+0x18,0x00); // time format
mem_writed(data+0x19,CALLBACK_RealPointer(call_casemap));
mem_writew(data+0x1d,0x002c); // list separator
reg_cx=0x1f;
CALLBACK_SCF(false);
break;
case 2: // Get pointer to uppercase table
@ -799,9 +846,9 @@ static Bitu DOS_21Handler(void) {
case 5: // Get pointer to filename terminator table
case 6: // Get pointer to collating sequence table
case 7: // Get pointer to double byte char set table
mem_writew(data ,0x0000); // We dont have this table...
mem_writew(data+2,0x0000); // End of table
reg_cx=4;
mem_writeb(data,reg_al);
mem_writed(data+1,dos.tables.dcbs); //used to be 0
reg_cx=5;
CALLBACK_SCF(false);
break;
default:
@ -821,7 +868,7 @@ static Bitu DOS_21Handler(void) {
case 0x67: /* Set handle count */
/* Weird call to increase amount of file handles needs to allocate memory if >20 */
{
DOS_PSP psp(dos.psp);
DOS_PSP psp(dos.psp());
psp.SetNumFiles(reg_bx);
CALLBACK_SCF(false);
break;
@ -854,8 +901,8 @@ static Bitu DOS_21Handler(void) {
CALLBACK_SCF(true);
LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al);
break;
case 0x68: /* FFLUSH Commit file */
case 0x63: /* Weirdo double byte stuff (fails but say it succeeded) available only in MSDOS 2.25 */
CALLBACK_SCF(false); //mirek
case 0xE0:
case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */
@ -865,13 +912,10 @@ static Bitu DOS_21Handler(void) {
case 0x6b: /* NULL Function */
case 0x61: /* UNUSED */
case 0xEF: /* Used in Ancient Art Of War CGA */
case 0x5d: /* Network Functions ||HMMM seems to critical error info and return 1!! Maybe implement it.??*/
/* al=06 clears cf and leaves al=6 and returns crit error flag location*/
case 0x1f: /* Get drive parameter block for default drive */
case 0x32: /* Get drive parameter block for specific drive */
case 0x5c: /* FLOCK File region locking */
case 0x5e: /* More Network Functions */
case 0x5f: /* And Even More Network Functions */
default:
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al);
reg_al=0x00; /* default value */
@ -894,7 +938,7 @@ static Bitu DOS_27Handler(void)
{
// Terminate & stay resident
Bit16u para = (reg_dx/16)+((reg_dx % 16)>0);
if (DOS_ResizeMemory(dos.psp,&para)) DOS_Terminate(true);
if (DOS_ResizeMemory(dos.psp(),&para)) DOS_Terminate(true);
return CBRET_NONE;
}
static Bitu DOS_25Handler(void) {
@ -903,9 +947,10 @@ static Bitu DOS_25Handler(void) {
SETFLAGBIT(CF,true);
}else{
SETFLAGBIT(CF,false);
reg_ax=0;
if((reg_cx != 1) ||(reg_dx != 1))
LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as diskdetection");
LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as diskdetection drive %X",reg_al);
reg_ax=0;
}
return CBRET_NONE;
}
@ -925,8 +970,14 @@ static Bitu DOS_28Handler(void) {
}
static Bitu DOS_29Handler(void) {
LOG(LOG_DOSMISC,LOG_ERROR)("int 29 called");
return CBRET_NONE;
static bool int29warn=false;
if(!int29warn) {
LOG(LOG_DOSMISC,LOG_WARN)("Int 29 called. Redirecting to int 10:0x0e");
int29warn=true;
}
reg_ah=0x0e;
CALLBACK_RunRealInt(0x10);
return CBRET_NONE;
}
static Bitu DOS_CaseMapFunc(void) {
@ -942,32 +993,32 @@ void DOS_ShutDown(Section* sec)
void DOS_Init(Section* sec) {
call_20=CALLBACK_Allocate();
CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET);
CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET,"DOS Int 20");
RealSetVec(0x20,CALLBACK_RealPointer(call_20));
call_21=CALLBACK_Allocate();
CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET_STI);
CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET_STI,"DOS Int 21");
RealSetVec(0x21,CALLBACK_RealPointer(call_21));
call_25=CALLBACK_Allocate();
CALLBACK_Setup(call_25,DOS_25Handler,CB_RETF);
CALLBACK_Setup(call_25,DOS_25Handler,CB_RETF,"DOS Int 25");
RealSetVec(0x25,CALLBACK_RealPointer(call_25));
call_26=CALLBACK_Allocate();
CALLBACK_Setup(call_26,DOS_26Handler,CB_RETF);
CALLBACK_Setup(call_26,DOS_26Handler,CB_RETF,"DOS Int 26");
RealSetVec(0x26,CALLBACK_RealPointer(call_26));
call_27=CALLBACK_Allocate();
CALLBACK_Setup(call_27,DOS_27Handler,CB_IRET);
CALLBACK_Setup(call_27,DOS_27Handler,CB_IRET,"DOS Int 27");
RealSetVec(0x27,CALLBACK_RealPointer(call_27));
call_28=CALLBACK_Allocate();
CALLBACK_Setup(call_28,DOS_28Handler,CB_IRET);
RealSetVec(0x28,CALLBACK_RealPointer(call_28));
call_28=CALLBACK_Allocate();
CALLBACK_Setup(call_28,DOS_28Handler,CB_IRET,"DOS Int 28");
RealSetVec(0x28,CALLBACK_RealPointer(call_28));
call_29=CALLBACK_Allocate();
CALLBACK_Setup(call_29,DOS_29Handler,CB_IRET);
RealSetVec(0x29,CALLBACK_RealPointer(call_29));
call_29=CALLBACK_Allocate();
CALLBACK_Setup(call_29,DOS_29Handler,CB_IRET,"CON Output Int 29");
RealSetVec(0x29,CALLBACK_RealPointer(call_29));
DOS_SetupFiles(); /* Setup system File tables */
DOS_SetupDevices(); /* Setup dos devices */
@ -995,6 +1046,6 @@ void DOS_Init(Section* sec) {
/* case map routine INT 0x21 0x38 */
call_casemap = CALLBACK_Allocate();
CALLBACK_Setup(call_casemap,DOS_CaseMapFunc,CB_RETF);
CALLBACK_Setup(call_casemap,DOS_CaseMapFunc,CB_RETF,"DOS CaseMap");
}

View File

@ -9,14 +9,14 @@
* 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.
* 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.
*/
/* $Id: dos_classes.cpp,v 1.33 2004/01/10 14:03:34 qbix79 Exp $ */
/* $Id: dos_classes.cpp,v 1.41 2004/08/04 09:12:53 qbix79 Exp $ */
#include <string.h>
#include <stdlib.h>
@ -64,11 +64,45 @@ void DOS_InfoBlock::SetLocation(Bit16u segment)
pt=PhysMake(seg,0);
/* Clear the initual Block */
for(Bitu i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff);
sSave(sDIB,regCXfrom5e,(Bit16u)0);
sSave(sDIB,countLRUcache,(Bit16u)0);
sSave(sDIB,countLRUopens,(Bit16u)0);
sSave(sDIB,protFCBs,(Bit16u)0);
sSave(sDIB,specialCodeSeg,(Bit16u)0);
sSave(sDIB,joindedDrives,(Bit8u)0);
sSave(sDIB,lastdrive,(Bit8u)0x01);//increase this if you add drives to cds-chain
sSave(sDIB,setverPtr,(Bit32u)0);
sSave(sDIB,a20FixOfs,(Bit16u)0);
sSave(sDIB,pspLastIfHMA,(Bit16u)0);
sSave(sDIB,blockDevices,(Bit8u)0);
sSave(sDIB,bootDrive,(Bit8u)0);
sSave(sDIB,useDwordMov,(Bit8u)1);
sSave(sDIB,extendedSize,(Bit16u)0x4000); // >16mb
sSave(sDIB,sharingCount,(Bit16u)0);
sSave(sDIB,sharingDelay,(Bit16u)0);
sSave(sDIB,nulNextDriver,(Bit32u)0xffffffff);
sSave(sDIB,nulAttributes,(Bit16u)0x8004);
sSave(sDIB,nulStrategy,(Bit32u)0x00000000);
sSave(sDIB,nulString[0],(Bit8u)0x4e);
sSave(sDIB,nulString[1],(Bit8u)0x55);
sSave(sDIB,nulString[2],(Bit8u)0x4c);
sSave(sDIB,nulString[3],(Bit8u)0x20);
sSave(sDIB,nulString[4],(Bit8u)0x20);
sSave(sDIB,nulString[5],(Bit8u)0x20);
sSave(sDIB,nulString[6],(Bit8u)0x20);
sSave(sDIB,nulString[7],(Bit8u)0x20);
}
void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb)
{
sSave(sDIB,firstMCB,_firstmcb);
sSave(sDIB,firstMCB,_firstmcb); //c2woody
}
void DOS_InfoBlock::SetfirstFileTable(RealPt _first_table){
@ -81,6 +115,26 @@ void DOS_InfoBlock::SetBuffers(Bit16u x,Bit16u y) {
}
void DOS_InfoBlock::SetCurDirStruct(Bit32u _curdirstruct)
{
sSave(sDIB,curDirStructure,_curdirstruct);
}
void DOS_InfoBlock::SetFCBTable(Bit32u _fcbtable)
{
sSave(sDIB,fcbTable,_fcbtable);
}
void DOS_InfoBlock::SetDeviceChainStart(Bit32u _devchain)
{
sSave(sDIB,nulNextDriver,_devchain);
}
void DOS_InfoBlock::SetDiskInfoBuffer(Bit32u _dinfobuf)
{
sSave(sDIB,diskInfoBuffer,_dinfobuf);
}
RealPt DOS_InfoBlock::GetPointer(void)
{
return RealMake(seg,offsetof(sDIB,firstDPB));
@ -94,7 +148,7 @@ Bit16u DOS_PSP::rootpsp = 0;
void DOS_PSP::MakeNew(Bit16u mem_size)
{
/* get previous */
DOS_PSP prevpsp(dos.psp);
DOS_PSP prevpsp(dos.psp());
/* Clear it first */
Bitu i;
for (i=0;i<sizeof(sPSP);i++) mem_writeb(pt+i,0);
@ -112,16 +166,16 @@ void DOS_PSP::MakeNew(Bit16u mem_size)
sSave(sPSP,service[1],0x21);
sSave(sPSP,service[2],0xcb);
/* psp and psp-parent */
sSave(sPSP,psp_parent,dos.psp);
sSave(sPSP,prev_psp,RealMake(dos.psp,0));
sSave(sPSP,psp_parent,dos.psp());
sSave(sPSP,prev_psp,0xffffffff);
sSave(sPSP,dos_version,0x0005);
/* terminate 22,break 23,crititcal error 24 address stored */
SaveVectors();
/* Process DTA */
sSave(sPSP,dta,RealMake(seg,128));
/* FCBs are filled with 0 */
// ....
/* Init file pointer and max_files */
sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files[0])));
sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files)));
sSave(sPSP,max_files,20);
for (i=0;i<20;i++) SetFileHandle(i,0xff);
@ -218,7 +272,7 @@ void DOS_PSP::SetCommandTail(RealPt src)
MEM_BlockCopy(pt+offsetof(sPSP,cmdtail),Real2Phys(src),128);
} else { // empty
sSave(sPSP,cmdtail.count,0x00);
mem_writeb(pt+offsetof(sPSP,cmdtail.buffer[0]),0x0d);
mem_writeb(pt+offsetof(sPSP,cmdtail.buffer),0x0d);
};
};
@ -403,3 +457,16 @@ void DOS_FCB::GetName(char * fillname) {
fillname[14]=0;
}
void DOS_FCB::GetAttr(Bit8u& attr) {
if(extended) attr=mem_readb(pt - 1);
}
void DOS_FCB::SetAttr(Bit8u attr) {
if(extended) mem_writeb(pt - 1,attr);
}
void DOS_SDA::Init() {
/* Clear */
for(Bitu i=0;i<sizeof(sSDA);i++) mem_writeb(pt+i,0x00);
sSave(sSDA,drive_crit_error,0xff);
}

View File

@ -9,7 +9,7 @@
* 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.
* 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
@ -34,6 +34,27 @@
static DOS_Device * devices[MAX_DEVICES];
static Bit32u device_count;
class device_NUL : public DOS_Device {
public:
device_NUL() { name="NUL"; };
bool Read(Bit8u * data,Bit16u * size) {
for(Bitu i = 0; i < *size;i++)
data[i]=0;
LOG(LOG_IOCTL,LOG_NORMAL)("NUL:READ");
return true;
}
bool Write(Bit8u * data,Bit16u * size) {
LOG(LOG_IOCTL,LOG_NORMAL)("NUL:WRITE");
return true;
}
bool Seek(Bit32u * pos,Bit32u type) {
LOG(LOG_IOCTL,LOG_NORMAL)("NUL:SEEK");
return true;
}
bool Close() { return true; }
Bit16u GetInformation(void) { return 0x8004; }
};
Bit8u DOS_FindDevice(char * name) {
/* loop through devices */
Bit8u index=0;
@ -73,5 +94,8 @@ void DOS_SetupDevices(void) {
DOS_Device * newdev;
newdev=new device_CON();
DOS_AddDevice(newdev);
DOS_Device * newdev2;
newdev2=new device_NUL();
DOS_AddDevice(newdev2);
}

View File

@ -9,16 +9,17 @@
* 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.
* 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.
*/
/* $Id */
/* $Id: dos_execute.cpp,v 1.44 2004/08/04 09:12:53 qbix79 Exp $ */
#include <string.h>
#include <ctype.h>
#include "dosbox.h"
#include "mem.h"
#include "dos_inc.h"
@ -26,6 +27,8 @@
#include "callback.h"
#include "debug.h"
char * RunningProgram="DOSBOX";
#ifdef _MSC_VER
#pragma pack(1)
#endif
@ -65,7 +68,7 @@ struct EXE_Header {
static void SaveRegisters(void) {
reg_sp-=20;
reg_sp-=18;
mem_writew(SegPhys(ss)+reg_sp+ 0,reg_ax);
mem_writew(SegPhys(ss)+reg_sp+ 2,reg_cx);
mem_writew(SegPhys(ss)+reg_sp+ 4,reg_dx);
@ -87,19 +90,28 @@ static void RestoreRegisters(void) {
reg_bp=mem_readw(SegPhys(ss)+reg_sp+12);
SegSet16(ds,mem_readw(SegPhys(ss)+reg_sp+14));
SegSet16(es,mem_readw(SegPhys(ss)+reg_sp+16));
reg_sp+=20;
reg_sp+=18;
}
extern void GFX_SetTitle(Bits cycles,Bits frameskip,bool paused);
void DOS_UpdatePSPName(void) {
DOS_MCB mcb(dos.psp()-1);
static char name[9];
mcb.GetFileName(name);
if (!strlen(name)) strcpy(name,"DOSBOX");
RunningProgram=name;
GFX_SetTitle(-1,-1,false);
}
bool DOS_Terminate(bool tsr) {
dos.return_code=reg_al;
dos.return_mode=RETURN_EXIT;
Bit16u mempsp = dos.psp;
Bit16u mempsp = dos.psp();
DOS_PSP curpsp(dos.psp);
if (dos.psp==curpsp.GetParent()) return true;
DOS_PSP curpsp(mempsp);
if (mempsp==curpsp.GetParent()) return true;
/* Free Files owned by process */
if (!tsr) curpsp.CloseFiles();
@ -108,10 +120,9 @@ bool DOS_Terminate(bool tsr) {
/* Restore vector 22,23,24 */
curpsp.RestoreVectors();
/* Set the parent PSP */
dos.psp = curpsp.GetParent();
dos.psp(curpsp.GetParent());
DOS_PSP parentpsp(curpsp.GetParent());
/* Restore the DTA of the parent psp */
dos.dta = parentpsp.GetDTA();
/* Restore the SS:SP to the previous one */
SegSet16(ss,RealSeg(parentpsp.GetStack()));
reg_sp = RealOff(parentpsp.GetStack());
@ -123,15 +134,13 @@ bool DOS_Terminate(bool tsr) {
mem_writew(SegPhys(ss)+reg_sp+4,0x200); //stack isn't preserved
// Free memory owned by process
if (!tsr) DOS_FreeProcessMemory(mempsp);
DOS_UpdatePSPName();
return true;
}
static bool MakeEnv(char * name,Bit16u * segment) {
/* If segment to copy environment is 0 copy the caller's environment */
DOS_PSP psp(dos.psp);
DOS_PSP psp(dos.psp());
PhysPt envread,envwrite;
Bit16u envsize=1;
bool parentenv=true;
@ -173,8 +182,7 @@ static bool MakeEnv(char * name,Bit16u * segment) {
} else return false;
}
bool DOS_NewPSP(Bit16u segment, Bit16u size)
{
bool DOS_NewPSP(Bit16u segment, Bit16u size) {
DOS_PSP psp(segment);
psp.MakeNew(size);
DOS_PSP psp_parent(psp.GetParent());
@ -182,8 +190,7 @@ bool DOS_NewPSP(Bit16u segment, Bit16u size)
return true;
};
bool DOS_ChildPSP(Bit16u segment, Bit16u size)
{
bool DOS_ChildPSP(Bit16u segment, Bit16u size) {
DOS_PSP psp(segment);
psp.MakeNew(size);
DOS_PSP psp_parent(psp.GetParent());
@ -194,7 +201,6 @@ bool DOS_ChildPSP(Bit16u segment, Bit16u size)
};
static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
/* Fix the PSP for psp and environment MCB's */
DOS_MCB mcb((Bit16u)(pspseg-1));
mcb.SetPSPSeg(pspseg);
@ -204,31 +210,14 @@ static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
DOS_PSP psp(pspseg);
psp.MakeNew(memsize);
psp.SetEnvironment(envseg);
/* Copy file handles //QBIX::ALWAYS COPY BUT LEFT ORIGINAL INCASE OF MISTAKES
/* if (DOS_PSP::rootpsp!=dos.psp) { */
// TODO: Improve this
// If prog wasnt started from commandline copy file table (California Games 2)
/* DOS_PSP oldpsp(dos.psp);
psp.CopyFileTable(&oldpsp);
} else {
psp.SetFileHandle(STDIN ,DOS_FindDevice("CON"));
psp.SetFileHandle(STDOUT,DOS_FindDevice("CON"));
psp.SetFileHandle(STDERR,DOS_FindDevice("CON"));
psp.SetFileHandle(STDAUX,DOS_FindDevice("CON"));
psp.SetFileHandle(STDNUL,DOS_FindDevice("CON"));
psp.SetFileHandle(STDPRN,DOS_FindDevice("CON"));
} */
/* Save old DTA in psp */
DOS_PSP oldpsp(dos.psp);
psp.CopyFileTable(&oldpsp,true);
psp.SetDTA(dos.dta);
/* Setup the DTA */
dos.dta=RealMake(pspseg,0x80);
/* Copy file handles */
DOS_PSP oldpsp(dos.psp());
psp.CopyFileTable(&oldpsp,true);
}
static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block)
{
static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block) {
DOS_PSP psp(pspseg);
// if cmdtail==0 it will inited as empty in SetCommandTail
psp.SetCommandTail(block.exec.cmdtail);
@ -263,14 +252,8 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
if (len<sizeof(EXE_Header)) iscom=true;
if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true;
else {
headersize=head.headersize*16;
if (head.extrabytes) {
imagesize = (head.pages-1)*512-headersize;
imagesize += head.extrabytes % 512;
} else
imagesize = head.pages*512-headersize;
// always load st least 512 Bytes (dos cache/dos bug?)
headersize = head.headersize*16;
imagesize = head.pages*512-headersize;
if (imagesize+headersize<512) imagesize = 512-headersize;
}
if (flags!=OVERLAY) {
@ -298,16 +281,20 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
else memsize=maxsize;
if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory");
loadseg=pspseg+16;
if ((!iscom) & (head.minmemory == 0) & (head.maxmemory == 0))
loadseg = (0x9e000 - imagesize)/16; //c2woody
} else loadseg=block.overlay.loadseg;
/* Load the executable */
Bit8u * loadbuf=(Bit8u *)new Bit8u[0x10000];
loadaddress=PhysMake(loadseg,0);
if (iscom) { /* COM Load 64k - 256 bytes max */
pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
readsize=0xffff-256;
DOS_ReadFile(fhandle,loadbuf,&readsize);
MEM_BlockWrite(loadaddress,loadbuf,readsize);
} else { /* EXE Load in 32kb blocks and then relocate */
} else { /* EXE Load in 32kb blocks and then relocate */
pos=headersize;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
while (imagesize>0x7FFF) {
readsize=0x8000;DOS_ReadFile(fhandle,loadbuf,&readsize);
@ -341,7 +328,6 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
SetupPSP(pspseg,memsize,envseg);
SetupCMDLine(pspseg,block);
};
CALLBACK_SCF(false); /* Carry flag cleared for caller if successfull */
if (flags==OVERLAY) return true; /* Everything done for overlays */
RealPt csip,sssp;
@ -353,14 +339,15 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
csip=RealMake(loadseg+head.initCS,head.initIP);
sssp=RealMake(loadseg+head.initSS,head.initSP);
}
if (flags==LOAD) {
DOS_PSP callpsp(dos.psp);
DOS_PSP callpsp(dos.psp());
/* Save the SS:SP on the PSP of calling program */
callpsp.SetStack(RealMakeSeg(ss,reg_sp));
/* Switch the psp's */
dos.psp=pspseg;
dos.psp(pspseg);
DOS_PSP newpsp(dos.psp());
dos.dta(RealMake(newpsp.GetSegment(),0x80));
block.exec.initsssp = sssp;
block.exec.initcsip = csip;
block.SaveData();
@ -371,14 +358,13 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
/* Get Caller's program CS:IP of the stack and set termination address to that */
RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp)));
SaveRegisters();
DOS_PSP callpsp(dos.psp);
DOS_PSP callpsp(dos.psp());
/* Save the SS:SP on the PSP of calling program */
callpsp.SetStack(RealMakeSeg(ss,reg_sp));
/* Switch the psp's and set new DTA */
dos.psp=pspseg;
DOS_PSP newpsp(dos.psp);
newpsp.SetDTA(dos.dta); /* Original: change this and line below. This way seems better(zone66 and unpack) */
//dos.dta=newpsp.GetDTA();
dos.psp(pspseg);
DOS_PSP newpsp(dos.psp());
dos.dta(RealMake(newpsp.GetSegment(),0x80));
/* save vectors */
newpsp.SaveVectors();
/* copy fcbs */
@ -399,6 +385,24 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
/* Started from debug.com, then set breakpoint at start */
DEBUG_CheckExecuteBreakpoint(RealSeg(csip),RealOff(csip));
#endif
/* Add the filename to PSP and environment MCB's */
char stripname[8];Bitu index=0;
while (char chr=*name++) {
switch (chr) {
case ':':case '\\':case '/':index=0;break;
default:if (index<8) stripname[index++]=toupper(chr);
}
}
index=0;
while (index<8) {
if (stripname[index]=='.') break;
if (!stripname[index]) break;
index++;
}
memset(&stripname[index],0,8-index);
DOS_MCB pspmcb(dos.psp()-1);
pspmcb.SetFileName(stripname);
DOS_UpdatePSPName();
return true;
}
return false;

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