DOSBox 0.71

This commit is contained in:
Carl.Kenner 2009-05-02 22:37:32 +00:00
parent e5731161bb
commit 5d0f3a05e8
142 changed files with 11913 additions and 1384 deletions

13
AUTHORS
View File

@ -1,8 +1,11 @@
The DOSBox Team
---------------
Sjoerd v.d. Berg <harekiet@users.sourceforge.net>
Peter Veenstra <qbix79@users.sourceforge.net>
Ulf Wohlers <finsterr@users.sourceforge.net>
Tommy Frössman <fanskapet@sidvicious.se>
Dean Beeler <canadacow@users.sourceforge.net>
Sjoerd v.d. Berg <harekiet>
Peter Veenstra <qbix79>
Ulf Wohlers <finsterr>
Tommy Frössman <fanskapet>
Dean Beeler <canadacow>
Sebastian Strohhäcker <c2woody>
nick_without_<> @ users.sourceforge.net

View File

@ -1,7 +1,59 @@
0.71
- Add a new recompiling cpu core, which should be easier to port.
- Add 64 bit version of the recompiling core.
- Add mipsel 32 bit version of the recompiling core.
- Fix a few small problems with FCBs. (fixes Jewels of darkness and
cyrus chess)
- Raise some more exceptions. (fixes vbdos)
- Fix a few problems with the dynamic core. (fixes Inner Words,
Archmimedean Dynasty and others)
- Improve/Fix fallback code for certain graphics cards.
- Fix a few cd audio related bugs.
- Add an undocumented MSCDEX feature. (Fixes Ultimate Domain)
- Fix some pcspeaker mode. (fixes Test Drive and similar games)
- Improve dos keyinput handling. (fixes Wing Commander 3 exit dialog)
- Remove Exit condition on fully nested mode. (fixes some demo)
- Add image file size detection.
- Add/Fix some ansi codes. (fixes PC Larn and certain versions of
infocom games)
- Several general DOS fixes. (fixes nba95, hexit and various other games)
- Add some valid input checks. (fixes 3d body adventure and similar
games)
- Fix digital joystick centering problem.
- Reenable textmode 54 and 55.
- Fix a pelmask problem with univbe 5.0 lite. (fixes Panzer General)
- Fix minor mixer underflow.
- Some general image and bios disk emulation fixes.
- Hopefully fix compilation on BSD and darwin.
- Try using ioctl cdrom access by default if possible.
- Fix some svga detection routine. (fixes Grandest Fleet 2 and Bobby Fischer
Teaches Chess)
- You can now close DOSBox using the status window in win32.
- Add support for NX enabled systems.
- Fix a casting error which only showed with certain compilers. (fixes
various games under mac os x and 64 bit linux)
- Improve timer and add gate 2 support. (fixes various games and
joystick problems)
- Improve mouse. Add undocumented backdoor. (fixes Last half of Darkness,
PC-BLOX and others)
- Add/improve support for ~ and ~username in all commands.
- Fix a font problem with the pcjr/tandy. (fixes personal deskmate 2)
- Change dma routine a bit. (fixes ticks in sound in various games)
- Allow read-only diskimages to be booted. (fixes various booter
games)
- Add basic hidden file support on cdrom images. (fixes Player
Manager 2)
- Add some rarely used functionality to the int10 mode setup. (fixes
WW2 Battles of the South pacific)
- Add ability to force scaler usage.
- Speed up flag generation and make it more 386-like.
- Some colourful feedback in the mapper.
- General code cleanup.
0.70
- Improve register handling and support with XMS.
- Fix some issues with deleting open files.(windows only issue)
- Add dummpy LPT1 class. (windows only issue)
- Add dummy LPT1 class. (windows only issue)
- Improve some of the internal dos commands. (choice, copy and shift)
- Improve ROM area. (for games that use it for random numbers or
overwrite it as some sort of detection thing)
@ -13,7 +65,7 @@
- Move some interrupt handlers to XT Bios locations.
- Add a dynamic fpu on x86.
- Improve fpu on non-x86.
- Trapflag gets strickt priority over hardware IRQs.
- Trapflag gets strict priority over hardware IRQs.
- Trapflag support for the dynamic core.
- Add dummy TRx handling.
- Fix a few rarely used character functions.

31
INSTALL
View File

@ -41,24 +41,39 @@ In step 1 you could add the following switches:
--enable-debug
enables the internal debugger. --enable-debug=heavy enables even more
debug options. Dosbox should then be run from a xterm and when the sdl-
window is active press pause to enter the debugger.
--disable-fpu
Will disable the emulated fpu. Although the fpu emulation code isn't
finished and isn't entirely accurate it's advised to leave it on.
window is active press alt-pause to enter the debugger.
--enable-core-inline
enables some memory increasing inlines. This greatly increases
compiletime for maybe a increase in speed.
--disable-dynamic-x86
disables the dynamic cpu core. Although it's unstable it can greatly
improve the speed of dosbox on x86 hosts.
--disable-fpu
disables the emulated fpu. Although the fpu emulation code isn't
finished and isn't entirely accurate it's advised to leave it on.
--disable-fpu-x86
disables the assembly fpu core. Although relatively new the x86 fpu
core has more accuracy then the regular fpu core.
--disable-dynamic-x86
disables the dynamic x86 specific cpu core. Although it might be
be a bit unstable, it can greatly improve the speed of dosbox on x86
hosts.
Please note that this option on x86 will result in a different
dynamic/recompiling cpu core being compiled then the default.
For more information see the option --disable-dynrec
--disable-dynrec
disables the recompiling cpu core. Currently x86 and x86_64 only.
You can activate this core on x86 by disabling the dynamic-x86 core.
--disable-dynamic-core
disables all dynamic cores. (same effect as
--disable-dynamic-x86 --disable-dynrec)
--disable-unaligned-memory
disables unaligned memory access.
Check the src subdir for the binary.
NOTE: If capslock and numlock appear to be broken. open

View File

@ -157,8 +157,8 @@ RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
check-recursive installcheck-recursive
DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/configure AUTHORS \
COPYING ChangeLog INSTALL Makefile.am NEWS THANKS acinclude.m4 \
aclocal.m4 config.guess config.h.in config.sub configure \
configure.in depcomp install-sh missing mkinstalldirs
aclocal.m4 config.guess config.h.in config.sub configure.in \
depcomp install-sh missing mkinstalldirs
DIST_SUBDIRS = $(SUBDIRS)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive

56
NEWS
View File

@ -1,7 +1,59 @@
0.71
- Add a new recompiling cpu core, which should be easier to port.
- Add 64 bit version of the recompiling core.
- Add mipsel 32 bit version of the recompiling core.
- Fix a few small problems with FCBs. (fixes Jewels of darkness and
cyrus chess)
- Raise some more exceptions. (fixes vbdos)
- Fix a few problems with the dynamic core. (fixes Inner Words,
Archmimedean Dynasty and others)
- Improve/Fix fallback code for certain graphics cards.
- Fix a few cd audio related bugs.
- Add an undocumented MSCDEX feature. (Fixes Ultimate Domain)
- Fix some pcspeaker mode. (fixes Test Drive and similar games)
- Improve dos keyinput handling. (fixes Wing Commander 3 exit dialog)
- Remove Exit condition on fully nested mode. (fixes some demo)
- Add image file size detection.
- Add/Fix some ansi codes. (fixes PC Larn and certain versions of
infocom games)
- Several general DOS fixes. (fixes nba95, hexit and various other games)
- Add some valid input checks. (fixes 3d body adventure and similar
games)
- Fix digital joystick centering problem.
- Reenable textmode 54 and 55.
- Fix a pelmask problem with univbe 5.0 lite. (fixes Panzer General)
- Fix minor mixer underflow.
- Some general image and bios disk emulation fixes.
- Hopefully fix compilation on BSD and darwin.
- Try using ioctl cdrom access by default if possible.
- Fix some svga detection routine. (fixes Grandest Fleet 2 and Bobby Fischer
Teaches Chess)
- You can now close DOSBox using the status window in win32.
- Add support for NX enabled systems.
- Fix a casting error which only showed with certain compilers. (fixes
various games under mac os x and 64 bit linux)
- Improve timer and add gate 2 support. (fixes various games and
joystick problems)
- Improve mouse. Add undocumented backdoor. (fixes Last half of Darkness,
PC-BLOX and others)
- Add/improve support for ~ and ~username in all commands.
- Fix a font problem with the pcjr/tandy. (fixes personal deskmate 2)
- Change dma routine a bit. (fixes ticks in sound in various games)
- Allow read-only diskimages to be booted. (fixes various booter
games)
- Add basic hidden file support on cdrom images. (fixes Player
Manager 2)
- Add some rarely used functionality to the int10 mode setup. (fixes
WW2 Battles of the South pacific)
- Add ability to force scaler usage.
- Speed up flag generation and make it more 386-like.
- Some colourful feedback in the mapper.
- General code cleanup.
0.70
- Improve register handling and support with XMS.
- Fix some issues with deleting open files.(windows only issue)
- Add dummpy LPT1 class. (windows only issue)
- Add dummy LPT1 class. (windows only issue)
- Improve some of the internal dos commands. (choice, copy and shift)
- Improve ROM area. (for games that use it for random numbers or
overwrite it as some sort of detection thing)
@ -13,7 +65,7 @@
- Move some interrupt handlers to XT Bios locations.
- Add a dynamic fpu on x86.
- Improve fpu on non-x86.
- Trapflag gets strickt priority over hardware IRQs.
- Trapflag gets strict priority over hardware IRQs.
- Trapflag support for the dynamic core.
- Add dummy TRx handling.
- Fix a few rarely used character functions.

217
README
View File

@ -1,4 +1,4 @@
DOSBox v0.70
DOSBox v0.71
=====
@ -33,11 +33,18 @@ INDEX:
15. Contact
==============
1. Quickstart:
==============
Type INTRO in DOSBox. That's it.
Type INTRO in DOSBox for a quick tour.
It is essential that you get familiar with the idea of mounting,
DOSBox does not automatically make any drive (or parts of it)
accessible to the emulation.
See the FAQ entry "I've got a Z instead of a C at the prompt" as
well as the description of the MOUNT command (section 4).
=======
@ -47,24 +54,26 @@ Type INTRO in DOSBox. That's it.
Some Frequently Asked Questions:
Q: I've got a Z instead of a C at the prompt.
Q: How do I change to fullscreen ?
Q: Do I always have to type these commands? Automation?
Q: How do I change to fullscreen?
Q: My CD-ROM doesn't work.
Q: The mouse doesn't work.
Q: There is no sound.
Q: The sound stutters or sounds stretched/weird.
Q: I can't type \ or : in DOSBox.
Q: The keyboard lags.
Q: The cursor always moves into one direction!
Q: The game/application can't find its CD-ROM.
Q: The game/application runs much too slow!
Q: Can DOSBox harm my computer?
Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ.
Q: What sound hardware does DOSBox presently emulate?
Q: DOSBox crashes on startup and I'm running arts
Q: DOSBox crashes on startup and I'm running arts.
Q: Great README, but I still don't get it.
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:\GAMES" will give
@ -75,7 +84,13 @@ A: You have to make your directories available as drives in DOSBox by using
fine, DOSBox will display the prompt "C:\>".
Q: How do I change to fullscreen ?
Q: Do I always have to type these commands? Automation?
A: In the DOSBox configuration file is an [autoexec] section. The commands
present there are run when DOSBox starts, so you can use this section
for the mounting.
Q: How do I change to fullscreen?
A: Press alt-enter. Alternatively: Edit the configuration file of DOSBox and
change the option fullscreen=false to fullscreen=true. If fullscreen looks
wrong in your opinion: Play with the option fullresolution in the
@ -86,17 +101,17 @@ A: Press alt-enter. Alternatively: Edit the configuration file of DOSBox and
Q: My CD-ROM doesn't work.
A: To mount your CD-ROM in DOSBox you have to specify some additional options
when mounting the CD-ROM.
To enable the most basic CD-ROM support:
To enable CD-ROM support (includes MSCDEX):
- mount d f:\ -t cdrom
To enable low-level SDL-support:
To enable low-level CD-ROM-support (uses ioctl if possible):
- 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 SDL-support:
- mount d f:\ -t cdrom -usecd 0 -noioctl
To enable low-level aspi-support (win98 with aspi-layer installed):
- mount d f:\ -t cdrom -usecd 0 -aspi
In the commands: - d driveletter you will get in DOSBox
- f:\ location of cdrom on your PC.
- f:\ location of CD-ROM on your PC.
- 0 The number of the CD-ROM drive, reported by mount -cd
See also the question: The game/application can't find its CD-ROM.
@ -123,11 +138,12 @@ A: Be sure that the sound is correctly configured in the game. This might be
Q: The sound stutters or sounds stretched/weird.
A: You're using too much cpu power to keep DOSBox running at the current speed.
You can lower the cycles, skip frames or get a faster machine.
You can also increase the prebuffer in the configfile.
A: You're using too much CPU power to keep DOSBox running at the current speed.
You can lower the cycles, skip frames, reduce the sampling rate of
the respective sound device (see the DOSBox configuration file) or
the mixer device. You can also increase the prebuffer in the configfile.
If you are using cycles=max or =auto, then make sure that there no
background processes interfering! (especially if they acces the harddisk)
background processes interfering! (especially if they access the harddisk)
Q: I can't type \ or : in DOSBox.
@ -137,7 +153,7 @@ A: This is a known problem. It only occurs if your keyboard layout isn't US.
2. Use / instead.
3. Open dosbox.conf and change usescancodes=false to usescancodes=true.
4. Add the commands you want to execute to the "configfile".
5. Change the dos keyboard layout (see Section 7 Keyboard Layout).
5. Change the DOS keyboard layout (see Section 7 Keyboard Layout).
6. Use ALT-58 for : and ALT-92 for \.
7. for \ try the keys around "enter". For ":" try shift and the keys
between "enter" and "l" (US keyboard layout).
@ -146,14 +162,32 @@ A: This is a known problem. It only occurs if your keyboard layout isn't US.
have a bug in the loader routines.
Q: The keyboard lags.
A: Lower the priority setting in the DOSBox configuration file
like set "priority=normal,normal". You might also want to
try lowering the cycles.
Q: The cursor always moves into one direction!
A: See if it still happens if you disable the joystick emulation,
set joysticktype=none in the [joystick] section of your DOSBox
configuration file. Maybe also try unplugging any joystick.
If you want to use the joystick in the game, try setting timed=false
and be sure to calibrate the joystick (both in your OS as well as
in the game or the game's setup).
Q: The game/application can't find its CD-ROM.
A: Be sure to mount the CD-ROM with -t cdrom switch, this will enable the
MSCDEX interface required by DOS games to interface with CD-ROMs.
Also try adding the correct label (-label LABEL). To enable lower-level
CD-ROM support, add the following switch to mount: -usecd #, where # is
the number of your CD-ROM drive reported by mount -cd. Under Windows you
can specify -ioctl or -aspi. Look at the description elsewhere in this
document for their meaning.
can specify -ioctl, -aspi or -noioctl. Look at the description elsewhere
in this document for their meaning.
Try creating a CD-ROM image (preferably CUE/BIN pair) and use the
DOSBox-internal IMGMOUNT tool to mount the image. This enables very
good low-level CD-ROM support on any operating system.
Q: The game/application runs much too slow!
@ -217,7 +251,7 @@ A: This isn't really a DOSBox problem, but the solution is to set the
Q: Great README, but I still don't get it.
A: A look at "The Newbie's pictorial guide to DOSBox" located at
http://vogons.zetafleet.com/viewforum.php?f=39 might help you.
Also try the wiki of dosbox:
Also try the wiki of DOSBox:
http://dosbox.sourceforge.net/wiki/
@ -227,7 +261,6 @@ http://dosbox.sourceforge.net
=========
3. Usage:
=========
@ -240,7 +273,7 @@ description:
dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile]
[-lang languagefile] [-machine machinetype] [-noconsole]
[-startmapper] [-noautoexec]
[-startmapper] [-noautoexec] [-scaler scaler | -forcescaler scaler]
dosbox -version
@ -269,15 +302,15 @@ dosbox -version
-lang languagefile
Start DOSBox using the language specified in "languagefile".
-noconsole (Windows Only)
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:
hercules, cga, pcjr, tandy, vga (default). The machinetype affects
both the videocard and the available soundcards.
-noconsole (Windows Only)
Start DOSBox without showing the console window. Output will
be redirected to stdout.txt and stderr.txt
-startmapper
Enter the keymapper directly on startup. Useful for people with
keyboard problems.
@ -285,6 +318,14 @@ dosbox -version
-noautoexec
Skips the [autoexec] section of the loaded configuration file.
-scaler scaler
Uses the scaler specified by "scaler". See the DOSBox configuration
file for the available scalers.
-forcescaler scaler
Similar to the -scaler parameter, but tries to force usage of
the specified scaler even if it might not fit.
-version
output version information and exit. Useful for frontends.
@ -318,35 +359,44 @@ To get a list of the internal commands type "HELP" at the prompt.
In addition, the following commands are available:
MOUNT "Emulated Drive letter" "Real Drive or Directory"
[-t type] [-aspi] [-ioctl] [-usecd number] [-size drivesize]
[-t type] [-aspi] [-ioctl] [-noioctl] [-usecd number] [-size drivesize]
[-label drivelabel] [-freesize size_in_mb]
[-freesize size_in_kb (floppies)]
MOUNT -cd
MOUNT -u "Emulated Drive letter"
Program to mount local directories as drives inside DOSBox.
"Emulated Drive letter"
The driveletter inside dosbox (eg. C).
The driveletter inside DOSBox (eg. C).
"Real Drive letter (usually for CD-ROMs in Windows) or Directory"
The local directory you want accessible inside dosbox.
The local directory you want accessible inside DOSBox.
-t type
Type of the mounted directory. Supported are: dir (default),
floppy, cdrom.
-size drivesize
Sets the size of the drive.
Sets the size of the drive, where drivesize is of the form
"bps,spc,tcl,fcl":
bps: bytes per sector, by default 512 for regular drives and
2048 for CD-ROM drives
spc: sectors per cluster, usually between 1 and 127
tcl: total clusters, between 1 and 65534
fcl: total free clusters, between 1 and tcl
-freesize size_in_mb
Sets the amount of free space available on a drive in megabytes.
-freesize size_in_mb | size_in_kb
Sets the amount of free space available on a drive in megabytes
(regular drives) or kilobytes (floppy drives).
This is a simpler version of -size.
-label drivelabel
Sets the name of the drive to "drivelabel". Needed on some
systems if the cd label isn't read correctly. Useful when a
program can't find its cdrom. If you don't specify a label and no
lowlevel support is selected (-usecd # and/or -ioctl/aspi):
program can't find its CD-ROM. If you don't specify a label and no
lowlevel support is selected (that is omitting the -usecd # and/or
-aspi parameters or specifying -noioctl):
For win32: label is extracted from "Real Drive".
For Linux: label is set to NO_LABEL.
@ -354,24 +404,27 @@ MOUNT -u "Emulated Drive letter"
is mounted. It will not be updated !!
-aspi
Forces use of the aspi layer. Only valid if mounting a cdrom under
Forces use of the aspi layer. Only valid if mounting a CD-ROM under
Windows systems with an ASPI-Layer.
-ioctl
Forces use of ioctl commands. Only valid if mounting a cdrom under
Forces use of ioctl commands. Only valid if mounting a CD-ROM under
a Windows OS which support them (Win2000/XP/NT).
-noioctl
Forces use of the SDL CD-ROM layer. Valid on all systems.
-usecd number
Forces use of SDL cdrom support for drive number.
Forces use of SDL CD-ROM support for drive number.
Number can be found by -cd. Valid on all systems.
-cd
Displays all detected cdrom drives and their numbers. Use with -usecd.
Displays all detected CD-ROM drives and their numbers. Use with -usecd.
-u
Removes the mount. Doesn't work for Z:\.
Note: It's possible to mount a local directory as cdrom drive.
Note: It's possible to mount a local directory as CD-ROM drive.
Hardware support is then missing.
Basically MOUNT allows you to connect real hardware to DOSBox's emulated PC.
@ -387,7 +440,7 @@ MOUNT -u "Emulated Drive letter"
Mounting your entire C drive with MOUNT C C:\ is NOT recommended! The same
is true for mounting the root of any other drive, except for CD-ROMs (due to
their read-only nature). Otherwise if you or DOSBox make a mistakes you may
their read-only nature). Otherwise if you or DOSBox make a mistake you may
loose all your files.
It is recommended to put all your applications/games into a subdirectory
and mount that.
@ -395,24 +448,27 @@ MOUNT -u "Emulated Drive letter"
General MOUNT Examples:
1. To mount c:\DirX as a floppy :
mount a c:\DirX -t floppy
2. To mount system cdrom drive E as cdrom drive D in DOSBox:
2. To mount system CD-ROM drive E as CD-ROM 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:
3. To mount system CD-ROM drive at mountpoint /media/cdrom as CD-ROM drive D
in DOSBox:
mount d /media/cdrom -t cdrom -usecd 0
4. To mount a drive with 870 mb free diskspace (simple version):
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 a drive with ~870 mb free diskspace (experts only, full control):
mount c d:\ -size 512,127,16513,13500
6. To mount /home/user/dirY as drive C in DOSBox:
mount c /home/user/dirY
7. To mount the directory where DOSBox was started as D in DOSBox:
mount d .
MEM
Program to display the amount of free memory.
CONFIG [-writeconf] [-writelang] localfile
CONFIG -writeconf localfile
CONFIG -writelang localfile
CONFIG -set "section property=value"
CONFIG -get "section property"
@ -432,8 +488,8 @@ CONFIG -get "section property"
-writelang localfile
Write the current language settings to file. "localfile" is
located on the local drive, not a mounted drive in DOSBox.
The language file controls all visible ouput of the internal commands
and the internal dos.
The language file controls all visible output of the internal commands
and the internal DOS.
-set "section property=value"
CONFIG will attempt to set the property to new value. At this moment
@ -469,7 +525,6 @@ LOADFIX -f
-f
frees all previously allocated memory
Examples:
1. To start mm2.exe and allocate 64kb memory
(mm2 will have 64 kb less available) :
@ -496,14 +551,14 @@ MIXER
left:right
The volume levels in percentages. If you put a D in front it will be
in deciBell (example mixer gus d-10).
in decibel (example mixer gus d-10).
/NOSHOW
Prevents DOSBox from showing the result if you set one
of the volume levels.
/LISTMIDI
Lists the available midi devices on your pc (Windows). To select a
Lists the available midi devices on your PC (Windows). To select a
device other than the Windows default midi-mapper, add a line
'config=id' to the [midi] section in the configuration file, where
'id' is the number for the device as listed by LISTMIDI.
@ -632,7 +687,7 @@ IPX
IPXNET STARTSERVER
IPXNET STARTSERVER starts and IPX tunneling server on this DOSBox
IPXNET STARTSERVER starts an IPX tunnelling 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 tunnelling server.
@ -712,7 +767,6 @@ For more information use the /? command line switch with the programs.
================
5. Special Keys:
================
@ -728,7 +782,7 @@ CTRL-ALT-F7 Start/Stop recording of OPL commands.
CTRL-ALT-F8 Start/Stop the recording of raw MIDI commands.
CTRL-F7 Decrease frameskip.
CTRL-F8 Increase frameskip.
CTRL-F9 Kill dosbox.
CTRL-F9 Kill DOSBox.
CTRL-F10 Capture/Release the mouse.
CTRL-F11 Slow down emulation (Decrease DOSBox Cycles).
CTRL-F12 Speed up emulation (Increase DOSBox Cycles).
@ -811,9 +865,9 @@ Examples about remapping the joystick:
You have a joystick attached, it is working fine under DOSBox and you
want to play some keyboard-only game with the joystick (it is assumed
that the game is controlled by the arrows on the keyboard):
1) Start the mapper, then klick on one of the arrows in the middle
1) Start the mapper, then click on one of the arrows in the middle
of the left part of the screen (right above the Mod1/Mod2 buttons).
EVENT should be key_left. Now klick on Add and move your joystick
EVENT should be key_left. Now click on Add and move your joystick
in the respective direction, this should add an event to the BIND.
2) Repeat the above for the missing three directions, additionally
the buttons of the joystick can be remapped as well (fire/jump).
@ -822,12 +876,12 @@ Examples about remapping the joystick:
You want to swap the y-axis of the joystick because some flightsim uses
the up/down joystick movement in a way you don't like, and it is not
configurable in the game itself:
1) Start the mapper and klick on Y- in the upper joystick field (this
1) Start the mapper and click on Y- in the upper joystick field (this
is for the first joystick if you have two joysticks attached) or the
lower joystick field (second joystick or, if you have only one
joystick attached, the second axes cross).
EVENT should be jaxis_0_1- (or jaxis_1_1-).
2) Click on Del to remove the current binding, then klick Add and move
2) Click on Del to remove the current binding, then click Add and move
your joystick downwards. A new bind should be created.
3) Repeat this for Y+, save the layout and finally test it with some game.
@ -845,8 +899,8 @@ is present in the configfile.
===================
To switch to a different keyboard layout, either the entry "keyboardlayout"
in the [dos]-section in dosbox.conf can be used, or the internal DOSBox
program keyb.com. Both accept dos-conform language codes (see below), but
in the [dos] section in dosbox.conf can be used, or the internal DOSBox
program keyb.com. Both accept DOS conforming language codes (see below), but
only by using keyb.com a custom codepage can be specified.
Layout switching
@ -861,10 +915,8 @@ Layout switching
NO (Norway), PL (Poland), RU (Russian Federation), SK (Slovakia), SP (Spain),
SU (Finland), SV (Sweden)
When a keyboard layout is loaded, it is possible to switch between the
foreign layout and the US-layout by pressing CTRL+ALT+F2.
Some keyboard layouts (for example layout GK codepage 869 and layout RU
codepage 808) have support for dual-layouts that can be activated by
codepage 808) have support for dual layouts that can be activated by
pressing LEFT-ALT+RIGHT-SHIFT and deactivated by LEFT-ALT+LEFT-SHIFT.
Supported external files
@ -874,12 +926,12 @@ Supported external files
See http://projects.freedos.net/keyb/ for precompiled keyboard layouts.
Both .CPI (MSDOS/compatible codepage files) and .CPX (freedos UPX-compressed
codepage files) can be used. Some codepages are compiled into DOSBox so it
codepage files) can be used. Some codepages are compiled into DOSBox, so it
is mostly not needed to care about external codepage files. If you need
a different (or custom) codepage file, copy it into the directory of the
DOSBox configuration file so it is accessible for DOSBox.
Additional layouts can be added by copying the corresponding .kl-file into
Additional layouts can be added by copying the corresponding .kl file into
the directory of dosbox.conf and using the first part of the filename as
language code.
Example: For the file UZ.KL (keyboard layout for Uzbekistan) specify
@ -925,7 +977,7 @@ of the nullmodem connection. These are all parameters:
* server: - This nullmodem will be a client connecting to the specified
server. (No server argument: be a server.)
* transparent:1 - Only send the serial data, no RTS/DTR handshake. Use this
when connecting to anyting other than a nullmodem.
when connecting to anything other than a nullmodem.
* telnet:1 - Interpret Telnet data from the remote site. Automatically
sets transparent.
* usedtr:1 - The connection will not be established until DTR is switched
@ -957,7 +1009,7 @@ CPU Cycles
at the top then. In this mode you can reduce the amount of cycles on a
percentage-basis (hit CTRL-F11) or raise it again (CTRL-F12).
Sometimes customly setting the number of cycles achieves better results,
Sometimes manually setting the number of cycles achieves better results,
in the DOSBox configuration file specify for example cycles=30000. When
running some DOS application you can raise the cycles with CTRL-F12 even
more, but you will be limited by the power of your actual CPU. You can see
@ -992,14 +1044,14 @@ as possible for DOSBox.
Advanced cycles configuration:
The cycles=auto and cycles=max settings can be parametrized to have
The cycles=auto and cycles=max settings can be parameterized to have
different startup defaults. The syntax is
cycles=auto ["realmode default"] ["protected mode default"%]
[limit "cycle limit"]
cycles=max ["protected mode default"%] [limit "cycle limit"]
Example:
cycles=auto 1000 80% limit 20000
will use cycles=1000 for real mode games, 80% cpu throttling for
will use cycles=1000 for real mode games, 80% CPU throttling for
protected mode games along with a hard cycle limit of 20000
@ -1018,7 +1070,7 @@ Running a certain game closes DOSBox, crashes with some message or hangs:
(unmodified configuration file)
- try it with sound disabled (use the sound configuration
program that comes with the game, additionally you can
use sbtype=none and gus=false)
set sbtype=none and gus=false in the DOSBox configuration file)
- change some entries of the DOSBox configuration file, especially try:
core=normal
fixed cycles (for example cycles=10000)
@ -1033,18 +1085,21 @@ The game exits to the DOSBox prompt with some error message:
- mount differently as some games are picky about the locations,
for example if you used "mount d d:\oldgames\game" try
"mount c d:\oldgames\game" and "mount c d:\oldgames"
- if the game requires a cdrom be sure you used "-t cdrom" when
mounting and try different additional parameters
- if the game requires a CD-ROM be sure you used "-t cdrom" when
mounting and try different additional parameters (the ioctl,
usecd and label switches, see the appropriate section)
- check the file permissions of the game files (remove read-only
attributes, add write permissions etc.)
- try reinstalling the game within dosbox
- try reinstalling the game within DOSBox
====================
11. 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
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.
@ -1066,7 +1121,7 @@ look in the current directory for dosbox.conf.
12. The Language File:
======================
A language file can be generated by CONFIG.COM.
A language file can be generated by CONFIG.COM (CONFIG -writelang langfile).
Read it, and you will hopefully understand how to change it.
Start DOSBox with the -lang switch to use your new language file.
Alternatively, you can setup the filename in the config file in the [dosbox]
@ -1087,17 +1142,7 @@ Check the INSTALL in the source distribution.
14. Special thanks:
===================
Vlad R. of the VDMSound project for excellent SoundBlaster info.
Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator.
The Bochs and DOSemu projects, which I used for information.
Freedos for ideas in making my shell.
Pierre-Yves Gérardy for hosting the old Beta Board.
Colin Snover for hosting our forum.
Jantien for the version management.
Shawn and Johannes for creating the MAC OS X PPC version.
Ido Beeri for the icon.
The Beta Testers.
See the THANKS file.
============

9
THANKS
View File

@ -12,11 +12,14 @@ Pierre-Yves G
Colin Snover for hosting our forum.
Sourceforge for hosting our homepage and other development tools.
Mirek Luza for his moderation of the forums.
c2woody for his debug work.
Mirek Luza, for his moderation of the forums.
eL_Pusher, DosFreak and MiniMax for their moderation of VOGONS forum.
crazyc and gulikoza for their work on the dynrec core.
Jantien for the version management.
Shawn and Johannes for creating the MAC OS X PPC version.
Shawn, Johannes and Marcus for creating the MAC OS X version.
Jochen for creating the OS/2 version.
Ido Beeri for the icon.
All the people who submitted a bug.
The Beta Testers.

21
config.guess vendored
View File

@ -1,9 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2006-02-23'
timestamp='2006-07-02'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@ -210,7 +211,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
exit ;;
macppc:MirBSD:*:*)
echo powerppc-unknown-mirbsd${UNAME_RELEASE}
echo powerpc-unknown-mirbsd${UNAME_RELEASE}
exit ;;
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
@ -770,6 +771,8 @@ EOF
case ${UNAME_MACHINE} in
pc98)
echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
@ -780,9 +783,6 @@ EOF
i*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:MSYS_NT-*:*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
@ -790,10 +790,10 @@ EOF
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
x86:Interix*:[345]*)
x86:Interix*:[3456]*)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
EM64T:Interix*:[345]*)
EM64T:Interix*:[3456]*)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
@ -831,6 +831,9 @@ EOF
arm*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
echo cris-axis-linux-gnu
exit ;;
@ -989,7 +992,7 @@ EOF
LIBC=gnulibc1
# endif
#else
#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__sun)
#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
LIBC=gnu
#else
LIBC=gnuaout

View File

@ -33,6 +33,10 @@
/* Define to 1 to use x86 dynamic cpu core */
#undef C_DYNAMIC_X86
/* Define to 1 to use recompiling cpu core. Can not be used together with the
dynamic-x86 core */
#undef C_DYNREC
/* Define to 1 to enable floating point emulation */
#undef C_FPU
@ -52,9 +56,6 @@
/* Define to 1 to enable heavy debugging, also have to enable C_DEBUG */
#undef C_HEAVY_DEBUG
/* 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
@ -73,6 +74,9 @@
/* Define to 1 to enable screenshots, requires libpng */
#undef C_SSHOT
/* The type of cpu this target has */
#undef C_TARGETCPU
/* Define to 1 to use a unaligned memory access */
#undef C_UNALIGNED_MEMORY
@ -103,6 +107,12 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
@ -115,6 +125,9 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
@ -124,7 +137,7 @@
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Compiling on GNU/Linux */
/* Compiling on GNU/Linux or *BSD */
#undef LINUX
/* Compiling on Mac OS X */
@ -194,6 +207,9 @@
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to `int` if you don't have socklen_t */
#undef socklen_t
#define INLINE inline
#if C_HAS_ATTRIBUTE

46
config.sub vendored
View File

@ -1,9 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
timestamp='2006-02-23'
timestamp='2006-07-02'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@ -240,7 +241,7 @@ case $basic_machine in
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
@ -248,7 +249,8 @@ case $basic_machine in
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| m32r | m32rle | m68000 | m68k | m88k | maxq | mb | microblaze | mcore \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@ -274,11 +276,11 @@ case $basic_machine in
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b \
| strongarm \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
@ -286,9 +288,6 @@ case $basic_machine in
| z8k)
basic_machine=$basic_machine-unknown
;;
m32c)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
basic_machine=$basic_machine-unknown
@ -318,7 +317,7 @@ case $basic_machine in
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* \
| avr-* | avr32-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | craynv-* | cydra-* \
@ -329,7 +328,7 @@ case $basic_machine in
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| m32r-* | m32rle-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
@ -358,11 +357,11 @@ case $basic_machine in
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
@ -373,8 +372,6 @@ case $basic_machine in
| ymp-* \
| z8k-*)
;;
m32c-*)
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
386bsd)
@ -1128,7 +1125,7 @@ case $basic_machine in
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b)
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
@ -1217,7 +1214,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos*)
| -skyos* | -haiku* | -rdos* | -toppers*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@ -1369,6 +1366,9 @@ else
# system, and we'll never get to this point.
case $basic_machine in
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
@ -1378,9 +1378,9 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
c4x-* | tic4x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20

493
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.60a for dosbox 0.70.
# Generated by GNU Autoconf 2.60a for dosbox 0.71.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
@ -557,8 +557,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='dosbox'
PACKAGE_TARNAME='dosbox'
PACKAGE_VERSION='0.70'
PACKAGE_STRING='dosbox 0.70'
PACKAGE_VERSION='0.71'
PACKAGE_STRING='dosbox 0.71'
PACKAGE_BUGREPORT=''
ac_unique_file="README"
@ -1215,7 +1215,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures dosbox 0.70 to adapt to many kinds of systems.
\`configure' configures dosbox 0.71 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1286,7 +1286,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of dosbox 0.70:";;
short | recursive ) echo "Configuration of dosbox 0.71:";;
esac
cat <<\_ACEOF
@ -1296,10 +1296,13 @@ Optional Features:
--disable-dependency-tracking Speeds up one-time builds
--enable-dependency-tracking Do not reject slow dependency extractors
--disable-sdltest Do not try to compile and run a test SDL program
--enable-alsa-midi compile with alsa midi support (default yes)
--disable-alsatest Do not try to compile and run a test Alsa program
--enable-debug Enable debug mode
--enable-core-inline Enable inlined memory handling in CPU Core
--disable-dynamic-core Disable all dynamic cores
--disable-dynamic-x86 Disable x86 dynamic cpu core
--disable-dynrec Disable recompiling cpu core
--disable-fpu Disable fpu support
--disable-fpu-x86 Disable x86 assembly fpu core
--disable-unaligned-memory
@ -1388,7 +1391,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
dosbox configure 0.70
dosbox configure 0.71
generated by GNU Autoconf 2.60a
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@ -1402,7 +1405,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by dosbox $as_me 0.70, which was
It was created by dosbox $as_me 0.71, which was
generated by GNU Autoconf 2.60a. Invocation command line was
$ $0 $@
@ -2170,7 +2173,7 @@ fi
# Define the identity of the package.
PACKAGE='dosbox'
VERSION='0.70'
VERSION='0.71'
cat >>confdefs.h <<_ACEOF
@ -8693,6 +8696,328 @@ _ACEOF
for ac_header in stdlib.h sys/types.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
echo $ECHO_N "(cached) $ECHO_C" >&6
fi
ac_res=`eval echo '${'$as_ac_Header'}'`
{ echo "$as_me:$LINENO: result: $ac_res" >&5
echo "${ECHO_T}$ac_res" >&6; }
else
# Is the header compilable?
{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6; }
# Is the header present?
{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <$ac_header>
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
else
ac_cpp_err=
fi
else
ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6; }
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
yes:no: )
{ echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
ac_header_preproc=yes
;;
no:yes:* )
{ echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
;;
esac
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
eval "$as_ac_Header=\$ac_header_preproc"
fi
ac_res=`eval echo '${'$as_ac_Header'}'`
{ echo "$as_me:$LINENO: result: $ac_res" >&5
echo "${ECHO_T}$ac_res" >&6; }
fi
if test `eval echo '${'$as_ac_Header'}'` = yes; then
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
for ac_header in sys/socket.h netinet/in.h pwd.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
eval "$as_ac_Header=yes"
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
eval "$as_ac_Header=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
ac_res=`eval echo '${'$as_ac_Header'}'`
{ echo "$as_me:$LINENO: result: $ac_res" >&5
echo "${ECHO_T}$ac_res" >&6; }
if test `eval echo '${'$as_ac_Header'}'` = yes; then
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
cat >conftest.$ac_ext <<_ACEOF
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
:
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
cat >>confdefs.h <<\_ACEOF
#define socklen_t int
_ACEOF
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ echo "$as_me:$LINENO: checking if environ can be included" >&5
echo $ECHO_N "checking if environ can be included... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
@ -9156,7 +9481,18 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
alsa_save_CFLAGS="$CFLAGS"
# Check whether --enable-alsa-midi was given.
if test "${enable_alsa_midi+set}" = set; then
enableval=$enable_alsa_midi; case "${enableval}" in
yes) alsa_midi=true;;
no) alsa_midi=false;;
esac
else
alsa_midi=true
fi
if test x$alsa_midi = xtrue ; then
alsa_save_CFLAGS="$CFLAGS"
alsa_save_LDFLAGS="$LDFLAGS"
alsa_save_LIBS="$LIBS"
alsa_found=yes
@ -9448,6 +9784,8 @@ fi
CXXFLAGS="$CXXFLAGS $ALSA_CFLAGS"
fi
#Check for big endian machine, should #define WORDS_BIGENDIAN if so
{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
@ -10121,39 +10459,49 @@ fi
{ echo "$as_me:$LINENO: checking for target cpu type" >&5
echo $ECHO_N "checking for target cpu type... $ECHO_C" >&6; }
case "$target_cpu" in
x86_64 | amd64)
cat >>confdefs.h <<\_ACEOF
#define C_TARGETCPU X86_64
_ACEOF
{ echo "$as_me:$LINENO: result: x86-64 bit compatible" >&5
echo "${ECHO_T}x86-64 bit compatible" >&6; }
c_targetcpu="x86_64"
c_unalignedmemory=yes
;;
i?86)
cat >>confdefs.h <<\_ACEOF
#define C_HOSTCPU X86
#define C_TARGETCPU X86
_ACEOF
{ echo "$as_me:$LINENO: result: x86 compatible" >&5
echo "${ECHO_T}x86 compatible" >&6; }
c_hostcpu="x86"
c_targetcpu="x86"
c_unalignedmemory=yes
;;
powerpc*)
cat >>confdefs.h <<\_ACEOF
#define C_HOSTCPU POWERPC
#define C_TARGETCPU POWERPC
_ACEOF
{ echo "$as_me:$LINENO: result: Power PC" >&5
echo "${ECHO_T}Power PC" >&6; }
c_hostcpu="powerpc"
c_targetcpu="powerpc"
c_unalignedmemory=yes
;;
m68k*)
cat >>confdefs.h <<\_ACEOF
#define C_HOSTCPU M68K
#define C_TARGETCPU M68K
_ACEOF
{ echo "$as_me:$LINENO: result: Motorola 68000" >&5
echo "${ECHO_T}Motorola 68000" >&6; }
c_hostcpu="m68k"
c_targetcpu="m68k"
c_unalignedmemory=yes
;;
*)
cat >>confdefs.h <<\_ACEOF
#define C_HOSTCPU UNKOWN
#define C_TARGETCPU UNKNOWN
_ACEOF
{ echo "$as_me:$LINENO: result: unknown" >&5
@ -10162,6 +10510,14 @@ echo "${ECHO_T}unknown" >&6; }
;;
esac
# Check whether --enable-dynamic-core was given.
if test "${enable_dynamic_core+set}" = set; then
enableval=$enable_dynamic_core;
else
enable_dynamic_core=yes
fi
# Check whether --enable-dynamic-x86 was given.
@ -10173,11 +10529,11 @@ fi
{ echo "$as_me:$LINENO: checking whether x86 dynamic cpu core will be enabled" >&5
echo $ECHO_N "checking whether x86 dynamic cpu core will be enabled... $ECHO_C" >&6; }
if test x$enable_dynamic_x86 = xno ; then
if test x$enable_dynamic_x86 = xno -o x$enable_dynamic_core = xno; then
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
else
if test x$c_hostcpu = xx86 ; then
if test x$c_targetcpu = xx86 ; then
cat >>confdefs.h <<\_ACEOF
#define C_DYNAMIC_X86 1
_ACEOF
@ -10192,6 +10548,48 @@ fi
# Check whether --enable-dynrec was given.
if test "${enable_dynrec+set}" = set; then
enableval=$enable_dynrec;
else
enable_dynrec=yes
fi
{ echo "$as_me:$LINENO: checking whether recompiling cpu core will be enabled" >&5
echo $ECHO_N "checking whether recompiling cpu core will be enabled... $ECHO_C" >&6; }
if test x$enable_dynrec = xno -o x$enable_dynamic_core = xno; then
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
else
if test x$c_targetcpu = xx86 ; then
if test x$enable_dynamic_x86 = xno ; then
cat >>confdefs.h <<\_ACEOF
#define C_DYNREC 1
_ACEOF
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
else
{ echo "$as_me:$LINENO: result: no, using dynamic-x86" >&5
echo "${ECHO_T}no, using dynamic-x86" >&6; }
fi
else
if test x$c_targetcpu = xx86_64 ; then
cat >>confdefs.h <<\_ACEOF
#define C_DYNREC 1
_ACEOF
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
else
{ echo "$as_me:$LINENO: result: no" >&5
echo "${ECHO_T}no" >&6; }
fi
fi
fi
# Check whether --enable-fpu was given.
if test "${enable_fpu+set}" = set; then
enableval=$enable_fpu;
@ -10229,7 +10627,7 @@ if test x$enable_fpu_x86 = xno ; then
echo "${ECHO_T}no" >&6; }
else
if test x$enable_fpu = xyes; then
if test x$c_hostcpu = xx86 ; then
if test x$c_targetcpu = xx86 ; then
cat >>confdefs.h <<\_ACEOF
#define C_FPU_X86 1
_ACEOF
@ -10845,28 +11243,7 @@ fi
# Check whether --enable-opengl was given.
if test "${enable_opengl+set}" = set; then
enableval=$enable_opengl;
else
enable_opengl=yes
fi
{ echo "$as_me:$LINENO: checking whether opengl display output will be enabled" >&5
echo $ECHO_N "checking whether opengl display output will be enabled... $ECHO_C" >&6; }
if test x$enable_opengl = xyes; then
case "$target" in
*-*-darwin*)
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
LIBS="$LIBS -framework OpenGL"
cat >>confdefs.h <<\_ACEOF
#define C_OPENGL 1
_ACEOF
;;
*)
{ echo "$as_me:$LINENO: checking for main in -lGL" >&5
{ echo "$as_me:$LINENO: checking for main in -lGL" >&5
echo $ECHO_N "checking for main in -lGL... $ECHO_C" >&6; }
if test "${ac_cv_lib_GL_main+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@ -10943,7 +11320,7 @@ else
have_gl_lib=no
fi
{ echo "$as_me:$LINENO: checking for main in -lopengl32" >&5
{ echo "$as_me:$LINENO: checking for main in -lopengl32" >&5
echo $ECHO_N "checking for main in -lopengl32... $ECHO_C" >&6; }
if test "${ac_cv_lib_opengl32_main+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@ -11020,7 +11397,7 @@ else
have_opengl32_lib=no
fi
if test "${ac_cv_header_GL_gl_h+set}" = set; then
if test "${ac_cv_header_GL_gl_h+set}" = set; then
{ echo "$as_me:$LINENO: checking for GL/gl.h" >&5
echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6; }
if test "${ac_cv_header_GL_gl_h+set}" = set; then
@ -11176,6 +11553,27 @@ else
fi
# Check whether --enable-opengl was given.
if test "${enable_opengl+set}" = set; then
enableval=$enable_opengl;
else
enable_opengl=yes
fi
{ echo "$as_me:$LINENO: checking whether opengl display output will be enabled" >&5
echo $ECHO_N "checking whether opengl display output will be enabled... $ECHO_C" >&6; }
if test x$enable_opengl = xyes; then
case "$target" in
*-*-darwin*)
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
LIBS="$LIBS -framework OpenGL"
cat >>confdefs.h <<\_ACEOF
#define C_OPENGL 1
_ACEOF
;;
*)
if test x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then
{ echo "$as_me:$LINENO: result: yes" >&5
echo "${ECHO_T}yes" >&6; }
@ -12043,7 +12441,7 @@ _ACEOF
LIBS="$LIBS -framework AudioUnit"
;;
*-*-linux-gnu*)
*-*-freebsd* | *-*-linux* | *-*-dragonfly* | *-*-netbsd* | *-*-openbsd*)
cat >>confdefs.h <<\_ACEOF
#define LINUX 1
@ -12185,7 +12583,7 @@ fi
ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/cpu/core_dyn_x86/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/hardware/serialport/Makefile src/ints/Makefile src/libs/Makefile src/libs/zmbv/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc_net/Makefile include/Makefile docs/Makefile"
ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/cpu/core_dyn_x86/Makefile src/cpu/core_dynrec/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/hardware/serialport/Makefile src/ints/Makefile src/libs/Makefile src/libs/zmbv/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc_net/Makefile include/Makefile docs/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@ -12598,7 +12996,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by dosbox $as_me 0.70, which was
This file was extended by dosbox $as_me 0.71, which was
generated by GNU Autoconf 2.60a. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -12651,7 +13049,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
dosbox config.status 0.70
dosbox config.status 0.71
configured by $0, generated by GNU Autoconf 2.60a,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@ -12772,6 +13170,7 @@ do
"src/cpu/core_full/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_full/Makefile" ;;
"src/cpu/core_normal/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_normal/Makefile" ;;
"src/cpu/core_dyn_x86/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_dyn_x86/Makefile" ;;
"src/cpu/core_dynrec/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_dynrec/Makefile" ;;
"src/debug/Makefile") CONFIG_FILES="$CONFIG_FILES src/debug/Makefile" ;;
"src/dos/Makefile") CONFIG_FILES="$CONFIG_FILES src/dos/Makefile" ;;
"src/fpu/Makefile") CONFIG_FILES="$CONFIG_FILES src/fpu/Makefile" ;;

View File

@ -1,5 +1,5 @@
dnl Init.
AC_INIT(dosbox,0.70)
AC_INIT(dosbox,0.71)
AC_PREREQ(2.50)
AC_CONFIG_SRCDIR(README)
@ -20,7 +20,7 @@ AC_PROG_INSTALL
AC_PROG_RANLIB
dnl Some needed libaries for OS2
dnl perharps join this with the other host depended checks. move them upwards
dnl perharps join this with the other target depended checks. move them upwards
if test x$target = xi386-pc-os2-emx ; then
CXXFLAGS="$CXXFLAGS -Zmt"
LDFLAGS="$LDFLAGS -Zomf -Zmt"
@ -50,6 +50,42 @@ AC_CHECK_SIZEOF(unsigned long)
AC_CHECK_SIZEOF(unsigned long long)
AC_CHECK_SIZEOF(int *)
dnl some semi complex check for sys/socket so it works on darwin as well
AC_CHECK_HEADERS([stdlib.h sys/types.h])
AC_CHECK_HEADERS([sys/socket.h netinet/in.h pwd.h], [], [],
[#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
])
dnl check for the socklen_t (darwin doesn't always have it)
AC_COMPILE_IFELSE([
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
],[],[AC_DEFINE([socklen_t],[int],[Define to `int` if you don't have socklen_t])])
AC_MSG_CHECKING(if environ can be included)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <unistd.h>
@ -93,7 +129,18 @@ int x=10;if( __builtin_expect ((x==1),0) ) ;
#switch language back
AC_LANG_POP(C++)
AM_PATH_ALSA(0.9.0, AC_DEFINE(HAVE_ALSA,1,[Define to 1 to use ALSA for MIDI]) , : )
dnl enable disable alsa and pass it's cflags to CXXFLAGS
AC_ARG_ENABLE(alsa-midi,
AC_HELP_STRING([--enable-alsa-midi],[compile with alsa midi support (default yes)]),
[ case "${enableval}" in
yes) alsa_midi=true;;
no) alsa_midi=false;;
esac],
[alsa_midi=true])
if test x$alsa_midi = xtrue ; then
AM_PATH_ALSA(0.9.0, AC_DEFINE(HAVE_ALSA,1,[Define to 1 to use ALSA for MIDI]) , : )
CXXFLAGS="$CXXFLAGS $ALSA_CFLAGS"
fi
#Check for big endian machine, should #define WORDS_BIGENDIAN if so
AC_C_BIGENDIAN
@ -135,41 +182,49 @@ AC_ARG_ENABLE(core-inline,AC_HELP_STRING([--enable-core-inline],[Enable inlined
dnl The target cpu checks for dynamic cores
AH_TEMPLATE(C_HOSTCPU,[The type of cpu this host has])
AH_TEMPLATE(C_TARGETCPU,[The type of cpu this target has])
AC_MSG_CHECKING(for target cpu type)
case "$target_cpu" in
x86_64 | amd64)
AC_DEFINE(C_TARGETCPU,X86_64)
AC_MSG_RESULT(x86-64 bit compatible)
c_targetcpu="x86_64"
c_unalignedmemory=yes
;;
i?86)
AC_DEFINE(C_HOSTCPU,X86)
AC_DEFINE(C_TARGETCPU,X86)
AC_MSG_RESULT(x86 compatible)
c_hostcpu="x86"
c_targetcpu="x86"
c_unalignedmemory=yes
;;
powerpc*)
AC_DEFINE(C_HOSTCPU,POWERPC)
AC_DEFINE(C_TARGETCPU,POWERPC)
AC_MSG_RESULT(Power PC)
c_hostcpu="powerpc"
c_targetcpu="powerpc"
c_unalignedmemory=yes
;;
m68k*)
AC_DEFINE(C_HOSTCPU,M68K)
AC_DEFINE(C_TARGETCPU,M68K)
AC_MSG_RESULT(Motorola 68000)
c_hostcpu="m68k"
c_targetcpu="m68k"
c_unalignedmemory=yes
;;
*)
AC_DEFINE(C_HOSTCPU,UNKOWN)
AC_DEFINE(C_TARGETCPU,UNKNOWN)
AC_MSG_RESULT(unknown)
c_unalignedmemory=no
;;
esac
AC_ARG_ENABLE(dynamic-core,AC_HELP_STRING([--disable-dynamic-core],[Disable all dynamic cores]),,enable_dynamic_core=yes)
AH_TEMPLATE(C_DYNAMIC_X86,[Define to 1 to use x86 dynamic cpu core])
AC_ARG_ENABLE(dynamic-x86,AC_HELP_STRING([--disable-dynamic-x86],[Disable x86 dynamic cpu core]),,enable_dynamic_x86=yes)
AC_MSG_CHECKING(whether x86 dynamic cpu core will be enabled)
if test x$enable_dynamic_x86 = xno ; then
if test x$enable_dynamic_x86 = xno -o x$enable_dynamic_core = xno; then
AC_MSG_RESULT(no)
else
if test x$c_hostcpu = xx86 ; then
if test x$c_targetcpu = xx86 ; then
AC_DEFINE(C_DYNAMIC_X86,1)
AC_MSG_RESULT(yes)
else
@ -177,6 +232,30 @@ else
fi
fi
AH_TEMPLATE(C_DYNREC,[Define to 1 to use recompiling cpu core. Can not be used together with the dynamic-x86 core])
AC_ARG_ENABLE(dynrec,AC_HELP_STRING([--disable-dynrec],[Disable recompiling cpu core]),,enable_dynrec=yes)
AC_MSG_CHECKING(whether recompiling cpu core will be enabled)
if test x$enable_dynrec = xno -o x$enable_dynamic_core = xno; then
AC_MSG_RESULT(no)
else
dnl x86 only enable it if dynamic-x86 is disabled.
if test x$c_targetcpu = xx86 ; then
if test x$enable_dynamic_x86 = xno ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT([no, using dynamic-x86])
fi
else
if test x$c_targetcpu = xx86_64 ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
fi
fi
AH_TEMPLATE(C_FPU,[Define to 1 to enable floating point emulation])
AC_ARG_ENABLE(fpu,AC_HELP_STRING([--disable-fpu],[Disable fpu support]),,enable_fpu=yes)
AC_MSG_CHECKING(whether fpu emulation will be enabled)
@ -194,7 +273,7 @@ if test x$enable_fpu_x86 = xno ; then
AC_MSG_RESULT(no)
else
if test x$enable_fpu = xyes; then
if test x$c_hostcpu = xx86 ; then
if test x$c_targetcpu = xx86 ; then
AC_DEFINE(C_FPU_X86,1)
AC_MSG_RESULT(yes)
else
@ -249,6 +328,9 @@ else
fi
AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support])
AC_CHECK_LIB(GL, main, have_gl_lib=yes, have_gl_lib=no , )
AC_CHECK_LIB(opengl32, main, have_opengl32_lib=yes,have_opengl32_lib=no , )
AC_CHECK_HEADER(GL/gl.h, have_gl_h=yes , have_gl_h=no , )
AC_ARG_ENABLE(opengl,AC_HELP_STRING([--disable-opengl],[Disable opengl support]),,enable_opengl=yes)
AC_MSG_CHECKING(whether opengl display output will be enabled)
if test x$enable_opengl = xyes; then
@ -259,9 +341,6 @@ case "$target" in
AC_DEFINE(C_OPENGL,1)
;;
*)
AC_CHECK_LIB(GL, main, have_gl_lib=yes, have_gl_lib=no , )
AC_CHECK_LIB(opengl32, main, have_opengl32_lib=yes,have_opengl32_lib=no , )
AC_CHECK_HEADER(GL/gl.h, have_gl_h=yes , have_gl_h=no , )
if test x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then
AC_MSG_RESULT(yes)
LIBS="$LIBS -lGL"
@ -309,7 +388,7 @@ int main(int argc,char * argv[]) {
],AC_MSG_RESULT(yes);AC_DEFINE(C_SET_PRIORITY,1),AC_MSG_RESULT(no))
dnl Some host detection and actions for them
dnl Some target detection and actions for them
case "$target" in
*-*-cygwin* | *-*-mingw32*)
LIBS="$LIBS -lwinmm"
@ -327,8 +406,8 @@ case "$target" in
AC_DEFINE(MACOSX, 1, [Compiling on Mac OS X])
LIBS="$LIBS -framework AudioUnit"
;;
*-*-linux-gnu*)
AC_DEFINE(LINUX, 1, [Compiling on GNU/Linux])
*-*-freebsd* | *-*-linux* | *-*-dragonfly* | *-*-netbsd* | *-*-openbsd*)
AC_DEFINE(LINUX, 1, [Compiling on GNU/Linux or *BSD])
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).])
;;
*-*-os2-emx*)
@ -358,6 +437,7 @@ src/cpu/Makefile
src/cpu/core_full/Makefile
src/cpu/core_normal/Makefile
src/cpu/core_dyn_x86/Makefile
src/cpu/core_dynrec/Makefile
src/debug/Makefile
src/dos/Makefile
src/fpu/Makefile

View File

@ -1,7 +1,7 @@
# Main Makefile for DOSBox
man_MANS = dosbox.1
EXTRA_DIST = $(man_MANS) README.video
EXTRA_DIST = $(man_MANS) README.video PORTING

View File

@ -142,7 +142,7 @@ target_os = @target_os@
target_vendor = @target_vendor@
man_MANS = dosbox.1
EXTRA_DIST = $(man_MANS) README.video
EXTRA_DIST = $(man_MANS) README.video PORTING
subdir = docs
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs

48
docs/PORTING Normal file
View File

@ -0,0 +1,48 @@
Some notes about porting DOSBox to systems with certain restrictions,
like handheld devices.
If memory is a constraint:
- in paging.h reduce the size of the TLB:
#define TLB_SIZE (64*1024)
the 64 gives access to the first 256mb of linear memory
drawback: some protected mode games won't work then
gain: reduces memory requirements about ~15mb
TODO: limit vmemory access to the size of the TLB,
otherwise games which use >256mb vaddresses will crash badly
- in render.h lower the scaler integration:
#define RENDER_USE_ADVANCED_SCALERS 1
or
#define RENDER_USE_ADVANCED_SCALERS 0
drawback: complex scalers and the scaler cache are disabled,
be sure to test if this affects speed!
with define RENDER_USE_ADVANCED_SCALERS==0 most simple
scalers are disabled as well, some graphics modes won't
work due to reduced cache sizes
gain: ~2mb with RENDER_USE_ADVANCED_SCALERS==1
~5mb with RENDER_USE_ADVANCED_SCALERS==0
- in dos_system.h reduce the drive cache entries:
#define MAX_OPENDIRS 256
drawback: some apps might not work whith large directory trees
gain: ~1mb per mounted drive
- remove the GUS emulation (gus.cpp, especially GUSRam[1024*1024] )
drawback: no gravis ultrasound
gain: reduces memory requirements about 1mb
- in vga.h reduce the size of the emulated graphics memory:
#define VGA_MEMORY (1*1024*1024)
drawback: some graphics modes won't work then
[EDIT: many modes won't work due to pixel caches]
gain: reduces memory requirements about 1mb
TODO: get this to actually work;
remove the respective svga modes, adapt some svga registers
If speed is a constraint:
- see if the simple core is faster, possibly remove the normal core
set the simple core as default
drawback: one game is known to not work with the simple core;
the simple core does only work for games which don't use paging
(when paging is requested the normal core is used automatically)
gain: the simple core should be somewhat faster
TODO: add possibility to easily remove the normal core, use fullcore fallback
- raise the default frameskip value
drawback: minor graphics smoothness loss for some games (video playback)
gain: reduces graphics load

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH DOSBOX 1 "Mar 28, 2006"
.TH DOSBOX 1 "Jul 01, 2007"
.\" Please adjust this date whenever revising the manpage.
.SH NAME
dosbox \- an x86/DOS emulator with sound/graphics
@ -8,6 +8,8 @@ dosbox \- an x86/DOS emulator with sound/graphics
.B [\-fullscreen]
.B [\-startmapper]
.B [\-noautoexec]
.BI "[\-scaler " scaler ]
.BI "[\-forcescaler " scaler ]
.BI "[\-conf " configfile ]
.BI "[\-lang " langfile ]
.B [file]
@ -39,6 +41,14 @@ A summary of options is included below.
.B \-noautoexec
Skips the [autoexec] section of the loaded configuration file.
.TP
.BI \-scaler " scaler"
.RI "Uses the graphical scaler specified by " scaler ". See the configuration"
file for the available scalers
.TP
.BI \-forcescaler " scaler"
.RB "Similar to the " \-scaler " parameter, but tries to force usage of"
the specified scaler even if it might not fit.
.TP
.BI \-c " command"
.RI "Runs the specified " command " before running "
.BR file .
@ -74,7 +84,7 @@ following extra commands are available:
.HP
.BI "MOUNT [\-t " type "] [\-size " size ]
.I driveletter sourcedirectory
.B [\-aspi] [\-ioctl]
.B [\-ioctl]
.BI "[\-usecd " number "] [\-label " drivelabel "] [\-freesize " freesize ]
.LP
.B MOUNT \-cd
@ -115,18 +125,13 @@ If you do specify a label this label will be kept as long as the drive
is mounted. It will not be updated !!
.RE
.TP
.B \-aspi
Forces to use the aspi layer. Only valid if mounting a cdrom under
Windows systems with an ASPI-Layer.
.TP
.B \-ioctl
Forces to use ioctl commands. Only valid if mounting a cdrom under
windows which support them (Win2000/XP/NT).
Forces to use ioctl commands.
.TP
.BI \-usecd " number"
Forces to use SDL cdrom support for drive number.
.IR Number " can be found by "
.BR \-cd ". Valid on all systems."
.BR \-cd ".
.TP
.B \-cd
.RB "Displays all detected cdrom drives and their numbers. Use with " \-usecd "."
@ -211,6 +216,13 @@ Boot will start floppy images or hard disk images independent of the
.TP
.RB "Read the " README " of " dosbox " for the full and correct syntax."
.RE
.TP
.B KEYB
.LP
Keyb can change the keyboardlayout and the codepage used inside dosbox.
.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.
First ~/.dosboxrc (if present) will be loaded. If no

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: callback.h,v 1.19 2007/01/08 19:45:37 qbix79 Exp $ */
/* $Id: callback.h,v 1.21 2007/06/12 20:22:07 c2woody Exp $ */
#ifndef DOSBOX_CALLBACK_H
#define DOSBOX_CALLBACK_H
@ -28,8 +28,8 @@
typedef Bitu (*CallBack_Handler)(void);
extern CallBack_Handler CallBack_Handlers[];
enum { CB_RETN,CB_RETF,CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1,
CB_IRQ0,CB_IRQ1,CB_IRQ9,CB_IRQ12,CB_IRQ12_RET,CB_IRQ6_PCJR,
enum { CB_RETN,CB_RETF,CB_RETF8,CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1,
CB_IRQ0,CB_IRQ1,CB_IRQ9,CB_IRQ12,CB_IRQ12_RET,CB_IRQ6_PCJR,CB_MOUSE,
CB_INT29,CB_INT16,CB_HOOKABLE,CB_TDE_IRET,CB_IPXESR,CB_IPXESR_RET };
#define CB_MAX 128
@ -43,10 +43,10 @@ enum {
extern Bit8u lastint;
INLINE RealPt CALLBACK_RealPointer(Bitu callback) {
return RealMake(CB_SEG,callback*CB_SIZE);
return RealMake(CB_SEG,(Bit16u)(callback*CB_SIZE));
}
INLINE PhysPt CALLBACK_PhysPointer(Bitu callback) {
return PhysMake(CB_SEG,callback*CB_SIZE);
return PhysMake(CB_SEG,(Bit16u)(callback*CB_SIZE));
}
INLINE PhysPt CALLBACK_GetBase(void) {

View File

@ -58,6 +58,8 @@ Bits CPU_Core_Simple_Run(void);
Bits CPU_Core_Full_Run(void);
Bits CPU_Core_Dyn_X86_Run(void);
Bits CPU_Core_Dyn_X86_Trap_Run(void);
Bits CPU_Core_Dynrec_Run(void);
Bits CPU_Core_Dynrec_Trap_Run(void);
//CPU Stuff
@ -68,10 +70,12 @@ bool CPU_LTR(Bitu selector);
void CPU_LIDT(Bitu limit,Bitu base);
void CPU_LGDT(Bitu limit,Bitu base);
void CPU_STR(Bitu & selector);
void CPU_SLDT(Bitu & selector);
void CPU_SIDT(Bitu & limit,Bitu & base);
void CPU_SGDT(Bitu & limit,Bitu & base);
Bitu CPU_STR(void);
Bitu CPU_SLDT(void);
Bitu CPU_SIDT_base(void);
Bitu CPU_SIDT_limit(void);
Bitu CPU_SGDT_base(void);
Bitu CPU_SGDT_limit(void);
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel);
void CPU_LAR(Bitu selector,Bitu & ar);
@ -88,8 +92,8 @@ bool CPU_READ_DRX(Bitu dr,Bit32u & retvalue);
bool CPU_WRITE_TRX(Bitu dr,Bitu value);
bool CPU_READ_TRX(Bitu dr,Bit32u & retvalue);
void CPU_SMSW(Bitu & word);
Bitu CPU_LMSW(Bitu word);
Bitu CPU_SMSW(void);
bool CPU_LMSW(Bitu word);
void CPU_VERR(Bitu selector);
void CPU_VERW(Bitu selector);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_inc.h,v 1.65 2007/01/08 20:36:53 qbix79 Exp $ */
/* $Id: dos_inc.h,v 1.70 2007/07/20 18:53:52 qbix79 Exp $ */
#ifndef DOSBOX_DOS_INC_H
#define DOSBOX_DOS_INC_H
@ -85,6 +85,9 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
#define DOS_SDA_OFS 0
#define DOS_MEM_START 0x102 //First Segment that DOS can use
#define DOS_PRIVATE_SEGMENT 0xc800
#define DOS_PRIVATE_SEGMENT_END 0xd000
/* internal Dos Tables */
extern DOS_File * Files[DOS_FILES];
@ -112,35 +115,35 @@ bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry);
bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate);
/* Routines for Drive Class */
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_OpenFile(char const * name,Bit8u flags,Bit16u * entry);
bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status);
bool DOS_CreateFile(char const * name,Bit16u attribute,Bit16u * entry);
bool DOS_UnlinkFile(char const * const name);
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);
bool DOS_FileExists(char * name);
bool DOS_Canonicalize(char const * const name,char * const big);
bool DOS_CreateTempFile(char * const name,Bit16u * entry);
bool DOS_FileExists(char const * const name);
/* Helper Functions */
bool DOS_MakeName(char * name,char * fullname,Bit8u * drive);
bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive);
/* Drive Handing Routines */
Bit8u DOS_GetDefaultDrive(void);
void DOS_SetDefaultDrive(Bit8u drive);
bool DOS_SetDrive(Bit8u drive);
bool DOS_GetCurrentDir(Bit8u drive,char * bugger);
bool DOS_ChangeDir(char * dir);
bool DOS_MakeDir(char * dir);
bool DOS_RemoveDir(char * dir);
bool DOS_Rename(char * oldname,char * newname);
bool DOS_GetCurrentDir(Bit8u drive,char * const buffer);
bool DOS_ChangeDir(char const * const dir);
bool DOS_MakeDir(char const * const dir);
bool DOS_RemoveDir(char const * const dir);
bool DOS_Rename(char const * const oldname,char const * const newname);
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free);
bool DOS_GetFileAttr(char * name,Bit16u * attr);
bool DOS_SetFileAttr(char * name,Bit16u attr);
bool DOS_GetFileAttr(char const * const name,Bit16u * attr);
bool DOS_SetFileAttr(char const * const name,Bit16u attr);
/* IOCTL Stuff */
bool DOS_IOCTL(void);
bool DOS_GetSTDINStatus();
Bit8u DOS_FindDevice(char * name);
Bit8u DOS_FindDevice(char const * name);
void DOS_SetupDevices(void);
/* Execute and new process creation */
@ -171,7 +174,7 @@ Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset, Bit16u numBlocks);
Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u numBlocks);
Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore);
Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore);
bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset,Bit16u numRec);
bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset);
bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset);
bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset);
void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset);
@ -257,9 +260,9 @@ public:
}
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;
case 1:mem_writeb(pt+addr,(Bit8u)val);break;
case 2:mem_writew(pt+addr,(Bit16u)val);break;
case 4:mem_writed(pt+addr,(Bit32u)val);break;
}
}
INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);}
@ -280,14 +283,14 @@ public:
void SaveVectors (void);
void RestoreVectors (void);
void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); };
Bit16u GetSize (void) { return sGet(sPSP,next_seg); };
Bit16u GetSize (void) { return (Bit16u)sGet(sPSP,next_seg); };
void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); };
Bit16u GetEnvironment (void) { return sGet(sPSP,environment); };
Bit16u GetEnvironment (void) { return (Bit16u)sGet(sPSP,environment); };
Bit16u GetSegment (void) { return seg; };
void SetFileHandle (Bit16u index, Bit8u handle);
Bit8u GetFileHandle (Bit16u index);
void SetParent (Bit16u parent) { sSave(sPSP,psp_parent,parent); };
Bit16u GetParent (void) { return sGet(sPSP,psp_parent); };
Bit16u GetParent (void) { return (Bit16u)sGet(sPSP,psp_parent); };
void SetStack (RealPt stackpt) { sSave(sPSP,stack,stackpt); };
RealPt GetStack (void) { return sGet(sPSP,stack); };
void SetInt22 (RealPt int22pt) { sSave(sPSP,int_22,int22pt); };
@ -455,8 +458,8 @@ public:
void SetDirID(Bit16u entry) { sSave(sDTA,dirID,entry); };
void SetDirIDCluster(Bit16u entry) { sSave(sDTA,dirCluster,entry); };
Bit16u GetDirID(void) { return sGet(sDTA,dirID); };
Bit16u GetDirIDCluster(void) { return sGet(sDTA,dirCluster); };
Bit16u GetDirID(void) { return (Bit16u)sGet(sDTA,dirID); };
Bit16u GetDirIDCluster(void) { return (Bit16u)sGet(sDTA,dirCluster); };
private:
#ifdef _MSC_VER
#pragma pack(1)
@ -532,14 +535,14 @@ private:
class DOS_MCB : public MemStruct{
public:
DOS_MCB(Bit16u seg) { SetPt(seg); }
void SetFileName(char * _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); }
void GetFileName(char * _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;}
void SetFileName(char const * const _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); }
void GetFileName(char * const _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;}
void SetType(Bit8u _type) { sSave(sMCB,type,_type);}
void SetSize(Bit16u _size) { sSave(sMCB,size,_size);}
void SetPSPSeg(Bit16u _pspseg) { sSave(sMCB,psp_segment,_pspseg);}
Bit8u GetType(void) { return sGet(sMCB,type);}
Bit16u GetSize(void) { return sGet(sMCB,size);}
Bit16u GetPSPSeg(void) { return sGet(sMCB,psp_segment);}
Bit8u GetType(void) { return (Bit8u)sGet(sMCB,type);}
Bit16u GetSize(void) { return (Bit16u)sGet(sMCB,size);}
Bit16u GetPSPSeg(void) { return (Bit16u)sGet(sMCB,psp_segment);}
private:
#ifdef _MSC_VER
#pragma pack (1)
@ -563,9 +566,9 @@ public:
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); }
Bit8u GetDrive(void) { return (Bit8u)sGet(sSDA,current_drive); }
Bit16u GetPSP(void) { return (Bit16u)sGet(sSDA,current_psp); }
Bit32u GetDTA(void) { return (Bit32u)sGet(sSDA,current_dta); }
private:
@ -620,6 +623,7 @@ struct DOS_Block {
RealPt filenamechar;
RealPt collatingseq;
Bit8u* country;//Will be copied to dos memory. resides in real mem
Bit16u dpb; //Fake Disk parameter system using only the first entry so the drive letter matches
} tables;
Bit16u loaded_codepage;
};

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_system.h,v 1.39 2007/01/21 16:21:22 c2woody Exp $ */
/* $Id: dos_system.h,v 1.40 2007/06/13 07:25:14 qbix79 Exp $ */
#ifndef DOSBOX_DOS_SYSTEM_H
#define DOSBOX_DOS_SYSTEM_H
@ -80,12 +80,10 @@ public:
virtual bool UpdateDateTimeFromHost() { return true; }
void SetDrive(Bit8u drv) { hdrive=drv;}
Bit8u GetDrive(void) { return hdrive;}
Bit8u type;
Bit32u flags;
Bit16u time;
Bit16u date;
Bit16u attr;
Bit32u size;
Bits refCtr;
bool open;
char* name;

View File

@ -114,8 +114,8 @@ INLINE void FPU_SetTag(Bit16u tag){
}
INLINE void FPU_SetCW(Bitu word){
fpu.cw = word;
fpu.cw_mask_all = word | 0x3f;
fpu.cw = (Bit16u)word;
fpu.cw_mask_all = (Bit16u)(word | 0x3f);
fpu.round = (FPU_Round)((word >> 10) & 3);
}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: inout.h,v 1.10 2007/01/08 19:45:37 qbix79 Exp $ */
/* $Id: inout.h,v 1.11 2007/06/12 20:22:07 c2woody Exp $ */
#ifndef DOSBOX_INOUT_H
#define DOSBOX_INOUT_H
@ -72,7 +72,7 @@ INLINE void IO_Write(Bitu port,Bit8u val) {
IO_WriteB(port,val);
}
INLINE Bit8u IO_Read(Bitu port){
return IO_ReadB(port);
return (Bit8u)IO_ReadB(port);
}
#endif

View File

@ -150,7 +150,7 @@ INLINE Bit32u phys_readd(PhysPt addr){
/* These don't check for alignment, better be sure it's correct */
void MEM_BlockWrite(PhysPt pt,void * data,Bitu size);
void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size);
void MEM_BlockRead(PhysPt pt,void * data,Bitu size);
void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size);
void MEM_StrCopy(PhysPt pt,char * data,Bitu size);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: paging.h,v 1.24 2007/01/08 19:45:37 qbix79 Exp $ */
/* $Id: paging.h,v 1.25 2007/06/12 20:22:07 c2woody Exp $ */
#ifndef DOSBOX_PAGING_H
#define DOSBOX_PAGING_H
@ -179,7 +179,7 @@ bool mem_unalignedwrited_checked_x86(PhysPt address,Bit32u val);
INLINE Bit8u mem_readb_inline(PhysPt address) {
Bitu index=(address>>12);
if (paging.tlb.read[index]) return host_readb(paging.tlb.read[index]+address);
else return paging.tlb.handler[index]->readb(address);
else return (Bit8u)paging.tlb.handler[index]->readb(address);
}
INLINE Bit16u mem_readw_inline(PhysPt address) {
@ -187,7 +187,7 @@ INLINE Bit16u mem_readw_inline(PhysPt address) {
Bitu index=(address>>12);
if (paging.tlb.read[index]) return host_readw(paging.tlb.read[index]+address);
else return paging.tlb.handler[index]->readw(address);
else return (Bit16u) paging.tlb.handler[index]->readw(address);
} else return mem_unalignedreadw(address);
}
@ -231,7 +231,7 @@ INLINE Bit16u mem_readw_dyncorex86(PhysPt address) {
Bitu index=(address>>12);
if (paging.tlb.read[index]) return host_readw(paging.tlb.read[index]+address);
else return paging.tlb.handler[index]->readw(address);
else return (Bit16u)paging.tlb.handler[index]->readw(address);
} else return mem_unalignedreadw(address);
}

View File

@ -49,7 +49,7 @@ INLINE Bits PIC_MakeCycles(double amount) {
}
INLINE double PIC_FullIndex(void) {
return PIC_Ticks+PIC_TickIndex();
return PIC_Ticks+(double)PIC_TickIndex();
}
void PIC_ActivateIRQ(Bitu irq);

View File

@ -98,7 +98,7 @@ INLINE PhysPt SegPhys(SegNames index) {
}
INLINE Bit16u SegValue(SegNames index) {
return Segs.val[index];
return (Bit16u)Segs.val[index];
}
INLINE RealPt RealMakeSeg(SegNames index,Bit16u off) {

View File

@ -19,6 +19,12 @@
#ifndef DOSBOX_RENDER_H
#define DOSBOX_RENDER_H
// 0: complex scalers off, scaler cache off, some simple scalers off, memory requirements reduced
// 1: complex scalers off, scaler cache off, all simple scalers on
// 2: complex scalers off, scaler cache on
// 3: complex scalers on
#define RENDER_USE_ADVANCED_SCALERS 3
#include "../src/gui/render_scalers.h"
#define RENDER_SKIP_CACHE 16
@ -63,6 +69,7 @@ typedef struct {
scalerMode_t outMode;
scalerOperation_t op;
bool clearCache;
bool forced;
ScalerLineHandler_t lineHandler;
ScalerLineHandler_t linePalHandler;
ScalerComplexHandler_t complexHandler;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: setup.h,v 1.26 2007/01/08 19:45:37 qbix79 Exp $ */
/* $Id: setup.h,v 1.27 2007/06/14 08:23:46 qbix79 Exp $ */
#ifndef DOSBOX_SETUP_H
#define DOSBOX_SETUP_H
@ -142,8 +142,8 @@ private:
public:
Section(char const * const _sectionname):sectionname(_sectionname) { }
void AddInitFunction(SectionFunction func,bool canchange=false) {initfunctions.push_back(Function_wrapper(func,canchange));}
void AddDestroyFunction(SectionFunction func,bool canchange=false) {destroyfunctions.push_front(Function_wrapper(func,canchange));}
void AddInitFunction(SectionFunction func,bool canchange=false);
void AddDestroyFunction(SectionFunction func,bool canchange=false);
void ExecuteInit(bool initall=true);
void ExecuteDestroy(bool destroyall=true);
const char* GetName() const {return sectionname.c_str();}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: shell.h,v 1.20 2007/01/08 19:59:06 qbix79 Exp $ */
/* $Id: shell.h,v 1.21 2007/06/14 08:23:46 qbix79 Exp $ */
#ifndef DOSBOX_SHELL_H
#define DOSBOX_SHELL_H
@ -77,7 +77,7 @@ public:
void DoCommand(char * cmd);
bool Execute(char * name,char * args);
/* Checks if it matches a hardware-property */
bool CheckConfig(char* cmd,char*line);
bool CheckConfig(char* cmd_in,char*line);
/* Some internal used functions */
char * Which(char * name);
/* Some supported commands */

View File

@ -4,13 +4,15 @@ SUBDIRS = cpu debug dos fpu gui hardware libs ints misc shell platform
bin_PROGRAMS = dosbox
if HAVE_WINDRES
ico_stuff = dosbox_ico.o
endif
dosbox_SOURCES = dosbox.cpp
dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \
ints/libints.a misc/libmisc.a shell/libshell.a hardware/serialport/libserial.a
if HAVE_WINDRES
dosbox_LDADD += dosbox_ico.o
endif
ints/libints.a misc/libmisc.a shell/libshell.a hardware/serialport/libserial.a \
$(ico_stuff)
EXTRA_DIST = dosbox.rc dosbox.ico
dosbox_ico.o: dosbox.rc dosbox.ico

View File

@ -36,7 +36,6 @@ NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_triplet = @host@
@HAVE_WINDRES_TRUE@am__append_1 = dosbox_ico.o
ACLOCAL = @ACLOCAL@
ALSA_CFLAGS = @ALSA_CFLAGS@
ALSA_LIBS = @ALSA_LIBS@
@ -145,10 +144,13 @@ SUBDIRS = cpu debug dos fpu gui hardware libs ints misc shell platform
bin_PROGRAMS = dosbox
@HAVE_WINDRES_TRUE@ico_stuff = dosbox_ico.o
dosbox_SOURCES = dosbox.cpp
dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \
ints/libints.a misc/libmisc.a shell/libshell.a hardware/serialport/libserial.a\
$(am__append_1)
ints/libints.a misc/libmisc.a shell/libshell.a hardware/serialport/libserial.a \
$(ico_stuff)
EXTRA_DIST = dosbox.rc dosbox.ico
subdir = src

View File

@ -1,7 +1,7 @@
SUBDIRS = core_full core_normal core_dyn_x86
SUBDIRS = core_full core_normal core_dyn_x86 core_dynrec
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 core_simple.cpp \
core_dyn_x86.cpp
core_dyn_x86.cpp core_dynrec.cpp

View File

@ -138,13 +138,13 @@ target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
SUBDIRS = core_full core_normal core_dyn_x86
SUBDIRS = core_full core_normal core_dyn_x86 core_dynrec
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 core_simple.cpp \
core_dyn_x86.cpp
core_dyn_x86.cpp core_dynrec.cpp
subdir = src/cpu
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -158,7 +158,7 @@ libcpu_a_LIBADD =
am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \
modrm.$(OBJEXT) core_full.$(OBJEXT) paging.$(OBJEXT) \
core_normal.$(OBJEXT) core_simple.$(OBJEXT) \
core_dyn_x86.$(OBJEXT)
core_dyn_x86.$(OBJEXT) core_dynrec.$(OBJEXT)
libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
@ -166,7 +166,8 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp
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)/core_dynrec.Po ./$(DEPDIR)/core_full.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/core_normal.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/core_simple.Po ./$(DEPDIR)/cpu.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/flags.Po ./$(DEPDIR)/modrm.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/paging.Po
@ -217,6 +218,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dyn_x86.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dynrec.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@

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: callback.cpp,v 1.36 2007/01/08 19:45:38 qbix79 Exp $ */
/* $Id: callback.cpp,v 1.37 2007/06/03 16:46:33 c2woody Exp $ */
#include <stdlib.h>
#include <string.h>
@ -155,6 +155,16 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
}
phys_writeb(physAddress+0x00,(Bit8u)0xCB); //A RETF Instruction
return (use_cb?5:1);
case CB_RETF8:
if (use_cb) {
phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x02, callback); //The immediate word
physAddress+=4;
}
phys_writeb(physAddress+0x00,(Bit8u)0xCA); //A RETF 8 Instruction
phys_writew(physAddress+0x01,(Bit16u)0x0008);
return (use_cb?7:3);
case CB_IRET:
if (use_cb) {
phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4
@ -300,6 +310,18 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
phys_writeb(physAddress+0x0e,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x0f,(Bit8u)0xcf); //An IRET Instruction
return (use_cb?0x14:0x10);
case CB_MOUSE:
phys_writew(physAddress+0x00,(Bit16u)0x07eb); // jmp i33hd
physAddress+=9;
// jump here to (i33hd):
if (use_cb) {
phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x02,callback); //The immediate word
physAddress+=4;
}
phys_writeb(physAddress+0x00,(Bit8u)0xCF); //An IRET Instruction
return (use_cb?0x0e:0x0a);
case CB_INT16:
phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI
if (use_cb) {

View File

@ -27,6 +27,11 @@
#include <stddef.h>
#include <stdlib.h>
#if defined (WIN32)
#include <windows.h>
#include <winbase.h>
#endif
#if (C_HAVE_MPROTECT)
#include <sys/mman.h>
@ -45,7 +50,7 @@
#include "inout.h"
#include "fpu.h"
#define CACHE_MAXSIZE (4096*2)
#define CACHE_MAXSIZE (4096*3)
#define CACHE_TOTAL (1024*1024*8)
#define CACHE_PAGES (512)
#define CACHE_BLOCKS (64*1024)
@ -258,12 +263,11 @@ Bits CPU_Core_Dyn_X86_Run(void) {
/* Determine the linear address of CS:EIP */
restart_core:
PhysPt ip_point=SegPhys(cs)+reg_eip;
Bitu ip_page=ip_point>>12;
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
CodePageHandler * chandler=0;
if (GCC_UNLIKELY(MakeCodePage(ip_page,chandler))) {
if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) {
CPU_Exception(cpu.exception.which,cpu.exception.error);
goto restart_core;
}

View File

@ -66,7 +66,7 @@ public:
}
}
bool InvalidateRange(Bitu start,Bitu end) {
Bits index=1+(start>>DYN_HASH_SHIFT);
Bits index=1+(end>>DYN_HASH_SHIFT);
bool is_current_block=false;
Bit32u ip_point=SegPhys(cs)+reg_eip;
ip_point=((paging.tlb.phys_page[ip_point>>12]-phys_page)<<12)+(ip_point&0xfff);
@ -457,8 +457,15 @@ static void cache_init(bool enable) {
}
}
if (cache_code_start_ptr==NULL) {
#if defined (WIN32)
cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (!cache_code_start_ptr)
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#else
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
if(!cache_code_start_ptr) E_Exit("Allocating dynamic cache failed");
#endif
if(!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
cache_code=(Bit8u*)(((int)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //MEM LEAK. store old pointer if you want to free it.
@ -510,6 +517,8 @@ static void cache_close(void) {
cache_blocks = NULL;
}
if (cache_code_start_ptr != NULL) {
### care: under windows VirtualFree() has to be used if
### VirtualAlloc was used for memory allocation
free(cache_code_start_ptr);
cache_code_start_ptr = NULL;
}

View File

@ -50,10 +50,11 @@ static struct DynDecode {
DynReg * segprefix;
} decode;
static bool MakeCodePage(Bitu lin_page,CodePageHandler * &cph) {
static bool MakeCodePage(Bitu lin_addr,CodePageHandler * &cph) {
Bit8u rdval;
//Ensure page contains memory:
if (GCC_UNLIKELY(mem_readb_checked_x86(lin_page << 12,&rdval))) return true;
if (GCC_UNLIKELY(mem_readb_checked_x86(lin_addr,&rdval))) return true;
Bitu lin_page=lin_addr >> 12;
PageHandler * handler=paging.tlb.handler[lin_page];
if (handler->flags & PFLAG_HASCODE) {
cph=( CodePageHandler *)handler;
@ -99,8 +100,10 @@ static Bit8u decode_fetchb(void) {
/* Advance to the next page */
decode.active_block->page.end=4095;
/* trigger possible page fault here */
mem_readb((++decode.page.first) << 12);
MakeCodePage(decode.page.first,decode.page.code);
decode.page.first++;
Bitu fetchaddr=decode.page.first << 12;
mem_readb(fetchaddr);
MakeCodePage(fetchaddr,decode.page.code);
CacheBlock * newblock=cache_getblock();
decode.active_block->crossblock=newblock;
newblock->crossblock=decode.active_block;
@ -142,7 +145,7 @@ static Bit32u decode_fetchd(void) {
#define START_WMMEM 64
static void INLINE decode_increase_wmapmask(Bitu size) {
static INLINE void decode_increase_wmapmask(Bitu size) {
Bitu mapidx;
CacheBlock* activecb=decode.active_block;
if (GCC_UNLIKELY(!activecb->cache.wmapmask)) {
@ -252,7 +255,8 @@ static INLINE void dyn_set_eip_end(void) {
static INLINE void dyn_set_eip_end(DynReg * endreg) {
gen_protectflags();
gen_dop_word(DOP_MOV,cpu.code.big,DREG(TMPW),DREG(EIP));
if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EIP));
else gen_extend_word(false,DREG(TMPW),DREG(EIP));
gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(TMPW),decode.code-decode.code_start);
}
@ -923,7 +927,7 @@ static void dyn_pop(DynReg * dynreg,bool checked=true) {
}
}
static void INLINE dyn_get_modrm(void) {
static INLINE void dyn_get_modrm(void) {
decode.modrm.val=decode_fetchb();
decode.modrm.mod=(decode.modrm.val >> 6) & 3;
decode.modrm.reg=(decode.modrm.val >> 3) & 7;
@ -1183,7 +1187,7 @@ static void dyn_mov_ebgb(void) {
DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
if (decode.modrm.mod<3) {
dyn_fill_ea();
dyn_write_byte_release(DREG(EA),rm_reg,rm_regi);
dyn_write_byte_release(DREG(EA),rm_reg,rm_regi==4);
} else {
gen_dop_byte(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,rm_regi);
}
@ -1810,7 +1814,8 @@ static void dyn_call_near_imm(void) {
dyn_set_eip_end(DREG(TMPW));
dyn_push(DREG(TMPW));
gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(TMPW),imm);
gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),DREG(TMPW));
if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(EIP),DREG(TMPW));
else gen_extend_word(false,DREG(EIP),DREG(TMPW));
dyn_reduce_cycles();
dyn_save_critical_regs();
gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
@ -2182,14 +2187,14 @@ restart_prefix:
gen_releasereg(DREG(ESP));
dyn_flags_gen_to_host();
gen_call_function((void *)&CPU_PUSHF,"%Rd%Id",DREG(TMPB),decode.big_op);
if (cpu.pmode) dyn_check_bool_exception(DREG(TMPB));
dyn_check_bool_exception(DREG(TMPB));
gen_releasereg(DREG(TMPB));
break;
case 0x9d: //POPF
gen_releasereg(DREG(ESP));
gen_releasereg(DREG(FLAGS));
gen_call_function((void *)&CPU_POPF,"%Rd%Id",DREG(TMPB),decode.big_op);
if (cpu.pmode) dyn_check_bool_exception(DREG(TMPB));
dyn_check_bool_exception(DREG(TMPB));
dyn_flags_host_to_gen();
gen_releasereg(DREG(TMPB));
break;
@ -2556,7 +2561,7 @@ restart_prefix:
dyn_save_critical_regs();
gen_call_function(
decode.modrm.reg == 3 ? (void*)&CPU_CALL : (void*)&CPU_JMP,
decode.big_op ? (char *)"%Id%Drw%Drd%Drd" : (char *)"%Id%Drw%Drw%Drd",
decode.big_op ? "%Id%Drw%Drd%Drd" : "%Id%Drw%Drw%Drd",
decode.big_op,DREG(EA),DREG(TMPW),DREG(TMPB));
dyn_flags_host_to_gen();
goto core_close_block;
@ -2589,7 +2594,6 @@ illegalopcode:
dyn_closeblock();
goto finish_block;
#if (C_DEBUG)
illegalopcodefull:
dyn_set_eip_last();
dyn_reduce_cycles();
dyn_save_critical_regs();

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2005 The DOSBox Team
* Copyright (C) 2002-2007 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
@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dyn_fpu.h,v 1.2 2006/09/19 16:27:58 c2woody Exp $ */
/* $Id: dyn_fpu.h,v 1.3 2007/06/14 17:47:24 c2woody Exp $ */
#include "dosbox.h"
#if C_FPU

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2005 The DOSBox Team
* Copyright (C) 2002-2007 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
@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dyn_fpu_dh.h,v 1.2 2006/11/11 14:42:38 c2woody Exp $ */
/* $Id: dyn_fpu_dh.h,v 1.4 2007/06/14 17:47:24 c2woody Exp $ */
#include "dosbox.h"
#if C_FPU
@ -65,7 +65,7 @@ static void FPU_FLDCW_DH(PhysPt addr){
}
static void FPU_FNSTCW_DH(PhysPt addr){
mem_writew(addr,dyn_dh_fpu.cw);
mem_writew(addr,(Bit16u)(dyn_dh_fpu.cw&0xffff));
}
static void FPU_FNINIT_DH(void){

View File

@ -163,7 +163,7 @@ static GenReg * FindDynReg(DynReg * dynreg,bool stale=false) {
genreg->Load(dynreg,stale);
return genreg;
}
if (genreg->last_used<first_used) {
if (genreg->last_used<(Bitu)first_used) {
first_used=genreg->last_used;
first_index=i;
}
@ -176,7 +176,7 @@ static GenReg * FindDynReg(DynReg * dynreg,bool stale=false) {
genreg->Load(dynreg,stale);
return genreg;
}
if (genreg->last_used<first_used) {
if (genreg->last_used<(Bitu)first_used) {
first_used=genreg->last_used;
first_index=i;
}
@ -721,11 +721,11 @@ static void gen_dshift_cl(bool dword,bool left,DynReg * dr1,DynReg * dr2,DynReg
dr1->flags|=DYNFLG_CHANGED;
}
static void gen_call_function(void * func,char * ops,...) {
static void gen_call_function(void * func,char const* ops,...) {
Bits paramcount=0;
bool release_flags=false;
struct ParamInfo {
char * line;
const char * line;
Bitu value;
} pinfo[32];
ParamInfo * retparam=0;
@ -743,10 +743,10 @@ static void gen_call_function(void * func,char * ops,...) {
Bits pindex=0;
while (*ops) {
if (*ops=='%') {
pinfo[pindex].line=ops+1;
pinfo[pindex].line=ops+1;
pinfo[pindex].value=va_arg(params,Bitu);
#if defined (MACOSX)
char * scan=pinfo[pindex].line;
const char * scan=pinfo[pindex].line;
if ((*scan=='I') || (*scan=='D')) stack_used+=4;
else if (*scan=='F') free_flags=true;
#endif
@ -777,7 +777,7 @@ static void gen_call_function(void * func,char * ops,...) {
paramcount=0;
while (pindex) {
pindex--;
char * scan=pinfo[pindex].line;
const char * scan=pinfo[pindex].line;
switch (*scan++) {
case 'I': /* immediate value */
paramcount++;

323
src/cpu/core_dynrec.cpp Normal file
View File

@ -0,0 +1,323 @@
/*
* Copyright (C) 2002-2007 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 "dosbox.h"
#if (C_DYNREC)
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#if defined (WIN32)
#include <windows.h>
#include <winbase.h>
#endif
#if (C_HAVE_MPROTECT)
#include <sys/mman.h>
#include <limits.h>
#ifndef PAGESIZE
#define PAGESIZE 4096
#endif
#endif /* C_HAVE_MPROTECT */
#include "callback.h"
#include "regs.h"
#include "mem.h"
#include "cpu.h"
#include "debug.h"
#include "paging.h"
#include "inout.h"
#include "lazyflags.h"
#define CACHE_MAXSIZE (4096)
#define CACHE_TOTAL (1024*1024*8)
#define CACHE_PAGES (512)
#define CACHE_BLOCKS (128*1024)
#define CACHE_ALIGN (16)
#define DYN_HASH_SHIFT (4)
#define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT)
#define DYN_LINKS (16)
#if 0
#define DYN_LOG LOG_MSG
#else
#define DYN_LOG
#endif
#if C_FPU
#define CPU_FPU 1 //Enable FPU escape instructions
#endif
// the emulated x86 registers
#define DRC_REG_EAX 0
#define DRC_REG_ECX 1
#define DRC_REG_EDX 2
#define DRC_REG_EBX 3
#define DRC_REG_ESP 4
#define DRC_REG_EBP 5
#define DRC_REG_ESI 6
#define DRC_REG_EDI 7
// the emulated x86 segment registers
#define DRC_SEG_ES 0
#define DRC_SEG_CS 1
#define DRC_SEG_SS 2
#define DRC_SEG_DS 3
#define DRC_SEG_FS 4
#define DRC_SEG_GS 5
// access to a general register
#define DRCD_REG(reg) (&cpu_regs.regs[reg].dword)
// access to a segment register
#define DRCD_SEG_VAL(seg) (&Segs.val[seg])
// access to the physical value of a segment register/selector
#define DRCD_SEG_PHYS(seg) (&Segs.phys[seg])
// access to an 8bit general register
#define DRCD_REG_BYTE(reg,idx) (&cpu_regs.regs[reg].byte[idx])
// access to 16/32bit general registers
#define DRCD_REG_WORD(reg,dwrd) ((dwrd)?((void*)(&cpu_regs.regs[reg].dword)):((void*)(&cpu_regs.regs[reg].word)))
enum BlockReturn {
BR_Normal=0,
BR_Cycles,
BR_Link1,BR_Link2,
BR_Opcode,
#if (C_DEBUG)
BR_OpcodeFull,
#endif
BR_Iret,
BR_CallBack,
BR_SMCBlock
};
// identificator to signal self-modification of the currently executed block
#define SMC_CURRENT_BLOCK 0xffff
static void IllegalOptionDynrec(const char* msg) {
E_Exit("DynrecCore: illegal option in %s",msg);
}
static struct {
BlockReturn (*runcode)(Bit8u*); // points to code that can start a block
Bitu callback; // the occurred callback
Bitu readdata; // spare space used when reading from memory
Bit32u protected_regs[8]; // space to save/restore register values
} core_dynrec;
#include "core_dynrec/cache.h"
#define X86 0x01
#define X86_64 0x02
#define MIPSEL32 0x03
#if C_TARGETCPU == X86_64
#include "core_dynrec/risc_x64.h"
#elif C_TARGETCPU == X86
#include "core_dynrec/risc_x86.h"
#elif C_TARGETCPU == MIPSEL32
#include "core_dynrec/risc_mipsel32.h"
#endif
#include "core_dynrec/decoder.h"
CacheBlockDynRec * LinkBlocks(BlockReturn ret) {
CacheBlockDynRec * block=NULL;
// the last instruction was a control flow modifying instruction
Bitu temp_ip=SegPhys(cs)+reg_eip;
Bitu temp_page=temp_ip >> 12;
CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)paging.tlb.handler[temp_page];
if (temp_handler->flags & PFLAG_HASCODE) {
// see if the target is an already translated block
block=temp_handler->FindCacheBlock(temp_ip & 4095);
if (!block) return NULL;
// found it, link the current block to
cache.block.running->LinkTo(ret==BR_Link2,block);
return block;
}
return NULL;
}
/*
The core tries to find the block that should be executed next.
If such a block is found, it is run, otherwise the instruction
stream starting at ip_point is translated (see decoder.h) and
makes up a new code block that will be run.
When control is returned to CPU_Core_Dynrec_Run (which might
be right after the block is run, or somewhen long after that
due to the direct cacheblock linking) the returncode decides
the next action. This might be continuing the translation and
execution process, or returning from the core etc.
*/
Bits CPU_Core_Dynrec_Run(void) {
for (;;) {
// Determine the linear address of CS:EIP
PhysPt ip_point=SegPhys(cs)+reg_eip;
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
CodePageHandlerDynRec * chandler=0;
// see if the current page is present and contains code
if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) {
// page not present, throw the exception
CPU_Exception(cpu.exception.which,cpu.exception.error);
continue;
}
// page doesn't contain code or is special
if (GCC_UNLIKELY(!chandler)) return CPU_Core_Normal_Run();
// find correct Dynamic Block to run
CacheBlockDynRec * block=chandler->FindCacheBlock(ip_point&4095);
if (!block) {
// no block found, thus translate the instruction stream
// unless the instruction is known to be modified
if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) {
// translate up to 32 instructions
block=CreateCacheBlock(chandler,ip_point,32);
} else {
// let the normal core handle this instruction to avoid zero-sized blocks
Bitu old_cycles=CPU_Cycles;
CPU_Cycles=1;
Bits nc_retcode=CPU_Core_Normal_Run();
if (!nc_retcode) {
CPU_Cycles=old_cycles-1;
continue;
}
CPU_CycleLeft+=old_cycles;
return nc_retcode;
}
}
run_block:
cache.block.running=0;
// now we're ready to run the dynamic code block
// BlockReturn ret=((BlockReturn (*)(void))(block->cache.start))();
BlockReturn ret=core_dynrec.runcode(block->cache.start);
switch (ret) {
case BR_Iret:
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
if (!GETFLAG(TF)) break;
// trapflag is set, switch to the trap-aware decoder
cpudecoder=CPU_Core_Dynrec_Trap_Run;
return CBRET_NONE;
case BR_Normal:
// the block was exited due to a non-predictable control flow
// modifying instruction (like ret) or some nontrivial cpu state
// changing instruction (for example switch to/from pmode),
// or the maximal number of instructions to translate was reached
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
break;
case BR_Cycles:
// cycles went negative, return from the core to handle
// external events, schedule the pic...
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
return CBRET_NONE;
case BR_CallBack:
// the callback code is executed in dosbox.conf, return the callback number
FillFlags();
return core_dynrec.callback;
case BR_SMCBlock:
// LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip);
cpu.exception.which=0;
// fallthrough, let the normal core handle the block-modifying instruction
case BR_Opcode:
// some instruction has been encountered that could not be translated
// (thus it is not part of the code block), the normal core will
// handle this instruction
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:
block=LinkBlocks(ret);
if (block) goto run_block;
break;
default:
E_Exit("Invalid return code %d", ret);
}
}
return CBRET_NONE;
}
Bits CPU_Core_Dynrec_Trap_Run(void) {
Bits oldCycles = CPU_Cycles;
CPU_Cycles = 1;
cpu.trap_skip = false;
// let the normal core execute the next (only one!) instruction
Bits ret=CPU_Core_Normal_Run();
// trap to int1 unless the last instruction deferred this
// (allows hardware interrupts to be served without interaction)
if (!cpu.trap_skip) CPU_HW_Interrupt(1);
CPU_Cycles = oldCycles-1;
// continue (either the trapflag was clear anyways, or the int1 cleared it)
cpudecoder = &CPU_Core_Dynrec_Run;
return ret;
}
void CPU_Core_Dynrec_Init(void) {
}
void CPU_Core_Dynrec_Cache_Init(bool enable_cache) {
// Initialize code cache and dynamic blocks
cache_init(enable_cache);
}
void CPU_Core_Dynrec_Cache_Close(void) {
cache_close();
}
#endif

View File

@ -0,0 +1,2 @@
noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \
dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h

View File

@ -0,0 +1,332 @@
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../../..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_triplet = @host@
ACLOCAL = @ACLOCAL@
ALSA_CFLAGS = @ALSA_CFLAGS@
ALSA_LIBS = @ALSA_LIBS@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
GREP = @GREP@
HAVE_WINDRES_FALSE = @HAVE_WINDRES_FALSE@
HAVE_WINDRES_TRUE = @HAVE_WINDRES_TRUE@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SDL_CFLAGS = @SDL_CFLAGS@
SDL_CONFIG = @SDL_CONFIG@
SDL_LIBS = @SDL_LIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
WINDRES = @WINDRES@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \
dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h
subdir = src/cpu/core_dynrec
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
DIST_SOURCES =
HEADERS = $(noinst_HEADERS)
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.in Makefile.am
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu src/cpu/core_dynrec/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ../../..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic ctags \
distclean distclean-generic distclean-tags distdir dvi dvi-am \
info info-am install install-am install-data install-data-am \
install-exec install-exec-am install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
uninstall uninstall-am uninstall-info-am
# 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.
.NOEXPORT:

642
src/cpu/core_dynrec/cache.h Normal file
View File

@ -0,0 +1,642 @@
/*
* Copyright (C) 2002-2007 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.
*/
class CodePageHandlerDynRec; // forward
// basic cache block representation
class CacheBlockDynRec {
public:
void Clear(void);
// link this cache block to another block, index specifies the code
// path (always zero for unconditional links, 0/1 for conditional ones
void LinkTo(Bitu index,CacheBlockDynRec * toblock) {
assert(toblock);
link[index].to=toblock;
link[index].next=toblock->link[index].from; // set target block
toblock->link[index].from=this; // remember who links me
}
struct {
Bit16u start,end; // where in the page is the original code
CodePageHandlerDynRec * handler; // page containing this code
} page;
struct {
Bit8u * start; // where in the cache are we
Bitu size;
CacheBlockDynRec * next;
// writemap masking maskpointer/start/length
// to allow holes in the writemap
Bit8u * wmapmask;
Bit16u maskstart;
Bit16u masklen;
} cache;
struct {
Bitu index;
CacheBlockDynRec * next;
} hash;
struct {
CacheBlockDynRec * to; // this block can transfer control to the to-block
CacheBlockDynRec * next;
CacheBlockDynRec * from; // the from-block can transfer control to this block
} link[2]; // maximal two links (conditional jumps)
CacheBlockDynRec * crossblock;
};
static struct {
struct {
CacheBlockDynRec * first; // the first cache block in the list
CacheBlockDynRec * active; // the current cache block
CacheBlockDynRec * free; // pointer to the free list
CacheBlockDynRec * running; // the last block that was entered for execution
} block;
Bit8u * pos; // position in the cache block
CodePageHandlerDynRec * free_pages; // pointer to the free list
CodePageHandlerDynRec * used_pages; // pointer to the list of used pages
CodePageHandlerDynRec * last_page; // the last used page
} cache;
static CacheBlockDynRec link_blocks[2]; // default linking (specially marked)
// the CodePageHandlerDynRec class provides access to the contained
// cache blocks and intercepts writes to the code for special treatment
class CodePageHandlerDynRec : public PageHandler {
public:
CodePageHandlerDynRec() {
invalidation_map=NULL;
}
void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
// initialize this codepage handler
phys_page=_phys_page;
// save the old pagehandler to provide direct read access to the memory,
// and to be able to restore it later on
old_pagehandler=_old_pagehandler;
// adjust flags
flags=old_pagehandler->flags|PFLAG_HASCODE;
flags&=~PFLAG_WRITEABLE;
active_blocks=0;
active_count=16;
// initialize the maps with zero (no cache blocks as well as code present)
memset(&hash_map,0,sizeof(hash_map));
memset(&write_map,0,sizeof(write_map));
if (invalidation_map!=NULL) {
free(invalidation_map);
invalidation_map=NULL;
}
}
// clear out blocks that contain code which has been modified
bool InvalidateRange(Bitu start,Bitu end) {
Bits index=1+(end>>DYN_HASH_SHIFT);
bool is_current_block=false; // if the current block is modified, it has to be exited as soon as possible
Bit32u ip_point=SegPhys(cs)+reg_eip;
ip_point=((paging.tlb.phys_page[ip_point>>12]-phys_page)<<12)+(ip_point&0xfff);
while (index>=0) {
Bitu map=0;
// see if there is still some code in the range
for (Bitu count=start;count<=end;count++) map+=write_map[count];
if (!map) return is_current_block; // no more code, finished
CacheBlockDynRec * block=hash_map[index];
while (block) {
CacheBlockDynRec * nextblock=block->hash.next;
// test if this block is in the range
if (start<=block->page.end && end>=block->page.start) {
if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true;
block->Clear(); // clear the block, decrements the write_map accordingly
}
block=nextblock;
}
index--;
}
return is_current_block;
}
// the following functions will clean all cache blocks that are invalid now due to the write
void writeb(PhysPt addr,Bitu val){
addr&=4095;
if (host_readb(hostmem+addr)==(Bit8u)val) return;
host_writeb(hostmem+addr,val);
// see if there's code where we are writing to
if (!*(Bit8u*)&write_map[addr]) {
if (active_blocks) return; // still some blocks in this page
active_count--;
if (!active_count) Release(); // delay page releasing until active_count is zero
return;
} else if (!invalidation_map) {
invalidation_map=(Bit8u*)malloc(4096);
memset(invalidation_map,0,4096);
}
invalidation_map[addr]++;
InvalidateRange(addr,addr);
}
void writew(PhysPt addr,Bitu val){
addr&=4095;
if (host_readw(hostmem+addr)==(Bit16u)val) return;
host_writew(hostmem+addr,val);
// see if there's code where we are writing to
if (!*(Bit16u*)&write_map[addr]) {
if (active_blocks) return; // still some blocks in this page
active_count--;
if (!active_count) Release(); // delay page releasing until active_count is zero
return;
} else if (!invalidation_map) {
invalidation_map=(Bit8u*)malloc(4096);
memset(invalidation_map,0,4096);
}
(*(Bit16u*)&invalidation_map[addr])+=0x101;
InvalidateRange(addr,addr+1);
}
void writed(PhysPt addr,Bitu val){
addr&=4095;
if (host_readd(hostmem+addr)==(Bit32u)val) return;
host_writed(hostmem+addr,val);
// see if there's code where we are writing to
if (!*(Bit32u*)&write_map[addr]) {
if (active_blocks) return; // still some blocks in this page
active_count--;
if (!active_count) Release(); // delay page releasing until active_count is zero
return;
} else if (!invalidation_map) {
invalidation_map=(Bit8u*)malloc(4096);
memset(invalidation_map,0,4096);
}
(*(Bit32u*)&invalidation_map[addr])+=0x1010101;
InvalidateRange(addr,addr+3);
}
bool writeb_checked(PhysPt addr,Bitu val) {
addr&=4095;
if (host_readb(hostmem+addr)==(Bit8u)val) return false;
// see if there's code where we are writing to
if (!*(Bit8u*)&write_map[addr]) {
if (!active_blocks) {
// no blocks left in this page, still delay the page releasing a bit
active_count--;
if (!active_count) Release();
}
} else {
if (!invalidation_map) {
invalidation_map=(Bit8u*)malloc(4096);
memset(invalidation_map,0,4096);
}
invalidation_map[addr]++;
if (InvalidateRange(addr,addr)) {
cpu.exception.which=SMC_CURRENT_BLOCK;
return true;
}
}
host_writeb(hostmem+addr,val);
return false;
}
bool writew_checked(PhysPt addr,Bitu val) {
addr&=4095;
if (host_readw(hostmem+addr)==(Bit16u)val) return false;
// see if there's code where we are writing to
if (!*(Bit16u*)&write_map[addr]) {
if (!active_blocks) {
// no blocks left in this page, still delay the page releasing a bit
active_count--;
if (!active_count) Release();
}
} else {
if (!invalidation_map) {
invalidation_map=(Bit8u*)malloc(4096);
memset(invalidation_map,0,4096);
}
(*(Bit16u*)&invalidation_map[addr])+=0x101;
if (InvalidateRange(addr,addr+1)) {
cpu.exception.which=SMC_CURRENT_BLOCK;
return true;
}
}
host_writew(hostmem+addr,val);
return false;
}
bool writed_checked(PhysPt addr,Bitu val) {
addr&=4095;
if (host_readd(hostmem+addr)==(Bit32u)val) return false;
// see if there's code where we are writing to
if (!*(Bit32u*)&write_map[addr]) {
if (!active_blocks) {
// no blocks left in this page, still delay the page releasing a bit
active_count--;
if (!active_count) Release();
}
} else {
if (!invalidation_map) {
invalidation_map=(Bit8u*)malloc(4096);
memset(invalidation_map,0,4096);
}
(*(Bit32u*)&invalidation_map[addr])+=0x1010101;
if (InvalidateRange(addr,addr+3)) {
cpu.exception.which=SMC_CURRENT_BLOCK;
return true;
}
}
host_writed(hostmem+addr,val);
return false;
}
// add a cache block to this page and note it in the hash map
void AddCacheBlock(CacheBlockDynRec * block) {
Bitu index=1+(block->page.start>>DYN_HASH_SHIFT);
block->hash.next=hash_map[index]; // link to old block at index from the new block
block->hash.index=index;
hash_map[index]=block; // put new block at hash position
block->page.handler=this;
active_blocks++;
}
// there's a block whose code started in a different page
void AddCrossBlock(CacheBlockDynRec * block) {
block->hash.next=hash_map[0];
block->hash.index=0;
hash_map[0]=block;
block->page.handler=this;
active_blocks++;
}
// remove a cache block
void DelCacheBlock(CacheBlockDynRec * block) {
active_blocks--;
active_count=16;
CacheBlockDynRec * * bwhere=&hash_map[block->hash.index];
while (*bwhere!=block) {
bwhere=&((*bwhere)->hash.next);
//Will crash if a block isn't found, which should never happen.
}
*bwhere=block->hash.next;
// remove the cleared block from the write map
if (GCC_UNLIKELY(block->cache.wmapmask!=NULL)) {
// first part is not influenced by the mask
for (Bitu i=block->page.start;i<block->cache.maskstart;i++) {
if (write_map[i]) write_map[i]--;
}
Bitu maskct=0;
// last part sticks to the writemap mask
for (Bitu i=block->cache.maskstart;i<=block->page.end;i++,maskct++) {
if (write_map[i]) {
// only adjust writemap if it isn't masked
if ((maskct>=block->cache.masklen) || (!block->cache.wmapmask[maskct])) write_map[i]--;
}
}
free(block->cache.wmapmask);
block->cache.wmapmask=NULL;
} else {
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); // revert to old handler
PAGING_ClearTLB();
// remove page from the lists
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) {
// clear out all cache blocks in this page
for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) {
CacheBlockDynRec * block=hash_map[index];
while (block) {
CacheBlockDynRec * nextblock=block->hash.next;
block->page.handler=0; // no need, full clear
block->Clear();
block=nextblock;
}
}
Release(); // now can release this page
}
CacheBlockDynRec * FindCacheBlock(Bitu start) {
CacheBlockDynRec * block=hash_map[1+(start>>DYN_HASH_SHIFT)];
// see if there's a cache block present at the start address
while (block) {
if (block->page.start==start) return block; // found
block=block->hash.next;
}
return 0; // none found
}
HostPt GetHostReadPt(Bitu phys_page) {
hostmem=old_pagehandler->GetHostReadPt(phys_page);
return hostmem;
}
HostPt GetHostWritePt(Bitu phys_page) {
return GetHostReadPt( phys_page );
}
public:
// the write map, there are write_map[i] cache blocks that cover the byte at address i
Bit8u write_map[4096];
Bit8u * invalidation_map;
CodePageHandlerDynRec * next, * prev; // page linking
private:
PageHandler * old_pagehandler;
// hash map to quickly find the cache blocks in this page
CacheBlockDynRec * hash_map[1+DYN_PAGE_HASH];
Bitu active_blocks; // the number of cache blocks in this page
Bitu active_count; // delaying parameter to not immediately release a page
HostPt hostmem;
Bitu phys_page;
};
static INLINE void cache_addunusedblock(CacheBlockDynRec * block) {
// block has become unused, add it to the freelist
block->cache.next=cache.block.free;
cache.block.free=block;
}
static CacheBlockDynRec * cache_getblock(void) {
// get a free cache block and advance the free pointer
CacheBlockDynRec * ret=cache.block.free;
if (!ret) E_Exit("Ran out of CacheBlocks" );
cache.block.free=ret->cache.next;
ret->cache.next=0;
return ret;
}
void CacheBlockDynRec::Clear(void) {
Bitu ind;
// check if this is not a cross page block
if (hash.index) for (ind=0;ind<2;ind++) {
CacheBlockDynRec * fromlink=link[ind].from;
link[ind].from=0;
while (fromlink) {
CacheBlockDynRec * nextlink=fromlink->link[ind].next;
// clear the next-link and let the block point to the standard linkcode
fromlink->link[ind].next=0;
fromlink->link[ind].to=&link_blocks[ind];
fromlink=nextlink;
}
if (link[ind].to!=&link_blocks[ind]) {
// not linked to the standard linkcode, find the block that links to this block
CacheBlockDynRec * * wherelink=&link[ind].to->link[ind].from;
while (*wherelink != this && *wherelink) {
wherelink = &(*wherelink)->link[ind].next;
}
// now remove the link
if(*wherelink)
*wherelink = (*wherelink)->link[ind].next;
else {
LOG(LOG_CPU,LOG_ERROR)("Cache anomaly. please investigate");
}
}
} else
cache_addunusedblock(this);
if (crossblock) {
// clear out the crossblock (in the page before) as well
crossblock->crossblock=0;
crossblock->Clear();
crossblock=0;
}
if (page.handler) {
// clear out the code page handler
page.handler->DelCacheBlock(this);
page.handler=0;
}
if (cache.wmapmask){
free(cache.wmapmask);
cache.wmapmask=NULL;
}
}
static CacheBlockDynRec * cache_openblock(void) {
CacheBlockDynRec * block=cache.block.active;
// check for enough space in this block
Bitu size=block->cache.size;
CacheBlockDynRec * nextblock=block->cache.next;
if (block->page.handler)
block->Clear();
// block size must be at least CACHE_MAXSIZE
while (size<CACHE_MAXSIZE) {
if (!nextblock)
goto skipresize;
// merge blocks
size+=nextblock->cache.size;
CacheBlockDynRec * tempblock=nextblock->cache.next;
if (nextblock->page.handler)
nextblock->Clear();
// block is free now
cache_addunusedblock(nextblock);
nextblock=tempblock;
}
skipresize:
// adjust parameters and open this block
block->cache.size=size;
block->cache.next=nextblock;
cache.pos=block->cache.start;
return block;
}
static void cache_closeblock(void) {
CacheBlockDynRec * block=cache.block.active;
// links point to the default linking code
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 alignment
Bitu written=(Bitu)(cache.pos-block->cache.start);
if (written>block->cache.size) {
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;
CacheBlockDynRec * newblock=cache_getblock();
// align block now to CACHE_ALIGN
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->cache.next) {
// LOG_MSG("Cache full restarting");
cache.block.active=cache.block.first;
} else {
cache.block.active=block->cache.next;
}
}
// place an 8bit value into the cache
static INLINE void cache_addb(Bit8u val) {
*cache.pos++=val;
}
// place a 16bit value into the cache
static INLINE void cache_addw(Bit16u val) {
*(Bit16u*)cache.pos=val;
cache.pos+=2;
}
// place a 32bit value into the cache
static INLINE void cache_addd(Bit32u val) {
*(Bit32u*)cache.pos=val;
cache.pos+=4;
}
// place a 64bit value into the cache
static INLINE void cache_addq(Bit64u val) {
*(Bit64u*)cache.pos=val;
cache.pos+=8;
}
static void dyn_return(BlockReturn retcode,bool ret_exception);
static void dyn_run_code(void);
// cache memory pointers, to be malloc'd later
static Bit8u * cache_code_start_ptr=NULL;
static Bit8u * cache_code=NULL;
static Bit8u * cache_code_link_blocks=NULL;
static CacheBlockDynRec * cache_blocks=NULL;
/* Define temporary pagesize so the MPROTECT case and the regular case share as much code as possible */
#if (C_HAVE_MPROTECT)
#define PAGESIZE_TEMP PAGESIZE
#else
#define PAGESIZE_TEMP 4096
#endif
static bool cache_initialized = false;
static void cache_init(bool enable) {
Bits i;
if (enable) {
// see if cache is already initialized
if (cache_initialized) return;
cache_initialized = true;
if (cache_blocks == NULL) {
// allocate the cache blocks memory
cache_blocks=(CacheBlockDynRec*)malloc(CACHE_BLOCKS*sizeof(CacheBlockDynRec));
if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
memset(cache_blocks,0,sizeof(CacheBlockDynRec)*CACHE_BLOCKS);
cache.block.free=&cache_blocks[0];
// initialize the cache blocks
for (i=0;i<CACHE_BLOCKS-1;i++) {
cache_blocks[i].link[0].to=(CacheBlockDynRec *)1;
cache_blocks[i].link[1].to=(CacheBlockDynRec *)1;
cache_blocks[i].cache.next=&cache_blocks[i+1];
}
}
if (cache_code_start_ptr==NULL) {
// allocate the code cache memory
#if defined (WIN32)
cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (!cache_code_start_ptr)
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#else
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#endif
if(!cache_code_start_ptr) E_Exit("Allocating dynamic cache failed");
// align the cache at a page boundary
cache_code=(Bit8u*)(((long)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //MEM LEAK. store old pointer if you want to free it.
cache_code_link_blocks=cache_code;
cache_code=cache_code+PAGESIZE_TEMP;
#if (C_HAVE_MPROTECT)
if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
LOG_MSG("Setting excute permission on the code cache has failed");
#endif
CacheBlockDynRec * block=cache_getblock();
cache.block.first=block;
cache.block.active=block;
block->cache.start=&cache_code[0];
block->cache.size=CACHE_TOTAL;
block->cache.next=0; // last block in the list
}
// setup the default blocks for block linkage returns
cache.pos=&cache_code_link_blocks[0];
link_blocks[0].cache.start=cache.pos;
// link code that returns with a special return code
dyn_return(BR_Link1,false);
cache.pos=&cache_code_link_blocks[32];
link_blocks[1].cache.start=cache.pos;
// link code that returns with a special return code
dyn_return(BR_Link2,false);
cache.pos=&cache_code_link_blocks[64];
core_dynrec.runcode=(BlockReturn (*)(Bit8u*))cache.pos;
// link_blocks[1].cache.start=cache.pos;
dyn_run_code();
cache.free_pages=0;
cache.last_page=0;
cache.used_pages=0;
// setup the code pages
for (i=0;i<CACHE_PAGES;i++) {
CodePageHandlerDynRec * newpage=new CodePageHandlerDynRec();
newpage->next=cache.free_pages;
cache.free_pages=newpage;
}
}
}
static void cache_close(void) {
/* for (;;) {
if (cache.used_pages) {
CodePageHandler * cpage=cache.used_pages;
CodePageHandler * npage=cache.used_pages->next;
cpage->ClearRelease();
delete cpage;
cache.used_pages=npage;
} else break;
}
if (cache_blocks != NULL) {
free(cache_blocks);
cache_blocks = NULL;
}
if (cache_code_start_ptr != NULL) {
### care: under windows VirtualFree() has to be used if
### VirtualAlloc was used for memory allocation
free(cache_code_start_ptr);
cache_code_start_ptr = NULL;
}
cache_code = NULL;
cache_code_link_blocks = NULL;
cache_initialized = false; */
}

View File

@ -0,0 +1,582 @@
/*
* Copyright (C) 2002-2007 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 "decoder_basic.h"
#include "operators.h"
#include "decoder_opcodes.h"
#include "dyn_fpu.h"
/*
The function CreateCacheBlock translates the instruction stream
until either an unhandled instruction is found, the maximal
number of translated instructions is reached or some critical
instruction is encountered.
*/
static CacheBlockDynRec * CreateCacheBlock(CodePageHandlerDynRec * codepage,PhysPt start,Bitu max_opcodes) {
// initialize a load of variables
decode.code_start=start;
decode.code=start;
decode.page.code=codepage;
decode.page.index=start&4095;
decode.page.wmap=codepage->write_map;
decode.page.invmap=codepage->invalidation_map;
decode.page.first=start >> 12;
decode.active_block=decode.block=cache_openblock();
decode.block->page.start=(Bit16u)decode.page.index;
codepage->AddCacheBlock(decode.block);
InitFlagsOptimization();
// every codeblock that is run sets cache.block.running to itself
// so the block linking knows the last executed block
gen_mov_direct_ptr(&cache.block.running,(DRC_PTR_SIZE_IM)decode.block);
// start with the cycles check
gen_mov_word_to_reg(FC_RETOP,&CPU_Cycles,true);
save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_leqzero(FC_RETOP);
save_info_dynrec[used_save_info_dynrec].type=cycle_check;
used_save_info_dynrec++;
decode.cycles=0;
while (max_opcodes--) {
// Init prefixes
decode.big_addr=cpu.code.big;
decode.big_op=cpu.code.big;
decode.seg_prefix=0;
decode.seg_prefix_used=false;
decode.rep=REP_NONE;
decode.cycles++;
decode.op_start=decode.code;
restart_prefix:
Bitu opcode;
if (!decode.page.invmap) opcode=decode_fetchb();
else {
// some entries in the invalidation map, see if the next
// instruction is known to be modified a lot
if (decode.page.index<4096) {
if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode;
opcode=decode_fetchb();
} else {
// switch to the next page
opcode=decode_fetchb();
if (GCC_UNLIKELY(decode.page.invmap &&
(decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode;
}
}
switch (opcode) {
// instructions 'op reg8,reg8' and 'op [],reg8'
case 0x00:dyn_dop_ebgb(DOP_ADD);break;
case 0x08:dyn_dop_ebgb(DOP_OR);break;
case 0x10:dyn_dop_ebgb(DOP_ADC);break;
case 0x18:dyn_dop_ebgb(DOP_SBB);break;
case 0x20:dyn_dop_ebgb(DOP_AND);break;
case 0x28:dyn_dop_ebgb(DOP_SUB);break;
case 0x30:dyn_dop_ebgb(DOP_XOR);break;
case 0x38:dyn_dop_ebgb(DOP_CMP);break;
// instructions 'op reg8,reg8' and 'op reg8,[]'
case 0x02:dyn_dop_gbeb(DOP_ADD);break;
case 0x0a:dyn_dop_gbeb(DOP_OR);break;
case 0x12:dyn_dop_gbeb(DOP_ADC);break;
case 0x1a:dyn_dop_gbeb(DOP_SBB);break;
case 0x22:dyn_dop_gbeb(DOP_AND);break;
case 0x2a:dyn_dop_gbeb(DOP_SUB);break;
case 0x32:dyn_dop_gbeb(DOP_XOR);break;
case 0x3a:dyn_dop_gbeb(DOP_CMP);break;
// instructions 'op reg16/32,reg16/32' and 'op [],reg16/32'
case 0x01:dyn_dop_evgv(DOP_ADD);break;
case 0x09:dyn_dop_evgv(DOP_OR);break;
case 0x11:dyn_dop_evgv(DOP_ADC);break;
case 0x19:dyn_dop_evgv(DOP_SBB);break;
case 0x21:dyn_dop_evgv(DOP_AND);break;
case 0x29:dyn_dop_evgv(DOP_SUB);break;
case 0x31:dyn_dop_evgv(DOP_XOR);break;
case 0x39:dyn_dop_evgv(DOP_CMP);break;
// instructions 'op reg16/32,reg16/32' and 'op reg16/32,[]'
case 0x03:dyn_dop_gvev(DOP_ADD);break;
case 0x0b:dyn_dop_gvev(DOP_OR);break;
case 0x13:dyn_dop_gvev(DOP_ADC);break;
case 0x1b:dyn_dop_gvev(DOP_SBB);break;
case 0x23:dyn_dop_gvev(DOP_AND);break;
case 0x2b:dyn_dop_gvev(DOP_SUB);break;
case 0x33:dyn_dop_gvev(DOP_XOR);break;
case 0x3b:dyn_dop_gvev(DOP_CMP);break;
// instructions 'op reg8,imm8'
case 0x04:dyn_dop_byte_imm(DOP_ADD,DRC_REG_EAX,0);break;
case 0x0c:dyn_dop_byte_imm(DOP_OR,DRC_REG_EAX,0);break;
case 0x14:dyn_dop_byte_imm(DOP_ADC,DRC_REG_EAX,0);break;
case 0x1c:dyn_dop_byte_imm(DOP_SBB,DRC_REG_EAX,0);break;
case 0x24:dyn_dop_byte_imm(DOP_AND,DRC_REG_EAX,0);break;
case 0x2c:dyn_dop_byte_imm(DOP_SUB,DRC_REG_EAX,0);break;
case 0x34:dyn_dop_byte_imm(DOP_XOR,DRC_REG_EAX,0);break;
case 0x3c:dyn_dop_byte_imm(DOP_CMP,DRC_REG_EAX,0);break;
// instructions 'op reg16/32,imm16/32'
case 0x05:dyn_dop_word_imm(DOP_ADD,DRC_REG_EAX);break;
case 0x0d:dyn_dop_word_imm_old(DOP_OR,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break;
case 0x15:dyn_dop_word_imm_old(DOP_ADC,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break;
case 0x1d:dyn_dop_word_imm_old(DOP_SBB,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break;
case 0x25:dyn_dop_word_imm(DOP_AND,DRC_REG_EAX);break;
case 0x2d:dyn_dop_word_imm_old(DOP_SUB,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break;
case 0x35:dyn_dop_word_imm_old(DOP_XOR,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break;
case 0x3d:dyn_dop_word_imm_old(DOP_CMP,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break;
// push segment register onto stack
case 0x06:dyn_push_seg(DRC_SEG_ES);break;
case 0x0e:dyn_push_seg(DRC_SEG_CS);break;
case 0x16:dyn_push_seg(DRC_SEG_SS);break;
case 0x1e:dyn_push_seg(DRC_SEG_DS);break;
// pop segment register from stack
case 0x07:dyn_pop_seg(DRC_SEG_ES);break;
case 0x17:dyn_pop_seg(DRC_SEG_SS);break;
case 0x1f:dyn_pop_seg(DRC_SEG_DS);break;
// segment prefixes
case 0x26:dyn_segprefix(DRC_SEG_ES);goto restart_prefix;
case 0x2e:dyn_segprefix(DRC_SEG_CS);goto restart_prefix;
case 0x36:dyn_segprefix(DRC_SEG_SS);goto restart_prefix;
case 0x3e:dyn_segprefix(DRC_SEG_DS);goto restart_prefix;
case 0x64:dyn_segprefix(DRC_SEG_FS);goto restart_prefix;
case 0x65:dyn_segprefix(DRC_SEG_GS);goto restart_prefix;
// case 0x27: DAA missing
// case 0x2f: DAS missing
// case 0x37: AAA missing
// case 0x3f: AAS missing
// dual opcodes
case 0x0f:
{
Bitu dual_code=decode_fetchb();
switch (dual_code) {
case 0x00:
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
dyn_grp6();
break;
case 0x01:
if (dyn_grp7()) goto finish_block;
break;
/* case 0x02:
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
dyn_larlsl(true);
break;
case 0x03:
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
dyn_larlsl(false);
break; */
case 0x20:dyn_mov_from_crx();break;
case 0x22:dyn_mov_to_crx();goto finish_block;
// short conditional jumps
case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87:
case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f:
dyn_branched_exit((BranchTypes)(dual_code&0xf),
decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
goto finish_block;
// conditional byte set instructions
/* case 0x90:case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97:
case 0x98:case 0x99:case 0x9a:case 0x9b:case 0x9c:case 0x9d:case 0x9e:case 0x9f:
dyn_set_byte_on_condition((BranchTypes)(dual_code&0xf));
AcquireFlags(FMASK_TEST);
break; */
// push/pop segment registers
case 0xa0:dyn_push_seg(DRC_SEG_FS);break;
case 0xa1:dyn_pop_seg(DRC_SEG_FS);break;
case 0xa8:dyn_push_seg(DRC_SEG_GS);break;
case 0xa9:dyn_pop_seg(DRC_SEG_GS);break;
// double shift instructions
case 0xa4:dyn_dshift_ev_gv(true,true);break;
case 0xa5:dyn_dshift_ev_gv(true,false);break;
case 0xac:dyn_dshift_ev_gv(false,true);break;
case 0xad:dyn_dshift_ev_gv(false,false);break;
case 0xaf:dyn_imul_gvev(0);break;
case 0xb4:dyn_load_seg_off_ea(DRC_SEG_FS);break;
case 0xb5:dyn_load_seg_off_ea(DRC_SEG_GS);break;
// zero-extending moves
case 0xb6:dyn_movx_ev_gb(false);break;
case 0xb7:dyn_movx_ev_gw(false);break;
// sign-extending moves
case 0xbe:dyn_movx_ev_gb(true);break;
case 0xbf:dyn_movx_ev_gw(true);break;
default:
// DYN_LOG("Unhandled dual opcode 0F%02X",dual_code);
goto illegalopcode;
}
break;
}
// 'inc/dec reg16/32'
case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47:
dyn_sop_word(SOP_INC,opcode&7);
break;
case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f:
dyn_sop_word(SOP_DEC,opcode&7);
break;
// 'push/pop reg16/32'
case 0x50:case 0x51:case 0x52:case 0x53:case 0x54:case 0x55:case 0x56:case 0x57:
dyn_push_reg(opcode&7);
break;
case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f:
dyn_pop_reg(opcode&7);
break;
case 0x60:
if (decode.big_op) gen_call_function_raw((void *)&dynrec_pusha_dword);
else gen_call_function_raw((void *)&dynrec_pusha_word);
break;
case 0x61:
if (decode.big_op) gen_call_function_raw((void *)&dynrec_popa_dword);
else gen_call_function_raw((void *)&dynrec_popa_word);
break;
// case 0x62: BOUND missing
// case 0x61: ARPL missing
case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix;
case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix;
// 'push imm8/16/32'
case 0x68:
dyn_push_word_imm(decode.big_op ? decode_fetchd() : decode_fetchw());
break;
case 0x6a:
dyn_push_byte_imm((Bit8s)decode_fetchb());
break;
// signed multiplication
case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break;
case 0x6b:dyn_imul_gvev(1);break;
// case 0x6c to 0x6f missing (ins/outs)
// short conditional jumps
case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77:
case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f:
dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb());
goto finish_block;
// 'op []/reg8,imm8'
case 0x80:
case 0x82:dyn_grp1_eb_ib();break;
// 'op []/reg16/32,imm16/32'
case 0x81:dyn_grp1_ev_iv(false);break;
case 0x83:dyn_grp1_ev_iv(true);break;
// 'test []/reg8/16/32,reg8/16/32'
case 0x84:dyn_dop_gbeb(DOP_TEST);break;
case 0x85:dyn_dop_gvev(DOP_TEST);break;
// 'xchg reg8/16/32,[]/reg8/16/32'
case 0x86:dyn_dop_ebgb_xchg();break;
case 0x87:dyn_dop_evgv_xchg();break;
// 'mov []/reg8/16/32,reg8/16/32'
case 0x88:dyn_dop_ebgb_mov();break;
case 0x89:dyn_dop_evgv_mov();break;
// 'mov reg8/16/32,[]/reg8/16/32'
case 0x8a:dyn_dop_gbeb_mov();break;
case 0x8b:dyn_dop_gvev_mov();break;
// move segment register into memory or a 16bit register
case 0x8c:dyn_mov_ev_seg();break;
// load effective address
case 0x8d:
dyn_get_modrm();
dyn_fill_ea(FC_ADDR,false);
gen_mov_word_from_reg(FC_ADDR,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op);
break;
// move a value from memory or a 16bit register into a segment register
case 0x8e:dyn_mov_seg_ev();break;
// 'pop []'
case 0x8f:dyn_pop_ev();break;
case 0x90: // nop
case 0x9b: // wait
case 0xf0: // lock
break;
case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97:
dyn_xchg_ax(opcode&7);
break;
// sign-extend al into ax/sign-extend ax into eax
case 0x98:dyn_cbw();break;
// sign-extend ax into dx:ax/sign-extend eax into edx:eax
case 0x99:dyn_cwd();break;
case 0x9a:dyn_call_far_imm();goto finish_block;
case 0x9c: // pushf
AcquireFlags(FMASK_TEST);
gen_call_function_I((void *)&CPU_PUSHF,decode.big_op);
dyn_check_exception(FC_RETOP);
break;
case 0x9d: // popf
gen_call_function_I((void *)&CPU_POPF,decode.big_op);
dyn_check_exception(FC_RETOP);
InvalidateFlags();
break;
case 0x9e:dyn_sahf();break;
// case 0x9f: LAHF missing
// 'mov al/ax,[]'
case 0xa0:
dyn_mov_byte_al_direct(decode.big_addr ? decode_fetchd() : decode_fetchw());
break;
case 0xa1:
dyn_mov_byte_ax_direct(decode.big_addr ? decode_fetchd() : decode_fetchw());
break;
// 'mov [],al/ax'
case 0xa2:
dyn_mov_byte_direct_al();
break;
case 0xa3:
dyn_mov_byte_direct_ax(decode.big_addr ? decode_fetchd() : decode_fetchw());
break;
// case 0xa6 to 0xaf string operations, some missing
// movsb/w/d
case 0xa4:dyn_string(STR_MOVSB);break;
case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break;
// stosb/w/d
case 0xaa:dyn_string(STR_STOSB);break;
case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break;
// lodsb/w/d
case 0xac:dyn_string(STR_LODSB);break;
case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break;
// 'test reg8/16/32,imm8/16/32'
case 0xa8:dyn_dop_byte_imm(DOP_TEST,DRC_REG_EAX,0);break;
case 0xa9:dyn_dop_word_imm_old(DOP_TEST,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break;
// 'mov reg8/16/32,imm8/16/32'
case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7:
dyn_mov_byte_imm(opcode&3,(opcode>>2)&1,decode_fetchb());
break;
case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf:
dyn_mov_word_imm(opcode&7);break;
break;
// 'shiftop []/reg8,imm8/1/cl'
case 0xc0:dyn_grp2_eb(grp2_imm);break;
case 0xd0:dyn_grp2_eb(grp2_1);break;
case 0xd2:dyn_grp2_eb(grp2_cl);break;
// 'shiftop []/reg16/32,imm8/1/cl'
case 0xc1:dyn_grp2_ev(grp2_imm);break;
case 0xd1:dyn_grp2_ev(grp2_1);break;
case 0xd3:dyn_grp2_ev(grp2_cl);break;
// retn [param]
case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block;
case 0xc3:dyn_ret_near(0);goto finish_block;
case 0xc4:dyn_load_seg_off_ea(DRC_SEG_ES);break;
case 0xc5:dyn_load_seg_off_ea(DRC_SEG_DS);break;
// 'mov []/reg8/16/32,imm8/16/32'
case 0xc6:dyn_dop_ebib_mov();break;
case 0xc7:dyn_dop_eviv_mov();break;
case 0xc8:dyn_enter();break;
case 0xc9:dyn_leave();break;
// retf [param]
case 0xca:dyn_ret_far(decode_fetchw());goto finish_block;
case 0xcb:dyn_ret_far(0);goto finish_block;
// int/iret
case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block;
case 0xcf:dyn_iret();goto finish_block;
// case 0xd4: AAM missing
// case 0xd5: AAD missing
// case 0xd6: SALC missing
// case 0xd7: XLAT missing
#ifdef CPU_FPU
// floating point instructions
case 0xd8:
dyn_fpu_esc0();
break;
case 0xd9:
dyn_fpu_esc1();
break;
case 0xda:
dyn_fpu_esc2();
break;
case 0xdb:
dyn_fpu_esc3();
break;
case 0xdc:
dyn_fpu_esc4();
break;
case 0xdd:
dyn_fpu_esc5();
break;
case 0xde:
dyn_fpu_esc6();
break;
case 0xdf:
dyn_fpu_esc7();
break;
#endif
// loop instructions
case 0xe0:dyn_loop(LOOP_NE);goto finish_block;
case 0xe1:dyn_loop(LOOP_E);goto finish_block;
case 0xe2:dyn_loop(LOOP_NONE);goto finish_block;
case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block;
// 'in al/ax/eax,port_imm'
case 0xe4:dyn_read_port_byte_direct(decode_fetchb());break;
case 0xe5:dyn_read_port_word_direct(decode_fetchb());break;
// 'out port_imm,al/ax/eax'
case 0xe6:dyn_write_port_byte_direct(decode_fetchb());break;
case 0xe7:dyn_write_port_word_direct(decode_fetchb());break;
// 'in al/ax/eax,port_dx'
case 0xec:dyn_read_port_byte();break;
case 0xed:dyn_read_port_word();break;
// 'out port_dx,al/ax/eax'
case 0xee:dyn_write_port_byte();break;
case 0xef:dyn_write_port_word();break;
// 'call near imm16/32'
case 0xe8:
dyn_call_near_imm();
goto finish_block;
// 'jmp near imm16/32'
case 0xe9:
dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
goto finish_block;
// 'jmp far'
case 0xea:
dyn_jmp_far_imm();
goto finish_block;
// 'jmp short imm8'
case 0xeb:
dyn_exit_link((Bit8s)decode_fetchb());
goto finish_block;
// repeat prefixes
case 0xf2:
decode.rep=REP_NZ;
goto restart_prefix;
case 0xf3:
decode.rep=REP_Z;
goto restart_prefix;
case 0xf5: //CMC
gen_call_function_raw((void*)dynrec_cmc);
break;
case 0xf8: //CLC
gen_call_function_raw((void*)dynrec_clc);
break;
case 0xf9: //STC
gen_call_function_raw((void*)dynrec_stc);
break;
case 0xf6:dyn_grp3_eb();break;
case 0xf7:dyn_grp3_ev();break;
case 0xfa: //CLI
gen_call_function_raw((void *)&CPU_CLI);
if (cpu.pmode) dyn_check_exception(FC_RETOP);
break;
case 0xfb: //STI
gen_call_function_raw((void *)&CPU_STI);
if (cpu.pmode) dyn_check_exception(FC_RETOP);
if (max_opcodes<=0) max_opcodes=1; //Allow 1 extra opcode
break;
case 0xfc: //CLD
gen_call_function_raw((void*)dynrec_cld);
break;
case 0xfd: //STD
gen_call_function_raw((void*)dynrec_std);
break;
case 0xfe:
if (dyn_grp4_eb()) goto finish_block;
break;
case 0xff:
if (dyn_grp4_ev()) goto core_close_block;
break;
default:
// DYN_LOG("Dynrec unhandled opcode %X",opcode);
goto illegalopcode;
}
}
// normal exit because the maximal number of opcodes has been reached
dyn_set_eip_end();
core_close_block:
dyn_reduce_cycles();
dyn_return(BR_Normal);
dyn_closeblock();
goto finish_block;
illegalopcode:
// some unhandled opcode has been encountered
dyn_set_eip_last();
dyn_reduce_cycles();
dyn_return(BR_Opcode); // tell the core what happened
dyn_closeblock();
goto finish_block;
finish_block:
// setup the correct end-address
decode.page.index--;
decode.active_block->page.end=(Bit16u)decode.page.index;
// LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end);
return decode.block;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,681 @@
/*
* Copyright (C) 2002-2007 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 "dosbox.h"
#if C_FPU
#include <math.h>
#include <float.h>
#include "cross.h"
#include "mem.h"
#include "fpu.h"
#include "cpu.h"
static void FPU_FDECSTP(){
TOP = (TOP - 1) & 7;
}
static void FPU_FINCSTP(){
TOP = (TOP + 1) & 7;
}
static void FPU_FNSTCW(PhysPt addr){
mem_writew(addr,fpu.cw);
}
static void FPU_FFREE(Bitu st) {
fpu.tags[st]=TAG_Empty;
}
#if C_FPU_X86
#include "../../fpu/fpu_instructions_x86.h"
#else
#include "../../fpu/fpu_instructions.h"
#endif
static INLINE void dyn_fpu_top() {
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
gen_add_imm(FC_OP2,decode.modrm.rm);
gen_and_imm(FC_OP2,7);
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
}
static INLINE void dyn_fpu_top_swapped() {
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
gen_add_imm(FC_OP1,decode.modrm.rm);
gen_and_imm(FC_OP1,7);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
}
static void dyn_eatree() {
Bitu group=(decode.modrm.val >> 3) & 7;
switch (group){
case 0x00: // FADD ST,STi
gen_call_function_R((void*)&FPU_FADD_EA,FC_OP1);
break;
case 0x01: // FMUL ST,STi
gen_call_function_R((void*)&FPU_FMUL_EA,FC_OP1);
break;
case 0x02: // FCOM STi
gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1);
break;
case 0x03: // FCOMP STi
gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04: // FSUB ST,STi
gen_call_function_R((void*)&FPU_FSUB_EA,FC_OP1);
break;
case 0x05: // FSUBR ST,STi
gen_call_function_R((void*)&FPU_FSUBR_EA,FC_OP1);
break;
case 0x06: // FDIV ST,STi
gen_call_function_R((void*)&FPU_FDIV_EA,FC_OP1);
break;
case 0x07: // FDIVR ST,STi
gen_call_function_R((void*)&FPU_FDIVR_EA,FC_OP1);
break;
default:
break;
}
}
static void dyn_fpu_esc0(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
dyn_fpu_top();
switch (decode.modrm.reg){
case 0x00: //FADD ST,STi
gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2);
break;
case 0x01: // FMUL ST,STi
gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2);
break;
case 0x02: // FCOM STi
gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
break;
case 0x03: // FCOMP STi
gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04: // FSUB ST,STi
gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2);
break;
case 0x05: // FSUBR ST,STi
gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2);
break;
case 0x06: // FDIV ST,STi
gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2);
break;
case 0x07: // FDIVR ST,STi
gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2);
break;
default:
break;
}
} else {
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FLD_F32_EA,FC_ADDR);
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
dyn_eatree();
}
}
static void dyn_fpu_esc1(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
switch (decode.modrm.reg){
case 0x00: /* FLD STi */
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
gen_add_imm(FC_OP1,decode.modrm.rm);
gen_and_imm(FC_OP1,7);
gen_protect_reg(FC_OP1);
gen_call_function_raw((void*)&FPU_PREP_PUSH);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
gen_restore_reg(FC_OP1);
gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
break;
case 0x01: /* FXCH STi */
dyn_fpu_top();
gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2);
break;
case 0x02: /* FNOP */
gen_call_function_raw((void*)&FPU_FNOP);
break;
case 0x03: /* FSTP STi */
dyn_fpu_top();
gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04:
switch(decode.modrm.rm){
case 0x00: /* FCHS */
gen_call_function_raw((void*)&FPU_FCHS);
break;
case 0x01: /* FABS */
gen_call_function_raw((void*)&FPU_FABS);
break;
case 0x02: /* UNKNOWN */
case 0x03: /* ILLEGAL */
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
break;
case 0x04: /* FTST */
gen_call_function_raw((void*)&FPU_FTST);
break;
case 0x05: /* FXAM */
gen_call_function_raw((void*)&FPU_FXAM);
break;
case 0x06: /* FTSTP (cyrix)*/
case 0x07: /* UNKNOWN */
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
break;
}
break;
case 0x05:
switch(decode.modrm.rm){
case 0x00: /* FLD1 */
gen_call_function_raw((void*)&FPU_FLD1);
break;
case 0x01: /* FLDL2T */
gen_call_function_raw((void*)&FPU_FLDL2T);
break;
case 0x02: /* FLDL2E */
gen_call_function_raw((void*)&FPU_FLDL2E);
break;
case 0x03: /* FLDPI */
gen_call_function_raw((void*)&FPU_FLDPI);
break;
case 0x04: /* FLDLG2 */
gen_call_function_raw((void*)&FPU_FLDLG2);
break;
case 0x05: /* FLDLN2 */
gen_call_function_raw((void*)&FPU_FLDLN2);
break;
case 0x06: /* FLDZ*/
gen_call_function_raw((void*)&FPU_FLDZ);
break;
case 0x07: /* ILLEGAL */
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
break;
}
break;
case 0x06:
switch(decode.modrm.rm){
case 0x00: /* F2XM1 */
gen_call_function_raw((void*)&FPU_F2XM1);
break;
case 0x01: /* FYL2X */
gen_call_function_raw((void*)&FPU_FYL2X);
break;
case 0x02: /* FPTAN */
gen_call_function_raw((void*)&FPU_FPTAN);
break;
case 0x03: /* FPATAN */
gen_call_function_raw((void*)&FPU_FPATAN);
break;
case 0x04: /* FXTRACT */
gen_call_function_raw((void*)&FPU_FXTRACT);
break;
case 0x05: /* FPREM1 */
gen_call_function_raw((void*)&FPU_FPREM1);
break;
case 0x06: /* FDECSTP */
gen_call_function_raw((void*)&FPU_FDECSTP);
break;
case 0x07: /* FINCSTP */
gen_call_function_raw((void*)&FPU_FINCSTP);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
break;
}
break;
case 0x07:
switch(decode.modrm.rm){
case 0x00: /* FPREM */
gen_call_function_raw((void*)&FPU_FPREM);
break;
case 0x01: /* FYL2XP1 */
gen_call_function_raw((void*)&FPU_FYL2XP1);
break;
case 0x02: /* FSQRT */
gen_call_function_raw((void*)&FPU_FSQRT);
break;
case 0x03: /* FSINCOS */
gen_call_function_raw((void*)&FPU_FSINCOS);
break;
case 0x04: /* FRNDINT */
gen_call_function_raw((void*)&FPU_FRNDINT);
break;
case 0x05: /* FSCALE */
gen_call_function_raw((void*)&FPU_FSCALE);
break;
case 0x06: /* FSIN */
gen_call_function_raw((void*)&FPU_FSIN);
break;
case 0x07: /* FCOS */
gen_call_function_raw((void*)&FPU_FCOS);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
break;
}
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
break;
}
} else {
switch(decode.modrm.reg){
case 0x00: /* FLD float*/
gen_call_function_raw((void*)&FPU_PREP_PUSH);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
dyn_fill_ea(FC_OP1);
gen_call_function_RR((void*)&FPU_FLD_F32,FC_OP1,FC_OP2);
break;
case 0x01: /* UNKNOWN */
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
case 0x02: /* FST float*/
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR);
break;
case 0x03: /* FSTP float*/
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04: /* FLDENV */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FLDENV,FC_ADDR);
break;
case 0x05: /* FLDCW */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void *)&FPU_FLDCW,FC_ADDR);
break;
case 0x06: /* FSTENV */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void *)&FPU_FSTENV,FC_ADDR);
break;
case 0x07: /* FNSTCW*/
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void *)&FPU_FNSTCW,FC_ADDR);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
}
}
}
static void dyn_fpu_esc2(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
switch(decode.modrm.reg){
case 0x05:
switch(decode.modrm.rm){
case 0x01: /* FUCOMPP */
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
gen_add_imm(FC_OP2,1);
gen_and_imm(FC_OP2,7);
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
gen_call_function_RR((void *)&FPU_FUCOM,FC_OP1,FC_OP2);
gen_call_function_raw((void *)&FPU_FPOP);
gen_call_function_raw((void *)&FPU_FPOP);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
}
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
}
} else {
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FLD_I32_EA,FC_ADDR);
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
dyn_eatree();
}
}
static void dyn_fpu_esc3(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
switch (decode.modrm.reg) {
case 0x04:
switch (decode.modrm.rm) {
case 0x00: //FNENI
case 0x01: //FNDIS
LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion: %d",decode.modrm.rm);
break;
case 0x02: //FNCLEX FCLEX
gen_call_function_raw((void*)&FPU_FCLEX);
break;
case 0x03: //FNINIT FINIT
gen_call_function_raw((void*)&FPU_FINIT);
break;
case 0x04: //FNSETPM
case 0x05: //FRSTPM
// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done");
break;
default:
E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
}
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
}
} else {
switch(decode.modrm.reg){
case 0x00: /* FILD */
gen_call_function_raw((void*)&FPU_PREP_PUSH);
dyn_fill_ea(FC_OP1);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
gen_call_function_RR((void*)&FPU_FLD_I32,FC_OP1,FC_OP2);
break;
case 0x01: /* FISTTP */
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
case 0x02: /* FIST */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR);
break;
case 0x03: /* FISTP */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x05: /* FLD 80 Bits Real */
gen_call_function_raw((void*)&FPU_PREP_PUSH);
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FLD_F80,FC_ADDR);
break;
case 0x07: /* FSTP 80 Bits Real */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_F80,FC_ADDR);
gen_call_function_raw((void*)&FPU_FPOP);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
}
}
}
static void dyn_fpu_esc4(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
switch(decode.modrm.reg){
case 0x00: /* FADD STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2);
break;
case 0x01: /* FMUL STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2);
break;
case 0x02: /* FCOM*/
dyn_fpu_top();
gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
break;
case 0x03: /* FCOMP*/
dyn_fpu_top();
gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04: /* FSUBR STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2);
break;
case 0x05: /* FSUB STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2);
break;
case 0x06: /* FDIVR STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2);
break;
case 0x07: /* FDIV STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2);
break;
default:
break;
}
} else {
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FLD_F64_EA,FC_ADDR);
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
dyn_eatree();
}
}
static void dyn_fpu_esc5(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
dyn_fpu_top();
switch(decode.modrm.reg){
case 0x00: /* FFREE STi */
gen_call_function_R((void*)&FPU_FFREE,FC_OP2);
break;
case 0x01: /* FXCH STi*/
gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2);
break;
case 0x02: /* FST STi */
gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
break;
case 0x03: /* FSTP STi*/
gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04: /* FUCOM STi */
gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2);
break;
case 0x05: /*FUCOMP STi */
gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2);
gen_call_function_raw((void*)&FPU_FPOP);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
}
} else {
switch(decode.modrm.reg){
case 0x00: /* FLD double real*/
gen_call_function_raw((void*)&FPU_PREP_PUSH);
dyn_fill_ea(FC_OP1);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
gen_call_function_RR((void*)&FPU_FLD_F64,FC_OP1,FC_OP2);
break;
case 0x01: /* FISTTP longint*/
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
case 0x02: /* FST double real*/
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR);
break;
case 0x03: /* FSTP double real*/
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04: /* FRSTOR */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FRSTOR,FC_ADDR);
break;
case 0x06: /* FSAVE */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FSAVE,FC_ADDR);
break;
case 0x07: /*FNSTSW */
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1);
gen_mov_word_to_reg(FC_OP2,(void*)(&fpu.sw),true);
dyn_fill_ea(FC_OP1);
gen_call_function_RR((void*)&mem_writew,FC_OP1,FC_OP2);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
}
}
}
static void dyn_fpu_esc6(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
switch(decode.modrm.reg){
case 0x00: /*FADDP STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2);
break;
case 0x01: /* FMULP STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2);
break;
case 0x02: /* FCOMP5*/
dyn_fpu_top();
gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
break; /* TODO IS THIS ALLRIGHT ????????? */
case 0x03: /*FCOMPP*/
if(decode.modrm.rm != 1) {
LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
return;
}
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
gen_add_imm(FC_OP2,1);
gen_and_imm(FC_OP2,7);
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
gen_call_function_raw((void*)&FPU_FPOP); /* extra pop at the bottom*/
break;
case 0x04: /* FSUBRP STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2);
break;
case 0x05: /* FSUBP STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2);
break;
case 0x06: /* FDIVRP STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2);
break;
case 0x07: /* FDIVP STi,ST*/
dyn_fpu_top_swapped();
gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2);
break;
default:
break;
}
gen_call_function_raw((void*)&FPU_FPOP);
} else {
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FLD_I16_EA,FC_ADDR);
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
dyn_eatree();
}
}
static void dyn_fpu_esc7(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
switch (decode.modrm.reg){
case 0x01: /* FXCH STi*/
dyn_fpu_top();
gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2);
break;
case 0x02: /* FSTP STi*/
case 0x03: /* FSTP STi*/
dyn_fpu_top();
gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04:
switch(decode.modrm.rm){
case 0x00: /* FNSTSW AX*/
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1);
gen_mov_word_to_reg(FC_OP1,(void*)(&fpu.sw),false);
gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_EAX,false),false);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
}
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
}
} else {
switch(decode.modrm.reg){
case 0x00: /* FILD Bit16s */
gen_call_function_raw((void*)&FPU_PREP_PUSH);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
dyn_fill_ea(FC_OP1);
gen_call_function_RR((void*)&FPU_FLD_I16,FC_OP1,FC_OP2);
break;
case 0x01:
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
case 0x02: /* FIST Bit16s */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR);
break;
case 0x03: /* FISTP Bit16s */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x04: /* FBLD packed BCD */
gen_call_function_raw((void*)&FPU_PREP_PUSH);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
dyn_fill_ea(FC_OP1);
gen_call_function_RR((void*)&FPU_FBLD,FC_OP1,FC_OP2);
break;
case 0x05: /* FILD Bit64s */
gen_call_function_raw((void*)&FPU_PREP_PUSH);
gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
dyn_fill_ea(FC_OP1);
gen_call_function_RR((void*)&FPU_FLD_I64,FC_OP1,FC_OP2);
break;
case 0x06: /* FBSTP packed BCD */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FBST,FC_ADDR);
gen_call_function_raw((void*)&FPU_FPOP);
break;
case 0x07: /* FISTP Bit64s */
dyn_fill_ea(FC_ADDR);
gen_call_function_R((void*)&FPU_FST_I64,FC_ADDR);
gen_call_function_raw((void*)&FPU_FPOP);
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
break;
}
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,632 @@
/*
* Copyright (C) 2002-2007 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.
*/
/* MIPS32 (little endian) backend by crazyc */
// some configuring defines that specify the capabilities of this architecture
// or aspects of the recompiling
// protect FC_ADDR over function calls if necessaray
// #define DRC_PROTECT_ADDR_REG
// try to use non-flags generating functions if possible
#define DRC_FLAGS_INVALIDATION
// try to replace _simple functions by code
#define DRC_FLAGS_INVALIDATION_DCODE
// type with the same size as a pointer
#define DRC_PTR_SIZE_IM Bit32u
// calling convention modifier
#define DRC_CALL_CONV /* nothing */
#define DRC_FC /* nothing */
// register mapping
typedef Bit8u HostReg;
#define HOST_v0 2
#define HOST_v1 3
#define HOST_a0 4
#define HOST_a1 5
#define HOST_t4 12
#define HOST_t5 13
#define HOST_t6 14
#define HOST_t7 15
#define HOST_s0 16
#define HOST_t8 24
#define HOST_t9 25
#define temp1 HOST_v1
#define temp2 HOST_t9
// register that holds function return values
#define FC_RETOP HOST_v0
// register used for address calculations,
#define FC_ADDR HOST_s0 // has to be saved across calls, see DRC_PROTECT_ADDR_REG
// register that holds the first parameter
#define FC_OP1 HOST_a0
// register that holds the second parameter
#define FC_OP2 HOST_a1
// register that holds byte-accessible temporary values
#define FC_TMP_BA1 HOST_t5
// register that holds byte-accessible temporary values
#define FC_TMP_BA2 HOST_t6
// temporary register for LEA
#define TEMP_REG_DRC HOST_t7
// save some state to improve code gen
static bool temp1_valid = false;
static Bit32u temp1_value;
// move a full register from reg_src to reg_dst
static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
if(reg_src == reg_dst) return;
cache_addw((reg_dst<<11)+0x21); // addu reg_dst, $0, reg_src
cache_addw(reg_src);
}
// move a 32bit constant value into dest_reg
static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
if(imm < 65536) {
cache_addw((Bit16u)imm); // ori dest_reg, $0, imm
cache_addw(0x3400+dest_reg);
} else if(((Bit32s)imm < 0) && ((Bit32s)imm >= -32768)) {
cache_addw((Bit16u)imm); // addiu dest_reg, $0, imm
cache_addw(0x2400+dest_reg);
} else if(!(imm & 0xffff)) {
cache_addw((Bit16u)(imm >> 16)); // lui dest_reg, %hi(imm)
cache_addw(0x3c00+dest_reg);
} else {
cache_addw((Bit16u)(imm >> 16)); // lui dest_reg, %hi(imm)
cache_addw(0x3c00+dest_reg);
cache_addw((Bit16u)imm); // ori dest_reg, dest_reg, %lo(imm)
cache_addw(0x3400+(dest_reg<<5)+dest_reg);
}
}
// this is the only place temp1 should be modified
static void INLINE mov_imm_to_temp1(Bit32u imm) {
if (temp1_valid && (temp1_value == imm)) return;
gen_mov_dword_to_reg_imm(temp1, imm);
temp1_valid = true;
temp1_value = imm;
}
static Bit16s gen_addr_temp1(Bit32u addr) {
Bit32u hihalf = addr & 0xffff0000;
Bit16s lohalf = addr & 0xffff;
if (lohalf > 32764) { // [l,s]wl will overflow
hihalf = addr;
lohalf = 0;
} else if(lohalf < 0) hihalf += 0x10000;
mov_imm_to_temp1(hihalf);
return lohalf;
}
// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
Bit16s lohalf = gen_addr_temp1((Bit32u)data);
// alignment....
if (dword) {
if ((Bit32u)data & 3) {
cache_addw(lohalf+3); // lwl dest_reg, 3(temp1)
cache_addw(0x8800+(temp1<<5)+dest_reg);
cache_addw(lohalf); // lwr dest_reg, 0(temp1)
cache_addw(0x9800+(temp1<<5)+dest_reg);
} else {
cache_addw(lohalf); // lw dest_reg, 0(temp1)
cache_addw(0x8C00+(temp1<<5)+dest_reg);
}
} else {
if ((Bit32u)data & 1) {
cache_addw(lohalf); // lbu dest_reg, 0(temp1)
cache_addw(0x9000+(temp1<<5)+dest_reg);
cache_addw(lohalf+1); // lbu temp2, 1(temp1)
cache_addw(0x9000+(temp1<<5)+temp2);
#if (_MIPS_ISA==MIPS32R2) || defined(PSP)
cache_addw(0x7a04); // ins dest_reg, temp2, 8, 8
cache_addw(0x7c00+(temp2<<5)+dest_reg);
#else
cache_addw((temp2<<11)+0x200); // sll temp2, temp2, 8
cache_addw(temp2);
cache_addw((dest_reg<<11)+0x25); // or dest_reg, temp2, dest_reg
cache_addw((temp2<<5)+dest_reg);
#endif
} else {
cache_addw(lohalf); // lhu dest_reg, 0(temp1);
cache_addw(0x9400+(temp1<<5)+dest_reg);
}
}
}
// move a 16bit constant value into dest_reg
// the upper 16bit of the destination register may be destroyed
static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
cache_addw(imm); // ori dest_reg, $0, imm
cache_addw(0x3400+dest_reg);
}
// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
Bit16s lohalf = gen_addr_temp1((Bit32u)dest);
// alignment....
if (dword) {
if ((Bit32u)dest & 3) {
cache_addw(lohalf+3); // swl src_reg, 3(temp1)
cache_addw(0xA800+(temp1<<5)+src_reg);
cache_addw(lohalf); // swr src_reg, 0(temp1)
cache_addw(0xB800+(temp1<<5)+src_reg);
} else {
cache_addw(lohalf); // sw src_reg, 0(temp1)
cache_addw(0xAC00+(temp1<<5)+src_reg);
}
} else {
if((Bit32u)dest & 1) {
cache_addw(lohalf); // sb src_reg, 0(temp1)
cache_addw(0xA000+(temp1<<5)+src_reg);
cache_addw((temp2<<11)+0x202); // srl temp2, src_reg, 8
cache_addw(src_reg);
cache_addw(lohalf+1); // sb temp2, 1(temp1)
cache_addw(0xA000+(temp1<<5)+temp2);
} else {
cache_addw(lohalf); // sh src_reg, 0(temp1);
cache_addw(0xA400+(temp1<<5)+src_reg);
}
}
}
// move an 8bit value from memory into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
Bit16s lohalf = gen_addr_temp1((Bit32u)data);
cache_addw(lohalf); // lbu dest_reg, 0(temp1)
cache_addw(0x9000+(temp1<<5)+dest_reg);
}
// move an 8bit value from memory into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
gen_mov_byte_to_reg_low(dest_reg, data);
}
// move an 8bit constant value into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void INLINE gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
gen_mov_word_to_reg_imm(dest_reg, imm);
}
// move an 8bit constant value into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
gen_mov_byte_to_reg_low_imm(dest_reg, imm);
}
// move the lowest 8bit of a register into memory
static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
Bit16s lohalf = gen_addr_temp1((Bit32u)dest);
cache_addw(lohalf); // sb src_reg, 0(temp1)
cache_addw(0xA000+(temp1<<5)+src_reg);
}
// convert an 8bit word to a 32bit dword
// the register is zero-extended (sign==false) or sign-extended (sign==true)
static void gen_extend_byte(bool sign,HostReg reg) {
if (sign) {
#if (_MIPS_ISA==MIPS32R2) || defined(PSP)
cache_addw((reg<<11)+0x420); // seb reg, reg
cache_addw(0x7c00+reg);
#else
arch that lacks seb
#endif
} else {
cache_addw(0xff); // andi reg, reg, 0xff
cache_addw(0x3000+(reg<<5)+reg);
}
}
// convert a 16bit word to a 32bit dword
// the register is zero-extended (sign==false) or sign-extended (sign==true)
static void gen_extend_word(bool sign,HostReg reg) {
if (sign) {
#if (_MIPS_ISA==MIPS32R2) || defined(PSP)
cache_addw((reg<<11)+0x620); // seh reg, reg
cache_addw(0x7c00+reg);
#else
arch that lacks seh
#endif
} else {
cache_addw(0xffff); // andi reg, reg, 0xffff
cache_addw(0x3000+(reg<<5)+reg);
}
}
// add a 32bit value from memory to a full register
static void gen_add(HostReg reg,void* op) {
gen_mov_word_to_reg(temp2, op, 1);
cache_addw((reg<<11)+0x21); // addu reg, reg, temp2
cache_addw((reg<<5)+temp2);
}
// add a 32bit constant value to a full register
static void gen_add_imm(HostReg reg,Bit32u imm) {
if(!imm) return;
if(((Bit32s)imm >= -32768) && ((Bit32s)imm < 32768)) {
cache_addw((Bit16u)imm); // addiu reg, reg, imm
cache_addw(0x2400+(reg<<5)+reg);
} else {
mov_imm_to_temp1(imm);
cache_addw((reg<<11)+0x21); // addu reg, reg, temp1
cache_addw((reg<<5)+temp1);
}
}
// and a 32bit constant value with a full register
static void gen_and_imm(HostReg reg,Bit32u imm) {
if(imm < 65536) {
cache_addw((Bit16u)imm); // andi reg, reg, imm
cache_addw(0x3000+(reg<<5)+reg);
} else {
mov_imm_to_temp1((Bit32u)imm);
cache_addw((reg<<11)+0x24); // and reg, temp1, reg
cache_addw((temp1<<5)+reg);
}
}
// move a 32bit constant value into memory
static void INLINE gen_mov_direct_dword(void* dest,Bit32u imm) {
gen_mov_dword_to_reg_imm(temp2, imm);
gen_mov_word_from_reg(temp2, dest, 1);
}
// move an address into memory
static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
gen_mov_direct_dword(dest,(Bit32u)imm);
}
// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
static void INLINE gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
if(!imm) return;
gen_mov_word_to_reg(temp2, dest, dword);
gen_add_imm(temp2, imm);
gen_mov_word_from_reg(temp2, dest, dword);
}
// add an 8bit constant value to a dword memory value
static void INLINE gen_add_direct_byte(void* dest,Bit8s imm) {
gen_add_direct_word(dest, (Bit32s)imm, 1);
}
// subtract an 8bit constant value from a dword memory value
static void INLINE gen_sub_direct_byte(void* dest,Bit8s imm) {
gen_add_direct_word(dest, -((Bit32s)imm), 1);
}
// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
static void INLINE gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
gen_add_direct_word(dest, -(Bit32s)imm, dword);
}
// effective address calculation, destination is dest_reg
// scale_reg is scaled by scale (scale_reg*(2^scale)) and
// added to dest_reg, then the immediate value is added
static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
if (scale) {
cache_addw((scale_reg<<11)+(scale<<6)); // sll scale_reg, scale_reg, scale
cache_addw(scale_reg);
}
cache_addw((dest_reg<<11)+0x21); // addu dest_reg, dest_reg, scale_reg
cache_addw((dest_reg<<5)+scale_reg);
gen_add_imm(dest_reg, imm);
}
// effective address calculation, destination is dest_reg
// dest_reg is scaled by scale (dest_reg*(2^scale)),
// then the immediate value is added
static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
if (scale) {
cache_addw((dest_reg<<11)+(scale<<6)); // sll dest_reg, dest_reg, scale
cache_addw(dest_reg);
}
gen_add_imm(dest_reg, imm);
}
#define DELAY cache_addd(0) // nop
// generate a call to a parameterless function
static void INLINE gen_call_function_raw(void * func) {
#if C_DEBUG
if ((cache.pos ^ func) & 0xf0000000) LOG_MSG("jump overflow\n");
#endif
temp1_valid = false;
cache_addd(0x0c000000+(((Bit32u)func>>2)&0x3ffffff)); // jal func
DELAY;
}
// generate a call to a function with paramcount parameters
// note: the parameters are loaded in the architecture specific way
// using the gen_load_param_ functions below
static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
Bit32u proc_addr = (Bit32u)cache.pos;
gen_call_function_raw(func);
return proc_addr;
}
#ifdef __mips_eabi
// max of 8 parameters in $a0-$a3 and $t0-$t3
// load an immediate value as param'th function parameter
static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
gen_mov_dword_to_reg_imm(param+4, imm);
}
// load an address as param'th function parameter
static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
gen_mov_dword_to_reg_imm(param+4, addr);
}
// load a host-register as param'th function parameter
static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
gen_mov_regs(param+4, reg);
}
// load a value from memory as param'th function parameter
static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
gen_mov_word_to_reg(param+4, (void *)mem, 1);
}
#else
other mips abis
#endif
// jump to an address pointed at by ptr, offset is in imm
static void INLINE gen_jmp_ptr(void * ptr,Bits imm=0) {
gen_mov_word_to_reg(temp2, ptr, 1);
if((imm < -32768) || (imm >= 32768)) {
gen_add_imm(temp2, imm);
imm = 0;
}
temp1_valid = false;
cache_addw((Bit16u)imm); // lw temp2, imm(temp2)
cache_addw(0x8C00+(temp2<<5)+temp2);
cache_addd((temp2<<21)+8); // jr temp2
DELAY;
}
// short conditional jump (+-127 bytes) if register is zero
// the destination is set by gen_fill_branch() later
static Bit32u INLINE gen_create_branch_on_zero(HostReg reg,bool dword) {
temp1_valid = false;
if(!dword) {
cache_addw(0xffff); // andi temp1, reg, 0xffff
cache_addw(0x3000+(reg<<5)+temp1);
}
cache_addw(0); // beq $0, reg, 0
cache_addw(0x1000+(dword?reg:temp1));
DELAY;
return ((Bit32u)cache.pos-8);
}
// short conditional jump (+-127 bytes) if register is nonzero
// the destination is set by gen_fill_branch() later
static Bit32u INLINE gen_create_branch_on_nonzero(HostReg reg,bool dword) {
temp1_valid = false;
if(!dword) {
cache_addw(0xffff); // andi temp1, reg, 0xffff
cache_addw(0x3000+(reg<<5)+temp1);
}
cache_addw(0); // bne $0, reg, 0
cache_addw(0x1400+(dword?reg:temp1));
DELAY;
return ((Bit32u)cache.pos-8);
}
// calculate relative offset and fill it into the location pointed to by data
static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
#if C_DEBUG
Bits len=(Bit32u)cache.pos-data;
if (len<0) len=-len;
if (len>126) LOG_MSG("Big jump %d",len);
#endif
temp1_valid = false; // this is a branch target
*(Bit16u*)data=((Bit16u)((Bit32u)cache.pos-data-4)>>2);
}
#if 0 // assume for the moment no branch will go farther then +/- 128KB
// conditional jump if register is nonzero
// for isdword==true the 32bit of the register are tested
// for isdword==false the lowest 8bit of the register are tested
static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
temp1_valid = false;
if (!isdword) {
cache_addw(0xff); // andi temp1, reg, 0xff
cache_addw(0x3000+(reg<<5)+temp1);
}
cache_addw(3); // beq $0, reg, +12
cache_addw(0x1000+(isdword?reg:temp1));
DELAY;
cache_addd(0x00000000); // fill j
DELAY;
return ((Bit32u)cache.pos-8);
}
// compare 32bit-register against zero and jump if value less/equal than zero
static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) {
temp1_valid = false;
cache_addw(3); // bgtz reg, +12
cache_addw(0x1c00+(reg<<5));
DELAY;
cache_addd(0x00000000); // fill j
DELAY;
return ((Bit32u)cache.pos-8);
}
// calculate long relative offset and fill it into the location pointed to by data
static void INLINE gen_fill_branch_long(Bit32u data) {
temp1_valid = false;
// this is an absolute branch
*(Bit32u*)data=0x08000000+(((Bit32u)cache.pos>>2)&0x3ffffff);
}
#else
// conditional jump if register is nonzero
// for isdword==true the 32bit of the register are tested
// for isdword==false the lowest 8bit of the register are tested
static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
temp1_valid = false;
if (!isdword) {
cache_addw(0xff); // andi temp1, reg, 0xff
cache_addw(0x3000+(reg<<5)+temp1);
}
cache_addw(0); // bne $0, reg, 0
cache_addw(0x1400+(isdword?reg:temp1));
DELAY;
return ((Bit32u)cache.pos-8);
}
// compare 32bit-register against zero and jump if value less/equal than zero
static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) {
temp1_valid = false;
cache_addw(0); // blez reg, 0
cache_addw(0x1800+(reg<<5));
DELAY;
return ((Bit32u)cache.pos-8);
}
// calculate long relative offset and fill it into the location pointed to by data
static void INLINE gen_fill_branch_long(Bit32u data) {
gen_fill_branch(data);
}
#endif
static void gen_run_code(void) {
temp1_valid = false;
cache_addd(0x27bdfff0); // addiu $sp, $sp, -16
cache_addd(0xafb00004); // sw $s0, 4($sp)
cache_addd(0x00800008); // jr $a0
cache_addd(0xafbf0000); // sw $ra, 0($sp)
}
// return from a function
static void gen_return_function(void) {
temp1_valid = false;
cache_addd(0x8fbf0000); // lw $ra, 0($sp)
cache_addd(0x8fb00004); // lw $s0, 4($sp)
cache_addd(0x03e00008); // jr $ra
cache_addd(0x27bd0010); // addiu $sp, $sp, 16
}
#ifdef DRC_FLAGS_INVALIDATION
// called when a call to a function can be replaced by a
// call to a simpler function
static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
#ifdef DRC_FLAGS_INVALIDATION_DCODE
// try to avoid function calls but rather directly fill in code
switch (flags_type) {
case t_ADDb:
case t_ADDw:
case t_ADDd:
*(Bit32u*)pos=0x00851021; // addu $v0, $a0, $a1
break;
case t_ORb:
case t_ORw:
case t_ORd:
*(Bit32u*)pos=0x00851025; // or $v0, $a0, $a1
break;
case t_ANDb:
case t_ANDw:
case t_ANDd:
*(Bit32u*)pos=0x00851024; // and $v0, $a0, $a1
break;
case t_SUBb:
case t_SUBw:
case t_SUBd:
*(Bit32u*)pos=0x00851023; // subu $v0, $a0, $a1
break;
case t_XORb:
case t_XORw:
case t_XORd:
*(Bit32u*)pos=0x00851026; // xor $v0, $a0, $a1
break;
case t_CMPb:
case t_CMPw:
case t_CMPd:
case t_TESTb:
case t_TESTw:
case t_TESTd:
*(Bit32u*)pos=0; // nop
break;
case t_INCb:
case t_INCw:
case t_INCd:
*(Bit32u*)pos=0x24820001; // addiu $v0, $a0, 1
break;
case t_DECb:
case t_DECw:
case t_DECd:
*(Bit32u*)pos=0x2482ffff; // addiu $v0, $a0, -1
break;
case t_SHLb:
case t_SHLw:
case t_SHLd:
*(Bit32u*)pos=0x00a41004; // sllv $v0, $a0, $a1
break;
case t_SHRb:
case t_SHRw:
case t_SHRd:
*(Bit32u*)pos=0x00a41006; // srlv $v0, $a0, $a1
break;
case t_SARd:
*(Bit32u*)pos=0x00a41007; // srav $v0, $a0, $a1
break;
#if (_MIPS_ISA==MIPS32R2) || defined(PSP)
case t_RORd:
*(Bit32u*)pos=0x00a41046; // rotr $v0, $a0, $a1
break;
#endif
case t_NEGb:
case t_NEGw:
case t_NEGd:
*(Bit32u*)pos=0x00041023; // subu $v0, $0, $a0
break;
default:
*(Bit32u*)pos=0x0c000000+((((Bit32u)fct_ptr)>>2)&0x3ffffff); // jal simple_func
break;
}
#else
*(Bit32u*)pos=0x0c000000+(((Bit32u)fct_ptr)>>2)&0x3ffffff); // jal simple_func
#endif
}
#endif

View File

@ -0,0 +1,598 @@
/*
* Copyright (C) 2002-2007 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.
*/
// some configuring defines that specify the capabilities of this architecture
// or aspects of the recompiling
// protect FC_ADDR over function calls if necessaray
// #define DRC_PROTECT_ADDR_REG
// try to use non-flags generating functions if possible
#define DRC_FLAGS_INVALIDATION
// try to replace _simple functions by code
// #define DRC_FLAGS_INVALIDATION_DCODE
// type with the same size as a pointer
#define DRC_PTR_SIZE_IM Bit64u
// calling convention modifier
#define DRC_CALL_CONV /* nothing */
#define DRC_FC /* nothing */
// register mapping
typedef Bit8u HostReg;
#define HOST_EAX 0
#define HOST_ECX 1
#define HOST_EDX 2
#define HOST_EBX 3
#define HOST_ESI 6
#define HOST_EDI 7
// register that holds function return values
#define FC_RETOP HOST_EAX
// register used for address calculations, if the ABI does not
// state that this register is preserved across function calls
// then define DRC_PROTECT_ADDR_REG above
#define FC_ADDR HOST_EBX
// register that holds the first parameter
#define FC_OP1 HOST_EDI
// register that holds the second parameter
#define FC_OP2 HOST_ESI
// register that holds byte-accessible temporary values
#define FC_TMP_BA1 HOST_ECX
// register that holds byte-accessible temporary values
#define FC_TMP_BA2 HOST_EDX
// temporary register for LEA
#define TEMP_REG_DRC HOST_ESI
// move a full register from reg_src to reg_dst
static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
cache_addb(0x8b); // mov reg_dst,reg_src
cache_addb(0xc0+(reg_dst<<3)+reg_src);
}
static INLINE void gen_memaddr(HostReg reg,void* data) {
Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+5);
if ((diff<0x80000000LL) && (diff>-0x80000000LL)) {
cache_addb(0x05+(reg<<3));
// RIP-relative addressing is offset after the instruction
cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL));
} else if ((Bit64u)data<0x100000000LL) {
cache_addw(0x2504+(reg<<3));
cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL));
} else {
E_Exit("DRC64:Unhandled memory reference");
}
}
// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
if (!dword) cache_addb(0x66);
cache_addb(0x8b); // mov reg,[data]
gen_memaddr(dest_reg,data);
}
// move a 16bit constant value into dest_reg
// the upper 16bit of the destination register may be destroyed
static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
cache_addb(0x66);
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addw(imm);
}
// move a 32bit constant value into dest_reg
static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addd(imm);
}
// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
if (!dword) cache_addb(0x66);
cache_addb(0x89); // mov [data],reg
gen_memaddr(src_reg,dest);
}
// move an 8bit value from memory into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
cache_addb(0x8a); // mov reg,[data]
gen_memaddr(dest_reg,data);
}
// move an 8bit value from memory into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
cache_addb(0x66);
cache_addb(0x8b); // mov reg,[data]
gen_memaddr(dest_reg,data);
}
// move an 8bit constant value into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
cache_addb(0xb0+dest_reg); // mov reg,imm
cache_addb(imm);
}
// move an 8bit constant value into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
cache_addb(0x66);
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addw(imm);
}
// move the lowest 8bit of a register into memory
static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
cache_addb(0x88); // mov [data],reg
gen_memaddr(src_reg,dest);
}
// convert an 8bit word to a 32bit dword
// the register is zero-extended (sign==false) or sign-extended (sign==true)
static void gen_extend_byte(bool sign,HostReg reg) {
cache_addw(0xb60f+(sign?0x800:0)); // movsx/movzx
cache_addb(0xc0+(reg<<3)+reg);
}
// convert a 16bit word to a 32bit dword
// the register is zero-extended (sign==false) or sign-extended (sign==true)
static void gen_extend_word(bool sign,HostReg reg) {
cache_addw(0xb70f+(sign?0x800:0)); // movsx/movzx
cache_addb(0xc0+(reg<<3)+reg);
}
// add a 32bit value from memory to a full register
static void gen_add(HostReg reg,void* op) {
cache_addb(0x03); // add reg,[data]
gen_memaddr(reg,op);
}
// add a 32bit constant value to a full register
static void gen_add_imm(HostReg reg,Bit32u imm) {
cache_addw(0xc081+(reg<<8)); // add reg,imm
cache_addd(imm);
}
// and a 32bit constant value with a full register
static void gen_and_imm(HostReg reg,Bit32u imm) {
cache_addw(0xe081+(reg<<8)); // and reg,imm
cache_addd(imm);
}
// move a 32bit constant value into memory
static void gen_mov_direct_dword(void* dest,Bit32u imm) {
cache_addw(0x04c7); // mov [data],imm
cache_addb(0x25);
cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL));
cache_addd(imm);
}
// move a 64bit constant value into a full register
static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm) {
cache_addb(0x48);
cache_addb(0xb8+dest_reg); // mov dest_reg,imm
cache_addq(imm);
}
// move an address into memory
static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
gen_mov_reg_qword(HOST_EAX,imm);
cache_addb(0x48);
gen_mov_word_from_reg(HOST_EAX,dest,true);
}
// add an 8bit constant value to a memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
cache_addw(0x0483); // add [data],imm
cache_addb(0x25);
cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL));
cache_addb(imm);
}
// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
if ((imm<128) && dword) {
gen_add_direct_byte(dest,(Bit8s)imm);
return;
}
if (!dword) cache_addb(0x66);
cache_addw(0x0481); // add [data],imm
cache_addb(0x25);
cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL));
if (dword) cache_addd((Bit32u)imm);
else cache_addw((Bit16u)imm);
}
// subtract an 8bit constant value from a memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
cache_addw(0x2c83); // sub [data],imm
cache_addb(0x25);
cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL));
cache_addb(imm);
}
// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
if ((imm<128) && dword) {
gen_sub_direct_byte(dest,(Bit8s)imm);
return;
}
if (!dword) cache_addb(0x66);
cache_addw(0x2c81); // sub [data],imm
cache_addb(0x25);
cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL));
if (dword) cache_addd((Bit32u)imm);
else cache_addw((Bit16u)imm);
}
// effective address calculation, destination is dest_reg
// scale_reg is scaled by scale (scale_reg*(2^scale)) and
// added to dest_reg, then the immediate value is added
static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
Bit8u rm_base;
Bitu imm_size;
if (!imm) {
imm_size=0; rm_base=0x0; //no imm
} else if ((imm>=-128 && imm<=127)) {
imm_size=1; rm_base=0x40; //Signed byte imm
} else {
imm_size=4; rm_base=0x80; //Signed dword imm
}
// ea_reg := ea_reg+TEMP_REG_DRC*(2^scale)+imm
// ea_reg := op1 + op2 *(2^scale)+imm
cache_addb(0x48);
cache_addb(0x8d); //LEA
cache_addb(0x04+(dest_reg << 3)+rm_base); //The sib indicator
cache_addb(dest_reg+(TEMP_REG_DRC<<3)+(scale<<6));
switch (imm_size) {
case 0: break;
case 1:cache_addb(imm);break;
case 4:cache_addd(imm);break;
}
}
// effective address calculation, destination is dest_reg
// dest_reg is scaled by scale (dest_reg*(2^scale)),
// then the immediate value is added
static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
// ea_reg := ea_reg*(2^scale)+imm
// ea_reg := op2 *(2^scale)+imm
cache_addb(0x48);
cache_addb(0x8d); //LEA
cache_addb(0x04+(dest_reg<<3));
cache_addb(0x05+(dest_reg<<3)+(scale<<6));
cache_addd(imm); // always add dword immediate
}
// generate a call to a parameterless function
static void INLINE gen_call_function_raw(void * func) {
cache_addb(0x48);
cache_addb(0xb8); // mov reg,imm64
cache_addq((Bit64u)func);
cache_addw(0xd0ff);
}
// generate a call to a function with paramcount parameters
// note: the parameters are loaded in the architecture specific way
// using the gen_load_param_ functions below
static Bit64u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
// align the stack
cache_addb(0x48);
cache_addw(0xc48b); // mov rax,rsp
cache_addb(0x48);
cache_addw(0xec83); // sub rsp,0x08
cache_addb(0x08); // 0x08==return address pushed onto stack by call
cache_addb(0x48);
cache_addw(0xe483); // and esp,0xfffffffffffffff0
cache_addb(0xf0);
cache_addb(0x48);
cache_addw(0xc483); // add rsp,0x08
cache_addb(0x08);
cache_addb(0x50); // push rax (==old rsp)
Bit64u proc_addr=(Bit64u)cache.pos;
// Do the actual call to the procedure
cache_addb(0x48);
cache_addb(0xb8); // mov reg,imm64
cache_addq((Bit64u)func);
cache_addw(0xd0ff);
// restore stack
cache_addb(0x5c); // pop rsp
return proc_addr;
}
// load an immediate value as param'th function parameter
static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
// move an immediate 32bit value into a 64bit param reg
switch (param) {
case 0: // mov param1,imm32
gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm);
break;
case 1: // mov param2,imm32
gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm);
break;
#if defined (_MSC_VER)
case 2: // mov r8,imm32
cache_addw(0xb849);
cache_addq((Bit32u)imm);
break;
case 3: // mov r9,imm32
cache_addw(0xb949);
cache_addq((Bit32u)imm);
break;
#else
case 2: // mov rdx,imm32
gen_mov_dword_to_reg_imm(HOST_EDX,(Bit32u)imm);
break;
case 3: // mov rcx,imm32
gen_mov_dword_to_reg_imm(HOST_ECX,(Bit32u)imm);
break;
#endif
default:
E_Exit("I(mm) >4 params unsupported");
break;
}
}
// load an address as param'th function parameter
static void INLINE gen_load_param_addr(DRC_PTR_SIZE_IM addr,Bitu param) {
// move an immediate 64bit value into a 64bit param reg
switch (param) {
case 0: // mov param1,addr64
gen_mov_reg_qword(FC_OP1,addr);
break;
case 1: // mov param2,addr64
gen_mov_reg_qword(FC_OP2,addr);
break;
#if defined (_MSC_VER)
case 2: // mov r8,addr64
cache_addw(0xb849);
cache_addq(addr);
break;
case 3: // mov r9,addr64
cache_addw(0xb949);
cache_addq(addr);
break;
#else
case 2: // mov rdx,addr64
gen_mov_reg_qword(HOST_EDX,addr);
break;
case 3: // mov rcx,addr64
gen_mov_reg_qword(HOST_ECX,addr);
break;
#endif
default:
E_Exit("A(ddr) >4 params unsupported");
break;
}
}
// load a host-register as param'th function parameter
static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
// move a register into a 64bit param reg, {inputregs}!={outputregs}
switch (param) {
case 0: // mov param1,reg&7
gen_mov_regs(FC_OP1,reg&7);
break;
case 1: // mov param2,reg&7
gen_mov_regs(FC_OP2,reg&7);
break;
#if defined (_MSC_VER)
case 2: // mov r8,reg&7
cache_addb(0x49);
gen_mov_regs(0,reg&7);
break;
case 3: // mov r9,reg&7
cache_addb(0x49);
gen_mov_regs(1,reg&7);
break;
#else
case 2: // mov rdx,reg&7
gen_mov_regs(HOST_EDX,reg&7);
break;
case 3: // mov rcx,reg&7
gen_mov_regs(HOST_ECX,reg&7);
break;
#endif
default:
E_Exit("R(eg) >4 params unsupported");
break;
}
}
// load a value from memory as param'th function parameter
static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
// move memory content into a 64bit param reg
switch (param) {
case 0: // mov param1,[mem]
gen_mov_word_to_reg(FC_OP1,(void*)mem,true);
break;
case 1: // mov param2,[mem]
gen_mov_word_to_reg(FC_OP2,(void*)mem,true);
break;
#if defined (_MSC_VER)
case 2: // mov r8,[mem]
cache_addb(0x49);
gen_mov_word_to_reg(0,(void*)mem,true);
break;
case 3: // mov r9,[mem]
cache_addb(0x49);
gen_mov_word_to_reg(1,(void*)mem,true);
break;
#else
case 2: // mov rdx,[mem]
gen_mov_word_to_reg(HOST_EDX,(void*)mem,true);
break;
case 3: // mov rcx,[mem]
gen_mov_word_to_reg(HOST_ECX,(void*)mem,true);
break;
#endif
default:
E_Exit("R(eg) >4 params unsupported");
break;
}
}
// jump to an address pointed at by ptr, offset is in imm
static void gen_jmp_ptr(void * ptr,Bits imm=0) {
cache_addw(0xa148); // mov rax,[data]
cache_addq((Bit64u)ptr);
cache_addb(0xff); // jmp [rax+imm]
if (!imm) {
cache_addb(0x20);
} else if ((imm>=-128 && imm<=127)) {
cache_addb(0x60);
cache_addb(imm);
} else {
cache_addb(0xa0);
cache_addd(imm);
}
}
// short conditional jump (+-127 bytes) if register is zero
// the destination is set by gen_fill_branch() later
static Bit64u gen_create_branch_on_zero(HostReg reg,bool dword) {
if (!dword) cache_addb(0x66);
cache_addb(0x0b); // or reg,reg
cache_addb(0xc0+reg+(reg<<3));
cache_addw(0x0074); // jz addr
return ((Bit64u)cache.pos-1);
}
// short conditional jump (+-127 bytes) if register is nonzero
// the destination is set by gen_fill_branch() later
static Bit64u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
if (!dword) cache_addb(0x66);
cache_addb(0x0b); // or reg,reg
cache_addb(0xc0+reg+(reg<<3));
cache_addw(0x0075); // jnz addr
return ((Bit64u)cache.pos-1);
}
// calculate relative offset and fill it into the location pointed to by data
static void gen_fill_branch(DRC_PTR_SIZE_IM data) {
#if C_DEBUG
Bit64s len=(Bit64u)cache.pos-data;
if (len<0) len=-len;
if (len>126) LOG_MSG("Big jump %d",len);
#endif
*(Bit8u*)data=(Bit8u)((Bit64u)cache.pos-data-1);
}
// conditional jump if register is nonzero
// for isdword==true the 32bit of the register are tested
// for isdword==false the lowest 8bit of the register are tested
static Bit64u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
// isdword: cmp reg32,0
// not isdword: cmp reg8,0
cache_addb(0x0a+(isdword?1:0)); // or reg,reg
cache_addb(0xc0+reg+(reg<<3));
cache_addw(0x850f); // jnz
cache_addd(0);
return ((Bit64u)cache.pos-4);
}
// compare 32bit-register against zero and jump if value less/equal than zero
static Bit64u gen_create_branch_long_leqzero(HostReg reg) {
cache_addw(0xf883+(reg<<8));
cache_addb(0x00); // cmp reg,0
cache_addw(0x8e0f); // jle
cache_addd(0);
return ((Bit64u)cache.pos-4);
}
// calculate long relative offset and fill it into the location pointed to by data
static void gen_fill_branch_long(Bit64u data) {
*(Bit32u*)data=(Bit32u)((Bit64u)cache.pos-data-4);
}
static void gen_run_code(void) {
cache_addb(0x53); // push rbx
cache_addw(0xd0ff+(FC_OP1<<8)); // call rdi
cache_addb(0x5b); // pop rbx
}
// return from a function
static void gen_return_function(void) {
cache_addb(0xc3); // ret
}
#ifdef DRC_FLAGS_INVALIDATION
// called when a call to a function can be replaced by a
// call to a simpler function
static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
*(Bit64u*)(pos+2)=(Bit64u)fct_ptr;
}
#endif

View File

@ -0,0 +1,507 @@
/*
* Copyright (C) 2002-2007 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.
*/
// some configuring defines that specify the capabilities of this architecture
// or aspects of the recompiling
// protect FC_ADDR over function calls if necessaray
// #define DRC_PROTECT_ADDR_REG
// try to use non-flags generating functions if possible
#define DRC_FLAGS_INVALIDATION
// try to replace _simple functions by code
#define DRC_FLAGS_INVALIDATION_DCODE
// type with the same size as a pointer
#define DRC_PTR_SIZE_IM Bit32u
// calling convention modifier
#if defined (WIN32)
#define DRC_CALL_CONV _fastcall
#define DRC_FC /* nothing */
#else
#define DRC_CALL_CONV /* nothing */
#define DRC_FC GCC_ATTRIBUTE(fastcall)
#endif
// register mapping
enum HostReg {
HOST_EAX=0,
HOST_ECX,
HOST_EDX,
HOST_EBX,
HOST_ESP,
HOST_EBP,
HOST_ESI,
HOST_EDI
};
// register that holds function return values
#define FC_RETOP HOST_EAX
// register used for address calculations, if the ABI does not
// state that this register is preserved across function calls
// then define DRC_PROTECT_ADDR_REG above
#define FC_ADDR HOST_EBX
// register that holds the first parameter
#define FC_OP1 HOST_ECX
// register that holds the second parameter
#define FC_OP2 HOST_EDX
// register that holds byte-accessible temporary values
#define FC_TMP_BA1 HOST_ECX
// register that holds byte-accessible temporary values
#define FC_TMP_BA2 HOST_EDX
// temporary register for LEA
#define TEMP_REG_DRC HOST_ESI
// move a full register from reg_src to reg_dst
static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
cache_addb(0x8b); // mov reg_dst,reg_src
cache_addb(0xc0+(reg_dst<<3)+reg_src);
}
// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
if (!dword) cache_addb(0x66);
cache_addw(0x058b+(dest_reg<<11)); // mov reg,[data]
cache_addd((Bit32u)data);
}
// move a 16bit constant value into dest_reg
// the upper 16bit of the destination register may be destroyed
static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
cache_addb(0x66);
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addw(imm);
}
// move a 32bit constant value into dest_reg
static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addd(imm);
}
// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
if (!dword) cache_addb(0x66);
cache_addw(0x0589+(src_reg<<11)); // mov [data],reg
cache_addd((Bit32u)dest);
}
// move an 8bit value from memory into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
cache_addw(0x058a+(dest_reg<<11)); // mov reg,[data]
cache_addd((Bit32u)data);
}
// move an 8bit value from memory into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
cache_addb(0x66);
cache_addw(0x058b+(dest_reg<<11)); // mov reg,[data]
cache_addd((Bit32u)data);
}
// move an 8bit constant value into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
cache_addb(0xb0+dest_reg); // mov reg,imm
cache_addb(imm);
}
// move an 8bit constant value into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
cache_addb(0x66);
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addw(imm);
}
// move the lowest 8bit of a register into memory
static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
cache_addw(0x0588+(src_reg<<11)); // mov [data],reg
cache_addd((Bit32u)dest);
}
// convert an 8bit word to a 32bit dword
// the register is zero-extended (sign==false) or sign-extended (sign==true)
static void gen_extend_byte(bool sign,HostReg reg) {
cache_addw(0xb60f+(sign?0x800:0)); // movsx/movzx
cache_addb(0xc0+(reg<<3)+reg);
}
// convert a 16bit word to a 32bit dword
// the register is zero-extended (sign==false) or sign-extended (sign==true)
static void gen_extend_word(bool sign,HostReg reg) {
cache_addw(0xb70f+(sign?0x800:0)); // movsx/movzx
cache_addb(0xc0+(reg<<3)+reg);
}
// add a 32bit value from memory to a full register
static void gen_add(HostReg reg,void* op) {
cache_addw(0x0503+(reg<<11)); // add reg,[data]
cache_addd((Bit32u)op);
}
// add a 32bit constant value to a full register
static void gen_add_imm(HostReg reg,Bit32u imm) {
cache_addw(0xc081+(reg<<8)); // add reg,imm
cache_addd(imm);
}
// and a 32bit constant value with a full register
static void gen_and_imm(HostReg reg,Bit32u imm) {
cache_addw(0xe081+(reg<<8)); // and reg,imm
cache_addd(imm);
}
// move a 32bit constant value into memory
static void gen_mov_direct_dword(void* dest,Bit32u imm) {
cache_addw(0x05c7); // mov [data],imm
cache_addd((Bit32u)dest);
cache_addd(imm);
}
// move an address into memory
static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
gen_mov_direct_dword(dest,(Bit32u)imm);
}
// add an 8bit constant value to a memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
cache_addw(0x0583); // add [data],imm
cache_addd((Bit32u)dest);
cache_addb(imm);
}
// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
if ((imm<128) && dword) {
gen_add_direct_byte(dest,(Bit8s)imm);
return;
}
if (!dword) cache_addb(0x66);
cache_addw(0x0581); // add [data],imm
cache_addd((Bit32u)dest);
if (dword) cache_addd((Bit32u)imm);
else cache_addw((Bit16u)imm);
}
// subtract an 8bit constant value from a memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
cache_addw(0x2d83); // sub [data],imm
cache_addd((Bit32u)dest);
cache_addb(imm);
}
// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
if ((imm<128) && dword) {
gen_sub_direct_byte(dest,(Bit8s)imm);
return;
}
if (!dword) cache_addb(0x66);
cache_addw(0x2d81); // sub [data],imm
cache_addd((Bit32u)dest);
if (dword) cache_addd((Bit32u)imm);
else cache_addw((Bit16u)imm);
}
// effective address calculation, destination is dest_reg
// scale_reg is scaled by scale (scale_reg*(2^scale)) and
// added to dest_reg, then the immediate value is added
static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
Bit8u rm_base;
Bitu imm_size;
if (!imm) {
imm_size=0; rm_base=0x0; //no imm
} else if ((imm>=-128 && imm<=127)) {
imm_size=1; rm_base=0x40; //Signed byte imm
} else {
imm_size=4; rm_base=0x80; //Signed dword imm
}
// ea_reg := ea_reg+TEMP_REG_DRC*(2^scale)+imm
// ea_reg := op1 + op2 *(2^scale)+imm
cache_addb(0x8d); //LEA
cache_addb(0x04+(dest_reg << 3)+rm_base); //The sib indicator
cache_addb(dest_reg+(TEMP_REG_DRC<<3)+(scale<<6));
switch (imm_size) {
case 0: break;
case 1:cache_addb(imm);break;
case 4:cache_addd(imm);break;
}
}
// effective address calculation, destination is dest_reg
// dest_reg is scaled by scale (dest_reg*(2^scale)),
// then the immediate value is added
static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
// ea_reg := ea_reg*(2^scale)+imm
// ea_reg := op2 *(2^scale)+imm
cache_addb(0x8d); //LEA
cache_addb(0x04+(dest_reg<<3));
cache_addb(0x05+(dest_reg<<3)+(scale<<6));
cache_addd(imm); // always add dword immediate
}
// generate a call to a parameterless function
static void INLINE gen_call_function_raw(void * func) {
cache_addb(0xe8);
cache_addd((Bit32u)func - (Bit32u)cache.pos-4);
}
// generate a call to a function with paramcount parameters
// note: the parameters are loaded in the architecture specific way
// using the gen_load_param_ functions below
static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
Bit32u proc_addr=(Bit32u)cache.pos;
// Do the actual call to the procedure
cache_addb(0xe8);
cache_addd((Bit32u)func - (Bit32u)cache.pos-4);
// Restore the params of the stack
if (paramcount) {
cache_addw(0xc483); //add ESP,imm byte
cache_addb((!fastcall)?paramcount*4:0);
}
return proc_addr;
}
// load an immediate value as param'th function parameter
static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
cache_addb(0x68); // push immediate
cache_addd(imm);
}
// load an address as param'th function parameter
static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
cache_addb(0x68); // push immediate (address)
cache_addd(addr);
}
// load a host-register as param'th function parameter
static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
cache_addb(0x50+(reg&7)); // push reg
}
// load a value from memory as param'th function parameter
static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
cache_addw(0x35ff); // push []
cache_addd(mem);
}
// jump to an address pointed at by ptr, offset is in imm
static void gen_jmp_ptr(void * ptr,Bits imm=0) {
gen_mov_word_to_reg(HOST_EAX,ptr,true);
cache_addb(0xff); // jmp [eax+imm]
if (!imm) {
cache_addb(0x20);
} else if ((imm>=-128 && imm<=127)) {
cache_addb(0x60);
cache_addb(imm);
} else {
cache_addb(0xa0);
cache_addd(imm);
}
}
// short conditional jump (+-127 bytes) if register is zero
// the destination is set by gen_fill_branch() later
static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
if (!dword) cache_addb(0x66);
cache_addb(0x0b); // or reg,reg
cache_addb(0xc0+reg+(reg<<3));
cache_addw(0x0074); // jz addr
return ((Bit32u)cache.pos-1);
}
// short conditional jump (+-127 bytes) if register is nonzero
// the destination is set by gen_fill_branch() later
static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
if (!dword) cache_addb(0x66);
cache_addb(0x0b); // or reg,reg
cache_addb(0xc0+reg+(reg<<3));
cache_addw(0x0075); // jnz addr
return ((Bit32u)cache.pos-1);
}
// calculate relative offset and fill it into the location pointed to by data
static void gen_fill_branch(DRC_PTR_SIZE_IM data) {
#if C_DEBUG
Bits len=(Bit32u)cache.pos-data;
if (len<0) len=-len;
if (len>126) LOG_MSG("Big jump %d",len);
#endif
*(Bit8u*)data=(Bit8u)((Bit32u)cache.pos-data-1);
}
// conditional jump if register is nonzero
// for isdword==true the 32bit of the register are tested
// for isdword==false the lowest 8bit of the register are tested
static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
// isdword: cmp reg32,0
// not isdword: cmp reg8,0
cache_addb(0x0a+(isdword?1:0)); // or reg,reg
cache_addb(0xc0+reg+(reg<<3));
cache_addw(0x850f); // jnz
cache_addd(0);
return ((Bit32u)cache.pos-4);
}
// compare 32bit-register against zero and jump if value less/equal than zero
static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
cache_addw(0xf883+(reg<<8));
cache_addb(0x00); // cmp reg,0
cache_addw(0x8e0f); // jle
cache_addd(0);
return ((Bit32u)cache.pos-4);
}
// calculate long relative offset and fill it into the location pointed to by data
static void gen_fill_branch_long(Bit32u data) {
*(Bit32u*)data=((Bit32u)cache.pos-data-4);
}
static void gen_run_code(void) {
cache_addd(0x0424448b); // mov eax,[esp+4]
cache_addb(0x53); // push ebx
cache_addw(0xd0ff); // call eax
cache_addb(0x5b); // pop ebx
}
// return from a function
static void gen_return_function(void) {
cache_addb(0xc3); // ret
}
#ifdef DRC_FLAGS_INVALIDATION
// called when a call to a function can be replaced by a
// call to a simpler function
static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
#ifdef DRC_FLAGS_INVALIDATION_DCODE
// try to avoid function calls but rather directly fill in code
switch (flags_type) {
case t_ADDb:
case t_ADDw:
case t_ADDd:
*(Bit32u*)pos=0xc203c18b;
*(pos+4)=0x90;
break;
case t_ORb:
case t_ORw:
case t_ORd:
*(Bit32u*)pos=0xc20bc18b;
*(pos+4)=0x90;
break;
case t_ANDb:
case t_ANDw:
case t_ANDd:
*(Bit32u*)pos=0xc223c18b;
*(pos+4)=0x90;
break;
case t_SUBb:
case t_SUBw:
case t_SUBd:
*(Bit32u*)pos=0xc22bc18b;
*(pos+4)=0x90;
break;
case t_XORb:
case t_XORw:
case t_XORd:
*(Bit32u*)pos=0xc233c18b;
*(pos+4)=0x90;
break;
case t_CMPb:
case t_CMPw:
case t_CMPd:
case t_TESTb:
case t_TESTw:
case t_TESTd:
*(Bit32u*)pos=0x909003eb;
*(pos+4)=0x90;
break;
case t_INCb:
case t_INCw:
case t_INCd:
*(Bit32u*)pos=0x9040c18b;
*(pos+4)=0x90;
break;
case t_DECb:
case t_DECw:
case t_DECd:
*(Bit32u*)pos=0x9048c18b;
*(pos+4)=0x90;
break;
case t_NEGb:
case t_NEGw:
case t_NEGd:
*(Bit32u*)pos=0xd8f7c18b;
*(pos+4)=0x90;
break;
default:
*(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4));
break;
}
#else
*(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4));
#endif
}
#endif

View File

@ -284,14 +284,12 @@ l_M_Ed:
inst_op1_d=4;
break;
case D_IRETw:
FillFlags();
CPU_IRET(false,GetIP());
if (GETFLAG(IF) && PIC_IRQCheck) {
return CBRET_NONE;
}
continue;
case D_IRETd:
FillFlags();
CPU_IRET(true,GetIP());
if (GETFLAG(IF) && PIC_IRQCheck)
return CBRET_NONE;
@ -407,12 +405,10 @@ l_M_Ed:
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;
@ -481,7 +477,6 @@ l_M_Ed:
cpu.cr0&=(~CR0_TASKSWITCH);
goto nextopcode;
case D_ICEBP:
FillFlags();
CPU_SW_Interrupt_NoIOPLCheck(1,GetIP());
continue;
default:

View File

@ -3,7 +3,6 @@
#define GetIP() (inst.cseip-SegBase(cs))
#define RunException() { \
FillFlags(); \
CPU_Exception(cpu.exception.which,cpu.exception.error); \
continue; \
}

View File

@ -338,8 +338,8 @@ switch (inst.code.op) {
CPU_JMP(true,inst_op2_d,inst_op1_d,GetIP());
continue;
case O_INT:
FillFlags();
#if C_DEBUG
FillFlags();
if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint())
return debugCallback;
else if (DEBUG_IntBreakpoint(inst_op1_b))
@ -379,18 +379,10 @@ switch (inst.code.op) {
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
switch (inst.rm_index) {
case 0x00: /* SLDT */
{
Bitu selector;
CPU_SLDT(selector);
inst_op1_d=(Bit32u)selector;
}
inst_op1_d=(Bit32u)CPU_SLDT();
break;
case 0x01: /* STR */
{
Bitu selector;
CPU_STR(selector);
inst_op1_d=(Bit32u)selector;
}
inst_op1_d=(Bit32u)CPU_STR();
break;
case 0x02: /* LLDT */
if (cpu.cpl) EXCEPTION(EXCEPTION_GP);
@ -401,11 +393,9 @@ switch (inst.code.op) {
if (CPU_LTR(inst_op1_d)) RunException();
goto nextopcode; /* Else value will saved */
case 0x04: /* VERR */
FillFlags();
CPU_VERR(inst_op1_d);
goto nextopcode; /* Else value will saved */
case 0x05: /* VERW */
FillFlags();
CPU_VERW(inst_op1_d);
goto nextopcode; /* Else value will saved */
default:
@ -417,21 +407,13 @@ switch (inst.code.op) {
case O_GRP7d:
switch (inst.rm_index) {
case 0: /* SGDT */
{
Bitu limit,base;
CPU_SGDT(limit,base);
SaveMw(inst.rm_eaa,limit);
SaveMd(inst.rm_eaa+2,base);
goto nextopcode;
}
SaveMw(inst.rm_eaa,CPU_SGDT_limit());
SaveMd(inst.rm_eaa+2,CPU_SGDT_base());
goto nextopcode;
case 1: /* SIDT */
{
Bitu limit,base;
CPU_SIDT(limit,base);
SaveMw(inst.rm_eaa,limit);
SaveMd(inst.rm_eaa+2,base);
goto nextopcode;
}
SaveMw(inst.rm_eaa,CPU_SIDT_limit());
SaveMd(inst.rm_eaa+2,CPU_SIDT_base());
goto nextopcode;
case 2: /* LGDT */
if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
CPU_LGDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF));
@ -441,11 +423,8 @@ switch (inst.code.op) {
CPU_LIDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF));
goto nextopcode;
case 4: /* SMSW */
{
Bitu word;CPU_SMSW(word);
inst_op1_d=word;
break;
}
inst_op1_d=CPU_SMSW();
break;
case 6: /* LMSW */
FillFlags();
if (CPU_LMSW(inst_op1_w)) RunException();
@ -481,7 +460,6 @@ switch (inst.code.op) {
case O_LAR:
{
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
FillFlags();
Bitu ar=inst_op2_d;
CPU_LAR(inst_op1_w,ar);
inst_op1_d=(Bit32u)ar;
@ -490,7 +468,6 @@ switch (inst.code.op) {
case O_LSL:
{
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
FillFlags();
Bitu limit=inst_op2_d;
CPU_LSL(inst_op1_w,limit);
inst_op1_d=(Bit32u)limit;
@ -499,7 +476,6 @@ switch (inst.code.op) {
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);
inst_op1_d=(Bit32u)new_sel;

View File

@ -25,15 +25,14 @@
case 0x01: /* STR */
{
Bitu saveval;
if (!which) CPU_SLDT(saveval);
else CPU_STR(saveval);
if (!which) saveval=CPU_SLDT();
else saveval=CPU_STR();
if (rm >= 0xc0) {GetEArw;*earw=saveval;}
else {GetEAa;SaveMw(eaa,saveval);}
}
break;
case 0x02:case 0x03:case 0x04:case 0x05:
{
FillFlags();
Bitu loadval;
if (rm >= 0xc0 ) {GetEArw;loadval=*earw;}
else {GetEAa;loadval=LoadMw(eaa);}
@ -64,17 +63,15 @@
{
GetRM;Bitu which=(rm>>3)&7;
if (rm < 0xc0) { //First ones all use EA
GetEAa;Bitu limit,base;
GetEAa;Bitu limit;
switch (which) {
case 0x00: /* SGDT */
CPU_SGDT(limit,base);
SaveMw(eaa,limit);
SaveMd(eaa+2,base);
SaveMw(eaa,CPU_SGDT_limit());
SaveMd(eaa+2,CPU_SGDT_base());
break;
case 0x01: /* SIDT */
CPU_SIDT(limit,base);
SaveMw(eaa,limit);
SaveMd(eaa+2,base);
SaveMw(eaa,CPU_SIDT_limit());
SaveMd(eaa+2,CPU_SIDT_base());
break;
case 0x02: /* LGDT */
if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
@ -85,8 +82,7 @@
CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF);
break;
case 0x04: /* SMSW */
CPU_SMSW(limit);
SaveMw(eaa,limit);
SaveMw(eaa,CPU_SMSW());
break;
case 0x06: /* LMSW */
limit=LoadMw(eaa);
@ -98,7 +94,7 @@
break;
}
} else {
GetEArw;Bitu limit;
GetEArw;
switch (which) {
case 0x02: /* LGDT */
if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
@ -107,8 +103,7 @@
if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
goto illegal_opcode;
case 0x04: /* SMSW */
CPU_SMSW(limit);
*earw=limit;
*earw=CPU_SMSW();
break;
case 0x06: /* LMSW */
if (CPU_LMSW(*earw)) RUNEXCEPTION();
@ -122,7 +117,6 @@
CASE_0F_W(0x02) /* LAR Gw,Ew */
{
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
FillFlags();
GetRMrw;Bitu ar=*rmrw;
if (rm >= 0xc0) {
GetEArw;CPU_LAR(*earw,ar);
@ -135,7 +129,6 @@
CASE_0F_W(0x03) /* LSL Gw,Ew */
{
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
FillFlags();
GetRMrw;Bitu limit=*rmrw;
if (rm >= 0xc0) {
GetEArw;CPU_LSL(*earw,limit);
@ -155,7 +148,7 @@
Bitu which=(rm >> 3) & 7;
if (rm < 0xc0 ) {
rm |= 0xc0;
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%d with non-register",which);
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",which);
}
GetEArd;
Bit32u crx_value;
@ -169,7 +162,7 @@
Bitu which=(rm >> 3) & 7;
if (rm < 0xc0 ) {
rm |= 0xc0;
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,DR% with non-register",which);
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,DR%u with non-register",which);
}
GetEArd;
Bit32u drx_value;
@ -183,7 +176,7 @@
Bitu which=(rm >> 3) & 7;
if (rm < 0xc0 ) {
rm |= 0xc0;
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR% with non-register",which);
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",which);
}
GetEArd;
if (CPU_WRITE_CRX(which,*eard)) RUNEXCEPTION();
@ -195,7 +188,7 @@
Bitu which=(rm >> 3) & 7;
if (rm < 0xc0 ) {
rm |= 0xc0;
LOG(LOG_CPU,LOG_ERROR)("MOV DR%,XXX with non-register",which);
LOG(LOG_CPU,LOG_ERROR)("MOV DR%u,XXX with non-register",which);
}
GetEArd;
if (CPU_WRITE_DRX(which,*eard)) RUNEXCEPTION();
@ -207,7 +200,7 @@
Bitu which=(rm >> 3) & 7;
if (rm < 0xc0 ) {
rm |= 0xc0;
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,TR% with non-register",which);
LOG(LOG_CPU,LOG_ERROR)("MOV XXX,TR%u with non-register",which);
}
GetEArd;
Bit32u trx_value;
@ -221,7 +214,7 @@
Bitu which=(rm >> 3) & 7;
if (rm < 0xc0 ) {
rm |= 0xc0;
LOG(LOG_CPU,LOG_ERROR)("MOV TR%,XXX with non-register",which);
LOG(LOG_CPU,LOG_ERROR)("MOV TR%u,XXX with non-register",which);
}
GetEArd;
if (CPU_WRITE_TRX(which,*eard)) RUNEXCEPTION();

View File

@ -170,7 +170,6 @@
CASE_D(0x63) /* ARPL Ed,Rd */
{
if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode;
FillFlags();
GetRMrw;
if (rm >= 0xc0 ) {
GetEArd;Bitu new_sel=(Bit16u)*eard;
@ -398,12 +397,10 @@
continue;
}
CASE_D(0x9c) /* PUSHFD */
FillFlags();
if (CPU_PUSHF(true)) RUNEXCEPTION();
break;
CASE_D(0x9d) /* POPFD */
if (CPU_POPF(true)) RUNEXCEPTION();
lflags.type=t_UNKNOWN;
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
@ -511,7 +508,6 @@
}
CASE_D(0xcf) /* IRET */
{
FillFlags();
CPU_IRET(true,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {

View File

@ -25,8 +25,8 @@
case 0x01: /* STR */
{
Bitu saveval;
if (!which) CPU_SLDT(saveval);
else CPU_STR(saveval);
if (!which) saveval=CPU_SLDT();
else saveval=CPU_STR();
if (rm >= 0xc0) {GetEArw;*earw=(Bit16u)saveval;}
else {GetEAa;SaveMw(eaa,saveval);}
}
@ -34,7 +34,6 @@
case 0x02:case 0x03:case 0x04:case 0x05:
{
/* Just use 16-bit loads since were only using selectors */
FillFlags();
Bitu loadval;
if (rm >= 0xc0 ) {GetEArw;loadval=*earw;}
else {GetEAa;loadval=LoadMw(eaa);}
@ -66,17 +65,15 @@
{
GetRM;Bitu which=(rm>>3)&7;
if (rm < 0xc0) { //First ones all use EA
GetEAa;Bitu limit,base;
GetEAa;Bitu limit;
switch (which) {
case 0x00: /* SGDT */
CPU_SGDT(limit,base);
SaveMw(eaa,(Bit16u)limit);
SaveMd(eaa+2,(Bit32u)base);
SaveMw(eaa,(Bit16u)CPU_SGDT_limit());
SaveMd(eaa+2,(Bit32u)CPU_SGDT_base());
break;
case 0x01: /* SIDT */
CPU_SIDT(limit,base);
SaveMw(eaa,(Bit16u)limit);
SaveMd(eaa+2,(Bit32u)base);
SaveMw(eaa,(Bit16u)CPU_SIDT_limit());
SaveMd(eaa+2,(Bit32u)CPU_SIDT_base());
break;
case 0x02: /* LGDT */
if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
@ -87,8 +84,7 @@
CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2));
break;
case 0x04: /* SMSW */
CPU_SMSW(limit);
SaveMw(eaa,(Bit16u)limit);
SaveMw(eaa,(Bit16u)CPU_SMSW());
break;
case 0x06: /* LMSW */
limit=LoadMw(eaa);
@ -100,7 +96,7 @@
break;
}
} else {
GetEArd;Bitu limit;
GetEArd;
switch (which) {
case 0x02: /* LGDT */
if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
@ -109,8 +105,7 @@
if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
goto illegal_opcode;
case 0x04: /* SMSW */
CPU_SMSW(limit);
*eard=(Bit32u)limit;
*eard=(Bit32u)CPU_SMSW();
break;
case 0x06: /* LMSW */
if (CPU_LMSW(*eard)) RUNEXCEPTION();
@ -127,7 +122,6 @@
CASE_0F_D(0x02) /* LAR Gd,Ed */
{
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
FillFlags();
GetRMrd;Bitu ar=*rmrd;
if (rm >= 0xc0) {
GetEArw;CPU_LAR(*earw,ar);
@ -140,7 +134,6 @@
CASE_0F_D(0x03) /* LSL Gd,Ew */
{
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
FillFlags();
GetRMrd;Bitu limit=*rmrd;
/* Just load 16-bit values for selectors */
if (rm >= 0xc0) {

View File

@ -239,7 +239,6 @@
CASE_W(0x63) /* ARPL Ew,Rw */
{
if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
FillFlags();
GetRMrw;
if (rm >= 0xc0 ) {
GetEArw;Bitu new_sel=*earw;
@ -574,12 +573,10 @@
CASE_B(0x9b) /* WAIT */
break; /* No waiting here */
CASE_W(0x9c) /* PUSHF */
FillFlags();
if (CPU_PUSHF(false)) RUNEXCEPTION();
break;
CASE_W(0x9d) /* POPF */
if (CPU_POPF(false)) RUNEXCEPTION();
lflags.type=t_UNKNOWN;
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
@ -740,8 +737,8 @@
CPU_RET(false,0,GETIP);
continue;
CASE_B(0xcc) /* INT3 */
FillFlags();
#if C_DEBUG
FillFlags();
if (DEBUG_Breakpoint())
return debugCallback;
#endif
@ -753,8 +750,8 @@
CASE_B(0xcd) /* INT Ib */
{
Bit8u num=Fetchb();
FillFlags();
#if C_DEBUG
FillFlags();
if (DEBUG_IntBreakpoint(num)) {
return debugCallback;
}
@ -767,7 +764,6 @@
}
CASE_B(0xce) /* INTO */
if (get_OF()) {
FillFlags();
CPU_SW_Interrupt(4,GETIP);
#if CPU_TRAP_CHECK
cpu.trap_skip=true;
@ -777,7 +773,6 @@
break;
CASE_W(0xcf) /* IRET */
{
FillFlags();
CPU_IRET(false,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
@ -953,7 +948,6 @@
LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK"); /* FIXME: see case D_LOCK in core_full/load.h */
break;
CASE_B(0xf1) /* ICEBP */
FillFlags();
CPU_SW_Interrupt_NoIOPLCheck(1,GETIP);
#if CPU_TRAP_CHECK
cpu.trap_skip=true;

View File

@ -42,7 +42,6 @@ static INLINE Bit32s Fetchds() {
#define RUNEXCEPTION() { \
FillFlags(); \
CPU_Exception(cpu.exception.which,cpu.exception.error); \
continue; \
}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: cpu.cpp,v 1.98 2007/02/22 08:35:34 qbix79 Exp $ */
/* $Id: cpu.cpp,v 1.102 2007/06/12 20:22:07 c2woody Exp $ */
#include <assert.h>
#include <sstream>
@ -27,6 +27,7 @@
#include "mapper.h"
#include "setup.h"
#include "paging.h"
#include "lazyflags.h"
#include "support.h"
Bitu DEBUG_EnableDebugger(void);
@ -62,10 +63,16 @@ Bitu CPU_AutoDetermineMode;
void CPU_Core_Full_Init(void);
void CPU_Core_Normal_Init(void);
void CPU_Core_Simple_Init(void);
#if (C_DYNAMIC_X86)
void CPU_Core_Dyn_X86_Init(void);
void CPU_Core_Dyn_X86_Cache_Init(bool enable_cache);
void CPU_Core_Dyn_X86_Cache_Close(void);
void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu);
#elif (C_DYNREC)
void CPU_Core_Dynrec_Init(void);
void CPU_Core_Dynrec_Cache_Init(bool enable_cache);
void CPU_Core_Dynrec_Cache_Close(void);
#endif
/* In debug mode exceptions are tested and dosbox exits when
* a unhandled exception state is detected.
@ -87,7 +94,7 @@ void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu);
#if defined(CPU_CHECK_IGNORE)
#define CPU_CHECK_COND(cond,msg,exc,sel) { \
cond; \
if (cond) do {} while (0); \
}
#elif defined(CPU_CHECK_EXCEPT)
#define CPU_CHECK_COND(cond,msg,exc,sel) { \
@ -178,6 +185,7 @@ bool CPU_POPF(Bitu use32) {
if (use32)
CPU_SetFlags(CPU_Pop32(),mask);
else CPU_SetFlags(CPU_Pop16(),mask & 0xffff);
DestroyConditionFlags();
return false;
}
@ -186,6 +194,7 @@ bool CPU_PUSHF(Bitu use32) {
/* Not enough privileges to execute PUSHF */
return CPU_PrepareException(EXCEPTION_GP,0);
}
FillFlags();
if (use32)
CPU_Push32(reg_flags & 0xfcffff);
else CPU_Push16(reg_flags);
@ -258,6 +267,7 @@ enum TSwitchType {
};
bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype,Bitu old_eip) {
FillFlags();
TaskStateSegment new_tss;
if (!new_tss.SetSelector(new_tss_selector))
E_Exit("Illegal TSS for switch, selector=%x, switchtype=%x",new_tss_selector,tstype);
@ -447,6 +457,7 @@ void CPU_Exception(Bitu which,Bitu error ) {
Bit8u lastint;
void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) {
lastint=num;
FillFlags();
#if C_DEBUG
switch (num) {
case 0xcd:
@ -666,6 +677,7 @@ void CPU_IRET(bool use32,Bitu oldeip) {
CPU_SetFlags(CPU_Pop16(),FMASK_ALL & 0xffff);
}
cpu.code.big=false;
DestroyConditionFlags();
return;
} else { /* Protected mode IRET */
if (reg_flags & FLAG_VM) {
@ -686,6 +698,7 @@ void CPU_IRET(bool use32,Bitu oldeip) {
CPU_SetFlags(CPU_Pop16(),FMASK_NORMAL|FLAG_NT);
}
cpu.code.big=false;
DestroyConditionFlags();
return;
}
}
@ -717,6 +730,7 @@ void CPU_IRET(bool use32,Bitu oldeip) {
n_gs=CPU_Pop32() & 0xffff;
CPU_SetFlags(n_flags,FMASK_ALL | FLAG_VM);
DestroyConditionFlags();
cpu.cpl=3;
CPU_SetSegGeneral(ss,n_ss);
@ -779,6 +793,7 @@ void CPU_IRET(bool use32,Bitu oldeip) {
Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL;
if (GETFLAG_IOPL<cpu.cpl) mask &= (~FLAG_IF);
CPU_SetFlags(n_flags,mask);
DestroyConditionFlags();
LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big);
} else {
/* Return to outer level */
@ -823,6 +838,7 @@ void CPU_IRET(bool use32,Bitu oldeip) {
Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL;
if (GETFLAG_IOPL<cpu.cpl) mask &= (~FLAG_IF);
CPU_SetFlags(n_flags,mask);
DestroyConditionFlags();
cpu.cpl=n_cs_rpl;
reg_eip=n_eip;
@ -1163,8 +1179,8 @@ call_code:
LOG(LOG_CPU,LOG_NORMAL)("CALL:TSS to %X",selector);
CPU_SwitchTask(selector,TSwitch_CALL_INT,oldeip);
break;
case DESC_INVALID:
// used by some installers
case DESC_DATA_EU_RW_NA: // vbdos
case DESC_INVALID: // used by some installers
CPU_Exception(EXCEPTION_GP,selector & 0xfffc);
return;
default:
@ -1377,8 +1393,8 @@ RET_same_level:
}
void CPU_SLDT(Bitu & selector) {
selector=cpu.gdt.SLDT();
Bitu CPU_SLDT(void) {
return cpu.gdt.SLDT();
}
bool CPU_LLDT(Bitu selector) {
@ -1390,8 +1406,8 @@ bool CPU_LLDT(Bitu selector) {
return false;
}
void CPU_STR(Bitu & selector) {
selector=cpu_tss.selector;
Bitu CPU_STR(void) {
return cpu_tss.selector;
}
bool CPU_LTR(Bitu selector) {
@ -1433,14 +1449,18 @@ void CPU_LIDT(Bitu limit,Bitu base) {
cpu.idt.SetBase(base);
}
void CPU_SGDT(Bitu & limit,Bitu & base) {
limit=cpu.gdt.GetLimit();
base=cpu.gdt.GetBase();
Bitu CPU_SGDT_base(void) {
return cpu.gdt.GetBase();
}
Bitu CPU_SGDT_limit(void) {
return cpu.gdt.GetLimit();
}
void CPU_SIDT(Bitu & limit,Bitu & base) {
limit=cpu.idt.GetLimit();
base=cpu.idt.GetBase();
Bitu CPU_SIDT_base(void) {
return cpu.idt.GetBase();
}
Bitu CPU_SIDT_limit(void) {
return cpu.idt.GetLimit();
}
@ -1610,11 +1630,11 @@ bool CPU_READ_TRX(Bitu tr,Bit32u & retvalue) {
}
void CPU_SMSW(Bitu & word) {
word=cpu.cr0;
Bitu CPU_SMSW(void) {
return cpu.cr0;
}
Bitu CPU_LMSW(Bitu word) {
bool CPU_LMSW(Bitu word) {
if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0);
word&=0xf;
if (cpu.cr0 & 1) word|=1;
@ -1624,6 +1644,7 @@ Bitu CPU_LMSW(Bitu word) {
}
void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
FillFlags();
if ((dest_sel & 3) < (src_sel & 3)) {
dest_sel=(dest_sel & 0xfffc) + (src_sel & 3);
// dest_sel|=0xff3f0000;
@ -1634,6 +1655,7 @@ void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
}
void CPU_LAR(Bitu selector,Bitu & ar) {
FillFlags();
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
@ -1685,6 +1707,7 @@ void CPU_LAR(Bitu selector,Bitu & ar) {
}
void CPU_LSL(Bitu selector,Bitu & limit) {
FillFlags();
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
@ -1727,6 +1750,7 @@ void CPU_LSL(Bitu selector,Bitu & limit) {
}
void CPU_VERR(Bitu selector) {
FillFlags();
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
@ -1759,6 +1783,7 @@ void CPU_VERR(Bitu selector) {
}
void CPU_VERW(Bitu selector) {
FillFlags();
if (selector == 0) {
SETFLAGBIT(ZF,false);
return;
@ -2050,6 +2075,8 @@ public:
CPU_Core_Full_Init();
#if (C_DYNAMIC_X86)
CPU_Core_Dyn_X86_Init();
#elif (C_DYNREC)
CPU_Core_Dynrec_Init();
#endif
MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles");
MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles");
@ -2153,6 +2180,10 @@ public:
cpudecoder=&CPU_Core_Normal_Run;
CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CORE;
}
#elif (C_DYNREC)
else if (!strcasecmp(core,"dynamic")) {
cpudecoder=&CPU_Core_Dynrec_Run;
}
#endif
else {
LOG_MSG("CPU:Unknown core type %s, switching back to normal.",core);
@ -2160,6 +2191,8 @@ public:
#if (C_DYNAMIC_X86)
CPU_Core_Dyn_X86_Cache_Init(!strcasecmp(core,"dynamic") || !strcasecmp(core,"dynamic_nodhfpu"));
#elif (C_DYNREC)
CPU_Core_Dynrec_Cache_Init(!strcasecmp(core,"dynamic"));
#endif
if(CPU_CycleMax <= 0) CPU_CycleMax = 3000;
@ -2177,6 +2210,8 @@ static CPU * test;
void CPU_ShutDown(Section* sec) {
#if (C_DYNAMIC_X86)
CPU_Core_Dyn_X86_Cache_Close();
#elif (C_DYNREC)
CPU_Core_Dynrec_Cache_Close();
#endif
delete test;
}

View File

@ -31,7 +31,7 @@ LazyFlags lflags;
/* CF Carry Flag -- Set on high-order bit carry or borrow; cleared
otherwise.
*/
Bitu get_CF(void) {
Bit32u get_CF(void) {
switch (lflags.type) {
case t_UNKNOWN:
@ -43,7 +43,6 @@ Bitu get_CF(void) {
case t_DECd:
case t_MUL:
return GETFLAG(CF);
break;
case t_ADDb:
return (lf_resb<lf_var1b);
case t_ADDw:
@ -129,7 +128,7 @@ Bitu get_CF(void) {
four bits of AL; cleared otherwise. Used for decimal
arithmetic.
*/
Bitu get_AF(void) {
Bit32u get_AF(void) {
Bitu type=lflags.type;
switch (type) {
case t_UNKNOWN:
@ -170,6 +169,18 @@ Bitu get_AF(void) {
return lf_var1w & 0x0f;
case t_NEGd:
return lf_var1d & 0x0f;
case t_SHLb:
case t_SHRb:
case t_SARb:
return lf_var2b & 0x1f;
case t_SHLw:
case t_SHRw:
case t_SARw:
return lf_var2w & 0x1f;
case t_SHLd:
case t_SHRd:
case t_SARd:
return lf_var2d & 0x1f;
case t_ORb:
case t_ORw:
case t_ORd:
@ -182,15 +193,6 @@ Bitu get_AF(void) {
case t_TESTb:
case t_TESTw:
case t_TESTd:
case t_SHLb:
case t_SHLw:
case t_SHLd:
case t_SHRb:
case t_SHRw:
case t_SHRd:
case t_SARb:
case t_SARw:
case t_SARd:
case t_DSHLw:
case t_DSHLd:
case t_DSHRw:
@ -207,7 +209,7 @@ Bitu get_AF(void) {
/* ZF Zero Flag -- Set if result is zero; cleared otherwise.
*/
Bitu get_ZF(void) {
Bit32u get_ZF(void) {
Bitu type=lflags.type;
switch (type) {
case t_UNKNOWN:
@ -275,7 +277,7 @@ Bitu get_ZF(void) {
/* SF Sign Flag -- Set equal to high-order bit of result (0 is
positive, 1 if negative).
*/
Bitu get_SF(void) {
Bit32u get_SF(void) {
Bitu type=lflags.type;
switch (type) {
case t_UNKNOWN:
@ -341,7 +343,7 @@ Bitu get_SF(void) {
return false;
}
Bitu get_OF(void) {
Bit32u get_OF(void) {
Bitu type=lflags.type;
switch (type) {
case t_UNKNOWN:
@ -387,18 +389,24 @@ Bitu get_OF(void) {
case t_NEGd:
return (lf_var1d == 0x80000000);
case t_SHLb:
case t_SHRb:
return (lf_resb ^ lf_var1b) & 0x80;
case t_SHLw:
case t_SHRw:
case t_DSHRw:
case t_DSHLw:
return (lf_resw ^ lf_var1w) & 0x8000;
case t_SHLd:
case t_SHRd:
case t_DSHRd:
case t_DSHLd:
return (lf_resd ^ lf_var1d) & 0x80000000;
case t_SHRb:
if ((lf_var2b&0x1f)==1) return (lf_var1b > 0x80);
else return false;
case t_SHRw:
if ((lf_var2b&0x1f)==1) return (lf_var1w > 0x8000);
else return false;
case t_SHRd:
if ((lf_var2b&0x1f)==1) return (lf_var1d > 0x80000000);
else return false;
case t_ORb:
case t_ORw:
case t_ORd:
@ -442,14 +450,14 @@ Bit16u parity_lookup[256] = {
FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF
};
Bitu get_PF(void) {
Bit32u get_PF(void) {
switch (lflags.type) {
case t_UNKNOWN:
return GETFLAG(PF);
default:
return (parity_lookup[lf_resb]);;
return (parity_lookup[lf_resb]);
};
return false;
return 0;
}
@ -486,6 +494,7 @@ Bitu FillFlags(void) {
#define SETCF(NEWBIT) reg_flags=(reg_flags & ~FLAG_CF)|(NEWBIT);
#define SET_FLAG SETFLAGBIT
Bitu FillFlags(void) {
switch (lflags.type) {
case t_UNKNOWN:
@ -683,6 +692,7 @@ Bitu FillFlags(void) {
DOFLAG_SFb;
SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2b&0x1f));
break;
case t_SHLw:
if (lf_var2b>16) SET_FLAG(CF,false);
@ -691,6 +701,7 @@ Bitu FillFlags(void) {
DOFLAG_SFw;
SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2w&0x1f));
break;
case t_SHLd:
SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1);
@ -698,6 +709,7 @@ Bitu FillFlags(void) {
DOFLAG_SFd;
SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2d&0x1f));
break;
@ -721,22 +733,28 @@ Bitu FillFlags(void) {
SET_FLAG(CF,(lf_var1b >> (lf_var2b - 1)) & 1);
DOFLAG_ZFb;
DOFLAG_SFb;
SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80);
if ((lf_var2b&0x1f)==1) SET_FLAG(OF,(lf_var1b >= 0x80));
else SET_FLAG(OF,false);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2b&0x1f));
break;
case t_SHRw:
SET_FLAG(CF,(lf_var1w >> (lf_var2b - 1)) & 1);
DOFLAG_ZFw;
DOFLAG_SFw;
SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
if ((lf_var2w&0x1f)==1) SET_FLAG(OF,(lf_var1w >= 0x8000));
else SET_FLAG(OF,false);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2w&0x1f));
break;
case t_SHRd:
SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1);
DOFLAG_ZFd;
DOFLAG_SFd;
SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
if ((lf_var2d&0x1f)==1) SET_FLAG(OF,(lf_var1d >= 0x80000000));
else SET_FLAG(OF,false);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2d&0x1f));
break;
@ -762,6 +780,7 @@ Bitu FillFlags(void) {
DOFLAG_SFb;
SET_FLAG(OF,false);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2b&0x1f));
break;
case t_SARw:
SET_FLAG(CF,(((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1);
@ -769,6 +788,7 @@ Bitu FillFlags(void) {
DOFLAG_SFw;
SET_FLAG(OF,false);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2w&0x1f));
break;
case t_SARd:
SET_FLAG(CF,(((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1);
@ -776,6 +796,7 @@ Bitu FillFlags(void) {
DOFLAG_SFd;
SET_FLAG(OF,false);
DOFLAG_PF;
SET_FLAG(AF,(lf_var2d&0x1f));
break;
case t_INCb:
@ -860,4 +881,308 @@ Bitu FillFlags(void) {
return reg_flags;
}
void FillFlagsNoCFOF(void) {
switch (lflags.type) {
case t_UNKNOWN:
return;
case t_ADDb:
DOFLAG_AF;
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_ADDw:
DOFLAG_AF;
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_ADDd:
DOFLAG_AF;
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_ADCb:
DOFLAG_AF;
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_ADCw:
DOFLAG_AF;
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_ADCd:
DOFLAG_AF;
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_SBBb:
DOFLAG_AF;
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_SBBw:
DOFLAG_AF;
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_SBBd:
DOFLAG_AF;
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_SUBb:
case t_CMPb:
DOFLAG_AF;
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_SUBw:
case t_CMPw:
DOFLAG_AF;
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_SUBd:
case t_CMPd:
DOFLAG_AF;
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_ORb:
SET_FLAG(AF,false);
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_ORw:
SET_FLAG(AF,false);
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_ORd:
SET_FLAG(AF,false);
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_TESTb:
case t_ANDb:
SET_FLAG(AF,false);
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_TESTw:
case t_ANDw:
SET_FLAG(AF,false);
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_TESTd:
case t_ANDd:
SET_FLAG(AF,false);
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_XORb:
SET_FLAG(AF,false);
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_XORw:
SET_FLAG(AF,false);
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_XORd:
SET_FLAG(AF,false);
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_SHLb:
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2b&0x1f));
break;
case t_SHLw:
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2w&0x1f));
break;
case t_SHLd:
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2d&0x1f));
break;
case t_DSHLw:
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_DSHLd:
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_SHRb:
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2b&0x1f));
break;
case t_SHRw:
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2w&0x1f));
break;
case t_SHRd:
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2d&0x1f));
break;
case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_DSHRd:
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_SARb:
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2b&0x1f));
break;
case t_SARw:
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2w&0x1f));
break;
case t_SARd:
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
SET_FLAG(AF,(lf_var2d&0x1f));
break;
case t_INCb:
SET_FLAG(AF,(lf_resb & 0x0f) == 0);
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_INCw:
SET_FLAG(AF,(lf_resw & 0x0f) == 0);
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_INCd:
SET_FLAG(AF,(lf_resd & 0x0f) == 0);
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_DECb:
SET_FLAG(AF,(lf_resb & 0x0f) == 0x0f);
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_DECw:
SET_FLAG(AF,(lf_resw & 0x0f) == 0x0f);
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_DECd:
SET_FLAG(AF,(lf_resd & 0x0f) == 0x0f);
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_NEGb:
SET_FLAG(AF,(lf_resb & 0x0f) != 0);
DOFLAG_ZFb;
DOFLAG_SFb;
DOFLAG_PF;
break;
case t_NEGw:
SET_FLAG(AF,(lf_resw & 0x0f) != 0);
DOFLAG_ZFw;
DOFLAG_SFw;
DOFLAG_PF;
break;
case t_NEGd:
SET_FLAG(AF,(lf_resd & 0x0f) != 0);
DOFLAG_ZFd;
DOFLAG_SFd;
DOFLAG_PF;
break;
case t_DIV:
case t_MUL:
break;
default:
LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type);
break;
}
lflags.type=t_UNKNOWN;
}
void DestroyConditionFlags(void) {
lflags.type=t_UNKNOWN;
}
#endif

View File

@ -230,13 +230,13 @@
#define ROLB(op1,op2,load,save) \
if (!(op2&0x7)) { \
if (op2&0x18) { \
FillFlags(); \
FillFlagsNoCFOF(); \
SETFLAGBIT(CF,op1 & 1); \
SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); \
} \
break; \
} \
FillFlags(); \
FillFlagsNoCFOF(); \
lf_var1b=load(op1); \
lf_var2b=op2&0x07; \
lf_resb=(lf_var1b << lf_var2b) | \
@ -248,12 +248,13 @@
#define ROLW(op1,op2,load,save) \
if (!(op2&0xf)) { \
if (op2&0x10) { \
FillFlags(); \
FillFlagsNoCFOF(); \
SETFLAGBIT(CF,op1 & 1); \
SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); \
} \
break; \
} \
FillFlags(); \
FillFlagsNoCFOF(); \
lf_var1w=load(op1); \
lf_var2b=op2&0xf; \
lf_resw=(lf_var1w << lf_var2b) | \
@ -264,7 +265,7 @@
#define ROLD(op1,op2,load,save) \
if (!op2) break; \
FillFlags(); \
FillFlagsNoCFOF(); \
lf_var1d=load(op1); \
lf_var2b=op2; \
lf_resd=(lf_var1d << lf_var2b) | \
@ -277,48 +278,49 @@
#define RORB(op1,op2,load,save) \
if (!(op2&0x7)) { \
if (op2&0x10) { \
FillFlags(); \
FillFlagsNoCFOF(); \
SETFLAGBIT(CF,op1>>7); \
SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); \
} \
break; \
} \
FillFlags(); \
FillFlagsNoCFOF(); \
lf_var1b=load(op1); \
lf_var2b=op2&0x07; \
lf_resb=(lf_var1b >> lf_var2b) | \
(lf_var1b << (8-lf_var2b)); \
save(op1,lf_resb); \
SETFLAGBIT(CF,lf_resb & 0x80); \
if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80);
SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80);
#define RORW(op1,op2,load,save) \
if (!(op2&0xf)) { \
if (op2&0x10) { \
FillFlags(); \
FillFlagsNoCFOF(); \
SETFLAGBIT(CF,op1>>15); \
SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1)); \
} \
break; \
} \
FillFlags(); \
FillFlagsNoCFOF(); \
lf_var1w=load(op1); \
lf_var2b=op2&0xf; \
lf_resw=(lf_var1w >> lf_var2b) | \
(lf_var1w << (16-lf_var2b)); \
save(op1,lf_resw); \
SETFLAGBIT(CF,lf_resw & 0x8000); \
if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000);
SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000);
#define RORD(op1,op2,load,save) \
if (!op2) break; \
FillFlags(); \
FillFlagsNoCFOF(); \
lf_var1d=load(op1); \
lf_var2b=op2; \
lf_resd=(lf_var1d >> lf_var2b) | \
(lf_var1d << (32-lf_var2b)); \
save(op1,lf_resd); \
SETFLAGBIT(CF,lf_resd & 0x80000000); \
if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000);
SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000);
#define RCLB(op1,op2,load,save) \
@ -376,7 +378,7 @@
(lf_var1b << (9-lf_var2b)); \
save(op1,lf_resb); \
SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); \
SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80); \
SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); \
}
#define RCRW(op1,op2,load,save) \
@ -389,7 +391,7 @@
(lf_var1w << (17-lf_var2b)); \
save(op1,lf_resw); \
SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); \
SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000); \
SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); \
}
#define RCRD(op1,op2,load,save) \
@ -406,7 +408,7 @@
} \
save(op1,lf_resd); \
SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); \
SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000); \
SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); \
}
@ -520,12 +522,14 @@
#define DAS() \
{ \
Bit8u osigned=reg_al & 0x80; \
if (((reg_al & 0x0f) > 9) || get_AF()) { \
if ((reg_al>0x99) || get_CF()) { \
reg_al-=0x60; \
SETFLAGBIT(CF,true); \
} else { \
SETFLAGBIT(CF,false); \
SETFLAGBIT(CF,(reg_al<=0x05)); \
} \
reg_al-=6; \
SETFLAGBIT(AF,true); \
@ -538,44 +542,61 @@
} \
SETFLAGBIT(AF,false); \
} \
SETFLAGBIT(OF,osigned && ((reg_al&0x80)==0)); \
SETFLAGBIT(SF,(reg_al&0x80)); \
SETFLAGBIT(ZF,(reg_al==0)); \
SETFLAGBIT(PF,parity_lookup[reg_al]); \
lflags.type=t_UNKNOWN;
lflags.type=t_UNKNOWN; \
}
#define AAA() \
if (get_AF() || ((reg_al & 0xf) > 9)) \
{ \
SETFLAGBIT(SF,((reg_al>=0x7a) && (reg_al<=0xf9))); \
if ((reg_al & 0xf) > 9) { \
SETFLAGBIT(OF,(reg_al&0xf0)==0x70); \
reg_ax += 0x106; \
SETFLAGBIT(AF,true); \
SETFLAGBIT(CF,true); \
SETFLAGBIT(ZF,(reg_al == 0)); \
SETFLAGBIT(AF,true); \
} else if (get_AF()) { \
reg_ax += 0x106; \
SETFLAGBIT(OF,false); \
SETFLAGBIT(CF,true); \
SETFLAGBIT(ZF,false); \
SETFLAGBIT(AF,true); \
} else { \
SETFLAGBIT(AF,false); \
SETFLAGBIT(OF,false); \
SETFLAGBIT(CF,false); \
SETFLAGBIT(ZF,(reg_al == 0)); \
SETFLAGBIT(AF,false); \
} \
SETFLAGBIT(PF,parity_lookup[reg_al]); \
reg_al &= 0x0F; \
lflags.type=t_UNKNOWN; \
SETFLAGBIT(SF,0); \
SETFLAGBIT(OF,0); \
SETFLAGBIT(ZF,(reg_al == 0)); \
SETFLAGBIT(PF,parity_lookup[reg_al]);
lflags.type=t_UNKNOWN;
#define AAS() \
if (((reg_al & 0x0f)>9) || get_AF()) { \
if ((reg_al & 0x0f)>9) { \
SETFLAGBIT(SF,(reg_al>0x85)); \
reg_ax -= 0x106; \
SETFLAGBIT(AF,true); \
SETFLAGBIT(OF,false); \
SETFLAGBIT(CF,true); \
SETFLAGBIT(AF,true); \
} else if (get_AF()) { \
SETFLAGBIT(OF,((reg_al>=0x80) && (reg_al<=0x85))); \
SETFLAGBIT(SF,(reg_al<0x06) || (reg_al>0x85)); \
reg_ax -= 0x106; \
SETFLAGBIT(CF,true); \
SETFLAGBIT(AF,true); \
} else { \
SETFLAGBIT(AF,false); \
SETFLAGBIT(SF,(reg_al>=0x80)); \
SETFLAGBIT(OF,false); \
SETFLAGBIT(CF,false); \
SETFLAGBIT(AF,false); \
} \
reg_al &= 0x0F; \
lflags.type=t_UNKNOWN; \
SETFLAGBIT(SF,0); \
SETFLAGBIT(OF,0); \
SETFLAGBIT(ZF,(reg_al == 0)); \
SETFLAGBIT(PF,parity_lookup[reg_al]);
SETFLAGBIT(PF,parity_lookup[reg_al]); \
reg_al &= 0x0F; \
lflags.type=t_UNKNOWN;
#define AAM(op1) \
{ \
@ -586,9 +607,9 @@
SETFLAGBIT(SF,(reg_al & 0x80)); \
SETFLAGBIT(ZF,(reg_al == 0)); \
SETFLAGBIT(PF,parity_lookup[reg_al]); \
SETFLAGBIT(CF,0); \
SETFLAGBIT(OF,0); \
SETFLAGBIT(AF,0); \
SETFLAGBIT(CF,false); \
SETFLAGBIT(OF,false); \
SETFLAGBIT(AF,false); \
lflags.type=t_UNKNOWN; \
} else EXCEPTION(0); \
}
@ -601,9 +622,9 @@
Bit16u ax2 = ax1 + reg_al; \
reg_al = (Bit8u) ax2; \
reg_ah = 0; \
SETFLAGBIT(CF,0); \
SETFLAGBIT(OF,0); \
SETFLAGBIT(AF,0); \
SETFLAGBIT(CF,false); \
SETFLAGBIT(OF,false); \
SETFLAGBIT(AF,false); \
SETFLAGBIT(SF,reg_al >= 0x80); \
SETFLAGBIT(ZF,reg_al == 0); \
SETFLAGBIT(PF,parity_lookup[reg_al]); \
@ -611,8 +632,8 @@
}
#define MULB(op1,load,save) \
FillFlags(); \
reg_ax=reg_al*load(op1); \
FillFlagsNoCFOF(); \
SETFLAGBIT(ZF,reg_al == 0); \
if (reg_ax & 0xff00) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
@ -622,10 +643,10 @@
#define MULW(op1,load,save) \
{ \
FillFlags(); \
Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \
reg_ax=(Bit16u)(tempu); \
reg_dx=(Bit16u)(tempu >> 16); \
FillFlagsNoCFOF(); \
SETFLAGBIT(ZF,reg_ax == 0); \
if (reg_dx) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
@ -636,10 +657,10 @@
#define MULD(op1,load,save) \
{ \
FillFlags(); \
Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \
reg_eax=(Bit32u)(tempu); \
reg_edx=(Bit32u)(tempu >> 32); \
FillFlagsNoCFOF(); \
SETFLAGBIT(ZF,reg_eax == 0); \
if (reg_edx) { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
@ -729,8 +750,8 @@
#define IMULB(op1,load,save) \
{ \
FillFlags(); \
reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \
FillFlagsNoCFOF(); \
if ((reg_ax & 0xff80)==0xff80 || \
(reg_ax & 0xff80)==0x0000) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
@ -742,10 +763,10 @@
#define IMULW(op1,load,save) \
{ \
FillFlags(); \
Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \
reg_ax=(Bit16s)(temps); \
reg_dx=(Bit16s)(temps >> 16); \
FillFlagsNoCFOF(); \
if (((temps & 0xffff8000)==0xffff8000 || \
(temps & 0xffff8000)==0x0000)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
@ -756,11 +777,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); \
FillFlagsNoCFOF(); \
if ((reg_edx==0xffffffff) && \
(reg_eax & 0x80000000) ) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
@ -774,10 +795,9 @@
#define DIMULW(op1,op2,op3,load,save) \
{ \
FillFlags(); \
Bits res; \
res=((Bit16s)op2) * ((Bit16s)op3); \
Bits res=((Bit16s)op2) * ((Bit16s)op3); \
save(op1,res & 0xffff); \
FillFlagsNoCFOF(); \
if ((res> -32768) && (res<32767)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
} else { \
@ -787,9 +807,9 @@
#define DIMULD(op1,op2,op3,load,save) \
{ \
FillFlags(); \
Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \
save(op1,(Bit32s)res); \
FillFlagsNoCFOF(); \
if ((res>-((Bit64s)(2147483647)+1)) && \
(res<(Bit64s)2147483647)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \

View File

@ -20,14 +20,16 @@
#define __LAZYFLAG_H
//Flag Handling
Bitu get_CF(void);
Bitu get_AF(void);
Bitu get_ZF(void);
Bitu get_SF(void);
Bitu get_OF(void);
Bitu get_PF(void);
Bit32u get_CF(void);
Bit32u get_AF(void);
Bit32u get_ZF(void);
Bit32u get_SF(void);
Bit32u get_OF(void);
Bit32u get_PF(void);
Bitu FillFlags(void);
void FillFlagsNoCFOF(void);
void DestroyConditionFlags(void);
#include "regs.h"

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: debug.cpp,v 1.85 2007/02/25 18:38:00 c2woody Exp $ */
/* $Id: debug.cpp,v 1.88 2007/06/12 20:22:07 c2woody Exp $ */
#include "dosbox.h"
#if C_DEBUG
@ -755,7 +755,7 @@ static void DrawRegisters(void) {
}
wattrset(dbg.win_reg,0);
mvwprintw(dbg.win_reg,3,60,"%d ",cycle_count);
mvwprintw(dbg.win_reg,3,60,"%u ",cycle_count);
wrefresh(dbg.win_reg);
};
@ -805,7 +805,7 @@ static void DrawCode(void)
line20[20 - drawsize*2] = ' ';
} else waddstr(dbg.win_code,line20);
char* res = 0;
char* res = "";
if (showExtend) res = AnalyzeInstruction(dline, saveSel);
// Spacepad it up to 28 characters
size_t dline_len = strlen(dline);
@ -1776,13 +1776,12 @@ static void LogCPUInfo(void)
sprintf(out1,"IDT base=%08X limit=%08X",cpu.idt.GetBase(),cpu.idt.GetLimit());
LOG(LOG_MISC,LOG_ERROR)(out1);
Bitu sel;
Bitu sel=CPU_STR();
Descriptor desc;
CPU_STR(sel);
cpu.gdt.GetDescriptor(sel,desc);
sprintf(out1,"TR selector=%04X, base=%08X limit=%08X*%X",sel,desc.GetBase(),desc.GetLimit(),desc.saved.seg.g?0x4000:1);
LOG(LOG_MISC,LOG_ERROR)(out1);
sel=cpu.gdt.SLDT();
sel=CPU_SLDT();
cpu.gdt.GetDescriptor(sel,desc);
sprintf(out1,"LDT selector=%04X, base=%08X limit=%08X*%X",sel,desc.GetBase(),desc.GetLimit(),desc.saved.seg.g?0x4000:1);
LOG(LOG_MISC,LOG_ERROR)(out1);
@ -2210,12 +2209,12 @@ void DEBUG_HeavyLogInstruction(void) {
inst.s_fs = SegValue(fs);
inst.s_gs = SegValue(gs);
inst.s_ss = SegValue(ss);
inst.c = get_CF();
inst.z = get_ZF();
inst.s = get_SF();
inst.o = get_OF();
inst.a = get_AF();
inst.p = get_PF();
inst.c = get_CF()>0;
inst.z = get_ZF()>0;
inst.s = get_SF()>0;
inst.o = get_OF()>0;
inst.a = get_AF()>0;
inst.p = get_PF()>0;
inst.i = GETFLAGBOOL(IF);
if (++logCount >= LOGCPUMAX) logCount = 0;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: debug_gui.cpp,v 1.31 2007/01/08 19:45:39 qbix79 Exp $ */
/* $Id: debug_gui.cpp,v 1.32 2007/05/09 14:35:51 c2woody Exp $ */
#include "dosbox.h"
@ -106,7 +106,7 @@ void LOG::operator() (char const* format, ...){
if (d_type>=LOG_MAX) return;
if ((d_severity!=LOG_ERROR) && (!loggrp[d_type].enabled)) return;
DEBUG_ShowMsg("%10d: %s:%s\n",cycle_count,loggrp[d_type].front,buf);
DEBUG_ShowMsg("%10u: %s:%s\n",cycle_count,loggrp[d_type].front,buf);
}
@ -250,6 +250,7 @@ void LOG_StartUp(void) {
lowcase(buf);
sect->Add_bool(buf,true);
}
MSG_Add("LOG_CONFIGFILE_HELP","Logging related options for the debugger.\n");
}

View File

@ -85,7 +85,7 @@ bool CDROM_Interface_SDL::GetAudioTracks (int& stTrack, int& end, TMSF& leadOut)
bool CDROM_Interface_SDL::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr)
{
if (CD_INDRIVE(SDL_CDStatus(cd))) {
FRAMES_TO_MSF(cd->track[track-1].offset+150,&start.min,&start.sec,&start.fr);
FRAMES_TO_MSF(cd->track[track-1].offset,&start.min,&start.sec,&start.fr);
attr = cd->track[track-1].type<<4;//sdl uses 0 for audio and 4 for data. instead of 0x00 and 0x40
}
return CD_INDRIVE(SDL_CDStatus(cd));

View File

@ -76,7 +76,7 @@ public:
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 ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return false; };
virtual bool LoadUnloadMedia (bool unload);
private:
@ -91,18 +91,18 @@ private:
class CDROM_Interface_Fake : public CDROM_Interface
{
public:
bool SetDevice (char* path, int forceCD) { return true; };
bool SetDevice (char* /*path*/, int /*forceCD*/) { return true; };
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) { return true; };
bool PauseAudio (bool resume) { return true; };
bool PlayAudioSector (unsigned long /*start*/,unsigned long /*len*/) { return true; };
bool PauseAudio (bool /*resume*/) { return true; };
bool StopAudio (void) { return true; };
bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return true; };
bool LoadUnloadMedia (bool unload) { return true; };
bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return true; };
bool LoadUnloadMedia (bool /*unload*/) { return true; };
};
class CDROM_Interface_Image : public CDROM_Interface
@ -112,6 +112,7 @@ private:
public:
virtual bool read(Bit8u *buffer, int seek, int count) = 0;
virtual int getLength() = 0;
virtual ~TrackFile() { };
};
class BinaryFile : public TrackFile {

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: cdrom_aspi_win32.cpp,v 1.17 2007/01/08 19:45:39 qbix79 Exp $ */
/* $Id: cdrom_aspi_win32.cpp,v 1.18 2007/06/12 20:22:07 c2woody Exp $ */
#if defined (WIN32)
@ -148,7 +148,6 @@ bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase)
ULONG result,newKeyResult;
char subKey[256];
char buffer[256];
ULONG bufferSize = 256;
ULONG subKeySize = 256;
HKEY hNewKey;
@ -596,7 +595,6 @@ bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata)
// attr = (upc.ADR<<4) | upc.Control;
attr = 0;
int pos = 0;
// Convert to mscdex format
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);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: cdrom_image.cpp,v 1.15 2007/02/22 08:36:25 qbix79 Exp $ */
/* $Id: cdrom_image.cpp,v 1.16 2007/06/12 20:22:08 c2woody Exp $ */
#include <cctype>
#include <cmath>
@ -190,7 +190,7 @@ bool CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut
bool CDROM_Interface_Image::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr)
{
if (track < 1 || track > tracks.size()) return false;
if (track < 1 || track > (int)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;
@ -254,7 +254,7 @@ bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long s
Bit8u* buf = new Bit8u[buflen];
bool success = true; //Gobliiins reads 0 sectors
for(int i = 0; i < num; i++) {
for(unsigned long i = 0; i < num; i++) {
success = ReadSector(&buf[i * sectorSize], raw, sector + i);
if (!success) break;
}
@ -308,7 +308,7 @@ void CDROM_Interface_Image::CDAudioCallBack(Bitu len)
}
SDL_mutexP(player.mutex);
while (player.bufLen < len) {
while (player.bufLen < (Bits)len) {
bool success;
if (player.targetFrame > player.currFrame)
success = player.cd->ReadSector(&player.buffer[player.bufLen], true, player.currFrame);
@ -607,7 +607,7 @@ bool CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname)
bool CDROM_Interface_Image::GetCueKeyword(string &keyword, istream &in)
{
in >> keyword;
for(int i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]);
for(Bitu i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]);
return true;
}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dev_con.h,v 1.28 2007/01/11 18:08:54 c2woody Exp $ */
/* $Id: dev_con.h,v 1.32 2007/06/30 19:33:45 c2woody Exp $ */
#include "dos_inc.h"
#include "../ints/int10.h"
@ -49,6 +49,7 @@ private:
Bit16u ncols;
Bit8s savecol;
Bit8s saverow;
bool warned;
} ansi;
};
@ -265,12 +266,18 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) {
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;
if(!ansi.warned) { //Inform the debugger that ansi is used.
ansi.warned = true;
LOG(LOG_IOCTL,LOG_WARN)("ANSI SEQUENCES USED");
}
/* Turn them into positions that are on the screen */
if(ansi.data[0] == 0) ansi.data[0] = 1;
if(ansi.data[1] == 0) ansi.data[1] = 1;
if(ansi.data[0] > ansi.nrows) ansi.data[0] = (Bit8u)ansi.nrows;
if(ansi.data[1] > ansi.ncols) ansi.data[1] = (Bit8u)ansi.ncols;
INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),page); /*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(page) ;
@ -333,7 +340,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) {
ansi.saverow=CURSOR_POS_ROW(page);
ClearAnsi();
break;
case 'K':/* erase till end of line (don't touch cursor) */
case 'K': /* erase till end of line (don't touch cursor) */
col = CURSOR_POS_COL(page);
row = CURSOR_POS_ROW(page);
INT10_WriteChar(' ',ansi.attr,page,ansi.ncols-col,true); //Use this one to prevent scrolling when end of screen is reached
@ -341,6 +348,12 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) {
INT10_SetCursorPos(row,col,page);
ClearAnsi();
break;
case 'M': /* delete line (NANSI) */
col = CURSOR_POS_COL(page);
row = CURSOR_POS_ROW(page);
INT10_ScrollWindow(row,0,ansi.nrows-1,ansi.ncols-1,ansi.data[0]? -ansi.data[0] : -1,ansi.attr,0xFF);
ClearAnsi();
break;
case 'l':/* (if code =7) disable linewrap */
case 'p':/* reassign keys (needs strings) */
case 'i':/* printer stuff */
@ -370,7 +383,7 @@ Bit16u device_CON::GetInformation(void) {
Bit16u tail=mem_readw(BIOS_KEYBOARD_BUFFER_TAIL);
if ((head==tail) && !readcache) return 0x80D3; /* No Key Available */
if (real_readw(0x40,head)) return 0x8093; /* Key Available */
if (readcache || real_readw(0x40,head)) return 0x8093; /* Key Available */
/* remove the zero from keyboard buffer */
Bit16u start=mem_readw(BIOS_KEYBOARD_BUFFER_START);
@ -391,6 +404,7 @@ device_CON::device_CON() {
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
ansi.saverow=0;
ansi.savecol=0;
ansi.warned=false;
ClearAnsi();
}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos.cpp,v 1.99 2007/01/13 08:35:49 qbix79 Exp $ */
/* $Id: dos.cpp,v 1.104 2007/07/27 19:17:23 qbix79 Exp $ */
#include <stdlib.h>
#include <string.h>
@ -45,11 +45,11 @@ void DOS_SetError(Bit16u code) {
#define DATA_TRANSFERS_TAKE_CYCLES 1
#ifdef DATA_TRANSFERS_TAKE_CYCLES
#include "cpu.h"
static inline void modify_cycles(Bitu value) {
static inline void modify_cycles(Bits value) {
if((4*value+5) < CPU_Cycles) CPU_Cycles -= 4*value; else CPU_Cycles = 5;
}
#else
static inline void modify_cycles(Bitu /* value */) {
static inline void modify_cycles(Bits /* value */) {
return;
}
#endif
@ -191,14 +191,12 @@ static Bitu DOS_21Handler(void) {
break;
case 0x0c: /* Flush Buffer and read STDIN call */
{
/* flush STDIN-buffer */
Bit8u c;Bit16u n;
while (DOS_GetSTDINStatus()) {
n=1; DOS_ReadFile(STDIN,&c,&n);
}
switch (reg_al) {
case 0x0:
/* flush STDIN-buffer */
Bit8u c;Bit16u n;
while (DOS_GetSTDINStatus()) {
n=1; DOS_ReadFile(STDIN,&c,&n);
}
break;
case 0x1:
case 0x6:
case 0x7:
@ -213,6 +211,7 @@ static Bitu DOS_21Handler(void) {
break;
default:
// LOG_ERROR("DOS:0C:Illegal Flush STDIN Buffer call %d",reg_al);
reg_al=0;
break;
}
}
@ -289,7 +288,7 @@ static Bitu DOS_21Handler(void) {
LOG(LOG_FCB,LOG_NORMAL)("DOS:0x22 FCB-Random write used, result:al=%d",reg_al);
break;
case 0x23: /* Get file size for FCB */
if (DOS_FCBGetFileSize(SegValue(ds),reg_dx,reg_cx)) reg_al = 0x00;
if (DOS_FCBGetFileSize(SegValue(ds),reg_dx)) reg_al = 0x00;
else reg_al = 0xFF;
break;
case 0x24: /* Set Random Record number for FCB */
@ -360,7 +359,10 @@ static Bitu DOS_21Handler(void) {
break;
case 0x2d: /* Set System Time */
LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set System Time not supported");
reg_al=0; /* Noone is changing system time */
//Check input parameters nonetheless
if( reg_ch > 23 || reg_cl > 59 || reg_dh > 59 || reg_dl > 99 )
reg_al = 0xff;
else reg_al = 0;
break;
case 0x2e: /* Set Verify flag */
dos.verify=(reg_al==1);
@ -386,12 +388,15 @@ static Bitu DOS_21Handler(void) {
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 */
case 0x1f: /* Get drive parameter block for default drive */
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--;
Bitu drive=reg_dl;if(!drive || reg_ah==0x1f) drive=dos.current_drive;else drive--;
if(Drives[drive]) {
reg_al=0x00;
LOG(LOG_DOSMISC,LOG_ERROR)("Get drive parameter block.");
reg_al = 0x00;
SegSet16(ds,dos.tables.dpb);
reg_bx = drive;//Faking only the first entry (that is the driveletter)
LOG(LOG_DOSMISC,LOG_ERROR)("Get drive parameter block.");
} else {
reg_al=0xff;
}
@ -988,23 +993,21 @@ static Bitu DOS_21Handler(void) {
LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al);
break;
case 0x68: /* FFLUSH Commit file */
CALLBACK_SCF(false); //mirek
case 0xE0:
case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x20: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x6b: /* NULL Function */
case 0x61: /* UNUSED */
case 0xEF: /* Used in Ancient Art Of War CGA */
case 0x1f: /* Get drive parameter block for default drive */
case 0x68: /* FFLUSH Commit file */
CALLBACK_SCF(false); //mirek
case 0xE0:
case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x20: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x6b: /* NULL Function */
case 0x61: /* UNUSED */
case 0xEF: /* Used in Ancient Art Of War CGA */
case 0x5c: /* FLOCK File region locking */
case 0x5e: /* 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 */
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 */
break;
};
return CBRET_NONE;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_classes.cpp,v 1.49 2007/01/08 19:45:39 qbix79 Exp $ */
/* $Id: dos_classes.cpp,v 1.52 2007/06/13 07:25:14 qbix79 Exp $ */
#include <string.h>
#include <stdlib.h>
@ -179,7 +179,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);
@ -461,9 +461,13 @@ void DOS_FCB::FileOpen(Bit8u _fhandle) {
sSave(sFCB,file_handle,_fhandle);
sSave(sFCB,cur_block,0);
sSave(sFCB,rec_size,128);
sSave(sFCB,rndm,0);
Bit8u temp=RealHandle(_fhandle);
sSave(sFCB,filesize,Files[temp]->size);
// sSave(sFCB,rndm,0); // breaks Jewels of darkness.
Bit8u temp = RealHandle(_fhandle);
Bit32u size = 0;
Files[temp]->Seek(&size,DOS_SEEK_END);
sSave(sFCB,filesize,size);
size = 0;
Files[temp]->Seek(&size,DOS_SEEK_SET);
sSave(sFCB,time,Files[temp]->time);
sSave(sFCB,date,Files[temp]->date);
}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_devices.cpp,v 1.16 2007/01/13 08:35:49 qbix79 Exp $ */
/* $Id: dos_devices.cpp,v 1.18 2007/06/14 08:23:46 qbix79 Exp $ */
#include <string.h>
#include "dosbox.h"
@ -92,12 +92,10 @@ bool DOS_Device::WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcod
}
DOS_File::DOS_File(const DOS_File& orig) {
type=orig.type;
flags=orig.flags;
time=orig.time;
date=orig.date;
attr=orig.attr;
size=orig.size;
refCtr=orig.refCtr;
open=orig.open;
name=0;
@ -107,12 +105,10 @@ DOS_File::DOS_File(const DOS_File& orig) {
}
DOS_File & DOS_File::operator= (const DOS_File & orig) {
type=orig.type;
flags=orig.flags;
time=orig.time;
date=orig.date;
attr=orig.attr;
size=orig.size;
refCtr=orig.refCtr;
open=orig.open;
if(name) {
@ -124,7 +120,7 @@ DOS_File & DOS_File::operator= (const DOS_File & orig) {
return *this;
}
Bit8u DOS_FindDevice(char * name) {
Bit8u DOS_FindDevice(char const * name) {
/* should only check for the names before the dot and spacepadded */
// STDAUX is alias for COM1
// A bit of a hack, but no application will probably use stdaux to determine wether a directory exists

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_files.cpp,v 1.81 2007/01/08 21:20:23 qbix79 Exp $ */
/* $Id: dos_files.cpp,v 1.90 2007/06/29 10:24:43 qbix79 Exp $ */
#include <string.h>
#include <stdlib.h>
@ -52,7 +52,7 @@ void DOS_SetDefaultDrive(Bit8u drive) {
if (drive<=DOS_DRIVES && ((drive<2) || Drives[drive])) dos.current_drive = drive;
}
bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive) {
if(!name || *name == 0 || *name == ' ') {
/* Both \0 and space are seperators and
@ -60,23 +60,23 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false;
}
const char * name_int = name;
char tempdir[DOS_PATHLENGTH];
char upname[DOS_PATHLENGTH];
Bitu r,w;
*drive=dos.current_drive;
/* First get the drive */
if (name[1]==':') {
*drive=(name[0] | 0x20)-'a';
name+=2;
if (name_int[1]==':') {
*drive=(name_int[0] | 0x20)-'a';
name_int+=2;
}
if (*drive>=DOS_DRIVES || !Drives[*drive]) {
DOS_SetError(DOSERR_PATH_NOT_FOUND);
return false;
}
r=0;w=0;
while (name[r]!=0 && (r<DOS_PATHLENGTH)) {
Bit8u c=name[r++];
while (name_int[r]!=0 && (r<DOS_PATHLENGTH)) {
Bit8u c=name_int[r++];
if ((c>='a') && (c<='z')) {upname[w++]=c-32;continue;}
if ((c>='A') && (c<='Z')) {upname[w++]=c;continue;}
if ((c>='0') && (c<='9')) {upname[w++]=c;continue;}
@ -90,6 +90,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
case '!': case '%': case '{': case '}': case '`': case '~':
case '_': case '-': case '.': case '*': case '?': case '&':
case '\'': case '+': case '^': case 246: case 255: case 0xa0:
case 0xe5:
upname[w++]=c;
break;
default:
@ -105,7 +106,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
else fullname[0]=0;
Bit32u lastdir=0;Bit32u t=0;
while (fullname[t]!=0) {
if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t;
if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t;
t++;
};
r=0;w=0;
@ -124,7 +125,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
Bit32s iDown, cDots;
bool dots = true;
Bit32u templen =strlen(tempdir);
Bit32s templen=(Bit32s)strlen(tempdir);
for(iDown=0;(iDown < templen) && dots;iDown++)
if(tempdir[iDown] != '.')
dots = false;
@ -133,7 +134,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
cDots = templen - 1;
if(dots && (cDots > 0))
{
for(iDown=strlen(fullname)-1;iDown>=0;iDown--)
for(iDown=(Bit32s)strlen(fullname)-1;iDown>=0;iDown--)
{
if(fullname[iDown]=='\\' || iDown==0)
{
@ -144,7 +145,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
}
}
fullname[lastdir]=0;
Bit32u t=0;lastdir=0;
t=0;lastdir=0;
while (fullname[t]!=0) {
if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t;
t++;
@ -173,7 +174,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
return true;
}
bool DOS_GetCurrentDir(Bit8u drive,char * buffer) {
bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) {
if (drive==0) drive=DOS_GetDefaultDrive();
else drive--;
if ((drive>DOS_DRIVES) || (!Drives[drive])) {
@ -184,7 +185,7 @@ bool DOS_GetCurrentDir(Bit8u drive,char * buffer) {
return true;
}
bool DOS_ChangeDir(char * dir) {
bool DOS_ChangeDir(char const * const dir) {
Bit8u drive;char fulldir[DOS_PATHLENGTH];
if (!DOS_MakeName(dir,fulldir,&drive)) return false;
@ -197,7 +198,7 @@ bool DOS_ChangeDir(char * dir) {
return false;
}
bool DOS_MakeDir(char * dir) {
bool DOS_MakeDir(char const * const dir) {
Bit8u drive;char fulldir[DOS_PATHLENGTH];
size_t len = strlen(dir);
if(!len || dir[len-1] == '\\') {
@ -215,7 +216,7 @@ bool DOS_MakeDir(char * dir) {
return false;
}
bool DOS_RemoveDir(char * dir) {
bool DOS_RemoveDir(char const * const dir) {
/* We need to do the test before the removal as can not rely on
* the host to forbid removal of the current directory.
* We never change directory. Everything happens in the drives.
@ -243,7 +244,7 @@ bool DOS_RemoveDir(char * dir) {
return false;
}
bool DOS_Rename(char * oldname,char * newname) {
bool DOS_Rename(char const * const oldname,char const * const newname) {
Bit8u driveold;char fullold[DOS_PATHLENGTH];
Bit8u drivenew;char fullnew[DOS_PATHLENGTH];
if (!DOS_MakeName(oldname,fullold,&driveold)) return false;
@ -382,13 +383,14 @@ bool DOS_CloseFile(Bit16u entry) {
return true;
}
static bool PathExists(char* name) {
char* leading = strrchr(name,'\\');
static bool PathExists(char const * const name) {
const char* leading = strrchr(name,'\\');
if(!leading) return true;
char temp[CROSS_LEN];
strcpy(temp,name);
leading = strrchr(temp,'\\');
*leading = 0;
char * lead = strrchr(temp,'\\');
if (lead == temp) return true;
*lead = 0;
Bit8u drive;char fulldir[DOS_PATHLENGTH];
if (!DOS_MakeName(temp,fulldir,&drive)) return false;
if(!Drives[drive]->TestDir(fulldir)) return false;
@ -396,7 +398,7 @@ static bool PathExists(char* name) {
}
bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry) {
// Creation of a device is the same as opening it
// Tc201 installer
if (DOS_FindDevice(name) != DOS_DEVICES)
@ -437,14 +439,14 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
}
}
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry) {
/* First check for devices */
if (flags>2) LOG(LOG_FILES,LOG_ERROR)("Special file open command %X file %s",flags,name);
else LOG(LOG_FILES,LOG_NORMAL)("file open command %X file %s",flags,name);
DOS_PSP psp(dos.psp());
Bit16u attr = 0;
Bit8u devnum = DOS_FindDevice((char *)name);
Bit8u devnum = DOS_FindDevice(name);
bool device = (devnum != DOS_DEVICES);
if(!device && DOS_GetFileAttr(name,&attr)) {
//DON'T ALLOW directories to be openened.(skip test if file is device).
@ -499,7 +501,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
}
}
bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status)
bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status)
// FIXME: Not yet supported : Bit 13 of flags (int 0x24 on critical error
{
Bit16u result = 0;
@ -525,7 +527,7 @@ bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u ac
return true;
};
bool DOS_UnlinkFile(char * name) {
bool DOS_UnlinkFile(char const * const name) {
char fullname[DOS_PATHLENGTH];Bit8u drive;
if (!DOS_MakeName(name,fullname,&drive)) return false;
if(Drives[drive]->FileUnlink(fullname)){
@ -536,7 +538,7 @@ bool DOS_UnlinkFile(char * name) {
}
}
bool DOS_GetFileAttr(char * name,Bit16u * attr) {
bool DOS_GetFileAttr(char const * const name,Bit16u * attr) {
char fullname[DOS_PATHLENGTH];Bit8u drive;
if (!DOS_MakeName(name,fullname,&drive)) return false;
if (Drives[drive]->GetFileAttr(fullname,attr)) {
@ -547,7 +549,7 @@ bool DOS_GetFileAttr(char * name,Bit16u * attr) {
}
}
bool DOS_SetFileAttr(char * name,Bit16u attr)
bool DOS_SetFileAttr(char const * const name,Bit16u attr)
// this function does not change the file attributs
// it just does some tests if file is available
// returns false when using on cdrom (stonekeep)
@ -562,7 +564,7 @@ bool DOS_SetFileAttr(char * name,Bit16u attr)
return Drives[drive]->GetFileAttr(fullname,&attrTemp);
}
bool DOS_Canonicalize(char * name,char * big) {
bool DOS_Canonicalize(char const * const name,char * const big) {
//TODO Add Better support for devices and shit but will it be needed i doubt it :)
Bit8u drive;
char fullname[DOS_PATHLENGTH];
@ -637,11 +639,11 @@ bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) {
bool DOS_CreateTempFile(char * name,Bit16u * entry) {
bool DOS_CreateTempFile(char * const name,Bit16u * entry) {
/* First add random crap to the end of the name and try to open */
/* Todo maybe check for euhm existence of the path name */
char * tempname;
tempname=name+strlen(name);
dos.errorcode=0;
do {
Bit32u i;
for (i=0;i<8;i++) {
@ -652,7 +654,8 @@ bool DOS_CreateTempFile(char * name,Bit16u * entry) {
tempname[i]=(rand()%26)+'A';
}
tempname[12]=0;
} while (!DOS_CreateFile(name,0,entry));
} while ((!DOS_CreateFile(name,0,entry)) && (dos.errorcode==DOSERR_FILE_ALREADY_EXISTS));
if (dos.errorcode) return false;
return true;
}
@ -688,7 +691,7 @@ Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *
char drive[2];
char name[9];
char ext[4];
} part GCC_ATTRIBUTE (packed) ;
} GCC_ATTRIBUTE (packed) part;
char full[DOS_FCBNAME];
} fcb_name;
#ifdef _MSC_VER
@ -773,7 +776,7 @@ savefcb:
return ret;
}
static void DTAExtendName(char * name,char * filename,char * ext) {
static void DTAExtendName(char * const name,char * const filename,char * const ext) {
char * find=strchr(name,'.');
if (find) {
strcpy(ext,find+1);
@ -878,10 +881,9 @@ Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset,Bit16u recno) {
Bit16u toread=rec_size;
if (!DOS_ReadFile(fhandle,dos_copybuf,&toread)) return FCB_READ_NODATA;
if (toread==0) return FCB_READ_NODATA;
if (toread<rec_size) {
PhysPt fill=Real2Phys(dos.dta())+toread;
Bitu i=rec_size-toread;
for (;i>0;i--) mem_writeb(fill++,0);
if (toread < rec_size) { //Zero pad copybuffer to rec_size
Bitu i = toread;
while(i < rec_size) dos_copybuf[i++] = 0;
}
MEM_BlockWrite(Real2Phys(dos.dta())+recno*rec_size,dos_copybuf,rec_size);
if (++cur_rec>127) { cur_block++;cur_rec=0; }
@ -927,10 +929,15 @@ Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) {
* random read updates old block and old record to reflect the random data
* before the read!!!!!!!!! and the random data is not updated! (user must do this)
* Random block read updates these fields to reflect the state after the read!
*/
/* BUG: numRec should return the amount of records read!
* Not implemented yet as I'm unsure how to count on error states (partial/failed)
*/
DOS_FCB fcb(seg,offset);
Bit32u random;Bit16u old_block;Bit8u old_rec;Bit8u error;
Bit32u random;Bit16u old_block;Bit8u old_rec;
Bit8u error=0;
/* Set the correct record from the random data */
fcb.GetRandom(random);
@ -952,7 +959,8 @@ Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) {
Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) {
/* see FCB_RandomRead */
DOS_FCB fcb(seg,offset);
Bit32u random;Bit16u old_block;Bit8u old_rec;Bit8u error;
Bit32u random;Bit16u old_block;Bit8u old_rec;
Bit8u error=0;
/* Set the correct record from the random data */
fcb.GetRandom(random);
@ -971,13 +979,14 @@ Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) {
return error;
}
bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset,Bit16u numRec) {
bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset) {
char shortname[DOS_PATHLENGTH];Bit16u entry;Bit8u handle;Bit16u rec_size;
DOS_FCB fcb(seg,offset);
fcb.GetName(shortname);
if (!DOS_OpenFile(shortname,0,&entry)) return false;
handle=RealHandle(entry);
Bit32u size=Files[handle]->size;
handle = RealHandle(entry);
Bit32u size = 0;
Files[handle]->Seek(&size,DOS_SEEK_END);
DOS_CloseFile(entry);fcb.GetSeqData(handle,rec_size);
Bit32u random=(size/rec_size);
if (size % rec_size) random++;
@ -1024,7 +1033,7 @@ void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset) {
}
bool DOS_FileExists(char * name) {
bool DOS_FileExists(char const * const name) {
char fullname[DOS_PATHLENGTH];Bit8u drive;
if (!DOS_MakeName(name,fullname,&drive)) return false;
return Drives[drive]->FileExists(fullname);
@ -1033,7 +1042,7 @@ bool DOS_FileExists(char * name) {
bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters) {
if (!drive) drive=dos.current_drive;
else drive--;
if (!Drives[drive]) return false;
if (drive >= DOS_DRIVES || !Drives[drive]) return false;
Bit16u _free_clusters;
Drives[drive]->AllocationInfo(_bytes_sector,_sectors_cluster,_total_clusters,&_free_clusters);
SegSet16(ds,RealSeg(dos.tables.mediaid));
@ -1050,8 +1059,7 @@ bool DOS_SetDrive(Bit8u drive) {
}
};
bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate)
{
bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate) {
Bit32u handle=RealHandle(entry);
if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);

View File

@ -37,7 +37,7 @@ static FILE* OpenDosboxFile(const char* name) {
localDrive* ldp=0;
// try to build dos name
if (DOS_MakeName((char*)name,fullname,&drive)) {
if (DOS_MakeName(name,fullname,&drive)) {
try {
// try to open file on mounted drive first
ldp=dynamic_cast<localDrive*>(Drives[drive]);

View File

@ -352,7 +352,7 @@ bool DOS_LinkUMBsToMemChain(Bit16u linkstate) {
/* Scan MCB-chain for last block before UMB-chain */
Bit16u mcb_segment=dos.firstMCB;
Bit16u prev_mcb_segment;
Bit16u prev_mcb_segment=dos.firstMCB;
DOS_MCB mcb(mcb_segment);
while ((mcb_segment!=umb_start) && (mcb.GetType()!=0x5a)) {
prev_mcb_segment=mcb_segment;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_mscdex.cpp,v 1.45 2007/01/21 16:21:22 c2woody Exp $ */
/* $Id: dos_mscdex.cpp,v 1.50 2007/07/20 18:22:28 qbix79 Exp $ */
#include <string.h>
#include <ctype.h>
@ -64,7 +64,7 @@ public:
void SetDriveLetter (Bit8u letter) { sSave(sDeviceHeader,driveLetter,letter); };
void SetNumSubUnits (Bit8u num) { sSave(sDeviceHeader,numSubUnits,num); };
Bit8u GetNumSubUnits (void) { return sGet(sDeviceHeader,numSubUnits); };
void SetName (char* _name) { MEM_BlockWrite(pt+offsetof(sDeviceHeader,name),_name,8); };
void SetName (char const* _name) { MEM_BlockWrite(pt+offsetof(sDeviceHeader,name),_name,8); };
void SetInterrupt (Bit16u ofs) { sSave(sDeviceHeader,interrupt,ofs); };
void SetStrategy (Bit16u ofs) { sSave(sDeviceHeader,strategy,ofs); };
@ -81,7 +81,7 @@ public:
Bit16u wReserved;
Bit8u driveLetter;
Bit8u numSubUnits;
} TDeviceHeader;
} GCC_ATTRIBUTE(packed) TDeviceHeader;
#ifdef _MSC_VER
#pragma pack()
#endif
@ -190,12 +190,14 @@ void CMscdex::GetDrives(PhysPt data)
bool CMscdex::IsValidDrive(Bit16u _drive)
{
_drive &= 0xff; //Only lowerpart (Ultimate domain)
for (Bit16u i=0; i<GetNumDrives(); i++) if (dinfo[i].drive==_drive) return true;
return false;
};
Bit8u CMscdex::GetSubUnit(Bit16u _drive)
{
_drive &= 0xff; //Only lowerpart (Ultimate domain)
for (Bit16u i=0; i<GetNumDrives(); i++) if (dinfo[i].drive==_drive) return (Bit8u)i;
return 0xff;
};
@ -321,11 +323,11 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit)
//Link it in the device chain
Bit32u start = dos_infoblock.GetDeviceChain();
Bit16u segm = start>>16;
Bit16u offm = start&0xFFFF;
Bit16u segm = (Bit16u)(start>>16);
Bit16u offm = (Bit16u)(start&0xFFFF);
while(start != 0xFFFFFFFF) {
segm = start>>16;
offm = start&0xFFFF;
segm = (Bit16u)(start>>16);
offm = (Bit16u)(start&0xFFFF);
start = real_readd(segm,offm);
}
real_writed(segm,offm,seg<<16);
@ -876,14 +878,17 @@ static Bit16u MSCDEX_IOCTL_Input(PhysPt buffer,Bit8u drive_unit) {
mscdex->GetCurrentPos(drive_unit,pos);
Bit8u addr_mode = mem_readb(buffer+1);
if (addr_mode==0) { // HSG
mem_writed(buffer+2,MSF_TO_FRAMES (pos.min, pos.sec, pos.fr));
Bit32u frames=MSF_TO_FRAMES(pos.min, pos.sec, pos.fr);
if (frames<150) MSCDEX_LOG("MSCDEX: Get position: invalid position %d:%d:%d", pos.min, pos.sec, pos.fr);
else frames-=150;
mem_writed(buffer+2,frames);
} else if (addr_mode==1) { // Red book
mem_writeb(buffer+2,pos.fr);
mem_writeb(buffer+3,pos.sec);
mem_writeb(buffer+4,pos.min);
mem_writeb(buffer+5,0x00);
} else {
LOG_MSG("MSCDEX: Get position: invalid address mode %x",addr_mode);
MSCDEX_LOG("MSCDEX: Get position: invalid address mode %x",addr_mode);
return 0x03; // invalid function
}
}break;

View File

@ -16,8 +16,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_programs.cpp,v 1.69 2007/02/22 08:37:12 qbix79 Exp $ */
/* $Id: dos_programs.cpp,v 1.76 2007/07/02 14:10:27 c2woody Exp $ */
#include "dosbox.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
@ -34,6 +35,12 @@
#include "dos_inc.h"
#include "bios.h"
#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
#include <sys/types.h>
#include <pwd.h>
#endif
#if defined(OS2)
#define INCL DOSFILEMGR
#define INCL_DOSERRORS
@ -46,6 +53,24 @@ Bitu DEBUG_EnableDebugger(void);
void MSCDEX_SetCDInterface(int intNr, int forceCD);
//Helper function for mount and imgmount to correctly find the path
static void ResolveHomedir(std::string & temp_line) {
if(!temp_line.size() || temp_line[0] != '~') return; //No ~
if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant
char * home = getenv("HOME");
if(home) temp_line.replace(0,1,std::string(home));
#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
} else { // The ~username variant
std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT);
if(namelen == std::string::npos) namelen = temp_line.size();
std::string username = temp_line.substr(1,namelen - 1);
struct passwd* pass = getpwnam(username.c_str());
if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~)
#endif // USERNAME lookup code
}
}
class MOUNT : public Program {
public:
void Run(void)
@ -108,24 +133,30 @@ public:
Bit8u mediaid;
std::string str_size;
if (type=="floppy") {
str_size="512,1,2847,2847";/* All space free */
str_size="512,1,2880,2880";/* All space free */
mediaid=0xF0; /* Floppy 1.44 media */
} else if (type=="dir") {
// 512*127*16513==~1GB total size
// 512*127*1700==~100MB total free size
str_size="512,127,16513,1700";
mediaid=0xF8; /* Hard Disk */
} else if (type=="cdrom") {
str_size="650,127,16513,1700";
str_size="2048,1,65535,0";
mediaid=0xF8; /* Hard Disk */
} else {
WriteOut(MSG_Get("PROGAM_MOUNT_ILL_TYPE"),type.c_str());
return;
}
/* Parse the free space in mb's */
/* Parse the free space in mb's (kb's for floppies) */
std::string mb_size;
if(cmd->FindString("-freesize",mb_size,true)) {
char teststr[1024];
Bit16u sizemb = static_cast<Bit16u>(atoi(mb_size.c_str()));
sprintf(teststr,"512,127,16513,%d",sizemb*1024*1024/(512*127));
if (type=="floppy") {
sprintf(teststr,"512,1,2880,%d",sizemb*1024/(512*1));
} else {
sprintf(teststr,"512,127,16513,%d",sizemb*1024*1024/(512*127));
}
str_size=teststr;
}
@ -184,11 +215,9 @@ public:
#else
if (stat(temp_line.c_str(),&test)) {
failed = true;
if(temp_line.size() && temp_line[0] == '~') {
char * home = getenv("HOME");
if(home) temp_line.replace(0,1,std::string(home));
if(!stat(temp_line.c_str(),&test)) failed = false;
}
ResolveHomedir(temp_line);
//Try again after resolving ~
if(!stat(temp_line.c_str(),&test)) failed = false;
}
if(failed) {
#endif
@ -220,9 +249,15 @@ public:
int num = -1;
cmd->FindInt("-usecd",num,true);
int error;
if (cmd->FindExist("-aspi",false)) MSCDEX_SetCDInterface(CDROM_USE_ASPI, num); else
if (cmd->FindExist("-ioctl",false)) MSCDEX_SetCDInterface(CDROM_USE_IOCTL, num);
else MSCDEX_SetCDInterface(CDROM_USE_SDL, num);
if (cmd->FindExist("-aspi",false)) {
MSCDEX_SetCDInterface(CDROM_USE_ASPI, num);
} else if (cmd->FindExist("-ioctl",false)) {
MSCDEX_SetCDInterface(CDROM_USE_IOCTL, num);
} else if (cmd->FindExist("-noioctl",false)) {
MSCDEX_SetCDInterface(CDROM_USE_SDL, num);
} else {
MSCDEX_SetCDInterface(CDROM_USE_IOCTL, num);
}
newdrive = new cdromDrive(drive,temp_line.c_str(),sizes[0],bit8size,sizes[2],0,mediaid,error);
// Check Mscdex, if it worked out...
switch (error) {
@ -374,21 +409,30 @@ private:
ldp=dynamic_cast<localDrive*>(Drives[drive]);
if(!ldp) return NULL;
tmpfile = ldp->GetSystemFilePtr(fullname, "r");
tmpfile = ldp->GetSystemFilePtr(fullname, "rb");
if(tmpfile == NULL) {
if (!tryload) *error=1;
return NULL;
}
fclose(tmpfile);
tmpfile = ldp->GetSystemFilePtr(fullname, "rb+");
if(tmpfile == NULL) {
if (!tryload) *error=2;
return NULL;
}
// get file size
fseek(tmpfile,0L, SEEK_END);
*ksize = (ftell(tmpfile) / 1024);
*bsize = ftell(tmpfile);
fclose(tmpfile);
tmpfile = ldp->GetSystemFilePtr(fullname, "rb+");
if(tmpfile == NULL) {
// if (!tryload) *error=2;
// return NULL;
WriteOut(MSG_Get("PROGRAM_BOOT_WRITE_PROTECTED"));
tmpfile = ldp->GetSystemFilePtr(fullname, "rb");
if(tmpfile == NULL) {
if (!tryload) *error=1;
return NULL;
}
}
return tmpfile;
}
catch(...) {
@ -401,12 +445,19 @@ private:
FILE* tmpfile = getFSFile_mounted(filename,ksize,bsize,&error);
if(tmpfile) return tmpfile;
//File not found on mounted filesystem. Try regular filesystem
tmpfile = fopen(filename,"rb+");
std::string filename_s(filename);
ResolveHomedir(filename_s);
tmpfile = fopen(filename_s.c_str(),"rb+");
if(!tmpfile) {
if( (tmpfile = fopen(filename,"r")) ) {
if( (tmpfile = fopen(filename_s.c_str(),"rb")) ) {
//File exists; So can't be opened in correct mode => error 2
fclose(tmpfile);
if(tryload) error = 2;
// fclose(tmpfile);
// if(tryload) error = 2;
WriteOut(MSG_Get("PROGRAM_BOOT_WRITE_PROTECTED"));
fseek(tmpfile,0L, SEEK_END);
*ksize = (ftell(tmpfile) / 1024);
*bsize = ftell(tmpfile);
return tmpfile;
}
// Give the delayed errormessages from the mounted variant (or from above)
if(error == 1) WriteOut(MSG_Get("PROGRAM_BOOT_NOT_EXIST"));
@ -886,6 +937,7 @@ public:
Bit8u mediaid;
if (type=="floppy" || type=="hdd" || type=="iso") {
Bit16u sizes[4];
bool imgsizedetect=false;
std::string str_size;
mediaid=0xF8;
@ -899,21 +951,21 @@ public:
}
cmd->FindString("-size",str_size,true);
if ((type=="hdd") && (str_size.size()==0)) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_GEOMETRY"));
return;
imgsizedetect=true;
} else {
char number[20];
const char * scan=str_size.c_str();
Bitu index=0;Bitu count=0;
while (*scan) {
if (*scan==',') {
number[index]=0;sizes[count++]=atoi(number);
index=0;
} else number[index++]=*scan;
scan++;
}
number[index]=0;sizes[count++]=atoi(number);
}
char number[20];
const char * scan=str_size.c_str();
Bitu index=0;Bitu count=0;
while (*scan) {
if (*scan==',') {
number[index]=0;sizes[count++]=atoi(number);
index=0;
} else number[index++]=*scan;
scan++;
}
number[index]=0;sizes[count++]=atoi(number);
if(fstype=="fat" || fstype=="iso") {
// get the drive letter
@ -947,29 +999,36 @@ public:
struct stat test;
if (stat(temp_line.c_str(),&test)) {
// convert dosbox filename to system filename
char fullname[CROSS_LEN];
char tmp[CROSS_LEN];
safe_strncpy(tmp, temp_line.c_str(), CROSS_LEN);
Bit8u dummy;
if (!DOS_MakeName(tmp, fullname, &dummy) || strncmp(Drives[dummy]->GetInfo(),"local directory",15)) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_NON_LOCAL_DRIVE"));
return;
}
localDrive *ldp = (localDrive*)Drives[dummy];
ldp->GetSystemFilename(tmp, fullname);
temp_line = tmp;
if (stat(temp_line.c_str(),&test)) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND"));
return;
}
if ((test.st_mode & S_IFDIR)) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT"));
return;
//See if it works if the ~ are written out
std::string homedir(temp_line);
ResolveHomedir(homedir);
if(!stat(homedir.c_str(),&test)) {
temp_line = homedir;
} else {
// convert dosbox filename to system filename
char fullname[CROSS_LEN];
char tmp[CROSS_LEN];
safe_strncpy(tmp, temp_line.c_str(), CROSS_LEN);
Bit8u dummy;
if (!DOS_MakeName(tmp, fullname, &dummy) || strncmp(Drives[dummy]->GetInfo(),"local directory",15)) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_NON_LOCAL_DRIVE"));
return;
}
localDrive *ldp = (localDrive*)Drives[dummy];
ldp->GetSystemFilename(tmp, fullname);
temp_line = tmp;
if (stat(temp_line.c_str(),&test)) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND"));
return;
}
if ((test.st_mode & S_IFDIR)) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT"));
return;
}
}
}
paths.push_back(temp_line);
@ -986,6 +1045,35 @@ public:
}
if(fstype=="fat") {
if (imgsizedetect) {
FILE * diskfile = fopen(temp_line.c_str(), "rb+");
if(!diskfile) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE"));
return;
}
fseek(diskfile, 0L, SEEK_END);
Bit32u fcsize = (Bit32u)(ftell(diskfile) / 512L);
Bit8u buf[512];
fseek(diskfile, 0L, SEEK_SET);
if (fread(buf,sizeof(Bit8u),512,diskfile)<512) {
fclose(diskfile);
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE"));
return;
}
fclose(diskfile);
if ((buf[510]!=0x55) || (buf[511]!=0xaa)) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY"));
return;
}
Bitu sectors=(Bitu)(fcsize/(16*63));
if (sectors*16*63!=fcsize) {
WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY"));
return;
}
sizes[0]=512; sizes[1]=63; sizes[2]=16; sizes[3]=sectors;
LOG_MSG("autosized image file: %d:%d:%d:%d",sizes[0],sizes[1],sizes[2],sizes[3]);
}
newdrive=new fatDrive(temp_line.c_str(),sizes[0],sizes[1],sizes[2],sizes[3],0);
if(!(dynamic_cast<fatDrive*>(newdrive))->created_succesfully) {
delete newdrive;
@ -1039,7 +1127,9 @@ public:
MSCDEX_SetCDInterface(CDROM_USE_SDL, -1);
// create new drives for all images
std::vector<DOS_Drive*> isoDisks;
for (int i = 0; i < paths.size(); i++) {
std::vector<std::string>::size_type i;
std::vector<DOS_Drive*>::size_type ct;
for (i = 0; i < paths.size(); i++) {
int error = -1;
DOS_Drive* newDrive = new isoDrive(drive, paths[i].c_str(), mediaid, error);
isoDisks.push_back(newDrive);
@ -1055,15 +1145,15 @@ public:
}
// error: clean up and leave
if (error) {
for(int i = 0; i < isoDisks.size(); i++) {
delete isoDisks[i];
for(ct = 0; ct < isoDisks.size(); ct++) {
delete isoDisks[ct];
}
return;
}
}
// Update DriveManager
for(int i = 0; i < isoDisks.size(); i++) {
DriveManager::AppendDisk(drive - 'A', isoDisks[i]);
for(ct = 0; ct < isoDisks.size(); ct++) {
DriveManager::AppendDisk(drive - 'A', isoDisks[ct]);
}
DriveManager::InitializeDrive(drive - 'A');
@ -1073,7 +1163,7 @@ public:
// Print status message (success)
WriteOut(MSG_Get("MSCDEX_SUCCESS"));
std::string tmp(paths[0]);
for (int i = 1; i < paths.size(); i++) {
for (i = 1; i < paths.size(); i++) {
tmp += "; " + paths[i];
}
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"), drive, tmp.c_str());
@ -1295,6 +1385,7 @@ void DOS_SetupPrograms(void) {
);
MSG_Add("PROGRAM_BOOT_NOT_EXIST","Bootdisk file does not exist. Failing.\n");
MSG_Add("PROGRAM_BOOT_NOT_OPEN","Cannot open bootdisk file. Failing.\n");
MSG_Add("PROGRAM_BOOT_WRITE_PROTECTED","Image file is read-only! Might create problems.\n");
MSG_Add("PROGRAM_BOOT_PRINT_ERROR","This command boots DOSBox from either a floppy or hard disk image.\n\n"
"For this command, one can specify a succession of floppy disks swappable\n"
"by pressing Ctrl-F4, and -l specifies the mounted drive to boot from. If\n"
@ -1321,6 +1412,10 @@ void DOS_SetupPrograms(void) {
"For \033[33mhardrive\033[0m images: Must specify drive geometry for hard drives:\n"
"bytes_per_sector, sectors_per_cylinder, heads_per_cylinder, cylinder_count.\n"
"\033[34;1mIMGMOUNT drive-letter location-of-image -size bps,spc,hpc,cyl\033[0m\n");
MSG_Add("PROGRAM_IMGMOUNT_INVALID_IMAGE","Could not load image file.\n"
"Check that the path is correct and the image is accessible.\n");
MSG_Add("PROGRAM_IMGMOUNT_INVALID_GEOMETRY","Could not extract drive geometry from image.\n"
"Use parameter -size bps,spc,hpc,cyl to specify the geometry.\n");
MSG_Add("PROGRAM_IMGMOUNT_TYPE_UNSUPPORTED","Type \"%s\" is unsupported. Specify \"hdd\" or \"floppy\" or\"iso\".\n");
MSG_Add("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED","Format \"%s\" is unsupported. Specify \"fat\" or \"iso\" or \"none\".\n");
MSG_Add("PROGRAM_IMGMOUNT_SPECIFY_FILE","Must specify file-image to mount.\n");

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dos_tables.cpp,v 1.26 2007/01/08 20:36:53 qbix79 Exp $ */
/* $Id: dos_tables.cpp,v 1.29 2007/07/20 18:53:52 qbix79 Exp $ */
#include "dosbox.h"
#include "mem.h"
@ -40,10 +40,10 @@ RealPt DOS_TableLowCase;
static Bitu call_casemap;
static Bit16u dos_memseg;
static Bit16u dos_memseg=DOS_PRIVATE_SEGMENT;
Bit16u DOS_GetMemory(Bit16u pages) {
if (pages+dos_memseg>=0xd000) {
if (pages+dos_memseg>=DOS_PRIVATE_SEGMENT_END) {
E_Exit("DOS:Not enough memory for internal tables");
}
Bit16u page=dos_memseg;
@ -73,8 +73,7 @@ static Bit8u country_info[0x22] = {
};
void DOS_SetupTables(void) {
dos_memseg=0xc800;
Bit16u seg,seg2;Bitu i;
Bit16u seg;Bitu i;
dos.tables.mediaid=RealMake(DOS_GetMemory(4),0);
dos.tables.tempdta=RealMake(DOS_GetMemory(4),0);
dos.tables.tempdta_fcbdelete=RealMake(DOS_GetMemory(4),0);
@ -146,6 +145,10 @@ void DOS_SetupTables(void) {
real_writew(seg,4,100); //File Table supports 100 files
dos_infoblock.SetFCBTable(RealMake(seg,0));
/* Create a fake DPB */
dos.tables.dpb=DOS_GetMemory(2);
for(Bitu d=0;d<26;d++) real_writeb(dos.tables.dpb,d,d);
/* Create a fake disk buffer head */
seg=DOS_GetMemory(6);
for (Bitu ct=0; ct<0x20; ct++) real_writeb(seg,ct,0);

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: drive_cache.cpp,v 1.49 2007/01/08 19:45:39 qbix79 Exp $ */
/* $Id: drive_cache.cpp,v 1.50 2007/06/12 20:22:08 c2woody Exp $ */
#include "drives.h"
#include "dos_inc.h"
@ -242,7 +242,7 @@ void DOS_Drive_Cache::AddEntry(const char* path, bool checkExists)
Bit32u i;
// Check if there are any open search dir that are affected by this...
if (dir) for (i=0; i<MAX_OPENDIRS; i++) {
if ((dirSearch[i]==dir) && (index<=dirSearch[i]->nextEntry))
if ((dirSearch[i]==dir) && ((Bit32u)index<=dirSearch[i]->nextEntry))
dirSearch[i]->nextEntry++;
}
};
@ -378,7 +378,7 @@ Bit16u DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name)
do {
foundNr = curDir->longNameList[mid]->shortNr;
mid++;
} while(mid<curDir->longNameList.size() && (CompareShortname(name,curDir->longNameList[mid]->shortname)==0));
} while((Bitu)mid<curDir->longNameList.size() && (CompareShortname(name,curDir->longNameList[mid]->shortname)==0));
break;
};
}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: drive_fat.cpp,v 1.20 2007/01/08 19:45:39 qbix79 Exp $ */
/* $Id: drive_fat.cpp,v 1.22 2007/06/14 08:23:46 qbix79 Exp $ */
#include <stdio.h>
#include <stdlib.h>
@ -399,8 +399,8 @@ bool fatDrive::getEntryName(char *fullname, char *entname) {
return true;
}
bool fatDrive::getFileDirEntry(char * filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry) {
Bit32u len = (Bit32u)strlen(filename);
bool fatDrive::getFileDirEntry(char const * const filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry) {
size_t len = strlen(filename);
char dirtoken[DOS_PATHLENGTH];
Bit32u currentClust = 0;
@ -408,6 +408,7 @@ bool fatDrive::getFileDirEntry(char * filename, direntry * useEntry, Bit32u * di
char * findDir;
char * findFile;
strcpy(dirtoken,filename);
findFile=dirtoken;
/* Skip if testing in root directory */
if ((len>0) && (filename[len-1]!='\\')) {
@ -794,7 +795,7 @@ bool fatDrive::FileCreate(DOS_File **file, char *name, Bit16u attributes) {
bool fatDrive::FileExists(const char *name) {
direntry fileEntry;
Bit32u dummy1, dummy2;
if(!getFileDirEntry((char *)name, &fileEntry, &dummy1, &dummy2)) return false;
if(!getFileDirEntry(name, &fileEntry, &dummy1, &dummy2)) return false;
return true;
}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: drive_iso.cpp,v 1.17 2007/01/21 16:21:22 c2woody Exp $ */
/* $Id: drive_iso.cpp,v 1.20 2007/06/15 19:05:48 c2woody Exp $ */
#include <cctype>
#include <cstring>
@ -52,10 +52,9 @@ isoFile::isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u
time = stat->time;
date = stat->date;
attr = stat->attr;
size = stat->size;
fileBegin = offset;
filePos = fileBegin;
fileEnd = fileBegin + size;
fileEnd = fileBegin + stat->size;
cachedSector = -1;
open = true;
this->name = NULL;
@ -65,11 +64,11 @@ isoFile::isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u
bool isoFile::Read(Bit8u *data, Bit16u *size)
{
if (filePos + *size > fileEnd)
*size = fileEnd - filePos;
*size = (Bit16u)(fileEnd - filePos);
Bit16u nowSize = 0;
int sector = filePos / ISO_FRAMESIZE;
Bit16u sectorPos = filePos % ISO_FRAMESIZE;
Bit16u sectorPos = (Bit16u)(filePos % ISO_FRAMESIZE);
if (sector != cachedSector) {
if (drive->readSector(buffer, sector)) cachedSector = sector;
@ -272,7 +271,7 @@ bool isoDrive::FindFirst(char *dir, DOS_DTA &dta, bool fcb_findfirst)
}
// get a directory iterator and save its id in the dta
dta.SetDirID(GetDirIterator(&de));
dta.SetDirID((Bit16u)GetDirIterator(&de));
Bit8u attr;
char pattern[ISO_MAXPATHNAME];
@ -349,6 +348,7 @@ bool isoDrive::GetFileAttr(char *name, Bit16u *attr)
bool success = lookup(&de, name);
if (success) {
*attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY;
if (IS_HIDDEN(de.fileFlags)) *attr |= DOS_ATTR_HIDDEN;
if (IS_DIR(de.fileFlags)) *attr |= DOS_ATTR_DIRECTORY;
}
return success;
@ -532,7 +532,7 @@ bool isoDrive :: loadImage()
isoPVD pvd;
readSector((Bit8u*)(&pvd), ISO_FIRST_VD);
if (pvd.type != 1 || strncmp((char*)pvd.standardIdent, "CD001", 5) || pvd.version != 1) return false;
return (readDirEntry(&this->rootEntry, pvd.rootEntry));
return (readDirEntry(&this->rootEntry, pvd.rootEntry)>0);
}
bool isoDrive :: lookup(isoDirEntry *de, const char *path)

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: drive_local.cpp,v 1.74 2007/01/09 17:44:20 c2woody Exp $ */
/* $Id: drive_local.cpp,v 1.75 2007/06/13 07:25:14 qbix79 Exp $ */
#include <stdio.h>
#include <stdlib.h>
@ -517,7 +517,6 @@ localFile::localFile(const char* _name, FILE * handle) {
} else {
time=1;date=1;
}
size=(Bit32u)temp_stat.st_size;
attr=DOS_ATTR_ARCHIVE;
last_action=NONE;
read_only_medium=false;

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: drives.h,v 1.36 2007/01/21 16:21:22 c2woody Exp $ */
/* $Id: drives.h,v 1.37 2007/06/14 08:23:46 qbix79 Exp $ */
#ifndef _DRIVES_H__
#define _DRIVES_H__
@ -181,7 +181,7 @@ private:
Bit32u getClustFirstSect(Bit32u clustNum);
bool FindNextInternal(Bit32u dirClustNumber, DOS_DTA & dta, direntry *foundEntry);
bool getDirClustNum(char * dir, Bit32u * clustNum, bool parDir);
bool getFileDirEntry(char * filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry);
bool getFileDirEntry(char const * const filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry);
bool addDirectoryEntry(Bit32u dirClustNumber, direntry useEntry);
void zeroOutCluster(Bit32u clustNumber);
bool getEntryName(char *fullname, char *entname);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: dosbox.cpp,v 1.115 2007/02/22 08:44:06 qbix79 Exp $ */
/* $Id: dosbox.cpp,v 1.118 2007/07/02 20:06:59 c2woody Exp $ */
#include <stdlib.h>
#include <stdarg.h>
@ -236,6 +236,10 @@ static void DOSBOX_RealInit(Section * sec) {
ticksLocked = false;
DOSBOX_SetLoop(&Normal_Loop);
MSG_Init(section);
MSG_Add("CONFIGFILE_INTRO",
"# This is the configurationfile for DOSBox %s.\n"
"# Lines starting with a # are commentlines.\n"
"# They are used to (briefly) document the effect of each option.\n");
MAPPER_AddHandler(DOSBOX_UnlockSpeed, MK_f12, MMOD2,"speedlock","Speedlock");
svgaCard = SVGA_S3Trio;
@ -299,6 +303,8 @@ void DOSBOX_Init(void) {
" Supported are none,normal2x,normal3x,advmame2x,advmame3x,hq2x,hq3x,\n"
" 2xsai,super2xsai,supereagle,advinterp2x,advinterp3x,\n"
" tv2x,tv3x,rgb2x,rgb3x,scan2x,scan3x.\n"
" If forced is appended (like scaler=hq2x forced), the scaler will be used\n"
" even if the result might not be desired.\n"
);
secprop=control->AddSection_prop("cpu",&CPU_Init,true);//done
@ -420,7 +426,7 @@ void DOSBOX_Init(void) {
"tandy -- Enable Tandy Sound System emulation (off,on,auto).\n"
" For auto Tandysound emulation is present only if machine is set to tandy.\n"
"tandyrate -- Sample rate of the Tandy 3-Voice generation.\n"
"disney -- Enable Disney Sound Source emulation.\n"
"disney -- Enable Disney Sound Source emulation. Covox Voice Master and Speech Thing compatible.\n"
);
secprop=control->AddSection_prop("joystick",&BIOS_Init,false);//done

View File

@ -64,11 +64,12 @@ public:
next=handler_list;
handler_list=this;
};
virtual bool Open(const char * conf) { return true; };
virtual bool Open(const char * /*conf*/) { return true; };
virtual void Close(void) {};
virtual void PlayMsg(Bit8u * msg) {};
virtual void PlaySysex(Bit8u * sysex,Bitu len) {};
virtual char * GetName(void) { return "none"; };
virtual void PlayMsg(Bit8u * /*msg*/) {};
virtual void PlaySysex(Bit8u * /*sysex*/,Bitu /*len*/) {};
virtual const char * GetName(void) { return "none"; };
virtual ~MidiHandler() { };
MidiHandler * next;
};
@ -199,7 +200,7 @@ getdefault:
static MIDI* test;
void MIDI_Destroy(Section* sec){
void MIDI_Destroy(Section* /*sec*/){
delete test;
}
void MIDI_Init(Section * sec) {

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: midi_alsa.h,v 1.15 2007/01/08 19:45:39 qbix79 Exp $ */
/* $Id: midi_alsa.h,v 1.16 2007/06/14 08:23:46 qbix79 Exp $ */
#define ALSA_PCM_OLD_HW_PARAMS_API
#define ALSA_PCM_OLD_SW_PARAMS_API
@ -50,7 +50,7 @@ private:
snd_seq_flush_output(seq_handle);
}
int parse_addr(char *arg, int *client, int *port) {
int parse_addr(const char *arg, int *client, int *port) {
char *p;
if (isdigit(*arg)) {
@ -69,7 +69,7 @@ private:
}
public:
MidiHandler_alsa() : MidiHandler() {};
char* GetName(void) { return "alsa"; }
const char* GetName(void) { return "alsa"; }
void PlaySysex(Bit8u * sysex,Bitu len) {
snd_seq_ev_set_sysex(&ev, len, sysex);
send_event(1);

View File

@ -24,7 +24,7 @@ private:
AudioUnit m_outputUnit;
public:
MidiHandler_coreaudio() : m_musicDevice(0), m_outputUnit(0) {}
char * GetName(void) { return "coreaudio"; }
const char * GetName(void) { return "coreaudio"; }
bool Open(const char * conf) {
int err;
AudioUnitConnection auconnect;

View File

@ -26,7 +26,7 @@ private:
bool isOpen;
public:
MidiHandler_oss() : MidiHandler(),isOpen(false) {};
char * GetName(void) { return "oss";};
const char * GetName(void) { return "oss";};
bool Open(const char * conf) {
char devname[512];
if (conf && conf[0]) safe_strncpy(devname,conf,512);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: midi_win32.h,v 1.13 2007/01/08 19:45:39 qbix79 Exp $ */
/* $Id: midi_win32.h,v 1.14 2007/06/14 08:23:46 qbix79 Exp $ */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
@ -34,7 +34,7 @@ private:
bool isOpen;
public:
MidiHandler_win32() : isOpen(false),MidiHandler() {};
char * GetName(void) { return "win32";};
const char * GetName(void) { return "win32";};
bool Open(const char * conf) {
if (isOpen) return false;
m_event = CreateEvent (NULL, true, true, NULL);

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: render.cpp,v 1.51 2007/02/03 13:00:16 harekiet Exp $ */
/* $Id: render.cpp,v 1.54 2007/07/05 16:03:49 c2woody Exp $ */
#include <sys/types.h>
#include <dirent.h>
@ -282,7 +282,7 @@ static void RENDER_Reset( void ) {
gfx_scalew = 1;
gfx_scaleh = 1;
}
if (dblh && dblw) {
if (dblh && dblw || (render.scale.forced && !dblh && !dblw)) {
/* Initialize always working defaults */
if (render.scale.size == 2)
simpleBlock = &ScaleNormal2x;
@ -291,7 +291,9 @@ static void RENDER_Reset( void ) {
else
simpleBlock = &ScaleNormal1x;
/* Maybe override them */
#if RENDER_USE_ADVANCED_SCALERS>0
switch (render.scale.op) {
#if RENDER_USE_ADVANCED_SCALERS>2
case scalerOpAdvInterp:
if (render.scale.size == 2)
complexBlock = &ScaleAdvInterp2x;
@ -322,6 +324,7 @@ static void RENDER_Reset( void ) {
if (render.scale.size == 2)
complexBlock = &Scale2xSaI;
break;
#endif
case scalerOpTV:
if (render.scale.size == 2)
simpleBlock = &ScaleTV2x;
@ -341,6 +344,7 @@ static void RENDER_Reset( void ) {
simpleBlock = &ScaleScan3x;
break;
}
#endif
} else if (dblw) {
simpleBlock = &ScaleNormalDw;
} else if (dblh) {
@ -351,10 +355,14 @@ forcenormal:
simpleBlock = &ScaleNormal1x;
}
if (complexBlock) {
#if RENDER_USE_ADVANCED_SCALERS>1
if ((width >= SCALER_COMPLEXWIDTH - 16) || height >= SCALER_COMPLEXHEIGHT - 16) {
LOG_MSG("Scaler can't handle this resolution, going back to normal");
goto forcenormal;
}
#else
goto forcenormal;
#endif
gfx_flags = complexBlock->gfxFlags;
xscale = complexBlock->xscale;
yscale = complexBlock->yscale;
@ -423,18 +431,24 @@ forcenormal:
E_Exit("Failed to create a rendering output");
ScalerLineBlock_t *lineBlock;
if (gfx_flags & GFX_HARDWARE) {
#if RENDER_USE_ADVANCED_SCALERS>1
if (complexBlock) {
lineBlock = &ScalerCache;
render.scale.complexHandler = complexBlock->Linear[ render.scale.outMode ];
} else {
} else
#endif
{
render.scale.complexHandler = 0;
lineBlock = &simpleBlock->Linear;
}
} else {
#if RENDER_USE_ADVANCED_SCALERS>1
if (complexBlock) {
lineBlock = &ScalerCache;
render.scale.complexHandler = complexBlock->Random[ render.scale.outMode ];
} else {
} else
#endif
{
render.scale.complexHandler = 0;
lineBlock = &simpleBlock->Random;
}
@ -548,6 +562,8 @@ void RENDER_Init(Section * sec) {
//For restarting the renderer.
static bool running = false;
bool aspect = render.aspect;
Bitu scalersize = render.scale.size;
bool scalerforced = render.scale.forced;
scalerOperation_t scaleOp = render.scale.op;
render.pal.first=256;
@ -555,15 +571,31 @@ void RENDER_Init(Section * sec) {
render.aspect=section->Get_bool("aspect");
render.frameskip.max=section->Get_int("frameskip");
render.frameskip.count=0;
const char * scaler;std::string cline;
const char * scaler;
std::string cline;
std::string scaler_str;
if (control->cmdline->FindString("-scaler",cline,false)) {
scaler=cline.c_str();
render.scale.forced=false;
} else if (control->cmdline->FindString("-forcescaler",cline,false)) {
scaler=cline.c_str();
render.scale.forced=true;
} else {
scaler=section->Get_string("scaler");
CommandLine cmd(0,section->Get_string("scaler"));
cmd.FindCommand(1,scaler_str);
scaler=scaler_str.c_str();
render.scale.forced=false;
if (cmd.GetCount()>1) {
std::string str;
if (cmd.FindCommand(2,str)) {
if (str=="forced") render.scale.forced=true;
}
}
}
if (!strcasecmp(scaler,"none")) { render.scale.op = scalerOpNormal;render.scale.size = 1; }
else if (!strcasecmp(scaler,"normal2x")) { render.scale.op = scalerOpNormal;render.scale.size = 2; }
else if (!strcasecmp(scaler,"normal3x")) { render.scale.op = scalerOpNormal;render.scale.size = 3; }
#if RENDER_USE_ADVANCED_SCALERS>2
else if (!strcasecmp(scaler,"advmame2x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 2; }
else if (!strcasecmp(scaler,"advmame3x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 3; }
else if (!strcasecmp(scaler,"advinterp2x")) { render.scale.op = scalerOpAdvInterp;render.scale.size = 2; }
@ -573,19 +605,24 @@ void RENDER_Init(Section * sec) {
else if (!strcasecmp(scaler,"2xsai")) { render.scale.op = scalerOpSaI;render.scale.size = 2; }
else if (!strcasecmp(scaler,"super2xsai")) { render.scale.op = scalerOpSuperSaI;render.scale.size = 2; }
else if (!strcasecmp(scaler,"supereagle")) { render.scale.op = scalerOpSuperEagle;render.scale.size = 2; }
#endif
#if RENDER_USE_ADVANCED_SCALERS>0
else if (!strcasecmp(scaler,"tv2x")) { render.scale.op = scalerOpTV;render.scale.size = 2; }
else if (!strcasecmp(scaler,"tv3x")) { render.scale.op = scalerOpTV;render.scale.size = 3; }
else if (!strcasecmp(scaler,"rgb2x")){ render.scale.op = scalerOpRGB;render.scale.size = 2; }
else if (!strcasecmp(scaler,"rgb3x")){ render.scale.op = scalerOpRGB;render.scale.size = 3; }
else if (!strcasecmp(scaler,"scan2x")){ render.scale.op = scalerOpScan;render.scale.size = 2; }
else if (!strcasecmp(scaler,"scan3x")){ render.scale.op = scalerOpScan;render.scale.size = 3; }
#endif
else {
render.scale.op = scalerOpNormal;render.scale.size = 1;
LOG_MSG("Illegal scaler type %s,falling back to normal.",scaler);
}
//If something changed that needs a ReInit
if(running && (render.aspect != aspect || render.scale.op != scaleOp))
if(running &&((render.aspect != aspect) || (render.scale.op != scaleOp) ||
(render.scale.size != scalersize) || (render.scale.forced != scalerforced) ||
render.scale.forced))
RENDER_CallBack( GFX_CallBackReset );
if(!running) render.updating=true;

View File

@ -36,7 +36,9 @@ static union {
} scalerWriteCache;
//scalerFrameCache_t scalerFrameCache;
scalerSourceCache_t scalerSourceCache;
#if RENDER_USE_ADVANCED_SCALERS>1
scalerChangeCache_t scalerChangeCache;
#endif
#define _conc2(A,B) A ## B
#define _conc3(A,B,C) A ## B ## C
@ -159,207 +161,223 @@ static INLINE void ScalerAddLines( Bitu changed, Bitu count ) {
#undef DBPP
#if RENDER_USE_ADVANCED_SCALERS>1
ScalerLineBlock_t ScalerCache = {
Cache_8_8, Cache_8_15, Cache_8_16, Cache_8_32,
0, Cache_15_15, Cache_15_16, Cache_15_32,
0, Cache_16_15, Cache_16_16, Cache_16_32,
0, Cache_32_15, Cache_32_16, Cache_32_32,
Cache_8_8, Cache_9_15, Cache_9_16, Cache_9_32,
{ Cache_8_8, Cache_8_15 , Cache_8_16 , Cache_8_32 },
{ 0, Cache_15_15, Cache_15_16, Cache_15_32},
{ 0, Cache_16_15, Cache_16_16, Cache_16_32},
{ 0, Cache_32_15, Cache_32_16, Cache_32_32},
{ Cache_8_8, Cache_9_15 , Cache_9_16 , Cache_9_32 }
};
#endif
ScalerSimpleBlock_t ScaleNormal1x = {
"Normal",
GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32,
1,1,
Normal1x_8_8_L, Normal1x_8_15_L, Normal1x_8_16_L, Normal1x_8_32_L,
0, Normal1x_15_15_L, Normal1x_15_16_L, Normal1x_15_32_L,
0, Normal1x_16_15_L, Normal1x_16_16_L, Normal1x_16_32_L,
0, Normal1x_32_15_L, Normal1x_32_16_L, Normal1x_32_32_L,
Normal1x_8_8_L, Normal1x_9_15_L, Normal1x_9_16_L, Normal1x_9_32_L,
Normal1x_8_8_R, Normal1x_8_15_R, Normal1x_8_16_R, Normal1x_8_32_R,
0, Normal1x_15_15_R, Normal1x_15_16_R, Normal1x_15_32_R,
0, Normal1x_16_15_R, Normal1x_16_16_R, Normal1x_16_32_R,
0, Normal1x_32_15_R, Normal1x_32_16_R, Normal1x_32_32_R,
Normal1x_8_8_R, Normal1x_9_15_R, Normal1x_9_16_R, Normal1x_9_32_R,
};
1,1,{
{ Normal1x_8_8_L, Normal1x_8_15_L , Normal1x_8_16_L , Normal1x_8_32_L },
{ 0, Normal1x_15_15_L, Normal1x_15_16_L, Normal1x_15_32_L},
{ 0, Normal1x_16_15_L, Normal1x_16_16_L, Normal1x_16_32_L},
{ 0, Normal1x_32_15_L, Normal1x_32_16_L, Normal1x_32_32_L},
{ Normal1x_8_8_L, Normal1x_9_15_L , Normal1x_9_16_L , Normal1x_9_32_L }
},{
{ Normal1x_8_8_R, Normal1x_8_15_R , Normal1x_8_16_R , Normal1x_8_32_R },
{ 0, Normal1x_15_15_R, Normal1x_15_16_R, Normal1x_15_32_R},
{ 0, Normal1x_16_15_R, Normal1x_16_16_R, Normal1x_16_32_R},
{ 0, Normal1x_32_15_R, Normal1x_32_16_R, Normal1x_32_32_R},
{ Normal1x_8_8_R, Normal1x_9_15_R , Normal1x_9_16_R , Normal1x_9_32_R }
}};
ScalerSimpleBlock_t ScaleNormalDw = {
"Normal",
GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32,
2,1,
NormalDw_8_8_L, NormalDw_8_15_L, NormalDw_8_16_L, NormalDw_8_32_L,
0, NormalDw_15_15_L, NormalDw_15_16_L, NormalDw_15_32_L,
0, NormalDw_16_15_L, NormalDw_16_16_L, NormalDw_16_32_L,
0, NormalDw_32_15_L, NormalDw_32_16_L, NormalDw_32_32_L,
NormalDw_8_8_L, NormalDw_9_15_L, NormalDw_9_16_L, NormalDw_9_32_L,
NormalDw_8_8_R, NormalDw_8_15_R, NormalDw_8_16_R, NormalDw_8_32_R,
0, NormalDw_15_15_R, NormalDw_15_16_R, NormalDw_15_32_R,
0, NormalDw_16_15_R, NormalDw_16_16_R, NormalDw_16_32_R,
0, NormalDw_32_15_R, NormalDw_32_16_R, NormalDw_32_32_R,
NormalDw_8_8_R, NormalDw_9_15_R, NormalDw_9_16_R, NormalDw_9_32_R,
};
2,1,{
{ NormalDw_8_8_L, NormalDw_8_15_L , NormalDw_8_16_L , NormalDw_8_32_L },
{ 0, NormalDw_15_15_L, NormalDw_15_16_L, NormalDw_15_32_L},
{ 0, NormalDw_16_15_L, NormalDw_16_16_L, NormalDw_16_32_L},
{ 0, NormalDw_32_15_L, NormalDw_32_16_L, NormalDw_32_32_L},
{ NormalDw_8_8_L, NormalDw_9_15_L , NormalDw_9_16_L , NormalDw_9_32_L }
},{
{ NormalDw_8_8_R, NormalDw_8_15_R , NormalDw_8_16_R , NormalDw_8_32_R },
{ 0, NormalDw_15_15_R, NormalDw_15_16_R, NormalDw_15_32_R},
{ 0, NormalDw_16_15_R, NormalDw_16_16_R, NormalDw_16_32_R},
{ 0, NormalDw_32_15_R, NormalDw_32_16_R, NormalDw_32_32_R},
{ NormalDw_8_8_R, NormalDw_9_15_R , NormalDw_9_16_R , NormalDw_9_32_R }
}};
ScalerSimpleBlock_t ScaleNormalDh = {
"Normal",
GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32,
1,2,
NormalDh_8_8_L, NormalDh_8_15_L, NormalDh_8_16_L, NormalDh_8_32_L,
0, NormalDh_15_15_L, NormalDh_15_16_L, NormalDh_15_32_L,
0, NormalDh_16_15_L, NormalDh_16_16_L, NormalDh_16_32_L,
0, NormalDh_32_15_L, NormalDh_32_16_L, NormalDh_32_32_L,
NormalDh_8_8_L, NormalDh_9_15_L, NormalDh_9_16_L, NormalDh_9_32_L,
NormalDh_8_8_R, NormalDh_8_15_R, NormalDh_8_16_R, NormalDh_8_32_R,
0, NormalDh_15_15_R, NormalDh_15_16_R, NormalDh_15_32_R,
0, NormalDh_16_15_R, NormalDh_16_16_R, NormalDh_16_32_R,
0, NormalDh_32_15_R, NormalDh_32_16_R, NormalDh_32_32_R,
NormalDh_8_8_R, NormalDh_9_15_R, NormalDh_9_16_R, NormalDh_9_32_R,
};
1,2,{
{ NormalDh_8_8_L, NormalDh_8_15_L , NormalDh_8_16_L , NormalDh_8_32_L },
{ 0, NormalDh_15_15_L, NormalDh_15_16_L, NormalDh_15_32_L},
{ 0, NormalDh_16_15_L, NormalDh_16_16_L, NormalDh_16_32_L},
{ 0, NormalDh_32_15_L, NormalDh_32_16_L, NormalDh_32_32_L},
{ NormalDh_8_8_L, NormalDh_9_15_L , NormalDh_9_16_L , NormalDh_9_32_L }
},{
{ NormalDh_8_8_R, NormalDh_8_15_R , NormalDh_8_16_R , NormalDh_8_32_R },
{ 0, NormalDh_15_15_R, NormalDh_15_16_R, NormalDh_15_32_R},
{ 0, NormalDh_16_15_R, NormalDh_16_16_R, NormalDh_16_32_R},
{ 0, NormalDh_32_15_R, NormalDh_32_16_R, NormalDh_32_32_R},
{ NormalDh_8_8_R, NormalDh_9_15_R , NormalDh_9_16_R , NormalDh_9_32_R }
}};
ScalerSimpleBlock_t ScaleNormal2x = {
"Normal2x",
GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32,
2,2,
Normal2x_8_8_L, Normal2x_8_15_L, Normal2x_8_16_L, Normal2x_8_32_L,
0, Normal2x_15_15_L, Normal2x_15_16_L, Normal2x_15_32_L,
0, Normal2x_16_15_L, Normal2x_16_16_L, Normal2x_16_32_L,
0, Normal2x_32_15_L, Normal2x_32_16_L, Normal2x_32_32_L,
Normal2x_8_8_L, Normal2x_9_15_L, Normal2x_9_16_L, Normal2x_9_32_L,
Normal2x_8_8_R, Normal2x_8_15_R, Normal2x_8_16_R, Normal2x_8_32_R,
0, Normal2x_15_15_R, Normal2x_15_16_R, Normal2x_15_32_R,
0, Normal2x_16_15_R, Normal2x_16_16_R, Normal2x_16_32_R,
0, Normal2x_32_15_R, Normal2x_32_16_R, Normal2x_32_32_R,
Normal2x_8_8_R, Normal2x_9_15_R, Normal2x_9_16_R, Normal2x_9_32_R,
};
2,2,{
{ Normal2x_8_8_L, Normal2x_8_15_L, Normal2x_8_16_L, Normal2x_8_32_L },
{ 0, Normal2x_15_15_L, Normal2x_15_16_L, Normal2x_15_32_L},
{ 0, Normal2x_16_15_L, Normal2x_16_16_L, Normal2x_16_32_L},
{ 0, Normal2x_32_15_L, Normal2x_32_16_L, Normal2x_32_32_L},
{ Normal2x_8_8_L, Normal2x_9_15_L , Normal2x_9_16_L, Normal2x_9_32_L }
},{
{ Normal2x_8_8_R, Normal2x_8_15_R , Normal2x_8_16_R, Normal2x_8_32_R },
{ 0, Normal2x_15_15_R, Normal2x_15_16_R, Normal2x_15_32_R},
{ 0, Normal2x_16_15_R, Normal2x_16_16_R, Normal2x_16_32_R},
{ 0, Normal2x_32_15_R, Normal2x_32_16_R, Normal2x_32_32_R},
{ Normal2x_8_8_R, Normal2x_9_15_R , Normal2x_9_16_R, Normal2x_9_32_R },
}};
ScalerSimpleBlock_t ScaleNormal3x = {
"Normal3x",
GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32,
3,3,
Normal3x_8_8_L, Normal3x_8_15_L, Normal3x_8_16_L, Normal3x_8_32_L,
0, Normal3x_15_15_L, Normal3x_15_16_L, Normal3x_15_32_L,
0, Normal3x_16_15_L, Normal3x_16_16_L, Normal3x_16_32_L,
0, Normal3x_32_15_L, Normal3x_32_16_L, Normal3x_32_32_L,
Normal3x_8_8_L, Normal3x_9_15_L, Normal3x_9_16_L, Normal3x_9_32_L,
Normal3x_8_8_R, Normal3x_8_15_R, Normal3x_8_16_R, Normal3x_8_32_R,
0, Normal3x_15_15_R, Normal3x_15_16_R, Normal3x_15_32_R,
0, Normal3x_16_15_R, Normal3x_16_16_R, Normal3x_16_32_R,
0, Normal3x_32_15_R, Normal3x_32_16_R, Normal3x_32_32_R,
Normal3x_8_8_R, Normal3x_9_15_R, Normal3x_9_16_R, Normal3x_9_32_R,
};
3,3,{
{ Normal3x_8_8_L, Normal3x_8_15_L , Normal3x_8_16_L , Normal3x_8_32_L },
{ 0, Normal3x_15_15_L, Normal3x_15_16_L, Normal3x_15_32_L},
{ 0, Normal3x_16_15_L, Normal3x_16_16_L, Normal3x_16_32_L},
{ 0, Normal3x_32_15_L, Normal3x_32_16_L, Normal3x_32_32_L},
{ Normal3x_8_8_L, Normal3x_9_15_L , Normal3x_9_16_L , Normal3x_9_32_L }
},{
{ Normal3x_8_8_R, Normal3x_8_15_R , Normal3x_8_16_R , Normal3x_8_32_R },
{ 0, Normal3x_15_15_R, Normal3x_15_16_R, Normal3x_15_32_R},
{ 0, Normal3x_16_15_R, Normal3x_16_16_R, Normal3x_16_32_R},
{ 0, Normal3x_32_15_R, Normal3x_32_16_R, Normal3x_32_32_R},
{ Normal3x_8_8_R, Normal3x_9_15_R , Normal3x_9_16_R , Normal3x_9_32_R }
}};
#if RENDER_USE_ADVANCED_SCALERS>0
ScalerSimpleBlock_t ScaleTV2x = {
"TV2x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
2,2,
0, TV2x_8_15_L, TV2x_8_16_L, TV2x_8_32_L,
0, TV2x_15_15_L, TV2x_15_16_L, TV2x_15_32_L,
0, TV2x_16_15_L, TV2x_16_16_L, TV2x_16_32_L,
0, TV2x_32_15_L, TV2x_32_16_L, TV2x_32_32_L,
0, TV2x_9_15_L, TV2x_9_16_L, TV2x_9_32_L,
0, TV2x_8_15_R, TV2x_8_16_R, TV2x_8_32_R,
0, TV2x_15_15_R, TV2x_15_16_R, TV2x_15_32_R,
0, TV2x_16_15_R, TV2x_16_16_R, TV2x_16_32_R,
0, TV2x_32_15_R, TV2x_32_16_R, TV2x_32_32_R,
0, TV2x_9_15_R, TV2x_9_16_R, TV2x_9_32_R,
};
2,2,{
{ 0, TV2x_8_15_L , TV2x_8_16_L , TV2x_8_32_L },
{ 0, TV2x_15_15_L, TV2x_15_16_L, TV2x_15_32_L},
{ 0, TV2x_16_15_L, TV2x_16_16_L, TV2x_16_32_L},
{ 0, TV2x_32_15_L, TV2x_32_16_L, TV2x_32_32_L},
{ 0, TV2x_9_15_L , TV2x_9_16_L , TV2x_9_32_L }
},{
{ 0, TV2x_8_15_R , TV2x_8_16_R , TV2x_8_32_R },
{ 0, TV2x_15_15_R, TV2x_15_16_R, TV2x_15_32_R},
{ 0, TV2x_16_15_R, TV2x_16_16_R, TV2x_16_32_R},
{ 0, TV2x_32_15_R, TV2x_32_16_R, TV2x_32_32_R},
{ 0, TV2x_9_15_R , TV2x_9_16_R , TV2x_9_32_R }
}};
ScalerSimpleBlock_t ScaleTV3x = {
"TV3x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
3,3,
0, TV3x_8_15_L, TV3x_8_16_L, TV3x_8_32_L,
0, TV3x_15_15_L, TV3x_15_16_L, TV3x_15_32_L,
0, TV3x_16_15_L, TV3x_16_16_L, TV3x_16_32_L,
0, TV3x_32_15_L, TV3x_32_16_L, TV3x_32_32_L,
0, TV3x_9_15_L, TV3x_9_16_L, TV3x_9_32_L,
0, TV3x_8_15_R, TV3x_8_16_R, TV3x_8_32_R,
0, TV3x_15_15_R, TV3x_15_16_R, TV3x_15_32_R,
0, TV3x_16_15_R, TV3x_16_16_R, TV3x_16_32_R,
0, TV3x_32_15_R, TV3x_32_16_R, TV3x_32_32_R,
0, TV3x_9_15_R, TV3x_9_16_R, TV3x_9_32_R,
};
3,3,{
{ 0, TV3x_8_15_L , TV3x_8_16_L , TV3x_8_32_L },
{ 0, TV3x_15_15_L, TV3x_15_16_L, TV3x_15_32_L},
{ 0, TV3x_16_15_L, TV3x_16_16_L, TV3x_16_32_L},
{ 0, TV3x_32_15_L, TV3x_32_16_L, TV3x_32_32_L},
{ 0, TV3x_9_15_L , TV3x_9_16_L , TV3x_9_32_L }
},{
{ 0, TV3x_8_15_R , TV3x_8_16_R , TV3x_8_32_R },
{ 0, TV3x_15_15_R, TV3x_15_16_R, TV3x_15_32_R},
{ 0, TV3x_16_15_R, TV3x_16_16_R, TV3x_16_32_R},
{ 0, TV3x_32_15_R, TV3x_32_16_R, TV3x_32_32_R},
{ 0, TV3x_9_15_R , TV3x_9_16_R , TV3x_9_32_R }
}};
ScalerSimpleBlock_t ScaleScan2x = {
"Scan2x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
2,2,
0, Scan2x_8_15_L, Scan2x_8_16_L, Scan2x_8_32_L,
0, Scan2x_15_15_L, Scan2x_15_16_L, Scan2x_15_32_L,
0, Scan2x_16_15_L, Scan2x_16_16_L, Scan2x_16_32_L,
0, Scan2x_32_15_L, Scan2x_32_16_L, Scan2x_32_32_L,
0, Scan2x_9_15_L, Scan2x_9_16_L, Scan2x_9_32_L,
0, Scan2x_8_15_R, Scan2x_8_16_R, Scan2x_8_32_R,
0, Scan2x_15_15_R, Scan2x_15_16_R, Scan2x_15_32_R,
0, Scan2x_16_15_R, Scan2x_16_16_R, Scan2x_16_32_R,
0, Scan2x_32_15_R, Scan2x_32_16_R, Scan2x_32_32_R,
0, Scan2x_9_15_R, Scan2x_9_16_R, Scan2x_9_32_R,
};
2,2,{
{ 0, Scan2x_8_15_L , Scan2x_8_16_L , Scan2x_8_32_L },
{ 0, Scan2x_15_15_L, Scan2x_15_16_L, Scan2x_15_32_L},
{ 0, Scan2x_16_15_L, Scan2x_16_16_L, Scan2x_16_32_L},
{ 0, Scan2x_32_15_L, Scan2x_32_16_L, Scan2x_32_32_L},
{ 0, Scan2x_9_15_L , Scan2x_9_16_L , Scan2x_9_32_L }
},{
{ 0, Scan2x_8_15_R , Scan2x_8_16_R , Scan2x_8_32_R },
{ 0, Scan2x_15_15_R, Scan2x_15_16_R, Scan2x_15_32_R},
{ 0, Scan2x_16_15_R, Scan2x_16_16_R, Scan2x_16_32_R},
{ 0, Scan2x_32_15_R, Scan2x_32_16_R, Scan2x_32_32_R},
{ 0, Scan2x_9_15_R , Scan2x_9_16_R , Scan2x_9_32_R }
}};
ScalerSimpleBlock_t ScaleScan3x = {
"Scan3x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
3,3,
0, Scan3x_8_15_L, Scan3x_8_16_L, Scan3x_8_32_L,
0, Scan3x_15_15_L, Scan3x_15_16_L, Scan3x_15_32_L,
0, Scan3x_16_15_L, Scan3x_16_16_L, Scan3x_16_32_L,
0, Scan3x_32_15_L, Scan3x_32_16_L, Scan3x_32_32_L,
0, Scan3x_9_15_L, Scan3x_9_16_L, Scan3x_9_32_L,
0, Scan3x_8_15_R, Scan3x_8_16_R, Scan3x_8_32_R,
0, Scan3x_15_15_R, Scan3x_15_16_R, Scan3x_15_32_R,
0, Scan3x_16_15_R, Scan3x_16_16_R, Scan3x_16_32_R,
0, Scan3x_32_15_R, Scan3x_32_16_R, Scan3x_32_32_R,
0, Scan3x_9_15_R, Scan3x_9_16_R, Scan3x_9_32_R,
};
3,3,{
{ 0, Scan3x_8_15_L , Scan3x_8_16_L , Scan3x_8_32_L },
{ 0, Scan3x_15_15_L, Scan3x_15_16_L, Scan3x_15_32_L},
{ 0, Scan3x_16_15_L, Scan3x_16_16_L, Scan3x_16_32_L},
{ 0, Scan3x_32_15_L, Scan3x_32_16_L, Scan3x_32_32_L},
{ 0, Scan3x_9_15_L , Scan3x_9_16_L , Scan3x_9_32_L },
},{
{ 0, Scan3x_8_15_R , Scan3x_8_16_R , Scan3x_8_32_R },
{ 0, Scan3x_15_15_R, Scan3x_15_16_R, Scan3x_15_32_R},
{ 0, Scan3x_16_15_R, Scan3x_16_16_R, Scan3x_16_32_R},
{ 0, Scan3x_32_15_R, Scan3x_32_16_R, Scan3x_32_32_R},
{ 0, Scan3x_9_15_R , Scan3x_9_16_R , Scan3x_9_32_R }
}};
ScalerSimpleBlock_t ScaleRGB2x = {
"RGB2x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
2,2,
0, RGB2x_8_15_L, RGB2x_8_16_L, RGB2x_8_32_L,
0, RGB2x_15_15_L, RGB2x_15_16_L, RGB2x_15_32_L,
0, RGB2x_16_15_L, RGB2x_16_16_L, RGB2x_16_32_L,
0, RGB2x_32_15_L, RGB2x_32_16_L, RGB2x_32_32_L,
0, RGB2x_9_15_L, RGB2x_9_16_L, RGB2x_9_32_L,
0, RGB2x_8_15_R, RGB2x_8_16_R, RGB2x_8_32_R,
0, RGB2x_15_15_R, RGB2x_15_16_R, RGB2x_15_32_R,
0, RGB2x_16_15_R, RGB2x_16_16_R, RGB2x_16_32_R,
0, RGB2x_32_15_R, RGB2x_32_16_R, RGB2x_32_32_R,
0, RGB2x_9_15_R, RGB2x_9_16_R, RGB2x_9_32_R,
};
2,2,{
{ 0, RGB2x_8_15_L , RGB2x_8_16_L , RGB2x_8_32_L },
{ 0, RGB2x_15_15_L, RGB2x_15_16_L, RGB2x_15_32_L},
{ 0, RGB2x_16_15_L, RGB2x_16_16_L, RGB2x_16_32_L},
{ 0, RGB2x_32_15_L, RGB2x_32_16_L, RGB2x_32_32_L},
{ 0, RGB2x_9_15_L , RGB2x_9_16_L , RGB2x_9_32_L }
},{
{ 0, RGB2x_8_15_R , RGB2x_8_16_R , RGB2x_8_32_R },
{ 0, RGB2x_15_15_R, RGB2x_15_16_R, RGB2x_15_32_R},
{ 0, RGB2x_16_15_R, RGB2x_16_16_R, RGB2x_16_32_R},
{ 0, RGB2x_32_15_R, RGB2x_32_16_R, RGB2x_32_32_R},
{ 0, RGB2x_9_15_R , RGB2x_9_16_R , RGB2x_9_32_R }
}};
ScalerSimpleBlock_t ScaleRGB3x = {
"RGB3x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
3,3,
0, RGB3x_8_15_L, RGB3x_8_16_L, RGB3x_8_32_L,
0, RGB3x_15_15_L, RGB3x_15_16_L, RGB3x_15_32_L,
0, RGB3x_16_15_L, RGB3x_16_16_L, RGB3x_16_32_L,
0, RGB3x_32_15_L, RGB3x_32_16_L, RGB3x_32_32_L,
0, RGB3x_9_15_L, RGB3x_9_16_L, RGB3x_9_32_L,
0, RGB3x_8_15_R, RGB3x_8_16_R, RGB3x_8_32_R,
0, RGB3x_15_15_R, RGB3x_15_16_R, RGB3x_15_32_R,
0, RGB3x_16_15_R, RGB3x_16_16_R, RGB3x_16_32_R,
0, RGB3x_32_15_R, RGB3x_32_16_R, RGB3x_32_32_R,
0, RGB3x_9_15_R, RGB3x_9_16_R, RGB3x_9_32_R,
};
3,3,{
{ 0, RGB3x_8_15_L , RGB3x_8_16_L , RGB3x_8_32_L },
{ 0, RGB3x_15_15_L, RGB3x_15_16_L, RGB3x_15_32_L},
{ 0, RGB3x_16_15_L, RGB3x_16_16_L, RGB3x_16_32_L},
{ 0, RGB3x_32_15_L, RGB3x_32_16_L, RGB3x_32_32_L},
{ 0, RGB3x_9_15_L , RGB3x_9_16_L , RGB3x_9_32_L }
},{
{ 0, RGB3x_8_15_R , RGB3x_8_16_R , RGB3x_8_32_R },
{ 0, RGB3x_15_15_R, RGB3x_15_16_R, RGB3x_15_32_R},
{ 0, RGB3x_16_15_R, RGB3x_16_16_R, RGB3x_16_32_R},
{ 0, RGB3x_32_15_R, RGB3x_32_16_R, RGB3x_32_32_R},
{ 0, RGB3x_9_15_R , RGB3x_9_16_R , RGB3x_9_32_R }
}};
#endif
/* Complex scalers */
#if RENDER_USE_ADVANCED_SCALERS>2
ScalerComplexBlock_t ScaleAdvMame2x ={
"AdvMame2x",
GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32,
2,2,
AdvMame2x_8_L,AdvMame2x_16_L,AdvMame2x_16_L,AdvMame2x_32_L,
AdvMame2x_8_R,AdvMame2x_16_R,AdvMame2x_16_R,AdvMame2x_32_R
{ AdvMame2x_8_L,AdvMame2x_16_L,AdvMame2x_16_L,AdvMame2x_32_L},
{ AdvMame2x_8_R,AdvMame2x_16_R,AdvMame2x_16_R,AdvMame2x_32_R}
};
ScalerComplexBlock_t ScaleAdvMame3x = {
"AdvMame3x",
GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32,
3,3,
AdvMame3x_8_L,AdvMame3x_16_L,AdvMame3x_16_L,AdvMame3x_32_L,
AdvMame3x_8_R,AdvMame3x_16_R,AdvMame3x_16_R,AdvMame3x_32_R
{ AdvMame3x_8_L,AdvMame3x_16_L,AdvMame3x_16_L,AdvMame3x_32_L},
{ AdvMame3x_8_R,AdvMame3x_16_R,AdvMame3x_16_R,AdvMame3x_32_R}
};
/* These need specific 15bpp versions */
@ -367,56 +385,56 @@ ScalerComplexBlock_t ScaleHQ2x ={
"HQ2x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
2,2,
0,HQ2x_16_L,HQ2x_16_L,HQ2x_32_L,
0,HQ2x_16_R,HQ2x_16_R,HQ2x_32_R
{ 0,HQ2x_16_L,HQ2x_16_L,HQ2x_32_L},
{ 0,HQ2x_16_R,HQ2x_16_R,HQ2x_32_R}
};
ScalerComplexBlock_t ScaleHQ3x ={
"HQ3x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
3,3,
0,HQ3x_16_L,HQ3x_16_L,HQ3x_32_L,
0,HQ3x_16_R,HQ3x_16_R,HQ3x_32_R
{ 0,HQ3x_16_L,HQ3x_16_L,HQ3x_32_L},
{ 0,HQ3x_16_R,HQ3x_16_R,HQ3x_32_R}
};
ScalerComplexBlock_t ScaleSuper2xSaI ={
"Super2xSaI",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
2,2,
0,Super2xSaI_16_L,Super2xSaI_16_L,Super2xSaI_32_L,
0,Super2xSaI_16_R,Super2xSaI_16_R,Super2xSaI_32_R
{ 0,Super2xSaI_16_L,Super2xSaI_16_L,Super2xSaI_32_L},
{ 0,Super2xSaI_16_R,Super2xSaI_16_R,Super2xSaI_32_R}
};
ScalerComplexBlock_t Scale2xSaI ={
"2xSaI",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
2,2,
0,_2xSaI_16_L,_2xSaI_16_L,_2xSaI_32_L,
0,_2xSaI_16_R,_2xSaI_16_R,_2xSaI_32_R
{ 0,_2xSaI_16_L,_2xSaI_16_L,_2xSaI_32_L},
{ 0,_2xSaI_16_R,_2xSaI_16_R,_2xSaI_32_R}
};
ScalerComplexBlock_t ScaleSuperEagle ={
"SuperEagle",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
2,2,
0,SuperEagle_16_L,SuperEagle_16_L,SuperEagle_32_L,
0,SuperEagle_16_R,SuperEagle_16_R,SuperEagle_32_R
{ 0,SuperEagle_16_L,SuperEagle_16_L,SuperEagle_32_L},
{ 0,SuperEagle_16_R,SuperEagle_16_R,SuperEagle_32_R}
};
ScalerComplexBlock_t ScaleAdvInterp2x = {
"AdvInterp2x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
2,2,
0,AdvInterp2x_15_L,AdvInterp2x_16_L,AdvInterp2x_32_L,
0,AdvInterp2x_15_R,AdvInterp2x_16_R,AdvInterp2x_32_R
{ 0,AdvInterp2x_15_L,AdvInterp2x_16_L,AdvInterp2x_32_L},
{ 0,AdvInterp2x_15_R,AdvInterp2x_16_R,AdvInterp2x_32_R}
};
ScalerComplexBlock_t ScaleAdvInterp3x = {
"AdvInterp3x",
GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY,
3,3,
0,AdvInterp3x_15_L,AdvInterp3x_16_L,AdvInterp3x_32_L,
0,AdvInterp3x_15_R,AdvInterp3x_16_R,AdvInterp3x_32_R
{ 0,AdvInterp3x_15_L,AdvInterp3x_16_L,AdvInterp3x_32_L},
{ 0,AdvInterp3x_15_R,AdvInterp3x_16_R,AdvInterp3x_32_R}
};
#endif

View File

@ -21,12 +21,20 @@
//#include "render.h"
#include "video.h"
#if RENDER_USE_ADVANCED_SCALERS>0
#define SCALER_MAXWIDTH 1280
#define SCALER_MAXHEIGHT 1024
#else
// reduced to save some memory
#define SCALER_MAXWIDTH 800
#define SCALER_MAXHEIGHT 600
#endif
#define SCALER_MAXWIDTH 1024
#define SCALER_MAXHEIGHT 768
#if RENDER_USE_ADVANCED_SCALERS>1
#define SCALER_COMPLEXWIDTH 800
#define SCALER_COMPLEXHEIGHT 600
#endif
#define SCALER_COMPLEXWIDTH 512
#define SCALER_COMPLEXHEIGHT 400
#define SCALER_BLOCKSIZE 16
typedef enum {
@ -35,16 +43,20 @@ typedef enum {
typedef enum scalerOperation {
scalerOpNormal,
#if RENDER_USE_ADVANCED_SCALERS>2
scalerOpAdvMame,
scalerOpAdvInterp,
scalerOpHQ,
scalerOpSaI,
scalerOpSuperSaI,
scalerOpSuperEagle,
#endif
#if RENDER_USE_ADVANCED_SCALERS>0
scalerOpTV,
scalerOpRGB,
scalerOpScan,
scalerLast,
#endif
scalerLast
} scalerOperation_t;
typedef void (*ScalerLineHandler_t)(const void *src);
@ -54,6 +66,7 @@ extern Bit8u Scaler_Aspect[];
extern Bit8u diff_table[];
extern Bitu Scaler_ChangedLineIndex;
extern Bit16u Scaler_ChangedLines[];
#if RENDER_USE_ADVANCED_SCALERS>1
/* Not entirely happy about those +2's since they make a non power of 2, with muls instead of shift */
typedef Bit8u scalerChangeCache_t [SCALER_COMPLEXHEIGHT][SCALER_COMPLEXWIDTH / SCALER_BLOCKSIZE] ;
typedef union {
@ -61,17 +74,20 @@ typedef union {
Bit16u b16 [SCALER_COMPLEXHEIGHT] [SCALER_COMPLEXWIDTH];
Bit8u b8 [SCALER_COMPLEXHEIGHT] [SCALER_COMPLEXWIDTH];
} scalerFrameCache_t;
#endif
typedef union {
Bit32u b32 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH];
Bit16u b16 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH];
Bit8u b8 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH];
} scalerSourceCache_t;
extern scalerSourceCache_t scalerSourceCache;
#if RENDER_USE_ADVANCED_SCALERS>1
extern scalerChangeCache_t scalerChangeCache;
#endif
typedef ScalerLineHandler_t ScalerLineBlock_t[5][4];
typedef struct {
char *name;
const char *name;
Bitu gfxFlags;
Bitu xscale,yscale;
ScalerComplexHandler_t Linear[4];
@ -79,7 +95,7 @@ typedef struct {
} ScalerComplexBlock_t;
typedef struct {
char *name;
const char *name;
Bitu gfxFlags;
Bitu xscale,yscale;
ScalerLineBlock_t Linear;
@ -97,13 +113,16 @@ extern ScalerSimpleBlock_t ScaleNormalDw;
extern ScalerSimpleBlock_t ScaleNormalDh;
extern ScalerSimpleBlock_t ScaleNormal2x;
extern ScalerSimpleBlock_t ScaleNormal3x;
#if RENDER_USE_ADVANCED_SCALERS>0
extern ScalerSimpleBlock_t ScaleTV2x;
extern ScalerSimpleBlock_t ScaleTV3x;
extern ScalerSimpleBlock_t ScaleRGB2x;
extern ScalerSimpleBlock_t ScaleRGB3x;
extern ScalerSimpleBlock_t ScaleScan2x;
extern ScalerSimpleBlock_t ScaleScan3x;
#endif
/* Complex scalers */
#if RENDER_USE_ADVANCED_SCALERS>2
extern ScalerComplexBlock_t ScaleHQ2x;
extern ScalerComplexBlock_t ScaleHQ3x;
extern ScalerComplexBlock_t Scale2xSaI;
@ -113,5 +132,8 @@ extern ScalerComplexBlock_t ScaleAdvMame2x;
extern ScalerComplexBlock_t ScaleAdvMame3x;
extern ScalerComplexBlock_t ScaleAdvInterp2x;
extern ScalerComplexBlock_t ScaleAdvInterp3x;
#endif
#if RENDER_USE_ADVANCED_SCALERS>1
extern ScalerLineBlock_t ScalerCache;
#endif
#endif

View File

@ -152,6 +152,7 @@
#define D6 fc[+2 + 2*SCALER_COMPLEXWIDTH]
#if RENDER_USE_ADVANCED_SCALERS>1
static void conc3d(Cache,SBPP,DBPP) (const void * s) {
#ifdef RENDER_NULL_INPUT
if (!s) {
@ -208,6 +209,7 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) {
render.scale.inLine++;
render.scale.complexHandler();
}
#endif
/* Simple scalers */
@ -281,6 +283,8 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) {
#if (DBPP > 8)
#if RENDER_USE_ADVANCED_SCALERS>0
#define SCALERNAME TV2x
#define SCALERWIDTH 2
#define SCALERHEIGHT 2
@ -390,9 +394,14 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) {
#undef SCALERHEIGHT
#undef SCALERFUNC
#endif //#if RENDER_USE_ADVANCED_SCALERS>0
#endif //#if (DBPP > 8)
/* Complex scalers */
#if RENDER_USE_ADVANCED_SCALERS>2
#if (SBPP == DBPP)
@ -549,6 +558,8 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) {
#endif // (SBPP == DBPP) && !defined (CACHEWITHPAL)
#endif // #if RENDER_USE_ADVANCED_SCALERS>2
#undef PSIZE
#undef PTYPE
#undef PMAKE

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: sdl_mapper.cpp,v 1.33 2007/02/22 15:12:48 c2woody Exp $ */
/* $Id: sdl_mapper.cpp,v 1.39 2007/07/17 13:50:27 c2woody Exp $ */
#include <vector>
#include <list>
@ -42,6 +42,8 @@ enum {
CLR_BLACK=0,
CLR_WHITE=1,
CLR_RED=2,
CLR_BLUE=3,
CLR_GREEN=4
};
enum BB_Types {
@ -64,6 +66,8 @@ enum BC_Types {
#define MAXSTICKS 8
#define MAXACTIVE 16
#define MAXBUTTON 32
#define MAXBUTTON_CAP 16
class CEvent;
class CHandlerEvent;
@ -600,23 +604,25 @@ public:
if (_dummy) {
sdl_joystick=NULL;
axes=0; buttons=0; hats=0;
button_wrap=16;
button_wrap=0;
button_cap=0; axes_cap=0; hats_cap=0;
return;
}
// initialize emulated joystick state
emulated_axes=2;
emulated_buttons=2;
emulated_hats=0;
pos_axis_lists=new CBindList[4];
neg_axis_lists=new CBindList[4];
button_lists=new CBindList[16];
button_lists=new CBindList[MAXBUTTON];
hat_lists=new CBindList[4];
Bitu i;
for (i=0; i<16; i++) {
for (i=0; i<MAXBUTTON; i++) {
button_autofire[i]=0;
old_button_state[i]=0;
old_hat_state[i]=0;
}
for(i=0;i<16;i++) old_hat_state[i]=0;
for (i=0; i<4; i++) {
old_pos_axis_state[i]=false;
old_neg_axis_state[i]=false;
@ -630,15 +636,25 @@ public:
sdl_joystick=SDL_JoystickOpen(_stick);
if (sdl_joystick==NULL) {
axes=0; buttons=0; hats=0;
button_wrap=0;
button_cap=0; axes_cap=0; hats_cap=0;
return;
}
axes=SDL_JoystickNumAxes(sdl_joystick);
buttons=SDL_JoystickNumButtons(sdl_joystick);
hats=SDL_JoystickNumHats(sdl_joystick);
button_wrap=buttons;
if (button_wrapping_enabled) button_wrap=emulated_buttons;
if (button_wrap>16) button_wrap=16;
LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(stick),axes,buttons);
button_cap=buttons;
if (button_wrapping_enabled) {
button_wrap=emulated_buttons;
if (buttons>MAXBUTTON_CAP) button_cap = MAXBUTTON_CAP;
}
if (button_wrap > MAXBUTTON) button_wrap = MAXBUTTON;
axes_cap=emulated_axes;
if (axes_cap>axes) axes_cap=axes;
hats_cap=emulated_hats;
if (hats_cap>hats) hats_cap=hats;
LOG_MSG("Using joystick %s with %d axes, %d buttons and %d hat(s)",SDL_JoystickName(stick),axes,buttons,hats);
}
~CStickBindGroup() {
SDL_JoystickClose(sdl_joystick);
@ -723,9 +739,9 @@ public:
/* query SDL joystick and activate bindings */
ActivateJoystickBoundEvents();
bool button_pressed[16];
bool button_pressed[MAXBUTTON];
Bitu i;
for (i=0; i<16; i++) button_pressed[i]=false;
for (i=0; i<MAXBUTTON; i++) button_pressed[i]=false;
for (i=0; i<MAX_VJOY_BUTTONS; i++) {
if (virtual_joysticks[emustick].button_pressed[i])
button_pressed[i % button_wrap]=true;
@ -746,10 +762,10 @@ public:
Bitu i;
bool button_pressed[16];
for (i=0; i<16; i++) button_pressed[i]=false;
bool button_pressed[MAXBUTTON];
for (i=0; i<MAXBUTTON; i++) button_pressed[i]=false;
/* read button states */
for (i=0; i<buttons; i++) {
for (i=0; i<button_cap; i++) {
if (SDL_JoystickGetButton(sdl_joystick,i))
button_pressed[i % button_wrap]=true;
}
@ -762,18 +778,39 @@ public:
}
}
for (i=0; i<emulated_axes; i++) {
for (i=0; i<axes_cap; i++) {
Sint16 caxis_pos=SDL_JoystickGetAxis(sdl_joystick,i);
/* activate bindings for joystick position */
if (caxis_pos>0) ActivateBindList(&pos_axis_lists[i],caxis_pos,false);
else if (caxis_pos<0) {
if (caxis_pos>1) {
if (old_neg_axis_state[i]) {
DeactivateBindList(&neg_axis_lists[i],false);
old_neg_axis_state[i] = false;
}
ActivateBindList(&pos_axis_lists[i],caxis_pos,false);
old_pos_axis_state[i] = true;
} else if (caxis_pos<-1) {
if (old_pos_axis_state[i]) {
DeactivateBindList(&pos_axis_lists[i],false);
old_pos_axis_state[i] = false;
}
if (caxis_pos!=-32768) caxis_pos=(Sint16)abs(caxis_pos);
else caxis_pos=32767;
ActivateBindList(&neg_axis_lists[i],caxis_pos,false);
old_neg_axis_state[i] = true;
} else {
/* center */
if (old_pos_axis_state[i]) {
DeactivateBindList(&pos_axis_lists[i],false);
old_pos_axis_state[i] = false;
}
if (old_neg_axis_state[i]) {
DeactivateBindList(&neg_axis_lists[i],false);
old_neg_axis_state[i] = false;
}
}
}
for (i=0; i<hats; i++) {
for (i=0; i<hats_cap; i++) {
Uint8 chat_state=SDL_JoystickGetHat(sdl_joystick,i);
/* activate binding if hat state has changed */
@ -832,11 +869,12 @@ protected:
CBindList * neg_axis_lists;
CBindList * button_lists;
CBindList * hat_lists;
Bitu stick,emustick,axes,buttons,hats,emulated_axes,emulated_buttons,button_wrap;
Bitu stick,emustick,axes,buttons,hats,emulated_axes,emulated_buttons,emulated_hats;
Bitu button_wrap,button_cap,axes_cap,hats_cap;
SDL_Joystick * sdl_joystick;
char configname[10];
Bitu button_autofire[16];
bool old_button_state[16];
Bitu button_autofire[MAXBUTTON];
bool old_button_state[MAXBUTTON];
bool old_pos_axis_state[16];
bool old_neg_axis_state[16];
Uint8 old_hat_state[16];
@ -849,6 +887,12 @@ public:
emulated_axes=4;
emulated_buttons=4;
if (button_wrapping_enabled) button_wrap=emulated_buttons;
axes_cap=emulated_axes;
if (axes_cap>axes) axes_cap=axes;
hats_cap=emulated_hats;
if (hats_cap>hats) hats_cap=hats;
JOYSTICK_Enable(1,true);
}
@ -885,9 +929,9 @@ public:
/* query SDL joystick and activate bindings */
ActivateJoystickBoundEvents();
bool button_pressed[16];
bool button_pressed[MAXBUTTON];
Bitu i;
for (i=0; i<16; i++) button_pressed[i]=false;
for (i=0; i<MAXBUTTON; i++) button_pressed[i]=false;
for (i=0; i<MAX_VJOY_BUTTONS; i++) {
if (virtual_joysticks[0].button_pressed[i])
button_pressed[i % button_wrap]=true;
@ -913,7 +957,14 @@ public:
emulated_axes=4;
emulated_buttons=4;
old_hat_position=0;
emulated_hats=1;
if (button_wrapping_enabled) button_wrap=emulated_buttons;
axes_cap=emulated_axes;
if (axes_cap>axes) axes_cap=axes;
hats_cap=emulated_hats;
if (hats_cap>hats) hats_cap=hats;
JOYSTICK_Enable(1,true);
JOYSTICK_Move_Y(1,1.0);
}
@ -958,9 +1009,9 @@ public:
/* query SDL joystick and activate bindings */
ActivateJoystickBoundEvents();
bool button_pressed[16];
bool button_pressed[MAXBUTTON];
Bitu i;
for (i=0; i<16; i++) button_pressed[i]=false;
for (i=0; i<MAXBUTTON; i++) button_pressed[i]=false;
for (i=0; i<MAX_VJOY_BUTTONS; i++) {
if (virtual_joysticks[0].button_pressed[i])
button_pressed[i % button_wrap]=true;
@ -1042,7 +1093,14 @@ public:
CCHBindGroup(Bitu _stick) : CStickBindGroup (_stick){
emulated_axes=4;
emulated_buttons=6;
emulated_hats=1;
if (button_wrapping_enabled) button_wrap=emulated_buttons;
axes_cap=emulated_axes;
if (axes_cap>axes) axes_cap=axes;
hats_cap=emulated_hats;
if (hats_cap>hats) hats_cap=hats;
JOYSTICK_Enable(1,true);
button_state=0;
}
@ -1137,8 +1195,8 @@ public:
if (bt_state>hat_priority[i][3]) bt_state=hat_priority[i][3];
}
bool button_pressed[6];
for (i=0; i<6; i++) button_pressed[i]=false;
bool button_pressed[MAXBUTTON];
for (i=0; i<MAXBUTTON; i++) button_pressed[i]=false;
for (i=0; i<MAX_VJOY_BUTTONS; i++) {
if (virtual_joysticks[0].button_pressed[i])
button_pressed[i % button_wrap]=true;
@ -1264,6 +1322,9 @@ protected:
const char * text;
};
class CEventButton;
static CEventButton * last_clicked = NULL;
class CEventButton : public CTextButton {
public:
CEventButton(Bitu _x,Bitu _y,Bitu _dx,Bitu _dy,const char * _text,CEvent * _event)
@ -1271,7 +1332,10 @@ public:
event=_event;
}
void Click(void) {
if (last_clicked) last_clicked->SetColor(CLR_WHITE);
this->SetColor(CLR_GREEN);
SetActiveEvent(event);
last_clicked=this;
}
protected:
CEvent * event;
@ -1300,6 +1364,8 @@ void CCaptionButton::Change(const char * format,...) {
mapper.redraw=true;
}
static void change_action_text(const char* text,Bit8u col);
static void MAPPER_SaveBinds(void);
class CBindButton : public CTextButton {
public:
@ -1312,6 +1378,7 @@ public:
case BB_Add:
mapper.addbind=true;
SetActiveBind(0);
change_action_text("Press a key/joystick button or move the joystick.",CLR_RED);
break;
case BB_Del:
if (mapper.abindit!=mapper.aevent->bindlist.end()) {
@ -1546,6 +1613,13 @@ static struct {
CCheckButton * mod1,* mod2,* mod3,* hold;
} bind_but;
static void change_action_text(const char* text,Bit8u col) {
bind_but.action->Change(text);
bind_but.action->SetColor(col);
}
static void SetActiveBind(CBind * _bind) {
mapper.abind=_bind;
if (_bind) {
@ -1575,10 +1649,11 @@ static void SetActiveEvent(CEvent * event) {
mapper.addbind=false;
bind_but.event_title->Change("EVENT:%s",event ? event->GetName(): "none");
if (!event) {
bind_but.action->Change("Select an event to change");
change_action_text("Select an event to change.",CLR_WHITE);
bind_but.add->Enable(false);
SetActiveBind(0);
} else {
change_action_text("Select a different event or hit the Add/Del/Next buttons.",CLR_WHITE);
mapper.abindit=event->bindlist.begin();
if (mapper.abindit!=event->bindlist.end()) {
SetActiveBind(*(mapper.abindit));
@ -1835,7 +1910,7 @@ static void CreateLayout(void) {
new CTextButton(PX(6),00,124,20,"Keyboard Layout");
new CTextButton(PX(17),00,124,20,"Joystick Layout");
bind_but.action=new CCaptionButton(200,330,0,0);
bind_but.action=new CCaptionButton(185,330,0,0);
bind_but.event_title=new CCaptionButton(0,350,0,0);
bind_but.bind_title=new CCaptionButton(00,365,0,0);
@ -1858,10 +1933,12 @@ static void CreateLayout(void) {
bind_but.bind_title->Change("Bind Title");
}
static SDL_Color map_pal[4]={
static SDL_Color map_pal[5]={
{0x00,0x00,0x00,0x00}, //0=black
{0xff,0xff,0xff,0x00}, //1=white
{0xff,0x00,0x00,0x00}, //2=red
{0x10,0x30,0xff,0x00}, //3=blue
{0x00,0xff,0x20,0x00} //4=green
};
static void CreateStringBind(char * line) {
@ -2066,13 +2143,23 @@ void BIND_MappingEvents(void) {
}
}
static void CreateBindGroups(void) {
bindgroups.clear();
new CKeyBindGroup(SDLK_LAST);
static void InitializeJoysticks(void) {
mapper.sticks.num=0;
mapper.sticks.num_groups=0;
if (joytype != JOY_NONE) {
mapper.sticks.num=SDL_NumJoysticks();
if (joytype==JOY_AUTO) {
if (mapper.sticks.num>1) joytype=JOY_2AXIS;
else if (mapper.sticks.num) joytype=JOY_4AXIS;
else joytype=JOY_NONE;
}
}
}
static void CreateBindGroups(void) {
bindgroups.clear();
new CKeyBindGroup(SDLK_LAST);
if (joytype != JOY_NONE) {
#if defined (REDUCE_JOYSTICK_POLLING)
// direct access to the SDL joystick, thus removed from the event handling
if (mapper.sticks.num) SDL_JoystickEventState(SDL_DISABLE);
@ -2082,31 +2169,29 @@ static void CreateBindGroups(void) {
else return;
#endif
Bit8u joyno=0;
if (joytype==JOY_AUTO) {
if (mapper.sticks.num>1) joytype=JOY_2AXIS;
else if (mapper.sticks.num) joytype=JOY_4AXIS;
else joytype=JOY_NONE;
}
switch (joytype) {
case JOY_NONE:
break;
case JOY_4AXIS:
mapper.sticks.stick[mapper.sticks.num_groups++]=new C4AxisBindGroup(joyno);
new CStickBindGroup(joyno+1U);
new CStickBindGroup(joyno+1U,true);
break;
case JOY_FCS:
mapper.sticks.stick[mapper.sticks.num_groups++]=new CFCSBindGroup(joyno);
new CStickBindGroup(joyno+1U);
new CStickBindGroup(joyno+1U,true);
break;
case JOY_CH:
mapper.sticks.stick[mapper.sticks.num_groups++]=new CCHBindGroup(joyno);
new CStickBindGroup(joyno+1U);
new CStickBindGroup(joyno+1U,true);
break;
case JOY_2AXIS:
default:
mapper.sticks.stick[mapper.sticks.num_groups++]=new CStickBindGroup(joyno);
if((joyno+1U) < mapper.sticks.num)
if((joyno+1U) < mapper.sticks.num) {
mapper.sticks.stick[mapper.sticks.num_groups++]=new CStickBindGroup(joyno+1U);
} else {
new CStickBindGroup(joyno+1U,true);
}
break;
}
}
@ -2146,7 +2231,8 @@ void MAPPER_Run(bool pressed) {
if (mapper.surface == NULL) E_Exit("Could not initialize video mode for mapper: %s",SDL_GetError());
/* Set some palette entries */
SDL_SetPalette(mapper.surface, SDL_LOGPAL|SDL_PHYSPAL, map_pal, 0, 4);
SDL_SetPalette(mapper.surface, SDL_LOGPAL|SDL_PHYSPAL, map_pal, 0, 5);
last_clicked=NULL;
/* Go in the event loop */
mapper.exit=false;
mapper.redraw=true;
@ -2170,6 +2256,7 @@ void MAPPER_Run(bool pressed) {
}
void MAPPER_Init(void) {
InitializeJoysticks();
CreateLayout();
CreateBindGroups();
if (!MAPPER_LoadBinds()) CreateDefaultBinds();

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: sdlmain.cpp,v 1.127 2007/01/24 16:29:09 harekiet Exp $ */
/* $Id: sdlmain.cpp,v 1.131 2007/06/12 20:22:08 c2woody Exp $ */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@ -28,6 +28,9 @@
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#ifdef WIN32
#include <signal.h>
#endif
#include "SDL.h"
@ -278,6 +281,7 @@ check_surface:
else if (flags & GFX_LOVE_15) testbpp=15;
else if (flags & GFX_LOVE_16) testbpp=16;
else if (flags & GFX_LOVE_32) testbpp=32;
else testbpp=0;
check_gotbpp:
if (sdl.desktop.fullscreen) gotbpp=SDL_VideoModeOK(640,480,testbpp,SDL_FULLSCREEN|SDL_HWSURFACE|SDL_HWPALETTE);
else gotbpp=sdl.desktop.bpp;
@ -395,7 +399,7 @@ Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,G
sdl.draw.scalex=scalex;
sdl.draw.scaley=scaley;
Bitu bpp;
Bitu bpp=0;
Bitu retFlags = 0;
if (sdl.blit.surface) {
@ -433,11 +437,17 @@ dosurface:
sdl.surface=SDL_SetVideoMode(width,height,bpp,(flags & GFX_CAN_RANDOM) ? SDL_SWSURFACE : SDL_HWSURFACE);
#ifdef WIN32
if (sdl.surface == NULL) {
LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with windib enabled.");
SDL_QuitSubSystem(SDL_INIT_VIDEO);
putenv("SDL_VIDEODRIVER=windib");
if (!sdl.using_windib) {
LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with windib enabled.");
putenv("SDL_VIDEODRIVER=windib");
sdl.using_windib=true;
} else {
LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with directx enabled.");
putenv("SDL_VIDEODRIVER=directx");
sdl.using_windib=false;
}
SDL_InitSubSystem(SDL_INIT_VIDEO);
sdl.using_windib=true;
sdl.surface = SDL_SetVideoMode(width,height,bpp,SDL_HWSURFACE);
}
#endif
@ -490,6 +500,10 @@ dosurface:
sdl.surface->format->Bmask,
0);
if (!sdl.blit.surface || (!sdl.blit.surface->flags&SDL_HWSURFACE)) {
if (sdl.blit.surface) {
SDL_FreeSurface(sdl.blit.surface);
sdl.blit.surface=0;
}
LOG_MSG("Failed to create ddraw surface, back to normal surface.");
goto dosurface;
}
@ -1133,7 +1147,11 @@ void Mouse_AutoLock(bool enable) {
static void HandleMouseMotion(SDL_MouseMotionEvent * motion) {
if (sdl.mouse.locked || !sdl.mouse.autoenable)
Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100,(float)motion->yrel*sdl.mouse.sensitivity/100,(float)(motion->x-sdl.clip.x)/(sdl.clip.w-1)*sdl.mouse.sensitivity/100,(float)(motion->y-sdl.clip.y)/(sdl.clip.h-1)*sdl.mouse.sensitivity/100.0,sdl.mouse.locked);
Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100.0f,
(float)motion->yrel*sdl.mouse.sensitivity/100.0f,
(float)(motion->x-sdl.clip.x)/(sdl.clip.w-1)*sdl.mouse.sensitivity/100.0f,
(float)(motion->y-sdl.clip.y)/(sdl.clip.h-1)*sdl.mouse.sensitivity/100.0f,
sdl.mouse.locked);
}
static void HandleMouseButton(SDL_MouseButtonEvent * button) {
@ -1183,7 +1201,7 @@ void GFX_Events() {
SDL_Event event;
#if defined (REDUCE_JOYSTICK_POLLING)
static int poll_delay=0;
int time=SDL_GetTicks();
int time=GetTicks();
if (time-poll_delay>20) {
poll_delay=time;
if (sdl.num_joysticks>0) SDL_JoystickUpdate();
@ -1293,6 +1311,23 @@ void GFX_Events() {
}
}
#if defined (WIN32)
static BOOL WINAPI ConsoleEventHandler(DWORD event) {
switch (event) {
case CTRL_SHUTDOWN_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_BREAK_EVENT:
raise(SIGTERM);
return TRUE;
case CTRL_C_EVENT:
default: //pass to the next handler
return FALSE;
}
}
#endif
/* static variable to show wether there is not a valid stdout.
* Fixes some bugs when -noconsole is used in a read only directory */
static bool no_stdout = false;
@ -1345,6 +1380,10 @@ int main(int argc, char* argv[]) {
DEBUG_SetupConsole();
#endif
#if defined(WIN32)
SetConsoleCtrlHandler((PHANDLER_ROUTINE) ConsoleEventHandler,TRUE);
#endif
#ifdef OS2
PPIB pib;
PTIB tib;
@ -1373,12 +1412,16 @@ int main(int argc, char* argv[]) {
char sdl_drv_name[128];
if (getenv("SDL_VIDEODRIVER")==NULL) {
if (SDL_VideoDriverName(sdl_drv_name,128)!=NULL) {
sdl.using_windib=false;
if (strcmp(sdl_drv_name,"directx")!=0) {
SDL_QuitSubSystem(SDL_INIT_VIDEO);
putenv("SDL_VIDEODRIVER=directx");
SDL_InitSubSystem(SDL_INIT_VIDEO);
if (SDL_InitSubSystem(SDL_INIT_VIDEO)<0) {
putenv("SDL_VIDEODRIVER=windib");
if (SDL_InitSubSystem(SDL_INIT_VIDEO)<0) E_Exit("Can't init SDL Video %s",SDL_GetError());
sdl.using_windib=true;
}
}
sdl.using_windib=false;
}
} else {
char* sdl_videodrv = getenv("SDL_VIDEODRIVER");

View File

@ -329,51 +329,51 @@ static const int slot_array[32]=
/* key scale level */
/* table is 3dB/octave , DV converts this into 6dB/octave */
/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
#define DV (0.1875/2.0)
#define SC(x) ((UINT32)((x)/(0.1875/2.0)))
static const UINT32 ksl_tab[8*16]=
{
/* OCT 0 */
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
SC(0.000), SC(0.000), SC(0.000), SC(0.000),
SC(0.000), SC(0.000), SC(0.000), SC(0.000),
SC(0.000), SC(0.000), SC(0.000), SC(0.000),
SC(0.000), SC(0.000), SC(0.000), SC(0.000),
/* OCT 1 */
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
SC(0.000), SC(0.000), SC(0.000), SC(0.000),
SC(0.000), SC(0.000), SC(0.000), SC(0.000),
SC(0.000), SC(0.750), SC(1.125), SC(1.500),
SC(1.875), SC(2.250), SC(2.625), SC(3.000),
/* OCT 2 */
0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
SC(0.000), SC(0.000), SC(0.000), SC(0.000),
SC(0.000), SC(1.125), SC(1.875), SC(2.625),
SC(3.000), SC(3.750), SC(4.125), SC(4.500),
SC(4.875), SC(5.250), SC(5.625), SC(6.000),
/* OCT 3 */
0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
SC(0.000), SC(0.000), SC(0.000), SC(1.875),
SC(3.000), SC(4.125), SC(4.875), SC(5.625),
SC(6.000), SC(6.750), SC(7.125), SC(7.500),
SC(7.875), SC(8.250), SC(8.625), SC(9.000),
/* OCT 4 */
0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
10.875/DV,11.250/DV,11.625/DV,12.000/DV,
SC(0.000), SC(0.000), SC(3.000), SC(4.875),
SC(6.000), SC(7.125), SC(7.875), SC(8.625),
SC(9.000), SC(9.750),SC(10.125),SC(10.500),
SC(10.875),SC(11.250),SC(11.625),SC(12.000),
/* OCT 5 */
0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
9.000/DV,10.125/DV,10.875/DV,11.625/DV,
12.000/DV,12.750/DV,13.125/DV,13.500/DV,
13.875/DV,14.250/DV,14.625/DV,15.000/DV,
SC(0.000), SC(3.000), SC(6.000), SC(7.875),
SC(9.000),SC(10.125),SC(10.875),SC(11.625),
SC(12.000),SC(12.750),SC(13.125),SC(13.500),
SC(13.875),SC(14.250),SC(14.625),SC(15.000),
/* OCT 6 */
0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
12.000/DV,13.125/DV,13.875/DV,14.625/DV,
15.000/DV,15.750/DV,16.125/DV,16.500/DV,
16.875/DV,17.250/DV,17.625/DV,18.000/DV,
SC(0.000), SC(6.000), SC(9.000),SC(10.875),
SC(12.000),SC(13.125),SC(13.875),SC(14.625),
SC(15.000),SC(15.750),SC(16.125),SC(16.500),
SC(16.875),SC(17.250),SC(17.625),SC(18.000),
/* OCT 7 */
0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
15.000/DV,16.125/DV,16.875/DV,17.625/DV,
18.000/DV,18.750/DV,19.125/DV,19.500/DV,
19.875/DV,20.250/DV,20.625/DV,21.000/DV
SC(0.000), SC(9.000),SC(12.000),SC(13.875),
SC(15.000),SC(16.125),SC(16.875),SC(17.625),
SC(18.000),SC(18.750),SC(19.125),SC(19.500),
SC(19.875),SC(20.250),SC(20.625),SC(21.000)
};
#undef DV
#undef SC
/* sustain level table (3dB per step) */
/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
@ -493,13 +493,13 @@ O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
/* multiple table */
#define ML 2
#define SC(x) ((UINT32)((x)*2))
static const UINT8 mul_tab[16]= {
/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */
0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
SC(0.50), SC(1.00), SC(2.00), SC(3.00), SC(4.00), SC(5.00), SC(6.00), SC(7.00),
SC(8.00), SC(9.00),SC(10.00),SC(10.00),SC(12.00),SC(12.00),SC(15.00),SC(15.00)
};
#undef ML
#undef SC
/* TL_TAB_LEN is calculated as:
* 12 - sinus amplitude bits (Y axis)
@ -1301,17 +1301,17 @@ static void OPL_initalize(FM_OPL *OPL)
/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
/* One entry from LFO_AM_TABLE lasts for 64 samples */
OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<<LFO_SH) * OPL->freqbase;
OPL->lfo_am_inc = (UINT32)((1.0 / 64.0 ) * (1<<LFO_SH) * OPL->freqbase);
/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<<LFO_SH) * OPL->freqbase;
OPL->lfo_pm_inc = (UINT32)((1.0 / 1024.0) * (1<<LFO_SH) * OPL->freqbase);
/*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/
/* Noise generator: a step takes 1 sample */
OPL->noise_f = (1.0 / 1.0) * (1<<FREQ_SH) * OPL->freqbase;
OPL->noise_f = (UINT32)((1.0 / 1.0) * (1<<FREQ_SH) * OPL->freqbase);
OPL->eg_timer_add = (1<<EG_SH) * OPL->freqbase;
OPL->eg_timer_add = (UINT32)((1<<EG_SH) * OPL->freqbase);
OPL->eg_timer_overflow = ( 1 ) * (1<<EG_SH);
/*logerror("OPLinit eg_timer_add=%8x eg_timer_overflow=%8x\n", OPL->eg_timer_add, OPL->eg_timer_overflow);*/

View File

@ -45,7 +45,7 @@ using namespace std;
#define GUS_BASE myGUS.portbase
#define GUS_RATE myGUS.rate
#define LOG_GUS
#define LOG_GUS 0
Bit8u adlib_commandreg;
static MixerChannel * gus_chan;
@ -58,7 +58,6 @@ static Bit16u vol16bit[4096];
#endif
static Bit32u pantable[16];
static Bitu show_test=0;
class GUSChannels;
static void CheckVoiceIrq(void);
@ -239,26 +238,6 @@ public:
double realadd = (frameadd*(double)myGUS.basefreq/(double)GUS_RATE) * (double)(1 << RAMP_FRACT);
RampAdd = (Bit32u)realadd;
}
void ShowWave(void) {
LOG_GUS("Wave %2d Ctrl %02x Current %d Start %d End %d Add %3.3f ",
channum,
ReadWaveCtrl(),
WaveAddr>>WAVE_FRACT,
WaveStart>>WAVE_FRACT,
WaveEnd>>WAVE_FRACT,
(float)WaveAdd/(float)(1 << WAVE_FRACT)
);
}
void ShowRamp(void) {
LOG_GUS("Ramp %2d Ctrl %02X Current %d Start %d End %d Add %d",
channum,
ReadRampCtrl(),
RampVol >> RAMP_FRACT,
RampStart >> RAMP_FRACT,
RampEnd >> RAMP_FRACT,
RampAdd >> RAMP_FRACT
);
}
INLINE void WaveUpdate(void) {
if (WaveCtrl & 0x3) return;
Bit32s WaveLeft;
@ -334,12 +313,7 @@ public:
bool eightbit;
if (RampCtrl & WaveCtrl & 3) return;
eightbit = ((WaveCtrl & 0x4) == 0);
#if 0
if (!(show_test & 1023)) {
ShowWave();
ShowRamp();
}
#endif
for(i=0;i<(int)len;i++) {
// Get sample
tmpsamp = GetSample(WaveAdd, WaveAddr, eightbit);
@ -463,7 +437,9 @@ static Bit16u ExecuteReadRegister(void) {
CheckVoiceIrq();
return (Bit16u)(tmpreg << 8);
default:
LOG_GUS("Read Register num 0x%x", myGUS.gRegSelect);
#if LOG_GUS
LOG_MSG("Read Register num 0x%x", myGUS.gRegSelect);
#endif
return myGUS.gRegData;
}
}
@ -564,7 +540,9 @@ static void ExecuteGlobRegister(void) {
myGUS.ActiveMask=0xffffffffU >> (32-myGUS.ActiveChannels);
gus_chan->Enable(true);
myGUS.basefreq = (Bit32u)((float)1000000/(1.619695497*(float)(myGUS.ActiveChannels)));
LOG_GUS("GUS set to %d channels", myGUS.ActiveChannels);
#if LOG_GUS
LOG_MSG("GUS set to %d channels", myGUS.ActiveChannels);
#endif
for (i=0;i<myGUS.ActiveChannels;i++) guschan[i]->UpdateWaveRamp();
break;
case 0x10: // Undocumented register used in Fast Tracker 2
@ -607,7 +585,10 @@ static void ExecuteGlobRegister(void) {
GUSReset();
break;
default:
LOG_GUS("Unimplemented global register %x -- %x", myGUS.gRegSelect, myGUS.gRegData);
#if LOG_GUS
LOG_MSG("Unimplemented global register %x -- %x", myGUS.gRegSelect, myGUS.gRegData);
#endif
break;
}
return;
}
@ -645,7 +626,9 @@ static Bitu read_gus(Bitu port,Bitu iolen) {
return 0;
}
default:
LOG_GUS("Read GUS at port 0x%x", port);
#if LOG_GUS
LOG_MSG("Read GUS at port 0x%x", port);
#endif
break;
}
@ -692,11 +675,15 @@ static void write_gus(Bitu port,Bitu val,Bitu iolen) {
if (myGUS.mixControl & 0x40) {
// IRQ configuration, only use low bits for irq 1
if (irqtable[val & 0x7]) myGUS.irq1=irqtable[val & 0x7];
LOG_GUS("Assigned GUS to IRQ %d", myGUS.irq1);
#if LOG_GUS
LOG_MSG("Assigned GUS to IRQ %d", myGUS.irq1);
#endif
} else {
// DMA configuration, only use low bits for dma 1
if (dmatable[val & 0x7]) myGUS.dma1=dmatable[val & 0x7];
LOG_GUS("Assigned GUS to DMA %d", myGUS.dma1);
#if LOG_GUS
LOG_MSG("Assigned GUS to DMA %d", myGUS.dma1);
#endif
}
break;
case 0x302:
@ -721,7 +708,9 @@ static void write_gus(Bitu port,Bitu val,Bitu iolen) {
if(myGUS.gDramAddr < sizeof(GUSRam)) GUSRam[myGUS.gDramAddr] = val;
break;
default:
LOG_GUS("Write GUS at port 0x%x with %x", port, val);
#if LOG_GUS
LOG_MSG("Write GUS at port 0x%x with %x", port, val);
#endif
break;
}
}

View File

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: iohandler.cpp,v 1.26 2007/02/22 08:32:21 qbix79 Exp $ */
/* $Id: iohandler.cpp,v 1.28 2007/06/12 20:22:08 c2woody Exp $ */
#include <string.h>
#include "dosbox.h"
@ -174,7 +174,7 @@ static Bits IOFaultCore(void) {
inline void IO_USEC_read_delay_old() {
if(CPU_CycleMax > static_cast<Bit32s>((IODELAY_READ_MICROS*1000.0))) {
// this could be calculated whenever CPU_CycleMax changes
Bitu delaycyc = static_cast<Bitu>((CPU_CycleMax/1000)*IODELAY_READ_MICROS);
Bits delaycyc = static_cast<Bits>((CPU_CycleMax/1000)*IODELAY_READ_MICROS);
if(CPU_Cycles > delaycyc) CPU_Cycles -= delaycyc;
else CPU_Cycles = 0;
}
@ -183,7 +183,7 @@ inline void IO_USEC_read_delay_old() {
inline void IO_USEC_write_delay_old() {
if(CPU_CycleMax > static_cast<Bit32s>((IODELAY_WRITE_MICROS*1000.0))) {
// this could be calculated whenever CPU_CycleMax changes
Bitu delaycyc = static_cast<Bitu>((CPU_CycleMax/1000)*IODELAY_WRITE_MICROS);
Bits delaycyc = static_cast<Bits>((CPU_CycleMax/1000)*IODELAY_WRITE_MICROS);
if(CPU_Cycles > delaycyc) CPU_Cycles -= delaycyc;
else CPU_Cycles = 0;
}
@ -194,14 +194,14 @@ inline void IO_USEC_write_delay_old() {
#define IODELAY_WRITE_MICROSk (Bit32u)(1024/0.75)
inline void IO_USEC_read_delay() {
Bitu delaycyc = CPU_CycleMax/IODELAY_READ_MICROSk;
Bits delaycyc = CPU_CycleMax/IODELAY_READ_MICROSk;
if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc = 0; //Else port acces will set cycles to 0. which might trigger problem with games which read 16 bit values
CPU_Cycles -= delaycyc;
CPU_IODelayRemoved += delaycyc;
}
inline void IO_USEC_write_delay() {
Bitu delaycyc = CPU_CycleMax/IODELAY_WRITE_MICROSk;
Bits delaycyc = CPU_CycleMax/IODELAY_WRITE_MICROSk;
if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc=0;
CPU_Cycles -= delaycyc;
CPU_IODelayRemoved += delaycyc;
@ -227,7 +227,6 @@ void IO_WriteB(Bitu port,Bitu val) {
RealPt icb = CALLBACK_RealPointer(call_priv_io);
SegSet16(cs,RealSeg(icb));
reg_eip = RealOff(icb)+0x08;
FillFlags();
CPU_Exception(cpu.exception.which,cpu.exception.error);
DOSBOX_RunMachine();
@ -263,7 +262,6 @@ void IO_WriteW(Bitu port,Bitu val) {
RealPt icb = CALLBACK_RealPointer(call_priv_io);
SegSet16(cs,RealSeg(icb));
reg_eip = RealOff(icb)+0x0a;
FillFlags();
CPU_Exception(cpu.exception.which,cpu.exception.error);
DOSBOX_RunMachine();
@ -299,7 +297,6 @@ void IO_WriteD(Bitu port,Bitu val) {
RealPt icb = CALLBACK_RealPointer(call_priv_io);
SegSet16(cs,RealSeg(icb));
reg_eip = RealOff(icb)+0x0c;
FillFlags();
CPU_Exception(cpu.exception.which,cpu.exception.error);
DOSBOX_RunMachine();
@ -330,7 +327,6 @@ Bitu IO_ReadB(Bitu port) {
RealPt icb = CALLBACK_RealPointer(call_priv_io);
SegSet16(cs,RealSeg(icb));
reg_eip = RealOff(icb)+0x00;
FillFlags();
CPU_Exception(cpu.exception.which,cpu.exception.error);
DOSBOX_RunMachine();
@ -366,7 +362,6 @@ Bitu IO_ReadW(Bitu port) {
RealPt icb = CALLBACK_RealPointer(call_priv_io);
SegSet16(cs,RealSeg(icb));
reg_eip = RealOff(icb)+0x02;
FillFlags();
CPU_Exception(cpu.exception.which,cpu.exception.error);
DOSBOX_RunMachine();
@ -402,7 +397,6 @@ Bitu IO_ReadD(Bitu port) {
RealPt icb = CALLBACK_RealPointer(call_priv_io);
SegSet16(cs,RealSeg(icb));
reg_eip = RealOff(icb)+0x04;
FillFlags();
CPU_Exception(cpu.exception.which,cpu.exception.error);
DOSBOX_RunMachine();

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