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 The DOSBox Team
--------------- ---------------
Sjoerd v.d. Berg <harekiet@zophar.net> Sjoerd v.d. Berg <harekiet@users.sourceforge.net>
Peter Veenstra <qbix79@users.sourceforge.net> Peter Veenstra <qbix79@users.sourceforge.net>
Felix Jakschitsch <yot@users.sourceforge.net>
Ulf Wohlers <finsterr@users.sourceforge.net> 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 0.61
- Added a beta dynamic cpu for x86 hosts (very unstable) - Added a beta dynamic cpu for x86 hosts (very unstable)
- Added opengl and hardware overlay display output - Added opengl and hardware overlay display output

View File

@ -3,5 +3,6 @@
EXTRA_DIST = autogen.sh EXTRA_DIST = autogen.sh
SUBDIRS = src include visualc docs visualc_net 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 EXTRA_DIST = autogen.sh
SUBDIRS = src include visualc docs visualc_net SUBDIRS = src include visualc docs visualc_net
docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = README NEWS THANKS AUTHORS
subdir = . subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = config.h CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES = CONFIG_CLEAN_FILES =
DIST_SOURCES = DIST_SOURCES =
DATA = $(doc_DATA)
RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
ps-recursive install-info-recursive uninstall-info-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: distclean-hdr:
-rm -f config.h stamp-h1 -rm -f config.h stamp-h1
uninstall-info-am: 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 # This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile. # into them and run `make' without going through this Makefile.
@ -446,9 +469,10 @@ distcleancheck: distclean
exit 1; } >&2 exit 1; } >&2
check-am: all-am check-am: all-am
check: check-recursive check: check-recursive
all-am: Makefile config.h all-am: Makefile $(DATA) config.h
installdirs: installdirs-recursive installdirs: installdirs-recursive
installdirs-am: installdirs-am:
$(mkinstalldirs) $(DESTDIR)$(docdir)
install: install-recursive install: install-recursive
install-exec: install-exec-recursive install-exec: install-exec-recursive
@ -491,7 +515,7 @@ info: info-recursive
info-am: info-am:
install-data-am: install-data-am: install-docDATA
install-exec-am: install-exec-am:
@ -519,7 +543,7 @@ ps: ps-recursive
ps-am: ps-am:
uninstall-am: uninstall-info-am uninstall-am: uninstall-docDATA uninstall-info-am
uninstall-info: uninstall-info-recursive uninstall-info: uninstall-info-recursive
@ -529,16 +553,17 @@ uninstall-info: uninstall-info-recursive
distclean-hdr distclean-recursive distclean-tags distcleancheck \ distclean-hdr distclean-recursive distclean-tags distcleancheck \
distdir distuninstallcheck dvi dvi-am dvi-recursive info \ distdir distuninstallcheck dvi dvi-am dvi-recursive info \
info-am info-recursive install install-am install-data \ info-am info-recursive install install-am install-data \
install-data-am install-data-recursive install-exec \ install-data-am install-data-recursive install-docDATA \
install-exec-am install-exec-recursive install-info \ install-exec install-exec-am install-exec-recursive \
install-info-am install-info-recursive install-man \ install-info install-info-am install-info-recursive install-man \
install-recursive install-strip installcheck installcheck-am \ install-recursive install-strip installcheck installcheck-am \
installdirs installdirs-am installdirs-recursive \ installdirs installdirs-am installdirs-recursive \
maintainer-clean maintainer-clean-generic \ maintainer-clean maintainer-clean-generic \
maintainer-clean-recursive mostlyclean mostlyclean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-generic \
mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \ mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \
ps-recursive tags tags-recursive uninstall uninstall-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. # 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. # 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 0.61
- Added a beta dynamic cpu for x86 hosts (very unstable) - Added a beta dynamic cpu for x86 hosts (very unstable)
- Added opengl and hardware overlay display output - Added opengl and hardware overlay display output

605
README
View File

@ -1,4 +1,5 @@
DOSBox v0.61 DOSBox v0.62
===== =====
NOTE: NOTE:
@ -6,7 +7,7 @@ NOTE:
While we hope that, one day, DOSBox will run virtually all programs 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- 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 release has added support for "protected mode" allowing for more complex and
recent programs, but note that this support is early in development 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 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 resources and may require a much faster processor for you to run it properly
in DOSBox. 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] dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile]
[-lang languagefile] [-machine machinetype] [-noconsole] [-lang languagefile] [-machine machinetype] [-noconsole]
[-startmapper]
dosbox -version
name name
If "name" is a directory it'll mount that as the C: drive. 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". Start dosbox using the language string specified in "languagefile".
-noconsole (Windows Only) -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 be redirected to stdout.txt and stderr.txt
-machine machinetype -machine machinetype
Setup dosbox to emulate a specific type of machine. Valid choices are: 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 Note: If a name/command/configfile/languagefile contains a space in it, put
the whole name/command/configfile/languagefile between quotes("example"). 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. DOSBox supports most of the DOS commands found in command.com.
In addition, the following commands are available: In addition, the following commands are available:
MOUNT "Emulated Drive letter" "Real Drive or Directory" MOUNT "Emulated Drive letter" "Real Drive or Directory"
[-t type] [-aspi] [-ioctl] [-usecd number] [-size drivesize] [-t type] [-aspi] [-ioctl] [-usecd number] [-size drivesize]
[-label drivelabel] [-label drivelabel] [-freesize sizemb]
MOUNT -cd MOUNT -cd
Program to mount local directories as drives inside DOSBox. Program to mount local directories as drives inside DOSBox.
@ -91,7 +266,11 @@ MOUNT -cd
floppy, cdrom. floppy, cdrom.
-size drivesize -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 -label drivelabel
Sets the name of the drive to "drivelabel". Needed on some Sets the name of the drive to "drivelabel". Needed on some
@ -104,7 +283,7 @@ MOUNT -cd
-ioctl -ioctl
Forces to use ioctl commands. Only valid if mounting a cdrom under 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 -usecd number
Forces to use SDL cdrom support for drive 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" 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 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. programs that demand specific drive letters.
For example: Touche: Adventures of The Fifth Musketeer must be run on your C: 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 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 were in D:\TOUCHE, you can use the command MOUNT C D:\ would allow you to
run Touche from the D drive. run Touche from the D drive.
@ -131,14 +310,16 @@ MOUNT -cd
General MOUNT Examples: General MOUNT Examples:
1. To mount c:\floppy as a floppy : 1. To mount c:\floppy as a floppy :
mount a c:\floppy -t 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 mount d e:\ -t cdrom
3. To mount system cdrom drive at mountpoint /media/cdrom as cdrom drive D 3. To mount system cdrom drive at mountpoint /media/cdrom as cdrom drive D
in dosbox: in dosbox:
mount d /media/cdrom -t cdrom -usecd 0 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 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 mount c /home/dos/dosgames
MEM MEM
@ -173,31 +354,272 @@ Examples:
3. To free previous allocated memory : 3. To free previous allocated memory :
loadfix -f 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. For more information use the /? command line switch with the programs.
=============
Special Keys: ================
============= 5. Special Keys:
================
ALT-ENTER Go full screen and back. ALT-ENTER Go full screen and back.
CTRL-F5 Save a screenshot. CTRL-F1 Start the keymapper.
CTRL-F6 Start/Stop recording sound output to a wave file. CTRL-F4 Swap mounted disk-image (Only used with imgmount).
CTRL-F7 Decrease frameskip. CTRL-F5 Save a screenshot.
CTRL-F8 Increase frameskip. 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-F9 Kill dosbox.
CTRL-F10 Capture/Release the mouse. CTRL-F10 Capture/Release the mouse.
CTRL-F11 Slow down emulation (Decrease DOSBox Cycles). CTRL-F11 Slow down emulation (Decrease DOSBox Cycles).
CTRL-F12 Speed up emulation (Increase DOSox 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 NOTE: Once you increase your DOSBox cycles beyond your computer's maximum
capacity, it will produce the same effect as slowing down the emulation. capacity, it will produce the same effect as slowing down the emulation.
This maximum will vary from computer to computer, there is no standard. 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 Fast machine. My guess would be pentium-2 400+ to get decent emulation
of games written for an 286 machine. 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. 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 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 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. 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. 9. The Config File:
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:
================
A config file can be generated by CONFIG.COM, which can be found on the 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 internal dosbox Z: drive when you start up dosbox. Look in the internal
programs section of the readme for usage of CONFIG.COM. programs section of the readme for usage of CONFIG.COM.
You can edit the generated configfile to customize DOSBox. You can edit the generated configfile to customize DOSBox.
The file is divided into several sections (the names have [] around it). The file is divided into several sections (the names have [] around it).
Some sections have options which you can set. Some sections have options which you can set.
# and % indicate comment-lines. # and % indicate comment-lines.
The generated configfile contains the current settings. You can alter them and 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. 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 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), current directory for dosbox.conf. Then it will look for ~/.dosboxrc (Linux),
~\dosbox.conf (win32) or "~/Library/Preferences/DOSBox Preferences" (MACOSX). ~\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. A language file can be generated by CONFIG.COM.
Read it and you will hopefully understand how to change it. 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. 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. Download the source.
Check the INSTALL in the source distribution. Check the INSTALL in the source distribution.
===============
Special Thanks:
=============== ===================
12. Special Thanks:
===================
Vlad R. of the vdmsound project for excellent sound blaster info. Vlad R. of the vdmsound project for excellent sound blaster info.
Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator. 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. Colin Snover for hosting our forum.
The Beta Testers. The Beta Testers.
========
Contact:
========
Harekiet harekiet@zophar.net
============
13. Contact:
============
See the site:
http://dosbox.sourceforge.net 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 AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
dnl dnl
AC_DEFUN(AM_PATH_SDL, AC_DEFUN([AM_PATH_SDL],
[dnl [dnl
dnl Get the cflags and libraries from the sdl-config script dnl Get the cflags and libraries from the sdl-config script
dnl dnl
@ -174,7 +174,7 @@ dnl
dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified, 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 and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result.
dnl dnl
AC_DEFUN(AM_PATH_ALSA, AC_DEFUN([AM_PATH_ALSA],
[dnl Save the original CFLAGS, LDFLAGS, and LIBS [dnl Save the original CFLAGS, LDFLAGS, and LIBS
alsa_save_CFLAGS="$CFLAGS" alsa_save_CFLAGS="$CFLAGS"
alsa_save_LDFLAGS="$LDFLAGS" alsa_save_LDFLAGS="$LDFLAGS"
@ -305,7 +305,7 @@ AC_SUBST(ALSA_LIBS)
AH_TOP([ 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -331,4 +331,49 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE
#define GCC_ATTRIBUTE(x) /* attribute not supported */ #define GCC_ATTRIBUTE(x) /* attribute not supported */
#endif]) #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 AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
dnl dnl
AC_DEFUN(AM_PATH_SDL, AC_DEFUN([AM_PATH_SDL],
[dnl [dnl
dnl Get the cflags and libraries from the sdl-config script dnl Get the cflags and libraries from the sdl-config script
dnl dnl
@ -187,7 +187,7 @@ dnl
dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified, 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 and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result.
dnl dnl
AC_DEFUN(AM_PATH_ALSA, AC_DEFUN([AM_PATH_ALSA],
[dnl Save the original CFLAGS, LDFLAGS, and LIBS [dnl Save the original CFLAGS, LDFLAGS, and LIBS
alsa_save_CFLAGS="$CFLAGS" alsa_save_CFLAGS="$CFLAGS"
alsa_save_LDFLAGS="$LDFLAGS" alsa_save_LDFLAGS="$LDFLAGS"
@ -318,7 +318,7 @@ AC_SUBST(ALSA_LIBS)
AH_TOP([ 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -344,7 +344,52 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE
#define GCC_ATTRIBUTE(x) /* attribute not supported */ #define GCC_ATTRIBUTE(x) /* attribute not supported */
#endif]) #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 -*- # 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -26,6 +26,9 @@
/* Define to 1 to enable internal debugger, requires libcurses */ /* Define to 1 to enable internal debugger, requires libcurses */
#undef C_DEBUG #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 */ /* Define to 1 to use x86 dynamic cpu core */
#undef C_DYNAMIC_X86 #undef C_DYNAMIC_X86
@ -41,12 +44,21 @@
/* The type of cpu this host has */ /* The type of cpu this host has */
#undef C_HOSTCPU #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 */ /* Define to 1 to enable internal modem support, requires SDL_net */
#undef C_MODEM #undef C_MODEM
/* Define to 1 to use opengl display output support */ /* Define to 1 to use opengl display output support */
#undef C_OPENGL #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 */ /* Define to 1 to enable screenshots, requires libpng */
#undef C_SSHOT #undef C_SSHOT
@ -59,6 +71,9 @@
/* Define to 1 to use ALSA for MIDI */ /* Define to 1 to use ALSA for MIDI */
#undef HAVE_ALSA #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. */ /* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H #undef HAVE_INTTYPES_H
@ -113,6 +128,24 @@
/* Define to the version of this package. */ /* Define to the version of this package. */
#undef PACKAGE_VERSION #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. */ /* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS #undef STDC_HEADERS
@ -145,3 +178,50 @@
#else #else
#define GCC_ATTRIBUTE(x) /* attribute not supported */ #define GCC_ATTRIBUTE(x) /* attribute not supported */
#endif #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 #! /bin/sh
# Configuration validation subroutine script. # Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 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. # This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME 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="\ version="\
GNU config.sub ($timestamp) 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. Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO 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* |\ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis) -apple | -axis | -knuth | -cray)
os= os=
basic_machine=$1 basic_machine=$1
;; ;;
@ -237,7 +237,7 @@ case $basic_machine in
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \ | i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \ | ip2k | iq2000 \
| m32r | m68000 | m68k | m88k | mcore \ | m32r | m32rle | m68000 | m68k | m88k | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \ | mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \ | mips16 \
| mips64 | mips64el \ | mips64 | mips64el \
@ -262,7 +262,7 @@ case $basic_machine in
| pyramid \ | pyramid \
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \ | sh64 | sh64le \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
| strongarm \ | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \ | tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \ | v850 | v850e \
@ -300,7 +300,7 @@ case $basic_machine in
| avr-* \ | avr-* \
| bs2000-* \ | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | cydra-* \ | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \ | d10v-* | d30v-* | dlx-* \
| elxsi-* \ | elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
@ -308,7 +308,7 @@ case $basic_machine in
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \ | i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \ | ip2k-* | iq2000-* \
| m32r-* \ | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | mcore-* \ | m88110-* | m88k-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
@ -326,8 +326,9 @@ case $basic_machine in
| mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \ | mipstx39-* | mipstx39el-* \
| mmix-* \
| msp430-* \ | msp430-* \
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | none-* | np1-* | ns16k-* | ns32k-* \
| orion-* \ | orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
@ -336,7 +337,7 @@ case $basic_machine in
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \ | tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \ | tron-* \
@ -363,6 +364,9 @@ case $basic_machine in
basic_machine=a29k-amd basic_machine=a29k-amd
os=-udi os=-udi
;; ;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k) adobe68k)
basic_machine=m68010-adobe basic_machine=m68010-adobe
os=-scout os=-scout
@ -442,12 +446,24 @@ case $basic_machine in
basic_machine=j90-cray basic_machine=j90-cray
os=-unicos os=-unicos
;; ;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16c)
basic_machine=cr16c-unknown
os=-elf
;;
crds | unos) crds | unos)
basic_machine=m68k-crds basic_machine=m68k-crds
;; ;;
cris | cris-* | etrax*) cris | cris-* | etrax*)
basic_machine=cris-axis basic_machine=cris-axis
;; ;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*) da30 | da30-*)
basic_machine=m68k-da30 basic_machine=m68k-da30
;; ;;
@ -648,10 +664,6 @@ case $basic_machine in
mips3*) mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;; ;;
mmix*)
basic_machine=mmix-knuth
os=-mmixware
;;
monitor) monitor)
basic_machine=m68k-rom68k basic_machine=m68k-rom68k
os=-coff os=-coff
@ -732,10 +744,6 @@ case $basic_machine in
np1) np1)
basic_machine=np1-gould basic_machine=np1-gould
;; ;;
nv1)
basic_machine=nv1-cray
os=-unicosmp
;;
nsr-tandem) nsr-tandem)
basic_machine=nsr-tandem basic_machine=nsr-tandem
;; ;;
@ -1048,6 +1056,9 @@ case $basic_machine in
romp) romp)
basic_machine=romp-ibm basic_machine=romp-ibm
;; ;;
mmix)
basic_machine=mmix-knuth
;;
rs6000) rs6000)
basic_machine=rs6000-ibm basic_machine=rs6000-ibm
;; ;;
@ -1070,7 +1081,7 @@ case $basic_machine in
sh64) sh64)
basic_machine=sh64-unknown basic_machine=sh64-unknown
;; ;;
sparc | sparcv9 | sparcv9b) sparc | sparcv8 | sparcv9 | sparcv9b)
basic_machine=sparc-sun basic_machine=sparc-sun
;; ;;
cydra) cydra)
@ -1143,8 +1154,9 @@ case $os in
| -aos* \ | -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \ | -chorusos* | -chorusrdb* \
@ -1362,6 +1374,9 @@ case $basic_machine in
*-ibm) *-ibm)
os=-aix os=-aix
;; ;;
*-knuth)
os=-mmixware
;;
*-wec) *-wec)
os=-proelf os=-proelf
;; ;;

2961
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
dnl Init. dnl Init.
AC_INIT(dosbox,0.61) AC_INIT(dosbox,0.62)
AC_PREREQ(2.50) AC_PREREQ(2.50)
AC_CONFIG_SRCDIR(README) AC_CONFIG_SRCDIR(README)
@ -26,7 +26,7 @@ AM_PATH_SDL($SDL_VERSION,
AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
) )
LIBS="$LIBS $SDL_LIBS" LIBS="$LIBS $SDL_LIBS"
CXXFLAGS="$CXXFLAGS $SDL_CFLAGS" CPPFLAGS="$CPPFLAGS $SDL_CFLAGS"
dnl Checks for header files. dnl Checks for header files.
@ -35,7 +35,12 @@ AC_C_CONST
AC_C_INLINE AC_C_INLINE
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
AC_STRUCT_TM 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_MSG_CHECKING(if environ can be included)
AC_TRY_LINK([#include <unistd.h> AC_TRY_LINK([#include <unistd.h>
@ -143,13 +148,15 @@ else
fi fi
AH_TEMPLATE(C_MODEM,[Define to 1 to enable internal modem support, requires SDL_net]) 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, , ) 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 if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then
LIBS="$LIBS -lSDL_net" LIBS="$LIBS -lSDL_net"
AC_DEFINE(C_MODEM,1) AC_DEFINE(C_MODEM,1)
AC_DEFINE(C_IPX,1)
else 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 fi
AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support]) AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support])
@ -170,10 +177,32 @@ else
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
fi 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 dnl Some host detection and actions for them
case "$target" in case "$target" in
*-*-cygwin* | *-*-mingw32*) *-*-cygwin* | *-*-mingw32*)
LIBS="$LIBS -lwinmm" 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*) *-*-darwin*)
dnl We have a problem here: both MacOS X and Darwin report dnl We have a problem here: both MacOS X and Darwin report

View File

@ -1,16 +1,20 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH DOSBOX 1 "October 5, 2003" .TH DOSBOX 1 "Sept 23, 2004"
.\" Please adjust this date whenever revising the manpage. .\" Please adjust this date whenever revising the manpage.
.SH NAME .SH NAME
dosbox \- an x86/DOS emulator with sound/graphics dosbox \- an x86/DOS emulator with sound/graphics
.SH SYNOPSIS .SH SYNOPSIS
.B dosbox .B dosbox
.B [\-fullscreen] .B [\-fullscreen]
.B [\-startmapper]
.BI "[\-conf " configfile ] .BI "[\-conf " configfile ]
.BI "[\-lang " langfile ] .BI "[\-lang " langfile ]
.B [file] .B [file]
.BI "[\-c " command ] .BI "[\-c " command ]
.B [\-exit] .B [\-exit]
.BI "[\-machine " machinetype ]
.LP
.B dosbox -version
.SH DESCRIPTION .SH DESCRIPTION
This manual page briefly documents This manual page briefly documents
.BR "dosbox" ", an x86/DOS emulator." .BR "dosbox" ", an x86/DOS emulator."
@ -22,6 +26,9 @@ A summary of options is included below.
.B \-fullscreen .B \-fullscreen
.RB "Start " dosbox " in fullscreen mode." .RB "Start " dosbox " in fullscreen mode."
.TP .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" .BI \-c " command"
.RI "Runs the specified " command " before running " .RI "Runs the specified " command " before running "
.BR file . .BR file .
@ -38,6 +45,13 @@ A summary of options is included below.
.TP .TP
.B \-exit .B \-exit
.BR dosbox " will exit after running the program specified by " file . .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" .SH "INTERNAL COMMANDS"
.B dosbox .B dosbox
supports most of the DOS commands found in command.com. In addition, the 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 ] .BI "MOUNT [\-t " type "] [\-size " size ]
.I driveletter sourcedirectory .I driveletter sourcedirectory
.B [\-aspi] [\-ioctl] .B [\-aspi] [\-ioctl]
.BI "[\-usecd " number "] [\-label " drivelabel ] .BI "[\-usecd " number "] [\-label " drivelabel "] [\-freesize " freesize ]
.LP .LP
.B MOUNT \-cd .B MOUNT \-cd
.LP .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. Type of the mounted directory. Supported are: dir (standard), floppy, cdrom.
.TP .TP
.BI \-size " drivesize" .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 .TP
.BI \-label " drivelabel" .BI \-label " drivelabel"
.RI "Sets the name of the drive to " drivelabel ". Needed on some" .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 .B \-f
Frees all memory eaten up by loadfix. Frees all memory eaten up by loadfix.
.RE .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 .SH FILES
Configuration and language files use a format similar to Windows .ini files. If a file named 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." .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 .TP 12m
.IP ALT\-ENTER .IP ALT\-ENTER
Go full screen and back. 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 .IP CTRL\-F5
Save a screenshot. Save a screenshot.
.IP CTRL\-F6 .IP CTRL\-F6
Start/Stop recording sound output to a wave file. 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 .IP CTRL\-F7
Decrease frameskip. Decrease frameskip.
.IP CTRL\-F8 .IP CTRL\-F8
@ -147,8 +197,9 @@ Slow down emulation (Increase DOSBox Cycles).
.IP CTRL\-F12 .IP CTRL\-F12
Speed up emulation (Decrease DOSBox Cycles). Speed up emulation (Decrease DOSBox Cycles).
.PP .PP
.B "Note: " These are the default keybindings. They can be changed in the keymapper.
Once you increase your DOSBox cycles beyond your computer's maximum .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. capacity, it will produce the same effect as slowing down the emulation.
This maximum will vary from computer to computer, there is no standard. This maximum will vary from computer to computer, there is no standard.
.SH "SYSTEM REQUIREMENTS" .SH "SYSTEM REQUIREMENTS"

View File

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

View File

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

View File

@ -9,13 +9,16 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#ifndef _BIOS_H_
#define _BIOS_H_
#define BIOS_BASE_ADDRESS_COM1 0x400 #define BIOS_BASE_ADDRESS_COM1 0x400
#define BIOS_BASE_ADDRESS_COM2 0x402 #define BIOS_BASE_ADDRESS_COM2 0x402
#define BIOS_BASE_ADDRESS_COM3 0x404 #define BIOS_BASE_ADDRESS_COM3 0x404
@ -88,6 +91,8 @@
#define BIOS_WAIT_FLAG_POINTER 0x498 #define BIOS_WAIT_FLAG_POINTER 0x498
#define BIOS_WAIT_FLAG_COUNT 0x49c #define BIOS_WAIT_FLAG_COUNT 0x49c
#define BIOS_WAIT_FLAG_ACTIVE 0x4a0 #define BIOS_WAIT_FLAG_ACTIVE 0x4a0
#define BIOS_WAIT_FLAG_TEMP 0x4a1
#define BIOS_PRINT_SCREEN_FLAG 0x500 #define BIOS_PRINT_SCREEN_FLAG 0x500
@ -96,23 +101,57 @@
/* The Section handling Bios Disk Access */ /* The Section handling Bios Disk Access */
#define BIOS_MAX_DISK 10 #define BIOS_MAX_DISK 10
class BIOS_Disk { struct diskGeo {
public: Bit32u ksize; /* Size in kilobytes */
virtual Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0; Bit16u secttrack; /* Sectors per track */
virtual Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0; 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: public:
Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data); Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data); Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
imageDisk(char * file); Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
private: Bit8u Write_AbsoluteSector(Bit32u sectnum, void * data);
Bit16u sector_size;
Bit16u heads,cylinders,sectors; void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
Bit8u * image; 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 BIOS_ZeroExtendedSize(void);
void char_out(Bit8u chr,Bit32u att,Bit8u page); void char_out(Bit8u chr,Bit32u att,Bit8u page);
@ -123,4 +162,4 @@ void INT2F_StartUp(void);
void INT33_StartUp(void); void INT33_StartUp(void);
void INT13_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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -35,6 +35,7 @@ extern CPU_Decoder * cpudecoder;
Bits CPU_Core_Normal_Run(void); Bits CPU_Core_Normal_Run(void);
Bits CPU_Core_Normal_Trap_Run(void); Bits CPU_Core_Normal_Trap_Run(void);
Bits CPU_Core_Simple_Run(void);
Bits CPU_Core_Full_Run(void); Bits CPU_Core_Full_Run(void);
Bits CPU_Core_Dyn_X86_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_SIDT(Bitu & limit,Bitu & base);
void CPU_SGDT(Bitu & limit,Bitu & base); void CPU_SGDT(Bitu & limit,Bitu & base);
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel); void CPU_ARPL(Bitu & dest_sel,Bitu src_sel);
void CPU_LAR(Bitu selector,Bitu & ar); void CPU_LAR(Bitu selector,Bitu & ar);
void CPU_LSL(Bitu selector,Bitu & limit); 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); Bitu CPU_GET_CRX(Bitu cr);
void CPU_SMSW(Bitu & word); void CPU_SMSW(Bitu & word);
bool CPU_LMSW(Bitu word); Bitu CPU_LMSW(Bitu word);
void CPU_VERR(Bitu selector); void CPU_VERR(Bitu selector);
void CPU_VERW(Bitu selector); void CPU_VERW(Bitu selector);
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen=0); void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen=0); void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
void CPU_RET(bool use32,Bitu bytes,Bitu opLen=0); 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_SOFTWARE 0x1
#define CPU_INT_EXCEPTION 0x2 #define CPU_INT_EXCEPTION 0x2
#define CPU_INT_HAS_ERROR 0x4 #define CPU_INT_HAS_ERROR 0x4
void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip);
void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen=0);
INLINE void CPU_HW_Interrupt(Bitu num) { 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) { INLINE void CPU_SW_Interrupt(Bitu num,Bitu oldeip) {
CPU_Interrupt(num,CPU_INT_SOFTWARE,OpLen); CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip);
} }
bool CPU_PrepareException(Bitu which,Bitu error);
void CPU_Exception(Bitu which,Bitu error=0); 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); bool CPU_SetSegGeneral(SegNames seg,Bitu value);
void CPU_HLT(Bitu opLen); bool CPU_PopSeg(SegNames seg,bool use32);
void CPU_CPUID(void); void CPU_CPUID(void);
Bitu CPU_Pop16(void); Bitu CPU_Pop16(void);
@ -407,5 +416,6 @@ INLINE void CPU_SetFlagsw(Bitu word) {
CPU_SetFlags(word,mask); CPU_SetFlags(word,mask);
}; };
#endif #endif

View File

