mirror of
https://github.com/retro100/dosbox-wii.git
synced 2024-09-28 17:58:36 +02:00
DOSBox 0.62
This commit is contained in:
parent
a0ed243c23
commit
6a0c0c74c0
7
AUTHORS
7
AUTHORS
@ -1,9 +1,8 @@
|
||||
The DOSBox Team
|
||||
---------------
|
||||
|
||||
Sjoerd v.d. Berg <harekiet@zophar.net>
|
||||
Sjoerd v.d. Berg <harekiet@users.sourceforge.net>
|
||||
Peter Veenstra <qbix79@users.sourceforge.net>
|
||||
Felix Jakschitsch <yot@users.sourceforge.net>
|
||||
Ulf Wohlers <finsterr@users.sourceforge.net>
|
||||
Tommy Frössman <fanskapet@php-coders.net>
|
||||
|
||||
Tommy Frössman <fanskapet@sidvicious.se>
|
||||
Dean Beeler <canadacow@users.sourceforge.net>
|
||||
|
62
ChangeLog
62
ChangeLog
@ -1,3 +1,65 @@
|
||||
0.62
|
||||
- Added blinking support in the shell and some color fixes.
|
||||
- Fixed commandline parsing when .bat files involved (fixes -exit)
|
||||
- Fixed issues with tabs in commandline not being processed correctly.
|
||||
- Cleaned/improved shutdown sequence.
|
||||
- Added some more bios functions (wait and delay functions).
|
||||
- Made our XMS driver conform the specs better. (c2woody)
|
||||
- Added support for some more ems functions.
|
||||
- Added intelligent mpu401 emulation. (Srecko)
|
||||
- Added soundblaster 16 emulation.
|
||||
- Rewrote GUS emulation to sound more authentic.
|
||||
- Improved pc speaker emulation.
|
||||
- Added an internal (programmable) mixer.
|
||||
- Added support a few soundblaster/adlib detection routines.
|
||||
- Fixed lot's of bugs related to DMA transfers.
|
||||
- Added interpolating prebuffering mixer routines.
|
||||
- Added recording of OPL commands and raw midi.
|
||||
- Fixed some bugs with the wave recording.
|
||||
- Changed sensitivity settings of the mouse.
|
||||
- Added ps2 mouse-emulation in bios interrupts (c2woody).
|
||||
- Fixed some bugs with mouse emulation limits.
|
||||
- Fixed a bug with an unterminated string in the drivelabel.
|
||||
- Changed file search routines a bit to be more compatible.
|
||||
- Added support for attribute-searching with fcb's.
|
||||
- Added basic SDA.
|
||||
- Added TPA and DIB.
|
||||
- Added Lot's of missing dos tables (c2woody).
|
||||
- Changed psp and dta functions to use dta.
|
||||
- Returned filename in ds:dx in create-random-file (c2woody).
|
||||
- Fixed a bug with date and time used on open files.
|
||||
- Some mscdex fixes.
|
||||
- Added the -version switch, which makes dosbox report its version.
|
||||
- Added a keymapper.
|
||||
- Added basic IPX emulation.
|
||||
- Added cdrom iso support and floppy images support.
|
||||
- Added the possibity to boot another dos version.
|
||||
- Added Serial passthrough support (win32 only).
|
||||
- Added the possibility to pause dosbox.
|
||||
- Changed OpenGL so that it is initialized only when used.
|
||||
- Make dosbox run at higher priority when active and lower when inactive.
|
||||
- Added direct draw output support (win32 only).
|
||||
- Added current running program to title bar.
|
||||
- Rewrote video emulation to support new scalers.
|
||||
- Added new graphics scalers like advmame3x,tv2x.
|
||||
- Added a support for a few anti-debugger tricks.
|
||||
- Improved the handling of the tab-key.
|
||||
- Improved support for the numeric keyboard.
|
||||
- Fixed a few cpu opcodes.
|
||||
- Added cpu core simple (for lowerend machines)
|
||||
- Fixed some nasty bugs in the dynamic cpu core.
|
||||
- Added a few (rarely used) fpu opcodes.
|
||||
- Fixed various issues with GCC 3.4.
|
||||
- Many internal timer improvements (PIT and PIC).
|
||||
- Added some more PIC commands (c2woody).
|
||||
- Added BCD counting to the timers.
|
||||
- Fix some vesa functions.
|
||||
- Add some basic support for 132x25 and 132x45 textmodes.
|
||||
- Improved Tandy emulation a lot.
|
||||
- Lowered cpu usage when dosbox is idle.
|
||||
- Allow virtualisation of some basic IO-ports (c2woody).
|
||||
|
||||
|
||||
0.61
|
||||
- Added a beta dynamic cpu for x86 hosts (very unstable)
|
||||
- Added opengl and hardware overlay display output
|
||||
|
@ -3,5 +3,6 @@
|
||||
EXTRA_DIST = autogen.sh
|
||||
SUBDIRS = src include visualc docs visualc_net
|
||||
|
||||
|
||||
docdir = $(prefix)/share/doc/$(PACKAGE)
|
||||
doc_DATA = README NEWS THANKS AUTHORS
|
||||
|
||||
|
39
Makefile.in
39
Makefile.in
@ -134,12 +134,17 @@ target_vendor = @target_vendor@
|
||||
|
||||
EXTRA_DIST = autogen.sh
|
||||
SUBDIRS = src include visualc docs visualc_net
|
||||
|
||||
docdir = $(prefix)/share/doc/$(PACKAGE)
|
||||
doc_DATA = README NEWS THANKS AUTHORS
|
||||
subdir = .
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
DIST_SOURCES =
|
||||
DATA = $(doc_DATA)
|
||||
|
||||
|
||||
RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
|
||||
ps-recursive install-info-recursive uninstall-info-recursive \
|
||||
@ -189,6 +194,24 @@ $(srcdir)/config.h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
distclean-hdr:
|
||||
-rm -f config.h stamp-h1
|
||||
uninstall-info-am:
|
||||
docDATA_INSTALL = $(INSTALL_DATA)
|
||||
install-docDATA: $(doc_DATA)
|
||||
@$(NORMAL_INSTALL)
|
||||
$(mkinstalldirs) $(DESTDIR)$(docdir)
|
||||
@list='$(doc_DATA)'; for p in $$list; do \
|
||||
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
|
||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
||||
echo " $(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f"; \
|
||||
$(docDATA_INSTALL) $$d$$p $(DESTDIR)$(docdir)/$$f; \
|
||||
done
|
||||
|
||||
uninstall-docDATA:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(doc_DATA)'; for p in $$list; do \
|
||||
f="`echo $$p | sed -e 's|^.*/||'`"; \
|
||||
echo " rm -f $(DESTDIR)$(docdir)/$$f"; \
|
||||
rm -f $(DESTDIR)$(docdir)/$$f; \
|
||||
done
|
||||
|
||||
# This directory's subdirectories are mostly independent; you can cd
|
||||
# into them and run `make' without going through this Makefile.
|
||||
@ -446,9 +469,10 @@ distcleancheck: distclean
|
||||
exit 1; } >&2
|
||||
check-am: all-am
|
||||
check: check-recursive
|
||||
all-am: Makefile config.h
|
||||
all-am: Makefile $(DATA) config.h
|
||||
installdirs: installdirs-recursive
|
||||
installdirs-am:
|
||||
$(mkinstalldirs) $(DESTDIR)$(docdir)
|
||||
|
||||
install: install-recursive
|
||||
install-exec: install-exec-recursive
|
||||
@ -491,7 +515,7 @@ info: info-recursive
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
install-data-am: install-docDATA
|
||||
|
||||
install-exec-am:
|
||||
|
||||
@ -519,7 +543,7 @@ ps: ps-recursive
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
uninstall-am: uninstall-docDATA uninstall-info-am
|
||||
|
||||
uninstall-info: uninstall-info-recursive
|
||||
|
||||
@ -529,16 +553,17 @@ uninstall-info: uninstall-info-recursive
|
||||
distclean-hdr distclean-recursive distclean-tags distcleancheck \
|
||||
distdir distuninstallcheck dvi dvi-am dvi-recursive info \
|
||||
info-am info-recursive install install-am install-data \
|
||||
install-data-am install-data-recursive install-exec \
|
||||
install-exec-am install-exec-recursive install-info \
|
||||
install-info-am install-info-recursive install-man \
|
||||
install-data-am install-data-recursive install-docDATA \
|
||||
install-exec install-exec-am install-exec-recursive \
|
||||
install-info install-info-am install-info-recursive install-man \
|
||||
install-recursive install-strip installcheck installcheck-am \
|
||||
installdirs installdirs-am installdirs-recursive \
|
||||
maintainer-clean maintainer-clean-generic \
|
||||
maintainer-clean-recursive mostlyclean mostlyclean-generic \
|
||||
mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \
|
||||
ps-recursive tags tags-recursive uninstall uninstall-am \
|
||||
uninstall-info-am uninstall-info-recursive uninstall-recursive
|
||||
uninstall-docDATA uninstall-info-am uninstall-info-recursive \
|
||||
uninstall-recursive
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
61
NEWS
61
NEWS
@ -1,3 +1,64 @@
|
||||
0.62
|
||||
- Added blinking support in the shell and some color fixes.
|
||||
- Fixed commandline parsing when .bat files involved (fixes -exit)
|
||||
- Fixed issues with tabs in commandline not being processed correctly.
|
||||
- Cleaned/improved shutdown sequence.
|
||||
- Added some more bios functions (wait and delay functions).
|
||||
- Made our XMS driver conform the specs better. (c2woody)
|
||||
- Added support for some more ems functions.
|
||||
- Added intelligent mpu401 emulation. (Srecko)
|
||||
- Added soundblaster 16 emulation.
|
||||
- Rewrote GUS emulation to sound more authentic.
|
||||
- Improved pc speaker emulation.
|
||||
- Added an internal (programmable) mixer.
|
||||
- Added support a few soundblaster/adlib detection routines.
|
||||
- Fixed lot's of bugs related to DMA transfers.
|
||||
- Added interpolating prebuffering mixer routines.
|
||||
- Added recording of OPL commands and raw midi.
|
||||
- Fixed some bugs with the wave recording.
|
||||
- Changed sensitivity settings of the mouse.
|
||||
- Added ps2 mouse-emulation in bios interrupts (c2woody).
|
||||
- Fixed some bugs with mouse emulation limits.
|
||||
- Fixed a bug with an unterminated string in the drivelabel.
|
||||
- Changed file search routines a bit to be more compatible.
|
||||
- Added support for attribute-searching with fcb's.
|
||||
- Added basic SDA.
|
||||
- Added TPA and DIB.
|
||||
- Added Lot's of missing dos tables (c2woody).
|
||||
- Changed psp and dta functions to use dta.
|
||||
- Returned filename in ds:dx in create-random-file (c2woody).
|
||||
- Fixed a bug with date and time used on open files.
|
||||
- Some mscdex fixes.
|
||||
- Added the -version switch, which makes dosbox report its version.
|
||||
- Added a keymapper.
|
||||
- Added basic IPX emulation.
|
||||
- Added cdrom iso support and floppy images support.
|
||||
- Added the possibity to boot another dos version.
|
||||
- Added Serial passthrough support (win32 only).
|
||||
- Added the possibility to pause dosbox.
|
||||
- Changed OpenGL so that it is initialized only when used.
|
||||
- Make dosbox run at higher priority when active and lower when inactive.
|
||||
- Added direct draw output support (win32 only).
|
||||
- Added current running program to title bar.
|
||||
- Rewrote video emulation to support new scalers.
|
||||
- Added new graphics scalers like advmame3x,tv2x.
|
||||
- Added a support for a few anti-debugger tricks.
|
||||
- Improved the handling of the tab-key.
|
||||
- Improved support for the numeric keyboard.
|
||||
- Fixed a few cpu opcodes.
|
||||
- Added cpu core simple (for lowerend machines)
|
||||
- Fixed some nasty bugs in the dynamic cpu core.
|
||||
- Added a few (rarely used) fpu opcodes.
|
||||
- Fixed various issues with GCC 3.4.
|
||||
- Many internal timer improvements (PIT and PIC).
|
||||
- Added some more PIC commands (c2woody).
|
||||
- Added BCD counting to the timers.
|
||||
- Fix some vesa functions.
|
||||
- Add some basic support for 132x25 and 132x45 textmodes.
|
||||
- Improved Tandy emulation a lot.
|
||||
- Lowered cpu usage when dosbox is idle.
|
||||
- Allow virtualisation of some basic IO-ports (c2woody).
|
||||
|
||||
0.61
|
||||
- Added a beta dynamic cpu for x86 hosts (very unstable)
|
||||
- Added opengl and hardware overlay display output
|
||||
|
605
README
605
README
@ -1,4 +1,5 @@
|
||||
DOSBox v0.61
|
||||
DOSBox v0.62
|
||||
|
||||
|
||||
=====
|
||||
NOTE:
|
||||
@ -6,7 +7,7 @@ NOTE:
|
||||
|
||||
While we hope that, one day, DOSBox will run virtually all programs
|
||||
ever made for the PC...we are not there yet. At present, DOSBox run on a high-
|
||||
end machine will roughly be the equivalent of a lowend 486 PC. While the 0.60
|
||||
end machine will roughly be the equivalent of a 486 PC. The 0.60
|
||||
release has added support for "protected mode" allowing for more complex and
|
||||
recent programs, but note that this support is early in development and
|
||||
nowhere near as complete as the support for 386 real-mode games (or
|
||||
@ -14,12 +15,180 @@ earlier). Also note that "protected mode" games need substantially more
|
||||
resources and may require a much faster processor for you to run it properly
|
||||
in DOSBox.
|
||||
|
||||
|
||||
|
||||
======
|
||||
Usage:
|
||||
INDEX:
|
||||
======
|
||||
1. Quickstart
|
||||
2. FAQ
|
||||
3. Usage
|
||||
4. Internal Programs
|
||||
5. Special Keys
|
||||
6. Keymapper
|
||||
7. System Requirements
|
||||
8. To run resource-demanding games
|
||||
9. The config file
|
||||
10. The language file
|
||||
11. Building your own version of DOSBox
|
||||
12. Special thanks
|
||||
13. Contact
|
||||
|
||||
|
||||
==============
|
||||
1. Quickstart:
|
||||
==============
|
||||
|
||||
Type INTRO in DOSBox. That's it.
|
||||
|
||||
|
||||
|
||||
|
||||
=======
|
||||
2. FAQ:
|
||||
=======
|
||||
|
||||
Some Frequently Asked Questions:
|
||||
|
||||
Q: I've got a Z instead of a C at the prompt.
|
||||
Q: My CD-ROM doesn't work.
|
||||
Q: The mouse doesn't work.
|
||||
Q: The sound stutters.
|
||||
Q: I can't type \ or : in DOSBox.
|
||||
Q: The game/application can't find its CD-ROM.
|
||||
Q: The game/application runs much too slow!
|
||||
Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ.
|
||||
Q: What sound hardware does DOSBox presently emulate?
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Q: I've got a Z instead of a C at the prompt.
|
||||
A: You have to make your directories available as drives in DOSBox by using
|
||||
the "mount" command. For example, in Windows "mount C D:\" would give
|
||||
you a C in DOSBox which points at your Windows D:\ drive.
|
||||
In Linux, "mount c /home/username" would give you a C in DOSBox
|
||||
which points at /home/username in Linux.
|
||||
|
||||
|
||||
Q: My CD-ROM doesn't work.
|
||||
A: To mount your cdrom in DOSBox you have to specify some additional options
|
||||
when mounting the cdrom.
|
||||
To enable the most basic cdrom support:
|
||||
- mount d f:\ -t cdrom
|
||||
To enable low-level SDL-support:
|
||||
- mount d f:\ -t cdrom -usecd 0
|
||||
To enable low-level ioctl-support(win2k/xp/linux):
|
||||
- mount d f:\ -t cdrom -usecd 0 -ioctl
|
||||
To enable low-level aspi-support (win98 with aspi-layer installed):
|
||||
- mount d f:\ -t cdrom -usecd 0 -apsi
|
||||
|
||||
In the commands: - d driveletter you in DOSBox
|
||||
- f:\ location of cdrom on your PC.
|
||||
- 0 The number of the cdrom drive, reported by mount -cd
|
||||
See also the question: The game/application can't find its CD-ROM.
|
||||
|
||||
|
||||
Q: The mouse doesn't work.
|
||||
A: Normally DOSBox detects the mouse being used by a game. If you click on
|
||||
the screen then it should get locked and work.
|
||||
Sometimes the DOSBox mouse detection doesn't work with certain games. You
|
||||
might have to force to lock the mouse then with ctrl-F10.
|
||||
|
||||
|
||||
Q: The sound stutters.
|
||||
A: You're using too much cpu power to keep DOSBox running at the current speed.
|
||||
You can either lower the cycles or skip frames or get a faster machine.
|
||||
You can also increase the prebuffer in the configfile
|
||||
|
||||
|
||||
Q: I can't type \ or : in DOSBox.
|
||||
A: This is a known problem. It only occurs if your keyboard layout isn't US.
|
||||
Some possible fixes:
|
||||
1. Switch your keyboard layout.
|
||||
2. Use / instead.
|
||||
3. Add the commands you want to execute to dosbox.conf
|
||||
4. Start the keymapper (CTRL-F1 or add -startmapper switch to dosbox)
|
||||
5. for \ try the keys around "enter". For ":" try shift and the keys between
|
||||
"enter" and "l" (US keyboard layout).
|
||||
6. Use keyb.com for FreeDOS (http://projects.freedos.net/keyb/).
|
||||
|
||||
|
||||
Q: The game/application can't find its CD-ROM.
|
||||
A: Be sure to mount the CD-ROM with -t cdrom switch. Also try adding the
|
||||
correct label (-label LABEL). To enable more low-level CD-ROM support add
|
||||
the following switch to mount: -usecd #, where # is the number of your
|
||||
CD-ROM drive reported by mount -cd. If you run Win32 you can specify -ioctl
|
||||
or -aspi. Look at the description elsewhere in this document for their
|
||||
meaning.
|
||||
|
||||
|
||||
Q: The game/application runs much too slow!
|
||||
A: Look at the section "To run resource-demanding games" for more information.
|
||||
|
||||
|
||||
Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ.
|
||||
A: This is possible! Just create a config file: config -writeconf dosbox.conf .
|
||||
Start your favourite editor and look at all the settings present. To
|
||||
start DOSBox with your new settings: dosbox -conf dosbox.conf
|
||||
|
||||
|
||||
Q: What sound hardware does DOSBox presently emulate?
|
||||
A: DOSBox emulates several legacy sound devices:
|
||||
- Internal PC speaker
|
||||
This emulation includes both the tone generator and several forms of
|
||||
digital sound output through the internal speaker.
|
||||
- Creative CMS/Gameblaster
|
||||
The is the first card released by Creative Labs(R). The default
|
||||
configuration places it on port 0x220. It should be noted that enabling
|
||||
this with the Adlib emulation may result in conflicts.
|
||||
- Tandy 3 voice
|
||||
The emulation of this sound hardware is complete with the exception of
|
||||
the noise channel, which is not very well documented and as such is only
|
||||
a best guess as to the sound's accuracy.
|
||||
- Adlib
|
||||
Borrowed from MAME, this emulation is almost perfect and includes the
|
||||
Adlib's ability to almost play digitized sound.
|
||||
- SoundBlaster Pro
|
||||
Coupled with the Adlib, DOSBox provides Soundblaster Pro level 8-bit
|
||||
stereo sound.
|
||||
- Disney Soundsource
|
||||
Using the printer port, this sound device outputs digital sound only.
|
||||
- Gravis Ultrasound
|
||||
The emulation of this hardware is nearly complete, though the MIDI
|
||||
capabilities have been left out since an MPU-401 has been
|
||||
emulated in other code.
|
||||
- MPU-401
|
||||
A MIDI passthrough interface is also emulated. This method of sound
|
||||
output will only work when used with a General Midi or MT-32 device.
|
||||
|
||||
|
||||
Q: Great README, but I still don't get it.
|
||||
A: While unlikely, this seems to happen. A look at "The Newbie's
|
||||
pictorial guide to DOSBox" located at
|
||||
http://vogons.zetafleet.com/viewforum.php?f=39 might help you.
|
||||
|
||||
|
||||
For more questions read the remainder of this README and/or check
|
||||
the site/forum:
|
||||
http://dosbox.sourceforge.net
|
||||
|
||||
|
||||
|
||||
|
||||
=========
|
||||
3. Usage:
|
||||
=========
|
||||
|
||||
An overview of the commandline options you can give to DOSBox:
|
||||
|
||||
dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile]
|
||||
[-lang languagefile] [-machine machinetype] [-noconsole]
|
||||
[-startmapper]
|
||||
|
||||
dosbox -version
|
||||
|
||||
name
|
||||
If "name" is a directory it'll mount that as the C: drive.
|
||||
@ -43,13 +212,19 @@ dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile]
|
||||
Start dosbox using the language string specified in "languagefile".
|
||||
|
||||
-noconsole (Windows Only)
|
||||
Start dosbox without showing the console window, output will
|
||||
Start dosbox without showing the console window. Output will
|
||||
be redirected to stdout.txt and stderr.txt
|
||||
|
||||
-machine machinetype
|
||||
Setup dosbox to emulate a specific type of machine. Valid choices are:
|
||||
auto,hercules,cga,tandy,vga.
|
||||
hercules, cga, tandy, vga (default).
|
||||
|
||||
-startmapper
|
||||
Enter the keymapper directly on startup. Useful for people with
|
||||
keyboard problems.
|
||||
|
||||
-version
|
||||
output version information and exit. Useful for frontends.
|
||||
|
||||
Note: If a name/command/configfile/languagefile contains a space in it, put
|
||||
the whole name/command/configfile/languagefile between quotes("example").
|
||||
@ -64,16 +239,16 @@ In Windows you can also drag directories/files onto the dosbox executable.
|
||||
|
||||
|
||||
|
||||
==================
|
||||
Internal Programs:
|
||||
==================
|
||||
=====================
|
||||
4. Internal Programs:
|
||||
=====================
|
||||
|
||||
DOSBox supports most of the DOS commands found in command.com.
|
||||
In addition, the following commands are available:
|
||||
|
||||
MOUNT "Emulated Drive letter" "Real Drive or Directory"
|
||||
[-t type] [-aspi] [-ioctl] [-usecd number] [-size drivesize]
|
||||
[-label drivelabel]
|
||||
[-label drivelabel] [-freesize sizemb]
|
||||
MOUNT -cd
|
||||
|
||||
Program to mount local directories as drives inside DOSBox.
|
||||
@ -91,7 +266,11 @@ MOUNT -cd
|
||||
floppy, cdrom.
|
||||
|
||||
-size drivesize
|
||||
Sets the size of the drive.
|
||||
Sets the size of the drive.
|
||||
|
||||
-freesize sizemb
|
||||
Sets the amount of free space available on a drive in MB's. This
|
||||
is a more simple version of -size.
|
||||
|
||||
-label drivelabel
|
||||
Sets the name of the drive to "drivelabel". Needed on some
|
||||
@ -104,7 +283,7 @@ MOUNT -cd
|
||||
|
||||
-ioctl
|
||||
Forces to use ioctl commands. Only valid if mounting a cdrom under
|
||||
windows which support them (Win2000/XP/NT).
|
||||
a Windows OS which support them (Win2000/XP/NT).
|
||||
|
||||
-usecd number
|
||||
Forces to use SDL cdrom support for drive number.
|
||||
@ -118,11 +297,11 @@ MOUNT -cd
|
||||
|
||||
Basically, MOUNT allows you to connect real hardware to DOSBox's "emulated"
|
||||
PC. So MOUNT C C:\ tells DOSBox to use your real C: drive as drive C: in
|
||||
DosBox. It also allows you to change the drive's letter identification for
|
||||
DOSBox. It also allows you to change the drive's letter identification for
|
||||
programs that demand specific drive letters.
|
||||
|
||||
For example: Touche: Adventures of The Fifth Musketeer must be run on your C:
|
||||
drive. Using DOSBox and it's mount command, you can trick into thinking it
|
||||
drive. Using DOSBox and its mount command, you can trick into thinking it
|
||||
is on C drive while placing it where you want it. For example, if the game
|
||||
were in D:\TOUCHE, you can use the command MOUNT C D:\ would allow you to
|
||||
run Touche from the D drive.
|
||||
@ -131,14 +310,16 @@ MOUNT -cd
|
||||
General MOUNT Examples:
|
||||
1. To mount c:\floppy as a floppy :
|
||||
mount a c:\floppy -t floppy
|
||||
2. To mount system cdrom drive E as cdrom drive D in dosbox:
|
||||
2. To mount system cdrom drive E as cdrom drive D in DOSBox:
|
||||
mount d e:\ -t cdrom
|
||||
3. To mount system cdrom drive at mountpoint /media/cdrom as cdrom drive D
|
||||
in dosbox:
|
||||
mount d /media/cdrom -t cdrom -usecd 0
|
||||
4. To mount a drive with 870 mb free diskspace (rarely needed! experts only):
|
||||
4. To mount a drive with 870 mb free diskspace (simple version):
|
||||
mount c d:\ -freesize 870
|
||||
5. To mount a drive with 870 mb free diskspace (experts only, full control):
|
||||
mount c d:\ -size 4025,127,16513,1700
|
||||
5. To mount /home/dos/dosgames as drive C in DOSBox:
|
||||
6. To mount /home/dos/dosgames as drive C in DOSBox:
|
||||
mount c /home/dos/dosgames
|
||||
|
||||
MEM
|
||||
@ -173,31 +354,272 @@ Examples:
|
||||
3. To free previous allocated memory :
|
||||
loadfix -f
|
||||
|
||||
|
||||
RESCAN
|
||||
Make DOSBox reread the directory structure. Useful if you changed something
|
||||
on a mounted drive outside of DOSBox.
|
||||
|
||||
|
||||
MIXER
|
||||
Makes DOSBox display its current volume settings.
|
||||
You can change this way:
|
||||
|
||||
mixer channel left:right [/NOSHOW]
|
||||
|
||||
channel
|
||||
Can be one of the following: MASTER, DISNEY, SPKR, GUS, SB, FM.
|
||||
|
||||
left:right
|
||||
The volume levels in percentages. If you put a D in front it will be
|
||||
in deciBell (example mixer gus d-10).
|
||||
|
||||
/NOSHOW
|
||||
Prevents DOSBox from showing the result if you set one
|
||||
of the volume levels.
|
||||
|
||||
|
||||
IMGMOUNT
|
||||
A utility to mount disk images and CD-ROM images in DOSBox.
|
||||
|
||||
IMGMOUNT DRIVE [imagefile] -t [image_type] -fs [image_format]
|
||||
-size [sectorsbytesize, sectorsperhead, heads, cylinders]
|
||||
|
||||
imagefile
|
||||
location of the image files to mount in DOSBox. Path is relative to
|
||||
a mount point already inside DOSBox. CD-ROM images can be mounted
|
||||
directly as well (path on the host).
|
||||
|
||||
-t
|
||||
The following are valid image types:
|
||||
floppy: Specifies a floppy image or images. DOSBox will automatically
|
||||
identify the disk geometry ( 360K, 1.2MB, 720K, 1.44MB, etc).
|
||||
iso: Specifies a CD-ROM iso image. The geometry is automatic and
|
||||
set for this size. This can be an iso or a cue/bin.
|
||||
hdd: Specifies a harddrive image. The proper CHS geometry
|
||||
must be set for this to work.
|
||||
|
||||
-fs
|
||||
The following are valid file system formats:
|
||||
iso: Specifies the ISO 9660 CD-ROM format.
|
||||
fat: Specifies the image uses the FAT file system. DOSBox will attempt
|
||||
to mount this image as a drive in DOSBox and make the files
|
||||
available from inside DOSBox.
|
||||
none: DOSBox will make no attempt to read the file system on the disk.
|
||||
This is useful if one needs to format it or one wants to boot
|
||||
off of the disk using the BOOT command. When using the "none"
|
||||
filesystem, one must specify the drive number (2 or 3,
|
||||
where 2 = master, 3 = slave) rather than a drive letter.
|
||||
For example, to mount a 70MB image as the slave drive device,
|
||||
one would type:
|
||||
"imgmount 3 d:\test.img -size 512,63,16,142 -fs none"
|
||||
(without the quotes) Compare this with a mount to read the
|
||||
drive in DOSBox, which would read as:
|
||||
"imgmount e: d:\test.img -size 512,63,16,142"
|
||||
|
||||
-size
|
||||
The Cylinders, Heads and Sectors specification of the drive.
|
||||
Required to mount hard drive images.
|
||||
|
||||
An example of CD-ROM images:
|
||||
1a. mount c /tmp
|
||||
1b. imgmount d c:\myiso.iso -t iso
|
||||
or (which also works):
|
||||
2. imgmount d /tmp/myiso.iso -t iso
|
||||
|
||||
|
||||
BOOT
|
||||
Boot will start floppy images or hard disk images independent of the
|
||||
operating system emulation offered by DOSBox. This will allow you to play
|
||||
booter floppies or boot to other operating systems inside DOSBox.
|
||||
|
||||
BOOT [diskimg1.img diskimg2.img .. diskimgN.img] [-l driveletter]
|
||||
|
||||
diskimgN.img
|
||||
This can be any number of floppy disk images one wants mounted after
|
||||
DOSBox boots the specified drive letter.
|
||||
To swap between images, one hits CTRL+F4 to swap out the current disk
|
||||
and swap in the next disk in the list. Once the last disk in the list is
|
||||
swapped out, the list loops back to the beginning.
|
||||
|
||||
[-l driveletter]
|
||||
This parameter allows one to specify the drive to boot from.
|
||||
The default is the A drive, the floppy drive. One can also boot off of
|
||||
a hard drive image mounted as master by specifying "-l C"
|
||||
without the quotes, or the drive as slave by specifying "-l D"
|
||||
|
||||
|
||||
IPX
|
||||
|
||||
You need to enable IPX networking in the configuration file of DOSBox.
|
||||
|
||||
All of the IPX networking is managed through the internal DOSBox program
|
||||
IPXNET. For help on the IPX networking from inside DOSBox, type
|
||||
"IPXNET HELP" (without quotes) and the program will list out the commands
|
||||
and relevant documentation.
|
||||
|
||||
With regard to actually setting up a network, one system needs to be
|
||||
the server. To set this up, in a DOSBox session, one should type
|
||||
"IPXNET STARTSERVER" (without the quotes). The server DOSBox session will
|
||||
automatically add itself to the virtual IPX network. In turn, for every
|
||||
other computer that should be part of the virtual IPX network,
|
||||
you'll need to type "IPXNET CONNECT <computer host name or IP>".
|
||||
For example, if your server is at bob.dosbox.com,
|
||||
you would type "IPXNET CONNECT bob.dosbox.com" on every non-server system.
|
||||
|
||||
The following is an IPXNET command reference:
|
||||
|
||||
IPXNET CONNECT
|
||||
|
||||
IPXNET CONNECT opens a connection to an IPX tunneling server
|
||||
running on another DOSBox session. The "address" parameter specifies
|
||||
the IP address or host name of the server computer. One can also
|
||||
specify the UDP port to use. By default IPXNET uses port 213, the
|
||||
assigned IANA port for IPX tunneling, for its connection.
|
||||
|
||||
The syntax for IPXNET CONNECT is:
|
||||
IPXNET CONNECT address <port>
|
||||
|
||||
IPXNET DISCONNECT
|
||||
|
||||
IPXNET DISCONNECT closes the connection to the IPX tunneling server.
|
||||
|
||||
The syntax for IPXNET DISCONNECT is:
|
||||
IPXNET DISCONNECT
|
||||
|
||||
IPXNET STARTSERVER
|
||||
|
||||
IPXNET STARTSERVER starts and IPX tunneling server on this DOSBox
|
||||
session. By default, the server will accept connections on UDP port
|
||||
213, though this can be changed. Once the server is started, DOSBox
|
||||
will automatically start a client connection to the IPX tunneling server.
|
||||
|
||||
The syntax for IPXNET STARTSERVER is:
|
||||
IPXNET STARTSERVER <port>
|
||||
|
||||
IPXNET STOPSERVER
|
||||
|
||||
IPXNET STOPSERVER stops the IPX tunneling server running on this DOSBox
|
||||
session. Care should be taken to ensure that all other connections have
|
||||
terminated as well since stopping the server may cause lockups on other
|
||||
machines still using the IPX tunneling server.
|
||||
|
||||
The syntax for IPXNET STOPSERVER is:
|
||||
IPXNET STOPSERVER
|
||||
|
||||
IPXNET PING
|
||||
|
||||
IPXNET PING broadcasts a ping request through the IPX tunneled network.
|
||||
In response, all other connected computers will respond to the ping
|
||||
and report the time it took to receive and send the ping message.
|
||||
|
||||
The syntax for IPXNET PING is:
|
||||
IPXNET PING
|
||||
|
||||
IPXNET STATUS
|
||||
|
||||
IPXNET STATUS reports the current state of this DOSBox's sessions
|
||||
IPX tunneling network. For a list of the computers connected to the
|
||||
network use the IPXNET PING command.
|
||||
|
||||
The syntax for IPXNET STATUS is:
|
||||
IPXNET STATUS
|
||||
|
||||
For more information use the /? command line switch with the programs.
|
||||
|
||||
|
||||
|
||||
=============
|
||||
Special Keys:
|
||||
=============
|
||||
|
||||
================
|
||||
5. Special Keys:
|
||||
================
|
||||
|
||||
ALT-ENTER Go full screen and back.
|
||||
CTRL-F5 Save a screenshot.
|
||||
CTRL-F6 Start/Stop recording sound output to a wave file.
|
||||
CTRL-F7 Decrease frameskip.
|
||||
CTRL-F8 Increase frameskip.
|
||||
CTRL-F1 Start the keymapper.
|
||||
CTRL-F4 Swap mounted disk-image (Only used with imgmount).
|
||||
CTRL-F5 Save a screenshot.
|
||||
CTRL-F6 Start/Stop recording sound output to a wave file.
|
||||
CTRL-ALT-F7 Start/Stop recording of OPL commands.
|
||||
CTRL-ALT-F8 Start/Stop the recording of raw MIDI commands.
|
||||
CTRL-F7 Decrease frameskip.
|
||||
CTRL-F8 Increase frameskip.
|
||||
CTRL-F9 Kill dosbox.
|
||||
CTRL-F10 Capture/Release the mouse.
|
||||
CTRL-F11 Slow down emulation (Decrease DOSBox Cycles).
|
||||
CTRL-F12 Speed up emulation (Increase DOSox Cycles).
|
||||
|
||||
These are the default keybindings. They can be changed in the keymapper.
|
||||
|
||||
NOTE: Once you increase your DOSBox cycles beyond your computer's maximum
|
||||
capacity, it will produce the same effect as slowing down the emulation.
|
||||
This maximum will vary from computer to computer, there is no standard.
|
||||
|
||||
====================
|
||||
System requirements:
|
||||
====================
|
||||
|
||||
|
||||
=============
|
||||
6. Keymapper:
|
||||
=============
|
||||
|
||||
When you start the keymapper (either with CTRL-F1 or -startmapper as a
|
||||
commandline argument) you are presented with a virtual keyboard.
|
||||
|
||||
This virtual keyboard corresponds with the keys DOSBox will report to its
|
||||
applications. If you click on a key with your mouse, you can see in the
|
||||
lowerleft corner which key on your keyboard corresponds with it.
|
||||
|
||||
Event: EVENT
|
||||
BIND: BIND
|
||||
Add Del
|
||||
mod1 hold Next
|
||||
mod2
|
||||
mod3
|
||||
|
||||
|
||||
EVENT
|
||||
The key DOSBox will report to the applications being emulated.
|
||||
BIND
|
||||
The key on your keyboard (as reported by SDL) which is connected to the
|
||||
EVENT.
|
||||
mod1,2,3
|
||||
Modfiers. These are keys you need to have pressed as well, while pressing
|
||||
BIND. mod1 = CTRL and mod2 = ALT. These are generally only used when you
|
||||
want to change the special keys of DOSBox.
|
||||
Add
|
||||
Add a new BIND to this EVENT. Basicly add a key from your keyboard which
|
||||
will produce the key EVENT in DOSBox.
|
||||
Del
|
||||
Delete the BIND to this EVENT. If an EVENT has no BINDS than it's not
|
||||
possible to type this key in DOSBox.
|
||||
Next
|
||||
Cycle through the list of keys(BINDS) which map to this EVENT.
|
||||
|
||||
|
||||
Example:
|
||||
Q1. You want to have the X on your keyboard to type a Z in DOSBox.
|
||||
A. With your mouse click on the Z on the keyboard mapper. Click "Add".
|
||||
Now press the X key on your keyboard.
|
||||
|
||||
Q2. If you click "Next" a few times you will notice that the Z on your
|
||||
keyboard also produces an Z in DOSBox.
|
||||
A. Therefore select the Z again and click "Next" till you have the Z on
|
||||
your keyboard. Now click "Del".
|
||||
|
||||
Q3. If you try it out in DOSBox you will notice that pressing X makes ZX
|
||||
appear.
|
||||
A. The X on your keyboard is still mapped to the X as well! Click on
|
||||
the X in the keyboard mapper and search with "Next" till you find the
|
||||
mapped key X. Click "Del".
|
||||
|
||||
|
||||
If you change the default mapping you can save your changes by pressing
|
||||
"Save". DOSBox will save the mapping to location specified in the configfile
|
||||
(mapperfile=mapper.txt). At startup DOSBox will load your mapperfile if it's
|
||||
present in the configfile.
|
||||
|
||||
|
||||
|
||||
=======================
|
||||
7. System requirements:
|
||||
=======================
|
||||
|
||||
Fast machine. My guess would be pentium-2 400+ to get decent emulation
|
||||
of games written for an 286 machine.
|
||||
@ -206,9 +628,10 @@ them to run fast though!! Be sure to read the next section on how to speed
|
||||
it up somewhat.
|
||||
|
||||
|
||||
================================
|
||||
To run resource-demanding games:
|
||||
================================
|
||||
|
||||
===================================
|
||||
8. To run resource-demanding games:
|
||||
===================================
|
||||
|
||||
DOSBox emulates the CPU, the sound and graphic cards, and some other
|
||||
stuff, all at the same time. You can overclock DOSBox by using CTRL+F12, but
|
||||
@ -236,109 +659,31 @@ You can also try to disable the sound through the setup utility of the game
|
||||
to further reduce load on your CPU.
|
||||
|
||||
|
||||
====
|
||||
FAQ:
|
||||
====
|
||||
|
||||
Q: I've got a Z instead of a C at the prompt.
|
||||
A: In DOSBox you can mount directories as drives.
|
||||
In win32: mount c D:\ would give you a C in DOSBox which points
|
||||
at D:\ in win32.
|
||||
In linux: mount c /home/username would give you a C in DOSBox
|
||||
which points at /home/username in Linux.
|
||||
|
||||
Q: The mouse doesn't work.
|
||||
A: Normally dosbox detects the mouse being used by a game. If you click on
|
||||
the screen then it should get locked and work.
|
||||
Sometimes the dosbox mouse detection doesn't work with certain games. You
|
||||
might have to force to lock the mouse then with ctrl-F10.
|
||||
|
||||
Q: The sound stutters.
|
||||
A: You're using too much cpu power to keep dosbox running at the current speed.
|
||||
You can either lower the cycles or skip frames or get a faster machine.
|
||||
|
||||
Q: I can't type \ in DOSBox.
|
||||
A: This is a known problem. It only occurs if your keyboard layout isn't US.
|
||||
Some possible fixes:
|
||||
1. Switch your keyboard layout.
|
||||
2. Use / instead.
|
||||
3. Add the commands you want to execute in dosbox.conf
|
||||
|
||||
Q: The game/application can't find its CD-ROM.
|
||||
A: Be sure to mount the CD-ROM with -t cdrom switch. Also try adding the cor-
|
||||
rect label (-label LABEL). To enable more low-level cdrom support add
|
||||
the following switch to mount: -usecd #, where # is the number of your
|
||||
CD-ROM drive reported by mount -cd. If you run Win32 you can specify -ioctl
|
||||
or -aspi. Look at the description elsewhere in this document for their
|
||||
meaning.
|
||||
|
||||
Q: The game/application runs much too slow!
|
||||
A: Look at the section "To run resource-demanding games" for more information.
|
||||
|
||||
Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ.
|
||||
A: This is possible! Just create a config file: config -writeconf dosbox.conf .
|
||||
Startup your favourite editor and look at all the settings present. To
|
||||
start DOSBox with your new settings: dosbox -conf dosbox.conf
|
||||
|
||||
Q: What sound hardware does DosBox presently emulate?
|
||||
A: DosBox emulates several legacy sound devices:
|
||||
- Internal PC speaker
|
||||
This emulation includes both the tone generator and several forms of digital
|
||||
sound output through the internal speaker.
|
||||
- Creative CMS/Gameblaster
|
||||
The is the first card released by Creative Labs(R). The default configuration places
|
||||
it on port 0x220. It should be noted that enabling this with the Adlib emulation may
|
||||
result in conflicts.
|
||||
- Tandy 3 voice
|
||||
The emulation of this sound hardware is complete with the exception of the noise channel,
|
||||
which is not very well documented and as such is only a best guess as to the sound's accuracy.
|
||||
- Adlib
|
||||
Borrowed from MAME, this emulation is almost perfect and includes the Adlib's ability to almost
|
||||
play digitized sound.
|
||||
- SoundBlaster Pro
|
||||
Coupled with the Adlib, DosBox provides Soundblaster Pro level 8-bit stereo sound.
|
||||
- Disney Soundsource
|
||||
Using the printer port, this sound device outputs digital sound only.
|
||||
- Gravis Ultrasound
|
||||
The emulation of this hardware is nearly complete, though the MIDI capabilities have been left
|
||||
out since an MPU-401 has been emulated in other code.
|
||||
- MPU-401
|
||||
A MIDI passthrough interface is also emulated. This method of sound output will only work when
|
||||
used with a General Midi or MT-32 device.
|
||||
|
||||
|
||||
Q: Great README, but I still don't get it.
|
||||
A: While unlikely this seems to happen. Maybe a look at "The Newbie's
|
||||
pictorial guide to dosbox" located at
|
||||
http://vogons.zetafleet.com/viewforum.php?f=39 might help you.
|
||||
|
||||
For more questions check the site/forum:
|
||||
http://dosbox.sourceforge.net
|
||||
|
||||
|
||||
================
|
||||
The Config File:
|
||||
================
|
||||
===================
|
||||
9. The Config File:
|
||||
===================
|
||||
|
||||
A config file can be generated by CONFIG.COM, which can be found on the
|
||||
internal dosbox Z: drive when you start up dosbox. Look in the internal
|
||||
programs section of the readme for usage of CONFIG.COM.
|
||||
You can edit the generated configfile to customize DOSBox.
|
||||
|
||||
The file is divided into several sections (the names have [] around it).
|
||||
Some sections have options which you can set.
|
||||
# and % indicate comment-lines.
|
||||
The generated configfile contains the current settings. You can alter them and
|
||||
start DOSBox with the -conf switch to load the file and use these settings.
|
||||
|
||||
DOSBox will if no configfile is specified with the -conf switch look in the
|
||||
current directory for dosbox.conf. Then it will look for ~/.dosboxrc (linux),
|
||||
~\dosbox.conf (win32) or "~/Library/Preferences/DOSBox Preferences" (MACOSX).
|
||||
If no configfile is specified with the -conf switch, DOSBox will look in the
|
||||
current directory for dosbox.conf. Then it will look for ~/.dosboxrc (Linux),
|
||||
~\dosbox.conf (Win32) or "~/Library/Preferences/DOSBox Preferences" (MACOSX).
|
||||
|
||||
|
||||
|
||||
==================
|
||||
The Language File:
|
||||
==================
|
||||
======================
|
||||
10. The Language File:
|
||||
======================
|
||||
|
||||
A language file can be generated by CONFIG.COM.
|
||||
Read it and you will hopefully understand how to change it.
|
||||
@ -347,16 +692,19 @@ or you can setup the filename in the config file in the [dosbox] section.
|
||||
There's a language= entry that can be changed with the filename.
|
||||
|
||||
|
||||
====================================
|
||||
Building your own version of DOSBox:
|
||||
====================================
|
||||
|
||||
========================================
|
||||
11. Building your own version of DOSBox:
|
||||
========================================
|
||||
|
||||
Download the source.
|
||||
Check the INSTALL in the source distribution.
|
||||
|
||||
===============
|
||||
Special Thanks:
|
||||
===============
|
||||
|
||||
|
||||
===================
|
||||
12. Special Thanks:
|
||||
===================
|
||||
|
||||
Vlad R. of the vdmsound project for excellent sound blaster info.
|
||||
Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator.
|
||||
@ -366,9 +714,12 @@ Pierre-Yves G
|
||||
Colin Snover for hosting our forum.
|
||||
The Beta Testers.
|
||||
|
||||
========
|
||||
Contact:
|
||||
========
|
||||
|
||||
Harekiet harekiet@zophar.net
|
||||
|
||||
============
|
||||
13. Contact:
|
||||
============
|
||||
|
||||
See the site:
|
||||
http://dosbox.sourceforge.net
|
||||
for an emailaddress (The Crew-page).
|
||||
|
51
acinclude.m4
51
acinclude.m4
@ -1,7 +1,7 @@
|
||||
dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
|
||||
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
|
||||
dnl
|
||||
AC_DEFUN(AM_PATH_SDL,
|
||||
AC_DEFUN([AM_PATH_SDL],
|
||||
[dnl
|
||||
dnl Get the cflags and libraries from the sdl-config script
|
||||
dnl
|
||||
@ -174,7 +174,7 @@ dnl
|
||||
dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified,
|
||||
dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result.
|
||||
dnl
|
||||
AC_DEFUN(AM_PATH_ALSA,
|
||||
AC_DEFUN([AM_PATH_ALSA],
|
||||
[dnl Save the original CFLAGS, LDFLAGS, and LIBS
|
||||
alsa_save_CFLAGS="$CFLAGS"
|
||||
alsa_save_LDFLAGS="$LDFLAGS"
|
||||
@ -305,7 +305,7 @@ AC_SUBST(ALSA_LIBS)
|
||||
|
||||
AH_TOP([
|
||||
/*
|
||||
* Copyright (C) 2002-2003 The DOSBox Team
|
||||
* Copyright (C) 2002-2004 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -331,4 +331,49 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE
|
||||
#define GCC_ATTRIBUTE(x) /* attribute not supported */
|
||||
#endif])
|
||||
|
||||
AH_BOTTOM([
|
||||
typedef double Real64;
|
||||
|
||||
#if SIZEOF_UNSIGNED_CHAR != 1
|
||||
# error "sizeof (unsigned char) != 1"
|
||||
#else
|
||||
typedef unsigned char Bit8u;
|
||||
typedef signed char Bit8s;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_SHORT != 2
|
||||
# error "sizeof (unsigned short) != 2"
|
||||
#else
|
||||
typedef unsigned short Bit16u;
|
||||
typedef signed short Bit16s;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_INT == 4
|
||||
typedef unsigned int Bit32u;
|
||||
typedef signed int Bit32s;
|
||||
#elif SIZEOF_UNSIGNED_LONG == 4
|
||||
typedef unsigned long Bit32u;
|
||||
typedef signed long Bit32s;
|
||||
#else
|
||||
# error "can't find sizeof(type) of 4 bytes!"
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_LONG == 8
|
||||
typedef unsigned long Bit64u;
|
||||
typedef signed long Bit64s;
|
||||
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
|
||||
typedef unsigned long long Bit64u;
|
||||
typedef signed long long Bit64s;
|
||||
#else
|
||||
# error "can't find data type of 8 bytes"
|
||||
#endif
|
||||
|
||||
#if SIZEOF_INT_P == 4
|
||||
typedef Bit32u Bitu;
|
||||
typedef Bit32s Bits;
|
||||
#else
|
||||
typedef Bit64u Bitu;
|
||||
typedef Bit64s Bits;
|
||||
#endif
|
||||
|
||||
])
|
||||
|
51
aclocal.m4
vendored
51
aclocal.m4
vendored
@ -14,7 +14,7 @@
|
||||
dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
|
||||
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
|
||||
dnl
|
||||
AC_DEFUN(AM_PATH_SDL,
|
||||
AC_DEFUN([AM_PATH_SDL],
|
||||
[dnl
|
||||
dnl Get the cflags and libraries from the sdl-config script
|
||||
dnl
|
||||
@ -187,7 +187,7 @@ dnl
|
||||
dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified,
|
||||
dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result.
|
||||
dnl
|
||||
AC_DEFUN(AM_PATH_ALSA,
|
||||
AC_DEFUN([AM_PATH_ALSA],
|
||||
[dnl Save the original CFLAGS, LDFLAGS, and LIBS
|
||||
alsa_save_CFLAGS="$CFLAGS"
|
||||
alsa_save_LDFLAGS="$LDFLAGS"
|
||||
@ -318,7 +318,7 @@ AC_SUBST(ALSA_LIBS)
|
||||
|
||||
AH_TOP([
|
||||
/*
|
||||
* Copyright (C) 2002-2003 The DOSBox Team
|
||||
* Copyright (C) 2002-2004 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -344,7 +344,52 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE
|
||||
#define GCC_ATTRIBUTE(x) /* attribute not supported */
|
||||
#endif])
|
||||
|
||||
AH_BOTTOM([
|
||||
typedef double Real64;
|
||||
|
||||
#if SIZEOF_UNSIGNED_CHAR != 1
|
||||
# error "sizeof (unsigned char) != 1"
|
||||
#else
|
||||
typedef unsigned char Bit8u;
|
||||
typedef signed char Bit8s;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_SHORT != 2
|
||||
# error "sizeof (unsigned short) != 2"
|
||||
#else
|
||||
typedef unsigned short Bit16u;
|
||||
typedef signed short Bit16s;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_INT == 4
|
||||
typedef unsigned int Bit32u;
|
||||
typedef signed int Bit32s;
|
||||
#elif SIZEOF_UNSIGNED_LONG == 4
|
||||
typedef unsigned long Bit32u;
|
||||
typedef signed long Bit32s;
|
||||
#else
|
||||
# error "can't find sizeof(type) of 4 bytes!"
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_LONG == 8
|
||||
typedef unsigned long Bit64u;
|
||||
typedef signed long Bit64s;
|
||||
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
|
||||
typedef unsigned long long Bit64u;
|
||||
typedef signed long long Bit64s;
|
||||
#else
|
||||
# error "can't find data type of 8 bytes"
|
||||
#endif
|
||||
|
||||
#if SIZEOF_INT_P == 4
|
||||
typedef Bit32u Bitu;
|
||||
typedef Bit32s Bits;
|
||||
#else
|
||||
typedef Bit64u Bitu;
|
||||
typedef Bit64s Bits;
|
||||
#endif
|
||||
|
||||
])
|
||||
|
||||
# Do all the work for Automake. -*- Autoconf -*-
|
||||
|
||||
|
769
config.guess
vendored
769
config.guess
vendored
File diff suppressed because it is too large
Load Diff
82
config.h.in
82
config.h.in
@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002-2003 The DOSBox Team
|
||||
* Copyright (C) 2002-2004 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -26,6 +26,9 @@
|
||||
/* Define to 1 to enable internal debugger, requires libcurses */
|
||||
#undef C_DEBUG
|
||||
|
||||
/* Define to 1 if you want serial passthrough support (Win32 only). */
|
||||
#undef C_DIRECTSERIAL
|
||||
|
||||
/* Define to 1 to use x86 dynamic cpu core */
|
||||
#undef C_DYNAMIC_X86
|
||||
|
||||
@ -41,12 +44,21 @@
|
||||
/* The type of cpu this host has */
|
||||
#undef C_HOSTCPU
|
||||
|
||||
/* Define to 1 to enable IPX over Internet networking, requires SDL_net */
|
||||
#undef C_IPX
|
||||
|
||||
/* Define to 1 to enable internal modem support, requires SDL_net */
|
||||
#undef C_MODEM
|
||||
|
||||
/* Define to 1 to use opengl display output support */
|
||||
#undef C_OPENGL
|
||||
|
||||
/* Define to 1 to enable SDL_sound support */
|
||||
#undef C_SDL_SOUND
|
||||
|
||||
/* Define to 1 if you have setpriority support */
|
||||
#undef C_SET_PRIORITY
|
||||
|
||||
/* Define to 1 to enable screenshots, requires libpng */
|
||||
#undef C_SSHOT
|
||||
|
||||
@ -59,6 +71,9 @@
|
||||
/* Define to 1 to use ALSA for MIDI */
|
||||
#undef HAVE_ALSA
|
||||
|
||||
/* Define to 1 if you have the <ddraw.h> header file. */
|
||||
#undef HAVE_DDRAW_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
@ -113,6 +128,24 @@
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* The size of a `int *', as computed by sizeof. */
|
||||
#undef SIZEOF_INT_P
|
||||
|
||||
/* The size of a `unsigned char', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_CHAR
|
||||
|
||||
/* The size of a `unsigned int', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_INT
|
||||
|
||||
/* The size of a `unsigned long', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_LONG
|
||||
|
||||
/* The size of a `unsigned long long', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_LONG_LONG
|
||||
|
||||
/* The size of a `unsigned short', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_SHORT
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
@ -145,3 +178,50 @@
|
||||
#else
|
||||
#define GCC_ATTRIBUTE(x) /* attribute not supported */
|
||||
#endif
|
||||
|
||||
|
||||
typedef double Real64;
|
||||
|
||||
#if SIZEOF_UNSIGNED_CHAR != 1
|
||||
# error "sizeof (unsigned char) != 1"
|
||||
#else
|
||||
typedef unsigned char Bit8u;
|
||||
typedef signed char Bit8s;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_SHORT != 2
|
||||
# error "sizeof (unsigned short) != 2"
|
||||
#else
|
||||
typedef unsigned short Bit16u;
|
||||
typedef signed short Bit16s;
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_INT == 4
|
||||
typedef unsigned int Bit32u;
|
||||
typedef signed int Bit32s;
|
||||
#elif SIZEOF_UNSIGNED_LONG == 4
|
||||
typedef unsigned long Bit32u;
|
||||
typedef signed long Bit32s;
|
||||
#else
|
||||
# error "can't find sizeof(type) of 4 bytes!"
|
||||
#endif
|
||||
|
||||
#if SIZEOF_UNSIGNED_LONG == 8
|
||||
typedef unsigned long Bit64u;
|
||||
typedef signed long Bit64s;
|
||||
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
|
||||
typedef unsigned long long Bit64u;
|
||||
typedef signed long long Bit64s;
|
||||
#else
|
||||
# error "can't find data type of 8 bytes"
|
||||
#endif
|
||||
|
||||
#if SIZEOF_INT_P == 4
|
||||
typedef Bit32u Bitu;
|
||||
typedef Bit32s Bits;
|
||||
#else
|
||||
typedef Bit64u Bitu;
|
||||
typedef Bit64s Bits;
|
||||
#endif
|
||||
|
||||
|
||||
|
57
config.sub
vendored
57
config.sub
vendored
@ -1,9 +1,9 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2004-01-05'
|
||||
timestamp='2004-06-24'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@ -70,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
@ -145,7 +145,7 @@ case $os in
|
||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis)
|
||||
-apple | -axis | -knuth | -cray)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
@ -237,7 +237,7 @@ case $basic_machine in
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| m32r | m68000 | m68k | m88k | mcore \
|
||||
| m32r | m32rle | m68000 | m68k | m88k | mcore \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
@ -262,7 +262,7 @@ case $basic_machine in
|
||||
| pyramid \
|
||||
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
|
||||
| strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
@ -300,7 +300,7 @@ case $basic_machine in
|
||||
| avr-* \
|
||||
| bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | cydra-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
|
||||
@ -308,7 +308,7 @@ case $basic_machine in
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| m32r-* \
|
||||
| m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | mcore-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
@ -326,8 +326,9 @@ case $basic_machine in
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| msp430-* \
|
||||
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
@ -336,7 +337,7 @@ case $basic_machine in
|
||||
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
||||
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tron-* \
|
||||
@ -363,6 +364,9 @@ case $basic_machine in
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
basic_machine=m68010-adobe
|
||||
os=-scout
|
||||
@ -442,12 +446,24 @@ case $basic_machine in
|
||||
basic_machine=j90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
craynv)
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16c)
|
||||
basic_machine=cr16c-unknown
|
||||
os=-elf
|
||||
;;
|
||||
crds | unos)
|
||||
basic_machine=m68k-crds
|
||||
;;
|
||||
cris | cris-* | etrax*)
|
||||
basic_machine=cris-axis
|
||||
;;
|
||||
crx)
|
||||
basic_machine=crx-unknown
|
||||
os=-elf
|
||||
;;
|
||||
da30 | da30-*)
|
||||
basic_machine=m68k-da30
|
||||
;;
|
||||
@ -648,10 +664,6 @@ case $basic_machine in
|
||||
mips3*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
|
||||
;;
|
||||
mmix*)
|
||||
basic_machine=mmix-knuth
|
||||
os=-mmixware
|
||||
;;
|
||||
monitor)
|
||||
basic_machine=m68k-rom68k
|
||||
os=-coff
|
||||
@ -732,10 +744,6 @@ case $basic_machine in
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
nv1)
|
||||
basic_machine=nv1-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
@ -1048,6 +1056,9 @@ case $basic_machine in
|
||||
romp)
|
||||
basic_machine=romp-ibm
|
||||
;;
|
||||
mmix)
|
||||
basic_machine=mmix-knuth
|
||||
;;
|
||||
rs6000)
|
||||
basic_machine=rs6000-ibm
|
||||
;;
|
||||
@ -1070,7 +1081,7 @@ case $basic_machine in
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparc | sparcv9 | sparcv9b)
|
||||
sparc | sparcv8 | sparcv9 | sparcv9b)
|
||||
basic_machine=sparc-sun
|
||||
;;
|
||||
cydra)
|
||||
@ -1143,8 +1154,9 @@ case $os in
|
||||
| -aos* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* \
|
||||
@ -1362,6 +1374,9 @@ case $basic_machine in
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
os=-proelf
|
||||
;;
|
||||
|
39
configure.in
39
configure.in
@ -1,5 +1,5 @@
|
||||
dnl Init.
|
||||
AC_INIT(dosbox,0.61)
|
||||
AC_INIT(dosbox,0.62)
|
||||
AC_PREREQ(2.50)
|
||||
AC_CONFIG_SRCDIR(README)
|
||||
|
||||
@ -26,7 +26,7 @@ AM_PATH_SDL($SDL_VERSION,
|
||||
AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
|
||||
)
|
||||
LIBS="$LIBS $SDL_LIBS"
|
||||
CXXFLAGS="$CXXFLAGS $SDL_CFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $SDL_CFLAGS"
|
||||
|
||||
dnl Checks for header files.
|
||||
|
||||
@ -35,7 +35,12 @@ AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_TYPE_SIZE_T
|
||||
AC_STRUCT_TM
|
||||
|
||||
AC_CHECK_SIZEOF(unsigned char)
|
||||
AC_CHECK_SIZEOF(unsigned short)
|
||||
AC_CHECK_SIZEOF(unsigned int)
|
||||
AC_CHECK_SIZEOF(unsigned long)
|
||||
AC_CHECK_SIZEOF(unsigned long long)
|
||||
AC_CHECK_SIZEOF(int *)
|
||||
|
||||
AC_MSG_CHECKING(if environ can be included)
|
||||
AC_TRY_LINK([#include <unistd.h>
|
||||
@ -143,13 +148,15 @@ else
|
||||
fi
|
||||
|
||||
AH_TEMPLATE(C_MODEM,[Define to 1 to enable internal modem support, requires SDL_net])
|
||||
AC_CHECK_HEADER(SDL/SDL_net.h,have_sdl_net_h=yes,)
|
||||
AH_TEMPLATE(C_IPX,[Define to 1 to enable IPX over Internet networking, requires SDL_net])
|
||||
AC_CHECK_HEADER(SDL_net.h,have_sdl_net_h=yes,)
|
||||
AC_CHECK_LIB(SDL_net, SDLNet_Init, have_sdl_net_lib=yes, , )
|
||||
if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then
|
||||
LIBS="$LIBS -lSDL_net"
|
||||
AC_DEFINE(C_MODEM,1)
|
||||
AC_DEFINE(C_IPX,1)
|
||||
else
|
||||
AC_MSG_WARN([Can't find SDL_net, internal modem disabled])
|
||||
AC_MSG_WARN([Can't find SDL_net, internal modem and ipx disabled])
|
||||
fi
|
||||
|
||||
AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support])
|
||||
@ -170,10 +177,32 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
AH_TEMPLATE(C_SDL_SOUND,[Define to 1 to enable SDL_sound support])
|
||||
AC_CHECK_HEADER(SDL/SDL_sound.h,have_SDL_sound_h=yes,)
|
||||
AC_CHECK_LIB(SDL_sound, Sound_Init, have_SDL_sound_lib=yes,,)
|
||||
if test x$have_SDL_sound_h = xyes -a x$have_SDL_sound_lib = xyes ; then
|
||||
LIBS="$LIBS -lSDL_sound"
|
||||
AC_DEFINE(C_SDL_SOUND,1)
|
||||
else
|
||||
AC_MSG_WARN([Can't find libSDL_sound, libSDL_sound support disabled])
|
||||
fi
|
||||
|
||||
AH_TEMPLATE(C_SET_PRIORITY,[Define to 1 if you have setpriority support])
|
||||
AC_MSG_CHECKING(for setpriority support)
|
||||
AC_LINK_IFELSE([
|
||||
#include <sys/resource.h>
|
||||
int main(int argc,char * argv[]) {
|
||||
return setpriority (PRIO_PROCESS, 0,PRIO_MIN+PRIO_MAX);
|
||||
};
|
||||
],AC_MSG_RESULT(yes);AC_DEFINE(C_SET_PRIORITY,1),AC_MSG_RESULT(no))
|
||||
|
||||
|
||||
dnl Some host detection and actions for them
|
||||
case "$target" in
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
LIBS="$LIBS -lwinmm"
|
||||
AC_CHECK_HEADERS(ddraw.h)
|
||||
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32 only).])
|
||||
;;
|
||||
*-*-darwin*)
|
||||
dnl We have a problem here: both MacOS X and Darwin report
|
||||
|
@ -1,16 +1,20 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH DOSBOX 1 "October 5, 2003"
|
||||
.TH DOSBOX 1 "Sept 23, 2004"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.SH NAME
|
||||
dosbox \- an x86/DOS emulator with sound/graphics
|
||||
.SH SYNOPSIS
|
||||
.B dosbox
|
||||
.B [\-fullscreen]
|
||||
.B [\-startmapper]
|
||||
.BI "[\-conf " configfile ]
|
||||
.BI "[\-lang " langfile ]
|
||||
.B [file]
|
||||
.BI "[\-c " command ]
|
||||
.B [\-exit]
|
||||
.BI "[\-machine " machinetype ]
|
||||
.LP
|
||||
.B dosbox -version
|
||||
.SH DESCRIPTION
|
||||
This manual page briefly documents
|
||||
.BR "dosbox" ", an x86/DOS emulator."
|
||||
@ -22,6 +26,9 @@ A summary of options is included below.
|
||||
.B \-fullscreen
|
||||
.RB "Start " dosbox " in fullscreen mode."
|
||||
.TP
|
||||
.B \-startmapper
|
||||
.RB "Start the internal keymapper on startup of " dosbox ". You can use it to change the keys " dosbox " uses."
|
||||
.TP
|
||||
.BI \-c " command"
|
||||
.RI "Runs the specified " command " before running "
|
||||
.BR file .
|
||||
@ -38,6 +45,13 @@ A summary of options is included below.
|
||||
.TP
|
||||
.B \-exit
|
||||
.BR dosbox " will exit after running the program specified by " file .
|
||||
.TP
|
||||
.BI \-machine " machinetype
|
||||
.RB "Setup " dosbox " to emulate a specific type of machine."
|
||||
.RI "Valid choices are: " "hercules, cga, tandy, vga(default)".
|
||||
.TP
|
||||
.B \-version
|
||||
Output version information and exit. Useful for frontends.
|
||||
.SH "INTERNAL COMMANDS"
|
||||
.B dosbox
|
||||
supports most of the DOS commands found in command.com. In addition, the
|
||||
@ -46,7 +60,7 @@ following extra commands are available:
|
||||
.BI "MOUNT [\-t " type "] [\-size " size ]
|
||||
.I driveletter sourcedirectory
|
||||
.B [\-aspi] [\-ioctl]
|
||||
.BI "[\-usecd " number "] [\-label " drivelabel ]
|
||||
.BI "[\-usecd " number "] [\-label " drivelabel "] [\-freesize " freesize ]
|
||||
.LP
|
||||
.B MOUNT \-cd
|
||||
.LP
|
||||
@ -63,7 +77,11 @@ The local directory you want to have inside dosbox.
|
||||
Type of the mounted directory. Supported are: dir (standard), floppy, cdrom.
|
||||
.TP
|
||||
.BI \-size " drivesize"
|
||||
Sets the size of the drive.
|
||||
Sets the size of the drive. See the examples in the README for details.
|
||||
.TP
|
||||
.BI \-freesize " freesize"
|
||||
Sets the amount of free space available on a drive in MB's. This is a more
|
||||
.RB "simple version of " \-size .
|
||||
.TP
|
||||
.BI \-label " drivelabel"
|
||||
.RI "Sets the name of the drive to " drivelabel ". Needed on some"
|
||||
@ -123,6 +141,30 @@ The amount of memory to eat up (in kb). Example -32, -64 or -128
|
||||
.B \-f
|
||||
Frees all memory eaten up by loadfix.
|
||||
.RE
|
||||
.TP
|
||||
.B IMGMOUNT
|
||||
.LP
|
||||
.RB "A utility to mount disk images and CD-ROM images in " DOSBox .
|
||||
.TP
|
||||
.RB "Read the " README " of " DOSBox " for the full and correct syntax."
|
||||
.RE
|
||||
.TP
|
||||
.B BOOT
|
||||
.LP
|
||||
.RB "Boot will start floppy images or hard disk images independent of the operating system emulation offered by " DOSBox ". This will allow you to play booter floppies or boot to other operating systems inside "DOSBox .
|
||||
.TP
|
||||
.RB "Read the " README " of " DOSBox " for the full and correct syntax."
|
||||
.RE
|
||||
.TP
|
||||
.B IPX
|
||||
.LP
|
||||
.RB "You need to enable IPX networking in the configuration file of "DOSBox .
|
||||
.RB "All of the IPX networking is managed through the internal " DOSBox " program
|
||||
.BR IPXNET ". For help on the IPX networking from inside " DOSBox ", type"
|
||||
.BR "IPXNET HELP" " and the program will list out the commands and relevant documentation."
|
||||
.TP
|
||||
.RB "Read the " README " of " DOSBox " for the full and correct syntax."
|
||||
.RE
|
||||
.SH FILES
|
||||
Configuration and language files use a format similar to Windows .ini files. If a file named
|
||||
.BR dosbox.conf " is found in the current directory, it will be automatically loaded."
|
||||
@ -130,10 +172,18 @@ Configuration and language files use a format similar to Windows .ini files. If
|
||||
.TP 12m
|
||||
.IP ALT\-ENTER
|
||||
Go full screen and back.
|
||||
.IP CTRL\-F1
|
||||
Start the keymapper.
|
||||
.IP CTRL\-F4
|
||||
Swap mounted disk-image (Only used with imgmount).
|
||||
.IP CTRL\-F5
|
||||
Save a screenshot.
|
||||
.IP CTRL\-F6
|
||||
Start/Stop recording sound output to a wave file.
|
||||
.IP CTRL\-ALT\-F7
|
||||
Start/Stop recording of OPL commands.
|
||||
.IP CTRL\-ALT\-F8
|
||||
Start/Stop the recording of raw MIDI commands.
|
||||
.IP CTRL\-F7
|
||||
Decrease frameskip.
|
||||
.IP CTRL\-F8
|
||||
@ -147,8 +197,9 @@ Slow down emulation (Increase DOSBox Cycles).
|
||||
.IP CTRL\-F12
|
||||
Speed up emulation (Decrease DOSBox Cycles).
|
||||
.PP
|
||||
.B "Note: "
|
||||
Once you increase your DOSBox cycles beyond your computer's maximum
|
||||
These are the default keybindings. They can be changed in the keymapper.
|
||||
.PP
|
||||
.BR "Note: " "Once you increase your " DOSBox " cycles beyond your computer's maximum
|
||||
capacity, it will produce the same effect as slowing down the emulation.
|
||||
This maximum will vary from computer to computer, there is no standard.
|
||||
.SH "SYSTEM REQUIREMENTS"
|
||||
|
@ -12,8 +12,11 @@ fpu.h \
|
||||
hardware.h \
|
||||
inout.h \
|
||||
joystick.h \
|
||||
ipx.h \
|
||||
ipxserver.h \
|
||||
keyboard.h \
|
||||
logging.h \
|
||||
mapper.h \
|
||||
mem.h \
|
||||
mixer.h \
|
||||
modules.h \
|
||||
|
@ -143,8 +143,11 @@ fpu.h \
|
||||
hardware.h \
|
||||
inout.h \
|
||||
joystick.h \
|
||||
ipx.h \
|
||||
ipxserver.h \
|
||||
keyboard.h \
|
||||
logging.h \
|
||||
mapper.h \
|
||||
mem.h \
|
||||
mixer.h \
|
||||
modules.h \
|
||||
|
@ -9,13 +9,16 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _BIOS_H_
|
||||
#define _BIOS_H_
|
||||
|
||||
#define BIOS_BASE_ADDRESS_COM1 0x400
|
||||
#define BIOS_BASE_ADDRESS_COM2 0x402
|
||||
#define BIOS_BASE_ADDRESS_COM3 0x404
|
||||
@ -88,6 +91,8 @@
|
||||
#define BIOS_WAIT_FLAG_POINTER 0x498
|
||||
#define BIOS_WAIT_FLAG_COUNT 0x49c
|
||||
#define BIOS_WAIT_FLAG_ACTIVE 0x4a0
|
||||
#define BIOS_WAIT_FLAG_TEMP 0x4a1
|
||||
|
||||
|
||||
#define BIOS_PRINT_SCREEN_FLAG 0x500
|
||||
|
||||
@ -96,23 +101,57 @@
|
||||
/* The Section handling Bios Disk Access */
|
||||
#define BIOS_MAX_DISK 10
|
||||
|
||||
class BIOS_Disk {
|
||||
public:
|
||||
virtual Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0;
|
||||
virtual Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data)=0;
|
||||
struct diskGeo {
|
||||
Bit32u ksize; /* Size in kilobytes */
|
||||
Bit16u secttrack; /* Sectors per track */
|
||||
Bit16u headscyl; /* Heads per cylinder */
|
||||
Bit16u cylcount; /* Cylinders per side */
|
||||
Bit16u biosval; /* Type to return from BIOS */
|
||||
};
|
||||
|
||||
class imageDisk : public BIOS_Disk {
|
||||
extern diskGeo DiskGeometryList[];
|
||||
|
||||
#include <stdio.h>
|
||||
#include "mem.h"
|
||||
#include "dos_inc.h"
|
||||
|
||||
class imageDisk {
|
||||
public:
|
||||
Bit8u Read_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data);
|
||||
Bit8u Write_Sector(Bit8u * count,Bit8u head,Bit16u cylinder,Bit16u sector,Bit8u * data);
|
||||
imageDisk(char * file);
|
||||
private:
|
||||
Bit16u sector_size;
|
||||
Bit16u heads,cylinders,sectors;
|
||||
Bit8u * image;
|
||||
Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
|
||||
Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
|
||||
Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
|
||||
Bit8u Write_AbsoluteSector(Bit32u sectnum, void * data);
|
||||
|
||||
void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
|
||||
void Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize);
|
||||
Bit8u GetBiosType(void);
|
||||
Bit32u getSectSize(void);
|
||||
imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
|
||||
~imageDisk() { if(diskimg != NULL) { fclose(diskimg); } };
|
||||
|
||||
bool hardDrive;
|
||||
bool active;
|
||||
FILE *diskimg;
|
||||
Bit8u diskname[512];
|
||||
Bit8u floppytype;
|
||||
|
||||
Bit32u sector_size;
|
||||
Bit32u heads,cylinders,sectors;
|
||||
};
|
||||
|
||||
void updateDPT(void);
|
||||
|
||||
#define MAX_HDD_IMAGES 2
|
||||
|
||||
extern imageDisk *imageDiskList[2 + MAX_HDD_IMAGES];
|
||||
extern imageDisk *diskSwap[20];
|
||||
extern Bits swapPosition;
|
||||
extern Bit16u imgDTASeg; /* Real memory location of temporary DTA pointer for fat image disk access */
|
||||
extern RealPt imgDTAPtr; /* Real memory location of temporary DTA pointer for fat image disk access */
|
||||
extern DOS_DTA *imgDTA;
|
||||
|
||||
void swapInDisks(void);
|
||||
void swapInNextDisk(void);
|
||||
|
||||
void BIOS_ZeroExtendedSize(void);
|
||||
void char_out(Bit8u chr,Bit32u att,Bit8u page);
|
||||
@ -123,4 +162,4 @@ void INT2F_StartUp(void);
|
||||
void INT33_StartUp(void);
|
||||
void INT13_StartUp(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -35,6 +35,7 @@ extern CPU_Decoder * cpudecoder;
|
||||
|
||||
Bits CPU_Core_Normal_Run(void);
|
||||
Bits CPU_Core_Normal_Trap_Run(void);
|
||||
Bits CPU_Core_Simple_Run(void);
|
||||
Bits CPU_Core_Full_Run(void);
|
||||
Bits CPU_Core_Dyn_X86_Run(void);
|
||||
|
||||
@ -52,7 +53,6 @@ void CPU_SLDT(Bitu & selector);
|
||||
void CPU_SIDT(Bitu & limit,Bitu & base);
|
||||
void CPU_SGDT(Bitu & limit,Bitu & base);
|
||||
|
||||
|
||||
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel);
|
||||
void CPU_LAR(Bitu selector,Bitu & ar);
|
||||
void CPU_LSL(Bitu selector,Bitu & limit);
|
||||
@ -61,35 +61,44 @@ bool CPU_SET_CRX(Bitu cr,Bitu value);
|
||||
Bitu CPU_GET_CRX(Bitu cr);
|
||||
|
||||
void CPU_SMSW(Bitu & word);
|
||||
bool CPU_LMSW(Bitu word);
|
||||
Bitu CPU_LMSW(Bitu word);
|
||||
|
||||
void CPU_VERR(Bitu selector);
|
||||
void CPU_VERW(Bitu selector);
|
||||
|
||||
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen=0);
|
||||
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen=0);
|
||||
void CPU_RET(bool use32,Bitu bytes,Bitu opLen=0);
|
||||
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
|
||||
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
|
||||
void CPU_RET(bool use32,Bitu bytes,Bitu oldeip);
|
||||
void CPU_IRET(bool use32,Bitu oldeip);
|
||||
void CPU_HLT(Bitu oldeip);
|
||||
|
||||
bool CPU_POPF(Bitu use32);
|
||||
bool CPU_PUSHF(Bitu use32);
|
||||
bool CPU_CLI(void);
|
||||
bool CPU_STI(void);
|
||||
|
||||
bool CPU_IO_Exception(Bitu port,Bitu size);
|
||||
void CPU_RunException(void);
|
||||
|
||||
void CPU_ENTER(bool use32,Bitu bytes,Bitu level);
|
||||
|
||||
#define CPU_INT_SOFTWARE 0x1
|
||||
#define CPU_INT_EXCEPTION 0x2
|
||||
#define CPU_INT_HAS_ERROR 0x4
|
||||
|
||||
|
||||
void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen=0);
|
||||
void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip);
|
||||
INLINE void CPU_HW_Interrupt(Bitu num) {
|
||||
CPU_Interrupt(num,0);
|
||||
CPU_Interrupt(num,0,reg_eip);
|
||||
}
|
||||
INLINE void CPU_SW_Interrupt(Bitu num,Bitu OpLen) {
|
||||
CPU_Interrupt(num,CPU_INT_SOFTWARE,OpLen);
|
||||
INLINE void CPU_SW_Interrupt(Bitu num,Bitu oldeip) {
|
||||
CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip);
|
||||
}
|
||||
|
||||
bool CPU_PrepareException(Bitu which,Bitu error);
|
||||
void CPU_Exception(Bitu which,Bitu error=0);
|
||||
void CPU_StartException(void);
|
||||
void CPU_SetupException(Bitu which,Bitu error=0);
|
||||
|
||||
void CPU_IRET(bool use32);
|
||||
bool CPU_SetSegGeneral(SegNames seg,Bitu value);
|
||||
void CPU_HLT(Bitu opLen);
|
||||
bool CPU_PopSeg(SegNames seg,bool use32);
|
||||
|
||||
void CPU_CPUID(void);
|
||||
Bitu CPU_Pop16(void);
|
||||
@ -407,5 +416,6 @@ INLINE void CPU_SetFlagsw(Bitu word) {
|
||||
CPU_SetFlags(word,mask);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: cross.h,v 1.7 2004/02/02 19:22:23 qbix79 Exp $ */
|
||||
/* $Id: cross.h,v 1.11 2004/09/16 21:46:03 qbix79 Exp $ */
|
||||
|
||||
#ifndef _CROSS_H
|
||||
#define _CROSS_H
|
||||
@ -29,6 +29,8 @@
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#define LONGTYPE(a) a##i64
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#else /* LINUX / GCC */
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
@ -39,7 +41,7 @@
|
||||
|
||||
|
||||
#if defined (WIN32) /* Win 32 */
|
||||
#define CROSS_FILENAME(blah) {if(blah && *blah && (blah[strlen(blah)-1] == '\\')) strcat(blah,".");}
|
||||
#define CROSS_FILENAME(blah)
|
||||
#define CROSS_FILESPLIT '\\'
|
||||
#define F_OK 0
|
||||
#else
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
188
include/dma.h
188
include/dma.h
@ -9,187 +9,85 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: dma.h,v 1.9 2004/01/10 14:03:33 qbix79 Exp $ */
|
||||
/* $Id: dma.h,v 1.12 2004/08/04 09:12:50 qbix79 Exp $ */
|
||||
|
||||
#ifndef __DMA_H
|
||||
#define __DMA_H
|
||||
|
||||
#include "mem.h"
|
||||
enum DMAEvent {
|
||||
DMA_REACHED_TC,
|
||||
DMA_MASKED,
|
||||
DMA_UNMASKED,
|
||||
DMA_TRANSFEREND
|
||||
};
|
||||
|
||||
#define DMA_MODE_DEMAND 0
|
||||
#define DMA_MODE_SINGLE 1
|
||||
#define DMA_MODE_BLOCK 2
|
||||
#define DMA_MODE_CASCADE 3
|
||||
|
||||
#define DMA_BASEADDR 0
|
||||
#define DMA_TRANSCOUNT 1
|
||||
#define DMA_PAGEREG 2
|
||||
|
||||
#define DMA_CMDREG 0
|
||||
#define DMA_MODEREG 1
|
||||
#define DMA_CLEARREG 2
|
||||
#define DMA_DMACREG 3
|
||||
#define DMA_CLRMASKREG 4
|
||||
#define DMA_SINGLEREG 5
|
||||
#define DMA_WRITEALLREG 6
|
||||
|
||||
static Bit8u ChannelPorts [3][8] = { 0x00, 0x02, 0x04, 0x06, 0xff, 0xc4, 0xc8, 0xcc,
|
||||
0x01, 0x03, 0x05, 0x07, 0xff, 0xc6, 0xca, 0xce,
|
||||
0x87, 0x83, 0x81, 0x82, 0xff, 0x8b, 0x89, 0x8a };
|
||||
|
||||
static Bit8u ControllerPorts [2][7] = { 0x08, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0xf,
|
||||
0xd0, 0xd6, 0xd8, 0xda, 0xdc, 0xd4, 0xde };
|
||||
|
||||
|
||||
typedef void (* DMA_EnableCallBack)(bool enable);
|
||||
|
||||
typedef void (* DMA_NewCallBack)(void *useChannel, bool tc);
|
||||
|
||||
void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback);
|
||||
|
||||
void DMA_CheckEnabled(void * usechan);
|
||||
|
||||
Bitu DMA_8_Read(Bitu channel,Bit8u * buffer,Bitu count);
|
||||
Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count);
|
||||
|
||||
Bitu DMA_16_Read(Bitu channel,Bit8u * buffer,Bitu count);
|
||||
Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count);
|
||||
|
||||
extern Bit8u read_dmaB(Bit32u port);
|
||||
extern Bit16u read_dmaW(Bit32u port);
|
||||
|
||||
extern void write_dmaB(Bit32u port,Bit8u val);
|
||||
extern void write_dmaW(Bit32u port,Bit16u val);
|
||||
class DmaChannel;
|
||||
typedef void (* DMA_CallBack)(DmaChannel * chan,DMAEvent event);
|
||||
|
||||
class DmaController {
|
||||
public:
|
||||
bool flipflop;
|
||||
Bit8u ctrlnum;
|
||||
Bit8u chanbase;
|
||||
public:
|
||||
|
||||
DmaController(Bit8u num) {
|
||||
int i;
|
||||
for(i=0;i<7;i++) {
|
||||
IO_RegisterReadBHandler(ControllerPorts[num][i],read_dmaB);
|
||||
IO_RegisterReadWHandler(ControllerPorts[num][i],read_dmaW);
|
||||
|
||||
IO_RegisterWriteBHandler(ControllerPorts[num][i],write_dmaB);
|
||||
IO_RegisterWriteWHandler(ControllerPorts[num][i],write_dmaW);
|
||||
}
|
||||
flipflop = true;
|
||||
flipflop = false;
|
||||
ctrlnum = num;
|
||||
chanbase = num * 4;
|
||||
}
|
||||
|
||||
Bit16u portRead(Bit32u port, bool eightbit);
|
||||
void portWrite(Bit32u port, Bit16u val, bool eightbit);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DmaChannel {
|
||||
public:
|
||||
|
||||
Bit8u channum;
|
||||
Bit32u pagebase;
|
||||
Bit16u baseaddr;
|
||||
Bit16u current_addr;
|
||||
Bit16u pageaddr;
|
||||
PhysPt physaddr;
|
||||
PhysPt curraddr;
|
||||
Bit32s transcnt;
|
||||
Bit32s currcnt;
|
||||
DmaController *myController;
|
||||
bool DMA16;
|
||||
bool addr_changed;
|
||||
public:
|
||||
Bit8u dmamode;
|
||||
bool dir;
|
||||
Bit16u curraddr;
|
||||
Bit16u basecnt;
|
||||
Bit16u currcnt;
|
||||
Bit8u channum;
|
||||
Bit8u pagenum;
|
||||
Bit8u DMA16;
|
||||
bool increment;
|
||||
bool autoinit;
|
||||
Bit8u trantype;
|
||||
bool masked;
|
||||
bool enabled;
|
||||
DMA_EnableCallBack enable_callback;
|
||||
DMA_NewCallBack newcallback;
|
||||
bool tcount;
|
||||
DMA_CallBack callback;
|
||||
|
||||
DmaChannel(Bit8u num, DmaController *useController, bool sb) {
|
||||
int i;
|
||||
masked = true;
|
||||
enabled = false;
|
||||
enable_callback = NULL;
|
||||
newcallback = NULL;
|
||||
if(num == 4) return;
|
||||
addr_changed=false;
|
||||
|
||||
for(i=0;i<3;i++) {
|
||||
IO_RegisterReadBHandler(ChannelPorts[i][num],read_dmaB);
|
||||
IO_RegisterReadWHandler(ChannelPorts[i][num],read_dmaW);
|
||||
|
||||
IO_RegisterWriteBHandler(ChannelPorts[i][num],write_dmaB);
|
||||
IO_RegisterWriteWHandler(ChannelPorts[i][num],write_dmaW);
|
||||
}
|
||||
myController = useController;
|
||||
channum = num;
|
||||
DMA16 = sb;
|
||||
baseaddr = 0;
|
||||
pageaddr = 0;
|
||||
physaddr = 0;
|
||||
curraddr = 0;
|
||||
transcnt = 0;
|
||||
currcnt = 0;
|
||||
dir = false;
|
||||
autoinit = false;
|
||||
DmaChannel(Bit8u num, bool dma16);
|
||||
void DoCallBack(DMAEvent event) {
|
||||
if (callback) (*callback)(this,event);
|
||||
}
|
||||
|
||||
void RegisterCallback(DMA_NewCallBack useCallBack) { newcallback = useCallBack; }
|
||||
|
||||
void reset(void) {
|
||||
addr_changed=false;
|
||||
curraddr = physaddr;
|
||||
currcnt = transcnt+1;
|
||||
current_addr = baseaddr;
|
||||
//LOG(LOG_DMA,LOG_NORMAL)("Setup at address %X:%X count %X",pageaddr,baseaddr,currcnt);
|
||||
void SetMask(bool _mask) {
|
||||
masked=_mask;
|
||||
DoCallBack(masked ? DMA_MASKED : DMA_UNMASKED);
|
||||
}
|
||||
|
||||
void MakeCallback(bool tc) {
|
||||
if (newcallback != NULL) {
|
||||
if(tc) {
|
||||
(*newcallback)(this, true);
|
||||
} else {
|
||||
if ((enabled) && (!masked) && (transcnt!=0)) {
|
||||
(*newcallback)(this, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void Register_Callback(DMA_CallBack _cb) {
|
||||
callback = _cb;
|
||||
SetMask(masked);
|
||||
}
|
||||
|
||||
Bit32u Read(Bit32s requestsize, Bit8u * buffer);
|
||||
|
||||
Bit32u Write(Bit32s requestsize, Bit8u * buffer);
|
||||
|
||||
void calcPhys(void);
|
||||
|
||||
Bit16u portRead(Bit32u port, bool eightbit);
|
||||
|
||||
void portWrite(Bit32u port, Bit16u val, bool eightbit);
|
||||
|
||||
// Notify channel when mask changes
|
||||
void Notify(void);
|
||||
|
||||
void ReachedTC(void) {
|
||||
tcount=true;
|
||||
DoCallBack(DMA_REACHED_TC);
|
||||
}
|
||||
void SetPage(Bit8u val) {
|
||||
pagenum=val;
|
||||
pagebase=(pagenum >> DMA16) << (16+DMA16);
|
||||
}
|
||||
Bitu Read(Bitu size, Bit8u * buffer);
|
||||
Bitu Write(Bitu size, Bit8u * buffer);
|
||||
};
|
||||
|
||||
|
||||
extern DmaChannel *DmaChannels[8];
|
||||
extern DmaController *DmaControllers[2];
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -9,13 +9,15 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: dos_inc.h,v 1.48 2004/08/04 09:12:50 qbix79 Exp $ */
|
||||
|
||||
#ifndef DOS_H_
|
||||
#define DOS_H_
|
||||
|
||||
@ -43,27 +45,25 @@ struct DOS_Version {
|
||||
Bit8u major,minor,revision;
|
||||
};
|
||||
|
||||
struct DOS_Block {
|
||||
DOS_Date date;
|
||||
DOS_Version version;
|
||||
Bit16u firstMCB;
|
||||
Bit16u errorcode;
|
||||
Bit16u psp;
|
||||
Bit16u env;
|
||||
RealPt cpmentry;
|
||||
RealPt dta;
|
||||
Bit8u return_code,return_mode;
|
||||
|
||||
Bit8u current_drive;
|
||||
bool verify;
|
||||
bool breakcheck;
|
||||
bool echo; // if set to true dev_con::read will echo input
|
||||
struct {
|
||||
RealPt indosflag;
|
||||
RealPt mediaid;
|
||||
RealPt tempdta;
|
||||
} tables;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack (1)
|
||||
#endif
|
||||
union bootSector {
|
||||
struct entries {
|
||||
Bit8u jump[3];
|
||||
Bit8u oem_name[8];
|
||||
Bit16u bytesect;
|
||||
Bit8u sectclust;
|
||||
Bit16u reserve_sect;
|
||||
Bit8u misc[496];
|
||||
} bootdata;
|
||||
Bit8u rawdata[512];
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack ()
|
||||
#endif
|
||||
|
||||
|
||||
enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
|
||||
enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
|
||||
@ -72,7 +72,7 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
|
||||
#define DOS_DRIVES 26
|
||||
|
||||
/* internal Dos Tables */
|
||||
extern DOS_Block dos;
|
||||
|
||||
extern DOS_File * Files[DOS_FILES];
|
||||
extern DOS_Drive * Drives[DOS_DRIVES];
|
||||
extern Bit8u dos_copybuf[0x10000];
|
||||
@ -100,7 +100,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry);
|
||||
bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status);
|
||||
bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry);
|
||||
bool DOS_UnlinkFile(char * name);
|
||||
bool DOS_FindFirst(char *search,Bit16u attr);
|
||||
bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false);
|
||||
bool DOS_FindNext(void);
|
||||
bool DOS_Canonicalize(char * name,char * big);
|
||||
bool DOS_CreateTempFile(char * name,Bit16u * entry);
|
||||
@ -208,30 +208,26 @@ INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) {
|
||||
|
||||
|
||||
/* Remains some classes used to access certain things */
|
||||
|
||||
#define sGet(s,m) GetIt(((s *)0)->m,(PhysPt)&(((s *)0)->m))
|
||||
#define sSave(s,m,val) SaveIt(((s *)0)->m,(PhysPt)&(((s *)0)->m),val)
|
||||
|
||||
#define sOffset(s,m) ((char*)&(((s*)NULL)->m)-(char*)NULL)
|
||||
#define sGet(s,m) GetIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m))
|
||||
#define sSave(s,m,val) SaveIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m),val)
|
||||
|
||||
class MemStruct {
|
||||
public:
|
||||
INLINE Bit8u GetIt(Bit8u&,PhysPt addr) {
|
||||
return mem_readb(pt+addr);
|
||||
INLINE Bitu GetIt(Bitu size,PhysPt addr) {
|
||||
switch (size) {
|
||||
case 1:return mem_readb(pt+addr);
|
||||
case 2:return mem_readw(pt+addr);
|
||||
case 4:return mem_readd(pt+addr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
INLINE Bit16u GetIt(Bit16u&,PhysPt addr) {
|
||||
return mem_readw(pt+addr);
|
||||
}
|
||||
INLINE Bit32u GetIt(Bit32u&,PhysPt addr) {
|
||||
return mem_readd(pt+addr);
|
||||
}
|
||||
INLINE void SaveIt(Bit8u&,PhysPt addr,Bit8u val) {
|
||||
mem_writeb(pt+addr,val);
|
||||
}
|
||||
INLINE void SaveIt(Bit16u&,PhysPt addr,Bit16u val) {
|
||||
mem_writew(pt+addr,val);
|
||||
}
|
||||
INLINE void SaveIt(Bit32u&,PhysPt addr,Bit32u val) {
|
||||
mem_writed(pt+addr,val);
|
||||
INLINE void SaveIt(Bitu size,PhysPt addr,Bitu val) {
|
||||
switch (size) {
|
||||
case 1:mem_writeb(pt+addr,val);break;
|
||||
case 2:mem_writew(pt+addr,val);break;
|
||||
case 4:mem_writed(pt+addr,val);break;
|
||||
}
|
||||
}
|
||||
INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);}
|
||||
INLINE void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);}
|
||||
@ -252,8 +248,6 @@ public:
|
||||
void RestoreVectors (void);
|
||||
void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); };
|
||||
Bit16u GetSize (void) { return sGet(sPSP,next_seg); };
|
||||
void SetDTA (RealPt ptdta) { sSave(sPSP,dta,ptdta); };
|
||||
RealPt GetDTA (void) { return sGet(sPSP,dta); };
|
||||
void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); };
|
||||
Bit16u GetEnvironment (void) { return sGet(sPSP,environment); };
|
||||
Bit16u GetSegment (void) { return seg; };
|
||||
@ -291,8 +285,11 @@ private:
|
||||
Bit16u max_files; /* Maximum open files */
|
||||
RealPt file_table; /* Pointer to File Table PSP:0x18 */
|
||||
RealPt prev_psp; /* Pointer to previous PSP */
|
||||
RealPt dta; /* Pointer to current Process DTA */
|
||||
Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */
|
||||
Bit8u interim_flag;
|
||||
Bit8u truename_flag;
|
||||
Bit16u nn_flags;
|
||||
Bit16u dos_version;
|
||||
Bit8u fill_2[14]; /* Lot's of unused stuff i can't care aboue */
|
||||
Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */
|
||||
Bit8u fill_3[9]; /* This has some blocks with FCB info */
|
||||
Bit8u fcb1[16]; /* first FCB */
|
||||
@ -343,25 +340,50 @@ public:
|
||||
void SetFirstMCB(Bit16u _first_mcb);
|
||||
void SetfirstFileTable(RealPt _first_table);
|
||||
void SetBuffers(Bit16u x,Bit16u y);
|
||||
void SetCurDirStruct(Bit32u _curdirstruct);
|
||||
void SetFCBTable(Bit32u _fcbtable);
|
||||
void SetDeviceChainStart(Bit32u _devchain);
|
||||
void SetDiskInfoBuffer(Bit32u _dinfobuf);
|
||||
RealPt GetPointer (void);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct sDIB {
|
||||
Bit8u stuff1[22]; // -0x18 some stuff, hopefully never used....
|
||||
Bit16u firstMCB; // -0x2 first memory control block
|
||||
RealPt firstDPB; // 0x00 first drive parameter block
|
||||
Bit16u regCXfrom5e; // -0x18 CX from last int21/ah=5e
|
||||
Bit16u countLRUcache; // -0x16 LRU counter for FCB caching
|
||||
Bit16u countLRUopens; // -0x14 LRU counter for FCB openings
|
||||
Bit8u stuff[6]; // -0x12 some stuff, hopefully never used....
|
||||
Bit16u sharingCount; // -0x0c sharing retry count
|
||||
Bit16u sharingDelay; // -0x0a sharing retry delay
|
||||
RealPt diskBufPtr; // -0x08 pointer to disk buffer
|
||||
Bit16u ptrCONinput; // -0x04 pointer to con input
|
||||
Bit16u firstMCB; // -0x02 first memory control block
|
||||
RealPt firstDPB; // 0x00 first drive parameter block
|
||||
RealPt firstFileTable; // 0x04 first system file table
|
||||
RealPt activeClock; // 0x08 active clock device header
|
||||
RealPt activeCon; // 0x0c active console device header
|
||||
RealPt activeCon; // 0x0c active console device header
|
||||
Bit16u maxSectorLength; // 0x10 maximum bytes per sector of any block device;
|
||||
RealPt discInfoBuffer; // 0x12 pointer to disc info buffer
|
||||
RealPt diskInfoBuffer; // 0x12 pointer to disk info buffer
|
||||
RealPt curDirStructure; // 0x16 pointer to current array of directory structure
|
||||
RealPt fcbTable; // 0x1a pointer to system FCB table
|
||||
Bit8u stuff2[0x21]; // 0x1e more stuff
|
||||
Bit16u buffers_x; // x in BUFFERS x,y
|
||||
Bit16u buffers_y; // y in BUFFERS x,y
|
||||
RealPt fcbTable; // 0x1a pointer to system FCB table
|
||||
Bit16u protFCBs; // 0x1e protected fcbs
|
||||
Bit8u blockDevices; // 0x20 installed block devices
|
||||
Bit8u lastdrive; // 0x21 lastdrive
|
||||
Bit32u nulNextDriver; // 0x22 NUL driver next pointer
|
||||
Bit16u nulAttributes; // 0x26 NUL driver aattributes
|
||||
Bit32u nulStrategy; // 0x28 NUL driver strategy routine
|
||||
Bit8u nulString[8]; // 0x2c NUL driver name string
|
||||
Bit8u joindedDrives; // 0x34 joined drives
|
||||
Bit16u specialCodeSeg; // 0x35 special code segment
|
||||
RealPt setverPtr; // 0x37 pointer to setver
|
||||
Bit16u a20FixOfs; // 0x3b a20 fix routine offset
|
||||
Bit16u pspLastIfHMA; // 0x3d psp of last program (if dos in hma)
|
||||
Bit16u buffers_x; // 0x3f x in BUFFERS x,y
|
||||
Bit16u buffers_y; // 0x41 y in BUFFERS x,y
|
||||
Bit8u bootDrive; // 0x43 boot drive
|
||||
Bit8u useDwordMov; // 0x44 use dword moves
|
||||
Bit16u extendedSize; // 0x45 size of extended memory
|
||||
// some more stuff, hopefully never used.
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#ifdef _MSC_VER
|
||||
@ -389,9 +411,9 @@ private:
|
||||
#endif
|
||||
struct sDTA {
|
||||
Bit8u sdrive; /* The Drive the search is taking place */
|
||||
Bit8u sattr; /* The Attributes that need to be found */
|
||||
Bit8u sname[8]; /* The Search pattern for the filename */
|
||||
Bit8u sext[3]; /* The Search pattern for the extenstion */
|
||||
Bit8u sattr; /* The Attributes that need to be found */
|
||||
Bit16u dirID; /* custom: dir-search ID for multiple searches at the same time */
|
||||
Bit8u fill[6];
|
||||
Bit8u attr;
|
||||
@ -422,6 +444,8 @@ public:
|
||||
void SetRandom(Bit32u _random);
|
||||
Bit8u GetDrive(void);
|
||||
bool Extended(void);
|
||||
void GetAttr(Bit8u & attr);
|
||||
void SetAttr(Bit8u attr);
|
||||
private:
|
||||
bool extended;
|
||||
PhysPt real_pt;
|
||||
@ -438,8 +462,11 @@ private:
|
||||
Bit16u date;
|
||||
Bit16u time;
|
||||
/* Reserved Block should be 8 bytes */
|
||||
Bit8u sft_entries;
|
||||
Bit8u share_attributes;
|
||||
Bit8u extra_info;
|
||||
Bit8u file_handle;
|
||||
Bit8u reserved[7];
|
||||
Bit8u reserved[4];
|
||||
/* end */
|
||||
Bit8u cur_rec; /* Current record in current block */
|
||||
Bit32u rndm; /* Current relative record number */
|
||||
@ -476,10 +503,78 @@ private:
|
||||
#endif
|
||||
};
|
||||
|
||||
extern DOS_InfoBlock dos_infoblock;;
|
||||
extern Bit16u sdaseg;
|
||||
#define DOS_SDA_SEG sdaseg
|
||||
#define DOS_SDA_OFS 0
|
||||
|
||||
|
||||
class DOS_SDA : public MemStruct {
|
||||
public:
|
||||
DOS_SDA(Bit16u _seg,Bit16u _offs) { SetPt(_seg,_offs); }
|
||||
void Init();
|
||||
void SetDrive(Bit8u _drive) { sSave(sSDA,current_drive, _drive); }
|
||||
void SetDTA(Bit32u _dta) { sSave(sSDA,current_dta, _dta); }
|
||||
void SetPSP(Bit16u _psp) { sSave(sSDA,current_psp, _psp); }
|
||||
Bit8u GetDrive(void) { return sGet(sSDA,current_drive); }
|
||||
Bit16u GetPSP(void) { return sGet(sSDA,current_psp); }
|
||||
Bit32u GetDTA(void) { return sGet(sSDA,current_dta); }
|
||||
|
||||
|
||||
private:
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack (1)
|
||||
#endif
|
||||
struct sSDA {
|
||||
Bit8u crit_error_flag; /* 0x00 Critical Error Flag */
|
||||
Bit8u inDOS_flag; /* 0x01 InDOS flag (count of active INT 21 calls) */
|
||||
Bit8u drive_crit_error; /* 0x02 Drive on which current critical error occurred or FFh */
|
||||
Bit8u locus_of_last_error; /* 0x03 locus of last error */
|
||||
Bit16u extended_error_code; /* 0x04 extended error code of last error */
|
||||
Bit8u suggested_action; /* 0x06 suggested action for last error */
|
||||
Bit8u error_class; /* 0x07 class of last error*/
|
||||
Bit32u last_error_pointer; /* 0x08 ES:DI pointer for last error */
|
||||
Bit32u current_dta; /* 0x0C current DTA (Disk Transfer Address) */
|
||||
Bit16u current_psp; /* 0x10 current PSP */
|
||||
Bit16u sp_int_23; /* 0x12 stores SP across an INT 23 */
|
||||
Bit16u return_code; /* 0x14 return code from last process termination (zerod after reading with AH=4Dh) */
|
||||
Bit8u current_drive; /* 0x16 current drive */
|
||||
Bit8u extended_break_flag; /* 0x17 extended break flag */
|
||||
Bit8u fill[2]; /* 0x18 flag: code page switching || flag: copy of previous byte in case of INT 24 Abort*/
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack()
|
||||
#endif
|
||||
};
|
||||
extern DOS_InfoBlock dos_infoblock;
|
||||
|
||||
struct DOS_Block {
|
||||
DOS_Date date;
|
||||
DOS_Version version;
|
||||
Bit16u firstMCB;
|
||||
Bit16u errorcode;
|
||||
Bit16u psp(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetPSP();};
|
||||
void psp(Bit16u _seg){ DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetPSP(_seg);};
|
||||
Bit16u env;
|
||||
RealPt cpmentry;
|
||||
RealPt dta(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDTA();};
|
||||
void dta(RealPt _dta){DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDTA(_dta);};
|
||||
Bit8u return_code,return_mode;
|
||||
|
||||
Bit8u current_drive;
|
||||
bool verify;
|
||||
bool breakcheck;
|
||||
bool echo; // if set to true dev_con::read will echo input
|
||||
struct {
|
||||
RealPt mediaid;
|
||||
RealPt tempdta;
|
||||
RealPt dcbs;
|
||||
} tables;
|
||||
};
|
||||
|
||||
extern DOS_Block dos;
|
||||
|
||||
INLINE Bit8u RealHandle(Bit16u handle) {
|
||||
DOS_PSP psp(dos.psp);
|
||||
DOS_PSP psp(dos.psp());
|
||||
return psp.GetFileHandle(handle);
|
||||
}
|
||||
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: dos_system.h,v 1.20 2004/01/12 20:25:57 finsterr Exp $ */
|
||||
/* $Id: dos_system.h,v 1.24 2004/08/04 09:12:50 qbix79 Exp $ */
|
||||
|
||||
#ifndef DOSSYSTEM_H_
|
||||
#define DOSSYSTEM_H_
|
||||
@ -54,7 +54,7 @@ class DOS_DTA;
|
||||
class DOS_File {
|
||||
public:
|
||||
DOS_File():flags(0) { name=0; refCtr = 0; };
|
||||
virtual ~DOS_File(){};
|
||||
virtual ~DOS_File(){if(name) delete [] name;};
|
||||
virtual bool Read(Bit8u * data,Bit16u * size)=0;
|
||||
virtual bool Write(Bit8u * data,Bit16u * size)=0;
|
||||
virtual bool Seek(Bit32u * pos,Bit32u type)=0;
|
||||
@ -66,6 +66,7 @@ public:
|
||||
virtual bool IsName(const char* _name) { if (!name) return false; return strcmp(name,_name)==0; };
|
||||
virtual void AddRef() { refCtr++; };
|
||||
virtual Bits RemoveRef() { return --refCtr; };
|
||||
virtual bool UpdateDateTimeFromHost() { return true; }
|
||||
Bit8u type;
|
||||
Bit32u flags;
|
||||
Bit16u time;
|
||||
@ -85,8 +86,8 @@ public:
|
||||
Bit8u fhandle;
|
||||
};
|
||||
|
||||
#define MAX_OPENDIRS 16
|
||||
|
||||
#define MAX_OPENDIRS 2048
|
||||
//Can be high as it's only storage (16 bit variable)
|
||||
class DOS_Drive_Cache {
|
||||
public:
|
||||
DOS_Drive_Cache (void);
|
||||
@ -104,7 +105,7 @@ public:
|
||||
char* GetExpandName (const char* path);
|
||||
bool GetShortName (const char* fullname, char* shortname);
|
||||
|
||||
bool FindFirst (char* path, Bitu dtaAddress, Bitu& id);
|
||||
bool FindFirst (char* path, Bitu& id);
|
||||
bool FindNext (Bitu id, char* &result);
|
||||
|
||||
void CacheOut (const char* path, bool ignoreLastDir = false);
|
||||
@ -119,21 +120,19 @@ public:
|
||||
public:
|
||||
CFileInfo(void) {
|
||||
orgname[0] = shortname[0] = 0;
|
||||
nextEntry = shortNr = compareCount = 0;
|
||||
nextEntry = shortNr = 0;
|
||||
isDir = false;
|
||||
}
|
||||
~CFileInfo(void) {
|
||||
for (Bit32u i=0; i<fileList.size(); i++) delete fileList[i];
|
||||
fileList.clear();
|
||||
longNameList.clear();
|
||||
compareCount = 0;
|
||||
};
|
||||
char orgname [CROSS_LEN];
|
||||
char shortname [DOS_NAMELENGTH_ASCII];
|
||||
bool isDir;
|
||||
Bitu nextEntry;
|
||||
Bitu shortNr;
|
||||
Bitu compareCount;
|
||||
// contents
|
||||
std::vector<CFileInfo*> fileList;
|
||||
std::vector<CFileInfo*> longNameList;
|
||||
@ -142,18 +141,18 @@ public:
|
||||
private:
|
||||
|
||||
bool RemoveTrailingDot (char* shortname);
|
||||
Bits GetLongName (CFileInfo* info, char* shortname);
|
||||
Bits GetLongName (CFileInfo* info, char* shortname);
|
||||
void CreateShortName (CFileInfo* dir, CFileInfo* info);
|
||||
Bit16u CreateShortNameID (CFileInfo* dir, const char* name);
|
||||
int CompareShortname (const char* compareName, const char* shortName);
|
||||
bool SetResult (CFileInfo* dir, char * &result, Bit16u entryNr);
|
||||
bool IsCachedIn (CFileInfo* dir);
|
||||
CFileInfo* FindDirInfo (const char* path, char* expandedPath);
|
||||
int CompareShortname (const char* compareName, const char* shortName);
|
||||
bool SetResult (CFileInfo* dir, char * &result, Bit16u entryNr);
|
||||
bool IsCachedIn (CFileInfo* dir);
|
||||
CFileInfo* FindDirInfo (const char* path, char* expandedPath);
|
||||
bool RemoveSpaces (char* str);
|
||||
bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id);
|
||||
void CreateEntry (CFileInfo* dir, const char* name);
|
||||
Bit16u GetFreeID (CFileInfo* dir);
|
||||
void Clear (void);
|
||||
bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id);
|
||||
void CreateEntry (CFileInfo* dir, const char* name);
|
||||
Bit16u GetFreeID (CFileInfo* dir);
|
||||
void Clear (void);
|
||||
|
||||
CFileInfo* dirBase;
|
||||
char dirPath [CROSS_LEN];
|
||||
@ -169,6 +168,7 @@ private:
|
||||
char dirSearchName [MAX_OPENDIRS];
|
||||
bool free [MAX_OPENDIRS];
|
||||
CFileInfo* dirFindFirst [MAX_OPENDIRS];
|
||||
Bitu nextFreeFindFirst;
|
||||
|
||||
char label [CROSS_LEN];
|
||||
};
|
||||
@ -217,7 +217,7 @@ public:
|
||||
virtual bool RemoveDir(char * _dir)=0;
|
||||
virtual bool MakeDir(char * _dir)=0;
|
||||
virtual bool TestDir(char * _dir)=0;
|
||||
virtual bool FindFirst(char * _dir,DOS_DTA & dta)=0;
|
||||
virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false)=0;
|
||||
virtual bool FindNext(DOS_DTA & dta)=0;
|
||||
virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
|
||||
virtual bool Rename(char * oldname,char * newname)=0;
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -24,25 +24,6 @@ void E_Exit(char * message,...);
|
||||
void MSG_Add(const char*,const char*); //add messages to the internal langaugefile
|
||||
const char* MSG_Get(char const *); //get messages from the internal langaugafile
|
||||
|
||||
/* The internal types */
|
||||
typedef unsigned char Bit8u;
|
||||
typedef signed char Bit8s;
|
||||
typedef unsigned short Bit16u;
|
||||
typedef signed short Bit16s;
|
||||
typedef unsigned long Bit32u;
|
||||
typedef signed long Bit32s;
|
||||
typedef double Real64;
|
||||
#if defined(_MSC_VER)
|
||||
typedef unsigned __int64 Bit64u;
|
||||
typedef signed __int64 Bit64s;
|
||||
#else
|
||||
typedef unsigned long long Bit64u;
|
||||
typedef signed long long Bit64s;
|
||||
#endif
|
||||
|
||||
typedef unsigned int Bitu;
|
||||
typedef signed int Bits;
|
||||
|
||||
#include <stddef.h>
|
||||
#include "config.h"
|
||||
|
||||
@ -63,11 +44,11 @@ enum MachineType {
|
||||
MCH_HERC,
|
||||
MCH_CGA,
|
||||
MCH_TANDY,
|
||||
MCH_VGA,
|
||||
MCH_AUTO
|
||||
MCH_VGA
|
||||
};
|
||||
|
||||
extern MachineType machine;
|
||||
extern bool SDLNetInited;
|
||||
|
||||
#ifndef __LOGGING_H_
|
||||
#include "logging.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -19,7 +19,17 @@
|
||||
#ifndef _HARDWARE_H_
|
||||
#define _HARDWARE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class Section;
|
||||
enum OPL_Mode {
|
||||
OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3
|
||||
};
|
||||
|
||||
void OPL_Init(Section* sec,Bitu base,OPL_Mode mode,Bitu rate);
|
||||
void CMS_Init(Section* sec,Bitu base,Bitu rate);
|
||||
extern Bit8u adlib_commandreg;
|
||||
FILE * OpenCaptureFile(const char * type,const char * ext);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -9,37 +9,51 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
typedef Bit8u (IO_ReadBHandler)(Bit32u port);
|
||||
typedef Bit16u (IO_ReadWHandler)(Bit32u port);
|
||||
typedef Bit32u (IO_ReadDHandler)(Bit32u port);
|
||||
typedef void (IO_WriteBHandler)(Bit32u port,Bit8u value);
|
||||
typedef void (IO_WriteWHandler)(Bit32u port,Bit16u value);
|
||||
typedef void (IO_WriteDHandler)(Bit32u port,Bit32u value);
|
||||
#define IO_MAX (64*1024+3)
|
||||
|
||||
void IO_RegisterReadBHandler(Bitu port,IO_ReadBHandler * handler);
|
||||
void IO_RegisterReadWHandler(Bitu port,IO_ReadWHandler * handler);
|
||||
void IO_RegisterReadDHandler(Bitu port,IO_ReadDHandler * handler);
|
||||
#define IO_MB 0x1
|
||||
#define IO_MW 0x2
|
||||
#define IO_MD 0x4
|
||||
#define IO_MA (IO_MB | IO_MW | IO_MD )
|
||||
|
||||
void IO_RegisterWriteBHandler(Bitu port,IO_WriteBHandler * handler);
|
||||
void IO_RegisterWriteWHandler(Bitu port,IO_WriteWHandler * handler);
|
||||
void IO_RegisterWriteDHandler(Bitu port,IO_WriteDHandler * handler);
|
||||
typedef Bitu IO_ReadHandler(Bitu port,Bitu iolen);
|
||||
typedef void IO_WriteHandler(Bitu port,Bitu val,Bitu iolen);
|
||||
|
||||
void IO_FreeReadHandler(Bitu port);
|
||||
void IO_FreeWriteHandler(Bitu port);
|
||||
extern IO_WriteHandler * io_writehandlers[3][IO_MAX];
|
||||
extern IO_ReadHandler * io_readhandlers[3][IO_MAX];
|
||||
|
||||
void IO_WriteB(Bitu port,Bit8u val);
|
||||
Bit8u IO_ReadB(Bitu port);
|
||||
void IO_WriteW(Bitu port,Bit16u val);
|
||||
Bit16u IO_ReadW(Bitu port);
|
||||
void IO_WriteD(Bitu port,Bit32u val);
|
||||
Bit32u IO_ReadD(Bitu port);
|
||||
void IO_RegisterReadHandler(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range=1);
|
||||
void IO_RegisterWriteHandler(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range=1);
|
||||
|
||||
void IO_FreeReadHandler(Bitu port,Bitu mask,Bitu range=0);
|
||||
void IO_FreeWriteHandler(Bitu port,Bitu mask,Bitu range=0);
|
||||
|
||||
INLINE void IO_WriteB(Bitu port,Bitu val) {
|
||||
io_writehandlers[0][port](port,val,1);
|
||||
};
|
||||
INLINE void IO_WriteW(Bitu port,Bitu val) {
|
||||
io_writehandlers[1][port](port,val,2);
|
||||
};
|
||||
INLINE void IO_WriteD(Bitu port,Bitu val) {
|
||||
io_writehandlers[2][port](port,val,4);
|
||||
};
|
||||
|
||||
INLINE Bitu IO_ReadB(Bitu port) {
|
||||
return io_readhandlers[0][port](port,1);
|
||||
}
|
||||
INLINE Bitu IO_ReadW(Bitu port) {
|
||||
return io_readhandlers[1][port](port,2);
|
||||
}
|
||||
INLINE Bitu IO_ReadD(Bitu port) {
|
||||
return io_readhandlers[2][port](port,4);
|
||||
}
|
||||
|
||||
INLINE void IO_Write(Bitu port,Bit8u val) {
|
||||
IO_WriteB(port,val);
|
||||
@ -48,11 +62,4 @@ INLINE Bit8u IO_Read(Bitu port){
|
||||
return IO_ReadB(port);
|
||||
}
|
||||
|
||||
INLINE void IO_RegisterReadHandler(Bitu port,IO_ReadBHandler * handler,char * name) {
|
||||
IO_RegisterReadBHandler(port,handler);
|
||||
}
|
||||
INLINE void IO_RegisterWriteHandler(Bitu port,IO_WriteBHandler * handler,char * name) {
|
||||
IO_RegisterWriteBHandler(port,handler);
|
||||
}
|
||||
|
||||
|
||||
|
92
include/ipx.h
Normal file
92
include/ipx.h
Normal 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
50
include/ipxserver.h
Normal 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
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -20,6 +20,7 @@
|
||||
#define _KEYBOARD_H_
|
||||
|
||||
enum KBD_KEYS {
|
||||
KBD_NONE,
|
||||
KBD_1, KBD_2, KBD_3, KBD_4, KBD_5, KBD_6, KBD_7, KBD_8, KBD_9, KBD_0,
|
||||
KBD_q, KBD_w, KBD_e, KBD_r, KBD_t, KBD_y, KBD_u, KBD_i, KBD_o, KBD_p,
|
||||
KBD_a, KBD_s, KBD_d, KBD_f, KBD_g, KBD_h, KBD_j, KBD_k, KBD_l, KBD_z,
|
||||
@ -35,25 +36,17 @@ enum KBD_KEYS {
|
||||
KBD_grave,KBD_minus,KBD_equals,KBD_backslash,KBD_leftbracket,KBD_rightbracket,
|
||||
KBD_semicolon,KBD_quote,KBD_period,KBD_comma,KBD_slash,
|
||||
|
||||
KBD_printscreen,KBD_pause,
|
||||
KBD_insert,KBD_home,KBD_pageup,KBD_delete,KBD_end,KBD_pagedown,
|
||||
KBD_left,KBD_up,KBD_down,KBD_right,
|
||||
|
||||
KBD_kp1,KBD_kp2,KBD_kp3,KBD_kp4,KBD_kp5,KBD_kp6,KBD_kp7,KBD_kp8,KBD_kp9,KBD_kp0,
|
||||
KBD_kpslash,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod,
|
||||
KBD_kpdivide,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod,
|
||||
|
||||
|
||||
KBD_LAST
|
||||
};
|
||||
|
||||
typedef void(KEYBOARD_EventHandler)(void);
|
||||
|
||||
void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler);
|
||||
void KEYBOARD_AddKey(KBD_KEYS key,Bitu ascii,Bitu mod,bool pressed);
|
||||
void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod);
|
||||
|
||||
|
||||
#define KBD_MOD_ALT 0x1
|
||||
#define KBD_MOD_CTRL 0x2
|
||||
#define KBD_MOD_SHIFT 0x4
|
||||
|
||||
void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed);
|
||||
|
||||
#endif
|
||||
|
40
include/mapper.h
Normal file
40
include/mapper.h
Normal 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
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -20,8 +20,6 @@
|
||||
#define __MEM_H
|
||||
#include <dosbox.h>
|
||||
|
||||
#define bmemcpy(mem1,mem2,size) memcpy((void *)mem1,(void *)mem2,size)
|
||||
|
||||
typedef Bit32u PhysPt;
|
||||
typedef Bit8u * HostPt;
|
||||
typedef Bit32u RealPt;
|
||||
@ -30,6 +28,8 @@ typedef Bit32s MemHandle;
|
||||
|
||||
#define MEM_PAGESIZE 4096
|
||||
|
||||
extern HostPt MemBase;
|
||||
|
||||
bool MEM_A20_Enabled(void);
|
||||
void MEM_A20_Enable(bool enable);
|
||||
|
||||
@ -123,9 +123,25 @@ void mem_writeb(PhysPt pt,Bit8u val);
|
||||
void mem_writew(PhysPt pt,Bit16u val);
|
||||
void mem_writed(PhysPt pt,Bit32u val);
|
||||
|
||||
void phys_writeb(PhysPt addr,Bit8u val);
|
||||
void phys_writew(PhysPt addr,Bit16u val);
|
||||
void phys_writed(PhysPt addr,Bit32u val);
|
||||
INLINE void phys_writeb(PhysPt addr,Bit8u val) {
|
||||
host_writeb(MemBase+addr,val);
|
||||
}
|
||||
INLINE void phys_writew(PhysPt addr,Bit16u val){
|
||||
host_writew(MemBase+addr,val);
|
||||
}
|
||||
INLINE void phys_writed(PhysPt addr,Bit32u val){
|
||||
host_writed(MemBase+addr,val);
|
||||
}
|
||||
|
||||
INLINE Bit8u phys_readb(PhysPt addr) {
|
||||
return host_readb(MemBase+addr);
|
||||
}
|
||||
INLINE Bit16u phys_readw(PhysPt addr){
|
||||
return host_readw(MemBase+addr);
|
||||
}
|
||||
INLINE Bit32u phys_readd(PhysPt addr){
|
||||
return host_readd(MemBase+addr);
|
||||
}
|
||||
|
||||
/* These don't check for alignment, better be sure it's correct */
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -17,25 +17,54 @@
|
||||
*/
|
||||
|
||||
typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len);
|
||||
typedef void (*MIXER_Handler)(Bitu len);
|
||||
|
||||
#define MIXER_8MONO 0
|
||||
#define MIXER_8STEREO 1
|
||||
#define MIXER_16MONO 2
|
||||
#define MIXER_16STEREO 3
|
||||
enum BlahModes {
|
||||
MIXER_8MONO,MIXER_8STEREO,
|
||||
MIXER_16MONO,MIXER_16STEREO
|
||||
};
|
||||
|
||||
enum MixerModes {
|
||||
M_8M,M_8S,
|
||||
M_16M,M_16S,
|
||||
};
|
||||
|
||||
#define MIXER_BUFSIZE (16*1024)
|
||||
#define MIXER_BUFMASK (MIXER_BUFSIZE-1)
|
||||
extern Bit8u MixTemp[MIXER_BUFSIZE];
|
||||
|
||||
#define MAX_AUDIO ((1<<(16-1))-1)
|
||||
#define MIN_AUDIO -(1<<(16-1))
|
||||
|
||||
class MixerChannel {
|
||||
public:
|
||||
void SetVolume(float _left,float _right);
|
||||
void UpdateVolume(void);
|
||||
void SetFreq(Bitu _freq);
|
||||
void Mix(Bitu _needed);
|
||||
void AddSilence(void); //Fill up until needed
|
||||
template<bool _8bit,bool stereo>
|
||||
void AddSamples(Bitu len,void * data);
|
||||
void AddSamples_m8(Bitu len,Bit8u * data);
|
||||
void AddSamples_s8(Bitu len,Bit8u * data);
|
||||
void AddSamples_m16(Bitu len,Bit16s * data);
|
||||
void AddSamples_s16(Bitu len,Bit16s * data);
|
||||
void AddStretched(Bitu len,Bit16s * data); //Strech block up into needed data
|
||||
void FillUp(void);
|
||||
void Enable(bool _yesno);
|
||||
MIXER_Handler handler;
|
||||
float volmain[2];
|
||||
Bit32s volmul[2];
|
||||
Bitu freq_add,freq_index;
|
||||
Bitu done,needed;
|
||||
Bits last[2];
|
||||
char * name;
|
||||
bool enabled;
|
||||
MixerChannel * next;
|
||||
};
|
||||
|
||||
|
||||
struct MIXER_Channel;
|
||||
|
||||
|
||||
MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * name);
|
||||
void MIXER_SetVolume(MIXER_Channel * chan,Bit8u vol);
|
||||
void MIXER_SetFreq(MIXER_Channel * chan,Bit32u freq);
|
||||
void MIXER_SetMode(MIXER_Channel * chan,Bit8u mode);
|
||||
void MIXER_Enable(MIXER_Channel * chan,bool enable);
|
||||
MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,char * name);
|
||||
MixerChannel * MIXER_FindChannel(const char * name);
|
||||
|
||||
/* PC Speakers functions, tightly related to the timer functions */
|
||||
|
||||
|
@ -9,16 +9,23 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: mouse.h,v 1.7 2004/08/04 09:12:51 qbix79 Exp $ */
|
||||
|
||||
#ifndef _MOUSE_H_
|
||||
#define _MOUSE_H_
|
||||
|
||||
void Mouse_ShowCursor(void);
|
||||
void Mouse_HideCursor(void);
|
||||
|
||||
void Mouse_SetPS2State(bool use);
|
||||
void Mouse_ChangePS2Callback(Bit16u pseg, Bit16u pofs);
|
||||
|
||||
void Mouse_CursorMoved(float x,float y);
|
||||
void Mouse_CursorSet(float x,float y);
|
||||
@ -28,3 +35,5 @@ void Mouse_ButtonReleased(Bit8u button);
|
||||
void Mouse_AutoLock(bool enable);
|
||||
void Mouse_NewVideoMode(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -9,16 +9,19 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: paging.h,v 1.11 2004/09/07 18:21:51 qbix79 Exp $ */
|
||||
|
||||
#ifndef _PAGING_H_
|
||||
#define _PAGING_H_
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "mem.h"
|
||||
|
||||
class PageDirectory;
|
||||
@ -70,13 +73,10 @@ bool PAGING_MakePhysPage(Bitu & page);
|
||||
void MEM_SetLFB(Bitu _page,Bitu _pages,HostPt _pt);
|
||||
void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler);
|
||||
|
||||
Bit32u MEM_PhysReadD(Bitu addr);
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack (1)
|
||||
#endif
|
||||
struct X86_PageEntryBlock{
|
||||
Bit32u p:1;
|
||||
Bit32u wr:1;
|
||||
Bit32u us:1;
|
||||
@ -88,8 +88,11 @@ typedef struct {
|
||||
Bit32u g:1;
|
||||
Bit32u avl:3;
|
||||
Bit32u base:20;
|
||||
} X86_PageEntryBlock GCC_ATTRIBUTE(packed);
|
||||
#pragma pack()
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack ()
|
||||
#endif
|
||||
|
||||
|
||||
union X86PageEntry {
|
||||
Bit32u load;
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -26,41 +26,36 @@ extern Bits CPU_CycleLeft;
|
||||
extern Bits CPU_CycleMax;
|
||||
|
||||
typedef void (PIC_EOIHandler) (void);
|
||||
typedef void (* PIC_EventHandler)(void);
|
||||
typedef void (* PIC_EventHandler)(Bitu val);
|
||||
|
||||
|
||||
#define PIC_MAXIRQ 15
|
||||
#define PIC_NOIRQ 0xFF
|
||||
|
||||
|
||||
extern Bitu PIC_IRQCheck;
|
||||
extern Bitu PIC_IRQActive;
|
||||
extern Bitu PIC_Ticks;
|
||||
|
||||
INLINE Bitu PIC_Index(void) {
|
||||
return ((CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)*1000)/CPU_CycleMax;
|
||||
INLINE float PIC_TickIndex(void) {
|
||||
return (CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)/(float)CPU_CycleMax;
|
||||
}
|
||||
|
||||
INLINE Bits PIC_MakeCycles(Bitu amount) {
|
||||
return (CPU_CycleMax*amount)/1000;
|
||||
INLINE Bits PIC_MakeCycles(double amount) {
|
||||
return (Bits)(CPU_CycleMax*amount);
|
||||
}
|
||||
|
||||
INLINE Bit64u PIC_MicroCount(void) {
|
||||
return PIC_Ticks*1000+PIC_Index();
|
||||
INLINE double PIC_FullIndex(void) {
|
||||
return PIC_Ticks+PIC_TickIndex();
|
||||
}
|
||||
|
||||
void PIC_ActivateIRQ(Bitu irq);
|
||||
|
||||
void PIC_DeActivateIRQ(Bitu irq);
|
||||
|
||||
void PIC_runIRQs(void);
|
||||
|
||||
void PIC_RegisterIRQ(Bitu irq,PIC_EOIHandler handler,char * name);
|
||||
void PIC_FreeIRQ(Bitu irq);
|
||||
bool PIC_RunQueue(void);
|
||||
|
||||
void PIC_AddEvent(PIC_EventHandler handler,Bitu delay);
|
||||
|
||||
//Delay in milliseconds
|
||||
void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val=0);
|
||||
void PIC_RemoveEvents(PIC_EventHandler handler);
|
||||
|
||||
void PIC_SetIRQMask(Bitu irq, bool masked);
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -19,22 +19,14 @@
|
||||
#ifndef __RENDER_H
|
||||
#define __RENDER_H
|
||||
|
||||
enum RENDER_Operation {
|
||||
OP_None,
|
||||
OP_Shot,
|
||||
OP_Normal2x,
|
||||
OP_AdvMame2x,
|
||||
};
|
||||
typedef void (* RENDER_Line_Handler)(const Bit8u * src);
|
||||
|
||||
typedef void (* RENDER_Line_Handler)(Bit8u * src);
|
||||
|
||||
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh);
|
||||
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,double ratio,bool dblw,bool dblh);
|
||||
bool RENDER_StartUpdate(void);
|
||||
void RENDER_EndUpdate(void);
|
||||
void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue);
|
||||
extern RENDER_Line_Handler RENDER_DrawLine;
|
||||
extern Bit8u * RENDER_TempLine;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -19,118 +19,137 @@
|
||||
#if !defined __SERIALPORT_H
|
||||
#define __SERIALPORT_H
|
||||
|
||||
#include <dosbox.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
//If it's too high you overflow terminal clients buffers i think
|
||||
#define FIFO_SIZE (1024)
|
||||
#define QUEUE_SIZE 1024
|
||||
|
||||
// Serial port interface //
|
||||
|
||||
#define M_CTS 0x01
|
||||
#define M_DSR 0x02
|
||||
#define M_RI 0x04
|
||||
#define M_DCD 0x08
|
||||
#define MS_CTS 0x01
|
||||
#define MS_DSR 0x02
|
||||
#define MS_RI 0x04
|
||||
#define MS_DCD 0x08
|
||||
|
||||
enum INT_TYPES {
|
||||
INT_MS,
|
||||
INT_TX,
|
||||
INT_RX,
|
||||
INT_RX_FIFO,
|
||||
INT_LS,
|
||||
INT_NONE,
|
||||
#define MC_DTR 0x1
|
||||
#define MC_RTS 0x2
|
||||
|
||||
|
||||
class CFifo {
|
||||
public:
|
||||
CFifo(Bitu _size) {
|
||||
size=_size;
|
||||
pos=used=0;
|
||||
data=new Bit8u[size];
|
||||
}
|
||||
~CFifo() {
|
||||
delete[] data;
|
||||
}
|
||||
INLINE Bitu left(void) {
|
||||
return size-used;
|
||||
}
|
||||
INLINE Bitu inuse(void) {
|
||||
return used;
|
||||
}
|
||||
void clear(void) {
|
||||
used=pos=0;
|
||||
}
|
||||
bool isFull() {
|
||||
return (used >= size);
|
||||
}
|
||||
void addb(Bit8u _val) {
|
||||
assert(used<size);
|
||||
Bitu where=pos+used;
|
||||
if (where>=size) where-=size;
|
||||
data[where]=_val;
|
||||
used++;
|
||||
}
|
||||
void adds(Bit8u * _str,Bitu _len) {
|
||||
assert((used+_len)<=size);
|
||||
Bitu where=pos+used;
|
||||
used+=_len;
|
||||
while (_len--) {
|
||||
if (where>=size) where-=size;
|
||||
data[where++]=*_str++;
|
||||
}
|
||||
}
|
||||
Bit8u getb(void) {
|
||||
if (!used) return data[pos];
|
||||
Bitu where=pos;
|
||||
if (++pos>=size) pos-=size;
|
||||
used--;
|
||||
return data[where];
|
||||
}
|
||||
void gets(Bit8u * _str,Bitu _len) {
|
||||
assert(used>=_len);
|
||||
used-=_len;
|
||||
while (_len--) {
|
||||
*_str++=data[pos];
|
||||
if (++pos>=size) pos-=size;
|
||||
}
|
||||
}
|
||||
private:
|
||||
Bit8u * data;
|
||||
Bitu size,pos,used;
|
||||
};
|
||||
|
||||
typedef void MControl_Handler(Bitu mc);
|
||||
|
||||
class CSerial {
|
||||
public:
|
||||
|
||||
CSerial() {
|
||||
|
||||
}
|
||||
// Constructor takes base port (0x3f0, 0x2f0, 0x2e0, etc.), IRQ, and initial bps //
|
||||
CSerial (Bit16u initbase, Bit8u initirq, Bit32u initbps);
|
||||
virtual ~CSerial();
|
||||
|
||||
// External port functions for IOHandlers //
|
||||
void write_port(Bit32u port, Bit8u val);
|
||||
Bit8u read_port(Bit32u port);
|
||||
void write_reg(Bitu reg, Bitu val);
|
||||
Bitu read_reg(Bitu reg);
|
||||
|
||||
static void write_serial(Bit32u port,Bit8u val);
|
||||
static Bit8u read_serial(Bit32u port);
|
||||
|
||||
void SetMCHandler(MControl_Handler * mcontrol);
|
||||
|
||||
/* Allow the modem to change the modem status bits */
|
||||
void setmodemstatus(Bit8u status);
|
||||
Bit8u getmodemstatus(void);
|
||||
Bit8u getlinestatus(void);
|
||||
void SetModemStatus(Bit8u status);
|
||||
virtual bool CanRecv(void)=0;
|
||||
virtual bool CanSend(void)=0;
|
||||
virtual void Send(Bit8u val)=0;
|
||||
virtual Bit8u Recv(Bit8u val)=0;
|
||||
virtual void Timer(void);
|
||||
|
||||
void checkint(void);
|
||||
void raiseint(INT_TYPES type);
|
||||
void lowerint(INT_TYPES type);
|
||||
|
||||
/* Access to the receive fifo */
|
||||
Bitu rx_free();
|
||||
void rx_addb(Bit8u byte);
|
||||
void rx_adds(Bit8u * data,Bitu size);
|
||||
Bitu rx_size();
|
||||
Bit8u rx_readb(void);
|
||||
Bitu base;
|
||||
Bitu irq;
|
||||
Bitu bps;
|
||||
Bit8u mctrl;
|
||||
|
||||
/* Access to the transmit fifo */
|
||||
Bitu tx_free();
|
||||
void tx_addb(Bit8u byte);
|
||||
Bitu tx_size();
|
||||
Bit8u tx_readb(void);
|
||||
|
||||
|
||||
// These variables maintain the status of the serial port
|
||||
Bit16u base;
|
||||
Bit16u irq;
|
||||
Bit32u bps;
|
||||
|
||||
bool FIFOenabled;
|
||||
Bit16u FIFOsize;
|
||||
CFifo *rqueue;
|
||||
CFifo *tqueue;
|
||||
|
||||
private:
|
||||
|
||||
void setdivisor(Bit8u dmsb, Bit8u dlsb);
|
||||
void checkforirq(void);
|
||||
struct {
|
||||
Bitu used;
|
||||
Bitu pos;
|
||||
Bit8u data[FIFO_SIZE];
|
||||
} rx_fifo,tx_fifo;
|
||||
struct {
|
||||
Bitu requested;
|
||||
Bitu enabled;
|
||||
INT_TYPES active;
|
||||
} ints;
|
||||
|
||||
Bitu rx_lastread;
|
||||
Bit8u irq_pending;
|
||||
void UpdateBaudrate(void);
|
||||
bool FIFOenabled;
|
||||
Bit8u FIFOsize;
|
||||
bool dotxint;
|
||||
|
||||
Bit8u scratch;
|
||||
Bit8u dlab;
|
||||
Bit8u divisor_lsb;
|
||||
Bit8u divisor_msb;
|
||||
Bit8u wordlen;
|
||||
Bit8u dtr;
|
||||
Bit8u rts;
|
||||
Bit8u out1;
|
||||
Bit8u out2;
|
||||
Bit8u local_loopback;
|
||||
Bit8u linectrl;
|
||||
Bit8u intid;
|
||||
Bit8u ierval;
|
||||
Bit8u iir;
|
||||
Bit8u ier;
|
||||
Bit8u mstatus;
|
||||
|
||||
Bit8u txval;
|
||||
Bit8u timeout;
|
||||
|
||||
MControl_Handler * mc_handler;
|
||||
char remotestr[4096];
|
||||
Bit8u linectrl;
|
||||
Bit8u errors;
|
||||
};
|
||||
|
||||
// This function returns the CSerial objects for ports 1-4 //
|
||||
CSerial *getComport(Bitu portnum);
|
||||
#include <list>
|
||||
|
||||
typedef std::list<CSerial *> CSerialList;
|
||||
typedef std::list<CSerial *>::iterator CSerial_it;
|
||||
|
||||
extern CSerialList seriallist;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: setup.h,v 1.15 2004/01/29 09:26:43 qbix79 Exp $ */
|
||||
/* $Id: setup.h,v 1.16 2004/08/04 09:12:51 qbix79 Exp $ */
|
||||
|
||||
#ifndef _SETUP_H_
|
||||
#define _SETUP_H_
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: shell.h,v 1.2 2004/01/10 14:03:33 qbix79 Exp $ */
|
||||
/* $Id: shell.h,v 1.7 2004/09/09 18:36:50 qbix79 Exp $ */
|
||||
|
||||
#ifndef SHELL_H_
|
||||
#define SHELL_H_
|
||||
@ -57,9 +57,7 @@ public:
|
||||
};
|
||||
|
||||
class DOS_Shell : public Program {
|
||||
|
||||
private:
|
||||
|
||||
std::list<std::string> l_history, l_completion;
|
||||
|
||||
char *completion_start;
|
||||
@ -102,6 +100,8 @@ public:
|
||||
void CMD_PAUSE(char * args);
|
||||
void CMD_SUBST(char* args);
|
||||
void CMD_LOADHIGH(char* args);
|
||||
void CMD_CHOICE(char * args);
|
||||
void CMD_ATTRIB(char * args);
|
||||
/* The shell's variables */
|
||||
Bit16u input_handle;
|
||||
BatchFile * bf;
|
||||
@ -117,15 +117,12 @@ struct SHELL_Cmd {
|
||||
const char * help; /* String with command help */
|
||||
};
|
||||
|
||||
static inline void StripSpaces(char*&args)
|
||||
{
|
||||
while(*args && (*args == ' '))
|
||||
static inline void StripSpaces(char*&args) {
|
||||
while(*args && ((*args == ' ') || (*args == '\t')))
|
||||
args++;
|
||||
}
|
||||
|
||||
|
||||
static inline char* ExpandDot(char*args, char* buffer)
|
||||
{
|
||||
static inline char* ExpandDot(char*args, char* buffer) {
|
||||
if(*args=='.')
|
||||
{
|
||||
if(*(args+1)==0)
|
||||
@ -139,11 +136,11 @@ static inline char* ExpandDot(char*args, char* buffer)
|
||||
buffer[1]=0;
|
||||
strcat(buffer,args);
|
||||
return buffer;
|
||||
}
|
||||
} else
|
||||
strcpy (buffer, args);
|
||||
}
|
||||
else strcpy(buffer,args);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -19,11 +19,11 @@
|
||||
#if !defined __SUPPORT_H
|
||||
#define __SUPPORT_H
|
||||
|
||||
|
||||
#include <dosbox.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
#if defined (_MSC_VER) /* MS Visual C++ */
|
||||
#define strcasecmp(a,b) stricmp(a,b)
|
||||
#define strncasecmp(a,b,n) _strnicmp(a,b,n)
|
||||
@ -39,13 +39,16 @@
|
||||
|
||||
void strreplace(char * str,char o,char n);
|
||||
char *ltrim(char *str);
|
||||
void rtrim(char * const str);
|
||||
char *trim(char *str);
|
||||
char *rtrim(char *str);
|
||||
char *trim(char * str);
|
||||
|
||||
bool ScanCMDBool(char * cmd,char * check);
|
||||
char * ScanCMDRemain(char * cmd);
|
||||
bool ScanCMDHex(char * cmd,char * check,Bits * result);
|
||||
char * StripWord(char * cmd);
|
||||
char * StripWord(char *&cmd);
|
||||
bool IsDecWord(char * word);
|
||||
bool IsHexWord(char * word);
|
||||
Bits ConvDecWord(char * word);
|
||||
Bits ConvHexWord(char * word);
|
||||
|
||||
INLINE char * upcase(char * str) {
|
||||
for (char* idx = str; *idx ; idx++) *idx = toupper(*idx);
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -25,19 +25,11 @@
|
||||
|
||||
#define GetTicks() SDL_GetTicks()
|
||||
|
||||
typedef void (*TIMER_TickHandler)(Bitu ticks);
|
||||
typedef void (*TIMER_MicroHandler)(void);
|
||||
|
||||
typedef void TIMER_Block;
|
||||
|
||||
typedef void (*TIMER_TickHandler)(void);
|
||||
|
||||
/* Register a function that gets called everytime if 1 or more ticks pass */
|
||||
TIMER_Block * TIMER_RegisterTickHandler(TIMER_TickHandler handler);
|
||||
/* Register a function to be called every x microseconds */
|
||||
TIMER_Block * TIMER_RegisterMicroHandler(TIMER_MicroHandler handler,Bitu micro);
|
||||
|
||||
/* Set the microseconds value to a new value */
|
||||
void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro);
|
||||
void TIMER_AddTickHandler(TIMER_TickHandler handler);
|
||||
void TIMER_DelTickHandler(TIMER_TickHandler handler);
|
||||
|
||||
/* This will add 1 milliscond to all timers */
|
||||
void TIMER_AddTick(void);
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -23,13 +23,13 @@
|
||||
#include "dosbox.h"
|
||||
|
||||
enum VGAModes {
|
||||
M_TEXT2,M_TEXT16,
|
||||
M_HERC,
|
||||
M_CGA2,M_CGA4,M_CGA16,
|
||||
M_TANDY16,
|
||||
M_EGA2,M_EGA4,M_EGA16,
|
||||
M_CGA2,M_CGA4,
|
||||
M_EGA16,
|
||||
M_VGA,
|
||||
M_LIN8,
|
||||
M_TEXT,
|
||||
M_HERC_GFX,M_HERC_TEXT,
|
||||
M_CGA16,M_TANDY2,M_TANDY4,M_TANDY16,M_TANDY_TEXT,
|
||||
M_ERROR,
|
||||
};
|
||||
|
||||
@ -60,9 +60,7 @@ typedef struct {
|
||||
|
||||
/* Some other screen related variables */
|
||||
Bitu line_compare;
|
||||
|
||||
bool chained; /* Enable or Disabled Chain 4 Mode */
|
||||
bool blinking; /* Attribute bit 7 is blinking */
|
||||
|
||||
/* Pixel Scrolling */
|
||||
Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */
|
||||
@ -91,10 +89,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
bool resizing;
|
||||
bool drawing;
|
||||
Bitu width;
|
||||
Bitu height;
|
||||
Bitu pitch;
|
||||
Bitu blocks;
|
||||
Bitu panning;
|
||||
Bitu address;
|
||||
@ -102,49 +98,62 @@ typedef struct {
|
||||
Bitu address_line_total;
|
||||
Bitu address_line;
|
||||
Bitu lines_total;
|
||||
Bitu lines_left;
|
||||
Bitu lines_done;
|
||||
Bitu lines_scaled;
|
||||
Bitu split_line;
|
||||
Bitu parts_total;
|
||||
Bitu parts_lines;
|
||||
Bitu parts_left;
|
||||
struct {
|
||||
Bitu vtotal;
|
||||
Bitu vstart;
|
||||
Bitu vend;
|
||||
Bitu htotal;
|
||||
Bitu hstart;
|
||||
Bitu hend;
|
||||
Bitu parts;
|
||||
} micro;
|
||||
Bitu scaleh;
|
||||
float vtotal;
|
||||
float vstart;
|
||||
float vend;
|
||||
float htotal;
|
||||
float hstart;
|
||||
float hend;
|
||||
float parts;
|
||||
} delay;
|
||||
bool double_scan;
|
||||
bool double_scan_active;
|
||||
Bit8u font_height;
|
||||
bool doublewidth,doubleheight;
|
||||
Bit8u font[64*1024];
|
||||
Bitu font1_start;
|
||||
Bitu font2_start;
|
||||
Bit8u * font_tables[2];
|
||||
Bitu blinking;
|
||||
struct {
|
||||
Bitu address;
|
||||
Bit8u sline,eline;
|
||||
Bit8u count,delay;
|
||||
Bit8u enabled;
|
||||
} cursor;
|
||||
} VGA_Draw;
|
||||
|
||||
typedef struct {
|
||||
Bit8u curmode;
|
||||
Bit16u originx, originy;
|
||||
Bit8u fstackpos, bstackpos;
|
||||
Bit8u forestack[3];
|
||||
Bit8u backstack[3];
|
||||
Bit16u startaddr;
|
||||
Bit8u posx, posy;
|
||||
Bit8u mc[64][64];
|
||||
} VGA_HWCURSOR;
|
||||
|
||||
typedef struct {
|
||||
Bit8u bank;
|
||||
Bit8u reg_lock1;
|
||||
Bit8u reg_lock2;
|
||||
Bit8u reg_31;
|
||||
Bit8u reg_35;
|
||||
Bit8u reg_40; // 8415/A functionality register
|
||||
Bit8u reg_43;
|
||||
Bit8u reg_45; // Hardware graphics cursor
|
||||
Bit8u reg_58;
|
||||
Bit8u reg_51;
|
||||
Bit8u reg_55;
|
||||
Bit8u ex_hor_overflow;
|
||||
Bit8u ex_ver_overflow;
|
||||
Bit16u la_window;
|
||||
Bit8u misc_control_2;
|
||||
Bit8u ext_mem_ctrl;
|
||||
struct {
|
||||
Bit8u r;
|
||||
Bit8u n;
|
||||
@ -154,6 +163,7 @@ typedef struct {
|
||||
Bit8u lock;
|
||||
Bit8u cmd;
|
||||
} pll;
|
||||
VGA_HWCURSOR hgc;
|
||||
} VGA_S3;
|
||||
|
||||
typedef struct {
|
||||
@ -162,18 +172,28 @@ typedef struct {
|
||||
} VGA_HERC;
|
||||
|
||||
typedef struct {
|
||||
Bit8u mode_control;
|
||||
Bit8u color_select;
|
||||
} VGA_CGA;
|
||||
Bit8u index;
|
||||
Bit8u htotal;
|
||||
Bit8u hdend;
|
||||
Bit8u hsyncp;
|
||||
Bit8u hsyncw;
|
||||
Bit8u vtotal;
|
||||
Bit8u vdend;
|
||||
Bit8u vadjust;
|
||||
Bit8u vsyncp;
|
||||
Bit8u vsyncw;
|
||||
Bit8u max_scanline;
|
||||
} VGA_OTHER;
|
||||
|
||||
typedef struct {
|
||||
Bit8u mode_control;
|
||||
Bit8u color_select;
|
||||
Bit8u mem_bank;
|
||||
Bit8u disp_bank;
|
||||
Bit8u reg_index;
|
||||
Bit8u mode_control1;
|
||||
Bit8u gfx_control;
|
||||
Bit8u palette_mask;
|
||||
Bit8u border_color;
|
||||
Bit8u mode_control2;
|
||||
} VGA_TANDY;
|
||||
|
||||
typedef struct {
|
||||
@ -256,7 +276,6 @@ typedef struct {
|
||||
Bit8u read_index;
|
||||
Bitu first_changed;
|
||||
RGBEntry rgb[0x100];
|
||||
Bit8u attr[16];
|
||||
} VGA_Dac;
|
||||
|
||||
union VGA_Latch {
|
||||
@ -285,8 +304,8 @@ typedef struct {
|
||||
VGA_Latch latch;
|
||||
VGA_S3 s3;
|
||||
VGA_HERC herc;
|
||||
VGA_CGA cga;
|
||||
VGA_TANDY tandy;
|
||||
VGA_OTHER other;
|
||||
VGA_Memory mem;
|
||||
} VGA_Type;
|
||||
|
||||
@ -294,12 +313,15 @@ typedef struct {
|
||||
|
||||
/* Functions for different resolutions */
|
||||
void VGA_SetMode(VGAModes mode);
|
||||
void VGA_DetermineMode(void);
|
||||
void VGA_SetupHandlers(void);
|
||||
void VGA_StartResize(void);
|
||||
void VGA_SetupDrawing(void);
|
||||
void VGA_SetupDrawing(Bitu val);
|
||||
void VGA_CheckScanLength(void);
|
||||
|
||||
/* Some DAC/Attribute functions */
|
||||
void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal);
|
||||
void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue);
|
||||
void VGA_ATTR_SetPalette(Bit8u index,Bit8u val);
|
||||
|
||||
/* The VGA Subfunction startups */
|
||||
@ -310,6 +332,8 @@ void VGA_SetupCRTC(void);
|
||||
void VGA_SetupMisc(void);
|
||||
void VGA_SetupGFX(void);
|
||||
void VGA_SetupSEQ(void);
|
||||
void VGA_SetupOther(void);
|
||||
void VGA_SetupXGA(void);
|
||||
|
||||
/* Some Support Functions */
|
||||
void VGA_SetClock(Bitu which,Bitu target);
|
||||
@ -317,6 +341,8 @@ void VGA_DACSetEntirePalette(void);
|
||||
void VGA_StartRetrace(void);
|
||||
void VGA_StartUpdateLFB(void);
|
||||
void VGA_SetBlinking(Bitu enabled);
|
||||
void VGA_SetCGA2Table(Bit8u val0,Bit8u val1);
|
||||
void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3);
|
||||
|
||||
extern VGA_Type vga;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -28,21 +28,43 @@ struct GFX_PalEntry {
|
||||
Bit8u unused;
|
||||
};
|
||||
|
||||
#define GFX_HASSCALING 0x0001
|
||||
#define GFX_HASCONVERT 0x0002
|
||||
#define CAN_8 0x0001
|
||||
#define CAN_16 0x0002
|
||||
#define CAN_32 0x0004
|
||||
|
||||
#define CAN_ALL (CAN_8|CAN_16|CAN_32)
|
||||
|
||||
#define LOVE_8 0x0010
|
||||
#define LOVE_16 0x0020
|
||||
#define LOVE_32 0x0040
|
||||
|
||||
#define NEED_RGB 0x0100
|
||||
#define DONT_ASPECT 0x0200
|
||||
|
||||
#define HAVE_SCALING 0x1000
|
||||
|
||||
|
||||
enum GFX_Modes {
|
||||
GFX_8,GFX_15,GFX_16,GFX_32,GFX_NONE,
|
||||
};
|
||||
|
||||
void GFX_Events(void);
|
||||
void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries);
|
||||
Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags);
|
||||
Bitu GFX_GetBestMode(Bitu flags);
|
||||
|
||||
Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue);
|
||||
void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack cb_reset);
|
||||
GFX_Modes GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_ResetCallBack cb_reset);
|
||||
|
||||
void GFX_ResetScreen(void);
|
||||
void GFX_Start(void);
|
||||
void GFX_Stop(void);
|
||||
void GFX_SwitchFullScreen(void);
|
||||
bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch);
|
||||
void GFX_EndUpdate(void);
|
||||
|
||||
/* Mouse related */
|
||||
void GFX_CaptureMouse(void);
|
||||
extern bool mouselocked; //true if mouse is confined to window
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -3,5 +3,5 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
noinst_LIBRARIES = libcpu.a
|
||||
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \
|
||||
paging.cpp lazyflags.h core_normal.cpp \
|
||||
paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \
|
||||
core_dyn_x86.cpp
|
@ -134,7 +134,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
noinst_LIBRARIES = libcpu.a
|
||||
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \
|
||||
paging.cpp lazyflags.h core_normal.cpp \
|
||||
paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \
|
||||
core_dyn_x86.cpp
|
||||
|
||||
subdir = src/cpu
|
||||
@ -148,7 +148,8 @@ libcpu_a_AR = $(AR) cru
|
||||
libcpu_a_LIBADD =
|
||||
am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \
|
||||
modrm.$(OBJEXT) core_full.$(OBJEXT) paging.$(OBJEXT) \
|
||||
core_normal.$(OBJEXT) core_dyn_x86.$(OBJEXT)
|
||||
core_normal.$(OBJEXT) core_simple.$(OBJEXT) \
|
||||
core_dyn_x86.$(OBJEXT)
|
||||
libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS)
|
||||
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
@ -157,8 +158,9 @@ am__depfiles_maybe = depfiles
|
||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/callback.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/core_dyn_x86.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/core_full.Po ./$(DEPDIR)/core_normal.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/cpu.Po ./$(DEPDIR)/flags.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/modrm.Po ./$(DEPDIR)/paging.Po
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/core_simple.Po ./$(DEPDIR)/cpu.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/flags.Po ./$(DEPDIR)/modrm.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/paging.Po
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
CXXLD = $(CXX)
|
||||
@ -208,6 +210,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dyn_x86.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_full.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_normal.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_simple.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flags.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modrm.Po@am__quote@
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: callback.cpp,v 1.19 2004/01/07 20:23:48 qbix79 Exp $ */
|
||||
/* $Id: callback.cpp,v 1.22 2004/08/29 11:22:37 qbix79 Exp $ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -67,8 +67,7 @@ void CALLBACK_Idle(void) {
|
||||
reg_eip=oldeip;
|
||||
SegSet16(cs,oldcs);
|
||||
SETFLAGBIT(IF,oldIF);
|
||||
if (CPU_CycleLeft<300) CPU_CycleLeft=1;
|
||||
else CPU_CycleLeft-=300;
|
||||
if (CPU_Cycles>0) CPU_Cycles=0;
|
||||
}
|
||||
|
||||
static Bitu default_handler(void) {
|
||||
@ -204,12 +203,14 @@ void CALLBACK_Init(Section* sec) {
|
||||
/* Setup the Stop Handler */
|
||||
call_stop=CALLBACK_Allocate();
|
||||
CallBack_Handlers[call_stop]=stop_handler;
|
||||
CALLBACK_SetDescription(call_stop,"stop");
|
||||
phys_writeb(CB_BASE+(call_stop<<4)+0,0xFE);
|
||||
phys_writeb(CB_BASE+(call_stop<<4)+1,0x38);
|
||||
phys_writew(CB_BASE+(call_stop<<4)+2,call_stop);
|
||||
/* Setup the idle handler */
|
||||
call_idle=CALLBACK_Allocate();
|
||||
CallBack_Handlers[call_idle]=stop_handler;
|
||||
CALLBACK_SetDescription(call_idle,"idle");
|
||||
for (i=0;i<=11;i++) phys_writeb(CB_BASE+(call_idle<<4)+i,0x90);
|
||||
phys_writeb(CB_BASE+(call_idle<<4)+12,0xFE);
|
||||
phys_writeb(CB_BASE+(call_idle<<4)+13,0x38);
|
||||
@ -217,7 +218,7 @@ void CALLBACK_Init(Section* sec) {
|
||||
|
||||
/* Setup all Interrupt to point to the default handler */
|
||||
call_default=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_default,&default_handler,CB_IRET);
|
||||
CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default");
|
||||
/* Only setup default handler for first half of interrupt table */
|
||||
for (i=0;i<0x40;i++) {
|
||||
real_writed(0,i*4,CALLBACK_RealPointer(call_default));
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -33,10 +33,11 @@
|
||||
#include "paging.h"
|
||||
#include "inout.h"
|
||||
|
||||
#define CACHE_TOTAL (1024*1024*2)
|
||||
#define CACHE_TOTAL (512*1024)
|
||||
#define CACHE_MAXSIZE (4096)
|
||||
#define CACHE_BLOCKS (50*1024)
|
||||
#define CACHE_BLOCKS (32*1024)
|
||||
#define CACHE_ALIGN (16)
|
||||
#define CACHE_PAGES (128)
|
||||
#define DYN_HASH_SHIFT (4)
|
||||
#define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT)
|
||||
#define DYN_LINKS (16)
|
||||
@ -68,8 +69,8 @@ enum DualOps {
|
||||
DOP_SUB,DOP_SBB,
|
||||
DOP_CMP,DOP_XOR,
|
||||
DOP_AND,DOP_OR,
|
||||
DOP_MOV,
|
||||
DOP_TEST,
|
||||
DOP_MOV,
|
||||
DOP_XCHG,
|
||||
};
|
||||
|
||||
@ -77,7 +78,7 @@ enum ShiftOps {
|
||||
SHIFT_ROL,SHIFT_ROR,
|
||||
SHIFT_RCL,SHIFT_RCR,
|
||||
SHIFT_SHL,SHIFT_SHR,
|
||||
SHIFT_SAR,
|
||||
SHIFT_SAL,SHIFT_SAR,
|
||||
};
|
||||
|
||||
enum BranchTypes {
|
||||
@ -87,19 +88,15 @@ enum BranchTypes {
|
||||
BR_L,BR_NL,BR_LE,BR_NLE
|
||||
};
|
||||
|
||||
enum BlockType {
|
||||
BT_Free=0,
|
||||
BT_Normal,
|
||||
BT_SingleLink,
|
||||
BT_DualLink,
|
||||
BT_CheckFlags,
|
||||
};
|
||||
|
||||
enum BlockReturn {
|
||||
BR_Normal=0,
|
||||
BR_Cycles,
|
||||
BR_Link1,BR_Link2,
|
||||
BR_Opcode,
|
||||
#if (C_DEBUG)
|
||||
BR_OpcodeFull,
|
||||
#endif
|
||||
BR_CallBack,
|
||||
};
|
||||
|
||||
@ -153,28 +150,23 @@ struct DynState {
|
||||
DynReg regs[G_MAX];
|
||||
};
|
||||
|
||||
static void dyn_releaseregs(void) {
|
||||
for (Bitu i=0;i<G_MAX;i++) gen_releasereg(&DynRegs[i]);
|
||||
}
|
||||
static void dyn_load_flags(void) {
|
||||
/* Load the host flags with emulated flags */
|
||||
gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(FLAGS));
|
||||
gen_dop_word_imm(DOP_AND,true,DREG(TMPW),FMASK_TEST);
|
||||
gen_load_flags(DREG(TMPW));
|
||||
gen_releasereg(DREG(TMPW));
|
||||
static void dyn_flags_host_to_gen(void) {
|
||||
gen_dop_word(DOP_MOV,true,DREG(EXIT),DREG(FLAGS));
|
||||
gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST);
|
||||
gen_load_flags(DREG(EXIT));
|
||||
gen_releasereg(DREG(EXIT));
|
||||
gen_releasereg(DREG(FLAGS));
|
||||
}
|
||||
|
||||
static void dyn_save_flags(bool stored=false) {
|
||||
/* Store the host flags back in emulated ones */
|
||||
gen_save_flags(DREG(EXIT),stored);
|
||||
static void dyn_flags_gen_to_host(void) {
|
||||
gen_save_flags(DREG(EXIT));
|
||||
gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST);
|
||||
gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FMASK_TEST);
|
||||
gen_dop_word(DOP_OR,true,DREG(FLAGS),DREG(EXIT)); //flags are marked for save
|
||||
gen_releasereg(DREG(EXIT));
|
||||
gen_releasereg(DREG(FLAGS));
|
||||
}
|
||||
|
||||
|
||||
static void dyn_savestate(DynState * state) {
|
||||
for (Bitu i=0;i<G_MAX;i++) {
|
||||
state->regs[i].flags=DynRegs[i].flags;
|
||||
@ -201,80 +193,61 @@ Bits CPU_Core_Dyn_X86_Run(void) {
|
||||
restart_core:
|
||||
PhysPt ip_point=SegPhys(cs)+reg_eip;
|
||||
Bitu ip_page=ip_point>>12;
|
||||
mem_readb(ip_point); //Init whatever page we are in
|
||||
PageHandler * handler=paging.tlb.handler[ip_page];
|
||||
CodePageHandler * chandler=0;
|
||||
#if C_HEAVY_DEBUG
|
||||
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
|
||||
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
|
||||
#endif
|
||||
if (handler->flags & PFLAG_HASCODE) {
|
||||
/* Find correct Dynamic Block to run */
|
||||
chandler=(CodePageHandler *)handler;
|
||||
findblock:;
|
||||
CacheBlock * block=chandler->FindCacheBlock(ip_point&4095);
|
||||
if (!block) {
|
||||
cache.block.running=0;
|
||||
block=CreateCacheBlock(ip_point,cpu.code.big,128);
|
||||
// DYN_LOG("Created block size %x type %d",block->cache.size,block->type);
|
||||
chandler->AddCacheBlock(block);
|
||||
if (block->page.end>=4096) {
|
||||
DYN_LOG("block crosses page boundary");
|
||||
}
|
||||
}
|
||||
run_block:
|
||||
BlockReturn ret=gen_runcode(block->cache.start);
|
||||
switch (ret) {
|
||||
case BR_Normal:
|
||||
/* Maybe check if we staying in the same page? */
|
||||
#if C_HEAVY_DEBUG
|
||||
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
|
||||
#endif
|
||||
goto restart_core;
|
||||
case BR_Cycles:
|
||||
#if C_HEAVY_DEBUG
|
||||
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
|
||||
#endif
|
||||
return CBRET_NONE;
|
||||
case BR_CallBack:
|
||||
return core_dyn.callback;
|
||||
case BR_Opcode:
|
||||
CPU_CycleLeft+=CPU_Cycles;
|
||||
CPU_Cycles=1;
|
||||
return CPU_Core_Normal_Run();
|
||||
case BR_Link1:
|
||||
case BR_Link2:
|
||||
{
|
||||
Bitu temp_ip=SegPhys(cs)+reg_eip;
|
||||
Bitu temp_page=temp_ip >> 12;
|
||||
CodePageHandler * temp_handler=(CodePageHandler *)paging.tlb.handler[temp_page];
|
||||
if (temp_handler->flags & PFLAG_HASCODE) {
|
||||
block=temp_handler->FindCacheBlock(temp_ip & 4095);
|
||||
if (!block) goto restart_core;
|
||||
cache_linkblocks(cache.block.running,block,ret==BR_Link2);
|
||||
goto run_block;
|
||||
}
|
||||
}
|
||||
goto restart_core;
|
||||
}
|
||||
} else {
|
||||
if (handler->flags & PFLAG_NOCODE) {
|
||||
LOG_MSG("DYNX86:Can't run code in this page");
|
||||
return CPU_Core_Normal_Run();
|
||||
}
|
||||
Bitu phys_page=ip_page;
|
||||
if (!PAGING_MakePhysPage(phys_page)) {
|
||||
LOG_MSG("DYNX86:Can't find physpage");
|
||||
return CPU_Core_Normal_Run();
|
||||
}
|
||||
chandler=new CodePageHandler(handler);
|
||||
MEM_SetPageHandler(phys_page,1,chandler); //Setup the handler
|
||||
PAGING_UnlinkPages(ip_page,1);
|
||||
goto findblock;
|
||||
CodePageHandler * chandler=MakeCodePage(ip_page);
|
||||
if (!chandler) return CPU_Core_Normal_Run();
|
||||
/* Find correct Dynamic Block to run */
|
||||
CacheBlock * block=chandler->FindCacheBlock(ip_point&4095);
|
||||
if (!block) {
|
||||
block=CreateCacheBlock(chandler,ip_point,32);
|
||||
}
|
||||
return 0;
|
||||
run_block:
|
||||
cache.block.running=0;
|
||||
BlockReturn ret=gen_runcode(block->cache.start);
|
||||
switch (ret) {
|
||||
case BR_Normal:
|
||||
/* Maybe check if we staying in the same page? */
|
||||
#if C_HEAVY_DEBUG
|
||||
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
|
||||
#endif
|
||||
goto restart_core;
|
||||
case BR_Cycles:
|
||||
#if C_HEAVY_DEBUG
|
||||
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
|
||||
#endif
|
||||
return CBRET_NONE;
|
||||
case BR_CallBack:
|
||||
return core_dyn.callback;
|
||||
case BR_Opcode:
|
||||
CPU_CycleLeft+=CPU_Cycles;
|
||||
CPU_Cycles=1;
|
||||
return CPU_Core_Normal_Run();
|
||||
#if (C_DEBUG)
|
||||
case BR_OpcodeFull:
|
||||
CPU_CycleLeft+=CPU_Cycles;
|
||||
CPU_Cycles=1;
|
||||
return CPU_Core_Full_Run();
|
||||
#endif
|
||||
case BR_Link1:
|
||||
case BR_Link2:
|
||||
{
|
||||
Bitu temp_ip=SegPhys(cs)+reg_eip;
|
||||
Bitu temp_page=temp_ip >> 12;
|
||||
CodePageHandler * temp_handler=(CodePageHandler *)paging.tlb.handler[temp_page];
|
||||
if (temp_handler->flags & PFLAG_HASCODE) {
|
||||
block=temp_handler->FindCacheBlock(temp_ip & 4095);
|
||||
if (!block) goto restart_core;
|
||||
cache.block.running->LinkTo(ret==BR_Link2,block);
|
||||
goto run_block;
|
||||
}
|
||||
}
|
||||
goto restart_core;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void CPU_Core_Dyn_X86_Init(void) {
|
||||
Bits i;
|
||||
/* Setup the global registers and their flags */
|
||||
|
@ -1,28 +1,34 @@
|
||||
struct CacheBlock {
|
||||
class CacheBlock {
|
||||
public:
|
||||
void Clear(void);
|
||||
void LinkTo(Bitu index,CacheBlock * toblock) {
|
||||
assert(toblock);
|
||||
link[index].to=toblock;
|
||||
link[index].next=toblock->link[index].from;
|
||||
toblock->link[index].from=this;
|
||||
}
|
||||
struct {
|
||||
Bit16s start,end; //Where the page is the original code
|
||||
Bitu first,last;
|
||||
Bit16u start,end; //Where the page is the original code
|
||||
CodePageHandler * handler; //Page containing this code
|
||||
} page;
|
||||
struct {
|
||||
Bit8u * start; //Where in the cache are we
|
||||
Bitu size;
|
||||
CacheBlock * next;
|
||||
} cache;
|
||||
BlockType type;
|
||||
CodePageHandler * code_page; //Page containing this code
|
||||
CacheBlock * page_link; //For code crossing a page boundary
|
||||
struct {
|
||||
Bitu index;
|
||||
CacheBlock * next;
|
||||
} hash;
|
||||
CacheBlock * list_next;
|
||||
struct {
|
||||
CacheBlock * to[2];
|
||||
CacheBlock * from[DYN_LINKS];
|
||||
Bitu index;
|
||||
} link;
|
||||
CacheBlock * links[2];
|
||||
CacheBlock * to;
|
||||
CacheBlock * next;
|
||||
CacheBlock * from;
|
||||
} link[2];
|
||||
CacheBlock * crossblock;
|
||||
};
|
||||
|
||||
class CacheBlock;
|
||||
static struct {
|
||||
struct {
|
||||
CacheBlock * first;
|
||||
@ -31,96 +37,124 @@ static struct {
|
||||
CacheBlock * running;
|
||||
} block;
|
||||
Bit8u * pos;
|
||||
CacheBlock linkblocks[2];
|
||||
CodePageHandler * free_pages;
|
||||
CodePageHandler * used_pages;
|
||||
CodePageHandler * last_page;
|
||||
} cache;
|
||||
|
||||
static Bit8u cache_code_link_blocks[2][16];
|
||||
static Bit8u cache_code[CACHE_TOTAL+CACHE_MAXSIZE];
|
||||
static CacheBlock cache_blocks[CACHE_BLOCKS];
|
||||
|
||||
static void cache_resetblock(CacheBlock * block);
|
||||
|
||||
static CacheBlock link_blocks[2];
|
||||
class CodePageHandler :public PageHandler {
|
||||
public:
|
||||
CodePageHandler(PageHandler * _old_pagehandler) {
|
||||
CodePageHandler() {}
|
||||
void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
|
||||
phys_page=_phys_page;
|
||||
old_pagehandler=_old_pagehandler;
|
||||
flags=old_pagehandler->flags|PFLAG_HASCODE;
|
||||
flags&=~PFLAG_WRITEABLE;
|
||||
active_blocks=0;
|
||||
active_count=16;
|
||||
memset(&hash_map,0,sizeof(hash_map));
|
||||
memset(&write_map,0,sizeof(write_map));
|
||||
}
|
||||
void InvalidateRange(Bits start,Bits end) {
|
||||
Bits maps=start>>DYN_HASH_SHIFT;
|
||||
Bits map=maps;
|
||||
Bits count=write_map[maps];
|
||||
while (map>=0 && count>0) {
|
||||
CacheBlock * block=hash_map[map];
|
||||
CacheBlock * * where=&hash_map[map];
|
||||
void InvalidateRange(Bitu start,Bitu end) {
|
||||
Bits index=1+(start>>DYN_HASH_SHIFT);
|
||||
while (index>=0) {
|
||||
Bitu map=0;
|
||||
for (Bitu count=start;count<=end;count++) map+=write_map[count];
|
||||
if (!map) return;
|
||||
CacheBlock * block=hash_map[index];
|
||||
while (block) {
|
||||
CacheBlock * nextblock=block->hash.next;
|
||||
if (start<=block->page.end && end>=block->page.start) {
|
||||
for (Bitu i=block->page.first;i<=block->page.last;i++) write_map[i]--;
|
||||
block->code_page=0; //Else resetblock will do double work
|
||||
count--;
|
||||
if (block==cache.block.running) LOG_MSG("Writing to current block");
|
||||
cache_resetblock(block);
|
||||
*where=nextblock;
|
||||
} else {
|
||||
where=&block->hash.next;
|
||||
}
|
||||
if (start<=block->page.end && end>=block->page.start)
|
||||
block->Clear();
|
||||
block=nextblock;
|
||||
}
|
||||
map--;
|
||||
index--;
|
||||
}
|
||||
}
|
||||
void writeb(PhysPt addr,Bitu val){
|
||||
if (val!=host_readb(hostmem+(addr&4095))) {
|
||||
InvalidateRange(addr&4095,addr&4095);
|
||||
host_writeb(hostmem+(addr&4095),val);
|
||||
}
|
||||
addr&=4095;
|
||||
host_writeb(hostmem+addr,val);
|
||||
if (!*(Bit8u*)&write_map[addr]) {
|
||||
if (active_blocks) return;
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
} else InvalidateRange(addr,addr);
|
||||
}
|
||||
void writew(PhysPt addr,Bitu val){
|
||||
if (val!=host_readw(hostmem+(addr&4095))) {
|
||||
InvalidateRange(addr&4095,(addr&4095)+1);
|
||||
host_writew(hostmem+(addr&4095),val);
|
||||
}
|
||||
addr&=4095;
|
||||
host_writew(hostmem+addr,val);
|
||||
if (!*(Bit16u*)&write_map[addr]) {
|
||||
if (active_blocks) return;
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
} else InvalidateRange(addr,addr+1);
|
||||
}
|
||||
void writed(PhysPt addr,Bitu val){
|
||||
if (val!=host_readd(hostmem+(addr&4095))) {
|
||||
InvalidateRange(addr&4095,(addr&4095)+3);
|
||||
host_writed(hostmem+(addr&4095),val);
|
||||
}
|
||||
addr&=4095;
|
||||
host_writed(hostmem+addr,val);
|
||||
if (!*(Bit32u*)&write_map[addr]) {
|
||||
if (active_blocks) return;
|
||||
active_count--;
|
||||
if (!active_count) Release();
|
||||
} else InvalidateRange(addr,addr+3);
|
||||
}
|
||||
void AddCacheBlock(CacheBlock * block) {
|
||||
Bit16u first,last;
|
||||
if (block->page.start<0) first=0;
|
||||
else first=block->page.start>>DYN_HASH_SHIFT;
|
||||
block->hash.next=hash_map[first];
|
||||
hash_map[first]=block;
|
||||
if (block->page.end>=4096) last=DYN_PAGE_HASH-1;
|
||||
else last=block->page.end>>DYN_HASH_SHIFT;
|
||||
block->page.first=first;
|
||||
block->page.last=last;
|
||||
for (;first<=last;first++) {
|
||||
write_map[first]++;
|
||||
}
|
||||
block->code_page=this;
|
||||
Bitu index=1+(block->page.start>>DYN_HASH_SHIFT);
|
||||
block->hash.next=hash_map[index];
|
||||
block->hash.index=index;
|
||||
hash_map[index]=block;
|
||||
block->page.handler=this;
|
||||
active_blocks++;
|
||||
}
|
||||
void AddCrossBlock(CacheBlock * block) {
|
||||
block->hash.next=hash_map[0];
|
||||
block->hash.index=0;
|
||||
hash_map[0]=block;
|
||||
block->page.handler=this;
|
||||
active_blocks++;
|
||||
}
|
||||
void DelCacheBlock(CacheBlock * block) {
|
||||
CacheBlock * * where=&hash_map[block->page.first];
|
||||
while (*where) {
|
||||
if (*where==block) {
|
||||
*where=block->hash.next;
|
||||
break;
|
||||
}
|
||||
active_blocks--;
|
||||
active_count=16;
|
||||
CacheBlock * * where=&hash_map[block->hash.index];
|
||||
while (*where!=block) {
|
||||
where=&((*where)->hash.next);
|
||||
//Will crash if a block isn't found, which should never happen.
|
||||
}
|
||||
for (Bitu i=block->page.first;i<=block->page.last;i++) {
|
||||
write_map[i]--;
|
||||
*where=block->hash.next;
|
||||
for (Bitu i=block->page.start;i<=block->page.end;i++) {
|
||||
if (write_map[i]) write_map[i]--;
|
||||
}
|
||||
}
|
||||
void Release(void) {
|
||||
MEM_SetPageHandler(phys_page,1,old_pagehandler);
|
||||
PAGING_ClearTLB();
|
||||
if (prev) prev->next=next;
|
||||
else cache.used_pages=next;
|
||||
if (next) next->prev=prev;
|
||||
else cache.last_page=prev;
|
||||
next=cache.free_pages;
|
||||
cache.free_pages=this;
|
||||
prev=0;
|
||||
}
|
||||
void ClearRelease(void) {
|
||||
for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) {
|
||||
CacheBlock * block=hash_map[index];
|
||||
while (block) {
|
||||
CacheBlock * nextblock=block->hash.next;
|
||||
block->page.handler=0; //No need, full clear
|
||||
block->Clear();
|
||||
block=nextblock;
|
||||
}
|
||||
}
|
||||
Release();
|
||||
}
|
||||
CacheBlock * FindCacheBlock(Bitu start) {
|
||||
CacheBlock * block=hash_map[start>>DYN_HASH_SHIFT];
|
||||
CacheBlock * block=hash_map[1+(start>>DYN_HASH_SHIFT)];
|
||||
while (block) {
|
||||
if (block->page.start==start) return block;
|
||||
block=block->hash.next;
|
||||
@ -131,133 +165,153 @@ public:
|
||||
hostmem=old_pagehandler->GetHostPt(phys_page);
|
||||
return hostmem;
|
||||
}
|
||||
public:
|
||||
Bit8u write_map[4096];
|
||||
CodePageHandler * next, * prev;
|
||||
private:
|
||||
PageHandler * old_pagehandler;
|
||||
CacheBlock * hash_map[DYN_PAGE_HASH];
|
||||
Bit8u write_map[DYN_PAGE_HASH];
|
||||
CacheBlock * hash_map[1+DYN_PAGE_HASH];
|
||||
Bitu active_blocks;
|
||||
Bitu active_count;
|
||||
HostPt hostmem;
|
||||
Bitu phys_page;
|
||||
};
|
||||
|
||||
|
||||
static CodePageHandler * MakeCodePage(Bitu lin_page) {
|
||||
mem_readb(lin_page << 12); //Ensure page contains memory
|
||||
PageHandler * handler=paging.tlb.handler[lin_page];
|
||||
if (handler->flags & PFLAG_HASCODE) return ( CodePageHandler *)handler;
|
||||
if (handler->flags & PFLAG_NOCODE) {
|
||||
LOG_MSG("DYNX86:Can't run code in this page");
|
||||
return 0;
|
||||
}
|
||||
Bitu phys_page=lin_page;
|
||||
if (!PAGING_MakePhysPage(phys_page)) {
|
||||
LOG_MSG("DYNX86:Can't find physpage");
|
||||
return 0;
|
||||
}
|
||||
/* Find a free CodePage */
|
||||
if (!cache.free_pages) {
|
||||
cache.used_pages->ClearRelease();
|
||||
}
|
||||
CodePageHandler * cpagehandler=cache.free_pages;
|
||||
cache.free_pages=cache.free_pages->next;
|
||||
cpagehandler->prev=cache.last_page;
|
||||
cpagehandler->next=0;
|
||||
if (cache.last_page) cache.last_page->next=cpagehandler;
|
||||
cache.last_page=cpagehandler;
|
||||
if (!cache.used_pages) cache.used_pages=cpagehandler;
|
||||
cpagehandler->SetupAt(phys_page,handler);
|
||||
MEM_SetPageHandler(phys_page,1,cpagehandler);
|
||||
PAGING_UnlinkPages(lin_page,1);
|
||||
return cpagehandler;
|
||||
}
|
||||
|
||||
static INLINE void cache_addunsedblock(CacheBlock * block) {
|
||||
block->list_next=cache.block.free;
|
||||
block->cache.next=cache.block.free;
|
||||
cache.block.free=block;
|
||||
}
|
||||
|
||||
static CacheBlock * cache_getblock(void) {
|
||||
CacheBlock * ret=cache.block.free;
|
||||
if (!ret) E_Exit("Ran out of CacheBlocks" );
|
||||
cache.block.free=ret->list_next;
|
||||
cache.block.free=ret->cache.next;
|
||||
ret->cache.next=0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static INLINE void cache_clearlinkfrom(CacheBlock * block,CacheBlock * from) {
|
||||
for (Bitu i=0;i<DYN_LINKS;i++) {
|
||||
if (block->link.from[i]==from) block->link.from[i]=0;
|
||||
void CacheBlock::Clear(void) {
|
||||
Bitu ind;
|
||||
/* Check if this is not a cross page block */
|
||||
if (hash.index) for (ind=0;ind<2;ind++) {
|
||||
CacheBlock * fromlink=link[ind].from;
|
||||
link[ind].from=0;
|
||||
while (fromlink) {
|
||||
CacheBlock * nextlink=fromlink->link[ind].next;
|
||||
fromlink->link[ind].next=0;
|
||||
fromlink->link[ind].to=&link_blocks[ind];
|
||||
fromlink=nextlink;
|
||||
}
|
||||
if (link[ind].to!=&link_blocks[ind]) {
|
||||
CacheBlock * * wherelink=&link[ind].to->link[ind].from;
|
||||
while (*wherelink!=this) {
|
||||
wherelink=&(*wherelink)->link[ind].next;
|
||||
}
|
||||
*wherelink=(*wherelink)->link[ind].next;
|
||||
}
|
||||
} else
|
||||
cache_addunsedblock(this);
|
||||
if (crossblock) {
|
||||
crossblock->crossblock=0;
|
||||
crossblock->Clear();
|
||||
crossblock=0;
|
||||
}
|
||||
if (page.handler) {
|
||||
page.handler->DelCacheBlock(this);
|
||||
page.handler=0;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void cache_clearlinkto(CacheBlock * block,CacheBlock * to) {
|
||||
if (block->link.to[0]==to) block->link.to[0]=&cache.linkblocks[0];
|
||||
if (block->link.to[1]==to) block->link.to[1]=&cache.linkblocks[1];
|
||||
}
|
||||
|
||||
static void cache_linkblocks(CacheBlock * from,CacheBlock * to,Bitu link) {
|
||||
from->link.to[link]=to;
|
||||
CacheBlock * clear=to->link.from[to->link.index];
|
||||
if (clear) {
|
||||
DYN_LOG("backlink buffer full");
|
||||
cache_clearlinkto(to->link.from[to->link.index],to);
|
||||
}
|
||||
to->link.from[to->link.index]=from;
|
||||
to->link.index++;
|
||||
if (to->link.index>=DYN_LINKS) to->link.index=0;
|
||||
}
|
||||
|
||||
static void cache_resetblock(CacheBlock * block) {
|
||||
Bits i;
|
||||
DYN_LOG("Resetted block");
|
||||
block->type=BT_Free;
|
||||
/* Clear all links to this block from other blocks */
|
||||
for (i=0;i<DYN_LINKS;i++) {
|
||||
if (block->link.from[i]) cache_clearlinkto(block->link.from[i],block);
|
||||
block->link.from[i]=0;
|
||||
}
|
||||
/* Clear all links from this block to other blocks */
|
||||
if (block->link.to[0]!=&cache.linkblocks[0]) {
|
||||
cache_clearlinkfrom(block->link.to[0],block);
|
||||
block->link.to[0]=&cache.linkblocks[0];
|
||||
}
|
||||
if (block->link.to[1]!=&cache.linkblocks[1]) {
|
||||
cache_clearlinkfrom(block->link.to[1],block);
|
||||
block->link.to[1]=&cache.linkblocks[1];
|
||||
}
|
||||
block->link.index=0;
|
||||
if (block->code_page) block->code_page->DelCacheBlock(block);
|
||||
}
|
||||
|
||||
static CacheBlock * cache_openblock(void) {
|
||||
CacheBlock * block=cache.block.active;
|
||||
/* check for enough space in this block */
|
||||
Bitu size=block->cache.size;
|
||||
CacheBlock * nextblock=block->list_next;
|
||||
CacheBlock * nextblock=block->cache.next;
|
||||
if (block->page.handler)
|
||||
block->Clear();
|
||||
while (size<CACHE_MAXSIZE) {
|
||||
if (!nextblock) goto skipresize;
|
||||
if (!nextblock)
|
||||
goto skipresize;
|
||||
size+=nextblock->cache.size;
|
||||
CacheBlock * tempblock=nextblock->list_next;
|
||||
if (nextblock->type!=BT_Free) cache_resetblock(nextblock);
|
||||
CacheBlock * tempblock=nextblock->cache.next;
|
||||
if (nextblock->page.handler)
|
||||
nextblock->Clear();
|
||||
cache_addunsedblock(nextblock);
|
||||
nextblock=tempblock;
|
||||
}
|
||||
skipresize:
|
||||
block->cache.size=size;
|
||||
block->list_next=nextblock;
|
||||
block->cache.next=nextblock;
|
||||
cache.pos=block->cache.start;
|
||||
return block;
|
||||
}
|
||||
|
||||
static void cache_closeblock(BlockType type) {
|
||||
static void cache_closeblock(void) {
|
||||
CacheBlock * block=cache.block.active;
|
||||
/* Setup some structures in the block determined by type */
|
||||
block->type=type;
|
||||
switch (type) {
|
||||
case BT_Normal:
|
||||
break;
|
||||
case BT_SingleLink:
|
||||
block->link.to[0]=&cache.linkblocks[0];
|
||||
break;
|
||||
case BT_DualLink:
|
||||
block->link.to[0]=&cache.linkblocks[0];
|
||||
block->link.to[1]=&cache.linkblocks[1];
|
||||
break;
|
||||
}
|
||||
block->link[0].to=&link_blocks[0];
|
||||
block->link[1].to=&link_blocks[1];
|
||||
block->link[0].from=0;
|
||||
block->link[1].from=0;
|
||||
block->link[0].next=0;
|
||||
block->link[1].next=0;
|
||||
/* Close the block with correct alignments */
|
||||
Bitu written=cache.pos-block->cache.start;
|
||||
if (written>block->cache.size) {
|
||||
if (!block->list_next) {
|
||||
if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun");
|
||||
} else E_Exit("CacheBlock overrun");
|
||||
if (!block->cache.next) {
|
||||
if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size);
|
||||
} else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size);
|
||||
} else {
|
||||
Bitu new_size;
|
||||
Bitu left=block->cache.size-written;
|
||||
/* Smaller than cache align then don't bother to resize */
|
||||
if (left>CACHE_ALIGN) {
|
||||
new_size=((written-1)|(CACHE_ALIGN-1))+1;
|
||||
} else new_size=block->cache.size;
|
||||
CacheBlock * newblock=cache_getblock();
|
||||
newblock->cache.start=block->cache.start+new_size;
|
||||
newblock->cache.size=block->cache.size-new_size;
|
||||
newblock->list_next=block->list_next;
|
||||
newblock->type=BT_Free;
|
||||
block->cache.size=new_size;
|
||||
block->list_next=newblock;
|
||||
CacheBlock * newblock=cache_getblock();
|
||||
newblock->cache.start=block->cache.start+new_size;
|
||||
newblock->cache.size=block->cache.size-new_size;
|
||||
newblock->cache.next=block->cache.next;
|
||||
block->cache.next=newblock;
|
||||
block->cache.size=new_size;
|
||||
}
|
||||
}
|
||||
/* Advance the active block pointer */
|
||||
if (!block->list_next) {
|
||||
DYN_LOG("Cache full restarting");
|
||||
if (!block->cache.next) {
|
||||
// LOG_MSG("Cache full restarting");
|
||||
cache.block.active=cache.block.first;
|
||||
} else {
|
||||
cache.block.active=block->list_next;
|
||||
cache.block.active=block->cache.next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,20 +337,29 @@ static void cache_init(void) {
|
||||
memset(&cache_blocks,0,sizeof(cache_blocks));
|
||||
cache.block.free=&cache_blocks[0];
|
||||
for (i=0;i<CACHE_BLOCKS-1;i++) {
|
||||
cache_blocks[i].list_next=&cache_blocks[i+1];
|
||||
cache_blocks[i].link.to[0]=&cache.linkblocks[0];
|
||||
cache_blocks[i].link.to[1]=&cache.linkblocks[1];
|
||||
cache_blocks[i].link[0].to=(CacheBlock *)1;
|
||||
cache_blocks[i].link[1].to=(CacheBlock *)1;
|
||||
cache_blocks[i].cache.next=&cache_blocks[i+1];
|
||||
}
|
||||
CacheBlock * block=cache_getblock();
|
||||
cache.block.first=block;
|
||||
cache.block.active=block;
|
||||
block->cache.start=&cache_code[0];
|
||||
block->cache.size=CACHE_TOTAL;
|
||||
block->list_next=0; //Last block in the list
|
||||
block->cache.next=0; //Last block in the list
|
||||
cache.pos=&cache_code_link_blocks[0][0];
|
||||
cache.linkblocks[0].cache.start=cache.pos;
|
||||
link_blocks[0].cache.start=cache.pos;
|
||||
gen_return(BR_Link1);
|
||||
cache.pos=&cache_code_link_blocks[1][0];
|
||||
cache.linkblocks[1].cache.start=cache.pos;
|
||||
link_blocks[1].cache.start=cache.pos;
|
||||
gen_return(BR_Link2);
|
||||
}
|
||||
cache.free_pages=0;
|
||||
cache.last_page=0;
|
||||
cache.used_pages=0;
|
||||
/* Setup the code pages */
|
||||
for (i=0;i<CACHE_PAGES-1;i++) {
|
||||
CodePageHandler * newpage=new CodePageHandler();
|
||||
newpage->next=cache.free_pages;
|
||||
cache.free_pages=newpage;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,57 +1,57 @@
|
||||
static Bitu dyn_helper_divb(Bit8u val) {
|
||||
if (!val) return 1;
|
||||
static bool dyn_helper_divb(Bit8u val) {
|
||||
if (!val) return CPU_PrepareException(0,0);
|
||||
Bitu quo=reg_ax / val;
|
||||
reg_ah=(Bit8u)(reg_ax % val);
|
||||
reg_al=(Bit8u)quo;
|
||||
if (quo>0xff) return 1;
|
||||
return 0;
|
||||
if (quo>0xff) return CPU_PrepareException(0,0);
|
||||
return false;
|
||||
}
|
||||
|
||||
static Bitu dyn_helper_idivb(Bit8s val) {
|
||||
if (!val) return 1;
|
||||
static bool dyn_helper_idivb(Bit8s val) {
|
||||
if (!val) return CPU_PrepareException(0,0);
|
||||
Bits quo=(Bit16s)reg_ax / val;
|
||||
reg_ah=(Bit8s)((Bit16s)reg_ax % val);
|
||||
reg_al=(Bit8s)quo;
|
||||
if (quo!=(Bit8s)reg_al) return 1;
|
||||
return 0;
|
||||
if (quo!=(Bit8s)reg_al) return CPU_PrepareException(0,0);
|
||||
return false;
|
||||
}
|
||||
|
||||
static Bitu dyn_helper_divw(Bit16u val) {
|
||||
if (!val) return 1;
|
||||
static bool dyn_helper_divw(Bit16u val) {
|
||||
if (!val) return CPU_PrepareException(0,0);
|
||||
Bitu num=(reg_dx<<16)|reg_ax;
|
||||
Bitu quo=num/val;
|
||||
reg_dx=(Bit16u)(num % val);
|
||||
reg_ax=(Bit16u)quo;
|
||||
if (quo!=reg_ax) return 1;
|
||||
return 0;
|
||||
if (quo!=reg_ax) return CPU_PrepareException(0,0);
|
||||
return false;
|
||||
}
|
||||
|
||||
static Bitu dyn_helper_idivw(Bit16s val) {
|
||||
if (!val) return 1;
|
||||
static bool dyn_helper_idivw(Bit16s val) {
|
||||
if (!val) return CPU_PrepareException(0,0);
|
||||
Bits num=(reg_dx<<16)|reg_ax;
|
||||
Bits quo=num/val;
|
||||
reg_dx=(Bit16s)(num % val);
|
||||
reg_ax=(Bit16s)quo;
|
||||
if (quo!=(Bit16s)reg_ax) return 1;
|
||||
return 0;
|
||||
if (quo!=(Bit16s)reg_ax) return CPU_PrepareException(0,0);
|
||||
return false;
|
||||
}
|
||||
|
||||
static Bitu dyn_helper_divd(Bit32u val) {
|
||||
if (!val) return 1;
|
||||
static bool dyn_helper_divd(Bit32u val) {
|
||||
if (!val) return CPU_PrepareException(0,0);
|
||||
Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax;
|
||||
Bit64u quo=num/val;
|
||||
reg_edx=(Bit32u)(num % val);
|
||||
reg_eax=(Bit32u)quo;
|
||||
if (quo!=(Bit64u)reg_eax) return 1;
|
||||
return 0;
|
||||
if (quo!=(Bit64u)reg_eax) return CPU_PrepareException(0,0);
|
||||
return false;
|
||||
}
|
||||
|
||||
static Bitu dyn_helper_idivd(Bit32s val) {
|
||||
if (!val) return 1;
|
||||
static bool dyn_helper_idivd(Bit32s val) {
|
||||
if (!val) return CPU_PrepareException(0,0);
|
||||
Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax;
|
||||
Bit64s quo=num/val;
|
||||
reg_edx=(Bit32s)(num % val);
|
||||
reg_eax=(Bit32s)(quo);
|
||||
if (quo!=(Bit64s)((Bit32s)reg_eax)) return 1;
|
||||
return 0;
|
||||
if (quo!=(Bit64s)((Bit32s)reg_eax)) return CPU_PrepareException(0,0);
|
||||
return false;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -32,8 +32,8 @@ static void gen_init(void);
|
||||
#define X86_REG_MASK(_REG_) (1 << X86_REG_ ## _REG_)
|
||||
|
||||
static struct {
|
||||
bool flagsactive;
|
||||
Bitu last_used;
|
||||
Bitu stored_flags;
|
||||
GenReg * regs[X86_REGS];
|
||||
} x86gen;
|
||||
|
||||
@ -98,13 +98,13 @@ static BlockReturn gen_runcode(Bit8u * code) {
|
||||
push edi
|
||||
mov ebx,[reg_flags]
|
||||
and ebx,FMASK_TEST
|
||||
push offset(return_address)
|
||||
push ebx
|
||||
popfd
|
||||
call eax
|
||||
jmp eax
|
||||
/* Restore the flags */
|
||||
pushfd
|
||||
return_address:
|
||||
/* return here with flags in ecx */
|
||||
and dword ptr [reg_flags],~FMASK_TEST
|
||||
pop ecx
|
||||
and ecx,FMASK_TEST
|
||||
or [reg_flags],ecx
|
||||
pop edi
|
||||
@ -114,23 +114,19 @@ static BlockReturn gen_runcode(Bit8u * code) {
|
||||
mov [retval],eax
|
||||
}
|
||||
#else
|
||||
register Bit32u tempflags=reg_flags & FMASK_TEST;
|
||||
__asm__ volatile (
|
||||
"movl %1,%%esi \n"
|
||||
"andl %2,%%esi \n"
|
||||
"pushl %%ebp \n"
|
||||
"pushl %%esi \n"
|
||||
"popfl \n"
|
||||
"calll *%4 \n"
|
||||
"popl %%ebp \n"
|
||||
"pushfl \n"
|
||||
"andl %3,(%1) \n"
|
||||
"popl %%esi \n"
|
||||
"andl %2,%%esi \n"
|
||||
"orl %%esi,(%1) \n"
|
||||
:"=a" (retval)
|
||||
:"m" (reg_flags), "n" (FMASK_TEST),"n" (~FMASK_TEST),"r" (code)
|
||||
:"%ecx","%edx","%ebx","%edi","%esi","cc","memory"
|
||||
"pushl %%ebp \n"
|
||||
"pushl $(run_return_adress) \n"
|
||||
"pushl %2 \n"
|
||||
"jmp *%3 \n"
|
||||
"run_return_adress: \n"
|
||||
"popl %%ebp \n"
|
||||
:"=a" (retval), "=c" (tempflags)
|
||||
:"r" (tempflags),"r" (code)
|
||||
:"%edx","%ebx","%edi","%esi","cc","memory"
|
||||
);
|
||||
reg_flags=(reg_flags & ~FMASK_TEST) | (tempflags & FMASK_TEST);
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
@ -232,28 +228,23 @@ static void gen_synchreg(DynReg * dnew,DynReg * dsynch) {
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_storeflags(void) {
|
||||
if (!x86gen.stored_flags) {
|
||||
cache_addb(0x9c); //PUSHFD
|
||||
static void gen_needflags(void) {
|
||||
if (!x86gen.flagsactive) {
|
||||
x86gen.flagsactive=true;
|
||||
cache_addb(0x9d); //POPFD
|
||||
}
|
||||
x86gen.stored_flags++;
|
||||
}
|
||||
|
||||
static void gen_restoreflags(bool noreduce=false) {
|
||||
if (noreduce) {
|
||||
cache_addb(0x9d);
|
||||
return;
|
||||
static void gen_protectflags(void) {
|
||||
if (x86gen.flagsactive) {
|
||||
x86gen.flagsactive=false;
|
||||
cache_addb(0x9c); //PUSHFD
|
||||
}
|
||||
if (x86gen.stored_flags) {
|
||||
x86gen.stored_flags--;
|
||||
if (!x86gen.stored_flags)
|
||||
cache_addb(0x9d); //POPFD
|
||||
} else IllegalOption();
|
||||
}
|
||||
|
||||
static void gen_reinit(void) {
|
||||
x86gen.last_used=0;
|
||||
x86gen.stored_flags=0;
|
||||
x86gen.flagsactive=false;
|
||||
for (Bitu i=0;i<X86_REGS;i++) {
|
||||
x86gen.regs[i]->dynreg=0;
|
||||
}
|
||||
@ -483,55 +474,32 @@ static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) {
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_shift_byte(ShiftOps op,DynReg * drecx,DynReg * dr1,Bit8u di1) {
|
||||
static void gen_shift_byte_cl(Bitu op,DynReg * dr1,Bit8u di1,DynReg * drecx) {
|
||||
ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
switch (op) {
|
||||
case SHIFT_ROL:cache_addw(0xc0d2+((gr1->index+di1)<<8));break;
|
||||
case SHIFT_ROR:cache_addw(0xc8d2+((gr1->index+di1)<<8));break;
|
||||
case SHIFT_RCL:cache_addw(0xd0d2+((gr1->index+di1)<<8));break;
|
||||
case SHIFT_RCR:cache_addw(0xd8d2+((gr1->index+di1)<<8));break;
|
||||
case SHIFT_SHL:cache_addw(0xe0d2+((gr1->index+di1)<<8));break;
|
||||
case SHIFT_SHR:cache_addw(0xe8d2+((gr1->index+di1)<<8));break;
|
||||
case SHIFT_SAR:cache_addw(0xf8d2+((gr1->index+di1)<<8));break;
|
||||
default:
|
||||
IllegalOption();
|
||||
}
|
||||
cache_addw(0xc0d2+(((Bit16u)op) << 11)+ ((gr1->index+di1)<<8));
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_shift_word(ShiftOps op,DynReg * drecx,bool dword,DynReg * dr1) {
|
||||
ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
|
||||
static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) {
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
if (!dword) cache_addb(0x66);
|
||||
switch (op) {
|
||||
case SHIFT_ROL:cache_addw(0xc0d3+((gr1->index)<<8));break;
|
||||
case SHIFT_ROR:cache_addw(0xc8d3+((gr1->index)<<8));break;
|
||||
case SHIFT_RCL:cache_addw(0xd0d3+((gr1->index)<<8));break;
|
||||
case SHIFT_RCR:cache_addw(0xd8d3+((gr1->index)<<8));break;
|
||||
case SHIFT_SHL:cache_addw(0xe0d3+((gr1->index)<<8));break;
|
||||
case SHIFT_SHR:cache_addw(0xe8d3+((gr1->index)<<8));break;
|
||||
case SHIFT_SAR:cache_addw(0xf8d3+((gr1->index)<<8));break;
|
||||
default:
|
||||
IllegalOption();
|
||||
}
|
||||
cache_addw(0xc0c0+(((Bit16u)op) << 11) + ((gr1->index+di1)<<8));
|
||||
cache_addb(imm);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_shift_word_imm(ShiftOps op,bool dword,DynReg * dr1,Bit8u imm) {
|
||||
static void gen_shift_word_cl(Bitu op,bool dword,DynReg * dr1,DynReg * drecx) {
|
||||
ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
if (!dword) cache_addb(0x66);
|
||||
switch (op) {
|
||||
case SHIFT_ROL:cache_addw(0xc0c1+((gr1->index)<<8));break;
|
||||
case SHIFT_ROR:cache_addw(0xc8c1+((gr1->index)<<8));break;
|
||||
case SHIFT_RCL:cache_addw(0xd0c1+((gr1->index)<<8));break;
|
||||
case SHIFT_RCR:cache_addw(0xd8c1+((gr1->index)<<8));break;
|
||||
case SHIFT_SHL:cache_addw(0xe0c1+((gr1->index)<<8));break;
|
||||
case SHIFT_SHR:cache_addw(0xe8c1+((gr1->index)<<8));break;
|
||||
case SHIFT_SAR:cache_addw(0xf8c1+((gr1->index)<<8));break;
|
||||
default:
|
||||
IllegalOption();
|
||||
}
|
||||
cache_addw(0xc0d3+(((Bit16u)op) << 11) + ((gr1->index)<<8));
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_shift_word_imm(Bitu op,bool dword,DynReg * dr1,Bit8u imm) {
|
||||
GenReg * gr1=FindDynReg(dr1);
|
||||
if (!dword) cache_addb(0x66);
|
||||
cache_addw(0xc0c1+(((Bit16u)op) << 11) + ((gr1->index)<<8));
|
||||
cache_addb(imm);
|
||||
dr1->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
@ -604,7 +572,7 @@ static void gen_call_function(void * func,char * ops,...) {
|
||||
x86gen.regs[X86_REG_EAX]->Clear();
|
||||
x86gen.regs[X86_REG_EAX]->notusable=true;;
|
||||
/* Save the flags */
|
||||
gen_storeflags();
|
||||
gen_protectflags();
|
||||
/* Scan for the amount of params */
|
||||
if (ops) {
|
||||
va_list params;
|
||||
@ -704,7 +672,6 @@ static void gen_call_function(void * func,char * ops,...) {
|
||||
}
|
||||
dynreg->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
gen_restoreflags();
|
||||
/* Restore EAX registers to be used again */
|
||||
x86gen.regs[X86_REG_EAX]->notusable=false;
|
||||
}
|
||||
@ -717,6 +684,11 @@ static Bit8u * gen_create_branch(BranchTypes type) {
|
||||
}
|
||||
|
||||
static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) {
|
||||
#if C_DEBUG
|
||||
Bits len=from-data;
|
||||
if (len<0) len=-len;
|
||||
if (len>126) LOG_MSG("BIg jump %d",len);
|
||||
#endif
|
||||
*data=(from-data-1);
|
||||
}
|
||||
|
||||
@ -747,17 +719,20 @@ static void gen_jmp_ptr(void * ptr,Bits imm=0) {
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_save_flags(DynReg * dynreg,bool stored) {
|
||||
static void gen_save_flags(DynReg * dynreg) {
|
||||
if (x86gen.flagsactive) IllegalOption();
|
||||
GenReg * genreg=FindDynReg(dynreg);
|
||||
if (!stored) cache_addb(0x9c); //Pushfd
|
||||
cache_addb(0x58+genreg->index); //POP 32 REG
|
||||
cache_addb(0x8b); //MOV REG,[esp]
|
||||
cache_addw(0x2404+(genreg->index << 3));
|
||||
dynreg->flags|=DYNFLG_CHANGED;
|
||||
}
|
||||
|
||||
static void gen_load_flags(DynReg * dynreg) {
|
||||
if (x86gen.flagsactive) IllegalOption();
|
||||
cache_addw(0xc483); //ADD ESP,4
|
||||
cache_addb(0x4);
|
||||
GenReg * genreg=FindDynReg(dynreg);
|
||||
cache_addb(0x50+genreg->index); //PUSH 32
|
||||
cache_addb(0x9d); //POPFD
|
||||
}
|
||||
|
||||
static void gen_save_host_direct(void * data,Bits imm) {
|
||||
@ -781,9 +756,11 @@ static void gen_load_host(void * data,DynReg * dr1,Bitu size) {
|
||||
}
|
||||
|
||||
static void gen_return(BlockReturn retcode) {
|
||||
cache_addb(0xb8);
|
||||
gen_protectflags();
|
||||
cache_addb(0x59); //POP ECX, the flags
|
||||
cache_addb(0xb8); //MOV EAX, retcode
|
||||
cache_addd(retcode);
|
||||
cache_addb(0xc3);
|
||||
cache_addb(0xc3); //RET
|
||||
}
|
||||
|
||||
static void gen_init(void) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -30,7 +30,7 @@ static void dyn_string(STRING_OP op) {
|
||||
DynReg * si_base=decode.segprefix ? decode.segprefix : DREG(DS);
|
||||
DynReg * di_base=DREG(ES);
|
||||
DynReg * tmp_reg;bool usesi;bool usedi;
|
||||
gen_storeflags();
|
||||
gen_protectflags();
|
||||
if (decode.rep) {
|
||||
gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);
|
||||
gen_releasereg(DREG(CYCLES));
|
||||
@ -149,9 +149,8 @@ static void dyn_string(STRING_OP op) {
|
||||
gen_releasereg(DREG(CYCLES));
|
||||
dyn_savestate(&cycle_state);
|
||||
Bit8u * cycle_branch=gen_create_branch(BR_NLE);
|
||||
gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start);
|
||||
dyn_releaseregs();
|
||||
gen_restoreflags(true);
|
||||
gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start);
|
||||
dyn_save_critical_regs();
|
||||
gen_return(BR_Cycles);
|
||||
gen_fill_branch(cycle_branch);
|
||||
dyn_loadstate(&cycle_state);
|
||||
@ -161,5 +160,4 @@ static void dyn_string(STRING_OP op) {
|
||||
gen_fill_jump(rep_ecx_jmp);
|
||||
}
|
||||
gen_releasereg(DREG(TMPW));
|
||||
gen_restoreflags();
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -54,47 +54,28 @@ typedef PhysPt EAPoint;
|
||||
#include "core_full/optable.h"
|
||||
#include "instructions.h"
|
||||
|
||||
#define LEAVECORE \
|
||||
SaveIP(); \
|
||||
FillFlags();
|
||||
|
||||
#define EXCEPTION(blah) \
|
||||
{ \
|
||||
Bit8u new_num=blah; \
|
||||
IPPoint=inst.opcode_start; \
|
||||
LEAVECORE; \
|
||||
CPU_Exception(new_num,0); \
|
||||
LoadIP(); \
|
||||
goto nextopcode; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
Bits CPU_Core_Full_Run(void) {
|
||||
FullData inst;
|
||||
restart_core:
|
||||
if (!cpu.code.big) {
|
||||
inst.start_prefix=0x0;;
|
||||
inst.start_entry=0x0;
|
||||
} else {
|
||||
inst.start_prefix=PREFIX_ADDR;
|
||||
inst.start_entry=0x200;
|
||||
}
|
||||
EAPoint IPPoint;
|
||||
LoadIP();
|
||||
lflags.type=t_UNKNOWN;
|
||||
while (CPU_Cycles-->0) {
|
||||
#if C_DEBUG
|
||||
cycle_count++;
|
||||
#if C_HEAVY_DEBUG
|
||||
SaveIP();
|
||||
if (DEBUG_HeavyIsBreakpoint()) {
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
return debugCallback;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
inst.opcode_start=IPPoint;
|
||||
inst.entry=inst.start_entry;
|
||||
inst.prefix=inst.start_prefix;
|
||||
LoadIP();
|
||||
inst.entry=cpu.code.big*0x200;
|
||||
inst.prefix=cpu.code.big;
|
||||
restartopcode:
|
||||
inst.entry=(inst.entry & 0xffffff00) | Fetchb();
|
||||
inst.code=OpCodeTable[inst.entry];
|
||||
@ -102,9 +83,13 @@ restartopcode:
|
||||
#include "core_full/op.h"
|
||||
#include "core_full/save.h"
|
||||
nextopcode:;
|
||||
SaveIP();
|
||||
continue;
|
||||
illegalopcode:
|
||||
LOG_MSG("Illegal opcode");
|
||||
CPU_Exception(0x6,0);
|
||||
}
|
||||
exit_core:
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
|
||||
|
@ -144,18 +144,12 @@ l_M_Ed:
|
||||
inst.op1.d=SegValue((SegNames)inst.rm_index);
|
||||
break;
|
||||
case M_Efw:
|
||||
if (inst.rm>=0xC0) {
|
||||
LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw ");
|
||||
goto nextopcode;
|
||||
}
|
||||
if (inst.rm>=0xc0) goto illegalopcode;
|
||||
inst.op1.d=LoadMw(inst.rm_eaa);
|
||||
inst.op2.d=LoadMw(inst.rm_eaa+2);
|
||||
break;
|
||||
case M_Efd:
|
||||
if (inst.rm>=0xc0) {
|
||||
LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw ");
|
||||
goto nextopcode;
|
||||
}
|
||||
if (inst.rm>=0xc0) goto illegalopcode;
|
||||
inst.op1.d=LoadMd(inst.rm_eaa);
|
||||
inst.op2.d=LoadMw(inst.rm_eaa+4);
|
||||
break;
|
||||
@ -183,8 +177,6 @@ l_M_Ed:
|
||||
inst.op2.d=1;
|
||||
inst.code=Groups[inst.code.op][inst.rm_index];
|
||||
goto l_MODRMswitch;
|
||||
|
||||
/* Should continue with normal handler afterwards */
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
@ -246,9 +238,6 @@ l_M_Ed:
|
||||
case L_REGd:
|
||||
inst.op1.d=reg_32(inst.code.extra);
|
||||
break;
|
||||
case L_FLG:
|
||||
inst.op1.d = FillFlags();
|
||||
break;
|
||||
case L_SEG:
|
||||
inst.op1.d=SegValue((SegNames)inst.code.extra);
|
||||
break;
|
||||
@ -282,10 +271,10 @@ l_M_Ed:
|
||||
inst.repz=true;
|
||||
goto restartopcode;
|
||||
case L_PREOP:
|
||||
inst.entry=inst.start_entry ^ 0x200;
|
||||
inst.entry=(cpu.code.big ^1) * 0x200;
|
||||
goto restartopcode;
|
||||
case L_PREADD:
|
||||
inst.prefix^=PREFIX_ADDR;
|
||||
inst.prefix=(inst.prefix & ~1) | (cpu.code.big ^ 1);
|
||||
goto restartopcode;
|
||||
case L_VAL:
|
||||
inst.op1.d=inst.code.extra;
|
||||
@ -295,41 +284,40 @@ l_M_Ed:
|
||||
inst.op1.d=4;
|
||||
break;
|
||||
case D_IRETw:
|
||||
LEAVECORE;
|
||||
CPU_IRET(false);
|
||||
FillFlags();
|
||||
CPU_IRET(false,GetIP());
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
return CBRET_NONE;
|
||||
}
|
||||
goto restart_core;
|
||||
continue;
|
||||
case D_IRETd:
|
||||
LEAVECORE;
|
||||
CPU_IRET(true);
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
FillFlags();
|
||||
CPU_IRET(true,GetIP());
|
||||
if (GETFLAG(IF) && PIC_IRQCheck)
|
||||
return CBRET_NONE;
|
||||
}
|
||||
goto restart_core;
|
||||
continue;
|
||||
case D_RETFwIw:
|
||||
{
|
||||
Bitu words=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_RET(false,words);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_RET(false,words,GetIP());
|
||||
continue;
|
||||
}
|
||||
case D_RETFw:
|
||||
LEAVECORE;
|
||||
CPU_RET(false,0);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_RET(false,0,GetIP());
|
||||
continue;
|
||||
case D_RETFdIw:
|
||||
{
|
||||
Bitu words=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_RET(true,words);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_RET(true,words,GetIP());
|
||||
continue;
|
||||
}
|
||||
case D_RETFd:
|
||||
LEAVECORE;
|
||||
CPU_RET(true,0);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_RET(true,0,GetIP());
|
||||
continue;
|
||||
/* Direct operations */
|
||||
case L_STRING:
|
||||
#include "string.h"
|
||||
@ -357,18 +345,10 @@ l_M_Ed:
|
||||
reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
|
||||
goto nextopcode;
|
||||
case D_POPSEGw:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_16())) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=2;
|
||||
CPU_StartException();goto restart_core;
|
||||
}
|
||||
if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException();
|
||||
goto nextopcode;
|
||||
case D_POPSEGd:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_32())) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=4;
|
||||
CPU_StartException();goto restart_core;
|
||||
}
|
||||
if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException();
|
||||
goto nextopcode;
|
||||
case D_SETALC:
|
||||
reg_al = get_CF() ? 0xFF : 0;
|
||||
@ -403,14 +383,10 @@ l_M_Ed:
|
||||
else reg_edx=0;
|
||||
goto nextopcode;
|
||||
case D_CLI:
|
||||
SETFLAGBIT(IF,false);
|
||||
if (CPU_CLI()) RunException();
|
||||
goto nextopcode;
|
||||
case D_STI:
|
||||
SETFLAGBIT(IF,true);
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
LEAVECORE;
|
||||
return CBRET_NONE;
|
||||
}
|
||||
if (CPU_STI()) RunException();
|
||||
goto nextopcode;
|
||||
case D_STC:
|
||||
FillFlags();SETFLAGBIT(CF,true);
|
||||
@ -430,71 +406,40 @@ l_M_Ed:
|
||||
SETFLAGBIT(DF,true);
|
||||
cpu.direction=-1;
|
||||
goto nextopcode;
|
||||
case D_PUSHF:
|
||||
FillFlags();
|
||||
if (CPU_PUSHF(inst.code.extra)) RunException();
|
||||
goto nextopcode;
|
||||
case D_POPF:
|
||||
if (CPU_POPF(inst.code.extra)) RunException();
|
||||
lflags.type=t_UNKNOWN;
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
SaveIP();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
goto nextopcode;
|
||||
case D_SAHF:
|
||||
SETFLAGSb(reg_ah);
|
||||
goto nextopcode;
|
||||
case D_LAHF:
|
||||
FillFlags();
|
||||
reg_ah=reg_flags&0xff;
|
||||
goto nextopcode;
|
||||
case D_WAIT:
|
||||
case D_NOP:
|
||||
goto nextopcode;
|
||||
case D_ENTERw:
|
||||
{
|
||||
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
|
||||
Bitu frame_ptr=reg_esp-2;
|
||||
if (cpu.stack.big) {
|
||||
reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,reg_bp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_ebp-=2;reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,mem_readw(SegBase(ss)+reg_ebp));
|
||||
}
|
||||
if (level) {
|
||||
reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,(Bit16u)frame_ptr);
|
||||
}
|
||||
reg_esp-=bytes;
|
||||
} else {
|
||||
reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,reg_bp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_bp-=2;reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,mem_readw(SegBase(ss)+reg_bp));
|
||||
}
|
||||
if (level) {
|
||||
reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,(Bit16u)frame_ptr);
|
||||
}
|
||||
reg_sp-=bytes;
|
||||
}
|
||||
reg_bp=frame_ptr;
|
||||
Bitu bytes=Fetchw();
|
||||
Bitu level=Fetchb();
|
||||
CPU_ENTER(false,bytes,level);
|
||||
goto nextopcode;
|
||||
}
|
||||
case D_ENTERd:
|
||||
{
|
||||
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
|
||||
Bitu frame_ptr=reg_esp-4;
|
||||
if (cpu.stack.big) {
|
||||
reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,reg_ebp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_ebp-=4;reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,mem_readd(SegBase(ss)+reg_ebp));
|
||||
}
|
||||
if (level) {
|
||||
reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,(Bit32u)frame_ptr);
|
||||
}
|
||||
reg_esp-=bytes;
|
||||
} else {
|
||||
reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,reg_ebp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_bp-=4;reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,mem_readd(SegBase(ss)+reg_bp));
|
||||
}
|
||||
if (level) {
|
||||
reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,(Bit32u)frame_ptr);
|
||||
}
|
||||
reg_sp-=bytes;
|
||||
}
|
||||
reg_ebp=frame_ptr;
|
||||
Bitu bytes=Fetchw();
|
||||
Bitu level=Fetchb();
|
||||
CPU_ENTER(true,bytes,level);
|
||||
goto nextopcode;
|
||||
}
|
||||
case D_LEAVEw:
|
||||
@ -523,14 +468,14 @@ l_M_Ed:
|
||||
CPU_CPUID();
|
||||
goto nextopcode;
|
||||
case D_HLT:
|
||||
LEAVECORE;
|
||||
CPU_HLT(IPPoint-inst.opcode_start);
|
||||
FillFlags();
|
||||
CPU_HLT(GetIP());
|
||||
return CBRET_NONE;
|
||||
case D_CLTS:
|
||||
//TODO Really clear it sometime
|
||||
goto nextopcode;
|
||||
default:
|
||||
LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %X",inst.code.load,inst.entry);
|
||||
break;
|
||||
goto illegalopcode;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
#define SaveIP() reg_eip=(Bit32u)(IPPoint-SegBase(cs));
|
||||
#define LoadIP() IPPoint=SegBase(cs)+reg_eip;
|
||||
#define SaveIP() reg_eip=(Bit32u)(inst.cseip-SegBase(cs));
|
||||
#define LoadIP() inst.cseip=SegBase(cs)+reg_eip;
|
||||
#define GetIP() (inst.cseip-SegBase(cs))
|
||||
|
||||
#define RunException() { \
|
||||
FillFlags(); \
|
||||
CPU_Exception(cpu.exception.which,cpu.exception.error); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
static INLINE Bit8u the_Fetchb(EAPoint & loc) {
|
||||
Bit8u temp=LoadMb(loc);
|
||||
@ -19,42 +25,16 @@ static INLINE Bit32u the_Fetchd(EAPoint & loc) {
|
||||
return temp;
|
||||
}
|
||||
|
||||
#define Fetchb() the_Fetchb(IPPoint)
|
||||
#define Fetchw() the_Fetchw(IPPoint)
|
||||
#define Fetchd() the_Fetchd(IPPoint)
|
||||
#define Fetchb() the_Fetchb(inst.cseip)
|
||||
#define Fetchw() the_Fetchw(inst.cseip)
|
||||
#define Fetchd() the_Fetchd(inst.cseip)
|
||||
|
||||
#define Fetchbs() (Bit8s)the_Fetchb(IPPoint)
|
||||
#define Fetchws() (Bit16s)the_Fetchw(IPPoint)
|
||||
#define Fetchds() (Bit32s)the_Fetchd(IPPoint)
|
||||
|
||||
#if 0
|
||||
static INLINE void Push_16(Bit16u blah) {
|
||||
reg_esp-=2;
|
||||
SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
|
||||
}
|
||||
|
||||
static INLINE void Push_32(Bit32u blah) {
|
||||
reg_esp-=4;
|
||||
SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
|
||||
}
|
||||
|
||||
static INLINE Bit16u Pop_16(void) {
|
||||
Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask));
|
||||
reg_esp+=2;
|
||||
return temp;
|
||||
}
|
||||
|
||||
static INLINE Bit32u Pop_32(void) {
|
||||
Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask));
|
||||
reg_esp+=4;
|
||||
return temp;
|
||||
}
|
||||
|
||||
#else
|
||||
#define Fetchbs() (Bit8s)the_Fetchb(inst.cseip)
|
||||
#define Fetchws() (Bit16s)the_Fetchw(inst.cseip)
|
||||
#define Fetchds() (Bit32s)the_Fetchd(inst.cseip)
|
||||
|
||||
#define Push_16 CPU_Push16
|
||||
#define Push_32 CPU_Push32
|
||||
#define Pop_16 CPU_Pop16
|
||||
#define Pop_32 CPU_Pop32
|
||||
|
||||
#endif
|
||||
|
@ -322,51 +322,57 @@ switch (inst.code.op) {
|
||||
Push_32(reg_eip);
|
||||
break;
|
||||
case O_CALLFw:
|
||||
LEAVECORE;
|
||||
CPU_CALL(false,inst.op2.d,inst.op1.d);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_CALL(false,inst.op2.d,inst.op1.d,GetIP());
|
||||
continue;
|
||||
case O_CALLFd:
|
||||
LEAVECORE;
|
||||
CPU_CALL(true,inst.op2.d,inst.op1.d);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_CALL(true,inst.op2.d,inst.op1.d,GetIP());
|
||||
continue;
|
||||
case O_JMPFw:
|
||||
LEAVECORE;
|
||||
CPU_JMP(false,inst.op2.d,inst.op1.d);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_JMP(false,inst.op2.d,inst.op1.d,GetIP());
|
||||
continue;
|
||||
case O_JMPFd:
|
||||
LEAVECORE;
|
||||
CPU_JMP(true,inst.op2.d,inst.op1.d);
|
||||
goto restart_core;
|
||||
FillFlags();
|
||||
CPU_JMP(true,inst.op2.d,inst.op1.d,GetIP());
|
||||
continue;
|
||||
case O_INT:
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
#if C_DEBUG
|
||||
if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint())
|
||||
return debugCallback;
|
||||
else if (DEBUG_IntBreakpoint(inst.op1.b))
|
||||
return debugCallback;
|
||||
#endif
|
||||
CPU_SW_Interrupt(inst.op1.b,IPPoint-inst.opcode_start);
|
||||
goto restart_core;
|
||||
CPU_SW_Interrupt(inst.op1.b,GetIP());
|
||||
continue;
|
||||
case O_INb:
|
||||
if (CPU_IO_Exception(inst.op1.d,1)) RunException();
|
||||
reg_al=IO_ReadB(inst.op1.d);
|
||||
goto nextopcode;
|
||||
case O_INw:
|
||||
if (CPU_IO_Exception(inst.op1.d,2)) RunException();
|
||||
reg_ax=IO_ReadW(inst.op1.d);
|
||||
goto nextopcode;
|
||||
case O_INd:
|
||||
if (CPU_IO_Exception(inst.op1.d,4)) RunException();
|
||||
reg_eax=IO_ReadD(inst.op1.d);
|
||||
goto nextopcode;
|
||||
case O_OUTb:
|
||||
if (CPU_IO_Exception(inst.op1.d,1)) RunException();
|
||||
IO_WriteB(inst.op1.d,reg_al);
|
||||
goto nextopcode;
|
||||
case O_OUTw:
|
||||
if (CPU_IO_Exception(inst.op1.d,2)) RunException();
|
||||
IO_WriteW(inst.op1.d,reg_ax);
|
||||
goto nextopcode;
|
||||
case O_OUTd:
|
||||
if (CPU_IO_Exception(inst.op1.d,4)) RunException();
|
||||
IO_WriteD(inst.op1.d,reg_eax);
|
||||
goto nextopcode;
|
||||
case O_CBACK:
|
||||
LEAVECORE;
|
||||
FillFlags();SaveIP();
|
||||
return inst.op1.d;
|
||||
case O_GRP6w:
|
||||
case O_GRP6d:
|
||||
@ -458,19 +464,22 @@ switch (inst.code.op) {
|
||||
case O_LAR:
|
||||
{
|
||||
FillFlags();
|
||||
Bitu ar;CPU_LAR(inst.op1.d,ar);
|
||||
Bitu ar=inst.op2.d;
|
||||
CPU_LAR(inst.op1.w,ar);
|
||||
inst.op1.d=(Bit32u)ar;
|
||||
}
|
||||
break;
|
||||
case O_LSL:
|
||||
{
|
||||
FillFlags();
|
||||
Bitu limit;CPU_LSL(inst.op1.d,limit);
|
||||
Bitu limit=inst.op2.d;
|
||||
CPU_LSL(inst.op1.w,limit);
|
||||
inst.op1.d=(Bit32u)limit;
|
||||
}
|
||||
break;
|
||||
case O_ARPL:
|
||||
{
|
||||
if ((reg_flags & FLAG_VM) || !cpu.pmode) goto illegalopcode;
|
||||
FillFlags();
|
||||
Bitu new_sel=inst.op1.d;
|
||||
CPU_ARPL(new_sel,inst.op2.d);
|
||||
|
@ -110,8 +110,9 @@ static OpCode OpCodeTable[1024]={
|
||||
/* 0x98 - 0x9f */
|
||||
{D_CBW ,0 ,0 ,0 },{D_CWD ,0 ,0 ,0 },
|
||||
{L_Ifw ,O_CALLFw ,0 ,0 },{D_WAIT ,0 ,0 ,0 },
|
||||
{L_FLG ,0 ,S_PUSHw,0 },{L_POPw ,0 ,S_FLGw ,0 },
|
||||
{L_REGb ,0 ,S_FLGb ,REGI_AH},{L_FLG ,0 ,S_REGb ,REGI_AH},
|
||||
{D_PUSHF ,0 ,0 ,0 },{D_POPF ,0 ,0 ,0 },
|
||||
{D_SAHF ,0 ,0 ,0 },{D_LAHF ,0 ,0 ,0 },
|
||||
|
||||
|
||||
/* 0xa0 - 0xa7 */
|
||||
{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_AXOP ,0 ,0 },
|
||||
@ -182,7 +183,7 @@ static OpCode OpCodeTable[1024]={
|
||||
|
||||
/* 0x100 - 0x107 */
|
||||
{L_MODRM ,O_GRP6w ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7w ,S_Ew ,M_Ew },
|
||||
{L_MODRM ,O_LAR ,S_Gw ,M_Ew },{L_MODRM ,O_LSL ,S_Gw ,M_Ew },
|
||||
{L_MODRM ,O_LAR ,S_Gw ,M_EwGw },{L_MODRM ,O_LSL ,S_Gw ,M_EwGw },
|
||||
{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 },
|
||||
{D_CLTS ,0 ,0 ,0 },{0 ,0 ,0 ,0 },
|
||||
/* 0x108 - 0x10f */
|
||||
@ -466,8 +467,8 @@ static OpCode OpCodeTable[1024]={
|
||||
/* 0x298 - 0x29f */
|
||||
{D_CWDE ,0 ,0 ,0 },{D_CDQ ,0 ,0 ,0 },
|
||||
{L_Ifd ,O_CALLFd ,0 ,0 },{D_WAIT ,0 ,0 ,0 },
|
||||
{L_FLG ,0 ,S_PUSHd,0 },{L_POPd ,0 ,S_FLGd ,0 },
|
||||
{L_REGb ,0 ,S_FLGb ,REGI_AH},{L_FLG ,0 ,S_REGb ,REGI_AH},
|
||||
{D_PUSHF ,0 ,0 ,true },{D_POPF ,0 ,0 ,true },
|
||||
{D_SAHF ,0 ,0 ,0 },{D_LAHF ,0 ,0 ,0 },
|
||||
|
||||
/* 0x2a0 - 0x2a7 */
|
||||
{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_EAXOP ,0 ,0 },
|
||||
@ -538,7 +539,7 @@ static OpCode OpCodeTable[1024]={
|
||||
|
||||
/* 0x300 - 0x307 */
|
||||
{L_MODRM ,O_GRP6d ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7d ,S_Ew ,M_Ew },
|
||||
{L_MODRM ,O_LAR ,S_Gd ,M_Ew },{L_MODRM ,O_LSL ,S_Gd ,M_Ew },
|
||||
{L_MODRM ,O_LAR ,S_Gd ,M_EdGd },{L_MODRM ,O_LSL ,S_Gd ,M_EdGd },
|
||||
{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 },
|
||||
{D_CLTS ,0 ,0 ,0 },{0 ,0 ,0 ,0 },
|
||||
/* 0x308 - 0x30f */
|
||||
|
@ -56,29 +56,14 @@ switch (inst.code.save) {
|
||||
reg_32(inst.code.extra)=inst.op1.d;
|
||||
break;
|
||||
case S_SEGm:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);
|
||||
CPU_StartException();
|
||||
goto restart_core;
|
||||
}
|
||||
if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) RunException();
|
||||
break;
|
||||
case S_SEGGw:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);
|
||||
CPU_StartException();
|
||||
goto restart_core;
|
||||
}
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) RunException();
|
||||
reg_16(inst.rm_index)=inst.op1.w;
|
||||
break;
|
||||
case S_SEGGd:
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) {
|
||||
LEAVECORE;
|
||||
reg_eip-=(IPPoint-inst.opcode_start);
|
||||
CPU_StartException();
|
||||
goto restart_core;
|
||||
}
|
||||
if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) RunException();
|
||||
reg_32(inst.rm_index)=inst.op1.d;
|
||||
break;
|
||||
case S_PUSHw:
|
||||
@ -94,39 +79,19 @@ switch (inst.code.save) {
|
||||
SaveIP();
|
||||
reg_eip+=inst.op1.d;
|
||||
reg_eip&=0xffff;
|
||||
LoadIP();
|
||||
break;
|
||||
continue;
|
||||
case S_C_AIPd:
|
||||
if (!inst.cond) goto nextopcode;
|
||||
case S_AIPd:
|
||||
SaveIP();
|
||||
reg_eip+=inst.op1.d;
|
||||
LoadIP();
|
||||
break;
|
||||
continue;
|
||||
case S_IPIw:
|
||||
reg_esp+=Fetchw();
|
||||
case S_IP:
|
||||
SaveIP();
|
||||
reg_eip=inst.op1.d;
|
||||
LoadIP();
|
||||
break;
|
||||
case S_FLGb:
|
||||
SETFLAGSb(inst.op1.b);
|
||||
break;
|
||||
case S_FLGw:
|
||||
SETFLAGSw(inst.op1.w);
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
SaveIP();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
break;
|
||||
case S_FLGd:
|
||||
SETFLAGSd(inst.op1.d);
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) {
|
||||
SaveIP();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
break;
|
||||
continue;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
|
@ -28,7 +28,7 @@
|
||||
count_left=count-CPU_Cycles;
|
||||
count=CPU_Cycles;
|
||||
CPU_Cycles=0;
|
||||
IPPoint=inst.opcode_start; //Reset IP to start of instruction
|
||||
LoadIP();
|
||||
} else {
|
||||
/* Won't interrupt scas and cmps instruction since they can interrupt themselves */
|
||||
count_left=0;
|
||||
|
@ -15,7 +15,7 @@ enum {
|
||||
L_POPfw,L_POPfd,
|
||||
L_SEG,
|
||||
|
||||
L_FLG,L_INTO,
|
||||
L_INTO,
|
||||
|
||||
L_VAL,
|
||||
L_PRESEG,
|
||||
@ -41,6 +41,8 @@ enum {
|
||||
|
||||
D_RETFw,D_RETFd,
|
||||
D_RETFwIw,D_RETFdIw,
|
||||
D_POPF,D_PUSHF,
|
||||
D_SAHF,D_LAHF,
|
||||
D_CPUID,
|
||||
D_HLT,D_CLTS,
|
||||
L_ERROR,
|
||||
@ -113,7 +115,6 @@ enum {
|
||||
S_AIPw,S_C_AIPw,
|
||||
S_AIPd,S_C_AIPd,
|
||||
|
||||
S_FLGb,S_FLGw,S_FLGd,
|
||||
S_IP,S_IPIw,
|
||||
};
|
||||
|
||||
@ -155,7 +156,6 @@ struct OpCode {
|
||||
|
||||
struct FullData {
|
||||
Bitu entry;
|
||||
EAPoint opcode_start;
|
||||
Bitu rm;
|
||||
EAPoint rm_eaa;
|
||||
Bitu rm_off;
|
||||
@ -163,6 +163,7 @@ struct FullData {
|
||||
Bitu rm_index;
|
||||
Bitu rm_mod;
|
||||
OpCode code;
|
||||
EAPoint cseip;
|
||||
union {
|
||||
Bit8u b;Bit8s bs;
|
||||
Bit16u w;Bit16s ws;
|
||||
@ -175,13 +176,11 @@ struct FullData {
|
||||
Bitu cond;
|
||||
bool repz;
|
||||
Bitu prefix;
|
||||
Bitu start_prefix;
|
||||
Bitu start_entry;
|
||||
};
|
||||
|
||||
|
||||
#define PREFIX_NONE 0x0
|
||||
#define PREFIX_SEG 0x1
|
||||
#define PREFIX_ADDR 0x2
|
||||
#define PREFIX_ADDR 0x1
|
||||
#define PREFIX_SEG 0x2
|
||||
#define PREFIX_REP 0x4
|
||||
|
||||
|
@ -9,13 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "mem.h"
|
||||
@ -30,43 +31,23 @@
|
||||
#include "debug.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define SegBase(c) SegPhys(c)
|
||||
#if (!C_CORE_INLINE)
|
||||
|
||||
#define LoadMb(off) mem_readb(off)
|
||||
#define LoadMw(off) mem_readw(off)
|
||||
#define LoadMd(off) mem_readd(off)
|
||||
|
||||
#define SaveMb(off,val) mem_writeb(off,val)
|
||||
#define SaveMw(off,val) mem_writew(off,val)
|
||||
#define SaveMd(off,val) mem_writed(off,val)
|
||||
|
||||
#else
|
||||
|
||||
#include "paging.h"
|
||||
#define LoadMb(off) mem_readb_inline(off)
|
||||
#define LoadMw(off) mem_readw_inline(off)
|
||||
#define LoadMd(off) mem_readd_inline(off)
|
||||
|
||||
#define SaveMb(off,val) mem_writeb_inline(off,val)
|
||||
#define SaveMw(off,val) mem_writew_inline(off,val)
|
||||
#define SaveMd(off,val) mem_writed_inline(off,val)
|
||||
|
||||
#endif
|
||||
|
||||
#define LoadMbs(off) (Bit8s)(LoadMb(off))
|
||||
#define LoadMws(off) (Bit16s)(LoadMw(off))
|
||||
#define LoadMds(off) (Bit32s)(LoadMd(off))
|
||||
|
||||
#define LoadRb(reg) reg
|
||||
#define LoadRw(reg) reg
|
||||
#define LoadRd(reg) reg
|
||||
|
||||
#define SaveRb(reg,val) reg=val
|
||||
#define SaveRw(reg,val) reg=val
|
||||
#define SaveRd(reg,val) reg=val
|
||||
|
||||
extern Bitu cycle_count;
|
||||
|
||||
#if C_FPU
|
||||
@ -80,122 +61,129 @@ extern Bitu cycle_count;
|
||||
#define OPCODE_0F 0x100
|
||||
#define OPCODE_SIZE 0x200
|
||||
|
||||
#define PREFIX_SEG 0x1
|
||||
#define PREFIX_ADDR 0x2
|
||||
#define PREFIX_SEG_ADDR (PREFIX_SEG|PREFIX_ADDR)
|
||||
#define PREFIX_REP 0x4
|
||||
#define PREFIX_ADDR 0x1
|
||||
#define PREFIX_REP 0x2
|
||||
|
||||
#define TEST_PREFIX_SEG (core.prefixes & PREFIX_SEG)
|
||||
#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR)
|
||||
#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP)
|
||||
|
||||
#define DO_PREFIX_SEG(_SEG) \
|
||||
core.prefixes|=PREFIX_SEG; \
|
||||
core.seg_prefix_base=SegBase(_SEG); \
|
||||
goto restart_prefix;
|
||||
BaseDS=SegBase(_SEG); \
|
||||
BaseSS=SegBase(_SEG); \
|
||||
goto restart_opcode;
|
||||
|
||||
#define DO_PREFIX_ADDR() \
|
||||
core.prefixes^=PREFIX_ADDR; \
|
||||
goto restart_prefix;
|
||||
#define DO_PREFIX_ADDR() \
|
||||
core.prefixes=(core.prefixes & ~PREFIX_ADDR) | \
|
||||
(cpu.code.big ^ PREFIX_ADDR); \
|
||||
core.ea_table=&EATable[(core.prefixes&1) * 256]; \
|
||||
goto restart_opcode;
|
||||
|
||||
#define DO_PREFIX_REP(_ZERO) \
|
||||
core.prefixes|=PREFIX_REP; \
|
||||
core.rep_zero=_ZERO; \
|
||||
goto restart_prefix;
|
||||
goto restart_opcode;
|
||||
|
||||
typedef PhysPt (*GetEATable[256])(void);
|
||||
typedef PhysPt (*GetEAHandler)(void);
|
||||
|
||||
static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff};
|
||||
|
||||
static struct {
|
||||
Bitu opcode_index;
|
||||
Bitu prefixes;
|
||||
Bitu index_default;
|
||||
Bitu prefix_default;
|
||||
PhysPt op_start;
|
||||
PhysPt ip_lookup;
|
||||
PhysPt seg_prefix_base;
|
||||
PhysPt cseip;
|
||||
PhysPt base_ds,base_ss;
|
||||
bool rep_zero;
|
||||
GetEATable * ea_table;
|
||||
Bitu prefixes;
|
||||
GetEAHandler * ea_table;
|
||||
struct {
|
||||
bool skip;
|
||||
} trap;
|
||||
} core;
|
||||
|
||||
#define GETIP (core.cseip-SegBase(cs))
|
||||
#define SAVEIP reg_eip=GETIP;
|
||||
#define LOADIP core.cseip=(SegBase(cs)+reg_eip);
|
||||
|
||||
#define SegBase(c) SegPhys(c)
|
||||
#define BaseDS core.base_ds
|
||||
#define BaseSS core.base_ss
|
||||
|
||||
static INLINE Bit8u Fetchb() {
|
||||
Bit8u temp=LoadMb(core.cseip);
|
||||
core.cseip+=1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
static INLINE Bit16u Fetchw() {
|
||||
Bit16u temp=LoadMw(core.cseip);
|
||||
core.cseip+=2;
|
||||
return temp;
|
||||
}
|
||||
static INLINE Bit32u Fetchd() {
|
||||
Bit32u temp=LoadMd(core.cseip);
|
||||
core.cseip+=4;
|
||||
return temp;
|
||||
}
|
||||
|
||||
#define Push_16 CPU_Push16
|
||||
#define Push_32 CPU_Push32
|
||||
#define Pop_16 CPU_Pop16
|
||||
#define Pop_32 CPU_Pop32
|
||||
|
||||
#include "instructions.h"
|
||||
#include "core_normal/support.h"
|
||||
#include "core_normal/string.h"
|
||||
|
||||
static GetEATable * EAPrefixTable[8] = {
|
||||
&GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR,
|
||||
&GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR,
|
||||
};
|
||||
|
||||
#define CASE_W(_WHICH) \
|
||||
case (OPCODE_NONE+_WHICH):
|
||||
|
||||
#define CASE_D(_WHICH) \
|
||||
case (OPCODE_SIZE+_WHICH):
|
||||
|
||||
#define CASE_B(_WHICH) \
|
||||
CASE_W(_WHICH) \
|
||||
CASE_D(_WHICH)
|
||||
|
||||
#define CASE_0F_W(_WHICH) \
|
||||
case ((OPCODE_0F|OPCODE_NONE)+_WHICH):
|
||||
|
||||
#define CASE_0F_D(_WHICH) \
|
||||
case ((OPCODE_0F|OPCODE_SIZE)+_WHICH):
|
||||
|
||||
#define CASE_0F_B(_WHICH) \
|
||||
CASE_0F_W(_WHICH) \
|
||||
CASE_0F_D(_WHICH)
|
||||
|
||||
#define EALookupTable (*(core.ea_table))
|
||||
#define EALookupTable (core.ea_table)
|
||||
|
||||
Bits CPU_Core_Normal_Run(void) {
|
||||
decode_start:
|
||||
if (cpu.code.big) {
|
||||
core.index_default=0x200;
|
||||
core.prefix_default=PREFIX_ADDR;
|
||||
} else {
|
||||
core.index_default=0;
|
||||
core.prefix_default=0;
|
||||
}
|
||||
LOADIP;
|
||||
lflags.type=t_UNKNOWN;
|
||||
while (CPU_Cycles-->0) {
|
||||
core.op_start=core.ip_lookup;
|
||||
core.opcode_index=core.index_default;
|
||||
core.prefixes=core.prefix_default;
|
||||
LOADIP;
|
||||
core.opcode_index=cpu.code.big*0x200;
|
||||
core.prefixes=cpu.code.big;
|
||||
core.ea_table=&EATable[cpu.code.big*256];
|
||||
BaseDS=SegBase(ds);
|
||||
BaseSS=SegBase(ss);
|
||||
#if C_DEBUG
|
||||
cycle_count++;
|
||||
#if C_HEAVY_DEBUG
|
||||
SAVEIP;
|
||||
if (DEBUG_HeavyIsBreakpoint()) {
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
return debugCallback;
|
||||
};
|
||||
#endif
|
||||
cycle_count++;
|
||||
#endif
|
||||
restart_prefix:
|
||||
core.ea_table=EAPrefixTable[core.prefixes];
|
||||
restart_opcode:
|
||||
switch (core.opcode_index+Fetchb()) {
|
||||
|
||||
#include "core_normal/prefix_none.h"
|
||||
#include "core_normal/prefix_0f.h"
|
||||
#include "core_normal/prefix_66.h"
|
||||
#include "core_normal/prefix_66_0f.h"
|
||||
default:
|
||||
ADDIPFAST(-1);
|
||||
#if C_DEBUG
|
||||
LOG_MSG("Unhandled code %X",core.opcode_index+Fetchb());
|
||||
#else
|
||||
E_Exit("Unhandled CPU opcode");
|
||||
illegal_opcode:
|
||||
#if C_DEBUG
|
||||
{
|
||||
Bitu len=(GETIP-reg_eip);
|
||||
LOADIP;
|
||||
if (len>16) len=16;
|
||||
char tempcode[16*2+1];char * writecode=tempcode;
|
||||
for (;len>0;len--) {
|
||||
sprintf(writecode,"%X",mem_readb(core.cseip++));
|
||||
writecode+=2;
|
||||
}
|
||||
LOG(LOG_CPU,LOG_ERROR)("Illegal/Unhandled opcode %s",tempcode);
|
||||
}
|
||||
#endif
|
||||
CPU_Exception(6,0);
|
||||
continue;
|
||||
}
|
||||
SAVEIP;
|
||||
}
|
||||
decode_end:
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
return CBRET_NONE;
|
||||
decode_end:
|
||||
SAVEIP;
|
||||
FillFlags();
|
||||
return CBRET_NONE;
|
||||
}
|
||||
|
||||
@ -206,7 +194,7 @@ Bits CPU_Core_Normal_Trap_Run(void) {
|
||||
core.trap.skip=false;
|
||||
|
||||
Bits ret=CPU_Core_Normal_Run();
|
||||
if (!core.trap.skip) CPU_SW_Interrupt(1,0);
|
||||
if (!core.trap.skip) CPU_SW_Interrupt(1,reg_eip);
|
||||
CPU_Cycles = oldCycles-1;
|
||||
cpudecoder = &CPU_Core_Normal_Run;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -141,17 +141,22 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define POPSEG(_SEG_,_VAL_,_ESP_CHANGE_) \
|
||||
if (CPU_SetSegGeneral(_SEG_,_VAL_)) { \
|
||||
LEAVECORE; \
|
||||
reg_eip-=(core.ip_lookup-core.op_start);reg_esp-=_ESP_CHANGE_; \
|
||||
CPU_StartException();goto decode_start; \
|
||||
}
|
||||
#define CASE_W(_WHICH) \
|
||||
case (OPCODE_NONE+_WHICH):
|
||||
|
||||
#define LOADSEG(_SEG_,_SEG_VAL_) \
|
||||
if (CPU_SetSegGeneral(_SEG_,_SEG_VAL_)) { \
|
||||
LEAVECORE; \
|
||||
reg_eip-=(core.ip_lookup-core.op_start); \
|
||||
CPU_StartException();goto decode_start; \
|
||||
} \
|
||||
#define CASE_D(_WHICH) \
|
||||
case (OPCODE_SIZE+_WHICH):
|
||||
|
||||
#define CASE_B(_WHICH) \
|
||||
CASE_W(_WHICH) \
|
||||
CASE_D(_WHICH)
|
||||
|
||||
#define CASE_0F_W(_WHICH) \
|
||||
case ((OPCODE_0F|OPCODE_NONE)+_WHICH):
|
||||
|
||||
#define CASE_0F_D(_WHICH) \
|
||||
case ((OPCODE_0F|OPCODE_SIZE)+_WHICH):
|
||||
|
||||
#define CASE_0F_B(_WHICH) \
|
||||
CASE_0F_W(_WHICH) \
|
||||
CASE_0F_D(_WHICH)
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -45,7 +45,7 @@
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which);
|
||||
goto illegal_opcode;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -77,7 +77,7 @@
|
||||
break;
|
||||
case 0x06: /* LMSW */
|
||||
limit=LoadMw(eaa);
|
||||
if (!CPU_LMSW(limit)) goto decode_end;
|
||||
if (CPU_LMSW(limit)) RUNEXCEPTION();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -88,11 +88,10 @@
|
||||
*earw=limit;
|
||||
break;
|
||||
case 0x06: /* LMSW */
|
||||
if (!CPU_LMSW(*earw)) goto decode_end;
|
||||
if (CPU_LMSW(*earw)) RUNEXCEPTION();
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which);
|
||||
break;
|
||||
goto illegal_opcode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,7 +99,7 @@
|
||||
CASE_0F_W(0x02) /* LAR Gw,Ew */
|
||||
{
|
||||
FillFlags();
|
||||
GetRMrw;Bitu ar;
|
||||
GetRMrw;Bitu ar=*rmrw;
|
||||
if (rm >= 0xc0) {
|
||||
GetEArw;CPU_LAR(*earw,ar);
|
||||
} else {
|
||||
@ -112,7 +111,7 @@
|
||||
CASE_0F_W(0x03) /* LSL Gw,Ew */
|
||||
{
|
||||
FillFlags();
|
||||
GetRMrw;Bitu limit;
|
||||
GetRMrw;Bitu limit=*rmrw;
|
||||
if (rm >= 0xc0) {
|
||||
GetEArw;CPU_LSL(*earw,limit);
|
||||
} else {
|
||||
@ -154,11 +153,8 @@
|
||||
Bitu which=(rm >> 3) & 7;
|
||||
if (rm >= 0xc0 ) {
|
||||
GetEArd;
|
||||
CPU_SET_CRX(which,*eard);
|
||||
} else {
|
||||
GetEAa;
|
||||
LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which);
|
||||
}
|
||||
if (CPU_SET_CRX(which,*eard)) RUNEXCEPTION();
|
||||
} else goto illegal_opcode;
|
||||
}
|
||||
break;
|
||||
CASE_0F_B(0x23) /* MOV DRx,Rd */
|
||||
@ -241,7 +237,7 @@
|
||||
CASE_0F_W(0xa0) /* PUSH FS */
|
||||
Push_16(SegValue(fs));break;
|
||||
CASE_0F_W(0xa1) /* POP FS */
|
||||
POPSEG(fs,Pop_16(),2);
|
||||
if (CPU_PopSeg(fs,false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_0F_B(0xa2) /* CPUID */
|
||||
CPU_CPUID();break;
|
||||
@ -268,7 +264,8 @@
|
||||
CASE_0F_W(0xa8) /* PUSH GS */
|
||||
Push_16(SegValue(gs));break;
|
||||
CASE_0F_W(0xa9) /* POP GS */
|
||||
POPSEG(gs,Pop_16(),2);break;
|
||||
if (CPU_PopSeg(gs,false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_0F_W(0xab) /* BTS Ew,Gw */
|
||||
{
|
||||
FillFlags();GetRMrw;
|
||||
@ -297,7 +294,7 @@
|
||||
CASE_0F_W(0xb2) /* LSS Ew */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(ss,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
@ -320,14 +317,14 @@
|
||||
CASE_0F_W(0xb4) /* LFS Ew */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(fs,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
CASE_0F_W(0xb5) /* LGS Ew */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(gs,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -25,7 +25,8 @@
|
||||
CASE_D(0x06) /* PUSH ES */
|
||||
Push_32(SegValue(es));break;
|
||||
CASE_D(0x07) /* POP ES */
|
||||
POPSEG(es,Pop_32(),4);break;
|
||||
if (CPU_PopSeg(es,true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_D(0x09) /* OR Ed,Gd */
|
||||
RMEdGd(ORD);break;
|
||||
CASE_D(0x0b) /* OR Gd,Ed */
|
||||
@ -43,7 +44,7 @@
|
||||
CASE_D(0x16) /* PUSH SS */
|
||||
Push_32(SegValue(ss));break;
|
||||
CASE_D(0x17) /* POP SS */
|
||||
POPSEG(ss,Pop_32(),4);
|
||||
if (CPU_PopSeg(ss,true)) RUNEXCEPTION();
|
||||
CPU_Cycles++;
|
||||
break;
|
||||
CASE_D(0x19) /* SBB Ed,Gd */
|
||||
@ -55,7 +56,8 @@
|
||||
CASE_D(0x1e) /* PUSH DS */
|
||||
Push_32(SegValue(ds));break;
|
||||
CASE_D(0x1f) /* POP DS */
|
||||
POPSEG(ds,Pop_32(),4);break;
|
||||
if (CPU_PopSeg(ds,true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_D(0x21) /* AND Ed,Gd */
|
||||
RMEdGd(ANDD);break;
|
||||
CASE_D(0x23) /* AND Gd,Ed */
|
||||
@ -167,6 +169,7 @@
|
||||
break;
|
||||
CASE_D(0x63) /* ARPL Ed,Rd */
|
||||
{
|
||||
if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode;
|
||||
FillFlags();
|
||||
GetRMrw;
|
||||
if (rm >= 0xc0 ) {
|
||||
@ -190,6 +193,12 @@
|
||||
CASE_D(0x6b) /* IMUL Gd,Ed,Ib */
|
||||
RMGdEdOp3(DIMULD,Fetchbs());
|
||||
break;
|
||||
CASE_D(0x6d) /* INSD */
|
||||
if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION();
|
||||
DoString(R_INSD);break;
|
||||
CASE_D(0x6f) /* OUTSD */
|
||||
if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION();
|
||||
DoString(R_OUTSD);break;
|
||||
CASE_D(0x70) /* JO */
|
||||
JumpCond32_b(TFLG_O);break;
|
||||
CASE_D(0x71) /* JNO */
|
||||
@ -332,12 +341,12 @@
|
||||
CASE_D(0x8d) /* LEA Gd */
|
||||
{
|
||||
//Little hack to always use segprefixed version
|
||||
core.seg_prefix_base=0;
|
||||
GetRMrd;
|
||||
BaseDS=BaseSS=0;
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
*rmrd=(Bit32u)(*GetEA_SEG_ADDR[rm])();
|
||||
*rmrd=(Bit32u)(*EATable[256+rm])();
|
||||
} else {
|
||||
*rmrd=(Bit32u)(*GetEA_SEG[rm])();
|
||||
*rmrd=(Bit32u)(*EATable[rm])();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -378,21 +387,17 @@
|
||||
CASE_D(0x9a) /* CALL FAR Ad */
|
||||
{
|
||||
Bit32u newip=Fetchd();Bit16u newcs=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_CALL(true,newcs,newip);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_CALL(true,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_D(0x9c) /* PUSHFD */
|
||||
FillFlags();
|
||||
Push_32(reg_flags);
|
||||
if (CPU_PUSHF(true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_D(0x9d) /* POPFD */
|
||||
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) {
|
||||
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
|
||||
CPU_Exception(13,0);
|
||||
goto decode_start;
|
||||
}
|
||||
SETFLAGSd(Pop_32())
|
||||
if (CPU_POPF(true)) RUNEXCEPTION();
|
||||
lflags.type=t_UNKNOWN;
|
||||
#if CPU_TRAP_CHECK
|
||||
if (GETFLAG(TF)) {
|
||||
cpudecoder=CPU_Core_Normal_Trap_Run;
|
||||
@ -402,7 +407,6 @@
|
||||
#if CPU_PIC_CHECK
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
|
||||
#endif
|
||||
|
||||
break;
|
||||
CASE_D(0xa1) /* MOV EAX,Od */
|
||||
{
|
||||
@ -447,25 +451,23 @@
|
||||
CASE_D(0xc1) /* GRP2 Ed,Ib */
|
||||
GRP2D(Fetchb());break;
|
||||
CASE_D(0xc2) /* RETN Iw */
|
||||
{
|
||||
Bit16u addsp=Fetchw();
|
||||
SETIP(Pop_32());reg_esp+=addsp;
|
||||
break;
|
||||
}
|
||||
reg_eip=Pop_32();
|
||||
reg_esp+=Fetchw();
|
||||
continue;
|
||||
CASE_D(0xc3) /* RETN */
|
||||
SETIP(Pop_32());
|
||||
break;
|
||||
reg_eip=Pop_32();
|
||||
continue;
|
||||
CASE_D(0xc4) /* LES */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(es,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
CASE_D(0xc5) /* LDS */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(ds,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
@ -478,36 +480,11 @@
|
||||
}
|
||||
CASE_D(0xc8) /* ENTER Iw,Ib */
|
||||
{
|
||||
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
|
||||
Bitu frame_ptr=reg_esp-4;
|
||||
if (cpu.stack.big) {
|
||||
reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,reg_ebp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_ebp-=4;reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,mem_readd(SegBase(ss)+reg_ebp));
|
||||
}
|
||||
if (level) {
|
||||
reg_esp-=4;
|
||||
mem_writed(SegBase(ss)+reg_esp,(Bit32u)frame_ptr);
|
||||
}
|
||||
reg_esp-=bytes;
|
||||
} else {
|
||||
reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,reg_ebp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_bp-=4;reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,mem_readd(SegBase(ss)+reg_bp));
|
||||
}
|
||||
if (level) {
|
||||
reg_sp-=4;
|
||||
mem_writed(SegBase(ss)+reg_sp,(Bit32u)frame_ptr);
|
||||
}
|
||||
reg_sp-=bytes;
|
||||
}
|
||||
reg_ebp=frame_ptr;
|
||||
break;
|
||||
Bitu bytes=Fetchw();
|
||||
Bitu level=Fetchb();
|
||||
CPU_ENTER(true,bytes,level);
|
||||
}
|
||||
break;
|
||||
CASE_D(0xc9) /* LEAVE */
|
||||
reg_esp&=~cpu.stack.mask;
|
||||
reg_esp|=(reg_ebp&cpu.stack.mask);
|
||||
@ -516,20 +493,20 @@
|
||||
CASE_D(0xca) /* RETF Iw */
|
||||
{
|
||||
Bitu words=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_RET(true,words,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_RET(true,words,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xcb) /* RETF */
|
||||
{
|
||||
LEAVECORE;
|
||||
CPU_RET(true,0,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_RET(true,0,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xcf) /* IRET */
|
||||
{
|
||||
LEAVECORE;
|
||||
CPU_IRET(true);
|
||||
FillFlags();
|
||||
CPU_IRET(true,GETIP);
|
||||
#if CPU_TRAP_CHECK
|
||||
if (GETFLAG(TF)) {
|
||||
cpudecoder=CPU_Core_Normal_Trap_Run;
|
||||
@ -539,36 +516,79 @@
|
||||
#if CPU_PIC_CHECK
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
|
||||
#endif
|
||||
//TODO TF check
|
||||
goto decode_start;
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xd1) /* GRP2 Ed,1 */
|
||||
GRP2D(1);break;
|
||||
CASE_D(0xd3) /* GRP2 Ed,CL */
|
||||
GRP2D(reg_cl);break;
|
||||
CASE_D(0xe0) /* LOOPNZ */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
JumpCond32_b(--reg_ecx && !get_ZF());
|
||||
} else {
|
||||
JumpCond32_b(--reg_cx && !get_ZF());
|
||||
}
|
||||
break;
|
||||
CASE_D(0xe1) /* LOOPZ */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
JumpCond32_b(--reg_ecx && get_ZF());
|
||||
} else {
|
||||
JumpCond32_b(--reg_cx && get_ZF());
|
||||
}
|
||||
break;
|
||||
CASE_D(0xe2) /* LOOP */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
JumpCond32_b(--reg_ecx);
|
||||
} else {
|
||||
JumpCond32_b(--reg_cx);
|
||||
}
|
||||
break;
|
||||
CASE_D(0xe3) /* JCXZ */
|
||||
JumpCond32_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR]));
|
||||
break;
|
||||
CASE_D(0xe5) /* IN EAX,Ib */
|
||||
reg_eax=IO_ReadD(Fetchb());
|
||||
break;
|
||||
CASE_D(0xe7) /* OUT Ib,EAX */
|
||||
IO_WriteD(Fetchb(),reg_eax);
|
||||
break;
|
||||
CASE_D(0xe8) /* CALL Jd */
|
||||
{
|
||||
Bit32s newip=Fetchds();
|
||||
Push_32((Bit32u)GETIP);
|
||||
ADDIPd(newip);
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
|
||||
reg_eax=IO_ReadD(port);
|
||||
break;
|
||||
}
|
||||
CASE_D(0xe7) /* OUT Ib,EAX */
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
|
||||
IO_WriteD(port,reg_eax);
|
||||
break;
|
||||
}
|
||||
CASE_D(0xe8) /* CALL Jd */
|
||||
{
|
||||
Bit32s addip=Fetchds();
|
||||
SAVEIP;
|
||||
Push_32(reg_eip);
|
||||
reg_eip+=addip;
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xe9) /* JMP Jd */
|
||||
ADDIPd(Fetchds());
|
||||
break;
|
||||
{
|
||||
Bit32s addip=Fetchds();
|
||||
SAVEIP;
|
||||
reg_eip+=addip;
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xea) /* JMP Ad */
|
||||
{
|
||||
Bit32u newip=Fetchd();
|
||||
Bit16u newcs=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_JMP(true,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xeb) /* JMP Jb */
|
||||
{
|
||||
Bit32s addip=Fetchbs();
|
||||
SAVEIP;
|
||||
reg_eip+=addip;
|
||||
continue;
|
||||
}
|
||||
CASE_D(0xed) /* IN EAX,DX */
|
||||
reg_eax=IO_ReadD(reg_dx);
|
||||
@ -631,31 +651,31 @@
|
||||
RMEd(DECD);
|
||||
break;
|
||||
case 0x02: /* CALL NEAR Ed */
|
||||
if (rm >= 0xc0 ) {GetEArd;Push_32(GETIP);SETIP(*eard);}
|
||||
else {GetEAa;Push_32(GETIP);SETIP(LoadMd(eaa));}
|
||||
break;
|
||||
if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
|
||||
else {GetEAa;reg_eip=LoadMd(eaa);}
|
||||
Push_32(GETIP);
|
||||
continue;
|
||||
case 0x03: /* CALL FAR Ed */
|
||||
{
|
||||
GetEAa;
|
||||
Bit32u newip=LoadMd(eaa);
|
||||
Bit16u newcs=LoadMw(eaa+4);
|
||||
LEAVECORE;
|
||||
CPU_CALL(true,newcs,newip);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_CALL(true,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x04: /* JMP NEAR Ed */
|
||||
if (rm >= 0xc0 ) {GetEArd;SETIP(*eard);}
|
||||
else {GetEAa;SETIP(LoadMd(eaa));}
|
||||
break;
|
||||
if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
|
||||
else {GetEAa;reg_eip=LoadMd(eaa);}
|
||||
continue;
|
||||
case 0x05: /* JMP FAR Ed */
|
||||
{
|
||||
GetEAa;
|
||||
Bit32u newip=LoadMd(eaa);
|
||||
Bit16u newcs=LoadMw(eaa+4);
|
||||
LEAVECORE;
|
||||
CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_JMP(true,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x06: /* Push Ed */
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -101,7 +101,7 @@
|
||||
CASE_0F_D(0x02) /* LAR Gd,Ed */
|
||||
{
|
||||
FillFlags();
|
||||
GetRMrd;Bitu ar;
|
||||
GetRMrd;Bitu ar=*rmrd;
|
||||
if (rm >= 0xc0) {
|
||||
GetEArw;CPU_LAR(*earw,ar);
|
||||
} else {
|
||||
@ -113,7 +113,7 @@
|
||||
CASE_0F_D(0x03) /* LSL Gd,Ew */
|
||||
{
|
||||
FillFlags();
|
||||
GetRMrd;Bitu limit;
|
||||
GetRMrd;Bitu limit=*rmrd;
|
||||
/* Just load 16-bit values for selectors */
|
||||
if (rm >= 0xc0) {
|
||||
GetEArw;CPU_LSL(*earw,limit);
|
||||
@ -159,7 +159,8 @@
|
||||
CASE_0F_D(0xa0) /* PUSH FS */
|
||||
Push_32(SegValue(fs));break;
|
||||
CASE_0F_D(0xa1) /* POP FS */
|
||||
POPSEG(fs,Pop_32(),4);break;
|
||||
if (CPU_PopSeg(fs,true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_0F_D(0xa3) /* BT Ed,Gd */
|
||||
{
|
||||
FillFlags();GetRMrd;
|
||||
@ -183,7 +184,8 @@
|
||||
CASE_0F_D(0xa8) /* PUSH GS */
|
||||
Push_32(SegValue(gs));break;
|
||||
CASE_0F_D(0xa9) /* POP GS */
|
||||
POPSEG(gs,Pop_32(),4);break;
|
||||
if (CPU_PopSeg(gs,true)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_0F_D(0xab) /* BTS Ed,Gd */
|
||||
{
|
||||
FillFlags();GetRMrd;
|
||||
@ -215,7 +217,7 @@
|
||||
CASE_0F_D(0xb2) /* LSS Ed */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(ss,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
@ -238,14 +240,14 @@
|
||||
CASE_0F_D(0xb4) /* LFS Ed */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(fs,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
CASE_0F_D(0xb5) /* LGS Ed */
|
||||
{
|
||||
GetRMrd;GetEAa;
|
||||
LOADSEG(gs,LoadMw(eaa+4));
|
||||
if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION();
|
||||
*rmrd=LoadMd(eaa);
|
||||
break;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -31,7 +31,8 @@
|
||||
CASE_W(0x06) /* PUSH ES */
|
||||
Push_16(SegValue(es));break;
|
||||
CASE_W(0x07) /* POP ES */
|
||||
POPSEG(es,Pop_16(),2);break;
|
||||
if (CPU_PopSeg(es,false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_B(0x08) /* OR Eb,Gb */
|
||||
RMEbGb(ORB);break;
|
||||
CASE_W(0x09) /* OR Ew,Gw */
|
||||
@ -65,7 +66,7 @@
|
||||
CASE_W(0x16) /* PUSH SS */
|
||||
Push_16(SegValue(ss));break;
|
||||
CASE_W(0x17) /* POP SS */
|
||||
POPSEG(ss,Pop_16(),2);
|
||||
if (CPU_PopSeg(ss,false)) RUNEXCEPTION();
|
||||
CPU_Cycles++; //Always do another instruction
|
||||
break;
|
||||
CASE_B(0x18) /* SBB Eb,Gb */
|
||||
@ -83,7 +84,7 @@
|
||||
CASE_W(0x1e) /* PUSH DS */
|
||||
Push_16(SegValue(ds));break;
|
||||
CASE_W(0x1f) /* POP DS */
|
||||
POPSEG(ds,Pop_16(),2);
|
||||
if (CPU_PopSeg(ds,false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_B(0x20) /* AND Eb,Gb */
|
||||
RMEbGb(ANDB);break;
|
||||
@ -237,6 +238,7 @@
|
||||
break;
|
||||
CASE_W(0x63) /* ARPL Ew,Rw */
|
||||
{
|
||||
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
|
||||
FillFlags();
|
||||
GetRMrw;
|
||||
if (rm >= 0xc0 ) {
|
||||
@ -255,7 +257,7 @@
|
||||
CASE_B(0x65) /* SEG GS: */
|
||||
DO_PREFIX_SEG(gs);break;
|
||||
CASE_B(0x66) /* Operand Size Prefix */
|
||||
core.opcode_index=core.index_default^OPCODE_SIZE;
|
||||
core.opcode_index=(cpu.code.big^0x1)*0x200;
|
||||
goto restart_opcode;
|
||||
CASE_B(0x67) /* Address Size Prefix */
|
||||
DO_PREFIX_ADDR();
|
||||
@ -271,12 +273,16 @@
|
||||
RMGwEwOp3(DIMULW,Fetchbs());
|
||||
break;
|
||||
CASE_B(0x6c) /* INSB */
|
||||
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
|
||||
DoString(R_INSB);break;
|
||||
CASE_W(0x6d) /* INSW */
|
||||
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
|
||||
DoString(R_INSW);break;
|
||||
CASE_B(0x6e) /* OUTSB */
|
||||
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
|
||||
DoString(R_OUTSB);break;
|
||||
CASE_W(0x6f) /* OUTSW */
|
||||
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
|
||||
DoString(R_OUTSW);break;
|
||||
CASE_W(0x70) /* JO */
|
||||
JumpCond16_b(TFLG_O);break;
|
||||
@ -476,12 +482,12 @@
|
||||
CASE_W(0x8d) /* LEA Gw */
|
||||
{
|
||||
//Little hack to always use segprefixed version
|
||||
core.seg_prefix_base=0;
|
||||
BaseDS=BaseSS=0;
|
||||
GetRMrw;
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
*rmrw=(Bit16u)(*GetEA_SEG_ADDR[rm])();
|
||||
*rmrw=(Bit16u)(*EATable[256+rm])();
|
||||
} else {
|
||||
*rmrw=(Bit16u)(*GetEA_SEG[rm])();
|
||||
*rmrw=(Bit16u)(*EATable[rm])();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -497,13 +503,10 @@
|
||||
case 0x03: /* MOV DS,Ew */
|
||||
case 0x05: /* MOV GS,Ew */
|
||||
case 0x04: /* MOV FS,Ew */
|
||||
LOADSEG((SegNames)which,val);
|
||||
break;
|
||||
case 0x01: /* MOV CS,Ew Illegal*/
|
||||
E_Exit("CPU:Illegal MOV CS Call");
|
||||
if (CPU_SetSegGeneral((SegNames)which,val)) RUNEXCEPTION();
|
||||
break;
|
||||
default:
|
||||
E_Exit("CPU:8E:Illegal RM Byte");
|
||||
goto illegal_opcode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -545,24 +548,20 @@
|
||||
break;
|
||||
CASE_W(0x9a) /* CALL Ap */
|
||||
{
|
||||
FillFlags();
|
||||
Bit16u newip=Fetchw();Bit16u newcs=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
CPU_CALL(false,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_B(0x9b) /* WAIT */
|
||||
break; /* No waiting here */
|
||||
CASE_W(0x9c) /* PUSHF */
|
||||
FillFlags();
|
||||
Push_16(reg_flags);
|
||||
if (CPU_PUSHF(false)) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_W(0x9d) /* POPF */
|
||||
if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) {
|
||||
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
|
||||
CPU_Exception(13,0);
|
||||
goto decode_start;
|
||||
}
|
||||
SETFLAGSw(Pop_16());
|
||||
if (CPU_POPF(false)) RUNEXCEPTION();
|
||||
lflags.type=t_UNKNOWN;
|
||||
#if CPU_TRAP_CHECK
|
||||
if (GETFLAG(TF)) {
|
||||
cpudecoder=CPU_Core_Normal_Trap_Run;
|
||||
@ -665,25 +664,23 @@
|
||||
CASE_W(0xc1) /* GRP2 Ew,Ib */
|
||||
GRP2W(Fetchb());break;
|
||||
CASE_W(0xc2) /* RETN Iw */
|
||||
{
|
||||
Bit16u addsp=Fetchw();
|
||||
SETIP(Pop_16());reg_esp+=addsp;
|
||||
break;
|
||||
}
|
||||
reg_eip=Pop_16();
|
||||
reg_esp+=Fetchw();
|
||||
continue;
|
||||
CASE_W(0xc3) /* RETN */
|
||||
SETIP(Pop_16());
|
||||
break;
|
||||
reg_eip=Pop_16();
|
||||
continue;
|
||||
CASE_W(0xc4) /* LES */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(es,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(es,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
CASE_W(0xc5) /* LDS */
|
||||
{
|
||||
GetRMrw;GetEAa;
|
||||
LOADSEG(ds,LoadMw(eaa+2));
|
||||
if (CPU_SetSegGeneral(ds,LoadMw(eaa+2))) RUNEXCEPTION();
|
||||
*rmrw=LoadMw(eaa);
|
||||
break;
|
||||
}
|
||||
@ -703,36 +700,11 @@
|
||||
}
|
||||
CASE_W(0xc8) /* ENTER Iw,Ib */
|
||||
{
|
||||
Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f;
|
||||
Bitu frame_ptr=reg_esp-2;
|
||||
if (cpu.stack.big) {
|
||||
reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,reg_bp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_ebp-=2;reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,mem_readw(SegBase(ss)+reg_ebp));
|
||||
}
|
||||
if (level) {
|
||||
reg_esp-=2;
|
||||
mem_writew(SegBase(ss)+reg_esp,(Bit16u)frame_ptr);
|
||||
}
|
||||
reg_esp-=bytes;
|
||||
} else {
|
||||
reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,reg_bp);
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
reg_bp-=2;reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,mem_readw(SegBase(ss)+reg_bp));
|
||||
}
|
||||
if (level) {
|
||||
reg_sp-=2;
|
||||
mem_writew(SegBase(ss)+reg_sp,(Bit16u)frame_ptr);
|
||||
}
|
||||
reg_sp-=bytes;
|
||||
}
|
||||
reg_bp=frame_ptr;
|
||||
break;
|
||||
Bitu bytes=Fetchw();
|
||||
Bitu level=Fetchb();
|
||||
CPU_ENTER(false,bytes,level);
|
||||
}
|
||||
break;
|
||||
CASE_W(0xc9) /* LEAVE */
|
||||
reg_esp&=~cpu.stack.mask;
|
||||
reg_esp|=(reg_ebp&cpu.stack.mask);
|
||||
@ -740,58 +712,55 @@
|
||||
break;
|
||||
CASE_W(0xca) /* RETF Iw */
|
||||
{
|
||||
Bitu words=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_RET(false,words,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
Bitu words=Fetchw();
|
||||
FillFlags();
|
||||
CPU_RET(false,words,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_W(0xcb) /* RETF */
|
||||
LEAVECORE;
|
||||
CPU_RET(false,0,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_RET(false,0,GETIP);
|
||||
continue;
|
||||
CASE_B(0xcc) /* INT3 */
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
#if C_DEBUG
|
||||
if (DEBUG_Breakpoint()) {
|
||||
if (DEBUG_Breakpoint())
|
||||
return debugCallback;
|
||||
}
|
||||
#endif
|
||||
CPU_SW_Interrupt(3,(core.ip_lookup-core.op_start));
|
||||
CPU_SW_Interrupt(3,GETIP);
|
||||
#if CPU_TRAP_CHECK
|
||||
core.trap.skip=true;
|
||||
#endif
|
||||
goto decode_start;
|
||||
continue;
|
||||
CASE_B(0xcd) /* INT Ib */
|
||||
{
|
||||
Bit8u num=Fetchb();
|
||||
LEAVECORE;
|
||||
FillFlags();
|
||||
#if C_DEBUG
|
||||
if (DEBUG_IntBreakpoint(num)) {
|
||||
return debugCallback;
|
||||
}
|
||||
#endif
|
||||
CPU_SW_Interrupt(num,core.ip_lookup-core.op_start);
|
||||
CPU_SW_Interrupt(num,GETIP);
|
||||
#if CPU_TRAP_CHECK
|
||||
core.trap.skip=true;
|
||||
#endif
|
||||
goto decode_start;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
CASE_B(0xce) /* INTO */
|
||||
if (get_OF()) {
|
||||
LEAVECORE;
|
||||
CPU_SW_Interrupt(4,core.ip_lookup-core.op_start);
|
||||
FillFlags();
|
||||
CPU_SW_Interrupt(4,GETIP);
|
||||
#if CPU_TRAP_CHECK
|
||||
core.trap.skip=true;
|
||||
#endif
|
||||
goto decode_start;
|
||||
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
CASE_W(0xcf) /* IRET */
|
||||
{
|
||||
LEAVECORE;
|
||||
CPU_IRET(false);
|
||||
FillFlags();
|
||||
CPU_IRET(false,GETIP);
|
||||
#if CPU_PIC_CHECK
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
|
||||
#endif
|
||||
@ -801,7 +770,7 @@
|
||||
return CBRET_NONE;
|
||||
}
|
||||
#endif
|
||||
goto decode_start;
|
||||
continue;
|
||||
}
|
||||
CASE_B(0xd0) /* GRP2 Eb,1 */
|
||||
GRP2B(1);break;
|
||||
@ -819,18 +788,10 @@
|
||||
reg_al = get_CF() ? 0xFF : 0;
|
||||
break;
|
||||
CASE_B(0xd7) /* XLAT */
|
||||
if (TEST_PREFIX_SEG) {
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
reg_al=LoadMb(core.seg_prefix_base+(Bit32u)(reg_ebx+reg_al));
|
||||
} else {
|
||||
reg_al=LoadMb(core.seg_prefix_base+(Bit16u)(reg_bx+reg_al));
|
||||
}
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
reg_al=LoadMb(BaseDS+(Bit32u)(reg_ebx+reg_al));
|
||||
} else {
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
reg_al=LoadMb(SegBase(ds)+(Bit32u)(reg_ebx+reg_al));
|
||||
} else {
|
||||
reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
|
||||
}
|
||||
reg_al=LoadMb(BaseDS+(Bit16u)(reg_bx+reg_al));
|
||||
}
|
||||
break;
|
||||
#ifdef CPU_FPU
|
||||
@ -866,84 +827,104 @@
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
CASE_B(0xe0) /* LOOPNZ */
|
||||
CASE_W(0xe0) /* LOOPNZ */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
if ((--reg_ecx) && !get_ZF()) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_ecx && !get_ZF());
|
||||
} else {
|
||||
if ((--reg_cx) && !get_ZF()) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_cx && !get_ZF());
|
||||
}
|
||||
break;
|
||||
CASE_B(0xe1) /* LOOPZ */
|
||||
CASE_W(0xe1) /* LOOPZ */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
if ((--reg_ecx) && get_ZF()) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_ecx && get_ZF());
|
||||
} else {
|
||||
if ((--reg_cx) && get_ZF()) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_cx && get_ZF());
|
||||
}
|
||||
break;
|
||||
CASE_B(0xe2) /* LOOP */
|
||||
CASE_W(0xe2) /* LOOP */
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
if ((--reg_ecx)) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_ecx);
|
||||
} else {
|
||||
if ((--reg_cx)) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
JumpCond16_b(--reg_cx);
|
||||
}
|
||||
break;
|
||||
CASE_B(0xe3) /* JCXZ */
|
||||
{
|
||||
Bitu test;
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
test=reg_ecx;
|
||||
} else test=reg_cx;
|
||||
if (!test) ADDIPFAST(Fetchbs());
|
||||
else ADDIPFAST(1);
|
||||
CASE_W(0xe3) /* JCXZ */
|
||||
JumpCond16_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR]));
|
||||
break;
|
||||
CASE_B(0xe4) /* IN AL,Ib */
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,1)) RUNEXCEPTION();
|
||||
reg_al=IO_ReadB(port);
|
||||
break;
|
||||
}
|
||||
CASE_B(0xe4) /* IN AL,Ib */
|
||||
reg_al=IO_ReadB(Fetchb());
|
||||
break;
|
||||
CASE_W(0xe5) /* IN AX,Ib */
|
||||
reg_ax=IO_ReadW(Fetchb());
|
||||
break;
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,2)) RUNEXCEPTION();
|
||||
reg_al=IO_ReadW(port);
|
||||
break;
|
||||
}
|
||||
CASE_B(0xe6) /* OUT Ib,AL */
|
||||
IO_WriteB(Fetchb(),reg_al);
|
||||
break;
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,1)) RUNEXCEPTION();
|
||||
IO_WriteB(port,reg_al);
|
||||
break;
|
||||
}
|
||||
CASE_W(0xe7) /* OUT Ib,AX */
|
||||
IO_WriteW(Fetchb(),reg_ax);
|
||||
break;
|
||||
{
|
||||
Bitu port=Fetchb();
|
||||
if (CPU_IO_Exception(port,2)) RUNEXCEPTION();
|
||||
IO_WriteW(port,reg_ax);
|
||||
break;
|
||||
}
|
||||
CASE_W(0xe8) /* CALL Jw */
|
||||
{
|
||||
Bit16s newip=Fetchws();
|
||||
Push_16((Bit16u)GETIP);
|
||||
ADDIPw(newip);
|
||||
break;
|
||||
Bit16u addip=Fetchws();
|
||||
SAVEIP;
|
||||
Push_16(reg_eip);
|
||||
reg_eip=(Bit16u)(reg_eip+addip);
|
||||
continue;
|
||||
}
|
||||
CASE_W(0xe9) /* JMP Jw */
|
||||
ADDIPw(Fetchws());
|
||||
break;
|
||||
{
|
||||
Bit16u addip=Fetchws();
|
||||
SAVEIP;
|
||||
reg_eip=(Bit16u)(reg_eip+addip);
|
||||
continue;
|
||||
}
|
||||
CASE_W(0xea) /* JMP Ap */
|
||||
{
|
||||
Bit16u newip=Fetchw();
|
||||
Bit16u newcs=Fetchw();
|
||||
LEAVECORE;
|
||||
CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_JMP(false,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
CASE_W(0xeb) /* JMP Jb */
|
||||
{
|
||||
Bit16s addip=Fetchbs();
|
||||
SAVEIP;
|
||||
reg_eip=(Bit16u)(reg_eip+addip);
|
||||
continue;
|
||||
}
|
||||
CASE_B(0xeb) /* JMP Jb */
|
||||
ADDIPFAST(Fetchbs());break;
|
||||
CASE_B(0xec) /* IN AL,DX */
|
||||
reg_al=IO_Read(reg_dx);break;
|
||||
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
|
||||
reg_al=IO_ReadB(reg_dx);
|
||||
break;
|
||||
CASE_W(0xed) /* IN AX,DX */
|
||||
reg_al=IO_Read(reg_dx);reg_ah=IO_Read(reg_dx+1);
|
||||
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
|
||||
reg_ax=IO_ReadW(reg_dx);
|
||||
break;
|
||||
CASE_B(0xee) /* OUT DX,AL */
|
||||
IO_WriteB(reg_dx,reg_al);break;
|
||||
if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
|
||||
IO_WriteB(reg_dx,reg_al);
|
||||
break;
|
||||
CASE_W(0xef) /* OUT DX,AX */
|
||||
IO_WriteW(reg_dx,reg_ax);break;
|
||||
if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
|
||||
IO_WriteW(reg_dx,reg_ax);
|
||||
break;
|
||||
CASE_B(0xf0) /* LOCK */
|
||||
LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK");
|
||||
break;
|
||||
@ -954,8 +935,8 @@
|
||||
DO_PREFIX_REP(true);
|
||||
break;
|
||||
CASE_B(0xf4) /* HLT */
|
||||
LEAVECORE;
|
||||
CPU_HLT(core.ip_lookup-core.op_start);
|
||||
FillFlags();
|
||||
CPU_HLT(GETIP);
|
||||
return CBRET_NONE; //Needs to return for hlt cpu core
|
||||
CASE_B(0xf5) /* CMC */
|
||||
FillFlags();
|
||||
@ -1058,20 +1039,10 @@
|
||||
SETFLAGBIT(CF,true);
|
||||
break;
|
||||
CASE_B(0xfa) /* CLI */
|
||||
if (cpu.pmode && (GETFLAG_IOPL<cpu.cpl)) {
|
||||
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
|
||||
CPU_Exception(13,0);
|
||||
goto decode_start;
|
||||
}
|
||||
SETFLAGBIT(IF,false);
|
||||
if (CPU_CLI()) RUNEXCEPTION();
|
||||
break;
|
||||
CASE_B(0xfb) /* STI */
|
||||
if (cpu.pmode && !GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) {
|
||||
LEAVECORE;reg_eip-=core.ip_lookup-core.op_start;
|
||||
CPU_Exception(13,0);
|
||||
goto decode_start;
|
||||
}
|
||||
SETFLAGBIT(IF,true);
|
||||
if (CPU_STI()) RUNEXCEPTION();
|
||||
#if CPU_PIC_CHECK
|
||||
if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
|
||||
#endif
|
||||
@ -1097,7 +1068,7 @@
|
||||
case 0x07: /* CallBack */
|
||||
{
|
||||
Bitu cb=Fetchw();
|
||||
LEAVECORE;
|
||||
FillFlags();SAVEIP;
|
||||
return cb;
|
||||
}
|
||||
default:
|
||||
@ -1117,31 +1088,32 @@
|
||||
RMEw(DECW);
|
||||
break;
|
||||
case 0x02: /* CALL Ev */
|
||||
if (rm >= 0xc0 ) {GetEArw;Push_16((Bit16u)GETIP);SETIP(*earw);}
|
||||
else {GetEAa;Push_16((Bit16u)GETIP);SETIP(LoadMw(eaa));}
|
||||
break;
|
||||
if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;}
|
||||
else {GetEAa;reg_eip=LoadMw(eaa);}
|
||||
Push_16(GETIP);
|
||||
continue;
|
||||
case 0x03: /* CALL Ep */
|
||||
{
|
||||
GetEAa;
|
||||
Bit16u newip=LoadMw(eaa);
|
||||
Bit16u newcs=LoadMw(eaa+2);
|
||||
LEAVECORE;
|
||||
CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_CALL(false,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x04: /* JMP Ev */
|
||||
if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);}
|
||||
else {GetEAa;SETIP(LoadMw(eaa));}
|
||||
break;
|
||||
if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;}
|
||||
else {GetEAa;reg_eip=LoadMw(eaa);}
|
||||
continue;
|
||||
case 0x05: /* JMP Ep */
|
||||
{
|
||||
GetEAa;
|
||||
Bit16u newip=LoadMw(eaa);
|
||||
Bit16u newcs=LoadMw(eaa+2);
|
||||
LEAVECORE;
|
||||
CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start);
|
||||
goto decode_start;
|
||||
FillFlags();
|
||||
CPU_JMP(false,newcs,newip,GETIP);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 0x06: /* PUSH Ev */
|
||||
|
@ -17,21 +17,13 @@ static void DoString(STRING_OP type) {
|
||||
Bitu count,count_left;
|
||||
Bits add_index;
|
||||
|
||||
if (TEST_PREFIX_SEG) si_base=core.seg_prefix_base;
|
||||
else si_base=SegBase(ds);
|
||||
si_base=BaseDS;
|
||||
di_base=SegBase(es);
|
||||
if (TEST_PREFIX_ADDR) {
|
||||
add_mask=0xFFFFFFFF;
|
||||
si_index=reg_esi;
|
||||
di_index=reg_edi;
|
||||
count=reg_ecx;
|
||||
} else {
|
||||
add_mask=0xFFFF;
|
||||
si_index=reg_si;
|
||||
di_index=reg_di;
|
||||
count=reg_cx;
|
||||
}
|
||||
if (!(TEST_PREFIX_REP)) {
|
||||
add_mask=AddrMaskTable[core.prefixes & PREFIX_ADDR];
|
||||
si_index=reg_esi & add_mask;
|
||||
di_index=reg_edi & add_mask;
|
||||
count=reg_ecx & add_mask;
|
||||
if (!TEST_PREFIX_REP) {
|
||||
count=1;
|
||||
} else {
|
||||
CPU_Cycles++;
|
||||
@ -40,7 +32,7 @@ static void DoString(STRING_OP type) {
|
||||
count_left=count-CPU_Cycles;
|
||||
count=CPU_Cycles;
|
||||
CPU_Cycles=0;
|
||||
core.ip_lookup=core.op_start; //Reset IP to start of instruction
|
||||
LOADIP; //RESET IP to the start
|
||||
} else {
|
||||
/* Won't interrupt scas and cmps instruction since they can interrupt themselves */
|
||||
count_left=0;
|
||||
|
@ -9,66 +9,25 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#define SETIP(_a_) (core.ip_lookup=SegBase(cs)+_a_)
|
||||
#define GETIP (Bit32u)(core.ip_lookup-SegBase(cs))
|
||||
#define SAVEIP {reg_eip=GETIP;}
|
||||
#define LOADIP {core.ip_lookup=(SegBase(cs)+reg_eip);}
|
||||
|
||||
#define LEAVECORE \
|
||||
SAVEIP; \
|
||||
FillFlags();
|
||||
#define LoadMbs(off) (Bit8s)(LoadMb(off))
|
||||
#define LoadMws(off) (Bit16s)(LoadMw(off))
|
||||
#define LoadMds(off) (Bit32s)(LoadMd(off))
|
||||
|
||||
static INLINE void ADDIPw(Bits add) {
|
||||
SAVEIP;
|
||||
reg_eip=(Bit16u)(reg_eip+add);
|
||||
LOADIP;
|
||||
}
|
||||
#define LoadRb(reg) reg
|
||||
#define LoadRw(reg) reg
|
||||
#define LoadRd(reg) reg
|
||||
|
||||
static INLINE void ADDIPd(Bits add) {
|
||||
SAVEIP;
|
||||
reg_eip=(reg_eip+add);
|
||||
LOADIP;
|
||||
}
|
||||
|
||||
static INLINE void ADDIPFAST(Bits blah) {
|
||||
// core.ip_lookup+=blah;
|
||||
SAVEIP;
|
||||
reg_eip=(reg_eip+blah);
|
||||
LOADIP;
|
||||
}
|
||||
|
||||
#define EXCEPTION(blah) \
|
||||
{ \
|
||||
Bit8u new_num=blah; \
|
||||
core.ip_lookup=core.op_start; \
|
||||
LEAVECORE; \
|
||||
CPU_Exception(new_num); \
|
||||
goto decode_start; \
|
||||
}
|
||||
|
||||
static INLINE Bit8u Fetchb() {
|
||||
Bit8u temp=LoadMb(core.ip_lookup);
|
||||
core.ip_lookup+=1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
static INLINE Bit16u Fetchw() {
|
||||
Bit16u temp=LoadMw(core.ip_lookup);
|
||||
core.ip_lookup+=2;
|
||||
return temp;
|
||||
}
|
||||
static INLINE Bit32u Fetchd() {
|
||||
Bit32u temp=LoadMd(core.ip_lookup);
|
||||
core.ip_lookup+=4;
|
||||
return temp;
|
||||
}
|
||||
#define SaveRb(reg,val) reg=val
|
||||
#define SaveRw(reg,val) reg=val
|
||||
#define SaveRd(reg,val) reg=val
|
||||
|
||||
static INLINE Bit8s Fetchbs() {
|
||||
return Fetchb();
|
||||
@ -81,68 +40,48 @@ static INLINE Bit32s Fetchds() {
|
||||
return Fetchd();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static INLINE void Push_16(Bit16u blah) {
|
||||
reg_esp-=2;
|
||||
SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
|
||||
};
|
||||
#define RUNEXCEPTION() { \
|
||||
FillFlags(); \
|
||||
CPU_Exception(cpu.exception.which,cpu.exception.error); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
static INLINE void Push_32(Bit32u blah) {
|
||||
reg_esp-=4;
|
||||
SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah);
|
||||
};
|
||||
|
||||
static INLINE Bit16u Pop_16() {
|
||||
Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask));
|
||||
reg_esp+=2;
|
||||
return temp;
|
||||
};
|
||||
|
||||
static INLINE Bit32u Pop_32() {
|
||||
Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask));
|
||||
reg_esp+=4;
|
||||
return temp;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define Push_16 CPU_Push16
|
||||
#define Push_32 CPU_Push32
|
||||
#define Pop_16 CPU_Pop16
|
||||
#define Pop_32 CPU_Pop32
|
||||
|
||||
#endif
|
||||
#define EXCEPTION(blah) \
|
||||
{ \
|
||||
CPU_Exception(blah); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
//TODO Could probably make all byte operands fast?
|
||||
#define JumpCond16_b(blah) \
|
||||
if (blah) { \
|
||||
ADDIPw(Fetchbs()); \
|
||||
} else { \
|
||||
ADDIPFAST(1); \
|
||||
}
|
||||
#define JumpCond16_b(COND) { \
|
||||
SAVEIP; \
|
||||
if (COND) reg_ip+=Fetchbs(); \
|
||||
reg_ip+=1; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define JumpCond32_b(blah) \
|
||||
if (blah) { \
|
||||
ADDIPd(Fetchbs()); \
|
||||
} else { \
|
||||
ADDIPFAST(1); \
|
||||
}
|
||||
#define JumpCond16_w(COND) { \
|
||||
SAVEIP; \
|
||||
if (COND) reg_ip+=Fetchws(); \
|
||||
reg_ip+=2; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define JumpCond16_w(blah) \
|
||||
if (blah) { \
|
||||
ADDIPw(Fetchws()); \
|
||||
} else { \
|
||||
ADDIPFAST(2); \
|
||||
}
|
||||
#define JumpCond32_b(COND) { \
|
||||
SAVEIP; \
|
||||
if (COND) reg_eip+=Fetchbs(); \
|
||||
reg_eip+=1; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define JumpCond32_d(COND) { \
|
||||
SAVEIP; \
|
||||
if (COND) reg_eip+=Fetchds(); \
|
||||
reg_eip+=4; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define JumpCond32_d(blah) \
|
||||
if (blah) { \
|
||||
ADDIPd(Fetchds()); \
|
||||
} else { \
|
||||
ADDIPFAST(4); \
|
||||
}
|
||||
|
||||
#define SETcc(cc) \
|
||||
{ \
|
||||
|
@ -9,207 +9,137 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
typedef PhysPt (*GetEATable[256])(void);
|
||||
typedef PhysPt (*EA_LookupHandler)(void);
|
||||
|
||||
|
||||
/* The MOD/RM Decoder for EA for this decoder's addressing modes */
|
||||
static PhysPt EA_16_00_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); }
|
||||
static PhysPt EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); }
|
||||
static PhysPt EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); }
|
||||
static PhysPt EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); }
|
||||
static PhysPt EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); }
|
||||
static PhysPt EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); }
|
||||
static PhysPt EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());}
|
||||
static PhysPt EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); }
|
||||
static PhysPt EA_16_00_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si); }
|
||||
static PhysPt EA_16_01_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di); }
|
||||
static PhysPt EA_16_02_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si); }
|
||||
static PhysPt EA_16_03_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di); }
|
||||
static PhysPt EA_16_04_n(void) { return BaseDS+(Bit16u)(reg_si); }
|
||||
static PhysPt EA_16_05_n(void) { return BaseDS+(Bit16u)(reg_di); }
|
||||
static PhysPt EA_16_06_n(void) { return BaseDS+(Bit16u)(Fetchw());}
|
||||
static PhysPt EA_16_07_n(void) { return BaseDS+(Bit16u)(reg_bx); }
|
||||
|
||||
static PhysPt EA_16_40_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_41_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_42_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_43_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_44_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); }
|
||||
static PhysPt EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchbs()); }
|
||||
static PhysPt EA_16_40_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_41_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_42_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_43_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_44_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_45_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_46_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchbs()); }
|
||||
static PhysPt EA_16_47_n(void) { return BaseDS+(Bit16u)(reg_bx+Fetchbs()); }
|
||||
|
||||
static PhysPt EA_16_80_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_81_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_82_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_83_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_84_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); }
|
||||
static PhysPt EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); }
|
||||
|
||||
static GetEATable GetEA_NONE={
|
||||
/* 00 */
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
/* 01 */
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
/* 10 */
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
/* 11 These are illegal so make em 0 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
|
||||
|
||||
static PhysPt EA_16_00_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si); }
|
||||
static PhysPt EA_16_01_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di); }
|
||||
static PhysPt EA_16_02_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si); }
|
||||
static PhysPt EA_16_03_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di); }
|
||||
static PhysPt EA_16_04_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si); }
|
||||
static PhysPt EA_16_05_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di); }
|
||||
static PhysPt EA_16_06_s(void) { return core.seg_prefix_base+(Bit16u)(Fetchw()); }
|
||||
static PhysPt EA_16_07_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx); }
|
||||
|
||||
static PhysPt EA_16_40_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_41_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_42_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_43_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_44_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchbs()); }
|
||||
static PhysPt EA_16_45_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchbs()); }
|
||||
static PhysPt EA_16_46_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchbs()); }
|
||||
static PhysPt EA_16_47_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchbs()); }
|
||||
|
||||
static PhysPt EA_16_80_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_81_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_82_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_83_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_84_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_85_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_86_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchws()); }
|
||||
static PhysPt EA_16_87_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchws()); }
|
||||
|
||||
static GetEATable GetEA_SEG={
|
||||
/* 00 */
|
||||
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
|
||||
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
|
||||
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
|
||||
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
|
||||
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
|
||||
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
|
||||
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
|
||||
EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s,
|
||||
/* 01 */
|
||||
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
|
||||
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
|
||||
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
|
||||
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
|
||||
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
|
||||
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
|
||||
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
|
||||
EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s,
|
||||
/* 10 */
|
||||
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
|
||||
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
|
||||
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
|
||||
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
|
||||
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
|
||||
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
|
||||
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
|
||||
EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s,
|
||||
/* 11 These are illegal so make em 0 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
static PhysPt EA_16_80_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_81_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_82_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_83_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_84_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchws()); }
|
||||
static PhysPt EA_16_85_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchws()); }
|
||||
static PhysPt EA_16_86_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchws()); }
|
||||
static PhysPt EA_16_87_n(void) { return BaseDS+(Bit16u)(reg_bx+Fetchws()); }
|
||||
|
||||
static Bit32u SIBZero=0;
|
||||
static Bit32u * SIBIndex[8]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_edi };
|
||||
|
||||
INLINE PhysPt Sib(Bitu mode) {
|
||||
static INLINE PhysPt Sib(Bitu mode) {
|
||||
Bit8u sib=Fetchb();
|
||||
PhysPt base;
|
||||
switch (sib&7) {
|
||||
case 0: /* EAX Base */
|
||||
base=SegBase(ds)+reg_eax;break;
|
||||
base=BaseDS+reg_eax;break;
|
||||
case 1: /* ECX Base */
|
||||
base=SegBase(ds)+reg_ecx;break;
|
||||
base=BaseDS+reg_ecx;break;
|
||||
case 2: /* EDX Base */
|
||||
base=SegBase(ds)+reg_edx;break;
|
||||
base=BaseDS+reg_edx;break;
|
||||
case 3: /* EBX Base */
|
||||
base=SegBase(ds)+reg_ebx;break;
|
||||
base=BaseDS+reg_ebx;break;
|
||||
case 4: /* ESP Base */
|
||||
base=SegBase(ss)+reg_esp;break;
|
||||
base=BaseSS+reg_esp;break;
|
||||
case 5: /* #1 Base */
|
||||
if (!mode) {
|
||||
base=SegBase(ds)+Fetchd();break;
|
||||
base=BaseDS+Fetchd();break;
|
||||
} else {
|
||||
base=SegBase(ss)+reg_ebp;break;
|
||||
base=BaseSS+reg_ebp;break;
|
||||
}
|
||||
case 6: /* ESI Base */
|
||||
base=SegBase(ds)+reg_esi;break;
|
||||
base=BaseDS+reg_esi;break;
|
||||
case 7: /* EDI Base */
|
||||
base=SegBase(ds)+reg_edi;break;
|
||||
base=BaseDS+reg_edi;break;
|
||||
}
|
||||
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
|
||||
return base;
|
||||
};
|
||||
|
||||
|
||||
static PhysPt EA_32_00_n(void) { return SegBase(ds)+reg_eax; }
|
||||
static PhysPt EA_32_01_n(void) { return SegBase(ds)+reg_ecx; }
|
||||
static PhysPt EA_32_02_n(void) { return SegBase(ds)+reg_edx; }
|
||||
static PhysPt EA_32_03_n(void) { return SegBase(ds)+reg_ebx; }
|
||||
static PhysPt EA_32_00_n(void) { return BaseDS+reg_eax; }
|
||||
static PhysPt EA_32_01_n(void) { return BaseDS+reg_ecx; }
|
||||
static PhysPt EA_32_02_n(void) { return BaseDS+reg_edx; }
|
||||
static PhysPt EA_32_03_n(void) { return BaseDS+reg_ebx; }
|
||||
static PhysPt EA_32_04_n(void) { return Sib(0);}
|
||||
static PhysPt EA_32_05_n(void) { return SegBase(ds)+Fetchd(); }
|
||||
static PhysPt EA_32_06_n(void) { return SegBase(ds)+reg_esi; }
|
||||
static PhysPt EA_32_07_n(void) { return SegBase(ds)+reg_edi; }
|
||||
static PhysPt EA_32_05_n(void) { return BaseDS+Fetchd(); }
|
||||
static PhysPt EA_32_06_n(void) { return BaseDS+reg_esi; }
|
||||
static PhysPt EA_32_07_n(void) { return BaseDS+reg_edi; }
|
||||
|
||||
static PhysPt EA_32_40_n(void) { return SegBase(ds)+reg_eax+Fetchbs(); }
|
||||
static PhysPt EA_32_41_n(void) { return SegBase(ds)+reg_ecx+Fetchbs(); }
|
||||
static PhysPt EA_32_42_n(void) { return SegBase(ds)+reg_edx+Fetchbs(); }
|
||||
static PhysPt EA_32_43_n(void) { return SegBase(ds)+reg_ebx+Fetchbs(); }
|
||||
static PhysPt EA_32_40_n(void) { return BaseDS+reg_eax+Fetchbs(); }
|
||||
static PhysPt EA_32_41_n(void) { return BaseDS+reg_ecx+Fetchbs(); }
|
||||
static PhysPt EA_32_42_n(void) { return BaseDS+reg_edx+Fetchbs(); }
|
||||
static PhysPt EA_32_43_n(void) { return BaseDS+reg_ebx+Fetchbs(); }
|
||||
static PhysPt EA_32_44_n(void) { PhysPt temp=Sib(1);return temp+Fetchbs();}
|
||||
//static PhysPt EA_32_44_n(void) { return Sib(1)+Fetchbs();}
|
||||
static PhysPt EA_32_45_n(void) { return SegBase(ss)+reg_ebp+Fetchbs(); }
|
||||
static PhysPt EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); }
|
||||
static PhysPt EA_32_47_n(void) { return SegBase(ds)+reg_edi+Fetchbs(); }
|
||||
static PhysPt EA_32_45_n(void) { return BaseSS+reg_ebp+Fetchbs(); }
|
||||
static PhysPt EA_32_46_n(void) { return BaseDS+reg_esi+Fetchbs(); }
|
||||
static PhysPt EA_32_47_n(void) { return BaseDS+reg_edi+Fetchbs(); }
|
||||
|
||||
static PhysPt EA_32_80_n(void) { return SegBase(ds)+reg_eax+Fetchds(); }
|
||||
static PhysPt EA_32_81_n(void) { return SegBase(ds)+reg_ecx+Fetchds(); }
|
||||
static PhysPt EA_32_82_n(void) { return SegBase(ds)+reg_edx+Fetchds(); }
|
||||
static PhysPt EA_32_83_n(void) { return SegBase(ds)+reg_ebx+Fetchds(); }
|
||||
static PhysPt EA_32_80_n(void) { return BaseDS+reg_eax+Fetchds(); }
|
||||
static PhysPt EA_32_81_n(void) { return BaseDS+reg_ecx+Fetchds(); }
|
||||
static PhysPt EA_32_82_n(void) { return BaseDS+reg_edx+Fetchds(); }
|
||||
static PhysPt EA_32_83_n(void) { return BaseDS+reg_ebx+Fetchds(); }
|
||||
static PhysPt EA_32_84_n(void) { PhysPt temp=Sib(2);return temp+Fetchds();}
|
||||
//static PhysPt EA_32_84_n(void) { return Sib(2)+Fetchds();}
|
||||
static PhysPt EA_32_85_n(void) { return SegBase(ss)+reg_ebp+Fetchds(); }
|
||||
static PhysPt EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); }
|
||||
static PhysPt EA_32_87_n(void) { return SegBase(ds)+reg_edi+Fetchds(); }
|
||||
static PhysPt EA_32_85_n(void) { return BaseSS+reg_ebp+Fetchds(); }
|
||||
static PhysPt EA_32_86_n(void) { return BaseDS+reg_esi+Fetchds(); }
|
||||
static PhysPt EA_32_87_n(void) { return BaseDS+reg_edi+Fetchds(); }
|
||||
|
||||
static GetEATable GetEA_ADDR={
|
||||
static GetEAHandler EATable[512]={
|
||||
/* 00 */
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
|
||||
/* 01 */
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
|
||||
/* 10 */
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
|
||||
/* 11 These are illegal so make em 0 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 00 */
|
||||
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
|
||||
EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
|
||||
@ -244,113 +174,12 @@ static GetEATable GetEA_ADDR={
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
INLINE PhysPt Sib_s(Bitu mode) {
|
||||
Bit8u sib=Fetchb();
|
||||
PhysPt base;
|
||||
switch (sib&7) {
|
||||
case 0: /* EAX Base */
|
||||
base=reg_eax;break;
|
||||
case 1: /* ECX Base */
|
||||
base=reg_ecx;break;
|
||||
case 2: /* EDX Base */
|
||||
base=reg_edx;break;
|
||||
case 3: /* EBX Base */
|
||||
base=reg_ebx;break;
|
||||
case 4: /* ESP Base */
|
||||
base=reg_esp;break;
|
||||
case 5: /* #1 Base */
|
||||
if (!mode) {
|
||||
base=Fetchd();break;
|
||||
} else {
|
||||
base=reg_ebp;break;
|
||||
}
|
||||
case 6: /* ESI Base */
|
||||
base=reg_esi;break;
|
||||
case 7: /* EDI Base */
|
||||
base=reg_edi;break;
|
||||
}
|
||||
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
|
||||
return base;
|
||||
};
|
||||
|
||||
|
||||
static PhysPt EA_32_00_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax); }
|
||||
static PhysPt EA_32_01_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx); }
|
||||
static PhysPt EA_32_02_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx); }
|
||||
static PhysPt EA_32_03_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx); }
|
||||
static PhysPt EA_32_04_s(void) { return core.seg_prefix_base+(Bit32u)(Sib_s(0));}
|
||||
static PhysPt EA_32_05_s(void) { return core.seg_prefix_base+(Bit32u)(Fetchd()); }
|
||||
static PhysPt EA_32_06_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi); }
|
||||
static PhysPt EA_32_07_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi); }
|
||||
|
||||
static PhysPt EA_32_40_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchbs()); }
|
||||
static PhysPt EA_32_41_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchbs()); }
|
||||
static PhysPt EA_32_42_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchbs()); }
|
||||
static PhysPt EA_32_43_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchbs()); }
|
||||
static PhysPt EA_32_44_s(void) { PhysPt temp=Sib_s(1);return core.seg_prefix_base+(Bit32u)(temp+Fetchbs());}
|
||||
static PhysPt EA_32_45_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchbs()); }
|
||||
static PhysPt EA_32_46_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchbs()); }
|
||||
static PhysPt EA_32_47_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchbs()); }
|
||||
|
||||
static PhysPt EA_32_80_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchds()); }
|
||||
static PhysPt EA_32_81_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchds()); }
|
||||
static PhysPt EA_32_82_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchds()); }
|
||||
static PhysPt EA_32_83_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchds()); }
|
||||
static PhysPt EA_32_84_s(void) { PhysPt temp=Sib_s(2);return core.seg_prefix_base+(Bit32u)(temp+Fetchds());}
|
||||
static PhysPt EA_32_85_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchds()); }
|
||||
static PhysPt EA_32_86_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchds()); }
|
||||
static PhysPt EA_32_87_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchds()); }
|
||||
|
||||
|
||||
static GetEATable GetEA_SEG_ADDR={
|
||||
/* 00 */
|
||||
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||
EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s,
|
||||
/* 01 */
|
||||
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||
EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s,
|
||||
/* 10 */
|
||||
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||
EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s,
|
||||
/* 11 These are illegal so make em 0 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
#define GetEADirect \
|
||||
PhysPt eaa; \
|
||||
if (TEST_PREFIX_SEG) { \
|
||||
if (TEST_PREFIX_ADDR) { \
|
||||
eaa=core.seg_prefix_base+Fetchd(); \
|
||||
} else { \
|
||||
eaa=core.seg_prefix_base+Fetchw(); \
|
||||
} \
|
||||
} else { \
|
||||
if (TEST_PREFIX_ADDR) { \
|
||||
eaa=SegBase(ds)+Fetchd(); \
|
||||
} else { \
|
||||
eaa=SegBase(ds)+Fetchw(); \
|
||||
} \
|
||||
}
|
||||
#define GetEADirect \
|
||||
PhysPt eaa; \
|
||||
if (TEST_PREFIX_ADDR) { \
|
||||
eaa=BaseDS+Fetchd(); \
|
||||
} else { \
|
||||
eaa=BaseDS+Fetchw(); \
|
||||
} \
|
||||
|
||||
|
||||
|
203
src/cpu/core_simple.cpp
Normal file
203
src/cpu/core_simple.cpp
Normal 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) {
|
||||
|
||||
}
|
||||
|
280
src/cpu/cpu.cpp
280
src/cpu/cpu.cpp
@ -9,21 +9,21 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: cpu.cpp,v 1.53 2004/01/14 17:09:41 harekiet Exp $ */
|
||||
/* $Id: cpu.cpp,v 1.61 2004/08/23 12:17:29 harekiet Exp $ */
|
||||
|
||||
#include <assert.h>
|
||||
#include "dosbox.h"
|
||||
#include "cpu.h"
|
||||
#include "memory.h"
|
||||
#include "debug.h"
|
||||
#include "keyboard.h"
|
||||
#include "mapper.h"
|
||||
#include "setup.h"
|
||||
#include "paging.h"
|
||||
#include "support.h"
|
||||
@ -46,12 +46,9 @@ Bits CPU_CycleUp = 0;
|
||||
Bits CPU_CycleDown = 0;
|
||||
CPU_Decoder * cpudecoder;
|
||||
|
||||
static struct {
|
||||
Bitu which,errorcode;
|
||||
} exception;
|
||||
|
||||
void CPU_Core_Full_Init(void);
|
||||
void CPU_Core_Normal_Init(void);
|
||||
void CPU_Core_Simple_Init(void);
|
||||
void CPU_Core_Dyn_X86_Init(void);
|
||||
|
||||
void CPU_Push16(Bitu value) {
|
||||
@ -91,6 +88,48 @@ void CPU_SetFlags(Bitu word,Bitu mask) {
|
||||
cpu.direction=1-((reg_flags & FLAG_DF) >> 9);
|
||||
}
|
||||
|
||||
bool CPU_PrepareException(Bitu which,Bitu error) {
|
||||
cpu.exception.which=which;
|
||||
cpu.exception.error=error;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPU_CLI(void) {
|
||||
if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) || (GETFLAG(VM) && (GETFLAG_IOPL<3)))) {
|
||||
return CPU_PrepareException(13,0);
|
||||
} else {
|
||||
SETFLAGBIT(IF,false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPU_STI(void) {
|
||||
if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) || (GETFLAG(VM) && (GETFLAG_IOPL<3)))) {
|
||||
return CPU_PrepareException(13,0);
|
||||
} else {
|
||||
SETFLAGBIT(IF,true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPU_POPF(Bitu use32) {
|
||||
if ((reg_flags & FLAG_VM) && (GETFLAG(IOPL)!=FLAG_IOPL))
|
||||
return CPU_PrepareException(13,0);
|
||||
if (use32)
|
||||
CPU_SetFlagsd(CPU_Pop32());
|
||||
else CPU_SetFlagsw(CPU_Pop16());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CPU_PUSHF(Bitu use32) {
|
||||
if ((reg_flags & FLAG_VM) && (GETFLAG(IOPL)!=FLAG_IOPL))
|
||||
return CPU_PrepareException(13,0);
|
||||
if (use32)
|
||||
CPU_Push32(reg_flags);
|
||||
else CPU_Push16(reg_flags);
|
||||
return false;
|
||||
}
|
||||
|
||||
class TaskStateSegment {
|
||||
public:
|
||||
TaskStateSegment() {
|
||||
@ -148,7 +187,7 @@ enum TSwitchType {
|
||||
TSwitch_JMP,TSwitch_CALL_INT,TSwitch_IRET
|
||||
};
|
||||
|
||||
bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype) {
|
||||
bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype,Bitu old_eip) {
|
||||
TaskStateSegment new_tss;
|
||||
if (!new_tss.SetSelector(new_tss_selector))
|
||||
E_Exit("Illegal TSS for switch");
|
||||
@ -163,7 +202,7 @@ bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype) {
|
||||
Bitu new_ldt;
|
||||
if (cpu_tss.is386) {
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,eflags),reg_flags);
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,eip),reg_eip);
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,eip),old_eip);
|
||||
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,eax),reg_eax);
|
||||
mem_writed(cpu_tss.base+offsetof(TSS_32,ecx),reg_ecx);
|
||||
@ -268,23 +307,31 @@ doconforming:
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPU_StartException(void) {
|
||||
CPU_Interrupt(cpu.exception.which,CPU_INT_EXCEPTION | ((cpu.exception.which>=8) ? CPU_INT_HAS_ERROR : 0));
|
||||
}
|
||||
|
||||
void CPU_SetupException(Bitu which,Bitu error) {
|
||||
cpu.exception.which=which;
|
||||
cpu.exception.error=error;
|
||||
bool CPU_IO_Exception(Bitu port,Bitu size) {
|
||||
if (cpu.pmode && ((GETFLAG_IOPL<cpu.cpl) || GETFLAG(VM))) {
|
||||
if (!cpu_tss.is386) goto doexception;
|
||||
PhysPt where=cpu_tss.base+0x66;
|
||||
Bitu ofs=mem_readw(where);
|
||||
if (ofs>cpu_tss.limit) goto doexception;
|
||||
where=cpu_tss.base+ofs+(port/8);
|
||||
Bitu map=mem_readw(where);
|
||||
Bitu mask=(0xffff>>(16-size)) << (port&7);
|
||||
if (map & mask) goto doexception;
|
||||
}
|
||||
return false;
|
||||
doexception:
|
||||
LOG_MSG("Exception");
|
||||
return CPU_PrepareException(13,0);
|
||||
}
|
||||
|
||||
void CPU_Exception(Bitu which,Bitu error ) {
|
||||
// LOG_MSG("Exception %d CS:%X IP:%X FLAGS:%X",num,SegValue(cs),reg_eip,reg_flags);
|
||||
CPU_SetupException(which,error);
|
||||
CPU_StartException();
|
||||
// LOG_MSG("Exception %d error %x",which,error);
|
||||
cpu.exception.error=error;
|
||||
CPU_Interrupt(which,CPU_INT_EXCEPTION | ((which>=8) ? CPU_INT_HAS_ERROR : 0),reg_eip);
|
||||
}
|
||||
|
||||
Bit8u lastint;
|
||||
void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
||||
void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) {
|
||||
lastint=num;
|
||||
#if C_DEBUG
|
||||
switch (num) {
|
||||
@ -302,10 +349,10 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
||||
};
|
||||
#endif
|
||||
if (!cpu.pmode) {
|
||||
/* Save everything on a 16-bit stack */
|
||||
/* Save everything on a 16-bit stack */
|
||||
CPU_Push16(reg_flags & 0xffff);
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_ip);
|
||||
CPU_Push16(oldeip);
|
||||
SETFLAGBIT(IF,false);
|
||||
SETFLAGBIT(TF,false);
|
||||
/* Get the new CS:IP from vector table */
|
||||
@ -323,7 +370,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
||||
if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE)) {
|
||||
// LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12);
|
||||
if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,0);
|
||||
return;
|
||||
}
|
||||
@ -332,7 +378,6 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
||||
//TODO Check for software interrupt and check gate's dpl<cpl
|
||||
cpu.idt.GetDescriptor(num<<3,gate);
|
||||
if (type&CPU_INT_SOFTWARE && gate.DPL()<cpu.cpl) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,num*8+2);
|
||||
return;
|
||||
}
|
||||
@ -345,7 +390,7 @@ void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) {
|
||||
Bitu gate_off=gate.GetOffset();
|
||||
cpu.gdt.GetDescriptor(gate_sel,cs_desc);
|
||||
Bitu cs_dpl=cs_desc.DPL();
|
||||
if (cs_dpl>cpu.cpl) E_Exit("Interrupt to higher privilege");
|
||||
if (cs_dpl>cpu.cpl) E_Exit("Interrupt to higher privilege");
|
||||
switch (cs_desc.Type()) {
|
||||
case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA:
|
||||
case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA:
|
||||
@ -397,12 +442,12 @@ do_interrupt:
|
||||
if (gate.Type() & 0x8) { /* 32-bit Gate */
|
||||
CPU_Push32(reg_flags);
|
||||
CPU_Push32(SegValue(cs));
|
||||
CPU_Push32(reg_eip);
|
||||
CPU_Push32(oldeip);
|
||||
if (type & CPU_INT_HAS_ERROR) CPU_Push32(cpu.exception.error);
|
||||
} else { /* 16-bit gate */
|
||||
CPU_Push16(reg_flags & 0xffff);
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_ip);
|
||||
CPU_Push16(oldeip);
|
||||
if (type & CPU_INT_HAS_ERROR) CPU_Push16(cpu.exception.error);
|
||||
}
|
||||
break;
|
||||
@ -410,7 +455,7 @@ do_interrupt:
|
||||
E_Exit("INT:Gate Selector points to illegal descriptor with type %x",cs_desc.Type());
|
||||
}
|
||||
if (!(gate.Type()&1))
|
||||
SETFLAGBIT(IF,false);
|
||||
SETFLAGBIT(IF,false);
|
||||
SETFLAGBIT(TF,false);
|
||||
SETFLAGBIT(NT,false);
|
||||
SETFLAGBIT(VM,false);
|
||||
@ -422,7 +467,7 @@ do_interrupt:
|
||||
return;
|
||||
}
|
||||
case DESC_TASK_GATE:
|
||||
CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT);
|
||||
CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT,oldeip);
|
||||
if (type & CPU_INT_HAS_ERROR) {
|
||||
//TODO Be sure about this, seems somewhat unclear
|
||||
if (cpu_tss.is386) CPU_Push32(cpu.exception.error);
|
||||
@ -437,7 +482,7 @@ do_interrupt:
|
||||
return ; // make compiler happy
|
||||
}
|
||||
|
||||
void CPU_IRET(bool use32) {
|
||||
void CPU_IRET(bool use32,Bitu oldeip) {
|
||||
if (!cpu.pmode) { /* RealMode IRET */
|
||||
realmode_iret:
|
||||
if (use32) {
|
||||
@ -454,7 +499,6 @@ realmode_iret:
|
||||
} else { /* Protected mode IRET */
|
||||
if (reg_flags & FLAG_VM) {
|
||||
if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
|
||||
reg_eip--;
|
||||
CPU_Exception(13,0);
|
||||
return;
|
||||
} else goto realmode_iret;
|
||||
@ -466,7 +510,7 @@ realmode_iret:
|
||||
if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set");
|
||||
if (!cpu_tss.IsValid()) E_Exit("TASK Iret without valid TSS");
|
||||
Bitu back_link=cpu_tss.Get_back();
|
||||
CPU_SwitchTask(back_link,TSwitch_IRET);
|
||||
CPU_SwitchTask(back_link,TSwitch_IRET,oldeip);
|
||||
return;
|
||||
}
|
||||
Bitu n_cs_sel,n_eip,n_flags;
|
||||
@ -506,7 +550,7 @@ realmode_iret:
|
||||
Bitu n_cs_rpl=n_cs_sel & 3;
|
||||
Descriptor n_cs_desc;
|
||||
cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc);
|
||||
if (n_cs_rpl<cpu.cpl)
|
||||
if (n_cs_rpl<cpu.cpl)
|
||||
E_Exit("IRET to lower privilege");
|
||||
if (n_cs_rpl==cpu.cpl) {
|
||||
/* Return to same level */
|
||||
@ -526,6 +570,7 @@ realmode_iret:
|
||||
cpu.code.big=n_cs_desc.Big()>0;
|
||||
Segs.val[cs]=n_cs_sel;
|
||||
reg_eip=n_eip;
|
||||
|
||||
CPU_SetFlagsd(n_flags);
|
||||
LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big);
|
||||
} else {
|
||||
@ -545,9 +590,11 @@ realmode_iret:
|
||||
Segs.phys[cs]=n_cs_desc.GetBase();
|
||||
cpu.code.big=n_cs_desc.Big()>0;
|
||||
Segs.val[cs]=n_cs_sel;
|
||||
|
||||
CPU_SetFlagsd(n_flags);
|
||||
|
||||
cpu.cpl=n_cs_rpl;
|
||||
reg_eip=n_eip;
|
||||
CPU_SetFlagsd(n_flags);
|
||||
Bitu n_ss,n_esp;
|
||||
if (use32) {
|
||||
n_esp=CPU_Pop32();
|
||||
@ -562,14 +609,15 @@ realmode_iret:
|
||||
} else {
|
||||
reg_sp=n_esp;
|
||||
}
|
||||
|
||||
//TODO Maybe validate other segments, but why would anyone use them?
|
||||
LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:X big %d",n_cs_sel,n_eip,cpu.code.big);
|
||||
LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
||||
void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip) {
|
||||
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
|
||||
if (!use32) {
|
||||
reg_eip=offset&0xffff;
|
||||
@ -584,7 +632,6 @@ void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
||||
Descriptor desc;
|
||||
cpu.gdt.GetDescriptor(selector,desc);
|
||||
if (!desc.saved.seg.p) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
}
|
||||
@ -592,8 +639,7 @@ void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
||||
case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA:
|
||||
case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA:
|
||||
if (rpl>cpu.cpl) E_Exit("JMP:NC:RPL>CPL");
|
||||
if (rpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL");
|
||||
cpu.cpl=desc.DPL();
|
||||
if (cpu.cpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL");
|
||||
LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:NC to %X:%X big %d",selector,offset,desc.Big());
|
||||
goto CODE_jmp;
|
||||
case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA:
|
||||
@ -610,7 +656,7 @@ CODE_jmp:
|
||||
if (desc.DPL()<cpu.cpl) E_Exit("JMP:TSS:dpl<cpl");
|
||||
if (desc.DPL()<rpl) E_Exit("JMP:TSS:dpl<rpl");
|
||||
LOG(LOG_CPU,LOG_NORMAL)("JMP:TSS to %X",selector);
|
||||
CPU_SwitchTask(selector,TSwitch_JMP);
|
||||
CPU_SwitchTask(selector,TSwitch_JMP,oldeip);
|
||||
break;
|
||||
default:
|
||||
E_Exit("JMP Illegal descriptor type %X",desc.Type());
|
||||
@ -621,15 +667,15 @@ CODE_jmp:
|
||||
|
||||
|
||||
|
||||
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
||||
void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip) {
|
||||
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
|
||||
if (!use32) {
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_ip);
|
||||
CPU_Push16(oldeip);
|
||||
reg_eip=offset&0xffff;
|
||||
} else {
|
||||
CPU_Push32(SegValue(cs));
|
||||
CPU_Push32(reg_eip);
|
||||
CPU_Push32(oldeip);
|
||||
reg_eip=offset;
|
||||
}
|
||||
cpu.code.big=false;
|
||||
@ -640,7 +686,6 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
||||
Bitu rpl=selector & 3;
|
||||
cpu.gdt.GetDescriptor(selector,call);
|
||||
if (!call.saved.seg.p) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
}
|
||||
@ -659,11 +704,11 @@ void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen) {
|
||||
call_code:
|
||||
if (!use32) {
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_ip);
|
||||
CPU_Push16(oldeip);
|
||||
reg_eip=offset & 0xffff;
|
||||
} else {
|
||||
CPU_Push32(SegValue(cs));
|
||||
CPU_Push32(reg_eip);
|
||||
CPU_Push32(oldeip);
|
||||
reg_eip=offset;
|
||||
}
|
||||
Segs.phys[cs]=call.GetBase();
|
||||
@ -679,7 +724,6 @@ call_code:
|
||||
Bitu n_cs_sel=call.GetSelector();
|
||||
if (!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc)) E_Exit("Call:Gate:Invalid CS selector.");
|
||||
if (!n_cs_desc.saved.seg.p) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
}
|
||||
@ -709,19 +753,22 @@ call_code:
|
||||
if (call.Type()==DESC_386_CALL_GATE) {
|
||||
CPU_Push32(o_ss); //save old stack
|
||||
CPU_Push32(o_esp);
|
||||
for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++)
|
||||
CPU_Push32(mem_readd(o_stack+i*4));
|
||||
if (call.saved.gate.paramcount&31)
|
||||
for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--)
|
||||
CPU_Push32(mem_readd(o_stack+i*4));
|
||||
CPU_Push32(SegValue(cs));
|
||||
CPU_Push32(reg_eip);
|
||||
CPU_Push32(oldeip);
|
||||
} else {
|
||||
CPU_Push16(o_ss); //save old stack
|
||||
CPU_Push16(o_esp);
|
||||
for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++)
|
||||
CPU_Push16(mem_readw(o_stack+i*2));
|
||||
if (call.saved.gate.paramcount&31)
|
||||
for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--)
|
||||
CPU_Push16(mem_readw(o_stack+i*2));
|
||||
CPU_Push16(SegValue(cs));
|
||||
CPU_Push16(reg_eip);
|
||||
CPU_Push16(oldeip);
|
||||
}
|
||||
|
||||
cpu.cpl = n_cs_desc.DPL();
|
||||
/* Switch to new CS:EIP */
|
||||
Segs.phys[cs] = n_cs_desc.GetBase();
|
||||
Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl;
|
||||
@ -742,7 +789,7 @@ call_gate_same_privilege:
|
||||
if (call.DPL()<cpu.cpl) E_Exit("CALL:TSS:dpl<cpl");
|
||||
if (call.DPL()<rpl) E_Exit("CALL:TSS:dpl<rpl");
|
||||
LOG(LOG_CPU,LOG_NORMAL)("CALL:TSS to %X",selector);
|
||||
CPU_SwitchTask(selector,TSwitch_CALL_INT);
|
||||
CPU_SwitchTask(selector,TSwitch_CALL_INT,oldeip);
|
||||
break;
|
||||
default:
|
||||
E_Exit("CALL:Descriptor type %x unsupported",call.Type());
|
||||
@ -753,7 +800,7 @@ call_gate_same_privilege:
|
||||
}
|
||||
|
||||
|
||||
void CPU_RET(bool use32,Bitu bytes,Bitu opLen) {
|
||||
void CPU_RET(bool use32,Bitu bytes,Bitu oldeip) {
|
||||
if (!cpu.pmode || (reg_flags & FLAG_VM)) {
|
||||
Bitu new_ip,new_cs;
|
||||
if (!use32) {
|
||||
@ -775,11 +822,13 @@ void CPU_RET(bool use32,Bitu bytes,Bitu opLen) {
|
||||
|
||||
Descriptor desc;
|
||||
Bitu rpl=selector & 3;
|
||||
if (rpl<cpu.cpl) E_Exit("RET to lower privilege");
|
||||
if (rpl<cpu.cpl) {
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
}
|
||||
cpu.gdt.GetDescriptor(selector,desc);
|
||||
|
||||
if (!desc.saved.seg.p) {
|
||||
reg_eip -= opLen;
|
||||
CPU_Exception(0x0B,selector & 0xfffc);
|
||||
return;
|
||||
};
|
||||
@ -820,7 +869,7 @@ RET_same_level:
|
||||
return;
|
||||
} else {
|
||||
/* Return to outer level */
|
||||
if (bytes) E_Exit("RETF outeer level with immediate value");
|
||||
if (bytes) E_Exit("RETF outer level with immediate value");
|
||||
Bitu n_esp,n_ss;
|
||||
if (use32) {
|
||||
n_esp = CPU_Pop32();
|
||||
@ -830,16 +879,19 @@ RET_same_level:
|
||||
n_ss = CPU_Pop16();
|
||||
}
|
||||
cpu.cpl = rpl;
|
||||
|
||||
CPU_SetSegGeneral(ss,n_ss);
|
||||
if (cpu.stack.big) {
|
||||
reg_esp = n_esp;
|
||||
} else {
|
||||
reg_sp = n_esp;
|
||||
}
|
||||
|
||||
Segs.phys[cs]=desc.GetBase();
|
||||
cpu.code.big=desc.Big()>0;
|
||||
Segs.val[cs]=selector;
|
||||
Segs.val[cs]=(selector&0xfffc) | cpu.cpl;
|
||||
reg_eip=offset;
|
||||
|
||||
// LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL());
|
||||
return;
|
||||
}
|
||||
@ -899,9 +951,8 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
|
||||
case 0:
|
||||
{
|
||||
Bitu changed=cpu.cr0 ^ value;
|
||||
if (!changed) return true;
|
||||
if (!changed) return false;
|
||||
cpu.cr0=value;
|
||||
//TODO Maybe always first change to core_full for a change to cr0
|
||||
if (value & CR0_PROTECTION) {
|
||||
cpu.pmode=true;
|
||||
LOG(LOG_CPU,LOG_NORMAL)("Protected mode");
|
||||
@ -911,7 +962,7 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) {
|
||||
PAGING_Enable(false);
|
||||
LOG(LOG_CPU,LOG_NORMAL)("Real mode");
|
||||
}
|
||||
return false; //Only changes with next CS change
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
paging.cr2=value;
|
||||
@ -946,11 +997,12 @@ void CPU_SMSW(Bitu & word) {
|
||||
word=cpu.cr0;
|
||||
}
|
||||
|
||||
bool CPU_LMSW(Bitu word) {
|
||||
Bitu CPU_LMSW(Bitu word) {
|
||||
word&=0xf;
|
||||
if (cpu.cr0 & 1) word|=1;
|
||||
word|=(cpu.cr0&0xfffffff0);
|
||||
return CPU_SET_CRX(0,word);
|
||||
CPU_SET_CRX(0,word);
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
|
||||
@ -964,8 +1016,11 @@ void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
|
||||
}
|
||||
|
||||
void CPU_LAR(Bitu selector,Bitu & ar) {
|
||||
if (selector == 0) {
|
||||
SETFLAGBIT(ZF,false);
|
||||
return;
|
||||
}
|
||||
Descriptor desc;Bitu rpl=selector & 3;
|
||||
ar=0;
|
||||
if (!cpu.gdt.GetDescriptor(selector,desc)){
|
||||
SETFLAGBIT(ZF,false);
|
||||
return;
|
||||
@ -974,16 +1029,20 @@ void CPU_LAR(Bitu selector,Bitu & ar) {
|
||||
case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA:
|
||||
case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA:
|
||||
break;
|
||||
|
||||
|
||||
case DESC_286_INT_GATE: case DESC_286_TRAP_GATE: {
|
||||
case DESC_386_INT_GATE: case DESC_386_TRAP_GATE:
|
||||
SETFLAGBIT(ZF,false);
|
||||
return;
|
||||
}
|
||||
|
||||
case DESC_LDT:
|
||||
case DESC_TASK_GATE:
|
||||
|
||||
case DESC_286_TSS_A: case DESC_286_TSS_B:
|
||||
case DESC_286_INT_GATE: case DESC_286_TRAP_GATE:
|
||||
case DESC_286_CALL_GATE:
|
||||
|
||||
case DESC_386_TSS_A: case DESC_386_TSS_B:
|
||||
case DESC_386_INT_GATE: case DESC_386_TRAP_GATE:
|
||||
case DESC_386_CALL_GATE:
|
||||
|
||||
|
||||
@ -1008,8 +1067,11 @@ void CPU_LAR(Bitu selector,Bitu & ar) {
|
||||
}
|
||||
|
||||
void CPU_LSL(Bitu selector,Bitu & limit) {
|
||||
if (selector == 0) {
|
||||
SETFLAGBIT(ZF,false);
|
||||
return;
|
||||
}
|
||||
Descriptor desc;Bitu rpl=selector & 3;
|
||||
limit=0;
|
||||
if (!cpu.gdt.GetDescriptor(selector,desc)){
|
||||
SETFLAGBIT(ZF,false);
|
||||
return;
|
||||
@ -1018,7 +1080,7 @@ void CPU_LSL(Bitu selector,Bitu & limit) {
|
||||
case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA:
|
||||
case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA:
|
||||
break;
|
||||
|
||||
|
||||
case DESC_LDT:
|
||||
case DESC_286_TSS_A:
|
||||
case DESC_286_TSS_B:
|
||||
@ -1047,6 +1109,10 @@ void CPU_LSL(Bitu selector,Bitu & limit) {
|
||||
}
|
||||
|
||||
void CPU_VERR(Bitu selector) {
|
||||
if (selector == 0) {
|
||||
SETFLAGBIT(ZF,false);
|
||||
return;
|
||||
}
|
||||
Descriptor desc;Bitu rpl=selector & 3;
|
||||
if (!cpu.gdt.GetDescriptor(selector,desc)){
|
||||
SETFLAGBIT(ZF,false);
|
||||
@ -1075,6 +1141,10 @@ void CPU_VERR(Bitu selector) {
|
||||
}
|
||||
|
||||
void CPU_VERW(Bitu selector) {
|
||||
if (selector == 0) {
|
||||
SETFLAGBIT(ZF,false);
|
||||
return;
|
||||
}
|
||||
Descriptor desc;Bitu rpl=selector & 3;
|
||||
if (!cpu.gdt.GetDescriptor(selector,desc)){
|
||||
SETFLAGBIT(ZF,false);
|
||||
@ -1113,13 +1183,11 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) {
|
||||
if (!desc.saved.seg.p) {
|
||||
if (seg==ss) E_Exit("CPU_SetSegGeneral: Stack segment not present.");
|
||||
// Throw Exception 0x0B - Segment not present
|
||||
CPU_SetupException(0x0B,value & 0xfffc);
|
||||
return true;
|
||||
return CPU_PrepareException(0x0B,value & 0xfffc);
|
||||
} else if (seg==ss) {
|
||||
// Stack segment loaded with illegal segment ?
|
||||
if ((desc.saved.seg.type<DESC_DATA_EU_RO_NA) || (desc.saved.seg.type>DESC_DATA_ED_RW_A)) {
|
||||
CPU_SetupException(0x0D,value & 0xfffc);
|
||||
return true;
|
||||
return CPU_PrepareException(0x0D,value & 0xfffc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1138,6 +1206,14 @@ bool CPU_SetSegGeneral(SegNames seg,Bitu value) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CPU_PopSeg(SegNames seg,bool use32) {
|
||||
Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask));
|
||||
if (CPU_SetSegGeneral(seg,val)) return true;
|
||||
Bitu addsp=2 << use32;
|
||||
reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+addsp)&cpu.stack.mask);
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPU_CPUID(void) {
|
||||
switch (reg_eax) {
|
||||
case 0: /* Vendor ID String and maximum level? */
|
||||
@ -1168,12 +1244,12 @@ static Bits HLT_Decode(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CPU_HLT(Bitu opLen) {
|
||||
void CPU_HLT(Bitu oldeip) {
|
||||
if (cpu.cpl) {
|
||||
reg_eip-=opLen;
|
||||
CPU_Exception(13,0);
|
||||
return;
|
||||
}
|
||||
reg_eip=oldeip;
|
||||
CPU_Cycles=0;
|
||||
cpu.hlt.cs=SegValue(cs);
|
||||
cpu.hlt.eip=reg_eip;
|
||||
@ -1182,8 +1258,40 @@ void CPU_HLT(Bitu opLen) {
|
||||
return;
|
||||
}
|
||||
|
||||
void CPU_ENTER(bool use32,Bitu bytes,Bitu level) {
|
||||
level&=0x1f;
|
||||
Bitu sp_index=reg_esp&cpu.stack.mask;
|
||||
Bitu bp_index=reg_ebp&cpu.stack.mask;
|
||||
if (!use32) {
|
||||
sp_index-=2;
|
||||
mem_writew(SegPhys(ss)+sp_index,reg_bp);
|
||||
reg_bp=(Bit16u)(reg_esp-2);
|
||||
if (level) {
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
sp_index-=2;bp_index-=2;
|
||||
mem_writew(SegPhys(ss)+sp_index,mem_readw(SegPhys(ss)+bp_index));
|
||||
}
|
||||
sp_index-=2;
|
||||
mem_writew(SegPhys(ss)+sp_index,reg_bp);
|
||||
}
|
||||
} else {
|
||||
sp_index-=4;
|
||||
mem_writed(SegPhys(ss)+sp_index,reg_ebp);
|
||||
reg_ebp=(reg_esp-4);
|
||||
if (level) {
|
||||
for (Bitu i=1;i<level;i++) {
|
||||
sp_index-=4;bp_index-=4;
|
||||
mem_writed(SegPhys(ss)+sp_index,mem_readd(SegPhys(ss)+bp_index));
|
||||
}
|
||||
sp_index-=4;
|
||||
mem_writed(SegPhys(ss)+sp_index,reg_ebp);
|
||||
}
|
||||
}
|
||||
sp_index-=bytes;
|
||||
reg_esp=(reg_esp&~cpu.stack.mask)|((sp_index)&cpu.stack.mask);
|
||||
}
|
||||
|
||||
extern void GFX_SetTitle(Bits cycles ,Bits frameskip);
|
||||
extern void GFX_SetTitle(Bits cycles ,Bits frameskip,bool paused);
|
||||
static void CPU_CycleIncrease(void) {
|
||||
Bits old_cycles=CPU_CycleMax;
|
||||
if(CPU_CycleUp < 100){
|
||||
@ -1195,7 +1303,7 @@ static void CPU_CycleIncrease(void) {
|
||||
CPU_CycleLeft=0;CPU_Cycles=0;
|
||||
if (CPU_CycleMax==old_cycles) CPU_CycleMax++;
|
||||
LOG_MSG("CPU:%d cycles",CPU_CycleMax);
|
||||
GFX_SetTitle(CPU_CycleMax,-1);
|
||||
GFX_SetTitle(CPU_CycleMax,-1,false);
|
||||
}
|
||||
|
||||
static void CPU_CycleDecrease(void) {
|
||||
@ -1207,10 +1315,9 @@ static void CPU_CycleDecrease(void) {
|
||||
CPU_CycleLeft=0;CPU_Cycles=0;
|
||||
if (CPU_CycleMax <= 0) CPU_CycleMax=1;
|
||||
LOG_MSG("CPU:%d cycles",CPU_CycleMax);
|
||||
GFX_SetTitle(CPU_CycleMax,-1);
|
||||
GFX_SetTitle(CPU_CycleMax,-1,false);
|
||||
}
|
||||
|
||||
|
||||
void CPU_Init(Section* sec) {
|
||||
Section_prop * section=static_cast<Section_prop *>(sec);
|
||||
reg_eax=0;
|
||||
@ -1240,14 +1347,13 @@ void CPU_Init(Section* sec) {
|
||||
|
||||
/* Init the cpu cores */
|
||||
CPU_Core_Normal_Init();
|
||||
CPU_Core_Simple_Init();
|
||||
CPU_Core_Full_Init();
|
||||
#if (C_DYNAMIC_X86)
|
||||
CPU_Core_Dyn_X86_Init();
|
||||
#endif
|
||||
|
||||
KEYBOARD_AddEvent(KBD_f11,KBD_MOD_CTRL,CPU_CycleDecrease);
|
||||
KEYBOARD_AddEvent(KBD_f12,KBD_MOD_CTRL,CPU_CycleIncrease);
|
||||
|
||||
MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles");
|
||||
MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles");
|
||||
CPU_Cycles=0;
|
||||
CPU_CycleMax=section->Get_int("cycles");;
|
||||
CPU_CycleUp=section->Get_int("cycleup");
|
||||
@ -1256,6 +1362,8 @@ void CPU_Init(Section* sec) {
|
||||
cpudecoder=&CPU_Core_Normal_Run;
|
||||
if (!strcasecmp(core,"normal")) {
|
||||
cpudecoder=&CPU_Core_Normal_Run;
|
||||
} else if (!strcasecmp(core,"simple")) {
|
||||
cpudecoder=&CPU_Core_Simple_Run;
|
||||
} else if (!strcasecmp(core,"full")) {
|
||||
cpudecoder=&CPU_Core_Full_Run;
|
||||
}
|
||||
@ -1267,12 +1375,12 @@ void CPU_Init(Section* sec) {
|
||||
else {
|
||||
LOG_MSG("CPU:Unknown core type %s, switcing back to normal.",core);
|
||||
}
|
||||
CPU_JMP(false,0,0); //Setup the first cpu core
|
||||
CPU_JMP(false,0,0,0); //Setup the first cpu core
|
||||
|
||||
if (!CPU_CycleMax) CPU_CycleMax = 2500;
|
||||
if(!CPU_CycleUp) CPU_CycleUp = 500;
|
||||
if(!CPU_CycleDown) CPU_CycleDown = 20;
|
||||
CPU_CycleLeft=0;
|
||||
GFX_SetTitle(CPU_CycleMax,-1);
|
||||
GFX_SetTitle(CPU_CycleMax,-1,false);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -548,7 +548,7 @@
|
||||
}
|
||||
|
||||
#define MULB(op1,load,save) \
|
||||
lflags.type=t_MUL; \
|
||||
FillFlags(); \
|
||||
reg_ax=reg_al*load(op1); \
|
||||
if (reg_ax & 0xff00) { \
|
||||
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
||||
@ -558,10 +558,10 @@
|
||||
|
||||
#define MULW(op1,load,save) \
|
||||
{ \
|
||||
FillFlags(); \
|
||||
Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \
|
||||
reg_ax=(Bit16u)(tempu); \
|
||||
reg_dx=(Bit16u)(tempu >> 16); \
|
||||
lflags.type=t_MUL; \
|
||||
if (reg_dx) { \
|
||||
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
||||
} else { \
|
||||
@ -571,10 +571,10 @@
|
||||
|
||||
#define MULD(op1,load,save) \
|
||||
{ \
|
||||
FillFlags(); \
|
||||
Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \
|
||||
reg_eax=(Bit32u)(tempu); \
|
||||
reg_edx=(Bit32u)(tempu >> 32); \
|
||||
lflags.type=t_MUL; \
|
||||
if (reg_edx) { \
|
||||
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
|
||||
} else { \
|
||||
@ -651,7 +651,7 @@
|
||||
|
||||
#define IMULB(op1,load,save) \
|
||||
{ \
|
||||
lflags.type=t_MUL; \
|
||||
FillFlags(); \
|
||||
reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \
|
||||
if ((reg_ax & 0xff80)==0xff80 || \
|
||||
(reg_ax & 0xff80)==0x0000) { \
|
||||
@ -664,10 +664,10 @@
|
||||
|
||||
#define IMULW(op1,load,save) \
|
||||
{ \
|
||||
FillFlags(); \
|
||||
Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \
|
||||
reg_ax=(Bit16s)(temps); \
|
||||
reg_dx=(Bit16s)(temps >> 16); \
|
||||
lflags.type=t_MUL; \
|
||||
if (((temps & 0xffff8000)==0xffff8000 || \
|
||||
(temps & 0xffff8000)==0x0000)) { \
|
||||
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
||||
@ -678,11 +678,11 @@
|
||||
|
||||
#define IMULD(op1,load,save) \
|
||||
{ \
|
||||
FillFlags(); \
|
||||
Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \
|
||||
((Bit64s)((Bit32s)(load(op1)))); \
|
||||
reg_eax=(Bit32u)(temps); \
|
||||
reg_edx=(Bit32u)(temps >> 32); \
|
||||
lflags.type=t_MUL; \
|
||||
if ((reg_edx==0xffffffff) && \
|
||||
(reg_eax & 0x80000000) ) { \
|
||||
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
||||
@ -696,10 +696,10 @@
|
||||
|
||||
#define DIMULW(op1,op2,op3,load,save) \
|
||||
{ \
|
||||
FillFlags(); \
|
||||
Bits res; \
|
||||
res=((Bit16s)op2) * ((Bit16s)op3); \
|
||||
save(op1,res & 0xffff); \
|
||||
lflags.type=t_MUL; \
|
||||
if ((res> -32768) && (res<32767)) { \
|
||||
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
||||
} else { \
|
||||
@ -709,9 +709,9 @@
|
||||
|
||||
#define DIMULD(op1,op2,op3,load,save) \
|
||||
{ \
|
||||
FillFlags(); \
|
||||
Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \
|
||||
save(op1,(Bit32s)res); \
|
||||
lflags.type=t_MUL; \
|
||||
if ((res>-((Bit64s)(2147483647)+1)) && \
|
||||
(res<(Bit64s)2147483647)) { \
|
||||
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -93,7 +93,7 @@ static Bits PageFaultCore(void) {
|
||||
if (!pf_queue.used) E_Exit("PF Core without PF");
|
||||
PF_Entry * entry=&pf_queue.entries[pf_queue.used-1];
|
||||
X86PageEntry pentry;
|
||||
pentry.load=MEM_PhysReadD(entry->page_addr);
|
||||
pentry.load=phys_readd(entry->page_addr);
|
||||
if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip)
|
||||
return -1;
|
||||
return 0;
|
||||
@ -102,6 +102,8 @@ static Bits PageFaultCore(void) {
|
||||
Bitu DEBUG_EnableDebugger(void);
|
||||
#endif
|
||||
|
||||
bool first=false;
|
||||
|
||||
void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) {
|
||||
/* Save the state of the cpu cores */
|
||||
LazyFlags old_lflags;
|
||||
@ -112,6 +114,8 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) {
|
||||
paging.cr2=lin_addr;
|
||||
PF_Entry * entry=&pf_queue.entries[pf_queue.used++];
|
||||
LOG(LOG_PAGING,LOG_NORMAL)("PageFault at %X type %d queue %d",lin_addr,type,pf_queue.used);
|
||||
// LOG_MSG("EAX:%04X ECX:%04X EDX:%04X EBX:%04X",reg_eax,reg_ecx,reg_edx,reg_ebx);
|
||||
// LOG_MSG("CS:%04X EIP:%08X SS:%04x SP:%08X",SegValue(cs),reg_eip,SegValue(ss),reg_esp);
|
||||
entry->cs=SegValue(cs);
|
||||
entry->eip=reg_eip;
|
||||
entry->page_addr=page_addr;
|
||||
@ -125,10 +129,9 @@ void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) {
|
||||
LOG(LOG_PAGING,LOG_NORMAL)("Left PageFault for %x queue %d",lin_addr,pf_queue.used);
|
||||
memcpy(&lflags,&old_lflags,sizeof(LazyFlags));
|
||||
cpudecoder=old_cpudecoder;
|
||||
// LOG_MSG("SS:%04x SP:%08X",SegValue(ss),reg_esp);
|
||||
}
|
||||
|
||||
|
||||
void MEM_PhysWriteD(Bitu addr,Bit32u val);
|
||||
class InitPageHandler : public PageHandler {
|
||||
public:
|
||||
InitPageHandler() {flags=PFLAG_INIT|PFLAG_NOCODE;}
|
||||
@ -164,28 +167,28 @@ public:
|
||||
Bitu t_index=lin_page & 0x3ff;
|
||||
Bitu table_addr=(paging.base.page<<12)+d_index*4;
|
||||
X86PageEntry table;
|
||||
table.load=MEM_PhysReadD(table_addr);
|
||||
table.load=phys_readd(table_addr);
|
||||
if (!table.block.p) {
|
||||
LOG(LOG_PAGING,LOG_ERROR)("NP Table");
|
||||
PAGING_PageFault(lin_addr,table_addr,0);
|
||||
table.load=MEM_PhysReadD(table_addr);
|
||||
table.load=phys_readd(table_addr);
|
||||
if (!table.block.p)
|
||||
E_Exit("Pagefault didn't correct table");
|
||||
}
|
||||
table.block.a=table.block.d=1; //Set access/Dirty
|
||||
MEM_PhysWriteD(table_addr,table.load);
|
||||
phys_writed(table_addr,table.load);
|
||||
X86PageEntry entry;
|
||||
Bitu entry_addr=(table.block.base<<12)+t_index*4;
|
||||
entry.load=MEM_PhysReadD(entry_addr);
|
||||
entry.load=phys_readd(entry_addr);
|
||||
if (!entry.block.p) {
|
||||
LOG(LOG_PAGING,LOG_ERROR)("NP Page");
|
||||
PAGING_PageFault(lin_addr,entry_addr,0);
|
||||
entry.load=MEM_PhysReadD(entry_addr);
|
||||
entry.load=phys_readd(entry_addr);
|
||||
if (!entry.block.p)
|
||||
E_Exit("Pagefault didn't correct page");
|
||||
}
|
||||
entry.block.a=entry.block.d=1; //Set access/Dirty
|
||||
MEM_PhysWriteD(entry_addr,entry.load);
|
||||
phys_writed(entry_addr,entry.load);
|
||||
phys_page=entry.block.base;
|
||||
} else {
|
||||
if (lin_page<LINK_START) phys_page=mapfirstmb[lin_page];
|
||||
@ -200,10 +203,10 @@ bool PAGING_MakePhysPage(Bitu & page) {
|
||||
Bitu d_index=page >> 10;
|
||||
Bitu t_index=page & 0x3ff;
|
||||
X86PageEntry table;
|
||||
table.load=MEM_PhysReadD((paging.base.page<<12)+d_index*4);
|
||||
table.load=phys_readd((paging.base.page<<12)+d_index*4);
|
||||
if (!table.block.p) return false;
|
||||
X86PageEntry entry;
|
||||
entry.load=MEM_PhysReadD((table.block.base<<12)+t_index*4);
|
||||
entry.load=phys_readd((table.block.base<<12)+t_index*4);
|
||||
if (!entry.block.p) return false;
|
||||
page=entry.block.base;
|
||||
} else {
|
||||
@ -251,16 +254,21 @@ void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) {
|
||||
void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) {
|
||||
PageHandler * handler=MEM_GetPageHandler(phys_page);
|
||||
Bitu lin_base=lin_page << 12;
|
||||
|
||||
if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE)
|
||||
E_Exit("Illegal page");
|
||||
|
||||
if (paging.links.used>=PAGING_LINKS) {
|
||||
LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache");
|
||||
PAGING_ClearTLB();
|
||||
}
|
||||
|
||||
HostPt host_mem=handler->GetHostPt(phys_page);
|
||||
paging.tlb.phys_page[lin_page]=phys_page;
|
||||
if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=host_mem-lin_base;
|
||||
else paging.tlb.read[lin_page]=0;
|
||||
if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=host_mem-lin_base;
|
||||
else paging.tlb.write[lin_page]=0;
|
||||
if (paging.links.used>=PAGING_LINKS) E_Exit("Not enough paging links");
|
||||
|
||||
paging.links.entries[paging.links.used++]=lin_page;
|
||||
paging.tlb.handler[lin_page]=handler;
|
||||
}
|
||||
@ -281,7 +289,7 @@ void PAGING_SetDirBase(Bitu cr3) {
|
||||
|
||||
paging.base.page=cr3 >> 12;
|
||||
paging.base.addr=cr3 & ~4095;
|
||||
LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page);
|
||||
// LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page);
|
||||
if (paging.enabled) {
|
||||
PAGING_ClearTLB();
|
||||
}
|
||||
@ -292,9 +300,15 @@ void PAGING_Enable(bool enabled) {
|
||||
if (paging.enabled==enabled) return;
|
||||
paging.enabled=enabled;
|
||||
if (!enabled) {
|
||||
LOG(LOG_PAGING,LOG_NORMAL)("Disabled");
|
||||
// LOG(LOG_PAGING,LOG_NORMAL)("Disabled");
|
||||
} else {
|
||||
LOG(LOG_PAGING,LOG_NORMAL)("Enabled");
|
||||
if (cpudecoder==CPU_Core_Simple_Run) {
|
||||
LOG_MSG("CPU core simple won't run this game,switching to normal");
|
||||
cpudecoder=CPU_Core_Normal_Run;
|
||||
CPU_CycleLeft+=CPU_Cycles;
|
||||
CPU_Cycles=0;
|
||||
}
|
||||
// LOG(LOG_PAGING,LOG_NORMAL)("Enabled");
|
||||
PAGING_SetDirBase(paging.cr3);
|
||||
}
|
||||
PAGING_ClearTLB();
|
||||
|
@ -9,16 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: debug.cpp,v 1.52 2004/01/27 14:52:28 qbix79 Exp $ */
|
||||
|
||||
#include "programs.h"
|
||||
/* $Id: debug.cpp,v 1.59 2004/08/31 23:11:35 harekiet Exp $ */
|
||||
|
||||
#include <string.h>
|
||||
#include <list>
|
||||
@ -26,19 +24,21 @@
|
||||
#include "dosbox.h"
|
||||
#if C_DEBUG
|
||||
#include "debug.h"
|
||||
#include "cross.h" //snprintf
|
||||
#include "cpu.h"
|
||||
#include "video.h"
|
||||
#include "pic.h"
|
||||
#include "keyboard.h"
|
||||
#include "mapper.h"
|
||||
#include "cpu.h"
|
||||
#include "callback.h"
|
||||
#include "inout.h"
|
||||
#include "mixer.h"
|
||||
#include "debug_inc.h"
|
||||
#include "timer.h"
|
||||
#include "paging.h"
|
||||
#include "../ints/xms.h"
|
||||
#include "support.h"
|
||||
#include "shell.h"
|
||||
#include "programs.h"
|
||||
#include "debug_inc.h"
|
||||
|
||||
#ifdef WIN32
|
||||
void WIN32_Console();
|
||||
@ -53,13 +53,17 @@ int old_cursor_state;
|
||||
static void DrawCode(void);
|
||||
static bool DEBUG_Log_Loop(int count);
|
||||
static void DEBUG_RaiseTimerIrq(void);
|
||||
static void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num);
|
||||
static void LogGDT(void);
|
||||
static void LogLDT(void);
|
||||
static void LogIDT(void);
|
||||
static void OutputVecTable(char* filename);
|
||||
static void DrawVariables(void);
|
||||
|
||||
char* AnalyzeInstruction(char* inst, bool saveSelector);
|
||||
void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num);
|
||||
Bit32u GetHexValue(char* str, char*& hex);
|
||||
void LogGDT(void);
|
||||
void LogLDT(void);
|
||||
void LogIDT(void);
|
||||
void OutputVecTable(char* filename);
|
||||
|
||||
|
||||
|
||||
class DEBUG;
|
||||
|
||||
@ -67,6 +71,7 @@ DEBUG* pDebugcom = 0;
|
||||
bool exitLoop = false;
|
||||
bool logHeavy = false;
|
||||
|
||||
|
||||
// Heavy Debugging Vars for logging
|
||||
#if C_HEAVY_DEBUG
|
||||
static FILE* cpuLogFile = 0;
|
||||
@ -74,6 +79,8 @@ static bool cpuLog = false;
|
||||
static int cpuLogCounter = 0;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static struct {
|
||||
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
|
||||
} oldregs;
|
||||
@ -86,6 +93,8 @@ DBGBlock dbg;
|
||||
static Bitu input_count;
|
||||
Bitu cycle_count;
|
||||
static bool debugging;
|
||||
|
||||
|
||||
static void SetColor(Bitu test) {
|
||||
if (test) {
|
||||
if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));}
|
||||
@ -535,35 +544,26 @@ void CBreakpoint::ShowList(void)
|
||||
bool DEBUG_Breakpoint(void)
|
||||
{
|
||||
/* First get the phyiscal address and check for a set Breakpoint */
|
||||
// PhysPt where=SegPhys(cs)+reg_eip-1;
|
||||
PhysPt where=GetAddress(SegValue(cs),reg_eip-1);
|
||||
if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip-1)) return false;
|
||||
PhysPt where=GetAddress(SegValue(cs),reg_eip);
|
||||
if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) return false;
|
||||
// Found. Breakpoint is valid
|
||||
reg_eip -= 1;
|
||||
CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints
|
||||
// exitLoop = true;
|
||||
// DEBUG_Enable();
|
||||
return true;
|
||||
};
|
||||
|
||||
bool DEBUG_IntBreakpoint(Bit8u intNum)
|
||||
{
|
||||
/* First get the phyiscal address and check for a set Breakpoint */
|
||||
// PhysPt where=SegPhys(cs)+reg_eip-2;
|
||||
PhysPt where=GetAddress(SegValue(cs),reg_eip-2);
|
||||
PhysPt where=GetAddress(SegValue(cs),reg_eip);
|
||||
if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false;
|
||||
// Found. Breakpoint is valid
|
||||
reg_eip -= 2;
|
||||
CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints
|
||||
// exitLoop = true;
|
||||
// DEBUG_Enable();
|
||||
return true;
|
||||
};
|
||||
|
||||
static bool StepOver()
|
||||
{
|
||||
exitLoop = false;
|
||||
// PhysPt start=SegPhys(cs)+reg_eip;
|
||||
PhysPt start=GetAddress(SegValue(cs),reg_eip);
|
||||
char dline[200];Bitu size;
|
||||
size=DasmI386(dline, start, reg_eip, cpu.code.big);
|
||||
@ -581,6 +581,10 @@ static bool StepOver()
|
||||
|
||||
bool DEBUG_ExitLoop(void)
|
||||
{
|
||||
#if C_HEAVY_DEBUG
|
||||
DrawVariables();
|
||||
#endif
|
||||
|
||||
if (exitLoop) {
|
||||
exitLoop = false;
|
||||
return true;
|
||||
@ -911,6 +915,30 @@ bool ParseCommand(char* str)
|
||||
else DEBUG_ShowMsg("DEBUG: Variable list load (%s) : failure",name);
|
||||
return true;
|
||||
}
|
||||
found = strstr(str,"SR ");
|
||||
if (found) { // Set register value
|
||||
found+=2;
|
||||
if (ChangeRegister(found)) DEBUG_ShowMsg("DEBUG: Set Register success.");
|
||||
else DEBUG_ShowMsg("DEBUG: Set Register failure.");
|
||||
return true;
|
||||
}
|
||||
found = strstr(str,"SM ");
|
||||
if (found) { // Set memory with following values
|
||||
found+=3;
|
||||
Bit16u seg = (Bit16u)GetHexValue(found,found); found++;
|
||||
Bit32u ofs = GetHexValue(found,found); found++;
|
||||
Bit16u count = 0;
|
||||
while (*found) {
|
||||
while (*found==' ') found++;
|
||||
if (*found) {
|
||||
Bit8u value = (Bit8u)GetHexValue(found,found); found++;
|
||||
mem_writeb(GetAddress(seg,ofs+count),value);
|
||||
count++;
|
||||
}
|
||||
};
|
||||
DEBUG_ShowMsg("DEBUG: Memory changed.");
|
||||
return true;
|
||||
}
|
||||
|
||||
found = strstr(str,"BP ");
|
||||
if (found) { // Add new breakpoint
|
||||
@ -1025,30 +1053,6 @@ bool ParseCommand(char* str)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
found = strstr(str,"SR ");
|
||||
if (found) { // Set register value
|
||||
found+=2;
|
||||
if (ChangeRegister(found)) DEBUG_ShowMsg("DEBUG: Set Register success.");
|
||||
else DEBUG_ShowMsg("DEBUG: Set Register failure.");
|
||||
return true;
|
||||
}
|
||||
found = strstr(str,"SM ");
|
||||
if (found) { // Set memory with following values
|
||||
found+=3;
|
||||
Bit16u seg = (Bit16u)GetHexValue(found,found); found++;
|
||||
Bit32u ofs = GetHexValue(found,found); found++;
|
||||
Bit16u count = 0;
|
||||
while (*found) {
|
||||
while (*found==' ') found++;
|
||||
if (*found) {
|
||||
Bit8u value = (Bit8u)GetHexValue(found,found); found++;
|
||||
mem_writeb(GetAddress(seg,ofs+count),value);
|
||||
count++;
|
||||
}
|
||||
};
|
||||
DEBUG_ShowMsg("DEBUG: Memory changed.");
|
||||
return true;
|
||||
}
|
||||
found = strstr(str,"INTT ");
|
||||
if (found) { // Create Cpu log file
|
||||
found+=4;
|
||||
@ -1433,6 +1437,7 @@ Bitu DEBUG_Loop(void) {
|
||||
Bit16u oldCS = SegValue(cs);
|
||||
Bit32u oldEIP = reg_eip;
|
||||
PIC_runIRQs();
|
||||
SDL_Delay(1);
|
||||
if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) {
|
||||
CBreakpoint::AddBreakpoint(oldCS,oldEIP,true);
|
||||
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
|
||||
@ -1455,13 +1460,14 @@ void DEBUG_DrawScreen(void) {
|
||||
DrawData();
|
||||
DrawCode();
|
||||
DrawRegisters();
|
||||
DrawVariables();
|
||||
}
|
||||
|
||||
static void DEBUG_RaiseTimerIrq(void) {
|
||||
PIC_ActivateIRQ(0);
|
||||
}
|
||||
|
||||
void LogGDT(void)
|
||||
static void LogGDT(void)
|
||||
{
|
||||
char out1[512];
|
||||
Descriptor desc;
|
||||
@ -1480,7 +1486,7 @@ void LogGDT(void)
|
||||
};
|
||||
};
|
||||
|
||||
void LogLDT(void)
|
||||
static void LogLDT(void)
|
||||
{
|
||||
char out1[512];
|
||||
Descriptor desc;
|
||||
@ -1501,7 +1507,7 @@ void LogLDT(void)
|
||||
};
|
||||
};
|
||||
|
||||
void LogIDT(void)
|
||||
static void LogIDT(void)
|
||||
{
|
||||
char out1[512];
|
||||
Descriptor desc;
|
||||
@ -1681,8 +1687,7 @@ void DEBUG_Init(Section* sec) {
|
||||
MSG_Add("DEBUG_CONFIGFILE_HELP","Nothing to setup yet!\n");
|
||||
DEBUG_DrawScreen();
|
||||
/* Add some keyhandlers */
|
||||
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable);
|
||||
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
|
||||
MAPPER_AddHandler(DEBUG_Enable,MK_pause,0,"debugger","Debugger");
|
||||
/* Clear the TBreakpoint list */
|
||||
memset((void*)&codeViewData,0,sizeof(codeViewData));
|
||||
/* setup debug.com */
|
||||
@ -1769,7 +1774,7 @@ bool CDebugVar::LoadVars(char* name)
|
||||
return true;
|
||||
};
|
||||
|
||||
void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num)
|
||||
static void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num)
|
||||
{
|
||||
FILE* f = fopen("MEMDUMP.TXT","wt");
|
||||
if (!f) {
|
||||
@ -1796,7 +1801,7 @@ void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num)
|
||||
DEBUG_ShowMsg("DEBUG: Memory dump success.");
|
||||
};
|
||||
|
||||
void OutputVecTable(char* filename)
|
||||
static void OutputVecTable(char* filename)
|
||||
{
|
||||
FILE* f = fopen(filename, "wt");
|
||||
if (!f)
|
||||
@ -1812,6 +1817,35 @@ void OutputVecTable(char* filename)
|
||||
DEBUG_ShowMsg("DEBUG: Interrupt vector table written to %s.", filename);
|
||||
}
|
||||
|
||||
#define DEBUG_VAR_BUF_LEN 16
|
||||
static void DrawVariables(void)
|
||||
{
|
||||
std::list<CDebugVar*>::iterator i;
|
||||
CDebugVar *dv;
|
||||
char buffer[DEBUG_VAR_BUF_LEN];
|
||||
|
||||
int idx = 0;
|
||||
for(i=CDebugVar::varList.begin(); i != CDebugVar::varList.end(); i++, idx++) {
|
||||
|
||||
if (idx == 4*3) {
|
||||
/* too many variables */
|
||||
break;
|
||||
}
|
||||
|
||||
dv = static_cast<CDebugVar*>(*i);
|
||||
|
||||
Bit16u value = mem_readw(dv->GetAdr());
|
||||
snprintf(buffer,DEBUG_VAR_BUF_LEN, "0x%04x", value);
|
||||
|
||||
int y = idx / 3;
|
||||
int x = (idx % 3) * 26;
|
||||
mvwprintw(dbg.win_var, y, x, dv->GetName());
|
||||
mvwprintw(dbg.win_var, y, (x + DEBUG_VAR_BUF_LEN + 1) , buffer);
|
||||
}
|
||||
|
||||
wrefresh(dbg.win_var);
|
||||
}
|
||||
#undef DEBUG_VAR_BUF_LEN
|
||||
// HEAVY DEBUGGING STUFF
|
||||
|
||||
#if C_HEAVY_DEBUG
|
||||
@ -1892,9 +1926,9 @@ bool DEBUG_HeavyIsBreakpoint(void)
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
#endif // HEAVY DEBUG
|
||||
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -53,7 +53,7 @@ void DEBUG_ShowMsg(char * format,...) {
|
||||
va_end(msg);
|
||||
wprintw(dbg.win_out,"%10d: %s\n",cycle_count,buf);
|
||||
wrefresh(dbg.win_out);
|
||||
if(debuglog) fprintf(debuglog,"%10d: %s\n",cycle_count,buf);
|
||||
if(debuglog) fprintf(debuglog,"%10d: %s\n",cycle_count,buf);
|
||||
}
|
||||
|
||||
void LOG::operator() (char* format, ...){
|
||||
@ -99,13 +99,15 @@ static void DrawBars(void) {
|
||||
attrset(COLOR_PAIR(PAIR_BLACK_BLUE));
|
||||
}
|
||||
/* Show the Register bar */
|
||||
mvaddstr(dbg.win_reg->_begy-1,0,"---[F1](Register Overview)---");
|
||||
mvaddstr(dbg.win_reg->_begy-1,0,"---(Register Overview)---");
|
||||
/* Show the Data Overview bar perhaps with more special stuff in the end */
|
||||
mvaddstr(dbg.win_data->_begy-1,0,"---[F2](Data Overview)---");
|
||||
mvaddstr(dbg.win_data->_begy-1,0,"---(Data Overview)---");
|
||||
/* Show the Code Overview perhaps with special stuff in bar too */
|
||||
mvaddstr(dbg.win_code->_begy-1,0,"---[F3](Code Overview)---");
|
||||
mvaddstr(dbg.win_code->_begy-1,0,"---(Code Overview)---");
|
||||
/* Show the Variable Overview bar */
|
||||
mvaddstr(dbg.win_var->_begy-1,0,"---(Variable Overview)---");
|
||||
/* Show the Output OverView */
|
||||
mvaddstr(dbg.win_out->_begy-1,0,"---[F4](OutPut/Input)---");
|
||||
mvaddstr(dbg.win_out->_begy-1,0,"---(OutPut/Input)---");
|
||||
attrset(0);
|
||||
}
|
||||
|
||||
@ -124,7 +126,10 @@ static void MakeSubWindows(void) {
|
||||
/* The Code Window */
|
||||
dbg.win_code=subwin(dbg.win_main,11,dbg.win_main->_maxx,outy,0);
|
||||
outy+=12;
|
||||
/* The output Window */
|
||||
/* The Variable Window */
|
||||
dbg.win_var=subwin(dbg.win_main,4,dbg.win_main->_maxx,outy,0);
|
||||
outy+=5;
|
||||
/* The Output Window */
|
||||
dbg.win_out=subwin(dbg.win_main,dbg.win_main->_maxy-outy-1,dbg.win_main->_maxx,outy,0);
|
||||
dbg.input_y=dbg.win_main->_maxy-1;
|
||||
scrollok(dbg.win_out,TRUE);
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
/* Local Debug Function */
|
||||
|
||||
/* $Id: debug_inc.h,v 1.8 2004/08/28 12:51:35 qbix79 Exp $ */
|
||||
|
||||
#include <curses.h>
|
||||
#include "mem.h"
|
||||
|
||||
@ -34,6 +37,7 @@ struct DBGBlock {
|
||||
WINDOW * win_reg; /* Register Window */
|
||||
WINDOW * win_data; /* Data Output window */
|
||||
WINDOW * win_code; /* Disassembly/Debug point Window */
|
||||
WINDOW * win_var; /* Variable Window */
|
||||
WINDOW * win_out; /* Text Output Window */
|
||||
Bit32u active_win; /* Current active window */
|
||||
Bit32u input_y;
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -4,6 +4,6 @@ noinst_LIBRARIES = libdos.a
|
||||
EXTRA_DIST = scsidefs.h wnaspi32.h
|
||||
libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \
|
||||
dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \
|
||||
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp \
|
||||
dev_con.h dos_mscdex.cpp \
|
||||
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp
|
||||
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
|
||||
drive_iso.cpp dev_con.h dos_mscdex.cpp \
|
||||
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp
|
||||
|
@ -135,9 +135,9 @@ noinst_LIBRARIES = libdos.a
|
||||
EXTRA_DIST = scsidefs.h wnaspi32.h
|
||||
libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \
|
||||
dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \
|
||||
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp \
|
||||
dev_con.h dos_mscdex.cpp \
|
||||
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp
|
||||
drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp drive_fat.cpp \
|
||||
drive_iso.cpp dev_con.h dos_mscdex.cpp \
|
||||
cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_image.cpp
|
||||
|
||||
subdir = src/dos
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
@ -153,9 +153,10 @@ am_libdos_a_OBJECTS = dos.$(OBJEXT) dos_devices.$(OBJEXT) \
|
||||
dos_memory.$(OBJEXT) dos_misc.$(OBJEXT) dos_classes.$(OBJEXT) \
|
||||
dos_programs.$(OBJEXT) dos_tables.$(OBJEXT) drives.$(OBJEXT) \
|
||||
drive_virtual.$(OBJEXT) drive_local.$(OBJEXT) \
|
||||
drive_cache.$(OBJEXT) dos_mscdex.$(OBJEXT) cdrom.$(OBJEXT) \
|
||||
drive_cache.$(OBJEXT) drive_fat.$(OBJEXT) drive_iso.$(OBJEXT) \
|
||||
dos_mscdex.$(OBJEXT) cdrom.$(OBJEXT) \
|
||||
cdrom_ioctl_win32.$(OBJEXT) cdrom_aspi_win32.$(OBJEXT) \
|
||||
cdrom_ioctl_linux.$(OBJEXT)
|
||||
cdrom_ioctl_linux.$(OBJEXT) cdrom_image.$(OBJEXT)
|
||||
libdos_a_OBJECTS = $(am_libdos_a_OBJECTS)
|
||||
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
|
||||
@ -163,6 +164,7 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/cdrom.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_aspi_win32.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_image.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_linux.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_win32.Po ./$(DEPDIR)/dos.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/dos_classes.Po \
|
||||
@ -172,8 +174,8 @@ am__depfiles_maybe = depfiles
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/dos_misc.Po ./$(DEPDIR)/dos_mscdex.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/dos_programs.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/dos_tables.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/drive_local.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po ./$(DEPDIR)/drive_fat.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/drive_iso.Po ./$(DEPDIR)/drive_local.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/drive_virtual.Po ./$(DEPDIR)/drives.Po
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
@ -215,6 +217,7 @@ distclean-compile:
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_aspi_win32.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_image.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_linux.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_win32.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos.Po@am__quote@
|
||||
@ -229,6 +232,8 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_programs.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_tables.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_cache.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_fat.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_iso.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_local.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_virtual.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drives.Po@am__quote@
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -21,6 +21,11 @@
|
||||
// SDL CDROM
|
||||
// ******************************************************
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include "dosbox.h"
|
||||
#include "SDL.h"
|
||||
#include "support.h"
|
||||
#include "cdrom.h"
|
||||
@ -175,8 +180,13 @@ int CDROM_GetMountType(char* path, int forceCD)
|
||||
cdName = SDL_CDName(i);
|
||||
if (strcmp(buffer,cdName)==0) return 0;
|
||||
};
|
||||
// TODO: Detect ISO
|
||||
return 2;
|
||||
|
||||
// Detect ISO
|
||||
struct stat file_stat;
|
||||
stat(path, &file_stat);
|
||||
if (S_ISREG(file_stat.st_mode)) return 1;
|
||||
|
||||
return 2;
|
||||
};
|
||||
|
||||
// ******************************************************
|
||||
|
140
src/dos/cdrom.h
140
src/dos/cdrom.h
@ -5,10 +5,17 @@
|
||||
#define MAX_ASPI_CDROM 5
|
||||
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "dosbox.h"
|
||||
#include "mem.h"
|
||||
#include "mixer.h"
|
||||
#include "SDL.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
#if defined(C_SDL_SOUND)
|
||||
#include "SDL_sound.h"
|
||||
#endif
|
||||
|
||||
#define RAW_SECTOR_SIZE 2352
|
||||
#define COOKED_SECTOR_SIZE 2048
|
||||
@ -46,26 +53,28 @@ public:
|
||||
virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0;
|
||||
|
||||
virtual bool LoadUnloadMedia (bool unload) = 0;
|
||||
|
||||
virtual void InitNewMedia (void) {};
|
||||
};
|
||||
|
||||
class CDROM_Interface_SDL : public CDROM_Interface
|
||||
{
|
||||
public:
|
||||
CDROM_Interface_SDL (void);
|
||||
~CDROM_Interface_SDL (void);
|
||||
virtual ~CDROM_Interface_SDL(void);
|
||||
|
||||
bool SetDevice (char* path, int forceCD);
|
||||
bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
|
||||
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
|
||||
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
|
||||
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
|
||||
bool GetAudioStatus (bool& playing, bool& pause);
|
||||
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
|
||||
bool PlayAudioSector (unsigned long start,unsigned long len);
|
||||
bool PauseAudio (bool resume);
|
||||
bool StopAudio (void);
|
||||
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; };
|
||||
bool LoadUnloadMedia (bool unload);
|
||||
virtual bool SetDevice (char* path, int forceCD);
|
||||
virtual bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
|
||||
virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
|
||||
virtual bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
|
||||
virtual bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
|
||||
virtual bool GetAudioStatus (bool& playing, bool& pause);
|
||||
virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
|
||||
virtual bool PlayAudioSector (unsigned long start,unsigned long len);
|
||||
virtual bool PauseAudio (bool resume);
|
||||
virtual bool StopAudio (void);
|
||||
virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; };
|
||||
virtual bool LoadUnloadMedia (bool unload);
|
||||
|
||||
private:
|
||||
bool Open (void);
|
||||
@ -93,6 +102,106 @@ public:
|
||||
bool LoadUnloadMedia (bool unload) { return true; };
|
||||
};
|
||||
|
||||
class CDROM_Interface_Image : public CDROM_Interface
|
||||
{
|
||||
private:
|
||||
class TrackFile {
|
||||
public:
|
||||
virtual bool read(Bit8u *buffer, int seek, int count) = 0;
|
||||
virtual int getLength() = 0;
|
||||
};
|
||||
|
||||
class BinaryFile : public TrackFile {
|
||||
public:
|
||||
BinaryFile(const char *filename, bool &error);
|
||||
~BinaryFile();
|
||||
bool read(Bit8u *buffer, int seek, int count);
|
||||
int getLength();
|
||||
private:
|
||||
BinaryFile();
|
||||
std::ifstream *file;
|
||||
};
|
||||
|
||||
#if defined(C_SDL_SOUND)
|
||||
class AudioFile : public TrackFile {
|
||||
public:
|
||||
AudioFile(const char *filename, bool &error);
|
||||
~AudioFile();
|
||||
bool read(Bit8u *buffer, int seek, int count);
|
||||
int getLength();
|
||||
private:
|
||||
AudioFile();
|
||||
Sound_Sample *sample;
|
||||
int lastCount;
|
||||
int lastSeek;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct Track {
|
||||
int number;
|
||||
int attr;
|
||||
int start;
|
||||
int length;
|
||||
int skip;
|
||||
int sectorSize;
|
||||
bool mode2;
|
||||
TrackFile *file;
|
||||
};
|
||||
|
||||
public:
|
||||
CDROM_Interface_Image (Bit8u subUnit);
|
||||
virtual ~CDROM_Interface_Image (void);
|
||||
void InitNewMedia (void);
|
||||
bool SetDevice (char* path, int forceCD);
|
||||
bool GetUPC (unsigned char& attr, char* upc);
|
||||
bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
|
||||
bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr);
|
||||
bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos);
|
||||
bool GetAudioStatus (bool& playing, bool& pause);
|
||||
bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen);
|
||||
bool PlayAudioSector (unsigned long start,unsigned long len);
|
||||
bool PauseAudio (bool resume);
|
||||
bool StopAudio (void);
|
||||
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num);
|
||||
bool LoadUnloadMedia (bool unload);
|
||||
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
|
||||
|
||||
static CDROM_Interface_Image* images[26];
|
||||
|
||||
private:
|
||||
// player
|
||||
static void CDAudioCallBack(Bitu len);
|
||||
int GetTrack(int sector);
|
||||
|
||||
static struct imagePlayer {
|
||||
CDROM_Interface_Image *cd;
|
||||
MixerChannel *channel;
|
||||
SDL_mutex *mutex;
|
||||
Bit8u buffer[8192];
|
||||
int bufLen;
|
||||
int currFrame;
|
||||
int targetFrame;
|
||||
bool isPlaying;
|
||||
bool isPaused;
|
||||
} player;
|
||||
|
||||
void ClearTracks();
|
||||
bool LoadIsoFile(char *filename);
|
||||
bool CanReadPVD(TrackFile *file, int sectorSize, bool mode2);
|
||||
// cue sheet processing
|
||||
bool LoadCueSheet(char *cuefile);
|
||||
bool GetRealFileName(std::string& filename, std::string& pathname);
|
||||
bool GetCueKeyword(std::string &keyword, std::istream &in);
|
||||
bool GetCueFrame(int &frames, std::istream &in);
|
||||
bool GetCueString(std::string &str, std::istream &in);
|
||||
bool AddTrack(Track &curr, int &shift, int prestart, int &totalPregap, int currPregap);
|
||||
|
||||
static int refCount;
|
||||
std::vector<Track> tracks;
|
||||
std::string mcn;
|
||||
Bit8u subUnit;
|
||||
};
|
||||
|
||||
#if defined (WIN32) /* Win 32 */
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
@ -104,7 +213,7 @@ class CDROM_Interface_Aspi : public CDROM_Interface
|
||||
{
|
||||
public:
|
||||
CDROM_Interface_Aspi (void);
|
||||
~CDROM_Interface_Aspi (void);
|
||||
virtual ~CDROM_Interface_Aspi(void);
|
||||
|
||||
bool SetDevice (char* path, int forceCD);
|
||||
|
||||
@ -151,7 +260,7 @@ class CDROM_Interface_Ioctl : public CDROM_Interface
|
||||
{
|
||||
public:
|
||||
CDROM_Interface_Ioctl (void);
|
||||
~CDROM_Interface_Ioctl (void);
|
||||
virtual ~CDROM_Interface_Ioctl(void);
|
||||
|
||||
bool SetDevice (char* path, int forceCD);
|
||||
|
||||
@ -171,6 +280,7 @@ public:
|
||||
|
||||
bool LoadUnloadMedia (bool unload);
|
||||
|
||||
void InitNewMedia (void) { Close(); Open(); };
|
||||
private:
|
||||
|
||||
bool Open (void);
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: cdrom_aspi_win32.cpp,v 1.10 2004/01/10 14:03:34 qbix79 Exp $ */
|
||||
/* $Id: cdrom_aspi_win32.cpp,v 1.12 2004/08/04 09:12:53 qbix79 Exp $ */
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
@ -39,6 +39,19 @@
|
||||
|
||||
#include "scsidefs.h"
|
||||
|
||||
// always use a buffer of the maximum struct size (like the union of all 'SRB_*' struct types)
|
||||
// Thanx SaPu
|
||||
typedef union {
|
||||
SRB_HAInquiry hainquiry;
|
||||
SRB_GDEVBlock gdevblock;
|
||||
SRB_ExecSCSICmd execscsicmd;
|
||||
SRB_Abort abort;
|
||||
SRB_BusDeviceReset busdevicereset;
|
||||
SRB_GetDiskInfo getdiskinfo;
|
||||
SRB_RescanPort rescanport;
|
||||
SRB_GetSetTimeouts getsettimeouts;
|
||||
} ASPI_SRB;
|
||||
|
||||
// *****************************************************************
|
||||
// Windows ASPI functions (should work for all WIN with ASPI layer)
|
||||
// *****************************************************************
|
||||
@ -78,34 +91,34 @@ bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize
|
||||
|
||||
BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID)
|
||||
{
|
||||
SRB_HAInquiry sh;
|
||||
SRB_GDEVBlock sd;
|
||||
ASPI_SRB sh;
|
||||
ASPI_SRB sd;
|
||||
DWORD d = pGetASPI32SupportInfo();
|
||||
int cnt = LOBYTE(LOWORD(d));
|
||||
int i,j,k,max;
|
||||
|
||||
for(i=0; i<cnt; i++) {
|
||||
memset(&sh, 0, sizeof(sh));
|
||||
sh.SRB_Cmd = SC_HA_INQUIRY;
|
||||
sh.SRB_HaId = i;
|
||||
sh.hainquiry.SRB_Cmd = SC_HA_INQUIRY;
|
||||
sh.hainquiry.SRB_HaId = i;
|
||||
pSendASPI32Command((LPSRB)&sh);
|
||||
if (sh.SRB_Status!=SS_COMP) continue;
|
||||
if (sh.hainquiry.SRB_Status!=SS_COMP) continue;
|
||||
|
||||
// Indicates the maximum number of targets the adapter supports
|
||||
// If the value is not 8 or 16, then it should be assumed max target is 8
|
||||
max = (int)sh.HA_Unique[3];
|
||||
max = (int)sh.hainquiry.HA_Unique[3];
|
||||
if ((max!=8) && (max!=16)) max = 8;
|
||||
|
||||
for(j=0; j<max; j++) {
|
||||
for(k=0; k<8; k++) {
|
||||
memset(&sd, 0, sizeof(sd));
|
||||
sd.SRB_Cmd = SC_GET_DEV_TYPE;
|
||||
sd.SRB_HaId = i;
|
||||
sd.SRB_Target = j;
|
||||
sd.SRB_Lun = k;
|
||||
sd.gdevblock.SRB_Cmd = SC_GET_DEV_TYPE;
|
||||
sd.gdevblock.SRB_HaId = i;
|
||||
sd.gdevblock.SRB_Target = j;
|
||||
sd.gdevblock.SRB_Lun = k;
|
||||
pSendASPI32Command((LPSRB)&sd);
|
||||
if (sd.SRB_Status == SS_COMP) {
|
||||
if (sd.SRB_DeviceType == DTYPE_CDROM) {
|
||||
if (sd.gdevblock.SRB_Status == SS_COMP) {
|
||||
if (sd.gdevblock.SRB_DeviceType == DTYPE_CDROM) {
|
||||
if ((target==j) && (lun==k)) {
|
||||
LOG(LOG_MISC,LOG_NORMAL)("SCSI: Getting Hardware vendor.");
|
||||
// "Hardware ID = vendor" match ?
|
||||
@ -175,23 +188,24 @@ bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase)
|
||||
|
||||
bool CDROM_Interface_Aspi::GetVendor(BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer)
|
||||
{
|
||||
SRB_ExecSCSICmd srbExec;
|
||||
ASPI_SRB srbExec;
|
||||
// SRB_ExecSCSICmd srbExec;
|
||||
memset ( &srbExec, 0, sizeof ( SRB_ExecSCSICmd ) );
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
srbExec.SRB_Cmd = SC_EXEC_SCSI_CMD ;
|
||||
srbExec.SRB_HaId = HA_num;
|
||||
srbExec.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
srbExec.SRB_Target = SCSI_Id;
|
||||
srbExec.SRB_Lun = SCSI_Lun;
|
||||
srbExec.SRB_BufLen = 36;
|
||||
srbExec.SRB_BufPointer = (unsigned char*)szBuffer;
|
||||
srbExec.SRB_SenseLen = SENSE_LEN;
|
||||
srbExec.SRB_CDBLen = 6;
|
||||
srbExec.SRB_PostProc = (LPVOID)hEvent;
|
||||
srbExec.CDBByte [ 0 ] = SCSI_INQUIRY;
|
||||
srbExec.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ]
|
||||
srbExec.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD ;
|
||||
srbExec.execscsicmd.SRB_HaId = HA_num;
|
||||
srbExec.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
srbExec.execscsicmd.SRB_Target = SCSI_Id;
|
||||
srbExec.execscsicmd.SRB_Lun = SCSI_Lun;
|
||||
srbExec.execscsicmd.SRB_BufLen = 36;
|
||||
srbExec.execscsicmd.SRB_BufPointer = (unsigned char*)szBuffer;
|
||||
srbExec.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
srbExec.execscsicmd.SRB_CDBLen = 6;
|
||||
srbExec.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
srbExec.execscsicmd.CDBByte [ 0 ] = SCSI_INQUIRY;
|
||||
srbExec.execscsicmd.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ]
|
||||
|
||||
ResetEvent(hEvent);
|
||||
int dwStatus = pSendASPI32Command ((LPSRB)&srbExec);
|
||||
@ -201,7 +215,7 @@ bool CDROM_Interface_Aspi::GetVendor(BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, c
|
||||
// LOG(LOG_MISC|LOG_ERROR,"SCSI: Pending done.");
|
||||
|
||||
CloseHandle(hEvent);
|
||||
if (srbExec.SRB_Status != SS_COMP) {
|
||||
if (srbExec.execscsicmd.SRB_Status != SS_COMP) {
|
||||
strcpy (szBuffer, "error" );
|
||||
return false;
|
||||
} else {
|
||||
@ -373,26 +387,28 @@ void CDROM_Interface_Aspi::GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * i
|
||||
|
||||
DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
// SRB_ExecSCSICmd s;
|
||||
ASPI_SRB s;
|
||||
DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_BufLen = sizeof(*toc);
|
||||
s.SRB_BufPointer = (BYTE FAR *)toc;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.SRB_CDBLen = 0x0A;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.CDBByte[0] = SCSI_READ_TOC;
|
||||
s.CDBByte[1] = 0x02; // 0x02 for MSF
|
||||
s.CDBByte[7] = 0x03;
|
||||
s.CDBByte[8] = 0x24;
|
||||
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.execscsicmd.SRB_HaId = haId;
|
||||
s.execscsicmd.SRB_Target = target;
|
||||
s.execscsicmd.SRB_Lun = lun;
|
||||
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.execscsicmd.SRB_BufLen = sizeof(*toc);
|
||||
s.execscsicmd.SRB_BufPointer = (BYTE FAR *)toc;
|
||||
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
s.execscsicmd.SRB_CDBLen = 0x0A;
|
||||
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.execscsicmd.CDBByte[0] = SCSI_READ_TOC;
|
||||
s.execscsicmd.CDBByte[1] = 0x02; // 0x02 for MSF
|
||||
s.execscsicmd.CDBByte[7] = 0x03;
|
||||
s.execscsicmd.CDBByte[8] = 0x24;
|
||||
|
||||
ResetEvent(hEvent);
|
||||
dwStatus=pSendASPI32Command((LPSRB)&s);
|
||||
@ -401,37 +417,39 @@ DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc)
|
||||
|
||||
CloseHandle(hEvent);
|
||||
|
||||
return (s.SRB_Status==SS_COMP);
|
||||
return (s.execscsicmd.SRB_Status==SS_COMP);
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
// SRB_ExecSCSICmd s;
|
||||
ASPI_SRB s;
|
||||
DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_BufLen = 0;
|
||||
s.SRB_BufPointer = 0;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.SRB_CDBLen = 12;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.execscsicmd.SRB_HaId = haId;
|
||||
s.execscsicmd.SRB_Target = target;
|
||||
s.execscsicmd.SRB_Lun = lun;
|
||||
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.execscsicmd.SRB_BufLen = 0;
|
||||
s.execscsicmd.SRB_BufPointer = 0;
|
||||
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
s.execscsicmd.SRB_CDBLen = 12;
|
||||
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = SCSI_PLAYAUD_12;
|
||||
s.CDBByte[1] = lun << 5;
|
||||
s.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF);
|
||||
s.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF);
|
||||
s.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF);
|
||||
s.CDBByte[5] = (unsigned char)((start & 0xFF));
|
||||
s.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF);
|
||||
s.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF);
|
||||
s.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF);
|
||||
s.CDBByte[9] = (unsigned char)(len & 0xFF);
|
||||
s.execscsicmd.CDBByte[0] = SCSI_PLAYAUD_12;
|
||||
s.execscsicmd.CDBByte[1] = lun << 5;
|
||||
s.execscsicmd.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF);
|
||||
s.execscsicmd.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF);
|
||||
s.execscsicmd.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF);
|
||||
s.execscsicmd.CDBByte[5] = (unsigned char)((start & 0xFF));
|
||||
s.execscsicmd.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF);
|
||||
s.execscsicmd.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF);
|
||||
s.execscsicmd.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF);
|
||||
s.execscsicmd.CDBByte[9] = (unsigned char)(len & 0xFF);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
@ -441,7 +459,7 @@ bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len
|
||||
|
||||
CloseHandle(hEvent);
|
||||
|
||||
return s.SRB_Status==SS_COMP;
|
||||
return s.execscsicmd.SRB_Status==SS_COMP;
|
||||
}
|
||||
|
||||
bool CDROM_Interface_Aspi::StopAudio(void)
|
||||
@ -451,23 +469,25 @@ bool CDROM_Interface_Aspi::StopAudio(void)
|
||||
|
||||
bool CDROM_Interface_Aspi::PauseAudio(bool resume)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
//SRB_ExecSCSICmd s;
|
||||
ASPI_SRB s;
|
||||
DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_BufLen = 0x00;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.SRB_CDBLen = 0x0A;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.CDBByte[0] = 0x4B;
|
||||
s.CDBByte[8] = (unsigned char)resume; // Pause
|
||||
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.execscsicmd.SRB_HaId = haId;
|
||||
s.execscsicmd.SRB_Target = target;
|
||||
s.execscsicmd.SRB_Lun = lun;
|
||||
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.execscsicmd.SRB_BufLen = 0x00;
|
||||
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
s.execscsicmd.SRB_CDBLen = 0x0A;
|
||||
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.execscsicmd.CDBByte[0] = 0x4B;
|
||||
s.execscsicmd.CDBByte[8] = (unsigned char)resume; // Pause
|
||||
|
||||
ResetEvent(hEvent);
|
||||
dwStatus=pSendASPI32Command((LPSRB)&s);
|
||||
@ -476,37 +496,39 @@ bool CDROM_Interface_Aspi::PauseAudio(bool resume)
|
||||
|
||||
CloseHandle(hEvent);
|
||||
|
||||
return (s.SRB_Status==SS_COMP);
|
||||
return (s.execscsicmd.SRB_Status==SS_COMP);
|
||||
};
|
||||
|
||||
bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos)
|
||||
{
|
||||
SUB_Q_CURRENT_POSITION pos;
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
// SRB_ExecSCSICmd s;
|
||||
ASPI_SRB s;
|
||||
DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.execscsicmd.SRB_HaId = haId;
|
||||
s.execscsicmd.SRB_Target = target;
|
||||
s.execscsicmd.SRB_Lun = lun;
|
||||
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = sizeof(pos);
|
||||
s.SRB_BufPointer = (BYTE FAR *)&pos;
|
||||
s.SRB_CDBLen = 10;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.execscsicmd.SRB_BufLen = sizeof(pos);
|
||||
s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&pos;
|
||||
s.execscsicmd.SRB_CDBLen = 10;
|
||||
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = SCSI_SUBCHANNEL;
|
||||
s.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.CDBByte[2] = 0x40; // subq
|
||||
s.CDBByte[3] = 0x01; // curr pos info
|
||||
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.CDBByte[7] = 0; // alloc len
|
||||
s.CDBByte[8] = sizeof(pos);
|
||||
s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
|
||||
s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.execscsicmd.CDBByte[2] = 0x40; // subq
|
||||
s.execscsicmd.CDBByte[3] = 0x01; // curr pos info
|
||||
s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.execscsicmd.CDBByte[7] = 0; // alloc len
|
||||
s.execscsicmd.CDBByte[8] = sizeof(pos);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
@ -516,7 +538,7 @@ bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track
|
||||
|
||||
CloseHandle(hEvent);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
attr = (pos.Control<<4) &0xEF;
|
||||
track = pos.TrackNumber;
|
||||
@ -534,31 +556,33 @@ bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track
|
||||
bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
|
||||
{
|
||||
SUB_Q_MEDIA_CATALOG_NUMBER upc;
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
ASPI_SRB s;
|
||||
//SRB_ExecSCSICmd s;
|
||||
DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.execscsicmd.SRB_HaId = haId;
|
||||
s.execscsicmd.SRB_Target = target;
|
||||
s.execscsicmd.SRB_Lun = lun;
|
||||
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = sizeof(upc);
|
||||
s.SRB_BufPointer = (BYTE FAR *)&upc;
|
||||
s.SRB_CDBLen = 10;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.execscsicmd.SRB_BufLen = sizeof(upc);
|
||||
s.execscsicmd.SRB_BufPointer = (BYTE FAR *)&upc;
|
||||
s.execscsicmd.SRB_CDBLen = 10;
|
||||
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = SCSI_SUBCHANNEL;
|
||||
s.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.CDBByte[2] = 0x40; // subq
|
||||
s.CDBByte[3] = 0x02; // get upc
|
||||
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.CDBByte[7] = 0; // alloc len
|
||||
s.CDBByte[8] = sizeof(upc);
|
||||
s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
|
||||
s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.execscsicmd.CDBByte[2] = 0x40; // subq
|
||||
s.execscsicmd.CDBByte[3] = 0x02; // get upc
|
||||
s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.execscsicmd.CDBByte[7] = 0; // alloc len
|
||||
s.execscsicmd.CDBByte[8] = sizeof(upc);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
@ -568,15 +592,14 @@ bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
|
||||
|
||||
CloseHandle(hEvent);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
// attr = (upc.ADR<<4) | upc.Control;
|
||||
attr = 0;
|
||||
int pos = 0;
|
||||
// Convert to mscdex format
|
||||
// for (int i=0; i<6; i++) upcdata[i] = (upc.MediaCatalog[pos++]<<4)+(upc.MediaCatalog[pos++]&0x0F);
|
||||
// upcdata[6] = (upc.MediaCatalog[pos++]<<4);
|
||||
for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i];
|
||||
for (int i=0; i<7; i++) upcdata[i] = (upc.MediaCatalog[i*2] << 4) | (upc.MediaCatalog[i*2+1] & 0x0F);
|
||||
|
||||
return true;
|
||||
};
|
||||
@ -586,31 +609,33 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
|
||||
playing = pause = false;
|
||||
|
||||
SUB_Q_HEADER sub;
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
// SRB_ExecSCSICmd s;
|
||||
ASPI_SRB s;
|
||||
DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.execscsicmd.SRB_HaId = haId;
|
||||
s.execscsicmd.SRB_Target = target;
|
||||
s.execscsicmd.SRB_Lun = lun;
|
||||
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = sizeof(sub);
|
||||
s.SRB_BufPointer = (BYTE FAR *)⊂
|
||||
s.SRB_CDBLen = 10;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.execscsicmd.SRB_BufLen = sizeof(sub);
|
||||
s.execscsicmd.SRB_BufPointer = (BYTE FAR *)⊂
|
||||
s.execscsicmd.SRB_CDBLen = 10;
|
||||
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = SCSI_SUBCHANNEL;
|
||||
s.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.CDBByte[2] = 0x00; // no subq
|
||||
s.CDBByte[3] = 0x00; // dont care
|
||||
s.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.CDBByte[7] = 0; // alloc len
|
||||
s.CDBByte[8] = sizeof(sub);
|
||||
s.execscsicmd.CDBByte[0] = SCSI_SUBCHANNEL;
|
||||
s.execscsicmd.CDBByte[1] = (lun<<5)|2; // lun & msf
|
||||
s.execscsicmd.CDBByte[2] = 0x00; // no subq
|
||||
s.execscsicmd.CDBByte[3] = 0x00; // dont care
|
||||
s.execscsicmd.CDBByte[6] = 0; // track number (only in isrc mode, ignored)
|
||||
s.execscsicmd.CDBByte[7] = 0; // alloc len
|
||||
s.execscsicmd.CDBByte[8] = sizeof(sub);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
@ -620,7 +645,7 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
|
||||
|
||||
CloseHandle(hEvent);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
playing = (sub.AudioStatus==0x11);
|
||||
pause = (sub.AudioStatus==0x12);
|
||||
@ -630,27 +655,29 @@ bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause)
|
||||
|
||||
bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
//SRB_ExecSCSICmd s;
|
||||
ASPI_SRB s;
|
||||
DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
memset(&s,0,sizeof(s));
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.execscsicmd.SRB_HaId = haId;
|
||||
s.execscsicmd.SRB_Target = target;
|
||||
s.execscsicmd.SRB_Lun = lun;
|
||||
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = 0;
|
||||
s.SRB_BufPointer = 0;
|
||||
s.SRB_CDBLen = 14;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.execscsicmd.SRB_BufLen = 0;
|
||||
s.execscsicmd.SRB_BufPointer = 0;
|
||||
s.execscsicmd.SRB_CDBLen = 6; // 14;
|
||||
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = SCSI_LOAD_UN;
|
||||
s.CDBByte[1] = (lun<<5)|1; // lun & immediate
|
||||
s.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media
|
||||
s.execscsicmd.CDBByte[0] = SCSI_LOAD_UN;
|
||||
s.execscsicmd.CDBByte[1] = (lun<<5)|1; // lun & immediate
|
||||
s.execscsicmd.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
@ -660,7 +687,7 @@ bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload)
|
||||
|
||||
CloseHandle(hEvent);
|
||||
|
||||
if (s.SRB_Status!=SS_COMP) return false;
|
||||
if (s.execscsicmd.SRB_Status!=SS_COMP) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
@ -684,7 +711,9 @@ bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaCha
|
||||
|
||||
bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num)
|
||||
{
|
||||
SRB_ExecSCSICmd s;DWORD dwStatus;
|
||||
//SRB_ExecSCSICmd s;
|
||||
ASPI_SRB s;
|
||||
DWORD dwStatus;
|
||||
|
||||
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
|
||||
@ -693,27 +722,27 @@ bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long se
|
||||
Bitu buflen = raw?2352*num:2048*num;
|
||||
Bit8u* bufdata = new Bit8u[buflen];
|
||||
|
||||
s.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.SRB_HaId = haId;
|
||||
s.SRB_Target = target;
|
||||
s.SRB_Lun = lun;
|
||||
s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.SRB_SenseLen = SENSE_LEN;
|
||||
s.execscsicmd.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
s.execscsicmd.SRB_HaId = haId;
|
||||
s.execscsicmd.SRB_Target = target;
|
||||
s.execscsicmd.SRB_Lun = lun;
|
||||
s.execscsicmd.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
s.execscsicmd.SRB_SenseLen = SENSE_LEN;
|
||||
|
||||
s.SRB_BufLen = buflen;
|
||||
s.SRB_BufPointer = (BYTE FAR*)bufdata;
|
||||
s.SRB_CDBLen = 12;
|
||||
s.SRB_PostProc = (LPVOID)hEvent;
|
||||
s.execscsicmd.SRB_BufLen = buflen;
|
||||
s.execscsicmd.SRB_BufPointer = (BYTE FAR*)bufdata;
|
||||
s.execscsicmd.SRB_CDBLen = 12;
|
||||
s.execscsicmd.SRB_PostProc = (LPVOID)hEvent;
|
||||
|
||||
s.CDBByte[0] = 0xBE;
|
||||
s.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF);
|
||||
s.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF);
|
||||
s.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF);
|
||||
s.CDBByte[5] = (unsigned char)((sector & 0xFF));
|
||||
s.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF);
|
||||
s.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF);
|
||||
s.CDBByte[8] = (unsigned char) (num & 0xFF);
|
||||
s.CDBByte[9] = (raw?0xF0:0x10);
|
||||
s.execscsicmd.CDBByte[0] = 0xBE;
|
||||
s.execscsicmd.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF);
|
||||
s.execscsicmd.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF);
|
||||
s.execscsicmd.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF);
|
||||
s.execscsicmd.CDBByte[5] = (unsigned char)((sector & 0xFF));
|
||||
s.execscsicmd.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF);
|
||||
s.execscsicmd.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF);
|
||||
s.execscsicmd.CDBByte[8] = (unsigned char) (num & 0xFF);
|
||||
s.execscsicmd.CDBByte[9] = (raw?0xF0:0x10);
|
||||
|
||||
ResetEvent(hEvent);
|
||||
|
||||
@ -728,7 +757,7 @@ bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long se
|
||||
|
||||
delete[] bufdata;
|
||||
|
||||
return (s.SRB_Status==SS_COMP);
|
||||
return (s.execscsicmd.SRB_Status==SS_COMP);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
651
src/dos/cdrom_image.cpp
Normal file
651
src/dos/cdrom_image.cpp
Normal 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();
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: cdrom_ioctl_win32.cpp,v 1.10 2004/01/10 14:03:34 qbix79 Exp $ */
|
||||
/* $Id: cdrom_ioctl_win32.cpp,v 1.11 2004/08/04 09:12:53 qbix79 Exp $ */
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: dev_con.h,v 1.16 2004/01/10 14:03:34 qbix79 Exp $ */
|
||||
/* $Id: dev_con.h,v 1.18 2004/08/26 19:41:20 qbix79 Exp $ */
|
||||
|
||||
#include "dos_inc.h"
|
||||
#include "../ints/int10.h"
|
||||
@ -31,22 +31,22 @@ public:
|
||||
bool Write(Bit8u * data,Bit16u * size);
|
||||
bool Seek(Bit32u * pos,Bit32u type);
|
||||
bool Close();
|
||||
void ClearAnsi(void);
|
||||
void ClearAnsi(void);
|
||||
Bit16u GetInformation(void);
|
||||
private:
|
||||
Bit8u cache;
|
||||
struct ansi { /* should create a constructor which fills them with the appriorate values */
|
||||
bool esc;
|
||||
bool sci;
|
||||
struct ansi { /* should create a constructor which fills them with the appriorate values */
|
||||
bool esc;
|
||||
bool sci;
|
||||
bool enabled;
|
||||
Bit8u attr;
|
||||
Bit8u data[NUMBER_ANSI_DATA];
|
||||
Bit8u numberofarg;
|
||||
Bit16u nrows;
|
||||
Bit16u ncols;
|
||||
Bit8s savecol;
|
||||
Bit8s saverow;
|
||||
} ansi;
|
||||
Bit8u attr;
|
||||
Bit8u data[NUMBER_ANSI_DATA];
|
||||
Bit8u numberofarg;
|
||||
Bit16u nrows;
|
||||
Bit16u ncols;
|
||||
Bit8s savecol;
|
||||
Bit8s saverow;
|
||||
} ansi;
|
||||
|
||||
};
|
||||
|
||||
@ -55,11 +55,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
|
||||
Bit16u count=0;
|
||||
if ((cache) && (*size)) {
|
||||
data[count++]=cache;
|
||||
if(dos.echo) {
|
||||
INT10_TeletypeOutput(cache,7);
|
||||
}
|
||||
cache=0;
|
||||
|
||||
if(dos.echo) INT10_TeletypeOutput(cache,7);
|
||||
cache=0;
|
||||
}
|
||||
while (*size>count) {
|
||||
reg_ah=0;
|
||||
@ -68,25 +65,24 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
|
||||
case 13:
|
||||
data[count++]=0x0D;
|
||||
if (*size>count) data[count++]=0x0A; // it's only expanded if there is room for it. (NO cache)
|
||||
*size=count;
|
||||
*size=count;
|
||||
reg_ax=oldax;
|
||||
if(dos.echo) {
|
||||
INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible)
|
||||
INT10_TeletypeOutput(10,7);
|
||||
}
|
||||
if(dos.echo) {
|
||||
INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible)
|
||||
INT10_TeletypeOutput(10,7);
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case 8:
|
||||
if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS
|
||||
else if(count) { //Remove data if it exists (extended keys don't go right)
|
||||
data[count--]=0;
|
||||
INT10_TeletypeOutput(8,7);
|
||||
INT10_TeletypeOutput(' ',7);
|
||||
} else {
|
||||
continue; //no data read yet so restart whileloop.
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
case 8:
|
||||
if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS
|
||||
else if(count) { //Remove data if it exists (extended keys don't go right)
|
||||
data[count--]=0;
|
||||
INT10_TeletypeOutput(8,7);
|
||||
INT10_TeletypeOutput(' ',7);
|
||||
} else {
|
||||
continue; //no data read yet so restart whileloop.
|
||||
}
|
||||
break;
|
||||
default:
|
||||
data[count++]=reg_al;
|
||||
break;
|
||||
@ -95,11 +91,10 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
|
||||
if (*size>count) data[count++]=reg_ah;
|
||||
else cache=reg_ah;
|
||||
break;
|
||||
|
||||
}
|
||||
if(dos.echo) { //what to do if *size==1 and character is BS ?????
|
||||
INT10_TeletypeOutput(reg_al,7);
|
||||
}
|
||||
}
|
||||
if(dos.echo) { //what to do if *size==1 and character is BS ?????
|
||||
INT10_TeletypeOutput(reg_al,7);
|
||||
}
|
||||
}
|
||||
*size=count;
|
||||
reg_ax=oldax;
|
||||
@ -109,243 +104,235 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
|
||||
|
||||
bool device_CON::Write(Bit8u * data,Bit16u * size) {
|
||||
Bit16u count=0;
|
||||
Bitu i;
|
||||
Bit8u col,row;
|
||||
Bitu i;
|
||||
Bit8u col,row;
|
||||
Bit8u tempdata;
|
||||
while (*size>count) {
|
||||
if (!ansi.esc){
|
||||
if(data[count]=='\033') {
|
||||
/*clear the datastructure */
|
||||
ClearAnsi();
|
||||
/* start the sequence */
|
||||
ansi.esc=true;
|
||||
count++;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
// pass attribute only if ansi is enabled
|
||||
while (*size>count) {
|
||||
if (!ansi.esc){
|
||||
if(data[count]=='\033') {
|
||||
/*clear the datastructure */
|
||||
ClearAnsi();
|
||||
/* start the sequence */
|
||||
ansi.esc=true;
|
||||
count++;
|
||||
continue;
|
||||
} else {
|
||||
/* pass attribute only if ansi is enabled */
|
||||
INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled);
|
||||
count++;
|
||||
continue;
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if(!ansi.sci){
|
||||
if(!ansi.sci){
|
||||
|
||||
switch(data[count]){
|
||||
case '[':
|
||||
ansi.sci=true;
|
||||
break;
|
||||
case '7': /* save cursor pos +attr */
|
||||
case '8': /* restore this (Wonder if this is actually used) */
|
||||
case 'D':/* scrolling DOWN*/
|
||||
case 'M':/* scrolling UP*/
|
||||
default:
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */
|
||||
ClearAnsi();
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
continue;
|
||||
|
||||
}
|
||||
/*ansi.esc and ansi.sci are true */
|
||||
switch(data[count]){
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
ansi.data[ansi.numberofarg]=10*ansi.data[ansi.numberofarg]+(data[count]-'0');
|
||||
break;
|
||||
case ';': /* till a max of NUMBER_ANSI_DATA */
|
||||
ansi.numberofarg++;
|
||||
break;
|
||||
case 'm': /* SGR */
|
||||
for(i=0;i<=ansi.numberofarg;i++){
|
||||
switch(data[count]){
|
||||
case '[':
|
||||
ansi.sci=true;
|
||||
break;
|
||||
case '7': /* save cursor pos +attr */
|
||||
case '8': /* restore this (Wonder if this is actually used) */
|
||||
case 'D':/* scrolling DOWN*/
|
||||
case 'M':/* scrolling UP*/
|
||||
default:
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */
|
||||
ClearAnsi();
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
/*ansi.esc and ansi.sci are true */
|
||||
switch(data[count]){
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
ansi.data[ansi.numberofarg]=10*ansi.data[ansi.numberofarg]+(data[count]-'0');
|
||||
break;
|
||||
case ';': /* till a max of NUMBER_ANSI_DATA */
|
||||
ansi.numberofarg++;
|
||||
break;
|
||||
case 'm': /* SGR */
|
||||
for(i=0;i<=ansi.numberofarg;i++){
|
||||
ansi.enabled=true;
|
||||
switch(ansi.data[i]){
|
||||
case 0: /* normal */
|
||||
ansi.attr=0x7;
|
||||
switch(ansi.data[i]){
|
||||
case 0: /* normal */
|
||||
ansi.attr=0x07;//Real ansi does this as well. (should do current defaults)
|
||||
ansi.enabled=false;
|
||||
break;
|
||||
case 1: /* bold mode on*/
|
||||
ansi.attr|=0x8;
|
||||
break;
|
||||
case 4: /* underline */
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet");
|
||||
break;
|
||||
case 5: /* blinking */
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for blinking yet");
|
||||
break;
|
||||
case 7: /* reverse */
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for reverse yet");
|
||||
break;
|
||||
case 30: /* fg color black */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x0;
|
||||
break;
|
||||
case 31: /* fg color red */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x4;
|
||||
break;
|
||||
case 32: /* fg color green */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x2;
|
||||
break;
|
||||
case 33: /* fg color yellow */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x6;
|
||||
break;
|
||||
case 34: /* fg color blue */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x1;
|
||||
break;
|
||||
case 35: /* fg color magenta */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x5;
|
||||
break;
|
||||
case 36: /* fg color cyan */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x3;
|
||||
break;
|
||||
case 37: /* fg color white */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x7;
|
||||
break;
|
||||
case 40:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x0;
|
||||
break;
|
||||
case 41:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x40;
|
||||
break;
|
||||
case 42:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x20;
|
||||
break;
|
||||
case 43:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x60;
|
||||
break;
|
||||
case 44:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x10;
|
||||
break;
|
||||
case 45:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x50;
|
||||
break;
|
||||
case 46:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x30;
|
||||
break;
|
||||
case 47:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x70;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
case 1: /* bold mode on*/
|
||||
ansi.attr|=0x08;
|
||||
break;
|
||||
case 4: /* underline */
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet");
|
||||
break;
|
||||
case 5: /* blinking */
|
||||
ansi.attr|=0x80;
|
||||
break;
|
||||
case 7: /* reverse */
|
||||
ansi.attr=0x70;//Just like real ansi. (should do use current colors reversed)
|
||||
break;
|
||||
case 30: /* fg color black */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x0;
|
||||
break;
|
||||
case 31: /* fg color red */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x4;
|
||||
break;
|
||||
case 32: /* fg color green */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x2;
|
||||
break;
|
||||
case 33: /* fg color yellow */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x6;
|
||||
break;
|
||||
case 34: /* fg color blue */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x1;
|
||||
break;
|
||||
case 35: /* fg color magenta */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x5;
|
||||
break;
|
||||
case 36: /* fg color cyan */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x3;
|
||||
break;
|
||||
case 37: /* fg color white */
|
||||
ansi.attr&=0xf8;
|
||||
ansi.attr|=0x7;
|
||||
break;
|
||||
case 40:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x0;
|
||||
break;
|
||||
case 41:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x40;
|
||||
break;
|
||||
case 42:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x20;
|
||||
break;
|
||||
case 43:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x60;
|
||||
break;
|
||||
case 44:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x10;
|
||||
break;
|
||||
case 45:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x50;
|
||||
break;
|
||||
case 46:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x30;
|
||||
break;
|
||||
case 47:
|
||||
ansi.attr&=0x8f;
|
||||
ansi.attr|=0x70;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'f':
|
||||
case 'H':/* Cursor Pos*/
|
||||
if(ansi.data[0]==0) ansi.data[0]=1;
|
||||
if(ansi.data[1]==0) ansi.data[1]=1;
|
||||
INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),0); /*ansi=1 based, int10 is 0 based */
|
||||
ClearAnsi();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'f':
|
||||
case 'H':/* Cursor Pos*/
|
||||
if(ansi.data[0]==0) ansi.data[0]=1;
|
||||
if(ansi.data[1]==0) ansi.data[1]=1;
|
||||
INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),0); /*ansi=1 based, int10 is 0 based */
|
||||
ClearAnsi();
|
||||
break;
|
||||
/* cursor up down and forward and backward only change the row or the col not both */
|
||||
case 'A': /* cursor up*/
|
||||
col=CURSOR_POS_COL(0) ;
|
||||
row=CURSOR_POS_ROW(0) ;
|
||||
case 'A': /* cursor up*/
|
||||
col=CURSOR_POS_COL(0) ;
|
||||
row=CURSOR_POS_ROW(0) ;
|
||||
tempdata = (ansi.data[0]? ansi.data[0] : 1);
|
||||
if(tempdata > row)
|
||||
{ row=0; }
|
||||
else
|
||||
{ row-=tempdata;}
|
||||
if(tempdata > row) { row=0; }
|
||||
else { row-=tempdata;}
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'B': /*cursor Down */
|
||||
col=CURSOR_POS_COL(0) ;
|
||||
row=CURSOR_POS_ROW(0) ;
|
||||
row=CURSOR_POS_ROW(0) ;
|
||||
tempdata = (ansi.data[0]? ansi.data[0] : 1);
|
||||
if(tempdata + static_cast<Bitu>(row) >= ansi.nrows)
|
||||
{ row = ansi.nrows - 1;}
|
||||
else
|
||||
{ row += tempdata; }
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
{ row = ansi.nrows - 1;}
|
||||
else { row += tempdata; }
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'C': /*cursor forward */
|
||||
col=CURSOR_POS_COL(0);
|
||||
case 'C': /*cursor forward */
|
||||
col=CURSOR_POS_COL(0);
|
||||
row=CURSOR_POS_ROW(0);
|
||||
tempdata=(ansi.data[0]? ansi.data[0] : 1);
|
||||
if(tempdata + static_cast<Bitu>(col) >= ansi.ncols)
|
||||
{ col = ansi.ncols - 1;}
|
||||
else
|
||||
{ col += tempdata;}
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'D': /*Cursor Backward */
|
||||
col=CURSOR_POS_COL(0);
|
||||
row=CURSOR_POS_ROW(0);
|
||||
tempdata=(ansi.data[0]? ansi.data[0] : 1);
|
||||
if(tempdata > col)
|
||||
{col = 0;}
|
||||
else
|
||||
{ col -= tempdata;}
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'J': /*erase screen and move cursor home*/
|
||||
if(ansi.data[0]==0) ansi.data[0]=2;
|
||||
if(ansi.data[0]!=2) {/* only number 2 (the standard one supported) */
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported",ansi.data[0]);
|
||||
break;
|
||||
}
|
||||
for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
|
||||
ClearAnsi();
|
||||
INT10_SetCursorPos(0,0,0);
|
||||
break;
|
||||
case 'h': /* set MODE (if code =7 enable linewrap) */
|
||||
case 'I': /*RESET MODE */
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: set/reset mode called(not supported)");
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'u': /* Restore Cursor Pos */
|
||||
INT10_SetCursorPos(ansi.saverow,ansi.savecol,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 's': /* SAVE CURSOR POS */
|
||||
ansi.savecol=CURSOR_POS_COL(0);
|
||||
ansi.saverow=CURSOR_POS_ROW(0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'K':/* erase till end of line */
|
||||
for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
|
||||
ClearAnsi(); /* maybe set cursor back to starting place ???? */
|
||||
if(tempdata + static_cast<Bitu>(col) >= ansi.ncols)
|
||||
{ col = ansi.ncols - 1;}
|
||||
else { col += tempdata;}
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'l':/* (if code =7) disable linewrap */
|
||||
case 'p':/* reassign keys (needs strings) */
|
||||
case 'i':/* printer stuff */
|
||||
default:
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unhandled char %c in esc[",data[count]);
|
||||
ClearAnsi();
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
case 'D': /*Cursor Backward */
|
||||
col=CURSOR_POS_COL(0);
|
||||
row=CURSOR_POS_ROW(0);
|
||||
tempdata=(ansi.data[0]? ansi.data[0] : 1);
|
||||
if(tempdata > col) {col = 0;}
|
||||
else { col -= tempdata;}
|
||||
INT10_SetCursorPos(row,col,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'J': /*erase screen and move cursor home*/
|
||||
if(ansi.data[0]==0) ansi.data[0]=2;
|
||||
if(ansi.data[0]!=2) {/* only number 2 (the standard one supported) */
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported",ansi.data[0]);
|
||||
break;
|
||||
}
|
||||
for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
|
||||
ClearAnsi();
|
||||
INT10_SetCursorPos(0,0,0);
|
||||
break;
|
||||
case 'h': /* set MODE (if code =7 enable linewrap) */
|
||||
case 'I': /*RESET MODE */
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: set/reset mode called(not supported)");
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'u': /* Restore Cursor Pos */
|
||||
INT10_SetCursorPos(ansi.saverow,ansi.savecol,0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 's': /* SAVE CURSOR POS */
|
||||
ansi.savecol=CURSOR_POS_COL(0);
|
||||
ansi.saverow=CURSOR_POS_ROW(0);
|
||||
ClearAnsi();
|
||||
break;
|
||||
case 'K':/* erase till end of line */
|
||||
for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true);
|
||||
ClearAnsi(); /* maybe set cursor back to starting place ???? */
|
||||
break;
|
||||
case 'l':/* (if code =7) disable linewrap */
|
||||
case 'p':/* reassign keys (needs strings) */
|
||||
case 'i':/* printer stuff */
|
||||
default:
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unhandled char %c in esc[",data[count]);
|
||||
ClearAnsi();
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
*size=count;
|
||||
return true;
|
||||
@ -372,22 +359,18 @@ Bit16u device_CON::GetInformation(void) {
|
||||
device_CON::device_CON() {
|
||||
name="CON";
|
||||
cache=0;
|
||||
ansi.esc=false;
|
||||
ansi.sci=false;
|
||||
ansi.enabled=false;
|
||||
ansi.attr=0x7;
|
||||
ansi.numberofarg=0;
|
||||
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
|
||||
ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented
|
||||
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
|
||||
ansi.saverow=0;
|
||||
ansi.savecol=0;
|
||||
ansi.attr=0x7;
|
||||
ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented
|
||||
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
|
||||
ansi.saverow=0;
|
||||
ansi.savecol=0;
|
||||
ClearAnsi();
|
||||
}
|
||||
|
||||
void device_CON::ClearAnsi(void){
|
||||
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
|
||||
ansi.esc=false;
|
||||
ansi.sci=false;
|
||||
ansi.numberofarg=0;
|
||||
for(Bit8u i=0; i<NUMBER_ANSI_DATA;i++) ansi.data[i]=0;
|
||||
ansi.esc=false;
|
||||
ansi.sci=false;
|
||||
ansi.numberofarg=0;
|
||||
}
|
||||
|
199
src/dos/dos.cpp
199
src/dos/dos.cpp
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: dos.cpp,v 1.65 2004/02/02 11:38:44 qbix79 Exp $ */
|
||||
/* $Id: dos.cpp,v 1.75 2004/09/21 20:04:55 qbix79 Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -45,20 +45,20 @@ void DOS_SetError(Bit16u code) {
|
||||
#define DOSNAMEBUF 256
|
||||
static Bitu DOS_21Handler(void) {
|
||||
if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) {
|
||||
DOS_PSP psp(dos.psp);
|
||||
psp.SetStack(RealMake(SegValue(ss),reg_sp-20));
|
||||
DOS_PSP psp(dos.psp());
|
||||
psp.SetStack(RealMake(SegValue(ss),reg_sp-18));
|
||||
}
|
||||
|
||||
char name1[DOSNAMEBUF+1];
|
||||
char name2[DOSNAMEBUF+1];
|
||||
switch (reg_ah) {
|
||||
case 0x01: /* Read character from STDIN, with echo */
|
||||
{
|
||||
Bit8u c;Bit16u n=1;
|
||||
dos.echo=true;
|
||||
dos.echo=true;
|
||||
DOS_ReadFile(STDIN,&c,&n);
|
||||
reg_al=c;
|
||||
dos.echo=false;
|
||||
|
||||
dos.echo=false;
|
||||
}
|
||||
break;
|
||||
case 0x02: /* Write character to STDOUT */
|
||||
@ -181,7 +181,7 @@ static Bitu DOS_21Handler(void) {
|
||||
break;
|
||||
case 0x10: /* Close File using FCB */
|
||||
if(DOS_FCBClose(SegValue(ds),reg_dx)){
|
||||
reg_al=0;
|
||||
reg_al=0;
|
||||
}else{
|
||||
reg_al=0xff;
|
||||
}
|
||||
@ -189,7 +189,7 @@ static Bitu DOS_21Handler(void) {
|
||||
break;
|
||||
case 0x11: /* Find First Matching File using FCB */
|
||||
if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){
|
||||
reg_al=0;
|
||||
reg_al=0;
|
||||
}else{
|
||||
reg_al=0xff;
|
||||
}
|
||||
@ -197,7 +197,7 @@ static Bitu DOS_21Handler(void) {
|
||||
break;
|
||||
case 0x12: /* Find Next Matching File using FCB */
|
||||
if(DOS_FCBFindNext(SegValue(ds),reg_dx)){
|
||||
reg_al=0;
|
||||
reg_al=0;
|
||||
}else{
|
||||
reg_al=0xff;
|
||||
}
|
||||
@ -254,29 +254,26 @@ static Bitu DOS_21Handler(void) {
|
||||
LOG(LOG_FCB,LOG_NORMAL)("DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al);
|
||||
break;
|
||||
case 0x29: /* Parse filename into FCB */
|
||||
{ Bit8u difference;
|
||||
char string[1024];
|
||||
MEM_StrCopy(SegPhys(ds)+reg_si,string,1024);
|
||||
reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference);
|
||||
reg_si+=difference;
|
||||
}
|
||||
{
|
||||
Bit8u difference;
|
||||
char string[1024];
|
||||
MEM_StrCopy(SegPhys(ds)+reg_si,string,1024);
|
||||
reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference);
|
||||
reg_si+=difference;
|
||||
}
|
||||
LOG(LOG_FCB,LOG_NORMAL)("DOS:29:FCB Parse Filename, result:al=%d",reg_al);
|
||||
break;
|
||||
break;
|
||||
case 0x19: /* Get current default drive */
|
||||
reg_al=DOS_GetDefaultDrive();
|
||||
break;
|
||||
case 0x1a: /* Set Disk Transfer Area Address */
|
||||
{
|
||||
dos.dta=RealMakeSeg(ds,reg_dx);
|
||||
DOS_PSP psp(dos.psp);
|
||||
psp.SetDTA(dos.dta);
|
||||
}
|
||||
dos.dta(RealMakeSeg(ds,reg_dx));
|
||||
break;
|
||||
case 0x25: /* Set Interrupt Vector */
|
||||
RealSetVec(reg_al,RealMakeSeg(ds,reg_dx));
|
||||
break;
|
||||
case 0x26: /* Create new PSP */
|
||||
DOS_NewPSP(reg_dx,DOS_PSP(dos.psp).GetSize());
|
||||
DOS_NewPSP(reg_dx,DOS_PSP(dos.psp()).GetSize());
|
||||
break;
|
||||
case 0x2a: /* Get System Date */
|
||||
{
|
||||
@ -319,29 +316,43 @@ static Bitu DOS_21Handler(void) {
|
||||
dos.verify=(reg_al==1);
|
||||
break;
|
||||
case 0x2f: /* Get Disk Transfer Area */
|
||||
SegSet16(es,RealSeg(dos.dta));
|
||||
reg_bx=RealOff(dos.dta);
|
||||
SegSet16(es,RealSeg(dos.dta()));
|
||||
reg_bx=RealOff(dos.dta());
|
||||
break;
|
||||
case 0x30: /* Get DOS Version */
|
||||
if (reg_al==0) reg_bh=0xFF; /* Fake Microsoft DOS */
|
||||
if (reg_al==1) reg_bh=0x10; /* DOS is in HMA */
|
||||
reg_al=dos.version.major;
|
||||
reg_ah=dos.version.minor;
|
||||
/* Serialnumber */
|
||||
reg_bl=0x00;
|
||||
reg_cx=0x0000;
|
||||
break;
|
||||
case 0x31: /* Terminate and stay resident */
|
||||
//TODO First get normal files executing
|
||||
// Important: This service does not set the carry flag!
|
||||
DOS_ResizeMemory(dos.psp,®_dx);
|
||||
DOS_ResizeMemory(dos.psp(),®_dx);
|
||||
DOS_Terminate(true);
|
||||
dos.return_code=reg_al;
|
||||
dos.return_code=reg_al; //Officially a field in the SDA
|
||||
dos.return_mode=RETURN_TSR;
|
||||
break;
|
||||
case 0x32: /* Get drive parameter block for specific drive */
|
||||
{ /* Officially a dpb should be returned as well. The disk detection part is implemented */
|
||||
Bitu drive=reg_dl;if(!drive) drive=dos.current_drive;else drive--;
|
||||
if(Drives[drive]) {
|
||||
reg_al=0x00;
|
||||
LOG(LOG_DOSMISC,LOG_ERROR)("Get drive parameter block.");
|
||||
} else {
|
||||
reg_al=0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x33: /* Extended Break Checking */
|
||||
switch (reg_al) {
|
||||
case 0:reg_dl=dos.breakcheck;break; /* Get the breakcheck flag */
|
||||
case 1:dos.breakcheck=(reg_dl>0);break; /* Set the breakcheck flag */
|
||||
case 2:{bool old=dos.breakcheck;dos.breakcheck=(reg_dl>0);reg_dl=old;}break;
|
||||
case 5:reg_dl=3;break; /* Always boot from c: :) */
|
||||
case 5:reg_dl=3;break;//TODO should be z /* Always boot from c: :) */
|
||||
case 6: /* Get true version number */
|
||||
reg_bl=dos.version.major;
|
||||
reg_bh=dos.version.minor;
|
||||
@ -353,8 +364,8 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
break;
|
||||
case 0x34: /* Get INDos Flag */
|
||||
SegSet16(es,RealSeg(dos.tables.indosflag));
|
||||
reg_bx=RealOff(dos.tables.indosflag);
|
||||
SegSet16(es,DOS_SDA_SEG);
|
||||
reg_bx=DOS_SDA_OFS + 0x01;
|
||||
break;
|
||||
case 0x35: /* Get interrupt vector */
|
||||
reg_bx=real_readw(0,((Bit16u)reg_al)*4);
|
||||
@ -363,8 +374,8 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x36: /* Get Free Disk Space */
|
||||
{
|
||||
Bit16u bytes,clusters,free;
|
||||
Bit8u sectors;
|
||||
if (DOS_GetFreeDiskSpace(reg_dl,&bytes,§ors,&clusters,&free)) {
|
||||
Bit8u sectors;
|
||||
if(DOS_GetFreeDiskSpace(reg_dl,&bytes,§ors,&clusters,&free)) {
|
||||
reg_ax=sectors;
|
||||
reg_bx=free;
|
||||
reg_cx=bytes;
|
||||
@ -466,7 +477,7 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x3f: /* READ Read from file or device */
|
||||
{
|
||||
Bit16u toread=reg_cx;
|
||||
dos.echo=true;
|
||||
dos.echo=true;
|
||||
if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) {
|
||||
MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread);
|
||||
reg_ax=toread;
|
||||
@ -475,7 +486,7 @@ static Bitu DOS_21Handler(void) {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
dos.echo=false;
|
||||
dos.echo=false;
|
||||
break;
|
||||
}
|
||||
case 0x40: /* WRITE Write to file or device */
|
||||
@ -621,7 +632,7 @@ static Bitu DOS_21Handler(void) {
|
||||
break;
|
||||
//TODO Check for use of execution state AL=5
|
||||
case 0x00:
|
||||
reg_ax=0x4c00; /* Terminate Program */
|
||||
reg_ax=0x4c00; /* Terminate Program */
|
||||
case 0x4c: /* EXIT Terminate with return code */
|
||||
|
||||
{
|
||||
@ -634,7 +645,7 @@ static Bitu DOS_21Handler(void) {
|
||||
break;
|
||||
}
|
||||
case 0x4d: /* Get Return code */
|
||||
reg_al=dos.return_code;
|
||||
reg_al=dos.return_code;/* Officially read from SDA and clear when read */
|
||||
reg_ah=dos.return_mode;
|
||||
break;
|
||||
case 0x4e: /* FINDFIRST Find first matching file */
|
||||
@ -650,17 +661,18 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x4f: /* FINDNEXT Find next matching file */
|
||||
if (DOS_FindNext()) {
|
||||
CALLBACK_SCF(false);
|
||||
reg_ax=0xffff; /* Undocumented */
|
||||
/* reg_ax=0xffff;*/ /* Undocumented */
|
||||
reg_ax=0; /* Undocumented:Qbix Willy beamish */
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
};
|
||||
break;
|
||||
case 0x50: /* Set current PSP */
|
||||
dos.psp=reg_bx;
|
||||
dos.psp(reg_bx);
|
||||
break;
|
||||
case 0x51: /* Get current PSP */
|
||||
reg_bx=dos.psp;
|
||||
reg_bx=dos.psp();
|
||||
break;
|
||||
case 0x52: { /* Get list of lists */
|
||||
RealPt addr=dos_infoblock.GetPointer();
|
||||
@ -671,14 +683,14 @@ static Bitu DOS_21Handler(void) {
|
||||
//TODO Think hard how shit this is gonna be
|
||||
//And will any game ever use this :)
|
||||
case 0x53: /* Translate BIOS parameter block to drive parameter block */
|
||||
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
|
||||
break;
|
||||
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
|
||||
break;
|
||||
case 0x54: /* Get verify flag */
|
||||
reg_al=dos.verify?1:0;
|
||||
reg_al=dos.verify?1:0;
|
||||
break;
|
||||
case 0x55: /* Create Child PSP*/
|
||||
DOS_ChildPSP(reg_dx,reg_si);
|
||||
dos.psp = reg_dx;
|
||||
dos.psp(reg_dx);
|
||||
break;
|
||||
case 0x56: /* RENAME Rename file */
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
@ -736,6 +748,7 @@ static Bitu DOS_21Handler(void) {
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
if (DOS_CreateTempFile(name1,&handle)) {
|
||||
reg_ax=handle;
|
||||
MEM_BlockWrite(SegPhys(ds)+reg_dx,name1,strlen(name1)+1);
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
@ -763,6 +776,19 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x5d: /* Network Functions */
|
||||
if(reg_al == 0x06) {
|
||||
SegSet16(ds,DOS_SDA_SEG);
|
||||
reg_si = DOS_SDA_OFS;
|
||||
reg_cx = 0x80; // swap if in dos
|
||||
reg_dx = 0x1a; // swap always
|
||||
LOG(LOG_DOSMISC,LOG_ERROR)("Get SDA, Let's hope for the best!");
|
||||
}
|
||||
break;
|
||||
case 0x5f: /* Network redirection */
|
||||
reg_ax=0x0001; //Failing it
|
||||
CALLBACK_SCF(true);
|
||||
break;
|
||||
case 0x60: /* Canonicalize filename or path */
|
||||
MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF);
|
||||
if (DOS_Canonicalize(name1,name2)) {
|
||||
@ -774,7 +800,15 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
break;
|
||||
case 0x62: /* Get Current PSP Address */
|
||||
reg_bx=dos.psp;
|
||||
reg_bx=dos.psp();
|
||||
break;
|
||||
case 0x63: /* DOUBLE BYTE CHARACTER SET */
|
||||
if(reg_al == 0) {
|
||||
SegSet16(ds,RealSeg(dos.tables.dcbs));
|
||||
reg_si=RealOff(dos.tables.dcbs);
|
||||
reg_al = 0;
|
||||
CALLBACK_SCF(false); //undocumented
|
||||
} else reg_al = 0xff; //Doesn't officially touch carry flag
|
||||
break;
|
||||
case 0x64: /* Set device driver lookahead flag */
|
||||
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
|
||||
@ -787,10 +821,23 @@ static Bitu DOS_21Handler(void) {
|
||||
switch (reg_al) {
|
||||
case 1:
|
||||
mem_writeb(data,reg_al);
|
||||
mem_writew(data+1,4);
|
||||
mem_writew(data+3,1);
|
||||
mem_writew(data+5,37);
|
||||
reg_cx=4;
|
||||
mem_writew(data+0x01,0x1c);
|
||||
mem_writew(data+0x03,1);
|
||||
mem_writew(data+0x05,0x01b5);
|
||||
mem_writew(data+0x07,0x0000); // date format
|
||||
mem_writeb(data+0x08,0x24); // currency symbol
|
||||
mem_writew(data+0x0a,0x0000);
|
||||
mem_writew(data+0x0c,0x0000);
|
||||
mem_writew(data+0x0e,0x002c); // thousands separator
|
||||
mem_writew(data+0x10,0x002e); // decimal separator
|
||||
mem_writew(data+0x12,0x002d); // date separator
|
||||
mem_writew(data+0x14,0x003a); // time separator
|
||||
mem_writeb(data+0x16,0x00); // currency format
|
||||
mem_writeb(data+0x17,0x02); // digits after decimal in currency
|
||||
mem_writeb(data+0x18,0x00); // time format
|
||||
mem_writed(data+0x19,CALLBACK_RealPointer(call_casemap));
|
||||
mem_writew(data+0x1d,0x002c); // list separator
|
||||
reg_cx=0x1f;
|
||||
CALLBACK_SCF(false);
|
||||
break;
|
||||
case 2: // Get pointer to uppercase table
|
||||
@ -799,9 +846,9 @@ static Bitu DOS_21Handler(void) {
|
||||
case 5: // Get pointer to filename terminator table
|
||||
case 6: // Get pointer to collating sequence table
|
||||
case 7: // Get pointer to double byte char set table
|
||||
mem_writew(data ,0x0000); // We dont have this table...
|
||||
mem_writew(data+2,0x0000); // End of table
|
||||
reg_cx=4;
|
||||
mem_writeb(data,reg_al);
|
||||
mem_writed(data+1,dos.tables.dcbs); //used to be 0
|
||||
reg_cx=5;
|
||||
CALLBACK_SCF(false);
|
||||
break;
|
||||
default:
|
||||
@ -821,7 +868,7 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x67: /* Set handle count */
|
||||
/* Weird call to increase amount of file handles needs to allocate memory if >20 */
|
||||
{
|
||||
DOS_PSP psp(dos.psp);
|
||||
DOS_PSP psp(dos.psp());
|
||||
psp.SetNumFiles(reg_bx);
|
||||
CALLBACK_SCF(false);
|
||||
break;
|
||||
@ -854,8 +901,8 @@ static Bitu DOS_21Handler(void) {
|
||||
CALLBACK_SCF(true);
|
||||
LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al);
|
||||
break;
|
||||
|
||||
case 0x68: /* FFLUSH Commit file */
|
||||
case 0x63: /* Weirdo double byte stuff (fails but say it succeeded) available only in MSDOS 2.25 */
|
||||
CALLBACK_SCF(false); //mirek
|
||||
case 0xE0:
|
||||
case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */
|
||||
@ -865,13 +912,10 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x6b: /* NULL Function */
|
||||
case 0x61: /* UNUSED */
|
||||
case 0xEF: /* Used in Ancient Art Of War CGA */
|
||||
case 0x5d: /* Network Functions ||HMMM seems to critical error info and return 1!! Maybe implement it.??*/
|
||||
/* al=06 clears cf and leaves al=6 and returns crit error flag location*/
|
||||
case 0x1f: /* Get drive parameter block for default drive */
|
||||
case 0x32: /* Get drive parameter block for specific drive */
|
||||
|
||||
case 0x5c: /* FLOCK File region locking */
|
||||
case 0x5e: /* More Network Functions */
|
||||
case 0x5f: /* And Even More Network Functions */
|
||||
default:
|
||||
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al);
|
||||
reg_al=0x00; /* default value */
|
||||
@ -894,7 +938,7 @@ static Bitu DOS_27Handler(void)
|
||||
{
|
||||
// Terminate & stay resident
|
||||
Bit16u para = (reg_dx/16)+((reg_dx % 16)>0);
|
||||
if (DOS_ResizeMemory(dos.psp,¶)) DOS_Terminate(true);
|
||||
if (DOS_ResizeMemory(dos.psp(),¶)) DOS_Terminate(true);
|
||||
return CBRET_NONE;
|
||||
}
|
||||
static Bitu DOS_25Handler(void) {
|
||||
@ -903,9 +947,10 @@ static Bitu DOS_25Handler(void) {
|
||||
SETFLAGBIT(CF,true);
|
||||
}else{
|
||||
SETFLAGBIT(CF,false);
|
||||
reg_ax=0;
|
||||
if((reg_cx != 1) ||(reg_dx != 1))
|
||||
LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as diskdetection");
|
||||
LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as diskdetection drive %X",reg_al);
|
||||
|
||||
reg_ax=0;
|
||||
}
|
||||
return CBRET_NONE;
|
||||
}
|
||||
@ -925,8 +970,14 @@ static Bitu DOS_28Handler(void) {
|
||||
}
|
||||
|
||||
static Bitu DOS_29Handler(void) {
|
||||
LOG(LOG_DOSMISC,LOG_ERROR)("int 29 called");
|
||||
return CBRET_NONE;
|
||||
static bool int29warn=false;
|
||||
if(!int29warn) {
|
||||
LOG(LOG_DOSMISC,LOG_WARN)("Int 29 called. Redirecting to int 10:0x0e");
|
||||
int29warn=true;
|
||||
}
|
||||
reg_ah=0x0e;
|
||||
CALLBACK_RunRealInt(0x10);
|
||||
return CBRET_NONE;
|
||||
}
|
||||
|
||||
static Bitu DOS_CaseMapFunc(void) {
|
||||
@ -942,32 +993,32 @@ void DOS_ShutDown(Section* sec)
|
||||
|
||||
void DOS_Init(Section* sec) {
|
||||
call_20=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET);
|
||||
CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET,"DOS Int 20");
|
||||
RealSetVec(0x20,CALLBACK_RealPointer(call_20));
|
||||
|
||||
call_21=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET_STI);
|
||||
CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET_STI,"DOS Int 21");
|
||||
RealSetVec(0x21,CALLBACK_RealPointer(call_21));
|
||||
|
||||
call_25=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_25,DOS_25Handler,CB_RETF);
|
||||
CALLBACK_Setup(call_25,DOS_25Handler,CB_RETF,"DOS Int 25");
|
||||
RealSetVec(0x25,CALLBACK_RealPointer(call_25));
|
||||
|
||||
call_26=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_26,DOS_26Handler,CB_RETF);
|
||||
CALLBACK_Setup(call_26,DOS_26Handler,CB_RETF,"DOS Int 26");
|
||||
RealSetVec(0x26,CALLBACK_RealPointer(call_26));
|
||||
|
||||
call_27=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_27,DOS_27Handler,CB_IRET);
|
||||
CALLBACK_Setup(call_27,DOS_27Handler,CB_IRET,"DOS Int 27");
|
||||
RealSetVec(0x27,CALLBACK_RealPointer(call_27));
|
||||
|
||||
call_28=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_28,DOS_28Handler,CB_IRET);
|
||||
RealSetVec(0x28,CALLBACK_RealPointer(call_28));
|
||||
call_28=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_28,DOS_28Handler,CB_IRET,"DOS Int 28");
|
||||
RealSetVec(0x28,CALLBACK_RealPointer(call_28));
|
||||
|
||||
call_29=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_29,DOS_29Handler,CB_IRET);
|
||||
RealSetVec(0x29,CALLBACK_RealPointer(call_29));
|
||||
call_29=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_29,DOS_29Handler,CB_IRET,"CON Output Int 29");
|
||||
RealSetVec(0x29,CALLBACK_RealPointer(call_29));
|
||||
|
||||
DOS_SetupFiles(); /* Setup system File tables */
|
||||
DOS_SetupDevices(); /* Setup dos devices */
|
||||
@ -995,6 +1046,6 @@ void DOS_Init(Section* sec) {
|
||||
|
||||
/* case map routine INT 0x21 0x38 */
|
||||
call_casemap = CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_casemap,DOS_CaseMapFunc,CB_RETF);
|
||||
CALLBACK_Setup(call_casemap,DOS_CaseMapFunc,CB_RETF,"DOS CaseMap");
|
||||
}
|
||||
|
||||
|
@ -9,14 +9,14 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: dos_classes.cpp,v 1.33 2004/01/10 14:03:34 qbix79 Exp $ */
|
||||
/* $Id: dos_classes.cpp,v 1.41 2004/08/04 09:12:53 qbix79 Exp $ */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -64,11 +64,45 @@ void DOS_InfoBlock::SetLocation(Bit16u segment)
|
||||
pt=PhysMake(seg,0);
|
||||
/* Clear the initual Block */
|
||||
for(Bitu i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff);
|
||||
|
||||
sSave(sDIB,regCXfrom5e,(Bit16u)0);
|
||||
sSave(sDIB,countLRUcache,(Bit16u)0);
|
||||
sSave(sDIB,countLRUopens,(Bit16u)0);
|
||||
|
||||
sSave(sDIB,protFCBs,(Bit16u)0);
|
||||
sSave(sDIB,specialCodeSeg,(Bit16u)0);
|
||||
sSave(sDIB,joindedDrives,(Bit8u)0);
|
||||
sSave(sDIB,lastdrive,(Bit8u)0x01);//increase this if you add drives to cds-chain
|
||||
|
||||
sSave(sDIB,setverPtr,(Bit32u)0);
|
||||
|
||||
sSave(sDIB,a20FixOfs,(Bit16u)0);
|
||||
sSave(sDIB,pspLastIfHMA,(Bit16u)0);
|
||||
sSave(sDIB,blockDevices,(Bit8u)0);
|
||||
|
||||
sSave(sDIB,bootDrive,(Bit8u)0);
|
||||
sSave(sDIB,useDwordMov,(Bit8u)1);
|
||||
sSave(sDIB,extendedSize,(Bit16u)0x4000); // >16mb
|
||||
|
||||
sSave(sDIB,sharingCount,(Bit16u)0);
|
||||
sSave(sDIB,sharingDelay,(Bit16u)0);
|
||||
|
||||
sSave(sDIB,nulNextDriver,(Bit32u)0xffffffff);
|
||||
sSave(sDIB,nulAttributes,(Bit16u)0x8004);
|
||||
sSave(sDIB,nulStrategy,(Bit32u)0x00000000);
|
||||
sSave(sDIB,nulString[0],(Bit8u)0x4e);
|
||||
sSave(sDIB,nulString[1],(Bit8u)0x55);
|
||||
sSave(sDIB,nulString[2],(Bit8u)0x4c);
|
||||
sSave(sDIB,nulString[3],(Bit8u)0x20);
|
||||
sSave(sDIB,nulString[4],(Bit8u)0x20);
|
||||
sSave(sDIB,nulString[5],(Bit8u)0x20);
|
||||
sSave(sDIB,nulString[6],(Bit8u)0x20);
|
||||
sSave(sDIB,nulString[7],(Bit8u)0x20);
|
||||
}
|
||||
|
||||
void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb)
|
||||
{
|
||||
sSave(sDIB,firstMCB,_firstmcb);
|
||||
sSave(sDIB,firstMCB,_firstmcb); //c2woody
|
||||
}
|
||||
|
||||
void DOS_InfoBlock::SetfirstFileTable(RealPt _first_table){
|
||||
@ -81,6 +115,26 @@ void DOS_InfoBlock::SetBuffers(Bit16u x,Bit16u y) {
|
||||
|
||||
}
|
||||
|
||||
void DOS_InfoBlock::SetCurDirStruct(Bit32u _curdirstruct)
|
||||
{
|
||||
sSave(sDIB,curDirStructure,_curdirstruct);
|
||||
}
|
||||
|
||||
void DOS_InfoBlock::SetFCBTable(Bit32u _fcbtable)
|
||||
{
|
||||
sSave(sDIB,fcbTable,_fcbtable);
|
||||
}
|
||||
|
||||
void DOS_InfoBlock::SetDeviceChainStart(Bit32u _devchain)
|
||||
{
|
||||
sSave(sDIB,nulNextDriver,_devchain);
|
||||
}
|
||||
|
||||
void DOS_InfoBlock::SetDiskInfoBuffer(Bit32u _dinfobuf)
|
||||
{
|
||||
sSave(sDIB,diskInfoBuffer,_dinfobuf);
|
||||
}
|
||||
|
||||
RealPt DOS_InfoBlock::GetPointer(void)
|
||||
{
|
||||
return RealMake(seg,offsetof(sDIB,firstDPB));
|
||||
@ -94,7 +148,7 @@ Bit16u DOS_PSP::rootpsp = 0;
|
||||
void DOS_PSP::MakeNew(Bit16u mem_size)
|
||||
{
|
||||
/* get previous */
|
||||
DOS_PSP prevpsp(dos.psp);
|
||||
DOS_PSP prevpsp(dos.psp());
|
||||
/* Clear it first */
|
||||
Bitu i;
|
||||
for (i=0;i<sizeof(sPSP);i++) mem_writeb(pt+i,0);
|
||||
@ -112,16 +166,16 @@ void DOS_PSP::MakeNew(Bit16u mem_size)
|
||||
sSave(sPSP,service[1],0x21);
|
||||
sSave(sPSP,service[2],0xcb);
|
||||
/* psp and psp-parent */
|
||||
sSave(sPSP,psp_parent,dos.psp);
|
||||
sSave(sPSP,prev_psp,RealMake(dos.psp,0));
|
||||
sSave(sPSP,psp_parent,dos.psp());
|
||||
sSave(sPSP,prev_psp,0xffffffff);
|
||||
sSave(sPSP,dos_version,0x0005);
|
||||
/* terminate 22,break 23,crititcal error 24 address stored */
|
||||
SaveVectors();
|
||||
/* Process DTA */
|
||||
sSave(sPSP,dta,RealMake(seg,128));
|
||||
|
||||
/* FCBs are filled with 0 */
|
||||
// ....
|
||||
/* Init file pointer and max_files */
|
||||
sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files[0])));
|
||||
sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files)));
|
||||
sSave(sPSP,max_files,20);
|
||||
for (i=0;i<20;i++) SetFileHandle(i,0xff);
|
||||
|
||||
@ -218,7 +272,7 @@ void DOS_PSP::SetCommandTail(RealPt src)
|
||||
MEM_BlockCopy(pt+offsetof(sPSP,cmdtail),Real2Phys(src),128);
|
||||
} else { // empty
|
||||
sSave(sPSP,cmdtail.count,0x00);
|
||||
mem_writeb(pt+offsetof(sPSP,cmdtail.buffer[0]),0x0d);
|
||||
mem_writeb(pt+offsetof(sPSP,cmdtail.buffer),0x0d);
|
||||
};
|
||||
};
|
||||
|
||||
@ -403,3 +457,16 @@ void DOS_FCB::GetName(char * fillname) {
|
||||
fillname[14]=0;
|
||||
}
|
||||
|
||||
void DOS_FCB::GetAttr(Bit8u& attr) {
|
||||
if(extended) attr=mem_readb(pt - 1);
|
||||
}
|
||||
|
||||
void DOS_FCB::SetAttr(Bit8u attr) {
|
||||
if(extended) mem_writeb(pt - 1,attr);
|
||||
}
|
||||
|
||||
void DOS_SDA::Init() {
|
||||
/* Clear */
|
||||
for(Bitu i=0;i<sizeof(sSDA);i++) mem_writeb(pt+i,0x00);
|
||||
sSave(sSDA,drive_crit_error,0xff);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
@ -34,6 +34,27 @@
|
||||
static DOS_Device * devices[MAX_DEVICES];
|
||||
static Bit32u device_count;
|
||||
|
||||
class device_NUL : public DOS_Device {
|
||||
public:
|
||||
device_NUL() { name="NUL"; };
|
||||
bool Read(Bit8u * data,Bit16u * size) {
|
||||
for(Bitu i = 0; i < *size;i++)
|
||||
data[i]=0;
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("NUL:READ");
|
||||
return true;
|
||||
}
|
||||
bool Write(Bit8u * data,Bit16u * size) {
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("NUL:WRITE");
|
||||
return true;
|
||||
}
|
||||
bool Seek(Bit32u * pos,Bit32u type) {
|
||||
LOG(LOG_IOCTL,LOG_NORMAL)("NUL:SEEK");
|
||||
return true;
|
||||
}
|
||||
bool Close() { return true; }
|
||||
Bit16u GetInformation(void) { return 0x8004; }
|
||||
};
|
||||
|
||||
Bit8u DOS_FindDevice(char * name) {
|
||||
/* loop through devices */
|
||||
Bit8u index=0;
|
||||
@ -73,5 +94,8 @@ void DOS_SetupDevices(void) {
|
||||
DOS_Device * newdev;
|
||||
newdev=new device_CON();
|
||||
DOS_AddDevice(newdev);
|
||||
DOS_Device * newdev2;
|
||||
newdev2=new device_NUL();
|
||||
DOS_AddDevice(newdev2);
|
||||
}
|
||||
|
||||
|
@ -9,16 +9,17 @@
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id */
|
||||
/* $Id: dos_execute.cpp,v 1.44 2004/08/04 09:12:53 qbix79 Exp $ */
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "dosbox.h"
|
||||
#include "mem.h"
|
||||
#include "dos_inc.h"
|
||||
@ -26,6 +27,8 @@
|
||||
#include "callback.h"
|
||||
#include "debug.h"
|
||||
|
||||
char * RunningProgram="DOSBOX";
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
@ -65,7 +68,7 @@ struct EXE_Header {
|
||||
|
||||
|
||||
static void SaveRegisters(void) {
|
||||
reg_sp-=20;
|
||||
reg_sp-=18;
|
||||
mem_writew(SegPhys(ss)+reg_sp+ 0,reg_ax);
|
||||
mem_writew(SegPhys(ss)+reg_sp+ 2,reg_cx);
|
||||
mem_writew(SegPhys(ss)+reg_sp+ 4,reg_dx);
|
||||
@ -87,19 +90,28 @@ static void RestoreRegisters(void) {
|
||||
reg_bp=mem_readw(SegPhys(ss)+reg_sp+12);
|
||||
SegSet16(ds,mem_readw(SegPhys(ss)+reg_sp+14));
|
||||
SegSet16(es,mem_readw(SegPhys(ss)+reg_sp+16));
|
||||
reg_sp+=20;
|
||||
reg_sp+=18;
|
||||
}
|
||||
|
||||
extern void GFX_SetTitle(Bits cycles,Bits frameskip,bool paused);
|
||||
void DOS_UpdatePSPName(void) {
|
||||
DOS_MCB mcb(dos.psp()-1);
|
||||
static char name[9];
|
||||
mcb.GetFileName(name);
|
||||
if (!strlen(name)) strcpy(name,"DOSBOX");
|
||||
RunningProgram=name;
|
||||
GFX_SetTitle(-1,-1,false);
|
||||
}
|
||||
|
||||
bool DOS_Terminate(bool tsr) {
|
||||
|
||||
dos.return_code=reg_al;
|
||||
dos.return_mode=RETURN_EXIT;
|
||||
|
||||
Bit16u mempsp = dos.psp;
|
||||
Bit16u mempsp = dos.psp();
|
||||
|
||||
DOS_PSP curpsp(dos.psp);
|
||||
if (dos.psp==curpsp.GetParent()) return true;
|
||||
DOS_PSP curpsp(mempsp);
|
||||
if (mempsp==curpsp.GetParent()) return true;
|
||||
/* Free Files owned by process */
|
||||
if (!tsr) curpsp.CloseFiles();
|
||||
|
||||
@ -108,10 +120,9 @@ bool DOS_Terminate(bool tsr) {
|
||||
/* Restore vector 22,23,24 */
|
||||
curpsp.RestoreVectors();
|
||||
/* Set the parent PSP */
|
||||
dos.psp = curpsp.GetParent();
|
||||
dos.psp(curpsp.GetParent());
|
||||
DOS_PSP parentpsp(curpsp.GetParent());
|
||||
/* Restore the DTA of the parent psp */
|
||||
dos.dta = parentpsp.GetDTA();
|
||||
|
||||
/* Restore the SS:SP to the previous one */
|
||||
SegSet16(ss,RealSeg(parentpsp.GetStack()));
|
||||
reg_sp = RealOff(parentpsp.GetStack());
|
||||
@ -123,15 +134,13 @@ bool DOS_Terminate(bool tsr) {
|
||||
mem_writew(SegPhys(ss)+reg_sp+4,0x200); //stack isn't preserved
|
||||
// Free memory owned by process
|
||||
if (!tsr) DOS_FreeProcessMemory(mempsp);
|
||||
DOS_UpdatePSPName();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool MakeEnv(char * name,Bit16u * segment) {
|
||||
|
||||
/* If segment to copy environment is 0 copy the caller's environment */
|
||||
DOS_PSP psp(dos.psp);
|
||||
DOS_PSP psp(dos.psp());
|
||||
PhysPt envread,envwrite;
|
||||
Bit16u envsize=1;
|
||||
bool parentenv=true;
|
||||
@ -173,8 +182,7 @@ static bool MakeEnv(char * name,Bit16u * segment) {
|
||||
} else return false;
|
||||
}
|
||||
|
||||
bool DOS_NewPSP(Bit16u segment, Bit16u size)
|
||||
{
|
||||
bool DOS_NewPSP(Bit16u segment, Bit16u size) {
|
||||
DOS_PSP psp(segment);
|
||||
psp.MakeNew(size);
|
||||
DOS_PSP psp_parent(psp.GetParent());
|
||||
@ -182,8 +190,7 @@ bool DOS_NewPSP(Bit16u segment, Bit16u size)
|
||||
return true;
|
||||
};
|
||||
|
||||
bool DOS_ChildPSP(Bit16u segment, Bit16u size)
|
||||
{
|
||||
bool DOS_ChildPSP(Bit16u segment, Bit16u size) {
|
||||
DOS_PSP psp(segment);
|
||||
psp.MakeNew(size);
|
||||
DOS_PSP psp_parent(psp.GetParent());
|
||||
@ -194,7 +201,6 @@ bool DOS_ChildPSP(Bit16u segment, Bit16u size)
|
||||
};
|
||||
|
||||
static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
|
||||
|
||||
/* Fix the PSP for psp and environment MCB's */
|
||||
DOS_MCB mcb((Bit16u)(pspseg-1));
|
||||
mcb.SetPSPSeg(pspseg);
|
||||
@ -204,31 +210,14 @@ static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
|
||||
DOS_PSP psp(pspseg);
|
||||
psp.MakeNew(memsize);
|
||||
psp.SetEnvironment(envseg);
|
||||
/* Copy file handles //QBIX::ALWAYS COPY BUT LEFT ORIGINAL INCASE OF MISTAKES
|
||||
/* if (DOS_PSP::rootpsp!=dos.psp) { */
|
||||
// TODO: Improve this
|
||||
// If prog wasnt started from commandline copy file table (California Games 2)
|
||||
/* DOS_PSP oldpsp(dos.psp);
|
||||
psp.CopyFileTable(&oldpsp);
|
||||
} else {
|
||||
psp.SetFileHandle(STDIN ,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDOUT,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDERR,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDAUX,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDNUL,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDPRN,DOS_FindDevice("CON"));
|
||||
} */
|
||||
/* Save old DTA in psp */
|
||||
DOS_PSP oldpsp(dos.psp);
|
||||
psp.CopyFileTable(&oldpsp,true);
|
||||
|
||||
psp.SetDTA(dos.dta);
|
||||
/* Setup the DTA */
|
||||
dos.dta=RealMake(pspseg,0x80);
|
||||
/* Copy file handles */
|
||||
DOS_PSP oldpsp(dos.psp());
|
||||
psp.CopyFileTable(&oldpsp,true);
|
||||
|
||||
}
|
||||
|
||||
static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block)
|
||||
{
|
||||
static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block) {
|
||||
DOS_PSP psp(pspseg);
|
||||
// if cmdtail==0 it will inited as empty in SetCommandTail
|
||||
psp.SetCommandTail(block.exec.cmdtail);
|
||||
@ -263,14 +252,8 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
|
||||
if (len<sizeof(EXE_Header)) iscom=true;
|
||||
if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true;
|
||||
else {
|
||||
headersize=head.headersize*16;
|
||||
if (head.extrabytes) {
|
||||
imagesize = (head.pages-1)*512-headersize;
|
||||
imagesize += head.extrabytes % 512;
|
||||
} else
|
||||
imagesize = head.pages*512-headersize;
|
||||
|
||||
// always load st least 512 Bytes (dos cache/dos bug?)
|
||||
headersize = head.headersize*16;
|
||||
imagesize = head.pages*512-headersize;
|
||||
if (imagesize+headersize<512) imagesize = 512-headersize;
|
||||
}
|
||||
if (flags!=OVERLAY) {
|
||||
@ -298,16 +281,20 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
|
||||
else memsize=maxsize;
|
||||
if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory");
|
||||
loadseg=pspseg+16;
|
||||
if ((!iscom) & (head.minmemory == 0) & (head.maxmemory == 0))
|
||||
loadseg = (0x9e000 - imagesize)/16; //c2woody
|
||||
|
||||
} else loadseg=block.overlay.loadseg;
|
||||
/* Load the executable */
|
||||
Bit8u * loadbuf=(Bit8u *)new Bit8u[0x10000];
|
||||
loadaddress=PhysMake(loadseg,0);
|
||||
|
||||
if (iscom) { /* COM Load 64k - 256 bytes max */
|
||||
pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
|
||||
readsize=0xffff-256;
|
||||
DOS_ReadFile(fhandle,loadbuf,&readsize);
|
||||
MEM_BlockWrite(loadaddress,loadbuf,readsize);
|
||||
} else { /* EXE Load in 32kb blocks and then relocate */
|
||||
} else { /* EXE Load in 32kb blocks and then relocate */
|
||||
pos=headersize;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
|
||||
while (imagesize>0x7FFF) {
|
||||
readsize=0x8000;DOS_ReadFile(fhandle,loadbuf,&readsize);
|
||||
@ -341,7 +328,6 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
|
||||
SetupPSP(pspseg,memsize,envseg);
|
||||
SetupCMDLine(pspseg,block);
|
||||
};
|
||||
|
||||
CALLBACK_SCF(false); /* Carry flag cleared for caller if successfull */
|
||||
if (flags==OVERLAY) return true; /* Everything done for overlays */
|
||||
RealPt csip,sssp;
|
||||
@ -353,14 +339,15 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
|
||||
csip=RealMake(loadseg+head.initCS,head.initIP);
|
||||
sssp=RealMake(loadseg+head.initSS,head.initSP);
|
||||
}
|
||||
|
||||
|
||||
if (flags==LOAD) {
|
||||
DOS_PSP callpsp(dos.psp);
|
||||
DOS_PSP callpsp(dos.psp());
|
||||
/* Save the SS:SP on the PSP of calling program */
|
||||
callpsp.SetStack(RealMakeSeg(ss,reg_sp));
|
||||
/* Switch the psp's */
|
||||
dos.psp=pspseg;
|
||||
|
||||
dos.psp(pspseg);
|
||||
DOS_PSP newpsp(dos.psp());
|
||||
dos.dta(RealMake(newpsp.GetSegment(),0x80));
|
||||
block.exec.initsssp = sssp;
|
||||
block.exec.initcsip = csip;
|
||||
block.SaveData();
|
||||
@ -371,14 +358,13 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
|
||||
/* Get Caller's program CS:IP of the stack and set termination address to that */
|
||||
RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp)));
|
||||
SaveRegisters();
|
||||
DOS_PSP callpsp(dos.psp);
|
||||
DOS_PSP callpsp(dos.psp());
|
||||
/* Save the SS:SP on the PSP of calling program */
|
||||
callpsp.SetStack(RealMakeSeg(ss,reg_sp));
|
||||
/* Switch the psp's and set new DTA */
|
||||
dos.psp=pspseg;
|
||||
DOS_PSP newpsp(dos.psp);
|
||||
newpsp.SetDTA(dos.dta); /* Original: change this and line below. This way seems better(zone66 and unpack) */
|
||||
//dos.dta=newpsp.GetDTA();
|
||||
dos.psp(pspseg);
|
||||
DOS_PSP newpsp(dos.psp());
|
||||
dos.dta(RealMake(newpsp.GetSegment(),0x80));
|
||||
/* save vectors */
|
||||
newpsp.SaveVectors();
|
||||
/* copy fcbs */
|
||||
@ -399,6 +385,24 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
|
||||
/* Started from debug.com, then set breakpoint at start */
|
||||
DEBUG_CheckExecuteBreakpoint(RealSeg(csip),RealOff(csip));
|
||||
#endif
|
||||
/* Add the filename to PSP and environment MCB's */
|
||||
char stripname[8];Bitu index=0;
|
||||
while (char chr=*name++) {
|
||||
switch (chr) {
|
||||
case ':':case '\\':case '/':index=0;break;
|
||||
default:if (index<8) stripname[index++]=toupper(chr);
|
||||
}
|
||||
}
|
||||
index=0;
|
||||
while (index<8) {
|
||||
if (stripname[index]=='.') break;
|
||||
if (!stripname[index]) break;
|
||||
index++;
|
||||
}
|
||||
memset(&stripname[index],0,8-index);
|
||||
DOS_MCB pspmcb(dos.psp()-1);
|
||||
pspmcb.SetFileName(stripname);
|
||||
DOS_UpdatePSPName();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user