mirror of
https://github.com/retro100/dosbox-wii.git
synced 2025-02-28 15:53:42 +01:00
DOSBox 0.71
This commit is contained in:
parent
e5731161bb
commit
5d0f3a05e8
13
AUTHORS
13
AUTHORS
@ -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
|
||||
|
56
ChangeLog
56
ChangeLog
@ -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
31
INSTALL
@ -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
|
||||
|
@ -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
56
NEWS
@ -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
217
README
@ -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
9
THANKS
@ -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
21
config.guess
vendored
@ -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
|
||||
|
24
config.h.in
24
config.h.in
@ -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
46
config.sub
vendored
@ -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
493
configure
vendored
@ -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" ;;
|
||||
|
120
configure.in
120
configure.in
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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
48
docs/PORTING
Normal 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
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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@
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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){
|
||||
|
@ -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
323
src/cpu/core_dynrec.cpp
Normal 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
|
2
src/cpu/core_dynrec/Makefile.am
Normal file
2
src/cpu/core_dynrec/Makefile.am
Normal 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
|
332
src/cpu/core_dynrec/Makefile.in
Normal file
332
src/cpu/core_dynrec/Makefile.in
Normal 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
642
src/cpu/core_dynrec/cache.h
Normal 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; */
|
||||
}
|
582
src/cpu/core_dynrec/decoder.h
Normal file
582
src/cpu/core_dynrec/decoder.h
Normal 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;
|
||||
}
|
1103
src/cpu/core_dynrec/decoder_basic.h
Normal file
1103
src/cpu/core_dynrec/decoder_basic.h
Normal file
File diff suppressed because it is too large
Load Diff
1416
src/cpu/core_dynrec/decoder_opcodes.h
Normal file
1416
src/cpu/core_dynrec/decoder_opcodes.h
Normal file
File diff suppressed because it is too large
Load Diff
681
src/cpu/core_dynrec/dyn_fpu.h
Normal file
681
src/cpu/core_dynrec/dyn_fpu.h
Normal 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
|
1995
src/cpu/core_dynrec/operators.h
Normal file
1995
src/cpu/core_dynrec/operators.h
Normal file
File diff suppressed because it is too large
Load Diff
632
src/cpu/core_dynrec/risc_mipsel32.h
Normal file
632
src/cpu/core_dynrec/risc_mipsel32.h
Normal 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
|
598
src/cpu/core_dynrec/risc_x64.h
Normal file
598
src/cpu/core_dynrec/risc_x64.h
Normal 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
|
507
src/cpu/core_dynrec/risc_x86.h
Normal file
507
src/cpu/core_dynrec/risc_x86.h
Normal 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
|
@ -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:
|
||||
|
@ -3,7 +3,6 @@
|
||||
#define GetIP() (inst.cseip-SegBase(cs))
|
||||
|
||||
#define RunException() { \
|
||||
FillFlags(); \
|
||||
CPU_Exception(cpu.exception.which,cpu.exception.error); \
|
||||
continue; \
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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)) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -42,7 +42,6 @@ static INLINE Bit32s Fetchds() {
|
||||
|
||||
|
||||
#define RUNEXCEPTION() { \
|
||||
FillFlags(); \
|
||||
CPU_Exception(cpu.exception.which,cpu.exception.error); \
|
||||
continue; \
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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); \
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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]);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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);*/
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user