@ -9,14 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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 #ifndef _CROSS_H
#define _CROSS_H #define _CROSS_H
@ -29,6 +29,8 @@
#include <direct.h> #include <direct.h>
#include <io.h> #include <io.h>
#define LONGTYPE(a) a##i64 #define LONGTYPE(a) a##i64
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#else /* LINUX / GCC */ #else /* LINUX / GCC */
#include <dirent.h> #include <dirent.h>
#include <unistd.h> #include <unistd.h>
@ -39,7 +41,7 @@
#if defined (WIN32) /* Win 32 */ #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 CROSS_FILESPLIT '\\'
#define F_OK 0 #define F_OK 0
#else #else

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,187 +9,85 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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 #ifndef __DMA_H
#define __DMA_H #define __DMA_H
#include "mem.h" enum DMAEvent {
DMA_REACHED_TC,
DMA_MASKED,
DMA_UNMASKED,
DMA_TRANSFEREND
};
#define DMA_MODE_DEMAND 0 class DmaChannel;
#define DMA_MODE_SINGLE 1 typedef void (* DMA_CallBack)(DmaChannel * chan,DMAEvent event);
#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 DmaController { class DmaController {
public: public:
bool flipflop; bool flipflop;
Bit8u ctrlnum; Bit8u ctrlnum;
Bit8u chanbase;
public: public:
DmaController(Bit8u num) { DmaController(Bit8u num) {
int i; flipflop = false;
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;
ctrlnum = num; ctrlnum = num;
chanbase = num * 4;
} }
Bit16u portRead(Bit32u port, bool eightbit);
void portWrite(Bit32u port, Bit16u val, bool eightbit);
}; };
class DmaChannel { class DmaChannel {
public: public:
Bit32u pagebase;
Bit8u channum;
Bit16u baseaddr; Bit16u baseaddr;
Bit16u current_addr; Bit16u curraddr;
Bit16u pageaddr; Bit16u basecnt;
PhysPt physaddr; Bit16u currcnt;
PhysPt curraddr; Bit8u channum;
Bit32s transcnt; Bit8u pagenum;
Bit32s currcnt; Bit8u DMA16;
DmaController *myController; bool increment;
bool DMA16;
bool addr_changed;
public:
Bit8u dmamode;
bool dir;
bool autoinit; bool autoinit;
Bit8u trantype; Bit8u trantype;
bool masked; bool masked;
bool enabled; bool tcount;
DMA_EnableCallBack enable_callback; DMA_CallBack callback;
DMA_NewCallBack newcallback;
DmaChannel(Bit8u num, DmaController *useController, bool sb) { DmaChannel(Bit8u num, bool dma16);
int i; void DoCallBack(DMAEvent event) {
masked = true; if (callback) (*callback)(this,event);
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;
} }
void SetMask(bool _mask) {
void RegisterCallback(DMA_NewCallBack useCallBack) { newcallback = useCallBack; } masked=_mask;
DoCallBack(masked ? DMA_MASKED : DMA_UNMASKED);
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 Register_Callback(DMA_CallBack _cb) {
void MakeCallback(bool tc) { callback = _cb;
if (newcallback != NULL) { SetMask(masked);
if(tc) {
(*newcallback)(this, true);
} else {
if ((enabled) && (!masked) && (transcnt!=0)) {
(*newcallback)(this, false);
}
}
}
} }
void ReachedTC(void) {
Bit32u Read(Bit32s requestsize, Bit8u * buffer); tcount=true;
DoCallBack(DMA_REACHED_TC);
Bit32u Write(Bit32s requestsize, Bit8u * buffer); }
void SetPage(Bit8u val) {
void calcPhys(void); pagenum=val;
pagebase=(pagenum >> DMA16) << (16+DMA16);
Bit16u portRead(Bit32u port, bool eightbit); }
Bitu Read(Bitu size, Bit8u * buffer);
void portWrite(Bit32u port, Bit16u val, bool eightbit); Bitu Write(Bitu size, Bit8u * buffer);
// Notify channel when mask changes
void Notify(void);
}; };
extern DmaChannel *DmaChannels[8]; extern DmaChannel *DmaChannels[8];
extern DmaController *DmaControllers[2]; extern DmaController *DmaControllers[2];
#endif #endif

View File

@ -9,13 +9,15 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: dos_inc.h,v 1.48 2004/08/04 09:12:50 qbix79 Exp $ */
#ifndef DOS_H_ #ifndef DOS_H_
#define DOS_H_ #define DOS_H_
@ -43,27 +45,25 @@ struct DOS_Version {
Bit8u major,minor,revision; Bit8u major,minor,revision;
}; };
struct DOS_Block {
DOS_Date date; #ifdef _MSC_VER
DOS_Version version; #pragma pack (1)
Bit16u firstMCB; #endif
Bit16u errorcode; union bootSector {
Bit16u psp; struct entries {
Bit16u env; Bit8u jump[3];
RealPt cpmentry; Bit8u oem_name[8];
RealPt dta; Bit16u bytesect;
Bit8u return_code,return_mode; Bit8u sectclust;
Bit16u reserve_sect;
Bit8u current_drive; Bit8u misc[496];
bool verify; } bootdata;
bool breakcheck; Bit8u rawdata[512];
bool echo; // if set to true dev_con::read will echo input } GCC_ATTRIBUTE(packed);
struct { #ifdef _MSC_VER
RealPt indosflag; #pragma pack ()
RealPt mediaid; #endif
RealPt tempdta;
} tables;
};
enum { MCB_FREE=0x0000,MCB_DOS=0x0008 }; enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3}; 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 #define DOS_DRIVES 26
/* internal Dos Tables */ /* internal Dos Tables */
extern DOS_Block dos;
extern DOS_File * Files[DOS_FILES]; extern DOS_File * Files[DOS_FILES];
extern DOS_Drive * Drives[DOS_DRIVES]; extern DOS_Drive * Drives[DOS_DRIVES];
extern Bit8u dos_copybuf[0x10000]; 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_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status);
bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry); bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry);
bool DOS_UnlinkFile(char * name); bool DOS_UnlinkFile(char * name);
bool DOS_FindFirst(char *search,Bit16u attr); bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false);
bool DOS_FindNext(void); bool DOS_FindNext(void);
bool DOS_Canonicalize(char * name,char * big); bool DOS_Canonicalize(char * name,char * big);
bool DOS_CreateTempFile(char * name,Bit16u * entry); 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 */ /* Remains some classes used to access certain things */
#define sOffset(s,m) ((char*)&(((s*)NULL)->m)-(char*)NULL)
#define sGet(s,m) GetIt(((s *)0)->m,(PhysPt)&(((s *)0)->m)) #define sGet(s,m) GetIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m))
#define sSave(s,m,val) SaveIt(((s *)0)->m,(PhysPt)&(((s *)0)->m),val) #define sSave(s,m,val) SaveIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m),val)
class MemStruct { class MemStruct {
public: public:
INLINE Bit8u GetIt(Bit8u&,PhysPt addr) { INLINE Bitu GetIt(Bitu size,PhysPt addr) {
return mem_readb(pt+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) { INLINE void SaveIt(Bitu size,PhysPt addr,Bitu val) {
return mem_readw(pt+addr); switch (size) {
} case 1:mem_writeb(pt+addr,val);break;
INLINE Bit32u GetIt(Bit32u&,PhysPt addr) { case 2:mem_writew(pt+addr,val);break;
return mem_readd(pt+addr); case 4:mem_writed(pt+addr,val);break;
} }
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 SetPt(Bit16u seg) { pt=PhysMake(seg,0);} INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);}
INLINE void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);} INLINE void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);}
@ -252,8 +248,6 @@ public:
void RestoreVectors (void); void RestoreVectors (void);
void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); }; void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); };
Bit16u GetSize (void) { return sGet(sPSP,next_seg); }; 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); }; void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); };
Bit16u GetEnvironment (void) { return sGet(sPSP,environment); }; Bit16u GetEnvironment (void) { return sGet(sPSP,environment); };
Bit16u GetSegment (void) { return seg; }; Bit16u GetSegment (void) { return seg; };
@ -291,8 +285,11 @@ private:
Bit16u max_files; /* Maximum open files */ Bit16u max_files; /* Maximum open files */
RealPt file_table; /* Pointer to File Table PSP:0x18 */ RealPt file_table; /* Pointer to File Table PSP:0x18 */
RealPt prev_psp; /* Pointer to previous PSP */ RealPt prev_psp; /* Pointer to previous PSP */
RealPt dta; /* Pointer to current Process DTA */ Bit8u interim_flag;
Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */ 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 service[3]; /* INT 0x21 Service call int 0x21;retf; */
Bit8u fill_3[9]; /* This has some blocks with FCB info */ Bit8u fill_3[9]; /* This has some blocks with FCB info */
Bit8u fcb1[16]; /* first FCB */ Bit8u fcb1[16]; /* first FCB */
@ -343,25 +340,50 @@ public:
void SetFirstMCB(Bit16u _first_mcb); void SetFirstMCB(Bit16u _first_mcb);
void SetfirstFileTable(RealPt _first_table); void SetfirstFileTable(RealPt _first_table);
void SetBuffers(Bit16u x,Bit16u y); 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); RealPt GetPointer (void);
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma pack(1) #pragma pack(1)
#endif #endif
struct sDIB { struct sDIB {
Bit8u stuff1[22]; // -0x18 some stuff, hopefully never used.... Bit16u regCXfrom5e; // -0x18 CX from last int21/ah=5e
Bit16u firstMCB; // -0x2 first memory control block Bit16u countLRUcache; // -0x16 LRU counter for FCB caching
RealPt firstDPB; // 0x00 first drive parameter block 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 firstFileTable; // 0x04 first system file table
RealPt activeClock; // 0x08 active clock device header 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; 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 curDirStructure; // 0x16 pointer to current array of directory structure
RealPt fcbTable; // 0x1a pointer to system FCB table RealPt fcbTable; // 0x1a pointer to system FCB table
Bit8u stuff2[0x21]; // 0x1e more stuff Bit16u protFCBs; // 0x1e protected fcbs
Bit16u buffers_x; // x in BUFFERS x,y Bit8u blockDevices; // 0x20 installed block devices
Bit16u buffers_y; // y in BUFFERS x,y 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. // some more stuff, hopefully never used.
} GCC_ATTRIBUTE(packed); } GCC_ATTRIBUTE(packed);
#ifdef _MSC_VER #ifdef _MSC_VER
@ -389,9 +411,9 @@ private:
#endif #endif
struct sDTA { struct sDTA {
Bit8u sdrive; /* The Drive the search is taking place */ 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 sname[8]; /* The Search pattern for the filename */
Bit8u sext[3]; /* The Search pattern for the extenstion */ 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 */ Bit16u dirID; /* custom: dir-search ID for multiple searches at the same time */
Bit8u fill[6]; Bit8u fill[6];
Bit8u attr; Bit8u attr;
@ -422,6 +444,8 @@ public:
void SetRandom(Bit32u _random); void SetRandom(Bit32u _random);
Bit8u GetDrive(void); Bit8u GetDrive(void);
bool Extended(void); bool Extended(void);
void GetAttr(Bit8u & attr);
void SetAttr(Bit8u attr);
private: private:
bool extended; bool extended;
PhysPt real_pt; PhysPt real_pt;
@ -438,8 +462,11 @@ private:
Bit16u date; Bit16u date;
Bit16u time; Bit16u time;
/* Reserved Block should be 8 bytes */ /* Reserved Block should be 8 bytes */
Bit8u sft_entries;
Bit8u share_attributes;
Bit8u extra_info;
Bit8u file_handle; Bit8u file_handle;
Bit8u reserved[7]; Bit8u reserved[4];
/* end */ /* end */
Bit8u cur_rec; /* Current record in current block */ Bit8u cur_rec; /* Current record in current block */
Bit32u rndm; /* Current relative record number */ Bit32u rndm; /* Current relative record number */
@ -476,10 +503,78 @@ private:
#endif #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) { INLINE Bit8u RealHandle(Bit16u handle) {
DOS_PSP psp(dos.psp); DOS_PSP psp(dos.psp());
return psp.GetFileHandle(handle); return psp.GetFileHandle(handle);
} }

View File

@ -9,14 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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_ #ifndef DOSSYSTEM_H_
#define DOSSYSTEM_H_ #define DOSSYSTEM_H_
@ -54,7 +54,7 @@ class DOS_DTA;
class DOS_File { class DOS_File {
public: public:
DOS_File():flags(0) { name=0; refCtr = 0; }; 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 Read(Bit8u * data,Bit16u * size)=0;
virtual bool Write(Bit8u * data,Bit16u * size)=0; virtual bool Write(Bit8u * data,Bit16u * size)=0;
virtual bool Seek(Bit32u * pos,Bit32u type)=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 bool IsName(const char* _name) { if (!name) return false; return strcmp(name,_name)==0; };
virtual void AddRef() { refCtr++; }; virtual void AddRef() { refCtr++; };
virtual Bits RemoveRef() { return --refCtr; }; virtual Bits RemoveRef() { return --refCtr; };
virtual bool UpdateDateTimeFromHost() { return true; }
Bit8u type; Bit8u type;
Bit32u flags; Bit32u flags;
Bit16u time; Bit16u time;
@ -85,8 +86,8 @@ public:
Bit8u fhandle; 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 { class DOS_Drive_Cache {
public: public:
DOS_Drive_Cache (void); DOS_Drive_Cache (void);
@ -104,7 +105,7 @@ public:
char* GetExpandName (const char* path); char* GetExpandName (const char* path);
bool GetShortName (const char* fullname, char* shortname); 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); bool FindNext (Bitu id, char* &result);
void CacheOut (const char* path, bool ignoreLastDir = false); void CacheOut (const char* path, bool ignoreLastDir = false);
@ -119,21 +120,19 @@ public:
public: public:
CFileInfo(void) { CFileInfo(void) {
orgname[0] = shortname[0] = 0; orgname[0] = shortname[0] = 0;
nextEntry = shortNr = compareCount = 0; nextEntry = shortNr = 0;
isDir = false; isDir = false;
} }
~CFileInfo(void) { ~CFileInfo(void) {
for (Bit32u i=0; i<fileList.size(); i++) delete fileList[i]; for (Bit32u i=0; i<fileList.size(); i++) delete fileList[i];
fileList.clear(); fileList.clear();
longNameList.clear(); longNameList.clear();
compareCount = 0;
}; };
char orgname [CROSS_LEN]; char orgname [CROSS_LEN];
char shortname [DOS_NAMELENGTH_ASCII]; char shortname [DOS_NAMELENGTH_ASCII];
bool isDir; bool isDir;
Bitu nextEntry; Bitu nextEntry;
Bitu shortNr; Bitu shortNr;
Bitu compareCount;
// contents // contents
std::vector<CFileInfo*> fileList; std::vector<CFileInfo*> fileList;
std::vector<CFileInfo*> longNameList; std::vector<CFileInfo*> longNameList;
@ -142,18 +141,18 @@ public:
private: private:
bool RemoveTrailingDot (char* shortname); bool RemoveTrailingDot (char* shortname);
Bits GetLongName (CFileInfo* info, char* shortname); Bits GetLongName (CFileInfo* info, char* shortname);
void CreateShortName (CFileInfo* dir, CFileInfo* info); void CreateShortName (CFileInfo* dir, CFileInfo* info);
Bit16u CreateShortNameID (CFileInfo* dir, const char* name); Bit16u CreateShortNameID (CFileInfo* dir, const char* name);
int CompareShortname (const char* compareName, const char* shortName); int CompareShortname (const char* compareName, const char* shortName);
bool SetResult (CFileInfo* dir, char * &result, Bit16u entryNr); bool SetResult (CFileInfo* dir, char * &result, Bit16u entryNr);
bool IsCachedIn (CFileInfo* dir); bool IsCachedIn (CFileInfo* dir);
CFileInfo* FindDirInfo (const char* path, char* expandedPath); CFileInfo* FindDirInfo (const char* path, char* expandedPath);
bool RemoveSpaces (char* str); bool RemoveSpaces (char* str);
bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id); bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id);
void CreateEntry (CFileInfo* dir, const char* name); void CreateEntry (CFileInfo* dir, const char* name);
Bit16u GetFreeID (CFileInfo* dir); Bit16u GetFreeID (CFileInfo* dir);
void Clear (void); void Clear (void);
CFileInfo* dirBase; CFileInfo* dirBase;
char dirPath [CROSS_LEN]; char dirPath [CROSS_LEN];
@ -169,6 +168,7 @@ private:
char dirSearchName [MAX_OPENDIRS]; char dirSearchName [MAX_OPENDIRS];
bool free [MAX_OPENDIRS]; bool free [MAX_OPENDIRS];
CFileInfo* dirFindFirst [MAX_OPENDIRS]; CFileInfo* dirFindFirst [MAX_OPENDIRS];
Bitu nextFreeFindFirst;
char label [CROSS_LEN]; char label [CROSS_LEN];
}; };
@ -217,7 +217,7 @@ public:
virtual bool RemoveDir(char * _dir)=0; virtual bool RemoveDir(char * _dir)=0;
virtual bool MakeDir(char * _dir)=0; virtual bool MakeDir(char * _dir)=0;
virtual bool TestDir(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 FindNext(DOS_DTA & dta)=0;
virtual bool GetFileAttr(char * name,Bit16u * attr)=0; virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
virtual bool Rename(char * oldname,char * newname)=0; virtual bool Rename(char * oldname,char * newname)=0;

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -24,25 +24,6 @@ void E_Exit(char * message,...);
void MSG_Add(const char*,const char*); //add messages to the internal langaugefile 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 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 <stddef.h>
#include "config.h" #include "config.h"
@ -63,11 +44,11 @@ enum MachineType {
MCH_HERC, MCH_HERC,
MCH_CGA, MCH_CGA,
MCH_TANDY, MCH_TANDY,
MCH_VGA, MCH_VGA
MCH_AUTO
}; };
extern MachineType machine; extern MachineType machine;
extern bool SDLNetInited;
#ifndef __LOGGING_H_ #ifndef __LOGGING_H_
#include "logging.h" #include "logging.h"

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -19,7 +19,17 @@
#ifndef _HARDWARE_H_ #ifndef _HARDWARE_H_
#define _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 #endif

View File

@ -9,37 +9,51 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
typedef Bit8u (IO_ReadBHandler)(Bit32u port); #define IO_MAX (64*1024+3)
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);
void IO_RegisterReadBHandler(Bitu port,IO_ReadBHandler * handler); #define IO_MB 0x1
void IO_RegisterReadWHandler(Bitu port,IO_ReadWHandler * handler); #define IO_MW 0x2
void IO_RegisterReadDHandler(Bitu port,IO_ReadDHandler * handler); #define IO_MD 0x4
#define IO_MA (IO_MB | IO_MW | IO_MD )
void IO_RegisterWriteBHandler(Bitu port,IO_WriteBHandler * handler); typedef Bitu IO_ReadHandler(Bitu port,Bitu iolen);
void IO_RegisterWriteWHandler(Bitu port,IO_WriteWHandler * handler); typedef void IO_WriteHandler(Bitu port,Bitu val,Bitu iolen);
void IO_RegisterWriteDHandler(Bitu port,IO_WriteDHandler * handler);
void IO_FreeReadHandler(Bitu port); extern IO_WriteHandler * io_writehandlers[3][IO_MAX];
void IO_FreeWriteHandler(Bitu port); extern IO_ReadHandler * io_readhandlers[3][IO_MAX];
void IO_WriteB(Bitu port,Bit8u val); void IO_RegisterReadHandler(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range=1);
Bit8u IO_ReadB(Bitu port); void IO_RegisterWriteHandler(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range=1);
void IO_WriteW(Bitu port,Bit16u val);
Bit16u IO_ReadW(Bitu port); void IO_FreeReadHandler(Bitu port,Bitu mask,Bitu range=0);
void IO_WriteD(Bitu port,Bit32u val); void IO_FreeWriteHandler(Bitu port,Bitu mask,Bitu range=0);
Bit32u IO_ReadD(Bitu port);
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) { INLINE void IO_Write(Bitu port,Bit8u val) {
IO_WriteB(port,val); IO_WriteB(port,val);
@ -48,11 +62,4 @@ INLINE Bit8u IO_Read(Bitu port){
return IO_ReadB(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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -20,6 +20,7 @@
#define _KEYBOARD_H_ #define _KEYBOARD_H_
enum KBD_KEYS { 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_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_q, KBD_w, KBD_e, KBD_r, KBD_t, KBD_y, KBD_u, KBD_i, KBD_o, KBD_p,
KBD_a, KBD_s, KBD_d, KBD_f, KBD_g, KBD_h, KBD_j, KBD_k, KBD_l, KBD_z, KBD_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_grave,KBD_minus,KBD_equals,KBD_backslash,KBD_leftbracket,KBD_rightbracket,
KBD_semicolon,KBD_quote,KBD_period,KBD_comma,KBD_slash, 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_insert,KBD_home,KBD_pageup,KBD_delete,KBD_end,KBD_pagedown,
KBD_left,KBD_up,KBD_down,KBD_right, 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_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 KBD_LAST
}; };
typedef void(KEYBOARD_EventHandler)(void); void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed);
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
#endif #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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -20,8 +20,6 @@
#define __MEM_H #define __MEM_H
#include <dosbox.h> #include <dosbox.h>
#define bmemcpy(mem1,mem2,size) memcpy((void *)mem1,(void *)mem2,size)
typedef Bit32u PhysPt; typedef Bit32u PhysPt;
typedef Bit8u * HostPt; typedef Bit8u * HostPt;
typedef Bit32u RealPt; typedef Bit32u RealPt;
@ -30,6 +28,8 @@ typedef Bit32s MemHandle;
#define MEM_PAGESIZE 4096 #define MEM_PAGESIZE 4096
extern HostPt MemBase;
bool MEM_A20_Enabled(void); bool MEM_A20_Enabled(void);
void MEM_A20_Enable(bool enable); 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_writew(PhysPt pt,Bit16u val);
void mem_writed(PhysPt pt,Bit32u val); void mem_writed(PhysPt pt,Bit32u val);
void phys_writeb(PhysPt addr,Bit8u val); INLINE void phys_writeb(PhysPt addr,Bit8u val) {
void phys_writew(PhysPt addr,Bit16u val); host_writeb(MemBase+addr,val);
void phys_writed(PhysPt addr,Bit32u 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 */ /* 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -17,25 +17,54 @@
*/ */
typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len); typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len);
typedef void (*MIXER_Handler)(Bitu len);
#define MIXER_8MONO 0 enum BlahModes {
#define MIXER_8STEREO 1 MIXER_8MONO,MIXER_8STEREO,
#define MIXER_16MONO 2 MIXER_16MONO,MIXER_16STEREO
#define MIXER_16STEREO 3 };
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 MAX_AUDIO ((1<<(16-1))-1)
#define MIN_AUDIO -(1<<(16-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;
};
MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,char * name);
struct MIXER_Channel; MixerChannel * MIXER_FindChannel(const char * name);
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);
/* PC Speakers functions, tightly related to the timer functions */ /* 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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_ShowCursor(void);
void Mouse_HideCursor(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_CursorMoved(float x,float y);
void Mouse_CursorSet(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_AutoLock(bool enable);
void Mouse_NewVideoMode(void); void Mouse_NewVideoMode(void);
#endif

View File

@ -9,16 +9,19 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: paging.h,v 1.11 2004/09/07 18:21:51 qbix79 Exp $ */
#ifndef _PAGING_H_ #ifndef _PAGING_H_
#define _PAGING_H_ #define _PAGING_H_
#include "dosbox.h"
#include "mem.h" #include "mem.h"
class PageDirectory; class PageDirectory;
@ -70,13 +73,10 @@ bool PAGING_MakePhysPage(Bitu & page);
void MEM_SetLFB(Bitu _page,Bitu _pages,HostPt _pt); void MEM_SetLFB(Bitu _page,Bitu _pages,HostPt _pt);
void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler); void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler);
Bit32u MEM_PhysReadD(Bitu addr); #ifdef _MSC_VER
#pragma pack (1)
#endif
struct X86_PageEntryBlock{
#pragma pack(1)
typedef struct {
Bit32u p:1; Bit32u p:1;
Bit32u wr:1; Bit32u wr:1;
Bit32u us:1; Bit32u us:1;
@ -88,8 +88,11 @@ typedef struct {
Bit32u g:1; Bit32u g:1;
Bit32u avl:3; Bit32u avl:3;
Bit32u base:20; Bit32u base:20;
} X86_PageEntryBlock GCC_ATTRIBUTE(packed); } GCC_ATTRIBUTE(packed);
#pragma pack() #ifdef _MSC_VER
#pragma pack ()
#endif
union X86PageEntry { union X86PageEntry {
Bit32u load; Bit32u load;

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -26,41 +26,36 @@ extern Bits CPU_CycleLeft;
extern Bits CPU_CycleMax; extern Bits CPU_CycleMax;
typedef void (PIC_EOIHandler) (void); typedef void (PIC_EOIHandler) (void);
typedef void (* PIC_EventHandler)(void); typedef void (* PIC_EventHandler)(Bitu val);
#define PIC_MAXIRQ 15 #define PIC_MAXIRQ 15
#define PIC_NOIRQ 0xFF #define PIC_NOIRQ 0xFF
extern Bitu PIC_IRQCheck; extern Bitu PIC_IRQCheck;
extern Bitu PIC_IRQActive; extern Bitu PIC_IRQActive;
extern Bitu PIC_Ticks; extern Bitu PIC_Ticks;
INLINE Bitu PIC_Index(void) { INLINE float PIC_TickIndex(void) {
return ((CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)*1000)/CPU_CycleMax; return (CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)/(float)CPU_CycleMax;
} }
INLINE Bits PIC_MakeCycles(Bitu amount) { INLINE Bits PIC_MakeCycles(double amount) {
return (CPU_CycleMax*amount)/1000; return (Bits)(CPU_CycleMax*amount);
} }
INLINE Bit64u PIC_MicroCount(void) { INLINE double PIC_FullIndex(void) {
return PIC_Ticks*1000+PIC_Index(); return PIC_Ticks+PIC_TickIndex();
} }
void PIC_ActivateIRQ(Bitu irq); void PIC_ActivateIRQ(Bitu irq);
void PIC_DeActivateIRQ(Bitu irq); void PIC_DeActivateIRQ(Bitu irq);
void PIC_runIRQs(void); void PIC_runIRQs(void);
void PIC_RegisterIRQ(Bitu irq,PIC_EOIHandler handler,char * name);
void PIC_FreeIRQ(Bitu irq);
bool PIC_RunQueue(void); 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_RemoveEvents(PIC_EventHandler handler);
void PIC_SetIRQMask(Bitu irq, bool masked); 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -19,22 +19,14 @@
#ifndef __RENDER_H #ifndef __RENDER_H
#define __RENDER_H #define __RENDER_H
enum RENDER_Operation { typedef void (* RENDER_Line_Handler)(const Bit8u * src);
OP_None,
OP_Shot,
OP_Normal2x,
OP_AdvMame2x,
};
typedef void (* RENDER_Line_Handler)(Bit8u * src); void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,bool dblw,bool dblh);
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh);
bool RENDER_StartUpdate(void); bool RENDER_StartUpdate(void);
void RENDER_EndUpdate(void); void RENDER_EndUpdate(void);
void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue);
extern RENDER_Line_Handler RENDER_DrawLine; extern RENDER_Line_Handler RENDER_DrawLine;
extern Bit8u * RENDER_TempLine;
#endif #endif

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -19,118 +19,137 @@
#if !defined __SERIALPORT_H #if !defined __SERIALPORT_H
#define __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 //If it's too high you overflow terminal clients buffers i think
#define FIFO_SIZE (1024) #define QUEUE_SIZE 1024
// Serial port interface // // Serial port interface //
#define M_CTS 0x01 #define MS_CTS 0x01
#define M_DSR 0x02 #define MS_DSR 0x02
#define M_RI 0x04 #define MS_RI 0x04
#define M_DCD 0x08 #define MS_DCD 0x08
enum INT_TYPES { #define MC_DTR 0x1
INT_MS, #define MC_RTS 0x2
INT_TX,
INT_RX,
INT_RX_FIFO, class CFifo {
INT_LS, public:
INT_NONE, 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 { class CSerial {
public: public:
CSerial() {
}
// Constructor takes base port (0x3f0, 0x2f0, 0x2e0, etc.), IRQ, and initial bps // // Constructor takes base port (0x3f0, 0x2f0, 0x2e0, etc.), IRQ, and initial bps //
CSerial (Bit16u initbase, Bit8u initirq, Bit32u initbps); CSerial (Bit16u initbase, Bit8u initirq, Bit32u initbps);
virtual ~CSerial(); virtual ~CSerial();
// External port functions for IOHandlers // void write_reg(Bitu reg, Bitu val);
void write_port(Bit32u port, Bit8u val); Bitu read_reg(Bitu reg);
Bit8u read_port(Bit32u port);
static void write_serial(Bit32u port,Bit8u val); void SetModemStatus(Bit8u status);
static Bit8u read_serial(Bit32u port); virtual bool CanRecv(void)=0;
virtual bool CanSend(void)=0;
void SetMCHandler(MControl_Handler * mcontrol); virtual void Send(Bit8u val)=0;
virtual Bit8u Recv(Bit8u val)=0;
/* Allow the modem to change the modem status bits */ virtual void Timer(void);
void setmodemstatus(Bit8u status);
Bit8u getmodemstatus(void);
Bit8u getlinestatus(void);
void checkint(void); void checkint(void);
void raiseint(INT_TYPES type);
void lowerint(INT_TYPES type);
/* Access to the receive fifo */ Bitu base;
Bitu rx_free(); Bitu irq;
void rx_addb(Bit8u byte); Bitu bps;
void rx_adds(Bit8u * data,Bitu size); Bit8u mctrl;
Bitu rx_size();
Bit8u rx_readb(void);
/* Access to the transmit fifo */ CFifo *rqueue;
Bitu tx_free(); CFifo *tqueue;
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;
private: private:
void UpdateBaudrate(void);
void setdivisor(Bit8u dmsb, Bit8u dlsb); bool FIFOenabled;
void checkforirq(void); Bit8u FIFOsize;
struct { bool dotxint;
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;
Bit8u scratch; Bit8u scratch;
Bit8u dlab; Bit8u dlab;
Bit8u divisor_lsb; Bit8u divisor_lsb;
Bit8u divisor_msb; Bit8u divisor_msb;
Bit8u wordlen;
Bit8u dtr;
Bit8u rts;
Bit8u out1;
Bit8u out2;
Bit8u local_loopback; Bit8u local_loopback;
Bit8u linectrl; Bit8u iir;
Bit8u intid; Bit8u ier;
Bit8u ierval;
Bit8u mstatus; Bit8u mstatus;
Bit8u txval; Bit8u linectrl;
Bit8u timeout; Bit8u errors;
MControl_Handler * mc_handler;
char remotestr[4096];
}; };
// This function returns the CSerial objects for ports 1-4 // #include <list>
CSerial *getComport(Bitu portnum);
typedef std::list<CSerial *> CSerialList;
typedef std::list<CSerial *>::iterator CSerial_it;
extern CSerialList seriallist;
#endif #endif

View File

@ -9,14 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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_ #ifndef _SETUP_H_
#define _SETUP_H_ #define _SETUP_H_

View File

@ -9,14 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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_ #ifndef SHELL_H_
#define SHELL_H_ #define SHELL_H_
@ -57,9 +57,7 @@ public:
}; };
class DOS_Shell : public Program { class DOS_Shell : public Program {
private: private:
std::list<std::string> l_history, l_completion; std::list<std::string> l_history, l_completion;
char *completion_start; char *completion_start;
@ -102,6 +100,8 @@ public:
void CMD_PAUSE(char * args); void CMD_PAUSE(char * args);
void CMD_SUBST(char* args); void CMD_SUBST(char* args);
void CMD_LOADHIGH(char* args); void CMD_LOADHIGH(char* args);
void CMD_CHOICE(char * args);
void CMD_ATTRIB(char * args);
/* The shell's variables */ /* The shell's variables */
Bit16u input_handle; Bit16u input_handle;
BatchFile * bf; BatchFile * bf;
@ -117,15 +117,12 @@ struct SHELL_Cmd {
const char * help; /* String with command help */ const char * help; /* String with command help */
}; };
static inline void StripSpaces(char*&args) static inline void StripSpaces(char*&args) {
{ while(*args && ((*args == ' ') || (*args == '\t')))
while(*args && (*args == ' '))
args++; args++;
} }
static inline char* ExpandDot(char*args, char* buffer) {
static inline char* ExpandDot(char*args, char* buffer)
{
if(*args=='.') if(*args=='.')
{ {
if(*(args+1)==0) if(*(args+1)==0)
@ -139,11 +136,11 @@ static inline char* ExpandDot(char*args, char* buffer)
buffer[1]=0; buffer[1]=0;
strcat(buffer,args); strcat(buffer,args);
return buffer; return buffer;
} } else
strcpy (buffer, args);
} }
else strcpy(buffer,args); else strcpy(buffer,args);
return buffer; return buffer;
} }
#endif #endif

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -19,11 +19,11 @@
#if !defined __SUPPORT_H #if !defined __SUPPORT_H
#define __SUPPORT_H #define __SUPPORT_H
#include <dosbox.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "dosbox.h"
#if defined (_MSC_VER) /* MS Visual C++ */ #if defined (_MSC_VER) /* MS Visual C++ */
#define strcasecmp(a,b) stricmp(a,b) #define strcasecmp(a,b) stricmp(a,b)
#define strncasecmp(a,b,n) _strnicmp(a,b,n) #define strncasecmp(a,b,n) _strnicmp(a,b,n)
@ -39,13 +39,16 @@
void strreplace(char * str,char o,char n); void strreplace(char * str,char o,char n);
char *ltrim(char *str); char *ltrim(char *str);
void rtrim(char * const str); char *rtrim(char *str);
char *trim(char *str); char *trim(char * str);
bool ScanCMDBool(char * cmd,char * check); bool ScanCMDBool(char * cmd,char * check);
char * ScanCMDRemain(char * cmd); 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) { INLINE char * upcase(char * str) {
for (char* idx = str; *idx ; idx++) *idx = toupper(*idx); 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -25,19 +25,11 @@
#define GetTicks() SDL_GetTicks() #define GetTicks() SDL_GetTicks()
typedef void (*TIMER_TickHandler)(Bitu ticks); typedef void (*TIMER_TickHandler)(void);
typedef void (*TIMER_MicroHandler)(void);
typedef void TIMER_Block;
/* Register a function that gets called everytime if 1 or more ticks pass */ /* Register a function that gets called everytime if 1 or more ticks pass */
TIMER_Block * TIMER_RegisterTickHandler(TIMER_TickHandler handler); void TIMER_AddTickHandler(TIMER_TickHandler handler);
/* Register a function to be called every x microseconds */ void TIMER_DelTickHandler(TIMER_TickHandler handler);
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);
/* This will add 1 milliscond to all timers */ /* This will add 1 milliscond to all timers */
void TIMER_AddTick(void); void TIMER_AddTick(void);

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -23,13 +23,13 @@
#include "dosbox.h" #include "dosbox.h"
enum VGAModes { enum VGAModes {
M_TEXT2,M_TEXT16, M_CGA2,M_CGA4,
M_HERC, M_EGA16,
M_CGA2,M_CGA4,M_CGA16,
M_TANDY16,
M_EGA2,M_EGA4,M_EGA16,
M_VGA, M_VGA,
M_LIN8, M_LIN8,
M_TEXT,
M_HERC_GFX,M_HERC_TEXT,
M_CGA16,M_TANDY2,M_TANDY4,M_TANDY16,M_TANDY_TEXT,
M_ERROR, M_ERROR,
}; };
@ -60,9 +60,7 @@ typedef struct {
/* Some other screen related variables */ /* Some other screen related variables */
Bitu line_compare; Bitu line_compare;
bool chained; /* Enable or Disabled Chain 4 Mode */ bool chained; /* Enable or Disabled Chain 4 Mode */
bool blinking; /* Attribute bit 7 is blinking */
/* Pixel Scrolling */ /* Pixel Scrolling */
Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */ Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */
@ -91,10 +89,8 @@ typedef struct {
typedef struct { typedef struct {
bool resizing; bool resizing;
bool drawing;
Bitu width; Bitu width;
Bitu height; Bitu height;
Bitu pitch;
Bitu blocks; Bitu blocks;
Bitu panning; Bitu panning;
Bitu address; Bitu address;
@ -102,49 +98,62 @@ typedef struct {
Bitu address_line_total; Bitu address_line_total;
Bitu address_line; Bitu address_line;
Bitu lines_total; Bitu lines_total;
Bitu lines_left; Bitu lines_done;
Bitu lines_scaled; Bitu lines_scaled;
Bitu split_line; Bitu split_line;
Bitu parts_total; Bitu parts_total;
Bitu parts_lines; Bitu parts_lines;
Bitu parts_left; Bitu parts_left;
struct { struct {
Bitu vtotal; float vtotal;
Bitu vstart; float vstart;
Bitu vend; float vend;
Bitu htotal; float htotal;
Bitu hstart; float hstart;
Bitu hend; float hend;
Bitu parts; float parts;
} micro; } delay;
Bitu scaleh;
bool double_scan; bool double_scan;
bool double_scan_active; bool doublewidth,doubleheight;
Bit8u font_height;
Bit8u font[64*1024]; Bit8u font[64*1024];
Bitu font1_start; Bit8u * font_tables[2];
Bitu font2_start;
Bitu blinking; Bitu blinking;
struct { struct {
Bitu address;
Bit8u sline,eline; Bit8u sline,eline;
Bit8u count,delay; Bit8u count,delay;
Bit8u enabled; Bit8u enabled;
} cursor; } cursor;
} VGA_Draw; } 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 { typedef struct {
Bit8u bank; Bit8u bank;
Bit8u reg_lock1; Bit8u reg_lock1;
Bit8u reg_lock2; Bit8u reg_lock2;
Bit8u reg_31; Bit8u reg_31;
Bit8u reg_35; Bit8u reg_35;
Bit8u reg_40; // 8415/A functionality register
Bit8u reg_43; Bit8u reg_43;
Bit8u reg_45; // Hardware graphics cursor
Bit8u reg_58; Bit8u reg_58;
Bit8u reg_51; Bit8u reg_51;
Bit8u reg_55; Bit8u reg_55;
Bit8u ex_hor_overflow; Bit8u ex_hor_overflow;
Bit8u ex_ver_overflow; Bit8u ex_ver_overflow;
Bit16u la_window; Bit16u la_window;
Bit8u misc_control_2;
Bit8u ext_mem_ctrl;
struct { struct {
Bit8u r; Bit8u r;
Bit8u n; Bit8u n;
@ -154,6 +163,7 @@ typedef struct {
Bit8u lock; Bit8u lock;
Bit8u cmd; Bit8u cmd;
} pll; } pll;
VGA_HWCURSOR hgc;
} VGA_S3; } VGA_S3;
typedef struct { typedef struct {
@ -162,18 +172,28 @@ typedef struct {
} VGA_HERC; } VGA_HERC;
typedef struct { typedef struct {
Bit8u mode_control; Bit8u index;
Bit8u color_select; Bit8u htotal;
} VGA_CGA; Bit8u hdend;
Bit8u hsyncp;
Bit8u hsyncw;
Bit8u vtotal;
Bit8u vdend;
Bit8u vadjust;
Bit8u vsyncp;
Bit8u vsyncw;
Bit8u max_scanline;
} VGA_OTHER;
typedef struct { typedef struct {
Bit8u mode_control;
Bit8u color_select;
Bit8u mem_bank; Bit8u mem_bank;
Bit8u disp_bank; Bit8u disp_bank;
Bit8u reg_index; Bit8u reg_index;
Bit8u mode_control1; Bit8u gfx_control;
Bit8u palette_mask; Bit8u palette_mask;
Bit8u border_color; Bit8u border_color;
Bit8u mode_control2;
} VGA_TANDY; } VGA_TANDY;
typedef struct { typedef struct {
@ -256,7 +276,6 @@ typedef struct {
Bit8u read_index; Bit8u read_index;
Bitu first_changed; Bitu first_changed;
RGBEntry rgb[0x100]; RGBEntry rgb[0x100];
Bit8u attr[16];
} VGA_Dac; } VGA_Dac;
union VGA_Latch { union VGA_Latch {
@ -285,8 +304,8 @@ typedef struct {
VGA_Latch latch; VGA_Latch latch;
VGA_S3 s3; VGA_S3 s3;
VGA_HERC herc; VGA_HERC herc;
VGA_CGA cga;
VGA_TANDY tandy; VGA_TANDY tandy;
VGA_OTHER other;
VGA_Memory mem; VGA_Memory mem;
} VGA_Type; } VGA_Type;
@ -294,12 +313,15 @@ typedef struct {
/* Functions for different resolutions */ /* Functions for different resolutions */
void VGA_SetMode(VGAModes mode); void VGA_SetMode(VGAModes mode);
void VGA_DetermineMode(void);
void VGA_SetupHandlers(void); void VGA_SetupHandlers(void);
void VGA_StartResize(void); void VGA_StartResize(void);
void VGA_SetupDrawing(void); void VGA_SetupDrawing(Bitu val);
void VGA_CheckScanLength(void);
/* Some DAC/Attribute functions */ /* Some DAC/Attribute functions */
void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal); 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); void VGA_ATTR_SetPalette(Bit8u index,Bit8u val);
/* The VGA Subfunction startups */ /* The VGA Subfunction startups */
@ -310,6 +332,8 @@ void VGA_SetupCRTC(void);
void VGA_SetupMisc(void); void VGA_SetupMisc(void);
void VGA_SetupGFX(void); void VGA_SetupGFX(void);
void VGA_SetupSEQ(void); void VGA_SetupSEQ(void);
void VGA_SetupOther(void);
void VGA_SetupXGA(void);
/* Some Support Functions */ /* Some Support Functions */
void VGA_SetClock(Bitu which,Bitu target); void VGA_SetClock(Bitu which,Bitu target);
@ -317,6 +341,8 @@ void VGA_DACSetEntirePalette(void);
void VGA_StartRetrace(void); void VGA_StartRetrace(void);
void VGA_StartUpdateLFB(void); void VGA_StartUpdateLFB(void);
void VGA_SetBlinking(Bitu enabled); 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; extern VGA_Type vga;

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -28,21 +28,43 @@ struct GFX_PalEntry {
Bit8u unused; Bit8u unused;
}; };
#define GFX_HASSCALING 0x0001 #define CAN_8 0x0001
#define GFX_HASCONVERT 0x0002 #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_Events(void);
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries); 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); 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_Start(void);
void GFX_Stop(void); void GFX_Stop(void);
void GFX_SwitchFullScreen(void); void GFX_SwitchFullScreen(void);
bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch); bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch);
void GFX_EndUpdate(void); void GFX_EndUpdate(void);
/* Mouse related */
void GFX_CaptureMouse(void);
extern bool mouselocked; //true if mouse is confined to window
#endif #endif

View File

@ -3,5 +3,5 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcpu.a noinst_LIBRARIES = libcpu.a
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \ 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 core_dyn_x86.cpp

View File

@ -134,7 +134,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libcpu.a noinst_LIBRARIES = libcpu.a
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \ 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 core_dyn_x86.cpp
subdir = src/cpu subdir = src/cpu
@ -148,7 +148,8 @@ libcpu_a_AR = $(AR) cru
libcpu_a_LIBADD = libcpu_a_LIBADD =
am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \ am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \
modrm.$(OBJEXT) core_full.$(OBJEXT) paging.$(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) libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) 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@DEP_FILES = ./$(DEPDIR)/callback.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/core_dyn_x86.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/core_dyn_x86.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/core_full.Po ./$(DEPDIR)/core_normal.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/core_full.Po ./$(DEPDIR)/core_normal.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/cpu.Po ./$(DEPDIR)/flags.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/core_simple.Po ./$(DEPDIR)/cpu.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/modrm.Po ./$(DEPDIR)/paging.Po @AMDEP_TRUE@ ./$(DEPDIR)/flags.Po ./$(DEPDIR)/modrm.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/paging.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX) CXXLD = $(CXX)
@ -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_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_full.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_normal.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)/cpu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flags.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@ @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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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 <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -67,8 +67,7 @@ void CALLBACK_Idle(void) {
reg_eip=oldeip; reg_eip=oldeip;
SegSet16(cs,oldcs); SegSet16(cs,oldcs);
SETFLAGBIT(IF,oldIF); SETFLAGBIT(IF,oldIF);
if (CPU_CycleLeft<300) CPU_CycleLeft=1; if (CPU_Cycles>0) CPU_Cycles=0;
else CPU_CycleLeft-=300;
} }
static Bitu default_handler(void) { static Bitu default_handler(void) {
@ -204,12 +203,14 @@ void CALLBACK_Init(Section* sec) {
/* Setup the Stop Handler */ /* Setup the Stop Handler */
call_stop=CALLBACK_Allocate(); call_stop=CALLBACK_Allocate();
CallBack_Handlers[call_stop]=stop_handler; 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)+0,0xFE);
phys_writeb(CB_BASE+(call_stop<<4)+1,0x38); phys_writeb(CB_BASE+(call_stop<<4)+1,0x38);
phys_writew(CB_BASE+(call_stop<<4)+2,call_stop); phys_writew(CB_BASE+(call_stop<<4)+2,call_stop);
/* Setup the idle handler */ /* Setup the idle handler */
call_idle=CALLBACK_Allocate(); call_idle=CALLBACK_Allocate();
CallBack_Handlers[call_idle]=stop_handler; CallBack_Handlers[call_idle]=stop_handler;
CALLBACK_SetDescription(call_idle,"idle");
for (i=0;i<=11;i++) phys_writeb(CB_BASE+(call_idle<<4)+i,0x90); 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)+12,0xFE);
phys_writeb(CB_BASE+(call_idle<<4)+13,0x38); 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 */ /* Setup all Interrupt to point to the default handler */
call_default=CALLBACK_Allocate(); call_default=CALLBACK_Allocate();
CALLBACK_Setup(call_default,&default_handler,CB_IRET); CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default");
/* Only setup default handler for first half of interrupt table */ /* Only setup default handler for first half of interrupt table */
for (i=0;i<0x40;i++) { for (i=0;i<0x40;i++) {
real_writed(0,i*4,CALLBACK_RealPointer(call_default)); 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -33,10 +33,11 @@
#include "paging.h" #include "paging.h"
#include "inout.h" #include "inout.h"
#define CACHE_TOTAL (1024*1024*2) #define CACHE_TOTAL (512*1024)
#define CACHE_MAXSIZE (4096) #define CACHE_MAXSIZE (4096)
#define CACHE_BLOCKS (50*1024) #define CACHE_BLOCKS (32*1024)
#define CACHE_ALIGN (16) #define CACHE_ALIGN (16)
#define CACHE_PAGES (128)
#define DYN_HASH_SHIFT (4) #define DYN_HASH_SHIFT (4)
#define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT) #define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT)
#define DYN_LINKS (16) #define DYN_LINKS (16)
@ -68,8 +69,8 @@ enum DualOps {
DOP_SUB,DOP_SBB, DOP_SUB,DOP_SBB,
DOP_CMP,DOP_XOR, DOP_CMP,DOP_XOR,
DOP_AND,DOP_OR, DOP_AND,DOP_OR,
DOP_MOV,
DOP_TEST, DOP_TEST,
DOP_MOV,
DOP_XCHG, DOP_XCHG,
}; };
@ -77,7 +78,7 @@ enum ShiftOps {
SHIFT_ROL,SHIFT_ROR, SHIFT_ROL,SHIFT_ROR,
SHIFT_RCL,SHIFT_RCR, SHIFT_RCL,SHIFT_RCR,
SHIFT_SHL,SHIFT_SHR, SHIFT_SHL,SHIFT_SHR,
SHIFT_SAR, SHIFT_SAL,SHIFT_SAR,
}; };
enum BranchTypes { enum BranchTypes {
@ -87,19 +88,15 @@ enum BranchTypes {
BR_L,BR_NL,BR_LE,BR_NLE BR_L,BR_NL,BR_LE,BR_NLE
}; };
enum BlockType {
BT_Free=0,
BT_Normal,
BT_SingleLink,
BT_DualLink,
BT_CheckFlags,
};
enum BlockReturn { enum BlockReturn {
BR_Normal=0, BR_Normal=0,
BR_Cycles, BR_Cycles,
BR_Link1,BR_Link2, BR_Link1,BR_Link2,
BR_Opcode, BR_Opcode,
#if (C_DEBUG)
BR_OpcodeFull,
#endif
BR_CallBack, BR_CallBack,
}; };
@ -153,28 +150,23 @@ struct DynState {
DynReg regs[G_MAX]; DynReg regs[G_MAX];
}; };
static void dyn_releaseregs(void) { static void dyn_flags_host_to_gen(void) {
for (Bitu i=0;i<G_MAX;i++) gen_releasereg(&DynRegs[i]); gen_dop_word(DOP_MOV,true,DREG(EXIT),DREG(FLAGS));
} gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST);
static void dyn_load_flags(void) { gen_load_flags(DREG(EXIT));
/* Load the host flags with emulated flags */ gen_releasereg(DREG(EXIT));
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));
gen_releasereg(DREG(FLAGS)); gen_releasereg(DREG(FLAGS));
} }
static void dyn_save_flags(bool stored=false) { static void dyn_flags_gen_to_host(void) {
/* Store the host flags back in emulated ones */ gen_save_flags(DREG(EXIT));
gen_save_flags(DREG(EXIT),stored);
gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST); 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_imm(DOP_AND,true,DREG(FLAGS),~FMASK_TEST);
gen_dop_word(DOP_OR,true,DREG(FLAGS),DREG(EXIT)); //flags are marked for save gen_dop_word(DOP_OR,true,DREG(FLAGS),DREG(EXIT)); //flags are marked for save
gen_releasereg(DREG(EXIT)); gen_releasereg(DREG(EXIT));
gen_releasereg(DREG(FLAGS));
} }
static void dyn_savestate(DynState * state) { static void dyn_savestate(DynState * state) {
for (Bitu i=0;i<G_MAX;i++) { for (Bitu i=0;i<G_MAX;i++) {
state->regs[i].flags=DynRegs[i].flags; state->regs[i].flags=DynRegs[i].flags;
@ -201,80 +193,61 @@ Bits CPU_Core_Dyn_X86_Run(void) {
restart_core: restart_core:
PhysPt ip_point=SegPhys(cs)+reg_eip; PhysPt ip_point=SegPhys(cs)+reg_eip;
Bitu ip_page=ip_point>>12; 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 C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback; if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif #endif
if (handler->flags & PFLAG_HASCODE) { CodePageHandler * chandler=MakeCodePage(ip_page);
/* Find correct Dynamic Block to run */ if (!chandler) return CPU_Core_Normal_Run();
chandler=(CodePageHandler *)handler; /* Find correct Dynamic Block to run */
findblock:; CacheBlock * block=chandler->FindCacheBlock(ip_point&4095);
CacheBlock * block=chandler->FindCacheBlock(ip_point&4095); if (!block) {
if (!block) { block=CreateCacheBlock(chandler,ip_point,32);
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;
} }
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) { void CPU_Core_Dyn_X86_Init(void) {
Bits i; Bits i;
/* Setup the global registers and their flags */ /* Setup the global registers and their flags */

View File

@ -1,28 +1,34 @@
struct CacheBlock { class CacheBlock {
public: 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 { struct {
Bit16s start,end; //Where the page is the original code Bit16u start,end; //Where the page is the original code
Bitu first,last; CodePageHandler * handler; //Page containing this code
} page; } page;
struct { struct {
Bit8u * start; //Where in the cache are we Bit8u * start; //Where in the cache are we
Bitu size; Bitu size;
CacheBlock * next;
} cache; } cache;
BlockType type;
CodePageHandler * code_page; //Page containing this code
CacheBlock * page_link; //For code crossing a page boundary
struct { struct {
Bitu index;
CacheBlock * next; CacheBlock * next;
} hash; } hash;
CacheBlock * list_next;
struct { struct {
CacheBlock * to[2]; CacheBlock * to;
CacheBlock * from[DYN_LINKS]; CacheBlock * next;
Bitu index; CacheBlock * from;
} link; } link[2];
CacheBlock * links[2]; CacheBlock * crossblock;
}; };
class CacheBlock;
static struct { static struct {
struct { struct {
CacheBlock * first; CacheBlock * first;
@ -31,96 +37,124 @@ static struct {
CacheBlock * running; CacheBlock * running;
} block; } block;
Bit8u * pos; Bit8u * pos;
CacheBlock linkblocks[2]; CodePageHandler * free_pages;
CodePageHandler * used_pages;
CodePageHandler * last_page;
} cache; } cache;
static Bit8u cache_code_link_blocks[2][16]; static Bit8u cache_code_link_blocks[2][16];
static Bit8u cache_code[CACHE_TOTAL+CACHE_MAXSIZE]; static Bit8u cache_code[CACHE_TOTAL+CACHE_MAXSIZE];
static CacheBlock cache_blocks[CACHE_BLOCKS]; static CacheBlock cache_blocks[CACHE_BLOCKS];
static CacheBlock link_blocks[2];
static void cache_resetblock(CacheBlock * block);
class CodePageHandler :public PageHandler { class CodePageHandler :public PageHandler {
public: public:
CodePageHandler(PageHandler * _old_pagehandler) { CodePageHandler() {}
void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
phys_page=_phys_page;
old_pagehandler=_old_pagehandler; old_pagehandler=_old_pagehandler;
flags=old_pagehandler->flags|PFLAG_HASCODE; flags=old_pagehandler->flags|PFLAG_HASCODE;
flags&=~PFLAG_WRITEABLE; flags&=~PFLAG_WRITEABLE;
active_blocks=0;
active_count=16;
memset(&hash_map,0,sizeof(hash_map)); memset(&hash_map,0,sizeof(hash_map));
memset(&write_map,0,sizeof(write_map)); memset(&write_map,0,sizeof(write_map));
} }
void InvalidateRange(Bits start,Bits end) { void InvalidateRange(Bitu start,Bitu end) {
Bits maps=start>>DYN_HASH_SHIFT; Bits index=1+(start>>DYN_HASH_SHIFT);
Bits map=maps; while (index>=0) {
Bits count=write_map[maps]; Bitu map=0;
while (map>=0 && count>0) { for (Bitu count=start;count<=end;count++) map+=write_map[count];
CacheBlock * block=hash_map[map]; if (!map) return;
CacheBlock * * where=&hash_map[map]; CacheBlock * block=hash_map[index];
while (block) { while (block) {
CacheBlock * nextblock=block->hash.next; CacheBlock * nextblock=block->hash.next;
if (start<=block->page.end && end>=block->page.start) { if (start<=block->page.end && end>=block->page.start)
for (Bitu i=block->page.first;i<=block->page.last;i++) write_map[i]--; block->Clear();
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;
}
block=nextblock; block=nextblock;
} }
map--; index--;
} }
} }
void writeb(PhysPt addr,Bitu val){ void writeb(PhysPt addr,Bitu val){
if (val!=host_readb(hostmem+(addr&4095))) { addr&=4095;
InvalidateRange(addr&4095,addr&4095); host_writeb(hostmem+addr,val);
host_writeb(hostmem+(addr&4095),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){ void writew(PhysPt addr,Bitu val){
if (val!=host_readw(hostmem+(addr&4095))) { addr&=4095;
InvalidateRange(addr&4095,(addr&4095)+1); host_writew(hostmem+addr,val);
host_writew(hostmem+(addr&4095),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){ void writed(PhysPt addr,Bitu val){
if (val!=host_readd(hostmem+(addr&4095))) { addr&=4095;
InvalidateRange(addr&4095,(addr&4095)+3); host_writed(hostmem+addr,val);
host_writed(hostmem+(addr&4095),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) { void AddCacheBlock(CacheBlock * block) {
Bit16u first,last; Bitu index=1+(block->page.start>>DYN_HASH_SHIFT);
if (block->page.start<0) first=0; block->hash.next=hash_map[index];
else first=block->page.start>>DYN_HASH_SHIFT; block->hash.index=index;
block->hash.next=hash_map[first]; hash_map[index]=block;
hash_map[first]=block; block->page.handler=this;
if (block->page.end>=4096) last=DYN_PAGE_HASH-1; active_blocks++;
else last=block->page.end>>DYN_HASH_SHIFT; }
block->page.first=first; void AddCrossBlock(CacheBlock * block) {
block->page.last=last; block->hash.next=hash_map[0];
for (;first<=last;first++) { block->hash.index=0;
write_map[first]++; hash_map[0]=block;
} block->page.handler=this;
block->code_page=this; active_blocks++;
} }
void DelCacheBlock(CacheBlock * block) { void DelCacheBlock(CacheBlock * block) {
CacheBlock * * where=&hash_map[block->page.first]; active_blocks--;
while (*where) { active_count=16;
if (*where==block) { CacheBlock * * where=&hash_map[block->hash.index];
*where=block->hash.next; while (*where!=block) {
break;
}
where=&((*where)->hash.next); 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++) { *where=block->hash.next;
write_map[i]--; 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 * FindCacheBlock(Bitu start) {
CacheBlock * block=hash_map[start>>DYN_HASH_SHIFT]; CacheBlock * block=hash_map[1+(start>>DYN_HASH_SHIFT)];
while (block) { while (block) {
if (block->page.start==start) return block; if (block->page.start==start) return block;
block=block->hash.next; block=block->hash.next;
@ -131,133 +165,153 @@ public:
hostmem=old_pagehandler->GetHostPt(phys_page); hostmem=old_pagehandler->GetHostPt(phys_page);
return hostmem; return hostmem;
} }
public:
Bit8u write_map[4096];
CodePageHandler * next, * prev;
private: private:
PageHandler * old_pagehandler; PageHandler * old_pagehandler;
CacheBlock * hash_map[DYN_PAGE_HASH]; CacheBlock * hash_map[1+DYN_PAGE_HASH];
Bit8u write_map[DYN_PAGE_HASH]; Bitu active_blocks;
Bitu active_count;
HostPt hostmem; 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) { static INLINE void cache_addunsedblock(CacheBlock * block) {
block->list_next=cache.block.free; block->cache.next=cache.block.free;
cache.block.free=block; cache.block.free=block;
} }
static CacheBlock * cache_getblock(void) { static CacheBlock * cache_getblock(void) {
CacheBlock * ret=cache.block.free; CacheBlock * ret=cache.block.free;
if (!ret) E_Exit("Ran out of CacheBlocks" ); 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; return ret;
} }
static INLINE void cache_clearlinkfrom(CacheBlock * block,CacheBlock * from) { void CacheBlock::Clear(void) {
for (Bitu i=0;i<DYN_LINKS;i++) { Bitu ind;
if (block->link.from[i]==from) block->link.from[i]=0; /* 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) { static CacheBlock * cache_openblock(void) {
CacheBlock * block=cache.block.active; CacheBlock * block=cache.block.active;
/* check for enough space in this block */ /* check for enough space in this block */
Bitu size=block->cache.size; 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) { while (size<CACHE_MAXSIZE) {
if (!nextblock) goto skipresize; if (!nextblock)
goto skipresize;
size+=nextblock->cache.size; size+=nextblock->cache.size;
CacheBlock * tempblock=nextblock->list_next; CacheBlock * tempblock=nextblock->cache.next;
if (nextblock->type!=BT_Free) cache_resetblock(nextblock); if (nextblock->page.handler)
nextblock->Clear();
cache_addunsedblock(nextblock); cache_addunsedblock(nextblock);
nextblock=tempblock; nextblock=tempblock;
} }
skipresize: skipresize:
block->cache.size=size; block->cache.size=size;
block->list_next=nextblock; block->cache.next=nextblock;
cache.pos=block->cache.start; cache.pos=block->cache.start;
return block; return block;
} }
static void cache_closeblock(BlockType type) { static void cache_closeblock(void) {
CacheBlock * block=cache.block.active; CacheBlock * block=cache.block.active;
/* Setup some structures in the block determined by type */ block->link[0].to=&link_blocks[0];
block->type=type; block->link[1].to=&link_blocks[1];
switch (type) { block->link[0].from=0;
case BT_Normal: block->link[1].from=0;
break; block->link[0].next=0;
case BT_SingleLink: block->link[1].next=0;
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;
}
/* Close the block with correct alignments */ /* Close the block with correct alignments */
Bitu written=cache.pos-block->cache.start; Bitu written=cache.pos-block->cache.start;
if (written>block->cache.size) { if (written>block->cache.size) {
if (!block->list_next) { if (!block->cache.next) {
if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun"); if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size);
} else E_Exit("CacheBlock overrun"); } else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size);
} else { } else {
Bitu new_size; Bitu new_size;
Bitu left=block->cache.size-written; Bitu left=block->cache.size-written;
/* Smaller than cache align then don't bother to resize */ /* Smaller than cache align then don't bother to resize */
if (left>CACHE_ALIGN) { if (left>CACHE_ALIGN) {
new_size=((written-1)|(CACHE_ALIGN-1))+1; new_size=((written-1)|(CACHE_ALIGN-1))+1;
} else new_size=block->cache.size; CacheBlock * newblock=cache_getblock();
CacheBlock * newblock=cache_getblock(); newblock->cache.start=block->cache.start+new_size;
newblock->cache.start=block->cache.start+new_size; newblock->cache.size=block->cache.size-new_size;
newblock->cache.size=block->cache.size-new_size; newblock->cache.next=block->cache.next;
newblock->list_next=block->list_next; block->cache.next=newblock;
newblock->type=BT_Free; block->cache.size=new_size;
block->cache.size=new_size; }
block->list_next=newblock;
} }
/* Advance the active block pointer */ /* Advance the active block pointer */
if (!block->list_next) { if (!block->cache.next) {
DYN_LOG("Cache full restarting"); // LOG_MSG("Cache full restarting");
cache.block.active=cache.block.first; cache.block.active=cache.block.first;
} else { } 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)); memset(&cache_blocks,0,sizeof(cache_blocks));
cache.block.free=&cache_blocks[0]; cache.block.free=&cache_blocks[0];
for (i=0;i<CACHE_BLOCKS-1;i++) { for (i=0;i<CACHE_BLOCKS-1;i++) {
cache_blocks[i].list_next=&cache_blocks[i+1]; cache_blocks[i].link[0].to=(CacheBlock *)1;
cache_blocks[i].link.to[0]=&cache.linkblocks[0]; cache_blocks[i].link[1].to=(CacheBlock *)1;
cache_blocks[i].link.to[1]=&cache.linkblocks[1]; cache_blocks[i].cache.next=&cache_blocks[i+1];
} }
CacheBlock * block=cache_getblock(); CacheBlock * block=cache_getblock();
cache.block.first=block; cache.block.first=block;
cache.block.active=block; cache.block.active=block;
block->cache.start=&cache_code[0]; block->cache.start=&cache_code[0];
block->cache.size=CACHE_TOTAL; 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.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); gen_return(BR_Link1);
cache.pos=&cache_code_link_blocks[1][0]; 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); 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) { static bool dyn_helper_divb(Bit8u val) {
if (!val) return 1; if (!val) return CPU_PrepareException(0,0);
Bitu quo=reg_ax / val; Bitu quo=reg_ax / val;
reg_ah=(Bit8u)(reg_ax % val); reg_ah=(Bit8u)(reg_ax % val);
reg_al=(Bit8u)quo; reg_al=(Bit8u)quo;
if (quo>0xff) return 1; if (quo>0xff) return CPU_PrepareException(0,0);
return 0; return false;
} }
static Bitu dyn_helper_idivb(Bit8s val) { static bool dyn_helper_idivb(Bit8s val) {
if (!val) return 1; if (!val) return CPU_PrepareException(0,0);
Bits quo=(Bit16s)reg_ax / val; Bits quo=(Bit16s)reg_ax / val;
reg_ah=(Bit8s)((Bit16s)reg_ax % val); reg_ah=(Bit8s)((Bit16s)reg_ax % val);
reg_al=(Bit8s)quo; reg_al=(Bit8s)quo;
if (quo!=(Bit8s)reg_al) return 1; if (quo!=(Bit8s)reg_al) return CPU_PrepareException(0,0);
return 0; return false;
} }
static Bitu dyn_helper_divw(Bit16u val) { static bool dyn_helper_divw(Bit16u val) {
if (!val) return 1; if (!val) return CPU_PrepareException(0,0);
Bitu num=(reg_dx<<16)|reg_ax; Bitu num=(reg_dx<<16)|reg_ax;
Bitu quo=num/val; Bitu quo=num/val;
reg_dx=(Bit16u)(num % val); reg_dx=(Bit16u)(num % val);
reg_ax=(Bit16u)quo; reg_ax=(Bit16u)quo;
if (quo!=reg_ax) return 1; if (quo!=reg_ax) return CPU_PrepareException(0,0);
return 0; return false;
} }
static Bitu dyn_helper_idivw(Bit16s val) { static bool dyn_helper_idivw(Bit16s val) {
if (!val) return 1; if (!val) return CPU_PrepareException(0,0);
Bits num=(reg_dx<<16)|reg_ax; Bits num=(reg_dx<<16)|reg_ax;
Bits quo=num/val; Bits quo=num/val;
reg_dx=(Bit16s)(num % val); reg_dx=(Bit16s)(num % val);
reg_ax=(Bit16s)quo; reg_ax=(Bit16s)quo;
if (quo!=(Bit16s)reg_ax) return 1; if (quo!=(Bit16s)reg_ax) return CPU_PrepareException(0,0);
return 0; return false;
} }
static Bitu dyn_helper_divd(Bit32u val) { static bool dyn_helper_divd(Bit32u val) {
if (!val) return 1; if (!val) return CPU_PrepareException(0,0);
Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax;
Bit64u quo=num/val; Bit64u quo=num/val;
reg_edx=(Bit32u)(num % val); reg_edx=(Bit32u)(num % val);
reg_eax=(Bit32u)quo; reg_eax=(Bit32u)quo;
if (quo!=(Bit64u)reg_eax) return 1; if (quo!=(Bit64u)reg_eax) return CPU_PrepareException(0,0);
return 0; return false;
} }
static Bitu dyn_helper_idivd(Bit32s val) { static bool dyn_helper_idivd(Bit32s val) {
if (!val) return 1; if (!val) return CPU_PrepareException(0,0);
Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax;
Bit64s quo=num/val; Bit64s quo=num/val;
reg_edx=(Bit32s)(num % val); reg_edx=(Bit32s)(num % val);
reg_eax=(Bit32s)(quo); reg_eax=(Bit32s)(quo);
if (quo!=(Bit64s)((Bit32s)reg_eax)) return 1; if (quo!=(Bit64s)((Bit32s)reg_eax)) return CPU_PrepareException(0,0);
return 0; return false;
} }

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -32,8 +32,8 @@ static void gen_init(void);
#define X86_REG_MASK(_REG_) (1 << X86_REG_ ## _REG_) #define X86_REG_MASK(_REG_) (1 << X86_REG_ ## _REG_)
static struct { static struct {
bool flagsactive;
Bitu last_used; Bitu last_used;
Bitu stored_flags;
GenReg * regs[X86_REGS]; GenReg * regs[X86_REGS];
} x86gen; } x86gen;
@ -98,13 +98,13 @@ static BlockReturn gen_runcode(Bit8u * code) {
push edi push edi
mov ebx,[reg_flags] mov ebx,[reg_flags]
and ebx,FMASK_TEST and ebx,FMASK_TEST
push offset(return_address)
push ebx push ebx
popfd jmp eax
call eax
/* Restore the flags */ /* Restore the flags */
pushfd return_address:
/* return here with flags in ecx */
and dword ptr [reg_flags],~FMASK_TEST and dword ptr [reg_flags],~FMASK_TEST
pop ecx
and ecx,FMASK_TEST and ecx,FMASK_TEST
or [reg_flags],ecx or [reg_flags],ecx
pop edi pop edi
@ -114,23 +114,19 @@ static BlockReturn gen_runcode(Bit8u * code) {
mov [retval],eax mov [retval],eax
} }
#else #else
register Bit32u tempflags=reg_flags & FMASK_TEST;
__asm__ volatile ( __asm__ volatile (
"movl %1,%%esi \n" "pushl %%ebp \n"
"andl %2,%%esi \n" "pushl $(run_return_adress) \n"
"pushl %%ebp \n" "pushl %2 \n"
"pushl %%esi \n" "jmp *%3 \n"
"popfl \n" "run_return_adress: \n"
"calll *%4 \n" "popl %%ebp \n"
"popl %%ebp \n" :"=a" (retval), "=c" (tempflags)
"pushfl \n" :"r" (tempflags),"r" (code)
"andl %3,(%1) \n" :"%edx","%ebx","%edi","%esi","cc","memory"
"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"
); );
reg_flags=(reg_flags & ~FMASK_TEST) | (tempflags & FMASK_TEST);
#endif #endif
return retval; return retval;
} }
@ -232,28 +228,23 @@ static void gen_synchreg(DynReg * dnew,DynReg * dsynch) {
} }
} }
static void gen_storeflags(void) { static void gen_needflags(void) {
if (!x86gen.stored_flags) { if (!x86gen.flagsactive) {
cache_addb(0x9c); //PUSHFD x86gen.flagsactive=true;
cache_addb(0x9d); //POPFD
} }
x86gen.stored_flags++;
} }
static void gen_restoreflags(bool noreduce=false) { static void gen_protectflags(void) {
if (noreduce) { if (x86gen.flagsactive) {
cache_addb(0x9d); x86gen.flagsactive=false;
return; 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) { static void gen_reinit(void) {
x86gen.last_used=0; x86gen.last_used=0;
x86gen.stored_flags=0; x86gen.flagsactive=false;
for (Bitu i=0;i<X86_REGS;i++) { for (Bitu i=0;i<X86_REGS;i++) {
x86gen.regs[i]->dynreg=0; x86gen.regs[i]->dynreg=0;
} }
@ -483,55 +474,32 @@ static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) {
dr1->flags|=DYNFLG_CHANGED; 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); ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
GenReg * gr1=FindDynReg(dr1); GenReg * gr1=FindDynReg(dr1);
switch (op) { cache_addw(0xc0d2+(((Bit16u)op) << 11)+ ((gr1->index+di1)<<8));
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();
}
dr1->flags|=DYNFLG_CHANGED; dr1->flags|=DYNFLG_CHANGED;
} }
static void gen_shift_word(ShiftOps op,DynReg * drecx,bool dword,DynReg * dr1) { static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) {
ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
GenReg * gr1=FindDynReg(dr1); GenReg * gr1=FindDynReg(dr1);
if (!dword) cache_addb(0x66); cache_addw(0xc0c0+(((Bit16u)op) << 11) + ((gr1->index+di1)<<8));
switch (op) { cache_addb(imm);
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();
}
dr1->flags|=DYNFLG_CHANGED; 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); GenReg * gr1=FindDynReg(dr1);
if (!dword) cache_addb(0x66); if (!dword) cache_addb(0x66);
switch (op) { cache_addw(0xc0d3+(((Bit16u)op) << 11) + ((gr1->index)<<8));
case SHIFT_ROL:cache_addw(0xc0c1+((gr1->index)<<8));break; dr1->flags|=DYNFLG_CHANGED;
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; static void gen_shift_word_imm(Bitu op,bool dword,DynReg * dr1,Bit8u imm) {
case SHIFT_SHL:cache_addw(0xe0c1+((gr1->index)<<8));break; GenReg * gr1=FindDynReg(dr1);
case SHIFT_SHR:cache_addw(0xe8c1+((gr1->index)<<8));break; if (!dword) cache_addb(0x66);
case SHIFT_SAR:cache_addw(0xf8c1+((gr1->index)<<8));break; cache_addw(0xc0c1+(((Bit16u)op) << 11) + ((gr1->index)<<8));
default:
IllegalOption();
}
cache_addb(imm); cache_addb(imm);
dr1->flags|=DYNFLG_CHANGED; 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]->Clear();
x86gen.regs[X86_REG_EAX]->notusable=true;; x86gen.regs[X86_REG_EAX]->notusable=true;;
/* Save the flags */ /* Save the flags */
gen_storeflags(); gen_protectflags();
/* Scan for the amount of params */ /* Scan for the amount of params */
if (ops) { if (ops) {
va_list params; va_list params;
@ -704,7 +672,6 @@ static void gen_call_function(void * func,char * ops,...) {
} }
dynreg->flags|=DYNFLG_CHANGED; dynreg->flags|=DYNFLG_CHANGED;
} }
gen_restoreflags();
/* Restore EAX registers to be used again */ /* Restore EAX registers to be used again */
x86gen.regs[X86_REG_EAX]->notusable=false; 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) { 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); *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); GenReg * genreg=FindDynReg(dynreg);
if (!stored) cache_addb(0x9c); //Pushfd cache_addb(0x8b); //MOV REG,[esp]
cache_addb(0x58+genreg->index); //POP 32 REG cache_addw(0x2404+(genreg->index << 3));
dynreg->flags|=DYNFLG_CHANGED; dynreg->flags|=DYNFLG_CHANGED;
} }
static void gen_load_flags(DynReg * dynreg) { static void gen_load_flags(DynReg * dynreg) {
if (x86gen.flagsactive) IllegalOption();
cache_addw(0xc483); //ADD ESP,4
cache_addb(0x4);
GenReg * genreg=FindDynReg(dynreg); GenReg * genreg=FindDynReg(dynreg);
cache_addb(0x50+genreg->index); //PUSH 32 cache_addb(0x50+genreg->index); //PUSH 32
cache_addb(0x9d); //POPFD
} }
static void gen_save_host_direct(void * data,Bits imm) { 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) { 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_addd(retcode);
cache_addb(0xc3); cache_addb(0xc3); //RET
} }
static void gen_init(void) { static void gen_init(void) {

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -30,7 +30,7 @@ static void dyn_string(STRING_OP op) {
DynReg * si_base=decode.segprefix ? decode.segprefix : DREG(DS); DynReg * si_base=decode.segprefix ? decode.segprefix : DREG(DS);
DynReg * di_base=DREG(ES); DynReg * di_base=DREG(ES);
DynReg * tmp_reg;bool usesi;bool usedi; DynReg * tmp_reg;bool usesi;bool usedi;
gen_storeflags(); gen_protectflags();
if (decode.rep) { if (decode.rep) {
gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles); gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);
gen_releasereg(DREG(CYCLES)); gen_releasereg(DREG(CYCLES));
@ -149,9 +149,8 @@ static void dyn_string(STRING_OP op) {
gen_releasereg(DREG(CYCLES)); gen_releasereg(DREG(CYCLES));
dyn_savestate(&cycle_state); dyn_savestate(&cycle_state);
Bit8u * cycle_branch=gen_create_branch(BR_NLE); Bit8u * cycle_branch=gen_create_branch(BR_NLE);
gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start); gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start);
dyn_releaseregs(); dyn_save_critical_regs();
gen_restoreflags(true);
gen_return(BR_Cycles); gen_return(BR_Cycles);
gen_fill_branch(cycle_branch); gen_fill_branch(cycle_branch);
dyn_loadstate(&cycle_state); dyn_loadstate(&cycle_state);
@ -161,5 +160,4 @@ static void dyn_string(STRING_OP op) {
gen_fill_jump(rep_ecx_jmp); gen_fill_jump(rep_ecx_jmp);
} }
gen_releasereg(DREG(TMPW)); gen_releasereg(DREG(TMPW));
gen_restoreflags();
} }

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -54,47 +54,28 @@ typedef PhysPt EAPoint;
#include "core_full/optable.h" #include "core_full/optable.h"
#include "instructions.h" #include "instructions.h"
#define LEAVECORE \
SaveIP(); \
FillFlags();
#define EXCEPTION(blah) \ #define EXCEPTION(blah) \
{ \ { \
Bit8u new_num=blah; \ Bit8u new_num=blah; \
IPPoint=inst.opcode_start; \
LEAVECORE; \
CPU_Exception(new_num,0); \ CPU_Exception(new_num,0); \
LoadIP(); \ continue; \
goto nextopcode; \
} }
Bits CPU_Core_Full_Run(void) { Bits CPU_Core_Full_Run(void) {
FullData inst; 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) { while (CPU_Cycles-->0) {
#if C_DEBUG #if C_DEBUG
cycle_count++; cycle_count++;
#if C_HEAVY_DEBUG #if C_HEAVY_DEBUG
SaveIP();
if (DEBUG_HeavyIsBreakpoint()) { if (DEBUG_HeavyIsBreakpoint()) {
LEAVECORE; FillFlags();
return debugCallback; return debugCallback;
}; };
#endif #endif
#endif #endif
inst.opcode_start=IPPoint; LoadIP();
inst.entry=inst.start_entry; inst.entry=cpu.code.big*0x200;
inst.prefix=inst.start_prefix; inst.prefix=cpu.code.big;
restartopcode: restartopcode:
inst.entry=(inst.entry & 0xffffff00) | Fetchb(); inst.entry=(inst.entry & 0xffffff00) | Fetchb();
inst.code=OpCodeTable[inst.entry]; inst.code=OpCodeTable[inst.entry];
@ -102,9 +83,13 @@ restartopcode:
#include "core_full/op.h" #include "core_full/op.h"
#include "core_full/save.h" #include "core_full/save.h"
nextopcode:; nextopcode:;
SaveIP();
continue;
illegalopcode:
LOG_MSG("Illegal opcode");
CPU_Exception(0x6,0);
} }
exit_core: FillFlags();
LEAVECORE;
return CBRET_NONE; return CBRET_NONE;
} }

View File

@ -144,18 +144,12 @@ l_M_Ed:
inst.op1.d=SegValue((SegNames)inst.rm_index); inst.op1.d=SegValue((SegNames)inst.rm_index);
break; break;
case M_Efw: case M_Efw:
if (inst.rm>=0xC0) { if (inst.rm>=0xc0) goto illegalopcode;
LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw ");
goto nextopcode;
}
inst.op1.d=LoadMw(inst.rm_eaa); inst.op1.d=LoadMw(inst.rm_eaa);
inst.op2.d=LoadMw(inst.rm_eaa+2); inst.op2.d=LoadMw(inst.rm_eaa+2);
break; break;
case M_Efd: case M_Efd:
if (inst.rm>=0xc0) { if (inst.rm>=0xc0) goto illegalopcode;
LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw ");
goto nextopcode;
}
inst.op1.d=LoadMd(inst.rm_eaa); inst.op1.d=LoadMd(inst.rm_eaa);
inst.op2.d=LoadMw(inst.rm_eaa+4); inst.op2.d=LoadMw(inst.rm_eaa+4);
break; break;
@ -183,8 +177,6 @@ l_M_Ed:
inst.op2.d=1; inst.op2.d=1;
inst.code=Groups[inst.code.op][inst.rm_index]; inst.code=Groups[inst.code.op][inst.rm_index];
goto l_MODRMswitch; goto l_MODRMswitch;
/* Should continue with normal handler afterwards */
case 0: case 0:
break; break;
default: default:
@ -246,9 +238,6 @@ l_M_Ed:
case L_REGd: case L_REGd:
inst.op1.d=reg_32(inst.code.extra); inst.op1.d=reg_32(inst.code.extra);
break; break;
case L_FLG:
inst.op1.d = FillFlags();
break;
case L_SEG: case L_SEG:
inst.op1.d=SegValue((SegNames)inst.code.extra); inst.op1.d=SegValue((SegNames)inst.code.extra);
break; break;
@ -282,10 +271,10 @@ l_M_Ed:
inst.repz=true; inst.repz=true;
goto restartopcode; goto restartopcode;
case L_PREOP: case L_PREOP:
inst.entry=inst.start_entry ^ 0x200; inst.entry=(cpu.code.big ^1) * 0x200;
goto restartopcode; goto restartopcode;
case L_PREADD: case L_PREADD:
inst.prefix^=PREFIX_ADDR; inst.prefix=(inst.prefix & ~1) | (cpu.code.big ^ 1);
goto restartopcode; goto restartopcode;
case L_VAL: case L_VAL:
inst.op1.d=inst.code.extra; inst.op1.d=inst.code.extra;
@ -295,41 +284,40 @@ l_M_Ed:
inst.op1.d=4; inst.op1.d=4;
break; break;
case D_IRETw: case D_IRETw:
LEAVECORE; FillFlags();
CPU_IRET(false); CPU_IRET(false,GetIP());
if (GETFLAG(IF) && PIC_IRQCheck) { if (GETFLAG(IF) && PIC_IRQCheck) {
return CBRET_NONE; return CBRET_NONE;
} }
goto restart_core; continue;
case D_IRETd: case D_IRETd:
LEAVECORE; FillFlags();
CPU_IRET(true); CPU_IRET(true,GetIP());
if (GETFLAG(IF) && PIC_IRQCheck) { if (GETFLAG(IF) && PIC_IRQCheck)
return CBRET_NONE; return CBRET_NONE;
} continue;
goto restart_core;
case D_RETFwIw: case D_RETFwIw:
{ {
Bitu words=Fetchw(); Bitu words=Fetchw();
LEAVECORE; FillFlags();
CPU_RET(false,words); CPU_RET(false,words,GetIP());
goto restart_core; continue;
} }
case D_RETFw: case D_RETFw:
LEAVECORE; FillFlags();
CPU_RET(false,0); CPU_RET(false,0,GetIP());
goto restart_core; continue;
case D_RETFdIw: case D_RETFdIw:
{ {
Bitu words=Fetchw(); Bitu words=Fetchw();
LEAVECORE; FillFlags();
CPU_RET(true,words); CPU_RET(true,words,GetIP());
goto restart_core; continue;
} }
case D_RETFd: case D_RETFd:
LEAVECORE; FillFlags();
CPU_RET(true,0); CPU_RET(true,0,GetIP());
goto restart_core; continue;
/* Direct operations */ /* Direct operations */
case L_STRING: case L_STRING:
#include "string.h" #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(); reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
goto nextopcode; goto nextopcode;
case D_POPSEGw: case D_POPSEGw:
if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_16())) { if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException();
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=2;
CPU_StartException();goto restart_core;
}
goto nextopcode; goto nextopcode;
case D_POPSEGd: case D_POPSEGd:
if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_32())) { if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException();
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=4;
CPU_StartException();goto restart_core;
}
goto nextopcode; goto nextopcode;
case D_SETALC: case D_SETALC:
reg_al = get_CF() ? 0xFF : 0; reg_al = get_CF() ? 0xFF : 0;
@ -403,14 +383,10 @@ l_M_Ed:
else reg_edx=0; else reg_edx=0;
goto nextopcode; goto nextopcode;
case D_CLI: case D_CLI:
SETFLAGBIT(IF,false); if (CPU_CLI()) RunException();
goto nextopcode; goto nextopcode;
case D_STI: case D_STI:
SETFLAGBIT(IF,true); if (CPU_STI()) RunException();
if (GETFLAG(IF) && PIC_IRQCheck) {
LEAVECORE;
return CBRET_NONE;
}
goto nextopcode; goto nextopcode;
case D_STC: case D_STC:
FillFlags();SETFLAGBIT(CF,true); FillFlags();SETFLAGBIT(CF,true);
@ -430,71 +406,40 @@ l_M_Ed:
SETFLAGBIT(DF,true); SETFLAGBIT(DF,true);
cpu.direction=-1; cpu.direction=-1;
goto nextopcode; 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_WAIT:
case D_NOP: case D_NOP:
goto nextopcode; goto nextopcode;
case D_ENTERw: case D_ENTERw:
{ {
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; Bitu bytes=Fetchw();
Bitu frame_ptr=reg_esp-2; Bitu level=Fetchb();
if (cpu.stack.big) { CPU_ENTER(false,bytes,level);
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;
goto nextopcode; goto nextopcode;
} }
case D_ENTERd: case D_ENTERd:
{ {
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; Bitu bytes=Fetchw();
Bitu frame_ptr=reg_esp-4; Bitu level=Fetchb();
if (cpu.stack.big) { CPU_ENTER(true,bytes,level);
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;
goto nextopcode; goto nextopcode;
} }
case D_LEAVEw: case D_LEAVEw:
@ -523,14 +468,14 @@ l_M_Ed:
CPU_CPUID(); CPU_CPUID();
goto nextopcode; goto nextopcode;
case D_HLT: case D_HLT:
LEAVECORE; FillFlags();
CPU_HLT(IPPoint-inst.opcode_start); CPU_HLT(GetIP());
return CBRET_NONE; return CBRET_NONE;
case D_CLTS: case D_CLTS:
//TODO Really clear it sometime //TODO Really clear it sometime
goto nextopcode; goto nextopcode;
default: default:
LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %X",inst.code.load,inst.entry); 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 SaveIP() reg_eip=(Bit32u)(inst.cseip-SegBase(cs));
#define LoadIP() IPPoint=SegBase(cs)+reg_eip; #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) { static INLINE Bit8u the_Fetchb(EAPoint & loc) {
Bit8u temp=LoadMb(loc); Bit8u temp=LoadMb(loc);
@ -19,42 +25,16 @@ static INLINE Bit32u the_Fetchd(EAPoint & loc) {
return temp; return temp;
} }
#define Fetchb() the_Fetchb(IPPoint) #define Fetchb() the_Fetchb(inst.cseip)
#define Fetchw() the_Fetchw(IPPoint) #define Fetchw() the_Fetchw(inst.cseip)
#define Fetchd() the_Fetchd(IPPoint) #define Fetchd() the_Fetchd(inst.cseip)
#define Fetchbs() (Bit8s)the_Fetchb(IPPoint) #define Fetchbs() (Bit8s)the_Fetchb(inst.cseip)
#define Fetchws() (Bit16s)the_Fetchw(IPPoint) #define Fetchws() (Bit16s)the_Fetchw(inst.cseip)
#define Fetchds() (Bit32s)the_Fetchd(IPPoint) #define Fetchds() (Bit32s)the_Fetchd(inst.cseip)
#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 Push_16 CPU_Push16 #define Push_16 CPU_Push16
#define Push_32 CPU_Push32 #define Push_32 CPU_Push32
#define Pop_16 CPU_Pop16 #define Pop_16 CPU_Pop16
#define Pop_32 CPU_Pop32 #define Pop_32 CPU_Pop32
#endif

View File

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

View File

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

View File

@ -56,29 +56,14 @@ switch (inst.code.save) {
reg_32(inst.code.extra)=inst.op1.d; reg_32(inst.code.extra)=inst.op1.d;
break; break;
case S_SEGm: case S_SEGm:
if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) { if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) RunException();
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);
CPU_StartException();
goto restart_core;
}
break; break;
case S_SEGGw: case S_SEGGw:
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) { if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) RunException();
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);
CPU_StartException();
goto restart_core;
}
reg_16(inst.rm_index)=inst.op1.w; reg_16(inst.rm_index)=inst.op1.w;
break; break;
case S_SEGGd: case S_SEGGd:
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) { if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) RunException();
LEAVECORE;
reg_eip-=(IPPoint-inst.opcode_start);
CPU_StartException();
goto restart_core;
}
reg_32(inst.rm_index)=inst.op1.d; reg_32(inst.rm_index)=inst.op1.d;
break; break;
case S_PUSHw: case S_PUSHw:
@ -94,39 +79,19 @@ switch (inst.code.save) {
SaveIP(); SaveIP();
reg_eip+=inst.op1.d; reg_eip+=inst.op1.d;
reg_eip&=0xffff; reg_eip&=0xffff;
LoadIP(); continue;
break;
case S_C_AIPd: case S_C_AIPd:
if (!inst.cond) goto nextopcode; if (!inst.cond) goto nextopcode;
case S_AIPd: case S_AIPd:
SaveIP(); SaveIP();
reg_eip+=inst.op1.d; reg_eip+=inst.op1.d;
LoadIP(); continue;
break;
case S_IPIw: case S_IPIw:
reg_esp+=Fetchw(); reg_esp+=Fetchw();
case S_IP: case S_IP:
SaveIP(); SaveIP();
reg_eip=inst.op1.d; reg_eip=inst.op1.d;
LoadIP(); continue;
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;
case 0: case 0:
break; break;
default: default:

View File

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

View File

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

View File

@ -9,13 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <stdio.h>
#include "dosbox.h" #include "dosbox.h"
#include "mem.h" #include "mem.h"
@ -30,43 +31,23 @@
#include "debug.h" #include "debug.h"
#endif #endif
#define SegBase(c) SegPhys(c)
#if (!C_CORE_INLINE) #if (!C_CORE_INLINE)
#define LoadMb(off) mem_readb(off) #define LoadMb(off) mem_readb(off)
#define LoadMw(off) mem_readw(off) #define LoadMw(off) mem_readw(off)
#define LoadMd(off) mem_readd(off) #define LoadMd(off) mem_readd(off)
#define SaveMb(off,val) mem_writeb(off,val) #define SaveMb(off,val) mem_writeb(off,val)
#define SaveMw(off,val) mem_writew(off,val) #define SaveMw(off,val) mem_writew(off,val)
#define SaveMd(off,val) mem_writed(off,val) #define SaveMd(off,val) mem_writed(off,val)
#else #else
#include "paging.h" #include "paging.h"
#define LoadMb(off) mem_readb_inline(off) #define LoadMb(off) mem_readb_inline(off)
#define LoadMw(off) mem_readw_inline(off) #define LoadMw(off) mem_readw_inline(off)
#define LoadMd(off) mem_readd_inline(off) #define LoadMd(off) mem_readd_inline(off)
#define SaveMb(off,val) mem_writeb_inline(off,val) #define SaveMb(off,val) mem_writeb_inline(off,val)
#define SaveMw(off,val) mem_writew_inline(off,val) #define SaveMw(off,val) mem_writew_inline(off,val)
#define SaveMd(off,val) mem_writed_inline(off,val) #define SaveMd(off,val) mem_writed_inline(off,val)
#endif #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; extern Bitu cycle_count;
#if C_FPU #if C_FPU
@ -80,122 +61,129 @@ extern Bitu cycle_count;
#define OPCODE_0F 0x100 #define OPCODE_0F 0x100
#define OPCODE_SIZE 0x200 #define OPCODE_SIZE 0x200
#define PREFIX_SEG 0x1 #define PREFIX_ADDR 0x1
#define PREFIX_ADDR 0x2 #define PREFIX_REP 0x2
#define PREFIX_SEG_ADDR (PREFIX_SEG|PREFIX_ADDR)
#define PREFIX_REP 0x4
#define TEST_PREFIX_SEG (core.prefixes & PREFIX_SEG)
#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) #define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR)
#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) #define TEST_PREFIX_REP (core.prefixes & PREFIX_REP)
#define DO_PREFIX_SEG(_SEG) \ #define DO_PREFIX_SEG(_SEG) \
core.prefixes|=PREFIX_SEG; \ BaseDS=SegBase(_SEG); \
core.seg_prefix_base=SegBase(_SEG); \ BaseSS=SegBase(_SEG); \
goto restart_prefix; goto restart_opcode;
#define DO_PREFIX_ADDR() \ #define DO_PREFIX_ADDR() \
core.prefixes^=PREFIX_ADDR; \ core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \
goto restart_prefix; (cpu.code.big ^ PREFIX_ADDR); \
core.ea_table=&EATable[(core.prefixes&1) * 256]; \
goto restart_opcode;
#define DO_PREFIX_REP(_ZERO) \ #define DO_PREFIX_REP(_ZERO) \
core.prefixes|=PREFIX_REP; \ core.prefixes|=PREFIX_REP; \
core.rep_zero=_ZERO; \ 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 { static struct {
Bitu opcode_index; Bitu opcode_index;
Bitu prefixes; PhysPt cseip;
Bitu index_default; PhysPt base_ds,base_ss;
Bitu prefix_default;
PhysPt op_start;
PhysPt ip_lookup;
PhysPt seg_prefix_base;
bool rep_zero; bool rep_zero;
GetEATable * ea_table; Bitu prefixes;
GetEAHandler * ea_table;
struct { struct {
bool skip; bool skip;
} trap; } trap;
} core; } 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 "instructions.h"
#include "core_normal/support.h" #include "core_normal/support.h"
#include "core_normal/string.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) \ #define EALookupTable (core.ea_table)
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))
Bits CPU_Core_Normal_Run(void) { 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) { while (CPU_Cycles-->0) {
core.op_start=core.ip_lookup; LOADIP;
core.opcode_index=core.index_default; core.opcode_index=cpu.code.big*0x200;
core.prefixes=core.prefix_default; core.prefixes=cpu.code.big;
core.ea_table=&EATable[cpu.code.big*256];
BaseDS=SegBase(ds);
BaseSS=SegBase(ss);
#if C_DEBUG #if C_DEBUG
cycle_count++;
#if C_HEAVY_DEBUG #if C_HEAVY_DEBUG
SAVEIP;
if (DEBUG_HeavyIsBreakpoint()) { if (DEBUG_HeavyIsBreakpoint()) {
LEAVECORE; FillFlags();
return debugCallback; return debugCallback;
}; };
#endif #endif
cycle_count++;
#endif #endif
restart_prefix:
core.ea_table=EAPrefixTable[core.prefixes];
restart_opcode: restart_opcode:
switch (core.opcode_index+Fetchb()) { switch (core.opcode_index+Fetchb()) {
#include "core_normal/prefix_none.h" #include "core_normal/prefix_none.h"
#include "core_normal/prefix_0f.h" #include "core_normal/prefix_0f.h"
#include "core_normal/prefix_66.h" #include "core_normal/prefix_66.h"
#include "core_normal/prefix_66_0f.h" #include "core_normal/prefix_66_0f.h"
default: default:
ADDIPFAST(-1); illegal_opcode:
#if C_DEBUG #if C_DEBUG
LOG_MSG("Unhandled code %X",core.opcode_index+Fetchb()); {
#else Bitu len=(GETIP-reg_eip);
E_Exit("Unhandled CPU opcode"); 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 #endif
CPU_Exception(6,0);
continue;
} }
SAVEIP;
} }
decode_end: FillFlags();
LEAVECORE; return CBRET_NONE;
decode_end:
SAVEIP;
FillFlags();
return CBRET_NONE; return CBRET_NONE;
} }
@ -206,7 +194,7 @@ Bits CPU_Core_Normal_Trap_Run(void) {
core.trap.skip=false; core.trap.skip=false;
Bits ret=CPU_Core_Normal_Run(); 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; CPU_Cycles = oldCycles-1;
cpudecoder = &CPU_Core_Normal_Run; cpudecoder = &CPU_Core_Normal_Run;

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -141,17 +141,22 @@
} \ } \
} }
#define POPSEG(_SEG_,_VAL_,_ESP_CHANGE_) \ #define CASE_W(_WHICH) \
if (CPU_SetSegGeneral(_SEG_,_VAL_)) { \ case (OPCODE_NONE+_WHICH):
LEAVECORE; \
reg_eip-=(core.ip_lookup-core.op_start);reg_esp-=_ESP_CHANGE_; \
CPU_StartException();goto decode_start; \
}
#define LOADSEG(_SEG_,_SEG_VAL_) \ #define CASE_D(_WHICH) \
if (CPU_SetSegGeneral(_SEG_,_SEG_VAL_)) { \ case (OPCODE_SIZE+_WHICH):
LEAVECORE; \
reg_eip-=(core.ip_lookup-core.op_start); \
CPU_StartException();goto decode_start; \
} \
#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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -45,7 +45,7 @@
} }
break; break;
default: default:
LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); goto illegal_opcode;
} }
} }
break; break;
@ -77,7 +77,7 @@
break; break;
case 0x06: /* LMSW */ case 0x06: /* LMSW */
limit=LoadMw(eaa); limit=LoadMw(eaa);
if (!CPU_LMSW(limit)) goto decode_end; if (CPU_LMSW(limit)) RUNEXCEPTION();
break; break;
} }
} else { } else {
@ -88,11 +88,10 @@
*earw=limit; *earw=limit;
break; break;
case 0x06: /* LMSW */ case 0x06: /* LMSW */
if (!CPU_LMSW(*earw)) goto decode_end; if (CPU_LMSW(*earw)) RUNEXCEPTION();
break; break;
default: default:
LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which); goto illegal_opcode;
break;
} }
} }
} }
@ -100,7 +99,7 @@
CASE_0F_W(0x02) /* LAR Gw,Ew */ CASE_0F_W(0x02) /* LAR Gw,Ew */
{ {
FillFlags(); FillFlags();
GetRMrw;Bitu ar; GetRMrw;Bitu ar=*rmrw;
if (rm >= 0xc0) { if (rm >= 0xc0) {
GetEArw;CPU_LAR(*earw,ar); GetEArw;CPU_LAR(*earw,ar);
} else { } else {
@ -112,7 +111,7 @@
CASE_0F_W(0x03) /* LSL Gw,Ew */ CASE_0F_W(0x03) /* LSL Gw,Ew */
{ {
FillFlags(); FillFlags();
GetRMrw;Bitu limit; GetRMrw;Bitu limit=*rmrw;
if (rm >= 0xc0) { if (rm >= 0xc0) {
GetEArw;CPU_LSL(*earw,limit); GetEArw;CPU_LSL(*earw,limit);
} else { } else {
@ -154,11 +153,8 @@
Bitu which=(rm >> 3) & 7; Bitu which=(rm >> 3) & 7;
if (rm >= 0xc0 ) { if (rm >= 0xc0 ) {
GetEArd; GetEArd;
CPU_SET_CRX(which,*eard); if (CPU_SET_CRX(which,*eard)) RUNEXCEPTION();
} else { } else goto illegal_opcode;
GetEAa;
LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which);
}
} }
break; break;
CASE_0F_B(0x23) /* MOV DRx,Rd */ CASE_0F_B(0x23) /* MOV DRx,Rd */
@ -241,7 +237,7 @@
CASE_0F_W(0xa0) /* PUSH FS */ CASE_0F_W(0xa0) /* PUSH FS */
Push_16(SegValue(fs));break; Push_16(SegValue(fs));break;
CASE_0F_W(0xa1) /* POP FS */ CASE_0F_W(0xa1) /* POP FS */
POPSEG(fs,Pop_16(),2); if (CPU_PopSeg(fs,false)) RUNEXCEPTION();
break; break;
CASE_0F_B(0xa2) /* CPUID */ CASE_0F_B(0xa2) /* CPUID */
CPU_CPUID();break; CPU_CPUID();break;
@ -268,7 +264,8 @@
CASE_0F_W(0xa8) /* PUSH GS */ CASE_0F_W(0xa8) /* PUSH GS */
Push_16(SegValue(gs));break; Push_16(SegValue(gs));break;
CASE_0F_W(0xa9) /* POP GS */ 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 */ CASE_0F_W(0xab) /* BTS Ew,Gw */
{ {
FillFlags();GetRMrw; FillFlags();GetRMrw;
@ -297,7 +294,7 @@
CASE_0F_W(0xb2) /* LSS Ew */ CASE_0F_W(0xb2) /* LSS Ew */
{ {
GetRMrw;GetEAa; GetRMrw;GetEAa;
LOADSEG(ss,LoadMw(eaa+2)); if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION();
*rmrw=LoadMw(eaa); *rmrw=LoadMw(eaa);
break; break;
} }
@ -320,14 +317,14 @@
CASE_0F_W(0xb4) /* LFS Ew */ CASE_0F_W(0xb4) /* LFS Ew */
{ {
GetRMrw;GetEAa; GetRMrw;GetEAa;
LOADSEG(fs,LoadMw(eaa+2)); if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION();
*rmrw=LoadMw(eaa); *rmrw=LoadMw(eaa);
break; break;
} }
CASE_0F_W(0xb5) /* LGS Ew */ CASE_0F_W(0xb5) /* LGS Ew */
{ {
GetRMrw;GetEAa; GetRMrw;GetEAa;
LOADSEG(gs,LoadMw(eaa+2)); if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION();
*rmrw=LoadMw(eaa); *rmrw=LoadMw(eaa);
break; break;
} }

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -25,7 +25,8 @@
CASE_D(0x06) /* PUSH ES */ CASE_D(0x06) /* PUSH ES */
Push_32(SegValue(es));break; Push_32(SegValue(es));break;
CASE_D(0x07) /* POP ES */ CASE_D(0x07) /* POP ES */
POPSEG(es,Pop_32(),4);break; if (CPU_PopSeg(es,true)) RUNEXCEPTION();
break;
CASE_D(0x09) /* OR Ed,Gd */ CASE_D(0x09) /* OR Ed,Gd */
RMEdGd(ORD);break; RMEdGd(ORD);break;
CASE_D(0x0b) /* OR Gd,Ed */ CASE_D(0x0b) /* OR Gd,Ed */
@ -43,7 +44,7 @@
CASE_D(0x16) /* PUSH SS */ CASE_D(0x16) /* PUSH SS */
Push_32(SegValue(ss));break; Push_32(SegValue(ss));break;
CASE_D(0x17) /* POP SS */ CASE_D(0x17) /* POP SS */
POPSEG(ss,Pop_32(),4); if (CPU_PopSeg(ss,true)) RUNEXCEPTION();
CPU_Cycles++; CPU_Cycles++;
break; break;
CASE_D(0x19) /* SBB Ed,Gd */ CASE_D(0x19) /* SBB Ed,Gd */
@ -55,7 +56,8 @@
CASE_D(0x1e) /* PUSH DS */ CASE_D(0x1e) /* PUSH DS */
Push_32(SegValue(ds));break; Push_32(SegValue(ds));break;
CASE_D(0x1f) /* POP DS */ CASE_D(0x1f) /* POP DS */
POPSEG(ds,Pop_32(),4);break; if (CPU_PopSeg(ds,true)) RUNEXCEPTION();
break;
CASE_D(0x21) /* AND Ed,Gd */ CASE_D(0x21) /* AND Ed,Gd */
RMEdGd(ANDD);break; RMEdGd(ANDD);break;
CASE_D(0x23) /* AND Gd,Ed */ CASE_D(0x23) /* AND Gd,Ed */
@ -167,6 +169,7 @@
break; break;
CASE_D(0x63) /* ARPL Ed,Rd */ CASE_D(0x63) /* ARPL Ed,Rd */
{ {
if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode;
FillFlags(); FillFlags();
GetRMrw; GetRMrw;
if (rm >= 0xc0 ) { if (rm >= 0xc0 ) {
@ -190,6 +193,12 @@
CASE_D(0x6b) /* IMUL Gd,Ed,Ib */ CASE_D(0x6b) /* IMUL Gd,Ed,Ib */
RMGdEdOp3(DIMULD,Fetchbs()); RMGdEdOp3(DIMULD,Fetchbs());
break; 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 */ CASE_D(0x70) /* JO */
JumpCond32_b(TFLG_O);break; JumpCond32_b(TFLG_O);break;
CASE_D(0x71) /* JNO */ CASE_D(0x71) /* JNO */
@ -332,12 +341,12 @@
CASE_D(0x8d) /* LEA Gd */ CASE_D(0x8d) /* LEA Gd */
{ {
//Little hack to always use segprefixed version //Little hack to always use segprefixed version
core.seg_prefix_base=0;
GetRMrd; GetRMrd;
BaseDS=BaseSS=0;
if (TEST_PREFIX_ADDR) { if (TEST_PREFIX_ADDR) {
*rmrd=(Bit32u)(*GetEA_SEG_ADDR[rm])(); *rmrd=(Bit32u)(*EATable[256+rm])();
} else { } else {
*rmrd=(Bit32u)(*GetEA_SEG[rm])(); *rmrd=(Bit32u)(*EATable[rm])();
} }
break; break;
} }
@ -378,21 +387,17 @@
CASE_D(0x9a) /* CALL FAR Ad */ CASE_D(0x9a) /* CALL FAR Ad */
{ {
Bit32u newip=Fetchd();Bit16u newcs=Fetchw(); Bit32u newip=Fetchd();Bit16u newcs=Fetchw();
LEAVECORE; FillFlags();
CPU_CALL(true,newcs,newip); CPU_CALL(true,newcs,newip,GETIP);
goto decode_start; continue;
} }
CASE_D(0x9c) /* PUSHFD */ CASE_D(0x9c) /* PUSHFD */
FillFlags(); FillFlags();
Push_32(reg_flags); if (CPU_PUSHF(true)) RUNEXCEPTION();
break; break;
CASE_D(0x9d) /* POPFD */ CASE_D(0x9d) /* POPFD */
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { if (CPU_POPF(true)) RUNEXCEPTION();
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start; lflags.type=t_UNKNOWN;
CPU_Exception(13,0);
goto decode_start;
}
SETFLAGSd(Pop_32())
#if CPU_TRAP_CHECK #if CPU_TRAP_CHECK
if (GETFLAG(TF)) { if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run; cpudecoder=CPU_Core_Normal_Trap_Run;
@ -402,7 +407,6 @@
#if CPU_PIC_CHECK #if CPU_PIC_CHECK
if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
#endif #endif
break; break;
CASE_D(0xa1) /* MOV EAX,Od */ CASE_D(0xa1) /* MOV EAX,Od */
{ {
@ -447,25 +451,23 @@
CASE_D(0xc1) /* GRP2 Ed,Ib */ CASE_D(0xc1) /* GRP2 Ed,Ib */
GRP2D(Fetchb());break; GRP2D(Fetchb());break;
CASE_D(0xc2) /* RETN Iw */ CASE_D(0xc2) /* RETN Iw */
{ reg_eip=Pop_32();
Bit16u addsp=Fetchw(); reg_esp+=Fetchw();
SETIP(Pop_32());reg_esp+=addsp; continue;
break;
}
CASE_D(0xc3) /* RETN */ CASE_D(0xc3) /* RETN */
SETIP(Pop_32()); reg_eip=Pop_32();
break; continue;
CASE_D(0xc4) /* LES */ CASE_D(0xc4) /* LES */
{ {
GetRMrd;GetEAa; GetRMrd;GetEAa;
LOADSEG(es,LoadMw(eaa+4)); if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa); *rmrd=LoadMd(eaa);
break; break;
} }
CASE_D(0xc5) /* LDS */ CASE_D(0xc5) /* LDS */
{ {
GetRMrd;GetEAa; GetRMrd;GetEAa;
LOADSEG(ds,LoadMw(eaa+4)); if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa); *rmrd=LoadMd(eaa);
break; break;
} }
@ -478,36 +480,11 @@
} }
CASE_D(0xc8) /* ENTER Iw,Ib */ CASE_D(0xc8) /* ENTER Iw,Ib */
{ {
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; Bitu bytes=Fetchw();
Bitu frame_ptr=reg_esp-4; Bitu level=Fetchb();
if (cpu.stack.big) { CPU_ENTER(true,bytes,level);
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;
} }
break;
CASE_D(0xc9) /* LEAVE */ CASE_D(0xc9) /* LEAVE */
reg_esp&=~cpu.stack.mask; reg_esp&=~cpu.stack.mask;
reg_esp|=(reg_ebp&cpu.stack.mask); reg_esp|=(reg_ebp&cpu.stack.mask);
@ -516,20 +493,20 @@
CASE_D(0xca) /* RETF Iw */ CASE_D(0xca) /* RETF Iw */
{ {
Bitu words=Fetchw(); Bitu words=Fetchw();
LEAVECORE; FillFlags();
CPU_RET(true,words,core.ip_lookup-core.op_start); CPU_RET(true,words,GETIP);
goto decode_start; continue;
} }
CASE_D(0xcb) /* RETF */ CASE_D(0xcb) /* RETF */
{ {
LEAVECORE; FillFlags();
CPU_RET(true,0,core.ip_lookup-core.op_start); CPU_RET(true,0,GETIP);
goto decode_start; continue;
} }
CASE_D(0xcf) /* IRET */ CASE_D(0xcf) /* IRET */
{ {
LEAVECORE; FillFlags();
CPU_IRET(true); CPU_IRET(true,GETIP);
#if CPU_TRAP_CHECK #if CPU_TRAP_CHECK
if (GETFLAG(TF)) { if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run; cpudecoder=CPU_Core_Normal_Trap_Run;
@ -539,36 +516,79 @@
#if CPU_PIC_CHECK #if CPU_PIC_CHECK
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
#endif #endif
//TODO TF check continue;
goto decode_start;
} }
CASE_D(0xd1) /* GRP2 Ed,1 */ CASE_D(0xd1) /* GRP2 Ed,1 */
GRP2D(1);break; GRP2D(1);break;
CASE_D(0xd3) /* GRP2 Ed,CL */ CASE_D(0xd3) /* GRP2 Ed,CL */
GRP2D(reg_cl);break; 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 */ CASE_D(0xe5) /* IN EAX,Ib */
reg_eax=IO_ReadD(Fetchb()); {
break; Bitu port=Fetchb();
CASE_D(0xe7) /* OUT Ib,EAX */ if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
IO_WriteD(Fetchb(),reg_eax); reg_eax=IO_ReadD(port);
break;
CASE_D(0xe8) /* CALL Jd */
{
Bit32s newip=Fetchds();
Push_32((Bit32u)GETIP);
ADDIPd(newip);
break; 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 */ CASE_D(0xe9) /* JMP Jd */
ADDIPd(Fetchds()); {
break; Bit32s addip=Fetchds();
SAVEIP;
reg_eip+=addip;
continue;
}
CASE_D(0xea) /* JMP Ad */ CASE_D(0xea) /* JMP Ad */
{ {
Bit32u newip=Fetchd(); Bit32u newip=Fetchd();
Bit16u newcs=Fetchw(); Bit16u newcs=Fetchw();
LEAVECORE; FillFlags();
CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start); CPU_JMP(true,newcs,newip,GETIP);
goto decode_start; continue;
}
CASE_D(0xeb) /* JMP Jb */
{
Bit32s addip=Fetchbs();
SAVEIP;
reg_eip+=addip;
continue;
} }
CASE_D(0xed) /* IN EAX,DX */ CASE_D(0xed) /* IN EAX,DX */
reg_eax=IO_ReadD(reg_dx); reg_eax=IO_ReadD(reg_dx);
@ -631,31 +651,31 @@
RMEd(DECD); RMEd(DECD);
break; break;
case 0x02: /* CALL NEAR Ed */ case 0x02: /* CALL NEAR Ed */
if (rm >= 0xc0 ) {GetEArd;Push_32(GETIP);SETIP(*eard);} if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
else {GetEAa;Push_32(GETIP);SETIP(LoadMd(eaa));} else {GetEAa;reg_eip=LoadMd(eaa);}
break; Push_32(GETIP);
continue;
case 0x03: /* CALL FAR Ed */ case 0x03: /* CALL FAR Ed */
{ {
GetEAa; GetEAa;
Bit32u newip=LoadMd(eaa); Bit32u newip=LoadMd(eaa);
Bit16u newcs=LoadMw(eaa+4); Bit16u newcs=LoadMw(eaa+4);
LEAVECORE; FillFlags();
CPU_CALL(true,newcs,newip); CPU_CALL(true,newcs,newip,GETIP);
goto decode_start; continue;
} }
break;
case 0x04: /* JMP NEAR Ed */ case 0x04: /* JMP NEAR Ed */
if (rm >= 0xc0 ) {GetEArd;SETIP(*eard);} if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
else {GetEAa;SETIP(LoadMd(eaa));} else {GetEAa;reg_eip=LoadMd(eaa);}
break; continue;
case 0x05: /* JMP FAR Ed */ case 0x05: /* JMP FAR Ed */
{ {
GetEAa; GetEAa;
Bit32u newip=LoadMd(eaa); Bit32u newip=LoadMd(eaa);
Bit16u newcs=LoadMw(eaa+4); Bit16u newcs=LoadMw(eaa+4);
LEAVECORE; FillFlags();
CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start); CPU_JMP(true,newcs,newip,GETIP);
goto decode_start; continue;
} }
break; break;
case 0x06: /* Push Ed */ case 0x06: /* Push Ed */

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -101,7 +101,7 @@
CASE_0F_D(0x02) /* LAR Gd,Ed */ CASE_0F_D(0x02) /* LAR Gd,Ed */
{ {
FillFlags(); FillFlags();
GetRMrd;Bitu ar; GetRMrd;Bitu ar=*rmrd;
if (rm >= 0xc0) { if (rm >= 0xc0) {
GetEArw;CPU_LAR(*earw,ar); GetEArw;CPU_LAR(*earw,ar);
} else { } else {
@ -113,7 +113,7 @@
CASE_0F_D(0x03) /* LSL Gd,Ew */ CASE_0F_D(0x03) /* LSL Gd,Ew */
{ {
FillFlags(); FillFlags();
GetRMrd;Bitu limit; GetRMrd;Bitu limit=*rmrd;
/* Just load 16-bit values for selectors */ /* Just load 16-bit values for selectors */
if (rm >= 0xc0) { if (rm >= 0xc0) {
GetEArw;CPU_LSL(*earw,limit); GetEArw;CPU_LSL(*earw,limit);
@ -159,7 +159,8 @@
CASE_0F_D(0xa0) /* PUSH FS */ CASE_0F_D(0xa0) /* PUSH FS */
Push_32(SegValue(fs));break; Push_32(SegValue(fs));break;
CASE_0F_D(0xa1) /* POP FS */ 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 */ CASE_0F_D(0xa3) /* BT Ed,Gd */
{ {
FillFlags();GetRMrd; FillFlags();GetRMrd;
@ -183,7 +184,8 @@
CASE_0F_D(0xa8) /* PUSH GS */ CASE_0F_D(0xa8) /* PUSH GS */
Push_32(SegValue(gs));break; Push_32(SegValue(gs));break;
CASE_0F_D(0xa9) /* POP GS */ 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 */ CASE_0F_D(0xab) /* BTS Ed,Gd */
{ {
FillFlags();GetRMrd; FillFlags();GetRMrd;
@ -215,7 +217,7 @@
CASE_0F_D(0xb2) /* LSS Ed */ CASE_0F_D(0xb2) /* LSS Ed */
{ {
GetRMrd;GetEAa; GetRMrd;GetEAa;
LOADSEG(ss,LoadMw(eaa+4)); if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa); *rmrd=LoadMd(eaa);
break; break;
} }
@ -238,14 +240,14 @@
CASE_0F_D(0xb4) /* LFS Ed */ CASE_0F_D(0xb4) /* LFS Ed */
{ {
GetRMrd;GetEAa; GetRMrd;GetEAa;
LOADSEG(fs,LoadMw(eaa+4)); if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa); *rmrd=LoadMd(eaa);
break; break;
} }
CASE_0F_D(0xb5) /* LGS Ed */ CASE_0F_D(0xb5) /* LGS Ed */
{ {
GetRMrd;GetEAa; GetRMrd;GetEAa;
LOADSEG(gs,LoadMw(eaa+4)); if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION();
*rmrd=LoadMd(eaa); *rmrd=LoadMd(eaa);
break; break;
} }

View File

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

View File

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

View File

@ -9,66 +9,25 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#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 \ #define LoadMbs(off) (Bit8s)(LoadMb(off))
SAVEIP; \ #define LoadMws(off) (Bit16s)(LoadMw(off))
FillFlags(); #define LoadMds(off) (Bit32s)(LoadMd(off))
static INLINE void ADDIPw(Bits add) { #define LoadRb(reg) reg
SAVEIP; #define LoadRw(reg) reg
reg_eip=(Bit16u)(reg_eip+add); #define LoadRd(reg) reg
LOADIP;
}
static INLINE void ADDIPd(Bits add) { #define SaveRb(reg,val) reg=val
SAVEIP; #define SaveRw(reg,val) reg=val
reg_eip=(reg_eip+add); #define SaveRd(reg,val) reg=val
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;
}
static INLINE Bit8s Fetchbs() { static INLINE Bit8s Fetchbs() {
return Fetchb(); return Fetchb();
@ -81,68 +40,48 @@ static INLINE Bit32s Fetchds() {
return Fetchd(); return Fetchd();
} }
#if 0
static INLINE void Push_16(Bit16u blah) { #define RUNEXCEPTION() { \
reg_esp-=2; FillFlags(); \
SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); CPU_Exception(cpu.exception.which,cpu.exception.error); \
}; continue; \
}
static INLINE void Push_32(Bit32u blah) { #define EXCEPTION(blah) \
reg_esp-=4; { \
SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); CPU_Exception(blah); \
}; continue; \
}
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
//TODO Could probably make all byte operands fast? //TODO Could probably make all byte operands fast?
#define JumpCond16_b(blah) \ #define JumpCond16_b(COND) { \
if (blah) { \ SAVEIP; \
ADDIPw(Fetchbs()); \ if (COND) reg_ip+=Fetchbs(); \
} else { \ reg_ip+=1; \
ADDIPFAST(1); \ continue; \
} }
#define JumpCond32_b(blah) \ #define JumpCond16_w(COND) { \
if (blah) { \ SAVEIP; \
ADDIPd(Fetchbs()); \ if (COND) reg_ip+=Fetchws(); \
} else { \ reg_ip+=2; \
ADDIPFAST(1); \ continue; \
} }
#define JumpCond16_w(blah) \ #define JumpCond32_b(COND) { \
if (blah) { \ SAVEIP; \
ADDIPw(Fetchws()); \ if (COND) reg_eip+=Fetchbs(); \
} else { \ reg_eip+=1; \
ADDIPFAST(2); \ 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) \ #define SETcc(cc) \
{ \ { \

View File

@ -9,207 +9,137 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
typedef PhysPt (*GetEATable[256])(void);
typedef PhysPt (*EA_LookupHandler)(void); typedef PhysPt (*EA_LookupHandler)(void);
/* The MOD/RM Decoder for EA for this decoder's addressing modes */ /* 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_00_n(void) { return BaseDS+(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_01_n(void) { return BaseDS+(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_02_n(void) { return BaseSS+(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_03_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di); }
static PhysPt EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); } static PhysPt EA_16_04_n(void) { return BaseDS+(Bit16u)(reg_si); }
static PhysPt EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); } static PhysPt EA_16_05_n(void) { return BaseDS+(Bit16u)(reg_di); }
static PhysPt EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());} static PhysPt EA_16_06_n(void) { return BaseDS+(Bit16u)(Fetchw());}
static PhysPt EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); } 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_40_n(void) { return BaseDS+(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_41_n(void) { return BaseDS+(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_42_n(void) { return BaseSS+(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_43_n(void) { return BaseSS+(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_44_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchbs()); }
static PhysPt EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); } static PhysPt EA_16_45_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchbs()); }
static PhysPt EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); } static PhysPt EA_16_46_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchbs()); }
static PhysPt EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+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_80_n(void) { return BaseDS+(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_81_n(void) { return BaseDS+(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_82_n(void) { return BaseSS+(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_83_n(void) { return BaseSS+(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_84_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchws()); }
static PhysPt EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); } static PhysPt EA_16_85_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchws()); }
static PhysPt EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); } static PhysPt EA_16_86_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchws()); }
static PhysPt EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); } static PhysPt EA_16_87_n(void) { return BaseDS+(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 Bit32u SIBZero=0; static Bit32u SIBZero=0;
static Bit32u * SIBIndex[8]= { &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&SIBZero,&reg_ebp,&reg_esi,&reg_edi }; 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(); Bit8u sib=Fetchb();
PhysPt base; PhysPt base;
switch (sib&7) { switch (sib&7) {
case 0: /* EAX Base */ case 0: /* EAX Base */
base=SegBase(ds)+reg_eax;break; base=BaseDS+reg_eax;break;
case 1: /* ECX Base */ case 1: /* ECX Base */
base=SegBase(ds)+reg_ecx;break; base=BaseDS+reg_ecx;break;
case 2: /* EDX Base */ case 2: /* EDX Base */
base=SegBase(ds)+reg_edx;break; base=BaseDS+reg_edx;break;
case 3: /* EBX Base */ case 3: /* EBX Base */
base=SegBase(ds)+reg_ebx;break; base=BaseDS+reg_ebx;break;
case 4: /* ESP Base */ case 4: /* ESP Base */
base=SegBase(ss)+reg_esp;break; base=BaseSS+reg_esp;break;
case 5: /* #1 Base */ case 5: /* #1 Base */
if (!mode) { if (!mode) {
base=SegBase(ds)+Fetchd();break; base=BaseDS+Fetchd();break;
} else { } else {
base=SegBase(ss)+reg_ebp;break; base=BaseSS+reg_ebp;break;
} }
case 6: /* ESI Base */ case 6: /* ESI Base */
base=SegBase(ds)+reg_esi;break; base=BaseDS+reg_esi;break;
case 7: /* EDI Base */ case 7: /* EDI Base */
base=SegBase(ds)+reg_edi;break; base=BaseDS+reg_edi;break;
} }
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
return base; return base;
}; };
static PhysPt EA_32_00_n(void) { return BaseDS+reg_eax; }
static PhysPt EA_32_00_n(void) { return SegBase(ds)+reg_eax; } static PhysPt EA_32_01_n(void) { return BaseDS+reg_ecx; }
static PhysPt EA_32_01_n(void) { return SegBase(ds)+reg_ecx; } static PhysPt EA_32_02_n(void) { return BaseDS+reg_edx; }
static PhysPt EA_32_02_n(void) { return SegBase(ds)+reg_edx; } static PhysPt EA_32_03_n(void) { return BaseDS+reg_ebx; }
static PhysPt EA_32_03_n(void) { return SegBase(ds)+reg_ebx; }
static PhysPt EA_32_04_n(void) { return Sib(0);} 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_05_n(void) { return BaseDS+Fetchd(); }
static PhysPt EA_32_06_n(void) { return SegBase(ds)+reg_esi; } static PhysPt EA_32_06_n(void) { return BaseDS+reg_esi; }
static PhysPt EA_32_07_n(void) { return SegBase(ds)+reg_edi; } 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_40_n(void) { return BaseDS+reg_eax+Fetchbs(); }
static PhysPt EA_32_41_n(void) { return SegBase(ds)+reg_ecx+Fetchbs(); } static PhysPt EA_32_41_n(void) { return BaseDS+reg_ecx+Fetchbs(); }
static PhysPt EA_32_42_n(void) { return SegBase(ds)+reg_edx+Fetchbs(); } static PhysPt EA_32_42_n(void) { return BaseDS+reg_edx+Fetchbs(); }
static PhysPt EA_32_43_n(void) { return SegBase(ds)+reg_ebx+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) { PhysPt temp=Sib(1);return temp+Fetchbs();}
//static PhysPt EA_32_44_n(void) { return Sib(1)+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_45_n(void) { return BaseSS+reg_ebp+Fetchbs(); }
static PhysPt EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); } static PhysPt EA_32_46_n(void) { return BaseDS+reg_esi+Fetchbs(); }
static PhysPt EA_32_47_n(void) { return SegBase(ds)+reg_edi+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_80_n(void) { return BaseDS+reg_eax+Fetchds(); }
static PhysPt EA_32_81_n(void) { return SegBase(ds)+reg_ecx+Fetchds(); } static PhysPt EA_32_81_n(void) { return BaseDS+reg_ecx+Fetchds(); }
static PhysPt EA_32_82_n(void) { return SegBase(ds)+reg_edx+Fetchds(); } static PhysPt EA_32_82_n(void) { return BaseDS+reg_edx+Fetchds(); }
static PhysPt EA_32_83_n(void) { return SegBase(ds)+reg_ebx+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) { PhysPt temp=Sib(2);return temp+Fetchds();}
//static PhysPt EA_32_84_n(void) { return Sib(2)+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_85_n(void) { return BaseSS+reg_ebp+Fetchds(); }
static PhysPt EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); } static PhysPt EA_32_86_n(void) { return BaseDS+reg_esi+Fetchds(); }
static PhysPt EA_32_87_n(void) { return SegBase(ds)+reg_edi+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 */ /* 00 */
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
@ -244,113 +174,12 @@ static GetEATable GetEA_ADDR={
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; };
INLINE PhysPt Sib_s(Bitu mode) { #define GetEADirect \
Bit8u sib=Fetchb(); PhysPt eaa; \
PhysPt base; if (TEST_PREFIX_ADDR) { \
switch (sib&7) { eaa=BaseDS+Fetchd(); \
case 0: /* EAX Base */ } else { \
base=reg_eax;break; eaa=BaseDS+Fetchw(); \
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(); \
} \
}

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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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 <assert.h>
#include "dosbox.h" #include "dosbox.h"
#include "cpu.h" #include "cpu.h"
#include "memory.h" #include "memory.h"
#include "debug.h" #include "debug.h"
#include "keyboard.h" #include "mapper.h"
#include "setup.h" #include "setup.h"
#include "paging.h" #include "paging.h"
#include "support.h" #include "support.h"
@ -46,12 +46,9 @@ Bits CPU_CycleUp = 0;
Bits CPU_CycleDown = 0; Bits CPU_CycleDown = 0;
CPU_Decoder * cpudecoder; CPU_Decoder * cpudecoder;
static struct {
Bitu which,errorcode;
} exception;
void CPU_Core_Full_Init(void); void CPU_Core_Full_Init(void);
void CPU_Core_Normal_Init(void); void CPU_Core_Normal_Init(void);
void CPU_Core_Simple_Init(void);
void CPU_Core_Dyn_X86_Init(void); void CPU_Core_Dyn_X86_Init(void);
void CPU_Push16(Bitu value) { void CPU_Push16(Bitu value) {
@ -91,6 +88,48 @@ void CPU_SetFlags(Bitu word,Bitu mask) {
cpu.direction=1-((reg_flags & FLAG_DF) >> 9); 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 { class TaskStateSegment {
public: public:
TaskStateSegment() { TaskStateSegment() {
@ -148,7 +187,7 @@ enum TSwitchType {
TSwitch_JMP,TSwitch_CALL_INT,TSwitch_IRET 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; TaskStateSegment new_tss;
if (!new_tss.SetSelector(new_tss_selector)) if (!new_tss.SetSelector(new_tss_selector))
E_Exit("Illegal TSS for switch"); E_Exit("Illegal TSS for switch");
@ -163,7 +202,7 @@ bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype) {
Bitu new_ldt; Bitu new_ldt;
if (cpu_tss.is386) { if (cpu_tss.is386) {
mem_writed(cpu_tss.base+offsetof(TSS_32,eflags),reg_flags); 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,eax),reg_eax);
mem_writed(cpu_tss.base+offsetof(TSS_32,ecx),reg_ecx); mem_writed(cpu_tss.base+offsetof(TSS_32,ecx),reg_ecx);
@ -268,23 +307,31 @@ doconforming:
return true; return true;
} }
void CPU_StartException(void) { bool CPU_IO_Exception(Bitu port,Bitu size) {
CPU_Interrupt(cpu.exception.which,CPU_INT_EXCEPTION | ((cpu.exception.which>=8) ? CPU_INT_HAS_ERROR : 0)); if (cpu.pmode && ((GETFLAG_IOPL<cpu.cpl) || GETFLAG(VM))) {
} if (!cpu_tss.is386) goto doexception;
PhysPt where=cpu_tss.base+0x66;
void CPU_SetupException(Bitu which,Bitu error) { Bitu ofs=mem_readw(where);
cpu.exception.which=which; if (ofs>cpu_tss.limit) goto doexception;
cpu.exception.error=error; 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 ) { void CPU_Exception(Bitu which,Bitu error ) {
// LOG_MSG("Exception %d CS:%X IP:%X FLAGS:%X",num,SegValue(cs),reg_eip,reg_flags); // LOG_MSG("Exception %d error %x",which,error);
CPU_SetupException(which,error); cpu.exception.error=error;
CPU_StartException(); CPU_Interrupt(which,CPU_INT_EXCEPTION | ((which>=8) ? CPU_INT_HAS_ERROR : 0),reg_eip);
} }
Bit8u lastint; Bit8u lastint;
void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) {
lastint=num; lastint=num;
#if C_DEBUG #if C_DEBUG
switch (num) { switch (num) {
@ -302,10 +349,10 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
}; };
#endif #endif
if (!cpu.pmode) { if (!cpu.pmode) {
/* Save everything on a 16-bit stack */ /* Save everything on a 16-bit stack */
CPU_Push16(reg_flags & 0xffff); CPU_Push16(reg_flags & 0xffff);
CPU_Push16(SegValue(cs)); CPU_Push16(SegValue(cs));
CPU_Push16(reg_ip); CPU_Push16(oldeip);
SETFLAGBIT(IF,false); SETFLAGBIT(IF,false);
SETFLAGBIT(TF,false); SETFLAGBIT(TF,false);
/* Get the new CS:IP from vector table */ /* 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)) { 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); // LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12);
if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
reg_eip-=opLen;
CPU_Exception(13,0); CPU_Exception(13,0);
return; 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 //TODO Check for software interrupt and check gate's dpl<cpl
cpu.idt.GetDescriptor(num<<3,gate); cpu.idt.GetDescriptor(num<<3,gate);
if (type&CPU_INT_SOFTWARE && gate.DPL()<cpu.cpl) { if (type&CPU_INT_SOFTWARE && gate.DPL()<cpu.cpl) {
reg_eip-=opLen;
CPU_Exception(13,num*8+2); CPU_Exception(13,num*8+2);
return; return;
} }
@ -345,7 +390,7 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
Bitu gate_off=gate.GetOffset(); Bitu gate_off=gate.GetOffset();
cpu.gdt.GetDescriptor(gate_sel,cs_desc); cpu.gdt.GetDescriptor(gate_sel,cs_desc);
Bitu cs_dpl=cs_desc.DPL(); 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()) { switch (cs_desc.Type()) {
case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA:
case DESC_CODE_R_NC_A: case DESC_CODE_R_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 */ if (gate.Type() & 0x8) { /* 32-bit Gate */
CPU_Push32(reg_flags); CPU_Push32(reg_flags);
CPU_Push32(SegValue(cs)); CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip); CPU_Push32(oldeip);
if (type & CPU_INT_HAS_ERROR) CPU_Push32(cpu.exception.error); if (type & CPU_INT_HAS_ERROR) CPU_Push32(cpu.exception.error);
} else { /* 16-bit gate */ } else { /* 16-bit gate */
CPU_Push16(reg_flags & 0xffff); CPU_Push16(reg_flags & 0xffff);
CPU_Push16(SegValue(cs)); CPU_Push16(SegValue(cs));
CPU_Push16(reg_ip); CPU_Push16(oldeip);
if (type & CPU_INT_HAS_ERROR) CPU_Push16(cpu.exception.error); if (type & CPU_INT_HAS_ERROR) CPU_Push16(cpu.exception.error);
} }
break; break;
@ -410,7 +455,7 @@ do_interrupt:
E_Exit("INT:Gate Selector points to illegal descriptor with type %x",cs_desc.Type()); E_Exit("INT:Gate Selector points to illegal descriptor with type %x",cs_desc.Type());
} }
if (!(gate.Type()&1)) if (!(gate.Type()&1))
SETFLAGBIT(IF,false); SETFLAGBIT(IF,false);
SETFLAGBIT(TF,false); SETFLAGBIT(TF,false);
SETFLAGBIT(NT,false); SETFLAGBIT(NT,false);
SETFLAGBIT(VM,false); SETFLAGBIT(VM,false);
@ -422,7 +467,7 @@ do_interrupt:
return; return;
} }
case DESC_TASK_GATE: 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) { if (type & CPU_INT_HAS_ERROR) {
//TODO Be sure about this, seems somewhat unclear //TODO Be sure about this, seems somewhat unclear
if (cpu_tss.is386) CPU_Push32(cpu.exception.error); if (cpu_tss.is386) CPU_Push32(cpu.exception.error);
@ -437,7 +482,7 @@ do_interrupt:
return ; // make compiler happy return ; // make compiler happy
} }
void CPU_IRET(bool use32) { void CPU_IRET(bool use32,Bitu oldeip) {
if (!cpu.pmode) { /* RealMode IRET */ if (!cpu.pmode) { /* RealMode IRET */
realmode_iret: realmode_iret:
if (use32) { if (use32) {
@ -454,7 +499,6 @@ realmode_iret:
} else { /* Protected mode IRET */ } else { /* Protected mode IRET */
if (reg_flags & FLAG_VM) { if (reg_flags & FLAG_VM) {
if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
reg_eip--;
CPU_Exception(13,0); CPU_Exception(13,0);
return; return;
} else goto realmode_iret; } else goto realmode_iret;
@ -466,7 +510,7 @@ realmode_iret:
if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set"); if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set");
if (!cpu_tss.IsValid()) E_Exit("TASK Iret without valid TSS"); if (!cpu_tss.IsValid()) E_Exit("TASK Iret without valid TSS");
Bitu back_link=cpu_tss.Get_back(); Bitu back_link=cpu_tss.Get_back();
CPU_SwitchTask(back_link,TSwitch_IRET); CPU_SwitchTask(back_link,TSwitch_IRET,oldeip);
return; return;
} }
Bitu n_cs_sel,n_eip,n_flags; Bitu n_cs_sel,n_eip,n_flags;
@ -506,7 +550,7 @@ realmode_iret:
Bitu n_cs_rpl=n_cs_sel & 3; Bitu n_cs_rpl=n_cs_sel & 3;
Descriptor n_cs_desc; Descriptor n_cs_desc;
cpu.gdt.GetDescriptor(n_cs_sel,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"); E_Exit("IRET to lower privilege");
if (n_cs_rpl==cpu.cpl) { if (n_cs_rpl==cpu.cpl) {
/* Return to same level */ /* Return to same level */
@ -526,6 +570,7 @@ realmode_iret:
cpu.code.big=n_cs_desc.Big()>0; cpu.code.big=n_cs_desc.Big()>0;
Segs.val[cs]=n_cs_sel; Segs.val[cs]=n_cs_sel;
reg_eip=n_eip; reg_eip=n_eip;
CPU_SetFlagsd(n_flags); CPU_SetFlagsd(n_flags);
LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big); LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big);
} else { } else {
@ -545,9 +590,11 @@ realmode_iret:
Segs.phys[cs]=n_cs_desc.GetBase(); Segs.phys[cs]=n_cs_desc.GetBase();
cpu.code.big=n_cs_desc.Big()>0; cpu.code.big=n_cs_desc.Big()>0;
Segs.val[cs]=n_cs_sel; Segs.val[cs]=n_cs_sel;
CPU_SetFlagsd(n_flags);
cpu.cpl=n_cs_rpl; cpu.cpl=n_cs_rpl;
reg_eip=n_eip; reg_eip=n_eip;
CPU_SetFlagsd(n_flags);
Bitu n_ss,n_esp; Bitu n_ss,n_esp;
if (use32) { if (use32) {
n_esp=CPU_Pop32(); n_esp=CPU_Pop32();
@ -562,14 +609,15 @@ realmode_iret:
} else { } else {
reg_sp=n_esp; reg_sp=n_esp;
} }
//TODO Maybe validate other segments, but why would anyone use them? //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; 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 (!cpu.pmode || (reg_flags & FLAG_VM)) {
if (!use32) { if (!use32) {
reg_eip=offset&0xffff; reg_eip=offset&0xffff;
@ -584,7 +632,6 @@ void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
Descriptor desc; Descriptor desc;
cpu.gdt.GetDescriptor(selector,desc); cpu.gdt.GetDescriptor(selector,desc);
if (!desc.saved.seg.p) { if (!desc.saved.seg.p) {
reg_eip -= opLen;
CPU_Exception(0x0B,selector & 0xfffc); CPU_Exception(0x0B,selector & 0xfffc);
return; 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_N_NC_A: case DESC_CODE_N_NC_NA:
case DESC_CODE_R_NC_A: case DESC_CODE_R_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>cpu.cpl) E_Exit("JMP:NC:RPL>CPL");
if (rpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL"); if (cpu.cpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL");
cpu.cpl=desc.DPL();
LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:NC to %X:%X big %d",selector,offset,desc.Big()); LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:NC to %X:%X big %d",selector,offset,desc.Big());
goto CODE_jmp; goto CODE_jmp;
case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: 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()<cpu.cpl) E_Exit("JMP:TSS:dpl<cpl");
if (desc.DPL()<rpl) E_Exit("JMP:TSS:dpl<rpl"); if (desc.DPL()<rpl) E_Exit("JMP:TSS:dpl<rpl");
LOG(LOG_CPU,LOG_NORMAL)("JMP:TSS to %X",selector); LOG(LOG_CPU,LOG_NORMAL)("JMP:TSS to %X",selector);
CPU_SwitchTask(selector,TSwitch_JMP); CPU_SwitchTask(selector,TSwitch_JMP,oldeip);
break; break;
default: default:
E_Exit("JMP Illegal descriptor type %X",desc.Type()); 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 (!cpu.pmode || (reg_flags & FLAG_VM)) {
if (!use32) { if (!use32) {
CPU_Push16(SegValue(cs)); CPU_Push16(SegValue(cs));
CPU_Push16(reg_ip); CPU_Push16(oldeip);
reg_eip=offset&0xffff; reg_eip=offset&0xffff;
} else { } else {
CPU_Push32(SegValue(cs)); CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip); CPU_Push32(oldeip);
reg_eip=offset; reg_eip=offset;
} }
cpu.code.big=false; cpu.code.big=false;
@ -640,7 +686,6 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
Bitu rpl=selector & 3; Bitu rpl=selector & 3;
cpu.gdt.GetDescriptor(selector,call); cpu.gdt.GetDescriptor(selector,call);
if (!call.saved.seg.p) { if (!call.saved.seg.p) {
reg_eip -= opLen;
CPU_Exception(0x0B,selector & 0xfffc); CPU_Exception(0x0B,selector & 0xfffc);
return; return;
} }
@ -659,11 +704,11 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
call_code: call_code:
if (!use32) { if (!use32) {
CPU_Push16(SegValue(cs)); CPU_Push16(SegValue(cs));
CPU_Push16(reg_ip); CPU_Push16(oldeip);
reg_eip=offset & 0xffff; reg_eip=offset & 0xffff;
} else { } else {
CPU_Push32(SegValue(cs)); CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip); CPU_Push32(oldeip);
reg_eip=offset; reg_eip=offset;
} }
Segs.phys[cs]=call.GetBase(); Segs.phys[cs]=call.GetBase();
@ -679,7 +724,6 @@ call_code:
Bitu n_cs_sel=call.GetSelector(); Bitu n_cs_sel=call.GetSelector();
if (!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc)) E_Exit("Call:Gate:Invalid CS selector."); if (!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc)) E_Exit("Call:Gate:Invalid CS selector.");
if (!n_cs_desc.saved.seg.p) { if (!n_cs_desc.saved.seg.p) {
reg_eip -= opLen;
CPU_Exception(0x0B,selector & 0xfffc); CPU_Exception(0x0B,selector & 0xfffc);
return; return;
} }
@ -709,19 +753,22 @@ call_code:
if (call.Type()==DESC_386_CALL_GATE) { if (call.Type()==DESC_386_CALL_GATE) {
CPU_Push32(o_ss); //save old stack CPU_Push32(o_ss); //save old stack
CPU_Push32(o_esp); CPU_Push32(o_esp);
for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++) if (call.saved.gate.paramcount&31)
CPU_Push32(mem_readd(o_stack+i*4)); 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(SegValue(cs));
CPU_Push32(reg_eip); CPU_Push32(oldeip);
} else { } else {
CPU_Push16(o_ss); //save old stack CPU_Push16(o_ss); //save old stack
CPU_Push16(o_esp); CPU_Push16(o_esp);
for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++) if (call.saved.gate.paramcount&31)
CPU_Push16(mem_readw(o_stack+i*2)); 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(SegValue(cs));
CPU_Push16(reg_eip); CPU_Push16(oldeip);
} }
cpu.cpl = n_cs_desc.DPL();
/* Switch to new CS:EIP */ /* Switch to new CS:EIP */
Segs.phys[cs] = n_cs_desc.GetBase(); Segs.phys[cs] = n_cs_desc.GetBase();
Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl; 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()<cpu.cpl) E_Exit("CALL:TSS:dpl<cpl");
if (call.DPL()<rpl) E_Exit("CALL:TSS:dpl<rpl"); if (call.DPL()<rpl) E_Exit("CALL:TSS:dpl<rpl");
LOG(LOG_CPU,LOG_NORMAL)("CALL:TSS to %X",selector); LOG(LOG_CPU,LOG_NORMAL)("CALL:TSS to %X",selector);
CPU_SwitchTask(selector,TSwitch_CALL_INT); CPU_SwitchTask(selector,TSwitch_CALL_INT,oldeip);
break; break;
default: default:
E_Exit("CALL:Descriptor type %x unsupported",call.Type()); 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)) { if (!cpu.pmode || (reg_flags & FLAG_VM)) {
Bitu new_ip,new_cs; Bitu new_ip,new_cs;
if (!use32) { if (!use32) {
@ -775,11 +822,13 @@ void CPU_RET(bool use32,Bitu bytes,Bitu opLen) {
Descriptor desc; Descriptor desc;
Bitu rpl=selector & 3; 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); cpu.gdt.GetDescriptor(selector,desc);
if (!desc.saved.seg.p) { if (!desc.saved.seg.p) {
reg_eip -= opLen;
CPU_Exception(0x0B,selector & 0xfffc); CPU_Exception(0x0B,selector & 0xfffc);
return; return;
}; };
@ -820,7 +869,7 @@ RET_same_level:
return; return;
} else { } else {
/* Return to outer level */ /* 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; Bitu n_esp,n_ss;
if (use32) { if (use32) {
n_esp = CPU_Pop32(); n_esp = CPU_Pop32();
@ -830,16 +879,19 @@ RET_same_level:
n_ss = CPU_Pop16(); n_ss = CPU_Pop16();
} }
cpu.cpl = rpl; cpu.cpl = rpl;
CPU_SetSegGeneral(ss,n_ss); CPU_SetSegGeneral(ss,n_ss);
if (cpu.stack.big) { if (cpu.stack.big) {
reg_esp = n_esp; reg_esp = n_esp;
} else { } else {
reg_sp = n_esp; reg_sp = n_esp;
} }
Segs.phys[cs]=desc.GetBase(); Segs.phys[cs]=desc.GetBase();
cpu.code.big=desc.Big()>0; cpu.code.big=desc.Big()>0;
Segs.val[cs]=selector; Segs.val[cs]=(selector&0xfffc) | cpu.cpl;
reg_eip=offset; reg_eip=offset;
// LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL()); // LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL());
return; return;
} }
@ -899,9 +951,8 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
case 0: case 0:
{ {
Bitu changed=cpu.cr0 ^ value; Bitu changed=cpu.cr0 ^ value;
if (!changed) return true; if (!changed) return false;
cpu.cr0=value; cpu.cr0=value;
//TODO Maybe always first change to core_full for a change to cr0
if (value & CR0_PROTECTION) { if (value & CR0_PROTECTION) {
cpu.pmode=true; cpu.pmode=true;
LOG(LOG_CPU,LOG_NORMAL)("Protected mode"); LOG(LOG_CPU,LOG_NORMAL)("Protected mode");
@ -911,7 +962,7 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
PAGING_Enable(false); PAGING_Enable(false);
LOG(LOG_CPU,LOG_NORMAL)("Real mode"); LOG(LOG_CPU,LOG_NORMAL)("Real mode");
} }
return false; //Only changes with next CS change break;
} }
case 2: case 2:
paging.cr2=value; paging.cr2=value;
@ -946,11 +997,12 @@ void CPU_SMSW(Bitu & word) {
word=cpu.cr0; word=cpu.cr0;
} }
bool CPU_LMSW(Bitu word) { Bitu CPU_LMSW(Bitu word) {
word&=0xf; word&=0xf;
if (cpu.cr0 & 1) word|=1; if (cpu.cr0 & 1) word|=1;
word|=(cpu.cr0&0xfffffff0); 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) { 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) { void CPU_LAR(Bitu selector,Bitu & ar) {
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
}
Descriptor desc;Bitu rpl=selector & 3; Descriptor desc;Bitu rpl=selector & 3;
ar=0;
if (!cpu.gdt.GetDescriptor(selector,desc)){ if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false); SETFLAGBIT(ZF,false);
return; 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_N_C_A: case DESC_CODE_N_C_NA:
case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA:
break; 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_LDT:
case DESC_TASK_GATE: case DESC_TASK_GATE:
case DESC_286_TSS_A: case DESC_286_TSS_B: 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_286_CALL_GATE:
case DESC_386_TSS_A: case DESC_386_TSS_B: 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: case DESC_386_CALL_GATE:
@ -1008,8 +1067,11 @@ void CPU_LAR(Bitu selector,Bitu & ar) {
} }
void CPU_LSL(Bitu selector,Bitu & limit) { void CPU_LSL(Bitu selector,Bitu & limit) {
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
}
Descriptor desc;Bitu rpl=selector & 3; Descriptor desc;Bitu rpl=selector & 3;
limit=0;
if (!cpu.gdt.GetDescriptor(selector,desc)){ if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false); SETFLAGBIT(ZF,false);
return; 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_N_C_A: case DESC_CODE_N_C_NA:
case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA:
break; break;
case DESC_LDT: case DESC_LDT:
case DESC_286_TSS_A: case DESC_286_TSS_A:
case DESC_286_TSS_B: case DESC_286_TSS_B:
@ -1047,6 +1109,10 @@ void CPU_LSL(Bitu selector,Bitu & limit) {
} }
void CPU_VERR(Bitu selector) { void CPU_VERR(Bitu selector) {
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
}
Descriptor desc;Bitu rpl=selector & 3; Descriptor desc;Bitu rpl=selector & 3;
if (!cpu.gdt.GetDescriptor(selector,desc)){ if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false); SETFLAGBIT(ZF,false);
@ -1075,6 +1141,10 @@ void CPU_VERR(Bitu selector) {
} }
void CPU_VERW(Bitu selector) { void CPU_VERW(Bitu selector) {
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
}
Descriptor desc;Bitu rpl=selector & 3; Descriptor desc;Bitu rpl=selector & 3;
if (!cpu.gdt.GetDescriptor(selector,desc)){ if (!cpu.gdt.GetDescriptor(selector,desc)){
SETFLAGBIT(ZF,false); SETFLAGBIT(ZF,false);
@ -1113,13 +1183,11 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) {
if (!desc.saved.seg.p) { if (!desc.saved.seg.p) {
if (seg==ss) E_Exit("CPU_SetSegGeneral: Stack segment not present."); if (seg==ss) E_Exit("CPU_SetSegGeneral: Stack segment not present.");
// Throw Exception 0x0B - Segment not present // Throw Exception 0x0B - Segment not present
CPU_SetupException(0x0B,value & 0xfffc); return CPU_PrepareException(0x0B,value & 0xfffc);
return true;
} else if (seg==ss) { } else if (seg==ss) {
// Stack segment loaded with illegal segment ? // 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)) { 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 CPU_PrepareException(0x0D,value & 0xfffc);
return true;
} }
} }
} }
@ -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) { void CPU_CPUID(void) {
switch (reg_eax) { switch (reg_eax) {
case 0: /* Vendor ID String and maximum level? */ case 0: /* Vendor ID String and maximum level? */
@ -1168,12 +1244,12 @@ static Bits HLT_Decode(void) {
return 0; return 0;
} }
void CPU_HLT(Bitu opLen) { void CPU_HLT(Bitu oldeip) {
if (cpu.cpl) { if (cpu.cpl) {
reg_eip-=opLen;
CPU_Exception(13,0); CPU_Exception(13,0);
return; return;
} }
reg_eip=oldeip;
CPU_Cycles=0; CPU_Cycles=0;
cpu.hlt.cs=SegValue(cs); cpu.hlt.cs=SegValue(cs);
cpu.hlt.eip=reg_eip; cpu.hlt.eip=reg_eip;
@ -1182,8 +1258,40 @@ void CPU_HLT(Bitu opLen) {
return; 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) { static void CPU_CycleIncrease(void) {
Bits old_cycles=CPU_CycleMax; Bits old_cycles=CPU_CycleMax;
if(CPU_CycleUp < 100){ if(CPU_CycleUp < 100){
@ -1195,7 +1303,7 @@ static void CPU_CycleIncrease(void) {
CPU_CycleLeft=0;CPU_Cycles=0; CPU_CycleLeft=0;CPU_Cycles=0;
if (CPU_CycleMax==old_cycles) CPU_CycleMax++; if (CPU_CycleMax==old_cycles) CPU_CycleMax++;
LOG_MSG("CPU:%d 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) { static void CPU_CycleDecrease(void) {
@ -1207,10 +1315,9 @@ static void CPU_CycleDecrease(void) {
CPU_CycleLeft=0;CPU_Cycles=0; CPU_CycleLeft=0;CPU_Cycles=0;
if (CPU_CycleMax <= 0) CPU_CycleMax=1; if (CPU_CycleMax <= 0) CPU_CycleMax=1;
LOG_MSG("CPU:%d cycles",CPU_CycleMax); LOG_MSG("CPU:%d cycles",CPU_CycleMax);
GFX_SetTitle(CPU_CycleMax,-1); GFX_SetTitle(CPU_CycleMax,-1,false);
} }
void CPU_Init(Section* sec) { void CPU_Init(Section* sec) {
Section_prop * section=static_cast<Section_prop *>(sec); Section_prop * section=static_cast<Section_prop *>(sec);
reg_eax=0; reg_eax=0;
@ -1240,14 +1347,13 @@ void CPU_Init(Section* sec) {
/* Init the cpu cores */ /* Init the cpu cores */
CPU_Core_Normal_Init(); CPU_Core_Normal_Init();
CPU_Core_Simple_Init();
CPU_Core_Full_Init(); CPU_Core_Full_Init();
#if (C_DYNAMIC_X86) #if (C_DYNAMIC_X86)
CPU_Core_Dyn_X86_Init(); CPU_Core_Dyn_X86_Init();
#endif #endif
MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles");
KEYBOARD_AddEvent(KBD_f11,KBD_MOD_CTRL,CPU_CycleDecrease); MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles");
KEYBOARD_AddEvent(KBD_f12,KBD_MOD_CTRL,CPU_CycleIncrease);
CPU_Cycles=0; CPU_Cycles=0;
CPU_CycleMax=section->Get_int("cycles");; CPU_CycleMax=section->Get_int("cycles");;
CPU_CycleUp=section->Get_int("cycleup"); CPU_CycleUp=section->Get_int("cycleup");
@ -1256,6 +1362,8 @@ void CPU_Init(Section* sec) {
cpudecoder=&CPU_Core_Normal_Run; cpudecoder=&CPU_Core_Normal_Run;
if (!strcasecmp(core,"normal")) { if (!strcasecmp(core,"normal")) {
cpudecoder=&CPU_Core_Normal_Run; cpudecoder=&CPU_Core_Normal_Run;
} else if (!strcasecmp(core,"simple")) {
cpudecoder=&CPU_Core_Simple_Run;
} else if (!strcasecmp(core,"full")) { } else if (!strcasecmp(core,"full")) {
cpudecoder=&CPU_Core_Full_Run; cpudecoder=&CPU_Core_Full_Run;
} }
@ -1267,12 +1375,12 @@ void CPU_Init(Section* sec) {
else { else {
LOG_MSG("CPU:Unknown core type %s, switcing back to normal.",core); 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_CycleMax) CPU_CycleMax = 2500;
if(!CPU_CycleUp) CPU_CycleUp = 500; if(!CPU_CycleUp) CPU_CycleUp = 500;
if(!CPU_CycleDown) CPU_CycleDown = 20; if(!CPU_CycleDown) CPU_CycleDown = 20;
CPU_CycleLeft=0; 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -548,7 +548,7 @@
} }
#define MULB(op1,load,save) \ #define MULB(op1,load,save) \
lflags.type=t_MUL; \ FillFlags(); \
reg_ax=reg_al*load(op1); \ reg_ax=reg_al*load(op1); \
if (reg_ax & 0xff00) { \ if (reg_ax & 0xff00) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
@ -558,10 +558,10 @@
#define MULW(op1,load,save) \ #define MULW(op1,load,save) \
{ \ { \
FillFlags(); \
Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \ Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \
reg_ax=(Bit16u)(tempu); \ reg_ax=(Bit16u)(tempu); \
reg_dx=(Bit16u)(tempu >> 16); \ reg_dx=(Bit16u)(tempu >> 16); \
lflags.type=t_MUL; \
if (reg_dx) { \ if (reg_dx) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
} else { \ } else { \
@ -571,10 +571,10 @@
#define MULD(op1,load,save) \ #define MULD(op1,load,save) \
{ \ { \
FillFlags(); \
Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \ Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \
reg_eax=(Bit32u)(tempu); \ reg_eax=(Bit32u)(tempu); \
reg_edx=(Bit32u)(tempu >> 32); \ reg_edx=(Bit32u)(tempu >> 32); \
lflags.type=t_MUL; \
if (reg_edx) { \ if (reg_edx) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
} else { \ } else { \
@ -651,7 +651,7 @@
#define IMULB(op1,load,save) \ #define IMULB(op1,load,save) \
{ \ { \
lflags.type=t_MUL; \ FillFlags(); \
reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \ reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \
if ((reg_ax & 0xff80)==0xff80 || \ if ((reg_ax & 0xff80)==0xff80 || \
(reg_ax & 0xff80)==0x0000) { \ (reg_ax & 0xff80)==0x0000) { \
@ -664,10 +664,10 @@
#define IMULW(op1,load,save) \ #define IMULW(op1,load,save) \
{ \ { \
FillFlags(); \
Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \ Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \
reg_ax=(Bit16s)(temps); \ reg_ax=(Bit16s)(temps); \
reg_dx=(Bit16s)(temps >> 16); \ reg_dx=(Bit16s)(temps >> 16); \
lflags.type=t_MUL; \
if (((temps & 0xffff8000)==0xffff8000 || \ if (((temps & 0xffff8000)==0xffff8000 || \
(temps & 0xffff8000)==0x0000)) { \ (temps & 0xffff8000)==0x0000)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
@ -678,11 +678,11 @@
#define IMULD(op1,load,save) \ #define IMULD(op1,load,save) \
{ \ { \
FillFlags(); \
Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \ Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \
((Bit64s)((Bit32s)(load(op1)))); \ ((Bit64s)((Bit32s)(load(op1)))); \
reg_eax=(Bit32u)(temps); \ reg_eax=(Bit32u)(temps); \
reg_edx=(Bit32u)(temps >> 32); \ reg_edx=(Bit32u)(temps >> 32); \
lflags.type=t_MUL; \
if ((reg_edx==0xffffffff) && \ if ((reg_edx==0xffffffff) && \
(reg_eax & 0x80000000) ) { \ (reg_eax & 0x80000000) ) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
@ -696,10 +696,10 @@
#define DIMULW(op1,op2,op3,load,save) \ #define DIMULW(op1,op2,op3,load,save) \
{ \ { \
FillFlags(); \
Bits res; \ Bits res; \
res=((Bit16s)op2) * ((Bit16s)op3); \ res=((Bit16s)op2) * ((Bit16s)op3); \
save(op1,res & 0xffff); \ save(op1,res & 0xffff); \
lflags.type=t_MUL; \
if ((res> -32768) && (res<32767)) { \ if ((res> -32768) && (res<32767)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
} else { \ } else { \
@ -709,9 +709,9 @@
#define DIMULD(op1,op2,op3,load,save) \ #define DIMULD(op1,op2,op3,load,save) \
{ \ { \
FillFlags(); \
Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \ Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \
save(op1,(Bit32s)res); \ save(op1,(Bit32s)res); \
lflags.type=t_MUL; \
if ((res>-((Bit64s)(2147483647)+1)) && \ if ((res>-((Bit64s)(2147483647)+1)) && \
(res<(Bit64s)2147483647)) { \ (res<(Bit64s)2147483647)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -93,7 +93,7 @@ static Bits PageFaultCore(void) {
if (!pf_queue.used) E_Exit("PF Core without PF"); if (!pf_queue.used) E_Exit("PF Core without PF");
PF_Entry * entry=&pf_queue.entries[pf_queue.used-1]; PF_Entry * entry=&pf_queue.entries[pf_queue.used-1];
X86PageEntry pentry; 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) if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip)
return -1; return -1;
return 0; return 0;
@ -102,6 +102,8 @@ static Bits PageFaultCore(void) {
Bitu DEBUG_EnableDebugger(void); Bitu DEBUG_EnableDebugger(void);
#endif #endif
bool first=false;
void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) { void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) {
/* Save the state of the cpu cores */ /* Save the state of the cpu cores */
LazyFlags old_lflags; LazyFlags old_lflags;
@ -112,6 +114,8 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) {
paging.cr2=lin_addr; paging.cr2=lin_addr;
PF_Entry * entry=&pf_queue.entries[pf_queue.used++]; 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(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->cs=SegValue(cs);
entry->eip=reg_eip; entry->eip=reg_eip;
entry->page_addr=page_addr; 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); LOG(LOG_PAGING,LOG_NORMAL)("Left PageFault for %x queue %d",lin_addr,pf_queue.used);
memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); memcpy(&lflags,&old_lflags,sizeof(LazyFlags));
cpudecoder=old_cpudecoder; cpudecoder=old_cpudecoder;
// LOG_MSG("SS:%04x SP:%08X",SegValue(ss),reg_esp);
} }
void MEM_PhysWriteD(Bitu addr,Bit32u val);
class InitPageHandler : public PageHandler { class InitPageHandler : public PageHandler {
public: public:
InitPageHandler() {flags=PFLAG_INIT|PFLAG_NOCODE;} InitPageHandler() {flags=PFLAG_INIT|PFLAG_NOCODE;}
@ -164,28 +167,28 @@ public:
Bitu t_index=lin_page & 0x3ff; Bitu t_index=lin_page & 0x3ff;
Bitu table_addr=(paging.base.page<<12)+d_index*4; Bitu table_addr=(paging.base.page<<12)+d_index*4;
X86PageEntry table; X86PageEntry table;
table.load=MEM_PhysReadD(table_addr); table.load=phys_readd(table_addr);
if (!table.block.p) { if (!table.block.p) {
LOG(LOG_PAGING,LOG_ERROR)("NP Table"); LOG(LOG_PAGING,LOG_ERROR)("NP Table");
PAGING_PageFault(lin_addr,table_addr,0); PAGING_PageFault(lin_addr,table_addr,0);
table.load=MEM_PhysReadD(table_addr); table.load=phys_readd(table_addr);
if (!table.block.p) if (!table.block.p)
E_Exit("Pagefault didn't correct table"); E_Exit("Pagefault didn't correct table");
} }
table.block.a=table.block.d=1; //Set access/Dirty table.block.a=table.block.d=1; //Set access/Dirty
MEM_PhysWriteD(table_addr,table.load); phys_writed(table_addr,table.load);
X86PageEntry entry; X86PageEntry entry;
Bitu entry_addr=(table.block.base<<12)+t_index*4; 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) { if (!entry.block.p) {
LOG(LOG_PAGING,LOG_ERROR)("NP Page"); LOG(LOG_PAGING,LOG_ERROR)("NP Page");
PAGING_PageFault(lin_addr,entry_addr,0); PAGING_PageFault(lin_addr,entry_addr,0);
entry.load=MEM_PhysReadD(entry_addr); entry.load=phys_readd(entry_addr);
if (!entry.block.p) if (!entry.block.p)
E_Exit("Pagefault didn't correct page"); E_Exit("Pagefault didn't correct page");
} }
entry.block.a=entry.block.d=1; //Set access/Dirty 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; phys_page=entry.block.base;
} else { } else {
if (lin_page<LINK_START) phys_page=mapfirstmb[lin_page]; 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 d_index=page >> 10;
Bitu t_index=page & 0x3ff; Bitu t_index=page & 0x3ff;
X86PageEntry table; 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; if (!table.block.p) return false;
X86PageEntry entry; 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; if (!entry.block.p) return false;
page=entry.block.base; page=entry.block.base;
} else { } else {
@ -251,16 +254,21 @@ void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) {
void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) { void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) {
PageHandler * handler=MEM_GetPageHandler(phys_page); PageHandler * handler=MEM_GetPageHandler(phys_page);
Bitu lin_base=lin_page << 12; Bitu lin_base=lin_page << 12;
if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE) if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE)
E_Exit("Illegal page"); 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); HostPt host_mem=handler->GetHostPt(phys_page);
paging.tlb.phys_page[lin_page]=phys_page; paging.tlb.phys_page[lin_page]=phys_page;
if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=host_mem-lin_base; if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=host_mem-lin_base;
else paging.tlb.read[lin_page]=0; else paging.tlb.read[lin_page]=0;
if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=host_mem-lin_base; if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=host_mem-lin_base;
else paging.tlb.write[lin_page]=0; 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.links.entries[paging.links.used++]=lin_page;
paging.tlb.handler[lin_page]=handler; paging.tlb.handler[lin_page]=handler;
} }
@ -281,7 +289,7 @@ void PAGING_SetDirBase(Bitu cr3) {
paging.base.page=cr3 >> 12; paging.base.page=cr3 >> 12;
paging.base.addr=cr3 & ~4095; 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) { if (paging.enabled) {
PAGING_ClearTLB(); PAGING_ClearTLB();
} }
@ -292,9 +300,15 @@ void PAGING_Enable(bool enabled) {
if (paging.enabled==enabled) return; if (paging.enabled==enabled) return;
paging.enabled=enabled; paging.enabled=enabled;
if (!enabled) { if (!enabled) {
LOG(LOG_PAGING,LOG_NORMAL)("Disabled"); // LOG(LOG_PAGING,LOG_NORMAL)("Disabled");
} else { } 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_SetDirBase(paging.cr3);
} }
PAGING_ClearTLB(); PAGING_ClearTLB();

View File

@ -9,16 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: debug.cpp,v 1.52 2004/01/27 14:52:28 qbix79 Exp $ */ /* $Id: debug.cpp,v 1.59 2004/08/31 23:11:35 harekiet Exp $ */
#include "programs.h"
#include <string.h> #include <string.h>
#include <list> #include <list>
@ -26,19 +24,21 @@
#include "dosbox.h" #include "dosbox.h"
#if C_DEBUG #if C_DEBUG
#include "debug.h" #include "debug.h"
#include "cross.h" //snprintf
#include "cpu.h" #include "cpu.h"
#include "video.h" #include "video.h"
#include "pic.h" #include "pic.h"
#include "keyboard.h" #include "mapper.h"
#include "cpu.h" #include "cpu.h"
#include "callback.h" #include "callback.h"
#include "inout.h" #include "inout.h"
#include "mixer.h" #include "mixer.h"
#include "debug_inc.h"
#include "timer.h" #include "timer.h"
#include "paging.h" #include "paging.h"
#include "../ints/xms.h" #include "support.h"
#include "shell.h" #include "shell.h"
#include "programs.h"
#include "debug_inc.h"
#ifdef WIN32 #ifdef WIN32
void WIN32_Console(); void WIN32_Console();
@ -53,13 +53,17 @@ int old_cursor_state;
static void DrawCode(void); static void DrawCode(void);
static bool DEBUG_Log_Loop(int count); static bool DEBUG_Log_Loop(int count);
static void DEBUG_RaiseTimerIrq(void); 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); char* AnalyzeInstruction(char* inst, bool saveSelector);
void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num);
Bit32u GetHexValue(char* str, char*& hex); Bit32u GetHexValue(char* str, char*& hex);
void LogGDT(void);
void LogLDT(void);
void LogIDT(void);
void OutputVecTable(char* filename);
class DEBUG; class DEBUG;
@ -67,6 +71,7 @@ DEBUG* pDebugcom = 0;
bool exitLoop = false; bool exitLoop = false;
bool logHeavy = false; bool logHeavy = false;
// Heavy Debugging Vars for logging // Heavy Debugging Vars for logging
#if C_HEAVY_DEBUG #if C_HEAVY_DEBUG
static FILE* cpuLogFile = 0; static FILE* cpuLogFile = 0;
@ -74,6 +79,8 @@ static bool cpuLog = false;
static int cpuLogCounter = 0; static int cpuLogCounter = 0;
#endif #endif
static struct { static struct {
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip; Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
} oldregs; } oldregs;
@ -86,6 +93,8 @@ DBGBlock dbg;
static Bitu input_count; static Bitu input_count;
Bitu cycle_count; Bitu cycle_count;
static bool debugging; static bool debugging;
static void SetColor(Bitu test) { static void SetColor(Bitu test) {
if (test) { if (test) {
if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));} if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));}
@ -535,35 +544,26 @@ void CBreakpoint::ShowList(void)
bool DEBUG_Breakpoint(void) bool DEBUG_Breakpoint(void)
{ {
/* First get the phyiscal address and check for a set Breakpoint */ /* 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);
PhysPt where=GetAddress(SegValue(cs),reg_eip-1); if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) return false;
if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip-1)) return false;
// Found. Breakpoint is valid // Found. Breakpoint is valid
reg_eip -= 1;
CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints
// exitLoop = true;
// DEBUG_Enable();
return true; return true;
}; };
bool DEBUG_IntBreakpoint(Bit8u intNum) bool DEBUG_IntBreakpoint(Bit8u intNum)
{ {
/* First get the phyiscal address and check for a set Breakpoint */ /* 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);
PhysPt where=GetAddress(SegValue(cs),reg_eip-2);
if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false; if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false;
// Found. Breakpoint is valid // Found. Breakpoint is valid
reg_eip -= 2;
CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints
// exitLoop = true;
// DEBUG_Enable();
return true; return true;
}; };
static bool StepOver() static bool StepOver()
{ {
exitLoop = false; exitLoop = false;
// PhysPt start=SegPhys(cs)+reg_eip;
PhysPt start=GetAddress(SegValue(cs),reg_eip); PhysPt start=GetAddress(SegValue(cs),reg_eip);
char dline[200];Bitu size; char dline[200];Bitu size;
size=DasmI386(dline, start, reg_eip, cpu.code.big); size=DasmI386(dline, start, reg_eip, cpu.code.big);
@ -581,6 +581,10 @@ static bool StepOver()
bool DEBUG_ExitLoop(void) bool DEBUG_ExitLoop(void)
{ {
#if C_HEAVY_DEBUG
DrawVariables();
#endif
if (exitLoop) { if (exitLoop) {
exitLoop = false; exitLoop = false;
return true; return true;
@ -911,6 +915,30 @@ bool ParseCommand(char* str)
else DEBUG_ShowMsg("DEBUG: Variable list load (%s) : failure",name); else DEBUG_ShowMsg("DEBUG: Variable list load (%s) : failure",name);
return true; 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 "); found = strstr(str,"BP ");
if (found) { // Add new breakpoint if (found) { // Add new breakpoint
@ -1025,30 +1053,6 @@ bool ParseCommand(char* str)
return true; return true;
} }
#endif #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 "); found = strstr(str,"INTT ");
if (found) { // Create Cpu log file if (found) { // Create Cpu log file
found+=4; found+=4;
@ -1433,6 +1437,7 @@ Bitu DEBUG_Loop(void) {
Bit16u oldCS = SegValue(cs); Bit16u oldCS = SegValue(cs);
Bit32u oldEIP = reg_eip; Bit32u oldEIP = reg_eip;
PIC_runIRQs(); PIC_runIRQs();
SDL_Delay(1);
if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) { if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) {
CBreakpoint::AddBreakpoint(oldCS,oldEIP,true); CBreakpoint::AddBreakpoint(oldCS,oldEIP,true);
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
@ -1455,13 +1460,14 @@ void DEBUG_DrawScreen(void) {
DrawData(); DrawData();
DrawCode(); DrawCode();
DrawRegisters(); DrawRegisters();
DrawVariables();
} }
static void DEBUG_RaiseTimerIrq(void) { static void DEBUG_RaiseTimerIrq(void) {
PIC_ActivateIRQ(0); PIC_ActivateIRQ(0);
} }
void LogGDT(void) static void LogGDT(void)
{ {
char out1[512]; char out1[512];
Descriptor desc; Descriptor desc;
@ -1480,7 +1486,7 @@ void LogGDT(void)
}; };
}; };
void LogLDT(void) static void LogLDT(void)
{ {
char out1[512]; char out1[512];
Descriptor desc; Descriptor desc;
@ -1501,7 +1507,7 @@ void LogLDT(void)
}; };
}; };
void LogIDT(void) static void LogIDT(void)
{ {
char out1[512]; char out1[512];
Descriptor desc; Descriptor desc;
@ -1681,8 +1687,7 @@ void DEBUG_Init(Section* sec) {
MSG_Add("DEBUG_CONFIGFILE_HELP","Nothing to setup yet!\n"); MSG_Add("DEBUG_CONFIGFILE_HELP","Nothing to setup yet!\n");
DEBUG_DrawScreen(); DEBUG_DrawScreen();
/* Add some keyhandlers */ /* Add some keyhandlers */
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable); MAPPER_AddHandler(DEBUG_Enable,MK_pause,0,"debugger","Debugger");
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
/* Clear the TBreakpoint list */ /* Clear the TBreakpoint list */
memset((void*)&codeViewData,0,sizeof(codeViewData)); memset((void*)&codeViewData,0,sizeof(codeViewData));
/* setup debug.com */ /* setup debug.com */
@ -1769,7 +1774,7 @@ bool CDebugVar::LoadVars(char* name)
return true; 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"); FILE* f = fopen("MEMDUMP.TXT","wt");
if (!f) { if (!f) {
@ -1796,7 +1801,7 @@ void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num)
DEBUG_ShowMsg("DEBUG: Memory dump success."); DEBUG_ShowMsg("DEBUG: Memory dump success.");
}; };
void OutputVecTable(char* filename) static void OutputVecTable(char* filename)
{ {
FILE* f = fopen(filename, "wt"); FILE* f = fopen(filename, "wt");
if (!f) if (!f)
@ -1812,6 +1817,35 @@ void OutputVecTable(char* filename)
DEBUG_ShowMsg("DEBUG: Interrupt vector table written to %s.", 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 // HEAVY DEBUGGING STUFF
#if C_HEAVY_DEBUG #if C_HEAVY_DEBUG
@ -1892,9 +1926,9 @@ bool DEBUG_HeavyIsBreakpoint(void)
} }
return false; return false;
}; };
#endif // HEAVY DEBUG #endif // HEAVY DEBUG
#endif // DEBUG #endif // DEBUG

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -53,7 +53,7 @@ void DEBUG_ShowMsg(char * format,...) {
va_end(msg); va_end(msg);
wprintw(dbg.win_out,"%10d: %s\n",cycle_count,buf); wprintw(dbg.win_out,"%10d: %s\n",cycle_count,buf);
wrefresh(dbg.win_out); 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, ...){ void LOG::operator() (char* format, ...){
@ -99,13 +99,15 @@ static void DrawBars(void) {
attrset(COLOR_PAIR(PAIR_BLACK_BLUE)); attrset(COLOR_PAIR(PAIR_BLACK_BLUE));
} }
/* Show the Register bar */ /* 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 */ /* 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 */ /* 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 */ /* 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); attrset(0);
} }
@ -124,7 +126,10 @@ static void MakeSubWindows(void) {
/* The Code Window */ /* The Code Window */
dbg.win_code=subwin(dbg.win_main,11,dbg.win_main->_maxx,outy,0); dbg.win_code=subwin(dbg.win_main,11,dbg.win_main->_maxx,outy,0);
outy+=12; 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.win_out=subwin(dbg.win_main,dbg.win_main->_maxy-outy-1,dbg.win_main->_maxx,outy,0);
dbg.input_y=dbg.win_main->_maxy-1; dbg.input_y=dbg.win_main->_maxy-1;
scrollok(dbg.win_out,TRUE); scrollok(dbg.win_out,TRUE);

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -17,6 +17,9 @@
*/ */
/* Local Debug Function */ /* Local Debug Function */
/* $Id: debug_inc.h,v 1.8 2004/08/28 12:51:35 qbix79 Exp $ */
#include <curses.h> #include <curses.h>
#include "mem.h" #include "mem.h"
@ -34,6 +37,7 @@ struct DBGBlock {
WINDOW * win_reg; /* Register Window */ WINDOW * win_reg; /* Register Window */
WINDOW * win_data; /* Data Output window */ WINDOW * win_data; /* Data Output window */
WINDOW * win_code; /* Disassembly/Debug point Window */ WINDOW * win_code; /* Disassembly/Debug point Window */
WINDOW * win_var; /* Variable Window */
WINDOW * win_out; /* Text Output Window */ WINDOW * win_out; /* Text Output Window */
Bit32u active_win; /* Current active window */ Bit32u active_win; /* Current active window */
Bit32u input_y; Bit32u input_y;

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,7 +9,7 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -4,6 +4,6 @@ noinst_LIBRARIES = libdos.a
EXTRA_DIST = scsidefs.h wnaspi32.h 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 \ 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 \ 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 \ drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
dev_con.h dos_mscdex.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.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 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 \ 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 \ 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 \ drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
dev_con.h dos_mscdex.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.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp
subdir = src/dos subdir = src/dos
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 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_memory.$(OBJEXT) dos_misc.$(OBJEXT) dos_classes.$(OBJEXT) \
dos_programs.$(OBJEXT) dos_tables.$(OBJEXT) drives.$(OBJEXT) \ dos_programs.$(OBJEXT) dos_tables.$(OBJEXT) drives.$(OBJEXT) \
drive_virtual.$(OBJEXT) drive_local.$(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_win32.$(OBJEXT) cdrom_aspi_win32.$(OBJEXT) \
cdrom_ioctl_linux.$(OBJEXT) cdrom_ioctl_linux.$(OBJEXT) cdrom_image.$(OBJEXT)
libdos_a_OBJECTS = $(am_libdos_a_OBJECTS) libdos_a_OBJECTS = $(am_libdos_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@ -163,6 +164,7 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/cdrom.Po \ @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/cdrom.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_aspi_win32.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_linux.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_win32.Po ./$(DEPDIR)/dos.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_win32.Po ./$(DEPDIR)/dos.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/dos_classes.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_misc.Po ./$(DEPDIR)/dos_mscdex.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/dos_programs.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_programs.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/dos_tables.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_tables.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po ./$(DEPDIR)/drive_fat.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/drive_local.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/drive_iso.Po ./$(DEPDIR)/drive_local.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/drive_virtual.Po ./$(DEPDIR)/drives.Po @AMDEP_TRUE@ ./$(DEPDIR)/drive_virtual.Po ./$(DEPDIR)/drives.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@ -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.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_aspi_win32.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_linux.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_win32.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@ @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_programs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_tables.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_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_local.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_virtual.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@ @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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -21,6 +21,11 @@
// SDL CDROM // SDL CDROM
// ****************************************************** // ******************************************************
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include "dosbox.h"
#include "SDL.h" #include "SDL.h"
#include "support.h" #include "support.h"
#include "cdrom.h" #include "cdrom.h"
@ -175,8 +180,13 @@ int CDROM_GetMountType(char* path, int forceCD)
cdName = SDL_CDName(i); cdName = SDL_CDName(i);
if (strcmp(buffer,cdName)==0) return 0; 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 #define MAX_ASPI_CDROM 5
#include <string.h> #include <string.h>
#include <iostream>
#include <vector>
#include "dosbox.h" #include "dosbox.h"
#include "mem.h" #include "mem.h"
#include "mixer.h"
#include "SDL.h" #include "SDL.h"
#include "SDL_thread.h"
#if defined(C_SDL_SOUND)
#include "SDL_sound.h"
#endif
#define RAW_SECTOR_SIZE 2352 #define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048 #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 ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0;
virtual bool LoadUnloadMedia (bool unload) = 0; virtual bool LoadUnloadMedia (bool unload) = 0;
virtual void InitNewMedia (void) {};
}; };
class CDROM_Interface_SDL : public CDROM_Interface class CDROM_Interface_SDL : public CDROM_Interface
{ {
public: public:
CDROM_Interface_SDL (void); CDROM_Interface_SDL (void);
~CDROM_Interface_SDL (void); virtual ~CDROM_Interface_SDL(void);
bool SetDevice (char* path, int forceCD); virtual bool SetDevice (char* path, int forceCD);
bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; }; virtual bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); virtual bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); virtual bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
bool GetAudioStatus (bool& playing, bool& pause); virtual bool GetAudioStatus (bool& playing, bool& pause);
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
bool PlayAudioSector (unsigned long start,unsigned long len); virtual bool PlayAudioSector (unsigned long start,unsigned long len);
bool PauseAudio (bool resume); virtual bool PauseAudio (bool resume);
bool StopAudio (void); virtual bool StopAudio (void);
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; }; virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; };
bool LoadUnloadMedia (bool unload); virtual bool LoadUnloadMedia (bool unload);
private: private:
bool Open (void); bool Open (void);
@ -93,6 +102,106 @@ public:
bool LoadUnloadMedia (bool unload) { return true; }; 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 */ #if defined (WIN32) /* Win 32 */
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
@ -104,7 +213,7 @@ class CDROM_Interface_Aspi : public CDROM_Interface
{ {
public: public:
CDROM_Interface_Aspi (void); CDROM_Interface_Aspi (void);
~CDROM_Interface_Aspi (void); virtual ~CDROM_Interface_Aspi(void);
bool SetDevice (char* path, int forceCD); bool SetDevice (char* path, int forceCD);
@ -151,7 +260,7 @@ class CDROM_Interface_Ioctl : public CDROM_Interface
{ {
public: public:
CDROM_Interface_Ioctl (void); CDROM_Interface_Ioctl (void);
~CDROM_Interface_Ioctl (void); virtual ~CDROM_Interface_Ioctl(void);
bool SetDevice (char* path, int forceCD); bool SetDevice (char* path, int forceCD);
@ -171,6 +280,7 @@ public:
bool LoadUnloadMedia (bool unload); bool LoadUnloadMedia (bool unload);
void InitNewMedia (void) { Close(); Open(); };
private: private:
bool Open (void); bool Open (void);

View File

@ -9,14 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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) #if defined (WIN32)
@ -39,6 +39,19 @@
#include "scsidefs.h" #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) // 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) BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID)
{ {
SRB_HAInquiry sh; ASPI_SRB sh;
SRB_GDEVBlock sd; ASPI_SRB sd;
DWORD d = pGetASPI32SupportInfo(); DWORD d = pGetASPI32SupportInfo();
int cnt = LOBYTE(LOWORD(d)); int cnt = LOBYTE(LOWORD(d));
int i,j,k,max; int i,j,k,max;
for(i=0; i<cnt; i++) { for(i=0; i<cnt; i++) {
memset(&sh, 0, sizeof(sh)); memset(&sh, 0, sizeof(sh));
sh.SRB_Cmd = SC_HA_INQUIRY; sh.hainquiry.SRB_Cmd = SC_HA_INQUIRY;
sh.SRB_HaId = i; sh.hainquiry.SRB_HaId = i;
pSendASPI32Command((LPSRB)&sh); 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 // 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 // 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; if ((max!=8) && (max!=16)) max = 8;
for(j=0; j<max; j++) { for(j=0; j<max; j++) {
for(k=0; k<8; k++) { for(k=0; k<8; k++) {
memset(&sd, 0, sizeof(sd)); memset(&sd, 0, sizeof(sd));
sd.SRB_Cmd = SC_GET_DEV_TYPE; sd.gdevblock.SRB_Cmd = SC_GET_DEV_TYPE;
sd.SRB_HaId = i; sd.gdevblock.SRB_HaId = i;
sd.SRB_Target = j; sd.gdevblock.SRB_Target = j;
sd.SRB_Lun = k; sd.gdevblock.SRB_Lun = k;
pSendASPI32Command((LPSRB)&sd); pSendASPI32Command((LPSRB)&sd);
if (sd.SRB_Status == SS_COMP) { if (sd.gdevblock.SRB_Status == SS_COMP) {
if (sd.SRB_DeviceType == DTYPE_CDROM) { if (sd.gdevblock.SRB_DeviceType == DTYPE_CDROM) {
if ((target==j) && (lun==k)) { if ((target==j) && (lun==k)) {
LOG(LOG_MISC,LOG_NORMAL)("SCSI: Getting Hardware vendor."); LOG(LOG_MISC,LOG_NORMAL)("SCSI: Getting Hardware vendor.");
// "Hardware ID = vendor" match ? // "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) 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 ) ); memset ( &srbExec, 0, sizeof ( SRB_ExecSCSICmd ) );
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
srbExec.SRB_Cmd = SC_EXEC_SCSI_CMD ; srbExec.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD ;
srbExec.SRB_HaId = HA_num; srbExec.execscsicmd.SRB_HaId = HA_num;
srbExec.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; srbExec.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
srbExec.SRB_Target = SCSI_Id; srbExec.execscsicmd.SRB_Target = SCSI_Id;
srbExec.SRB_Lun = SCSI_Lun; srbExec.execscsicmd.SRB_Lun = SCSI_Lun;
srbExec.SRB_BufLen = 36; srbExec.execscsicmd.SRB_BufLen = 36;
srbExec.SRB_BufPointer = (unsigned char*)szBuffer; srbExec.execscsicmd.SRB_BufPointer = (unsigned char*)szBuffer;
srbExec.SRB_SenseLen = SENSE_LEN; srbExec.execscsicmd.SRB_SenseLen = SENSE_LEN;
srbExec.SRB_CDBLen = 6; srbExec.execscsicmd.SRB_CDBLen = 6;
srbExec.SRB_PostProc = (LPVOID)hEvent; srbExec.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
srbExec.CDBByte [ 0 ] = SCSI_INQUIRY; srbExec.execscsicmd.CDBByte [ 0 ] = SCSI_INQUIRY;
srbExec.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ] srbExec.execscsicmd.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ]
ResetEvent(hEvent); ResetEvent(hEvent);
int dwStatus = pSendASPI32Command ((LPSRB)&srbExec); 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."); // LOG(LOG_MISC|LOG_ERROR,"SCSI: Pending done.");
CloseHandle(hEvent); CloseHandle(hEvent);
if (srbExec.SRB_Status != SS_COMP) { if (srbExec.execscsicmd.SRB_Status != SS_COMP) {
strcpy (szBuffer, "error" ); strcpy (szBuffer, "error" );
return false; return false;
} else { } 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) 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); hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s)); memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId; s.execscsicmd.SRB_HaId = haId;
s.SRB_Target = target; s.execscsicmd.SRB_Target = target;
s.SRB_Lun = lun; s.execscsicmd.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = sizeof(*toc); s.execscsicmd.SRB_BufLen = sizeof(*toc);
s.SRB_BufPointer = (BYTE FAR *)toc; s.execscsicmd.SRB_BufPointer = (BYTE FAR *)toc;
s.SRB_SenseLen = SENSE_LEN; s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 0x0A; s.execscsicmd.SRB_CDBLen = 0x0A;
s.SRB_PostProc = (LPVOID)hEvent; s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_READ_TOC; s.execscsicmd.CDBByte[0] = SCSI_READ_TOC;
s.CDBByte[1] = 0x02; // 0x02 for MSF s.execscsicmd.CDBByte[1] = 0x02; // 0x02 for MSF
s.CDBByte[7] = 0x03; s.execscsicmd.CDBByte[7] = 0x03;
s.CDBByte[8] = 0x24; s.execscsicmd.CDBByte[8] = 0x24;
ResetEvent(hEvent); ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s); dwStatus=pSendASPI32Command((LPSRB)&s);
@ -401,37 +417,39 @@ DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
CloseHandle(hEvent); 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) 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); hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s)); memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId; s.execscsicmd.SRB_HaId = haId;
s.SRB_Target = target; s.execscsicmd.SRB_Target = target;
s.SRB_Lun = lun; s.execscsicmd.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0; s.execscsicmd.SRB_BufLen = 0;
s.SRB_BufPointer = 0; s.execscsicmd.SRB_BufPointer = 0;
s.SRB_SenseLen = SENSE_LEN; s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 12; s.execscsicmd.SRB_CDBLen = 12;
s.SRB_PostProc = (LPVOID)hEvent; s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_PLAYAUD_12; s.execscsicmd.CDBByte[0] = SCSI_PLAYAUD_12;
s.CDBByte[1] = lun << 5; s.execscsicmd.CDBByte[1] = lun << 5;
s.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF); s.execscsicmd.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF);
s.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF); s.execscsicmd.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF);
s.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF); s.execscsicmd.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF);
s.CDBByte[5] = (unsigned char)((start & 0xFF)); s.execscsicmd.CDBByte[5] = (unsigned char)((start & 0xFF));
s.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF); s.execscsicmd.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF);
s.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF); s.execscsicmd.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF);
s.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF); s.execscsicmd.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF);
s.CDBByte[9] = (unsigned char)(len & 0xFF); s.execscsicmd.CDBByte[9] = (unsigned char)(len & 0xFF);
ResetEvent(hEvent); ResetEvent(hEvent);
@ -441,7 +459,7 @@ bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len
CloseHandle(hEvent); CloseHandle(hEvent);
return s.SRB_Status==SS_COMP; return s.execscsicmd.SRB_Status==SS_COMP;
} }
bool CDROM_Interface_Aspi::StopAudio(void) bool CDROM_Interface_Aspi::StopAudio(void)
@ -451,23 +469,25 @@ bool CDROM_Interface_Aspi::StopAudio(void)
bool CDROM_Interface_Aspi::PauseAudio(bool resume) 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); hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s)); memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId; s.execscsicmd.SRB_HaId = haId;
s.SRB_Target = target; s.execscsicmd.SRB_Target = target;
s.SRB_Lun = lun; s.execscsicmd.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_BufLen = 0x00; s.execscsicmd.SRB_BufLen = 0x00;
s.SRB_SenseLen = SENSE_LEN; s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_CDBLen = 0x0A; s.execscsicmd.SRB_CDBLen = 0x0A;
s.SRB_PostProc = (LPVOID)hEvent; s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0x4B; s.execscsicmd.CDBByte[0] = 0x4B;
s.CDBByte[8] = (unsigned char)resume; // Pause s.execscsicmd.CDBByte[8] = (unsigned char)resume; // Pause
ResetEvent(hEvent); ResetEvent(hEvent);
dwStatus=pSendASPI32Command((LPSRB)&s); dwStatus=pSendASPI32Command((LPSRB)&s);
@ -476,37 +496,39 @@ bool CDROM_Interface_Aspi::PauseAudio(bool resume)
CloseHandle(hEvent); 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) bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
{ {
SUB_Q_CURRENT_POSITION pos; SUB_Q_CURRENT_POSITION pos;
SRB_ExecSCSICmd s;DWORD dwStatus; // SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s)); memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId; s.execscsicmd.SRB_HaId = haId;
s.SRB_Target = target; s.execscsicmd.SRB_Target = target;
s.SRB_Lun = lun; s.execscsicmd.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN; s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = sizeof(pos); s.execscsicmd.SRB_BufLen = sizeof(pos);
s.SRB_BufPointer = (BYTE FAR *)&pos; s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&pos;
s.SRB_CDBLen = 10; s.execscsicmd.SRB_CDBLen = 10;
s.SRB_PostProc = (LPVOID)hEvent; s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_SUBCHANNEL; s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
s.CDBByte[1] = (lun<<5)|2; // lun & msf s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
s.CDBByte[2] = 0x40; // subq s.execscsicmd.CDBByte[2] = 0x40; // subq
s.CDBByte[3] = 0x01; // curr pos info s.execscsicmd.CDBByte[3] = 0x01; // curr pos info
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.CDBByte[7] = 0; // alloc len s.execscsicmd.CDBByte[7] = 0; // alloc len
s.CDBByte[8] = sizeof(pos); s.execscsicmd.CDBByte[8] = sizeof(pos);
ResetEvent(hEvent); ResetEvent(hEvent);
@ -516,7 +538,7 @@ bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track
CloseHandle(hEvent); CloseHandle(hEvent);
if (s.SRB_Status!=SS_COMP) return false; if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
attr = (pos.Control<<4) &0xEF; attr = (pos.Control<<4) &0xEF;
track = pos.TrackNumber; 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) bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
{ {
SUB_Q_MEDIA_CATALOG_NUMBER upc; 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); hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s)); memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId; s.execscsicmd.SRB_HaId = haId;
s.SRB_Target = target; s.execscsicmd.SRB_Target = target;
s.SRB_Lun = lun; s.execscsicmd.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN; s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = sizeof(upc); s.execscsicmd.SRB_BufLen = sizeof(upc);
s.SRB_BufPointer = (BYTE FAR *)&upc; s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&upc;
s.SRB_CDBLen = 10; s.execscsicmd.SRB_CDBLen = 10;
s.SRB_PostProc = (LPVOID)hEvent; s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_SUBCHANNEL; s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
s.CDBByte[1] = (lun<<5)|2; // lun & msf s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
s.CDBByte[2] = 0x40; // subq s.execscsicmd.CDBByte[2] = 0x40; // subq
s.CDBByte[3] = 0x02; // get upc s.execscsicmd.CDBByte[3] = 0x02; // get upc
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.CDBByte[7] = 0; // alloc len s.execscsicmd.CDBByte[7] = 0; // alloc len
s.CDBByte[8] = sizeof(upc); s.execscsicmd.CDBByte[8] = sizeof(upc);
ResetEvent(hEvent); ResetEvent(hEvent);
@ -568,15 +592,14 @@ bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
CloseHandle(hEvent); 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 = (upc.ADR<<4) | upc.Control;
attr = 0; attr = 0;
int pos = 0; int pos = 0;
// Convert to mscdex format // 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];
for (int i=0; i<7; i++) upcdata[i] = (upc.MediaCatalog[i*2] << 4) | (upc.MediaCatalog[i*2+1] & 0x0F);
return true; return true;
}; };
@ -586,31 +609,33 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
playing = pause = false; playing = pause = false;
SUB_Q_HEADER sub; SUB_Q_HEADER sub;
SRB_ExecSCSICmd s;DWORD dwStatus; // SRB_ExecSCSICmd s;
ASPI_SRB s;
DWORD dwStatus;
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s)); memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId; s.execscsicmd.SRB_HaId = haId;
s.SRB_Target = target; s.execscsicmd.SRB_Target = target;
s.SRB_Lun = lun; s.execscsicmd.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN; s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = sizeof(sub); s.execscsicmd.SRB_BufLen = sizeof(sub);
s.SRB_BufPointer = (BYTE FAR *)&sub; s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&sub;
s.SRB_CDBLen = 10; s.execscsicmd.SRB_CDBLen = 10;
s.SRB_PostProc = (LPVOID)hEvent; s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_SUBCHANNEL; s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
s.CDBByte[1] = (lun<<5)|2; // lun & msf s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
s.CDBByte[2] = 0x00; // no subq s.execscsicmd.CDBByte[2] = 0x00; // no subq
s.CDBByte[3] = 0x00; // dont care s.execscsicmd.CDBByte[3] = 0x00; // dont care
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
s.CDBByte[7] = 0; // alloc len s.execscsicmd.CDBByte[7] = 0; // alloc len
s.CDBByte[8] = sizeof(sub); s.execscsicmd.CDBByte[8] = sizeof(sub);
ResetEvent(hEvent); ResetEvent(hEvent);
@ -620,7 +645,7 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
CloseHandle(hEvent); CloseHandle(hEvent);
if (s.SRB_Status!=SS_COMP) return false; if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
playing = (sub.AudioStatus==0x11); playing = (sub.AudioStatus==0x11);
pause = (sub.AudioStatus==0x12); pause = (sub.AudioStatus==0x12);
@ -630,27 +655,29 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload) 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); hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
memset(&s,0,sizeof(s)); memset(&s,0,sizeof(s));
s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId; s.execscsicmd.SRB_HaId = haId;
s.SRB_Target = target; s.execscsicmd.SRB_Target = target;
s.SRB_Lun = lun; s.execscsicmd.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN; s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = 0; s.execscsicmd.SRB_BufLen = 0;
s.SRB_BufPointer = 0; s.execscsicmd.SRB_BufPointer = 0;
s.SRB_CDBLen = 14; s.execscsicmd.SRB_CDBLen = 6; // 14;
s.SRB_PostProc = (LPVOID)hEvent; s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = SCSI_LOAD_UN; s.execscsicmd.CDBByte[0] = SCSI_LOAD_UN;
s.CDBByte[1] = (lun<<5)|1; // lun & immediate s.execscsicmd.CDBByte[1] = (lun<<5)|1; // lun & immediate
s.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media s.execscsicmd.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media
ResetEvent(hEvent); ResetEvent(hEvent);
@ -660,7 +687,7 @@ bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
CloseHandle(hEvent); CloseHandle(hEvent);
if (s.SRB_Status!=SS_COMP) return false; if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
return true; 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) 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); 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; Bitu buflen = raw?2352*num:2048*num;
Bit8u* bufdata = new Bit8u[buflen]; Bit8u* bufdata = new Bit8u[buflen];
s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
s.SRB_HaId = haId; s.execscsicmd.SRB_HaId = haId;
s.SRB_Target = target; s.execscsicmd.SRB_Target = target;
s.SRB_Lun = lun; s.execscsicmd.SRB_Lun = lun;
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
s.SRB_SenseLen = SENSE_LEN; s.execscsicmd.SRB_SenseLen = SENSE_LEN;
s.SRB_BufLen = buflen; s.execscsicmd.SRB_BufLen = buflen;
s.SRB_BufPointer = (BYTE FAR*)bufdata; s.execscsicmd.SRB_BufPointer = (BYTE FAR*)bufdata;
s.SRB_CDBLen = 12; s.execscsicmd.SRB_CDBLen = 12;
s.SRB_PostProc = (LPVOID)hEvent; s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
s.CDBByte[0] = 0xBE; s.execscsicmd.CDBByte[0] = 0xBE;
s.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF); s.execscsicmd.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF);
s.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF); s.execscsicmd.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF);
s.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF); s.execscsicmd.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF);
s.CDBByte[5] = (unsigned char)((sector & 0xFF)); s.execscsicmd.CDBByte[5] = (unsigned char)((sector & 0xFF));
s.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF); s.execscsicmd.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF);
s.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF); s.execscsicmd.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF);
s.CDBByte[8] = (unsigned char) (num & 0xFF); s.execscsicmd.CDBByte[8] = (unsigned char) (num & 0xFF);
s.CDBByte[9] = (raw?0xF0:0x10); s.execscsicmd.CDBByte[9] = (raw?0xF0:0x10);
ResetEvent(hEvent); ResetEvent(hEvent);
@ -728,7 +757,7 @@ bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long se
delete[] bufdata; delete[] bufdata;
return (s.SRB_Status==SS_COMP); return (s.execscsicmd.SRB_Status==SS_COMP);
}; };
#endif #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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software

View File

@ -9,14 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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) #if defined (WIN32)

View File

@ -9,14 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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 "dos_inc.h"
#include "../ints/int10.h" #include "../ints/int10.h"
@ -31,22 +31,22 @@ public:
bool Write(Bit8u * data,Bit16u * size); bool Write(Bit8u * data,Bit16u * size);
bool Seek(Bit32u * pos,Bit32u type); bool Seek(Bit32u * pos,Bit32u type);
bool Close(); bool Close();
void ClearAnsi(void); void ClearAnsi(void);
Bit16u GetInformation(void); Bit16u GetInformation(void);
private: private:
Bit8u cache; Bit8u cache;
struct ansi { /* should create a constructor which fills them with the appriorate values */ struct ansi { /* should create a constructor which fills them with the appriorate values */
bool esc; bool esc;
bool sci; bool sci;
bool enabled; bool enabled;
Bit8u attr; Bit8u attr;
Bit8u data[NUMBER_ANSI_DATA]; Bit8u data[NUMBER_ANSI_DATA];
Bit8u numberofarg; Bit8u numberofarg;
Bit16u nrows; Bit16u nrows;
Bit16u ncols; Bit16u ncols;
Bit8s savecol; Bit8s savecol;
Bit8s saverow; Bit8s saverow;
} ansi; } ansi;
}; };
@ -55,11 +55,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
Bit16u count=0; Bit16u count=0;
if ((cache) && (*size)) { if ((cache) && (*size)) {
data[count++]=cache; data[count++]=cache;
if(dos.echo) { if(dos.echo) INT10_TeletypeOutput(cache,7);
INT10_TeletypeOutput(cache,7); cache=0;
}
cache=0;
} }
while (*size>count) { while (*size>count) {
reg_ah=0; reg_ah=0;
@ -68,25 +65,24 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
case 13: case 13:
data[count++]=0x0D; data[count++]=0x0D;
if (*size>count) data[count++]=0x0A; // it's only expanded if there is room for it. (NO cache) 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; reg_ax=oldax;
if(dos.echo) { if(dos.echo) {
INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible) INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible)
INT10_TeletypeOutput(10,7); INT10_TeletypeOutput(10,7);
} }
return true; return true;
break; break;
case 8: case 8:
if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS 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) else if(count) { //Remove data if it exists (extended keys don't go right)
data[count--]=0; data[count--]=0;
INT10_TeletypeOutput(8,7); INT10_TeletypeOutput(8,7);
INT10_TeletypeOutput(' ',7); INT10_TeletypeOutput(' ',7);
} else { } else {
continue; //no data read yet so restart whileloop. continue; //no data read yet so restart whileloop.
} }
break;
break;
default: default:
data[count++]=reg_al; data[count++]=reg_al;
break; break;
@ -95,11 +91,10 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
if (*size>count) data[count++]=reg_ah; if (*size>count) data[count++]=reg_ah;
else cache=reg_ah; else cache=reg_ah;
break; break;
}
} if(dos.echo) { //what to do if *size==1 and character is BS ?????
if(dos.echo) { //what to do if *size==1 and character is BS ????? INT10_TeletypeOutput(reg_al,7);
INT10_TeletypeOutput(reg_al,7); }
}
} }
*size=count; *size=count;
reg_ax=oldax; reg_ax=oldax;
@ -109,243 +104,235 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
bool device_CON::Write(Bit8u * data,Bit16u * size) { bool device_CON::Write(Bit8u * data,Bit16u * size) {
Bit16u count=0; Bit16u count=0;
Bitu i; Bitu i;
Bit8u col,row; Bit8u col,row;
Bit8u tempdata; Bit8u tempdata;
while (*size>count) { while (*size>count) {
if (!ansi.esc){ if (!ansi.esc){
if(data[count]=='\033') { if(data[count]=='\033') {
/*clear the datastructure */ /*clear the datastructure */
ClearAnsi(); ClearAnsi();
/* start the sequence */ /* start the sequence */
ansi.esc=true; ansi.esc=true;
count++; count++;
continue; continue;
} else {
} else { /* pass attribute only if ansi is enabled */
// pass attribute only if ansi is enabled
INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled); INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled);
count++; count++;
continue; continue;
}; }
}; }
if(!ansi.sci){ if(!ansi.sci){
switch(data[count]){ switch(data[count]){
case '[': case '[':
ansi.sci=true; ansi.sci=true;
break; break;
case '7': /* save cursor pos +attr */ case '7': /* save cursor pos +attr */
case '8': /* restore this (Wonder if this is actually used) */ case '8': /* restore this (Wonder if this is actually used) */
case 'D':/* scrolling DOWN*/ case 'D':/* scrolling DOWN*/
case 'M':/* scrolling UP*/ case 'M':/* scrolling UP*/
default: default:
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */ LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */
ClearAnsi(); ClearAnsi();
break; break;
} }
count++; count++;
continue; continue;
}
} /*ansi.esc and ansi.sci are true */
/*ansi.esc and ansi.sci are true */ switch(data[count]){
switch(data[count]){ case '0':
case '0': case '1':
case '1': case '2':
case '2': case '3':
case '3': case '4':
case '4': case '5':
case '5': case '6':
case '6': case '7':
case '7': case '8':
case '8': case '9':
case '9': ansi.data[ansi.numberofarg]=10*ansi.data[ansi.numberofarg]+(data[count]-'0');
ansi.data[ansi.numberofarg]=10*ansi.data[ansi.numberofarg]+(data[count]-'0'); break;
break; case ';': /* till a max of NUMBER_ANSI_DATA */
case ';': /* till a max of NUMBER_ANSI_DATA */ ansi.numberofarg++;
ansi.numberofarg++; break;
break; case 'm': /* SGR */
case 'm': /* SGR */ for(i=0;i<=ansi.numberofarg;i++){
for(i=0;i<=ansi.numberofarg;i++){
ansi.enabled=true; ansi.enabled=true;
switch(ansi.data[i]){ switch(ansi.data[i]){
case 0: /* normal */ case 0: /* normal */
ansi.attr=0x7; ansi.attr=0x07;//Real ansi does this as well. (should do current defaults)
ansi.enabled=false; ansi.enabled=false;
break; break;
case 1: /* bold mode on*/ case 1: /* bold mode on*/
ansi.attr|=0x8; ansi.attr|=0x08;
break; break;
case 4: /* underline */ case 4: /* underline */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet"); LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet");
break; break;
case 5: /* blinking */ case 5: /* blinking */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for blinking yet"); ansi.attr|=0x80;
break; break;
case 7: /* reverse */ case 7: /* reverse */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for reverse yet"); ansi.attr=0x70;//Just like real ansi. (should do use current colors reversed)
break; break;
case 30: /* fg color black */ case 30: /* fg color black */
ansi.attr&=0xf8; ansi.attr&=0xf8;
ansi.attr|=0x0; ansi.attr|=0x0;
break; break;
case 31: /* fg color red */ case 31: /* fg color red */
ansi.attr&=0xf8; ansi.attr&=0xf8;
ansi.attr|=0x4; ansi.attr|=0x4;
break; break;
case 32: /* fg color green */ case 32: /* fg color green */
ansi.attr&=0xf8; ansi.attr&=0xf8;
ansi.attr|=0x2; ansi.attr|=0x2;
break; break;
case 33: /* fg color yellow */ case 33: /* fg color yellow */
ansi.attr&=0xf8; ansi.attr&=0xf8;
ansi.attr|=0x6; ansi.attr|=0x6;
break; break;
case 34: /* fg color blue */ case 34: /* fg color blue */
ansi.attr&=0xf8; ansi.attr&=0xf8;
ansi.attr|=0x1; ansi.attr|=0x1;
break; break;
case 35: /* fg color magenta */ case 35: /* fg color magenta */
ansi.attr&=0xf8; ansi.attr&=0xf8;
ansi.attr|=0x5; ansi.attr|=0x5;
break; break;
case 36: /* fg color cyan */ case 36: /* fg color cyan */
ansi.attr&=0xf8; ansi.attr&=0xf8;
ansi.attr|=0x3; ansi.attr|=0x3;
break; break;
case 37: /* fg color white */ case 37: /* fg color white */
ansi.attr&=0xf8; ansi.attr&=0xf8;
ansi.attr|=0x7; ansi.attr|=0x7;
break; break;
case 40: case 40:
ansi.attr&=0x8f; ansi.attr&=0x8f;
ansi.attr|=0x0; ansi.attr|=0x0;
break; break;
case 41: case 41:
ansi.attr&=0x8f; ansi.attr&=0x8f;
ansi.attr|=0x40; ansi.attr|=0x40;
break; break;
case 42: case 42:
ansi.attr&=0x8f; ansi.attr&=0x8f;
ansi.attr|=0x20; ansi.attr|=0x20;
break; break;
case 43: case 43:
ansi.attr&=0x8f; ansi.attr&=0x8f;
ansi.attr|=0x60; ansi.attr|=0x60;
break; break;
case 44: case 44:
ansi.attr&=0x8f; ansi.attr&=0x8f;
ansi.attr|=0x10; ansi.attr|=0x10;
break; break;
case 45: case 45:
ansi.attr&=0x8f; ansi.attr&=0x8f;
ansi.attr|=0x50; ansi.attr|=0x50;
break; break;
case 46: case 46:
ansi.attr&=0x8f; ansi.attr&=0x8f;
ansi.attr|=0x30; ansi.attr|=0x30;
break; break;
case 47: case 47:
ansi.attr&=0x8f; ansi.attr&=0x8f;
ansi.attr|=0x70; ansi.attr|=0x70;
break; break;
default: default:
break; 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 */ /* cursor up down and forward and backward only change the row or the col not both */
case 'A': /* cursor up*/ case 'A': /* cursor up*/
col=CURSOR_POS_COL(0) ; col=CURSOR_POS_COL(0) ;
row=CURSOR_POS_ROW(0) ; row=CURSOR_POS_ROW(0) ;
tempdata = (ansi.data[0]? ansi.data[0] : 1); tempdata = (ansi.data[0]? ansi.data[0] : 1);
if(tempdata > row) if(tempdata > row) { row=0; }
{ row=0; } else { row-=tempdata;}
else
{ row-=tempdata;}
INT10_SetCursorPos(row,col,0); INT10_SetCursorPos(row,col,0);
ClearAnsi(); ClearAnsi();
break; break;
case 'B': /*cursor Down */ case 'B': /*cursor Down */
col=CURSOR_POS_COL(0) ; col=CURSOR_POS_COL(0) ;
row=CURSOR_POS_ROW(0) ; row=CURSOR_POS_ROW(0) ;
tempdata = (ansi.data[0]? ansi.data[0] : 1); tempdata = (ansi.data[0]? ansi.data[0] : 1);
if(tempdata + static_cast<Bitu>(row) >= ansi.nrows) if(tempdata + static_cast<Bitu>(row) >= ansi.nrows)
{ row = ansi.nrows - 1;} { row = ansi.nrows - 1;}
else else { row += tempdata; }
{ row += tempdata; } INT10_SetCursorPos(row,col,0);
INT10_SetCursorPos(row,col,0); ClearAnsi();
ClearAnsi();
break; break;
case 'C': /*cursor forward */ case 'C': /*cursor forward */
col=CURSOR_POS_COL(0); 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>(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); tempdata=(ansi.data[0]? ansi.data[0] : 1);
if(tempdata > col) if(tempdata + static_cast<Bitu>(col) >= ansi.ncols)
{col = 0;} { col = ansi.ncols - 1;}
else else { col += tempdata;}
{ col -= tempdata;} INT10_SetCursorPos(row,col,0);
INT10_SetCursorPos(row,col,0); ClearAnsi();
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; break;
case 'l':/* (if code =7) disable linewrap */ case 'D': /*Cursor Backward */
case 'p':/* reassign keys (needs strings) */ col=CURSOR_POS_COL(0);
case 'i':/* printer stuff */ row=CURSOR_POS_ROW(0);
default: tempdata=(ansi.data[0]? ansi.data[0] : 1);
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unhandled char %c in esc[",data[count]); if(tempdata > col) {col = 0;}
ClearAnsi(); else { col -= tempdata;}
break; INT10_SetCursorPos(row,col,0);
} ClearAnsi();
count++; 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; *size=count;
return true; return true;
@ -372,22 +359,18 @@ Bit16u device_CON::GetInformation(void) {
device_CON::device_CON() { device_CON::device_CON() {
name="CON"; name="CON";
cache=0; cache=0;
ansi.esc=false;
ansi.sci=false;
ansi.enabled=false; ansi.enabled=false;
ansi.attr=0x7; ansi.attr=0x7;
ansi.numberofarg=0; ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0; ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented ansi.saverow=0;
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1; ansi.savecol=0;
ansi.saverow=0;
ansi.savecol=0;
ClearAnsi(); ClearAnsi();
} }
void device_CON::ClearAnsi(void){ void device_CON::ClearAnsi(void){
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0; for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
ansi.esc=false; ansi.esc=false;
ansi.sci=false; ansi.sci=false;
ansi.numberofarg=0; ansi.numberofarg=0;
} }

View File

@ -9,14 +9,14 @@
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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 <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -45,20 +45,20 @@ void DOS_SetError(Bit16u code) {
#define DOSNAMEBUF 256 #define DOSNAMEBUF 256
static Bitu DOS_21Handler(void) { static Bitu DOS_21Handler(void) {
if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) { if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) {
DOS_PSP psp(dos.psp); DOS_PSP psp(dos.psp());
psp.SetStack(RealMake(SegValue(ss),reg_sp-20)); psp.SetStack(RealMake(SegValue(ss),reg_sp-18));
} }
char name1[DOSNAMEBUF+1]; char name1[DOSNAMEBUF+1];
char name2[DOSNAMEBUF+1]; char name2[DOSNAMEBUF+1];
switch (reg_ah) { switch (reg_ah) {
case 0x01: /* Read character from STDIN, with echo */ case 0x01: /* Read character from STDIN, with echo */
{ {
Bit8u c;Bit16u n=1; Bit8u c;Bit16u n=1;
dos.echo=true; dos.echo=true;
DOS_ReadFile(STDIN,&c,&n); DOS_ReadFile(STDIN,&c,&n);
reg_al=c; reg_al=c;
dos.echo=false; dos.echo=false;
} }
break; break;
case 0x02: /* Write character to STDOUT */ case 0x02: /* Write character to STDOUT */
@ -181,7 +181,7 @@ static Bitu DOS_21Handler(void) {
break; break;
case 0x10: /* Close File using FCB */ case 0x10: /* Close File using FCB */
if(DOS_FCBClose(SegValue(ds),reg_dx)){ if(DOS_FCBClose(SegValue(ds),reg_dx)){
reg_al=0; reg_al=0;
}else{ }else{
reg_al=0xff; reg_al=0xff;
} }
@ -189,7 +189,7 @@ static Bitu DOS_21Handler(void) {
break; break;
case 0x11: /* Find First Matching File using FCB */ case 0x11: /* Find First Matching File using FCB */
if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){ if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){
reg_al=0; reg_al=0;
}else{ }else{
reg_al=0xff; reg_al=0xff;
} }
@ -197,7 +197,7 @@ static Bitu DOS_21Handler(void) {
break; break;
case 0x12: /* Find Next Matching File using FCB */ case 0x12: /* Find Next Matching File using FCB */
if(DOS_FCBFindNext(SegValue(ds),reg_dx)){ if(DOS_FCBFindNext(SegValue(ds),reg_dx)){
reg_al=0; reg_al=0;
}else{ }else{
reg_al=0xff; 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); LOG(LOG_FCB,LOG_NORMAL)("DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al);
break; break;
case 0x29: /* Parse filename into FCB */ case 0x29: /* Parse filename into FCB */
{ Bit8u difference; {
char string[1024]; Bit8u difference;
MEM_StrCopy(SegPhys(ds)+reg_si,string,1024); char string[1024];
reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference); MEM_StrCopy(SegPhys(ds)+reg_si,string,1024);
reg_si+=difference; 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); LOG(LOG_FCB,LOG_NORMAL)("DOS:29:FCB Parse Filename, result:al=%d",reg_al);
break; break;
case 0x19: /* Get current default drive */ case 0x19: /* Get current default drive */
reg_al=DOS_GetDefaultDrive(); reg_al=DOS_GetDefaultDrive();
break; break;
case 0x1a: /* Set Disk Transfer Area Address */ case 0x1a: /* Set Disk Transfer Area Address */
{ dos.dta(RealMakeSeg(ds,reg_dx));
dos.dta=RealMakeSeg(ds,reg_dx);
DOS_PSP psp(dos.psp);
psp.SetDTA(dos.dta);
}
break; break;
case 0x25: /* Set Interrupt Vector */ case 0x25: /* Set Interrupt Vector */
RealSetVec(reg_al,RealMakeSeg(ds,reg_dx)); RealSetVec(reg_al,RealMakeSeg(ds,reg_dx));
break; break;
case 0x26: /* Create new PSP */ case 0x26: /* Create new PSP */
DOS_NewPSP(reg_dx,DOS_PSP(dos.psp).GetSize()); DOS_NewPSP(reg_dx,DOS_PSP(dos.psp()).GetSize());
break; break;
case 0x2a: /* Get System Date */ case 0x2a: /* Get System Date */
{ {
@ -319,29 +316,43 @@ static Bitu DOS_21Handler(void) {
dos.verify=(reg_al==1); dos.verify=(reg_al==1);
break; break;
case 0x2f: /* Get Disk Transfer Area */ case 0x2f: /* Get Disk Transfer Area */
SegSet16(es,RealSeg(dos.dta)); SegSet16(es,RealSeg(dos.dta()));
reg_bx=RealOff(dos.dta); reg_bx=RealOff(dos.dta());
break; break;
case 0x30: /* Get DOS Version */ case 0x30: /* Get DOS Version */
if (reg_al==0) reg_bh=0xFF; /* Fake Microsoft DOS */ if (reg_al==0) reg_bh=0xFF; /* Fake Microsoft DOS */
if (reg_al==1) reg_bh=0x10; /* DOS is in HMA */ if (reg_al==1) reg_bh=0x10; /* DOS is in HMA */
reg_al=dos.version.major; reg_al=dos.version.major;
reg_ah=dos.version.minor; reg_ah=dos.version.minor;
/* Serialnumber */
reg_bl=0x00;
reg_cx=0x0000;
break; break;
case 0x31: /* Terminate and stay resident */ case 0x31: /* Terminate and stay resident */
//TODO First get normal files executing //TODO First get normal files executing
// Important: This service does not set the carry flag! // 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_Terminate(true);
dos.return_code=reg_al; dos.return_code=reg_al; //Officially a field in the SDA
dos.return_mode=RETURN_TSR; dos.return_mode=RETURN_TSR;
break; 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 */ case 0x33: /* Extended Break Checking */
switch (reg_al) { switch (reg_al) {
case 0:reg_dl=dos.breakcheck;break; /* Get the breakcheck flag */ case 0:reg_dl=dos.breakcheck;break; /* Get the breakcheck flag */
case 1:dos.breakcheck=(reg_dl>0);break; /* Set 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 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 */ case 6: /* Get true version number */
reg_bl=dos.version.major; reg_bl=dos.version.major;
reg_bh=dos.version.minor; reg_bh=dos.version.minor;
@ -353,8 +364,8 @@ static Bitu DOS_21Handler(void) {
} }
break; break;
case 0x34: /* Get INDos Flag */ case 0x34: /* Get INDos Flag */
SegSet16(es,RealSeg(dos.tables.indosflag)); SegSet16(es,DOS_SDA_SEG);
reg_bx=RealOff(dos.tables.indosflag); reg_bx=DOS_SDA_OFS + 0x01;
break; break;
case 0x35: /* Get interrupt vector */ case 0x35: /* Get interrupt vector */
reg_bx=real_readw(0,((Bit16u)reg_al)*4); reg_bx=real_readw(0,((Bit16u)reg_al)*4);
@ -363,8 +374,8 @@ static Bitu DOS_21Handler(void) {
case 0x36: /* Get Free Disk Space */ case 0x36: /* Get Free Disk Space */
{ {
Bit16u bytes,clusters,free; Bit16u bytes,clusters,free;
Bit8u sectors; Bit8u sectors;
if (DOS_GetFreeDiskSpace(reg_dl,&bytes,&sectors,&clusters,&free)) { if(DOS_GetFreeDiskSpace(reg_dl,&bytes,&sectors,&clusters,&free)) {
reg_ax=sectors; reg_ax=sectors;
reg_bx=free; reg_bx=free;
reg_cx=bytes; reg_cx=bytes;
@ -466,7 +477,7 @@ static Bitu DOS_21Handler(void) {
case 0x3f: /* READ Read from file or device */ case 0x3f: /* READ Read from file or device */
{ {
Bit16u toread=reg_cx; Bit16u toread=reg_cx;
dos.echo=true; dos.echo=true;
if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) {
MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread); MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread);
reg_ax=toread; reg_ax=toread;
@ -475,7 +486,7 @@ static Bitu DOS_21Handler(void) {
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
CALLBACK_SCF(true); CALLBACK_SCF(true);
} }
dos.echo=false; dos.echo=false;
break; break;
} }
case 0x40: /* WRITE Write to file or device */ case 0x40: /* WRITE Write to file or device */
@ -621,7 +632,7 @@ static Bitu DOS_21Handler(void) {
break; break;
//TODO Check for use of execution state AL=5 //TODO Check for use of execution state AL=5
case 0x00: case 0x00:
reg_ax=0x4c00; /* Terminate Program */ reg_ax=0x4c00; /* Terminate Program */
case 0x4c: /* EXIT Terminate with return code */ case 0x4c: /* EXIT Terminate with return code */
{ {
@ -634,7 +645,7 @@ static Bitu DOS_21Handler(void) {
break; break;
} }
case 0x4d: /* Get Return code */ 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; reg_ah=dos.return_mode;
break; break;
case 0x4e: /* FINDFIRST Find first matching file */ case 0x4e: /* FINDFIRST Find first matching file */
@ -650,17 +661,18 @@ static Bitu DOS_21Handler(void) {
case 0x4f: /* FINDNEXT Find next matching file */ case 0x4f: /* FINDNEXT Find next matching file */
if (DOS_FindNext()) { if (DOS_FindNext()) {
CALLBACK_SCF(false); CALLBACK_SCF(false);
reg_ax=0xffff; /* Undocumented */ /* reg_ax=0xffff;*/ /* Undocumented */
reg_ax=0; /* Undocumented:Qbix Willy beamish */
} else { } else {
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
CALLBACK_SCF(true); CALLBACK_SCF(true);
}; };
break; break;
case 0x50: /* Set current PSP */ case 0x50: /* Set current PSP */
dos.psp=reg_bx; dos.psp(reg_bx);
break; break;
case 0x51: /* Get current PSP */ case 0x51: /* Get current PSP */
reg_bx=dos.psp; reg_bx=dos.psp();
break; break;
case 0x52: { /* Get list of lists */ case 0x52: { /* Get list of lists */
RealPt addr=dos_infoblock.GetPointer(); RealPt addr=dos_infoblock.GetPointer();
@ -671,14 +683,14 @@ static Bitu DOS_21Handler(void) {
//TODO Think hard how shit this is gonna be //TODO Think hard how shit this is gonna be
//And will any game ever use this :) //And will any game ever use this :)
case 0x53: /* Translate BIOS parameter block to drive parameter block */ case 0x53: /* Translate BIOS parameter block to drive parameter block */
E_Exit("Unhandled Dos 21 call %02X",reg_ah); E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break; break;
case 0x54: /* Get verify flag */ case 0x54: /* Get verify flag */
reg_al=dos.verify?1:0; reg_al=dos.verify?1:0;
break; break;
case 0x55: /* Create Child PSP*/ case 0x55: /* Create Child PSP*/
DOS_ChildPSP(reg_dx,reg_si); DOS_ChildPSP(reg_dx,reg_si);
dos.psp = reg_dx; dos.psp(reg_dx);
break; break;
case 0x56: /* RENAME Rename file */ case 0x56: /* RENAME Rename file */
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); 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); MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
if (DOS_CreateTempFile(name1,&handle)) { if (DOS_CreateTempFile(name1,&handle)) {
reg_ax=handle; reg_ax=handle;
MEM_BlockWrite(SegPhys(ds)+reg_dx,name1,strlen(name1)+1);
CALLBACK_SCF(false); CALLBACK_SCF(false);
} else { } else {
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
@ -763,6 +776,19 @@ static Bitu DOS_21Handler(void) {
} }
break; 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 */ case 0x60: /* Canonicalize filename or path */
MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF); MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF);
if (DOS_Canonicalize(name1,name2)) { if (DOS_Canonicalize(name1,name2)) {
@ -774,7 +800,15 @@ static Bitu DOS_21Handler(void) {
} }
break; break;
case 0x62: /* Get Current PSP Address */ 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; break;
case 0x64: /* Set device driver lookahead flag */ case 0x64: /* Set device driver lookahead flag */
E_Exit("Unhandled Dos 21 call %02X",reg_ah); E_Exit("Unhandled Dos 21 call %02X",reg_ah);
@ -787,10 +821,23 @@ static Bitu DOS_21Handler(void) {
switch (reg_al) { switch (reg_al) {
case 1: case 1:
mem_writeb(data,reg_al); mem_writeb(data,reg_al);
mem_writew(data+1,4); mem_writew(data+0x01,0x1c);
mem_writew(data+3,1); mem_writew(data+0x03,1);
mem_writew(data+5,37); mem_writew(data+0x05,0x01b5);
reg_cx=4; 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); CALLBACK_SCF(false);
break; break;
case 2: // Get pointer to uppercase table 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 5: // Get pointer to filename terminator table
case 6: // Get pointer to collating sequence table case 6: // Get pointer to collating sequence table
case 7: // Get pointer to double byte char set table case 7: // Get pointer to double byte char set table
mem_writew(data ,0x0000); // We dont have this table... mem_writeb(data,reg_al);
mem_writew(data+2,0x0000); // End of table mem_writed(data+1,dos.tables.dcbs); //used to be 0
reg_cx=4; reg_cx=5;
CALLBACK_SCF(false); CALLBACK_SCF(false);
break; break;
default: default:
@ -821,7 +868,7 @@ static Bitu DOS_21Handler(void) {
case 0x67: /* Set handle count */ case 0x67: /* Set handle count */
/* Weird call to increase amount of file handles needs to allocate memory if >20 */ /* 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); psp.SetNumFiles(reg_bx);
CALLBACK_SCF(false); CALLBACK_SCF(false);
break; break;
@ -854,8 +901,8 @@ static Bitu DOS_21Handler(void) {
CALLBACK_SCF(true); CALLBACK_SCF(true);
LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al); LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al);
break; break;
case 0x68: /* FFLUSH Commit file */ 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 CALLBACK_SCF(false); //mirek
case 0xE0: case 0xE0:
case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */ 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 0x6b: /* NULL Function */
case 0x61: /* UNUSED */ case 0x61: /* UNUSED */
case 0xEF: /* Used in Ancient Art Of War CGA */ 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 0x1f: /* Get drive parameter block for default drive */
case 0x32: /* Get drive parameter block for specific drive */
case 0x5c: /* FLOCK File region locking */ case 0x5c: /* FLOCK File region locking */
case 0x5e: /* More Network Functions */ case 0x5e: /* More Network Functions */
case 0x5f: /* And Even More Network Functions */
default: default:
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al); 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 */ reg_al=0x00; /* default value */
@ -894,7 +938,7 @@ static Bitu DOS_27Handler(void)
{ {
// Terminate & stay resident // Terminate & stay resident
Bit16u para = (reg_dx/16)+((reg_dx % 16)>0); 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; return CBRET_NONE;
} }
static Bitu DOS_25Handler(void) { static Bitu DOS_25Handler(void) {
@ -903,9 +947,10 @@ static Bitu DOS_25Handler(void) {
SETFLAGBIT(CF,true); SETFLAGBIT(CF,true);
}else{ }else{
SETFLAGBIT(CF,false); SETFLAGBIT(CF,false);
reg_ax=0;
if((reg_cx != 1) ||(reg_dx != 1)) 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; return CBRET_NONE;
} }
@ -925,8 +970,14 @@ static Bitu DOS_28Handler(void) {
} }
static Bitu DOS_29Handler(void) { static Bitu DOS_29Handler(void) {
LOG(LOG_DOSMISC,LOG_ERROR)("int 29 called"); static bool int29warn=false;
return CBRET_NONE; 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) { static Bitu DOS_CaseMapFunc(void) {
@ -942,32 +993,32 @@ void DOS_ShutDown(Section* sec)
void DOS_Init(Section* sec) { void DOS_Init(Section* sec) {
call_20=CALLBACK_Allocate(); 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)); RealSetVec(0x20,CALLBACK_RealPointer(call_20));
call_21=CALLBACK_Allocate(); 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)); RealSetVec(0x21,CALLBACK_RealPointer(call_21));
call_25=CALLBACK_Allocate(); 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)); RealSetVec(0x25,CALLBACK_RealPointer(call_25));
call_26=CALLBACK_Allocate(); 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)); RealSetVec(0x26,CALLBACK_RealPointer(call_26));
call_27=CALLBACK_Allocate(); 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)); RealSetVec(0x27,CALLBACK_RealPointer(call_27));
call_28=CALLBACK_Allocate(); call_28=CALLBACK_Allocate();
CALLBACK_Setup(call_28,DOS_28Handler,CB_IRET); CALLBACK_Setup(call_28,DOS_28Handler,CB_IRET,"DOS Int 28");
RealSetVec(0x28,CALLBACK_RealPointer(call_28)); RealSetVec(0x28,CALLBACK_RealPointer(call_28));
call_29=CALLBACK_Allocate(); call_29=CALLBACK_Allocate();
CALLBACK_Setup(call_29,DOS_29Handler,CB_IRET); CALLBACK_Setup(call_29,DOS_29Handler,CB_IRET,"CON Output Int 29");
RealSetVec(0x29,CALLBACK_RealPointer(call_29)); RealSetVec(0x29,CALLBACK_RealPointer(call_29));
DOS_SetupFiles(); /* Setup system File tables */ DOS_SetupFiles(); /* Setup system File tables */
DOS_SetupDevices(); /* Setup dos devices */ DOS_SetupDevices(); /* Setup dos devices */
@ -995,6 +1046,6 @@ void DOS_Init(Section* sec) {
/* case map routine INT 0x21 0x38 */ /* case map routine INT 0x21 0x38 */
call_casemap = CALLBACK_Allocate(); 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $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 <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -64,11 +64,45 @@ void DOS_InfoBlock::SetLocation(Bit16u segment)
pt=PhysMake(seg,0); pt=PhysMake(seg,0);
/* Clear the initual Block */ /* Clear the initual Block */
for(Bitu i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff); 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) void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb)
{ {
sSave(sDIB,firstMCB,_firstmcb); sSave(sDIB,firstMCB,_firstmcb); //c2woody
} }
void DOS_InfoBlock::SetfirstFileTable(RealPt _first_table){ 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) RealPt DOS_InfoBlock::GetPointer(void)
{ {
return RealMake(seg,offsetof(sDIB,firstDPB)); return RealMake(seg,offsetof(sDIB,firstDPB));
@ -94,7 +148,7 @@ Bit16u DOS_PSP::rootpsp = 0;
void DOS_PSP::MakeNew(Bit16u mem_size) void DOS_PSP::MakeNew(Bit16u mem_size)
{ {
/* get previous */ /* get previous */
DOS_PSP prevpsp(dos.psp); DOS_PSP prevpsp(dos.psp());
/* Clear it first */ /* Clear it first */
Bitu i; Bitu i;
for (i=0;i<sizeof(sPSP);i++) mem_writeb(pt+i,0); 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[1],0x21);
sSave(sPSP,service[2],0xcb); sSave(sPSP,service[2],0xcb);
/* psp and psp-parent */ /* psp and psp-parent */
sSave(sPSP,psp_parent,dos.psp); sSave(sPSP,psp_parent,dos.psp());
sSave(sPSP,prev_psp,RealMake(dos.psp,0)); sSave(sPSP,prev_psp,0xffffffff);
sSave(sPSP,dos_version,0x0005);
/* terminate 22,break 23,crititcal error 24 address stored */ /* terminate 22,break 23,crititcal error 24 address stored */
SaveVectors(); SaveVectors();
/* Process DTA */
sSave(sPSP,dta,RealMake(seg,128));
/* FCBs are filled with 0 */ /* FCBs are filled with 0 */
// .... // ....
/* Init file pointer and max_files */ /* 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); sSave(sPSP,max_files,20);
for (i=0;i<20;i++) SetFileHandle(i,0xff); 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); MEM_BlockCopy(pt+offsetof(sPSP,cmdtail),Real2Phys(src),128);
} else { // empty } else { // empty
sSave(sPSP,cmdtail.count,0x00); 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; 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
@ -34,6 +34,27 @@
static DOS_Device * devices[MAX_DEVICES]; static DOS_Device * devices[MAX_DEVICES];
static Bit32u device_count; 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) { Bit8u DOS_FindDevice(char * name) {
/* loop through devices */ /* loop through devices */
Bit8u index=0; Bit8u index=0;
@ -73,5 +94,8 @@ void DOS_SetupDevices(void) {
DOS_Device * newdev; DOS_Device * newdev;
newdev=new device_CON(); newdev=new device_CON();
DOS_AddDevice(newdev); 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, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id */ /* $Id: dos_execute.cpp,v 1.44 2004/08/04 09:12:53 qbix79 Exp $ */
#include <string.h> #include <string.h>
#include <ctype.h>
#include "dosbox.h" #include "dosbox.h"
#include "mem.h" #include "mem.h"
#include "dos_inc.h" #include "dos_inc.h"
@ -26,6 +27,8 @@
#include "callback.h" #include "callback.h"
#include "debug.h" #include "debug.h"
char * RunningProgram="DOSBOX";
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma pack(1) #pragma pack(1)
#endif #endif
@ -65,7 +68,7 @@ struct EXE_Header {
static void SaveRegisters(void) { 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+ 0,reg_ax);
mem_writew(SegPhys(ss)+reg_sp+ 2,reg_cx); mem_writew(SegPhys(ss)+reg_sp+ 2,reg_cx);
mem_writew(SegPhys(ss)+reg_sp+ 4,reg_dx); 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); reg_bp=mem_readw(SegPhys(ss)+reg_sp+12);
SegSet16(ds,mem_readw(SegPhys(ss)+reg_sp+14)); SegSet16(ds,mem_readw(SegPhys(ss)+reg_sp+14));
SegSet16(es,mem_readw(SegPhys(ss)+reg_sp+16)); 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) { bool DOS_Terminate(bool tsr) {
dos.return_code=reg_al; dos.return_code=reg_al;
dos.return_mode=RETURN_EXIT; dos.return_mode=RETURN_EXIT;
Bit16u mempsp = dos.psp; Bit16u mempsp = dos.psp();
DOS_PSP curpsp(dos.psp); DOS_PSP curpsp(mempsp);
if (dos.psp==curpsp.GetParent()) return true; if (mempsp==curpsp.GetParent()) return true;
/* Free Files owned by process */ /* Free Files owned by process */
if (!tsr) curpsp.CloseFiles(); if (!tsr) curpsp.CloseFiles();
@ -108,10 +120,9 @@ bool DOS_Terminate(bool tsr) {
/* Restore vector 22,23,24 */ /* Restore vector 22,23,24 */
curpsp.RestoreVectors(); curpsp.RestoreVectors();
/* Set the parent PSP */ /* Set the parent PSP */
dos.psp = curpsp.GetParent(); dos.psp(curpsp.GetParent());
DOS_PSP parentpsp(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 */ /* Restore the SS:SP to the previous one */
SegSet16(ss,RealSeg(parentpsp.GetStack())); SegSet16(ss,RealSeg(parentpsp.GetStack()));
reg_sp = RealOff(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 mem_writew(SegPhys(ss)+reg_sp+4,0x200); //stack isn't preserved
// Free memory owned by process // Free memory owned by process
if (!tsr) DOS_FreeProcessMemory(mempsp); if (!tsr) DOS_FreeProcessMemory(mempsp);
DOS_UpdatePSPName();
return true; return true;
} }
static bool MakeEnv(char * name,Bit16u * segment) { static bool MakeEnv(char * name,Bit16u * segment) {
/* If segment to copy environment is 0 copy the caller's environment */ /* If segment to copy environment is 0 copy the caller's environment */
DOS_PSP psp(dos.psp); DOS_PSP psp(dos.psp());
PhysPt envread,envwrite; PhysPt envread,envwrite;
Bit16u envsize=1; Bit16u envsize=1;
bool parentenv=true; bool parentenv=true;
@ -173,8 +182,7 @@ static bool MakeEnv(char * name,Bit16u * segment) {
} else return false; } else return false;
} }
bool DOS_NewPSP(Bit16u segment, Bit16u size) bool DOS_NewPSP(Bit16u segment, Bit16u size) {
{
DOS_PSP psp(segment); DOS_PSP psp(segment);
psp.MakeNew(size); psp.MakeNew(size);
DOS_PSP psp_parent(psp.GetParent()); DOS_PSP psp_parent(psp.GetParent());
@ -182,8 +190,7 @@ bool DOS_NewPSP(Bit16u segment, Bit16u size)
return true; return true;
}; };
bool DOS_ChildPSP(Bit16u segment, Bit16u size) bool DOS_ChildPSP(Bit16u segment, Bit16u size) {
{
DOS_PSP psp(segment); DOS_PSP psp(segment);
psp.MakeNew(size); psp.MakeNew(size);
DOS_PSP psp_parent(psp.GetParent()); 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) { static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
/* Fix the PSP for psp and environment MCB's */ /* Fix the PSP for psp and environment MCB's */
DOS_MCB mcb((Bit16u)(pspseg-1)); DOS_MCB mcb((Bit16u)(pspseg-1));
mcb.SetPSPSeg(pspseg); mcb.SetPSPSeg(pspseg);
@ -204,31 +210,14 @@ static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
DOS_PSP psp(pspseg); DOS_PSP psp(pspseg);
psp.MakeNew(memsize); psp.MakeNew(memsize);
psp.SetEnvironment(envseg); 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); /* Copy file handles */
/* Setup the DTA */ DOS_PSP oldpsp(dos.psp());
dos.dta=RealMake(pspseg,0x80); psp.CopyFileTable(&oldpsp,true);
} }
static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block) static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block) {
{
DOS_PSP psp(pspseg); DOS_PSP psp(pspseg);
// if cmdtail==0 it will inited as empty in SetCommandTail // if cmdtail==0 it will inited as empty in SetCommandTail
psp.SetCommandTail(block.exec.cmdtail); 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 (len<sizeof(EXE_Header)) iscom=true;
if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true; if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true;
else { else {
headersize=head.headersize*16; headersize = head.headersize*16;
if (head.extrabytes) { imagesize = head.pages*512-headersize;
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?)
if (imagesize+headersize<512) imagesize = 512-headersize; if (imagesize+headersize<512) imagesize = 512-headersize;
} }
if (flags!=OVERLAY) { if (flags!=OVERLAY) {
@ -298,16 +281,20 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
else memsize=maxsize; else memsize=maxsize;
if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory"); if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory");
loadseg=pspseg+16; loadseg=pspseg+16;
if ((!iscom) & (head.minmemory == 0) & (head.maxmemory == 0))
loadseg = (0x9e000 - imagesize)/16; //c2woody
} else loadseg=block.overlay.loadseg; } else loadseg=block.overlay.loadseg;
/* Load the executable */ /* Load the executable */
Bit8u * loadbuf=(Bit8u *)new Bit8u[0x10000]; Bit8u * loadbuf=(Bit8u *)new Bit8u[0x10000];
loadaddress=PhysMake(loadseg,0); loadaddress=PhysMake(loadseg,0);
if (iscom) { /* COM Load 64k - 256 bytes max */ if (iscom) { /* COM Load 64k - 256 bytes max */
pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET); pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
readsize=0xffff-256; readsize=0xffff-256;
DOS_ReadFile(fhandle,loadbuf,&readsize); DOS_ReadFile(fhandle,loadbuf,&readsize);
MEM_BlockWrite(loadaddress,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); pos=headersize;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
while (imagesize>0x7FFF) { while (imagesize>0x7FFF) {
readsize=0x8000;DOS_ReadFile(fhandle,loadbuf,&readsize); 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); SetupPSP(pspseg,memsize,envseg);
SetupCMDLine(pspseg,block); SetupCMDLine(pspseg,block);
}; };
CALLBACK_SCF(false); /* Carry flag cleared for caller if successfull */ CALLBACK_SCF(false); /* Carry flag cleared for caller if successfull */
if (flags==OVERLAY) return true; /* Everything done for overlays */ if (flags==OVERLAY) return true; /* Everything done for overlays */
RealPt csip,sssp; RealPt csip,sssp;
@ -353,14 +339,15 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
csip=RealMake(loadseg+head.initCS,head.initIP); csip=RealMake(loadseg+head.initCS,head.initIP);
sssp=RealMake(loadseg+head.initSS,head.initSP); sssp=RealMake(loadseg+head.initSS,head.initSP);
} }
if (flags==LOAD) { if (flags==LOAD) {
DOS_PSP callpsp(dos.psp); DOS_PSP callpsp(dos.psp());
/* Save the SS:SP on the PSP of calling program */ /* Save the SS:SP on the PSP of calling program */
callpsp.SetStack(RealMakeSeg(ss,reg_sp)); callpsp.SetStack(RealMakeSeg(ss,reg_sp));
/* Switch the psp's */ /* 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.initsssp = sssp;
block.exec.initcsip = csip; block.exec.initcsip = csip;
block.SaveData(); 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 */ /* 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))); RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp)));
SaveRegisters(); SaveRegisters();
DOS_PSP callpsp(dos.psp); DOS_PSP callpsp(dos.psp());
/* Save the SS:SP on the PSP of calling program */ /* Save the SS:SP on the PSP of calling program */
callpsp.SetStack(RealMakeSeg(ss,reg_sp)); callpsp.SetStack(RealMakeSeg(ss,reg_sp));
/* Switch the psp's and set new DTA */ /* Switch the psp's and set new DTA */
dos.psp=pspseg; dos.psp(pspseg);
DOS_PSP newpsp(dos.psp); DOS_PSP newpsp(dos.psp());
newpsp.SetDTA(dos.dta); /* Original: change this and line below. This way seems better(zone66 and unpack) */ dos.dta(RealMake(newpsp.GetSegment(),0x80));
//dos.dta=newpsp.GetDTA();
/* save vectors */ /* save vectors */
newpsp.SaveVectors(); newpsp.SaveVectors();
/* copy fcbs */ /* 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 */ /* Started from debug.com, then set breakpoint at start */
DEBUG_CheckExecuteBreakpoint(RealSeg(csip),RealOff(csip)); DEBUG_CheckExecuteBreakpoint(RealSeg(csip),RealOff(csip));
#endif #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 true;
} }
return false; return false;

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