diff --git a/ChangeLog b/ChangeLog index 90cdcdb..a01db8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +0.61 + - Added a beta dynamic cpu for x86 hosts (very unstable) + - Added opengl and hardware overlay display output + - Rewrote the vga screen updates to go in lines + - Added paging and v86 support to cpu emulation + - Added a config option to simulate a certain type of machine + - Added hercules graphics emulation + - Made CGA/TANDY modes more compatible + - Updated textmode drawing routines to support blinking colors + - Fixed VESA set page function that was documented wrong + - Fixed some wrongly emulated cpu opcodes. + - improved exception handling + - debugger: fixes; logging of gdt,lgt,idt, new commands(Fizzban) + - fixed some mscdex issues (drive letter header error, added get directory entry) + - added/fixed some bios funcs + - added some rarely used xms functions (thanks c2woody!) + - implemented GUS emulation + - Added 16-bit DMA support (for GUS and eventually SB16) + - Fixed many small bugs in filehandling routines + - Many small FPU fixes (c2woody/Fizzban) + - Some keyboard improvements (pharlab games) + - Some Timer and cmos/rtc fixes (Mirek/Srecko/Others) + - Lot's of mouse fixes (Help from various people) + - Enabled internal modem + - Made the DOS parsing routines a bit more flexible + - Added Subst (Srecko) + - Added cdrom ioctl support for linux (prompt) + - Many internal DOS fixes: memory/files/datastructures. + - Got some help from c2woody in allowing more than 1 irq being served + - Disabled DPMI (not needed anymore. DOSBox handles almost every extender) + - Search configfile in $HOME directory if none present in current directory + - Added another way to switch to protected mode. (Thanks Morten Eriksen!) + - Fixed some odd badly documented behaviour with PSP/DTA + - Added some warnings on opening of readonly files in writemode(DOS default). + - Many shell enhanchements + - Fixed a win32 specific bug dealing with filenames starting with a "." + - Fixed some bugs with the directory structure: not found/can't save errors + 0.60 - rewrote memory system for future paging support - fixed several EMS and XMS bugs and rewrite for new memory system diff --git a/Makefile.am b/Makefile.am index cb2acfb..bfb4714 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Main Makefile for DOSBox EXTRA_DIST = autogen.sh -SUBDIRS = src include visualc docs +SUBDIRS = src include visualc docs visualc_net diff --git a/Makefile.in b/Makefile.in index a72024c..3428331 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -133,7 +133,7 @@ target_os = @target_os@ target_vendor = @target_vendor@ EXTRA_DIST = autogen.sh -SUBDIRS = src include visualc docs +SUBDIRS = src include visualc docs visualc_net subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -461,7 +461,7 @@ install-am: all-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -480,7 +480,6 @@ clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags @@ -505,7 +504,6 @@ installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/NEWS b/NEWS index 7e7c1e5..d3f4b51 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,41 @@ +0.61 + - Added a beta dynamic cpu for x86 hosts (very unstable) + - Added opengl and hardware overlay display output + - Rewrote the vga screen updates to go in lines + - Added paging and v86 support to cpu emulation + - Added a config option to simulate a certain type of machine + - Added hercules graphics emulation + - Made CGA/TANDY modes more compatible + - Updated textmode drawing routines to support blinking colors + - Fixed VESA set page function that was documented wrong + - Fixed some wrongly emulated cpu opcodes. + - improved exception handling + - debugger: fixes; logging of gdt,lgt,idt, new commands(Fizzban) + - fixed some mscdex issues (drive letter header error, added get directory entry) + - added/fixed some bios funcs + - added some rarely used xms functions (thanks c2woody!) + - implemented GUS emulation + - Added 16-bit DMA support (for GUS and eventually SB16) + - Fixed many small bugs in filehandling routines + - Many small FPU fixes (c2woody/Fizzban) + - Some keyboard improvements (pharlab games) + - Some Timer and cmos/rtc fixes (Mirek/Srecko/Others) + - Lot's of mouse fixes (Help from various people) + - Enabled internal modem + - Made the DOS parsing routines a bit more flexible + - Added Subst (Srecko) + - Added cdrom ioctl support for linux (prompt) + - Many internal DOS fixes: memory/files/datastructures. + - Got some help from c2woody in allowing more than 1 irq being served + - Disabled DPMI (not needed anymore. DOSBox handles almost every extender) + - Search configfile in $HOME directory if none present in current directory + - Added another way to switch to protected mode. (Thanks Morten Eriksen!) + - Fixed some odd badly documented behaviour with PSP/DTA + - Added some warnings on opening of readonly files in writemode(DOS default). + - Many shell enhanchements + - Fixed a win32 specific bug dealing with filenames starting with a "." + - Fixed some bugs with the directory structure: not found/can't save errors + 0.60 - rewrote memory system for future paging support - fixed several EMS and XMS bugs and rewrite for new memory system diff --git a/README b/README index 4a7d377..fedaf56 100644 --- a/README +++ b/README @@ -1,25 +1,25 @@ -DOSBox v0.60 +DOSBox v0.61 ===== NOTE: ===== -While we hope that, one day, DosBox will run virtually all programs -ever made for the PC...we are not there yet. At present, DosBox run on a 1.7 -Gigahertz PC is roughly the equivalent of a 25MHz 386 PC. While the 0.60 +While we hope that, one day, DOSBox will run virtually all programs +ever made for the PC...we are not there yet. At present, DOSBox run on a high- +end machine will roughly be the equivalent of a lowend 486 PC. While the 0.60 release has added support for "protected mode" allowing for more complex and recent programs, but note that this support is early in development and nowhere near as complete as the support for 386 real-mode games (or earlier). Also note that "protected mode" games need substantially more resources and may require a much faster processor for you to run it properly -in DosBox. +in DOSBox. ====== Usage: ====== dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] - [-lang languagefile] + [-lang languagefile] [-machine machinetype] [-noconsole] name If "name" is a directory it'll mount that as the C: drive. @@ -45,6 +45,11 @@ dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] -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: + auto,hercules,cga,tandy,vga. + Note: If a name/command/configfile/languagefile contains a space in it, put the whole name/command/configfile/languagefile between quotes("example"). @@ -63,7 +68,7 @@ In Windows you can also drag directories/files onto the dosbox executable. Internal Programs: ================== -dosbox supports most of the DOS commands found in command.com. +DOSBox supports most of the DOS commands found in command.com. In addition, the following commands are available: MOUNT "Emulated Drive letter" "Real Drive or Directory" @@ -111,13 +116,13 @@ MOUNT -cd Note: It's possible to mount a local directory as cdrom drive. Hardware support is then missing. - Basically, MOUNT allows you to connect real hardware to DosBox's "emulated" - PC. So MOUNT C C:\ tells DosBox to use your real C: drive as drive C: in + Basically, MOUNT allows you to connect real hardware to DOSBox's "emulated" + PC. So MOUNT C C:\ tells DOSBox to use your real C: drive as drive C: in DosBox. It also allows you to change the drive's letter identification for programs that demand specific drive letters. For example: Touche: Adventures of The Fifth Musketeer must be run on your C: - drive. Using DosBox and it's mount command, you can trick into thinking it + drive. Using DOSBox and it's mount command, you can trick into thinking it is on C drive while placing it where you want it. For example, if the game were in D:\TOUCHE, you can use the command MOUNT C D:\ would allow you to run Touche from the D drive. @@ -133,7 +138,7 @@ MOUNT -cd mount d /media/cdrom -t cdrom -usecd 0 4. To mount a drive with 870 mb free diskspace (rarely needed! experts only): mount c d:\ -size 4025,127,16513,1700 - 5. to mount /home/dos/dosgames as drive C in dosbox: + 5. To mount /home/dos/dosgames as drive C in DOSBox: mount c /home/dos/dosgames MEM @@ -143,6 +148,11 @@ CONFIG [-writeconf] [-writelang] localfile Write the current configuration or language settings to file. "localfile" is located on the local drive !!! + Example: + To create a configfile in your current directory: + config -writeconf dosbox.conf + + LOADFIX [-size] [program] [program-parameters] LOADFIX -f Program to "eat up" memory. Useful for old programs which don't expect much @@ -247,6 +257,60 @@ Q: The sound stutters. A: You're using too much cpu power to keep dosbox running at the current speed. You can either lower the cycles or skip frames or get a faster machine. +Q: I can't type \ in DOSBox. +A: This is a known problem. It only occurs if your keyboard layout isn't US. + Some possible fixes: + 1. Switch your keyboard layout. + 2. Use / instead. + 3. Add the commands you want to execute in dosbox.conf + +Q: The game/application can't find its CD-ROM. +A: Be sure to mount the CD-ROM with -t cdrom switch. Also try adding the cor- + rect label (-label LABEL). To enable more low-level cdrom support add + the following switch to mount: -usecd #, where # is the number of your + CD-ROM drive reported by mount -cd. If you run Win32 you can specify -ioctl + or -aspi. Look at the description elsewhere in this document for their + meaning. + +Q: The game/application runs much too slow! +A: Look at the section "To run resource-demanding games" for more information. + +Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ. +A: This is possible! Just create a config file: config -writeconf dosbox.conf . + Startup your favourite editor and look at all the settings present. To + start DOSBox with your new settings: dosbox -conf dosbox.conf + +Q: What sound hardware does DosBox presently emulate? +A: DosBox emulates several legacy sound devices: + - Internal PC speaker + This emulation includes both the tone generator and several forms of digital + sound output through the internal speaker. + - Creative CMS/Gameblaster + The is the first card released by Creative Labs(R). The default configuration places + it on port 0x220. It should be noted that enabling this with the Adlib emulation may + result in conflicts. + - Tandy 3 voice + The emulation of this sound hardware is complete with the exception of the noise channel, + which is not very well documented and as such is only a best guess as to the sound's accuracy. + - Adlib + Borrowed from MAME, this emulation is almost perfect and includes the Adlib's ability to almost + play digitized sound. + - SoundBlaster Pro + Coupled with the Adlib, DosBox provides Soundblaster Pro level 8-bit stereo sound. + - Disney Soundsource + Using the printer port, this sound device outputs digital sound only. + - Gravis Ultrasound + The emulation of this hardware is nearly complete, though the MIDI capabilities have been left + out since an MPU-401 has been emulated in other code. + - MPU-401 + A MIDI passthrough interface is also emulated. This method of sound output will only work when + used with a General Midi or MT-32 device. + + +Q: Great README, but I still don't get it. +A: While unlikely this seems to happen. Maybe a look at "The Newbie's + pictorial guide to dosbox" located at + http://vogons.zetafleet.com/viewforum.php?f=39 might help you. For more questions check the site/forum: http://dosbox.sourceforge.net @@ -256,12 +320,21 @@ http://dosbox.sourceforge.net The Config File: ================ -A config file can be generated by CONFIG.COM. Edit it to customize DOSBox. +A config file can be generated by CONFIG.COM, which can be found on the +internal dosbox Z: drive when you start up dosbox. Look in the internal +programs section of the readme for usage of CONFIG.COM. +You can edit the generated configfile to customize DOSBox. The file is divided into several sections (the names have [] around it). Some sections have options which you can set. -# and % indicate commentlines. +# and % indicate comment-lines. The generated configfile contains the current settings. You can alter them and -start dosbox with the -conf switch to load the file and use these settings. +start DOSBox with the -conf switch to load the file and use these settings. + +DOSBox will if no configfile is specified with the -conf switch look in the +current directory for dosbox.conf. Then it will look for ~/.dosboxrc (linux), +~\dosbox.conf (win32) or "~/Library/Preferences/DOSBox Preferences" (MACOSX). + + ================== The Language File: @@ -269,7 +342,7 @@ The Language File: A language file can be generated by CONFIG.COM. Read it and you will hopefully understand how to change it. -Start Dosbox with the -lang switch to use your new language file +Start DOSBox with the -lang switch to use your new language file or you can setup the filename in the config file in the [dosbox] section. There's a language= entry that can be changed with the filename. @@ -289,6 +362,8 @@ Vlad R. of the vdmsound project for excellent sound blaster 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. The Beta Testers. ======== diff --git a/THANKS b/THANKS index 9a46546..7bb1097 100644 --- a/THANKS +++ b/THANKS @@ -8,5 +8,8 @@ Jarek Burczynski for the new OPL 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. + All the people who submitted a bug. The Beta Testers. diff --git a/aclocal.m4 b/aclocal.m4 index 47566a4..5cae2fb 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.7.7 -*- Autoconf -*- +# generated automatically by aclocal 1.7.9 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. @@ -498,7 +498,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.7"]) # Call AM_AUTOMAKE_VERSION so it can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.7.7])]) + [AM_AUTOMAKE_VERSION([1.7.9])]) # Helper functions for option handling. -*- Autoconf -*- diff --git a/autogen.sh b/autogen.sh index 9126bca..5e6dff9 100644 --- a/autogen.sh +++ b/autogen.sh @@ -10,4 +10,5 @@ autoheader automake --gnits --include-deps --add-missing --copy autoconf -echo "Now you are ready to run ./configure, afterwards check config.h for extra build settings" +echo "Now you are ready to run ./configure." +echo "You can also run ./configure --help for extra features to enable/disable." diff --git a/config.h.in b/config.h.in index c616d0d..6d5cbe1 100644 --- a/config.h.in +++ b/config.h.in @@ -26,6 +26,9 @@ /* Define to 1 to enable internal debugger, requires libcurses */ #undef C_DEBUG +/* Define to 1 to use x86 dynamic cpu core */ +#undef C_DYNAMIC_X86 + /* Define to 1 to enable floating point emulation */ #undef C_FPU @@ -35,9 +38,15 @@ /* 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 internal modem support, requires SDL_net */ #undef C_MODEM +/* Define to 1 to use opengl display output support */ +#undef C_OPENGL + /* Define to 1 to enable screenshots, requires libpng */ #undef C_SSHOT @@ -80,6 +89,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Compiling on GNU/Linux */ +#undef LINUX + /* Compiling on Mac OS X */ #undef MACOSX @@ -117,9 +129,11 @@ /* Define to empty if `const' does not conform to ANSI C. */ #undef const -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus #undef inline +#endif /* Define to `unsigned' if does not define. */ #undef size_t diff --git a/config.sub b/config.sub index 79657cd..463186d 100644 --- a/config.sub +++ b/config.sub @@ -3,7 +3,7 @@ # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -timestamp='2003-10-07' +timestamp='2004-01-05' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -118,7 +118,8 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -379,6 +380,9 @@ case $basic_machine in amd64) basic_machine=x86_64-pc ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; amdahl) basic_machine=580-amdahl os=-sysv @@ -743,6 +747,10 @@ case $basic_machine in basic_machine=or32-unknown os=-coff ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose @@ -963,6 +971,10 @@ case $basic_machine in tower | tower-32) basic_machine=m68k-ncr ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; udi29k) basic_machine=a29k-amd os=-udi @@ -1137,13 +1149,13 @@ case $os in | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei*) + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1182,6 +1194,9 @@ case $os in -opened*) os=-openedition ;; + -os400*) + os=-os400 + ;; -wince*) os=-wince ;; @@ -1203,6 +1218,9 @@ case $os in -atheos*) os=-atheos ;; + -syllable*) + os=-syllable + ;; -386bsd) os=-bsd ;; @@ -1225,6 +1243,9 @@ case $os in -sinix*) os=-sysv4 ;; + -tpf*) + os=-tpf + ;; -triton*) os=-sysv3 ;; @@ -1473,9 +1494,15 @@ case $basic_machine in -mvs* | -opened*) vendor=ibm ;; + -os400*) + vendor=ibm + ;; -ptx*) vendor=sequent ;; + -tpf*) + vendor=ibm + ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; diff --git a/configure b/configure index 7311667..ca16902 100644 --- a/configure +++ b/configure @@ -1,9 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.57 for dosbox 0.60. +# Generated by GNU Autoconf 2.59 for dosbox 0.61. # -# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 -# Free Software Foundation, Inc. +# Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## @@ -20,9 +19,10 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi +DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. -if (FOO=FOO; unset FOO) >/dev/null 2>&1; then +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false @@ -41,7 +41,7 @@ for as_var in \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do - if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var @@ -218,16 +218,17 @@ rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else + test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. -as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. -as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS @@ -266,8 +267,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='dosbox' PACKAGE_TARNAME='dosbox' -PACKAGE_VERSION='0.60' -PACKAGE_STRING='dosbox 0.60' +PACKAGE_VERSION='0.61' +PACKAGE_STRING='dosbox 0.61' PACKAGE_BUGREPORT='' ac_unique_file="README" @@ -667,7 +668,7 @@ done # Be sure to have absolute paths. for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir + localstatedir libdir includedir oldincludedir infodir mandir do eval ac_val=$`echo $ac_var` case $ac_val in @@ -707,10 +708,10 @@ if test -z "$srcdir"; then # Try the directory containing this script, then its parent. ac_confdir=`(dirname "$0") 2>/dev/null || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -785,7 +786,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.60 to adapt to many kinds of systems. +\`configure' configures dosbox 0.61 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -810,9 +811,9 @@ _ACEOF cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] + [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] + [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify @@ -852,7 +853,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of dosbox 0.60:";; + short | recursive ) echo "Configuration of dosbox 0.61:";; esac cat <<\_ACEOF @@ -865,7 +866,9 @@ Optional Features: --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-fpu Disable FPU support + --disable-dynamic-x86 Disable x86 dynamic cpu core + --disable-fpu Disable fpu support + --disable-opengl Disable opengl support Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -922,12 +925,45 @@ case $srcdir in ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac -# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be -# absolute. -ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` -ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` -ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` -ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac cd $ac_dir # Check for guested configure; otherwise get Cygnus style configure. @@ -938,7 +974,7 @@ ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` echo $SHELL $ac_srcdir/configure --help=recursive elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then + test -f $ac_srcdir/configure.in; then echo $ac_configure --help else @@ -951,11 +987,10 @@ fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -dosbox configure 0.60 -generated by GNU Autoconf 2.57 +dosbox configure 0.61 +generated by GNU Autoconf 2.59 -Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 -Free Software Foundation, Inc. +Copyright (C) 2003 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -966,8 +1001,8 @@ cat >&5 <<_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.60, which was -generated by GNU Autoconf 2.57. Invocation command line was +It was created by dosbox $as_me 0.61, which was +generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ @@ -1044,19 +1079,19 @@ do 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. + ac_must_keep_next=false # Got value, back to normal. else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac fi ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" # Get rid of the leading space. @@ -1090,12 +1125,12 @@ _ASBOX case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in *ac_space=\ *) sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" ;; *) sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } @@ -1124,7 +1159,7 @@ _ASBOX for ac_var in $ac_subst_files do eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" + echo "$ac_var='"'"'$ac_val'"'"'" done | sort echo fi @@ -1223,7 +1258,7 @@ fi # value. ac_cache_corrupted=false for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val="\$ac_cv_env_${ac_var}_value" @@ -1240,13 +1275,13 @@ echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: + ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. @@ -1425,6 +1460,7 @@ am__api_version="1.7" # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 @@ -1441,6 +1477,7 @@ do case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. @@ -1448,20 +1485,20 @@ case $as_dir/ in # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi done done ;; @@ -1605,7 +1642,7 @@ done echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else @@ -1661,7 +1698,7 @@ fi # Define the identity of the package. PACKAGE='dosbox' - VERSION='0.60' + VERSION='0.61' cat >>confdefs.h <<_ACEOF @@ -1792,7 +1829,7 @@ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else @@ -2155,7 +2192,6 @@ ac_compiler=`set X $ac_compile; echo $2` (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2175,8 +2211,8 @@ ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -echo "$as_me:$LINENO: checking for C compiler default output" >&5 -echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 @@ -2196,23 +2232,23 @@ do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; + ;; conftest.$ac_ext ) - # This is the source file. - ;; + # This is the source file. + ;; [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; + # We found the default executable, but exeext='' is most + # certainly right. + break;; *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext - break;; + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; * ) - break;; + break;; esac done else @@ -2286,8 +2322,8 @@ for ac_file in conftest.exe conftest conftest.*; do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext - break;; + export ac_cv_exeext + break;; * ) break;; esac done @@ -2312,7 +2348,6 @@ if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2363,7 +2398,6 @@ if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2383,11 +2417,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2400,7 +2443,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi @@ -2416,7 +2459,6 @@ if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2433,11 +2475,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2450,7 +2501,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cc_g=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 @@ -2477,7 +2528,6 @@ else ac_cv_prog_cc_stdc=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2505,6 +2555,16 @@ static char *f (char * (*g) (char **, int), char **p, ...) va_end (v); return s; } + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std1 is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std1. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; @@ -2531,11 +2591,20 @@ do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2548,7 +2617,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext +rm -f conftest.err conftest.$ac_objext done rm -f conftest.$ac_ext conftest.$ac_objext CC=$ac_save_CC @@ -2576,11 +2645,20 @@ cat >conftest.$ac_ext <<_ACEOF _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2595,7 +2673,6 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2613,11 +2690,20 @@ exit (42); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2630,9 +2716,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 continue fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2649,11 +2734,20 @@ exit (42); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -2665,7 +2759,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then @@ -2679,7 +2773,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -2881,7 +2975,6 @@ do # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2892,7 +2985,7 @@ cat >>conftest.$ac_ext <<_ACEOF #else # include #endif - Syntax error + Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -2904,6 +2997,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 @@ -2924,7 +3018,6 @@ rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2942,6 +3035,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 @@ -2988,7 +3082,6 @@ do # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -2999,7 +3092,7 @@ cat >>conftest.$ac_ext <<_ACEOF #else # include #endif - Syntax error + Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 @@ -3011,6 +3104,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 @@ -3031,7 +3125,6 @@ rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether non-existent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -3049,6 +3142,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 @@ -3206,7 +3300,6 @@ if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -3226,11 +3319,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3243,7 +3345,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi @@ -3259,7 +3361,6 @@ if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -3276,11 +3377,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3293,7 +3403,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_prog_cxx_g=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 @@ -3321,7 +3431,6 @@ for ac_declaration in \ 'void exit (int);' do cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -3339,11 +3448,20 @@ exit (42); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3356,9 +3474,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 continue fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -3375,11 +3492,20 @@ exit (42); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3391,7 +3517,7 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done rm -f conftest* if test -n "$ac_declaration"; then @@ -3519,6 +3645,7 @@ fi # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 @@ -3535,6 +3662,7 @@ do case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. @@ -3542,20 +3670,20 @@ case $as_dir/ in # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi done done ;; @@ -3771,7 +3899,6 @@ echo $ECHO_N "checking for SDL - version >= $min_sdl_version... $ECHO_C" >&6 echo $ac_n "cross compiling; assumed OK... $ac_c" else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -3882,7 +4009,6 @@ echo "${ECHO_T}no" >&6 CFLAGS="$CFLAGS $SDL_CFLAGS" LIBS="$LIBS $SDL_LIBS" cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -3902,11 +4028,20 @@ main () _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 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 -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -3930,7 +4065,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 echo "*** or that you have moved SDL since it was installed. In the latter case, you" echo "*** may want to edit the sdl-config script: $SDL_CONFIG" fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi @@ -3956,7 +4092,6 @@ if test "${ac_cv_c_const+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4019,11 +4154,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4036,7 +4180,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 echo "${ECHO_T}$ac_cv_c_const" >&6 @@ -4056,7 +4200,6 @@ else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4071,11 +4214,20 @@ $ac_kw foo_t foo () {return 0; } _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4087,23 +4239,27 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext done fi echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 echo "${ECHO_T}$ac_cv_c_inline" >&6 + + case $ac_cv_c_inline in inline | yes) ;; - no) -cat >>confdefs.h <<\_ACEOF -#define inline + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif _ACEOF - ;; - *) cat >>confdefs.h <<_ACEOF -#define inline $ac_cv_c_inline -_ACEOF - ;; + ;; esac @@ -4128,7 +4284,6 @@ if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4149,11 +4304,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4166,12 +4330,11 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4193,7 +4356,6 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4218,7 +4380,6 @@ if test $ac_cv_header_stdc = yes; then : else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4230,9 +4391,9 @@ cat >>conftest.$ac_ext <<_ACEOF # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif @@ -4243,7 +4404,7 @@ main () int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) + || toupper (i) != TOUPPER (i)) exit(2); exit (0); } @@ -4293,7 +4454,7 @@ fi for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h + inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -4302,7 +4463,6 @@ if eval "test \"\${$as_ac_Header+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4314,11 +4474,20 @@ $ac_includes_default _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4331,7 +4500,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 @@ -4351,7 +4520,6 @@ if test "${ac_cv_type_size_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4371,11 +4539,20 @@ if (sizeof (size_t)) _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4388,7 +4565,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_size_t=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 echo "${ECHO_T}$ac_cv_type_size_t" >&6 @@ -4408,7 +4585,6 @@ if test "${ac_cv_struct_tm+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4427,11 +4603,20 @@ struct tm *tp; tp->tm_sec; _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4444,7 +4629,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_struct_tm=sys/time.h fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 echo "${ECHO_T}$ac_cv_struct_tm" >&6 @@ -4461,7 +4646,6 @@ fi 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 -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4479,11 +4663,20 @@ main () _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 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 -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4502,11 +4695,11 @@ sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext echo "$as_me:$LINENO: checking if environ can be linked" >&5 echo $ECHO_N "checking if environ can be linked... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4523,11 +4716,20 @@ main () _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 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 -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4546,7 +4748,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext #Check if the compiler support attributes @@ -4555,7 +4758,6 @@ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext echo "$as_me:$LINENO: checking if compiler allows __attribute__" >&5 echo $ECHO_N "checking if compiler allows __attribute__... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4572,11 +4774,20 @@ typedef struct { } __attribute__ ((packed)) junk; _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4594,7 +4805,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext alsa_save_CFLAGS="$CFLAGS" alsa_save_LDFLAGS="$LDFLAGS" @@ -4672,7 +4883,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4723,11 +4933,20 @@ exit(0); _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4745,7 +4964,7 @@ echo "${ECHO_T}not present." >&6 alsa_found=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -4762,7 +4981,6 @@ else ac_check_lib_save_LIBS=$LIBS LIBS="-lasound $LIBS" cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4786,11 +5004,20 @@ snd_ctl_open (); _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 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 -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4803,7 +5030,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_asound_snd_ctl_open=no fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_asound_snd_ctl_open" >&5 @@ -4853,7 +5081,6 @@ if test "${ac_cv_c_bigendian+set}" = set; then else # See if sys/param.h defines the BYTE_ORDER macro. cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4875,11 +5102,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4887,7 +5123,6 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (exit $ac_status); }; }; then # It does; now see whether it defined to BIG_ENDIAN or not. cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4909,11 +5144,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4926,7 +5170,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_bigendian=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 @@ -4936,7 +5180,6 @@ if test "$cross_compiling" = yes; then # try to guess the endianness by grepping values into an object file ac_cv_c_bigendian=unknown cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -4958,11 +5201,20 @@ main () _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -4984,10 +5236,9 @@ else sed 's/^/| /' conftest.$ac_ext >&5 fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext else cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5029,7 +5280,7 @@ fi rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext fi echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 echo "${ECHO_T}$ac_cv_c_bigendian" >&6 @@ -5073,7 +5324,6 @@ else echo "$as_me:$LINENO: checking curses.h usability" >&5 echo $ECHO_N "checking curses.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5084,11 +5334,20 @@ $ac_includes_default _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5101,7 +5360,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 @@ -5109,7 +5368,6 @@ echo "${ECHO_T}$ac_header_compiler" >&6 echo "$as_me:$LINENO: checking curses.h presence" >&5 echo $ECHO_N "checking curses.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5127,6 +5385,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 @@ -5146,33 +5405,32 @@ 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 in - yes:no ) +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) { echo "$as_me:$LINENO: WARNING: curses.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: curses.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: curses.h: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 + { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: curses.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes ;; - no:yes ) + no:yes:* ) { echo "$as_me:$LINENO: WARNING: curses.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: curses.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: curses.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: curses.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: curses.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: curses.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: curses.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: curses.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: curses.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: curses.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: curses.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: curses.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: curses.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## +## --------------------------------- ## +## Report this to the dosbox lists. ## +## --------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 @@ -5202,7 +5460,6 @@ else ac_check_lib_save_LIBS=$LIBS LIBS="-lcurses $LIBS" cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5226,11 +5483,20 @@ initscr (); _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 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 -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5243,7 +5509,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_curses_initscr=no fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_curses_initscr" >&5 @@ -5260,7 +5527,6 @@ else ac_check_lib_save_LIBS=$LIBS LIBS="-lpdcurses $LIBS" cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5284,11 +5550,20 @@ initscr (); _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 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 -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5301,7 +5576,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pdcurses_initscr=no fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_pdcurses_initscr" >&5 @@ -5350,7 +5626,7 @@ if test "${enable_core_inline+set}" = set; then if test x$enable_core_inline = xyes ; then echo "$as_me:$LINENO: result: enabling inlined memory handling in CPU Core" >&5 -echo "${ECHO_T}enabling inlined memory handling in CPU Core" >&6, +echo "${ECHO_T}enabling inlined memory handling in CPU Core" >&6 cat >>confdefs.h <<\_ACEOF #define C_CORE_INLINE 1 _ACEOF @@ -5361,26 +5637,80 @@ 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 + i386|i486|i586|i686) + cat >>confdefs.h <<\_ACEOF +#define C_HOSTCPU X86 +_ACEOF + + echo "$as_me:$LINENO: result: x86 compatible" >&5 +echo "${ECHO_T}x86 compatible" >&6 + c_hostcpu="x86" + ;; + *) + cat >>confdefs.h <<\_ACEOF +#define C_HOSTCPU UNKOWN +_ACEOF + + echo "$as_me:$LINENO: result: unknown" >&5 +echo "${ECHO_T}unknown" >&6 + ;; +esac + + +# Check whether --enable-dynamic-x86 or --disable-dynamic-x86 was given. +if test "${enable_dynamic_x86+set}" = set; then + enableval="$enable_dynamic_x86" + +else + enable_dynamic_x86=yes +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 + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +else + if test x$c_hostcpu = xx86 ; then + cat >>confdefs.h <<\_ACEOF +#define C_DYNAMIC_X86 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 + + + + + # Check whether --enable-fpu or --disable-fpu was given. if test "${enable_fpu+set}" = set; then enableval="$enable_fpu" - if test x$enable_fpu = xno ; then - echo "$as_me:$LINENO: result: disabling FPU supportd" >&5 -echo "${ECHO_T}disabling FPU supportd" >&6 - else - cat >>confdefs.h <<\_ACEOF -#define C_FPU 1 -_ACEOF - - fi - else + enable_fpu=yes +fi; +echo "$as_me:$LINENO: checking whether fpu emulation will be enabled" >&5 +echo $ECHO_N "checking whether fpu emulation will be enabled... $ECHO_C" >&6 +if test x$enable_fpu = xyes ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 cat >>confdefs.h <<\_ACEOF #define C_FPU 1 _ACEOF -fi; +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi @@ -5397,7 +5727,6 @@ else echo "$as_me:$LINENO: checking png.h usability" >&5 echo $ECHO_N "checking png.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5408,11 +5737,20 @@ $ac_includes_default _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5425,7 +5763,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 @@ -5433,7 +5771,6 @@ echo "${ECHO_T}$ac_header_compiler" >&6 echo "$as_me:$LINENO: checking png.h presence" >&5 echo $ECHO_N "checking png.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5451,6 +5788,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 @@ -5470,33 +5808,32 @@ 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 in - yes:no ) +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) { echo "$as_me:$LINENO: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: png.h: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 + { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: png.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes ;; - no:yes ) + no:yes:* ) { echo "$as_me:$LINENO: WARNING: png.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: png.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: png.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: png.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: png.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: png.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: png.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: png.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: png.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## +## --------------------------------- ## +## Report this to the dosbox lists. ## +## --------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 @@ -5526,7 +5863,6 @@ else ac_check_lib_save_LIBS=$LIBS LIBS="-lpng -lz $LIBS" cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5550,11 +5886,20 @@ png_check_sig (); _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 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 -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5567,7 +5912,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_png_png_check_sig=no fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_check_sig" >&5 @@ -5602,7 +5948,6 @@ else echo "$as_me:$LINENO: checking SDL/SDL_net.h usability" >&5 echo $ECHO_N "checking SDL/SDL_net.h usability... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5613,11 +5958,20 @@ $ac_includes_default _ACEOF rm -f conftest.$ac_objext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&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 -s conftest.$ac_objext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5630,7 +5984,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi -rm -f conftest.$ac_objext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6 @@ -5638,7 +5992,6 @@ echo "${ECHO_T}$ac_header_compiler" >&6 echo "$as_me:$LINENO: checking SDL/SDL_net.h presence" >&5 echo $ECHO_N "checking SDL/SDL_net.h presence... $ECHO_C" >&6 cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5656,6 +6009,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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 @@ -5675,33 +6029,32 @@ 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 in - yes:no ) +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: SDL/SDL_net.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: proceeding with the preprocessor's result" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 + { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: SDL/SDL_net.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes ;; - no:yes ) + no:yes:* ) { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: present but cannot be compiled" >&5 echo "$as_me: WARNING: SDL/SDL_net.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: SDL/SDL_net.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: SDL/SDL_net.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: SDL/SDL_net.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: SDL/SDL_net.h: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: SDL/SDL_net.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: SDL/SDL_net.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: SDL/SDL_net.h: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX -## ------------------------------------ ## -## Report this to bug-autoconf@gnu.org. ## -## ------------------------------------ ## +## --------------------------------- ## +## Report this to the dosbox lists. ## +## --------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 @@ -5731,7 +6084,6 @@ else ac_check_lib_save_LIBS=$LIBS LIBS="-lSDL_net $LIBS" cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -5755,11 +6107,20 @@ SDLNet_Init (); _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 + (eval $ac_link) 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 -s conftest$ac_exeext' + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 (eval $ac_try) 2>&5 ac_status=$? @@ -5772,7 +6133,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_SDL_net_SDLNet_Init=no fi -rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_net_SDLNet_Init" >&5 @@ -5793,6 +6155,306 @@ echo "$as_me: WARNING: Can't find SDL_net, internal modem disabled" >&2;} fi + +# Check whether --enable-opengl or --disable-opengl was given. +if test "${enable_opengl+set}" = set; then + enableval="$enable_opengl" + +else + enable_opengl=yes +fi; +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 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_GL_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_GL_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_GL_main" >&5 +echo "${ECHO_T}$ac_cv_lib_GL_main" >&6 +if test $ac_cv_lib_GL_main = yes; then + have_gl_lib=yes +else + have_gl_lib=no +fi + +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 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lopengl32 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_opengl32_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_opengl32_main=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_opengl32_main" >&5 +echo "${ECHO_T}$ac_cv_lib_opengl32_main" >&6 +if test $ac_cv_lib_opengl32_main = yes; then + have_opengl32_lib=yes +else + have_opengl32_lib=no +fi + +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 + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking GL/gl.h usability" >&5 +echo $ECHO_N "checking GL/gl.h 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 +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&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 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 GL/gl.h presence" >&5 +echo $ECHO_N "checking GL/gl.h 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 +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&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: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: GL/gl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: GL/gl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: GL/gl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: GL/gl.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: GL/gl.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: GL/gl.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: GL/gl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: GL/gl.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: GL/gl.h: in the future, the compiler will take precedence" >&2;} + ( + cat <<\_ASBOX +## --------------------------------- ## +## Report this to the dosbox lists. ## +## --------------------------------- ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +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 + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_GL_gl_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_GL_gl_h" >&5 +echo "${ECHO_T}$ac_cv_header_GL_gl_h" >&6 + +fi +if test $ac_cv_header_GL_gl_h = yes; then + have_gl_h=yes +else + have_gl_h=no +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 -a x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + LIBS="$LIBS -lGL" + cat >>confdefs.h <<\_ACEOF +#define C_OPENGL 1 +_ACEOF + +elif test x$enable_opengl = xyes -a x$have_gl_h = xyes -a x$have_opengl32_lib = xyes ; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + LIBS="$LIBS -lopengl32" + cat >>confdefs.h <<\_ACEOF +#define C_OPENGL 1 +_ACEOF + +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + case "$target" in *-*-cygwin* | *-*-mingw32*) LIBS="$LIBS -lwinmm" @@ -5804,11 +6466,18 @@ cat >>confdefs.h <<\_ACEOF _ACEOF LIBS="$LIBS -framework AudioUnit" + ;; + *-*-linux-gnu*) + +cat >>confdefs.h <<\_ACEOF +#define LINUX 1 +_ACEOF + ;; esac - ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_16/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/ints/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc/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/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/ints/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc/Makefile visualc_net/Makefile include/Makefile docs/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -5837,13 +6506,13 @@ _ACEOF # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" ;; esac; } | @@ -5873,13 +6542,13 @@ test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ + ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/; s/:*\${srcdir}:*/:/; s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; +s/^\([^=]*=[ ]*\):*/\1/; s/:*$//; -s/^[^=]*=[ ]*$//; +s/^[^=]*=[ ]*$//; }' fi @@ -5890,7 +6559,7 @@ ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` # 2. Add them. ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' @@ -5955,9 +6624,10 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi +DUALCASE=1; export DUALCASE # for MKS sh # Support unset when possible. -if (FOO=FOO; unset FOO) >/dev/null 2>&1; then +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false @@ -5976,7 +6646,7 @@ for as_var in \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do - if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else $as_unset $as_var @@ -6155,16 +6825,17 @@ rm -f conf$$ conf$$.exe conf$$.file if mkdir -p . 2>/dev/null; then as_mkdir_p=: else + test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_executable_p="test -f" # Sed expression to map a string onto a valid CPP name. -as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. -as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # IFS @@ -6190,8 +6861,8 @@ _ASBOX } >&5 cat >&5 <<_CSEOF -This file was extended by dosbox $as_me 0.60, which was -generated by GNU Autoconf 2.57. Invocation command line was +This file was extended by dosbox $as_me 0.61, which was +generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -6235,9 +6906,9 @@ Usage: $0 [OPTIONS] [FILE]... -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] - instantiate the configuration file FILE + instantiate the configuration file FILE --header=FILE[:TEMPLATE] - instantiate the configuration header FILE + instantiate the configuration header FILE Configuration files: $config_files @@ -6253,12 +6924,11 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -dosbox config.status 0.60 -configured by $0, generated by GNU Autoconf 2.57, +dosbox config.status 0.61 +configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" -Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. +Copyright (C) 2003 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." srcdir=$srcdir @@ -6367,9 +7037,9 @@ do "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/cpu/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/cpu/Makefile" ;; - "src/cpu/core_16/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/cpu/core_16/Makefile" ;; "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/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" ;; @@ -6381,6 +7051,7 @@ do "src/platform/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/platform/Makefile" ;; "src/platform/visualc/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/platform/visualc/Makefile" ;; "visualc/Makefile" ) CONFIG_FILES="$CONFIG_FILES visualc/Makefile" ;; + "visualc_net/Makefile" ) CONFIG_FILES="$CONFIG_FILES visualc_net/Makefile" ;; "include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; @@ -6563,9 +7234,9 @@ _ACEOF (echo ':t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" fi ac_sed_frag=`expr $ac_sed_frag + 1` ac_beg=$ac_end @@ -6583,21 +7254,21 @@ for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -6613,10 +7284,10 @@ echo X"$ac_file" | as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -6654,12 +7325,45 @@ case $srcdir in ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac -# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be -# absolute. -ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` -ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` -ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` -ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac case $INSTALL in @@ -6667,11 +7371,6 @@ ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` *) ac_INSTALL=$ac_top_builddir$INSTALL ;; esac - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ @@ -6681,7 +7380,7 @@ echo "$as_me: creating $ac_file" >&6;} configure_input="$ac_file. " fi configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." + sed 's,.*/,,'` by configure." # First look for the input files in the build tree, otherwise in the # src tree. @@ -6690,26 +7389,32 @@ echo "$as_me: creating $ac_file" >&6;} case $f in -) echo $tmp/stdin ;; [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } - echo $f;; + echo "$f";; *) # Relative - if test -f "$f"; then - # Build tree - echo $f - elif test -f "$srcdir/$f"; then - # Source tree - echo $srcdir/$f - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } - fi;; + fi;; esac done` || { (exit 1); exit 1; } + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub @@ -6749,12 +7454,12 @@ cat >>$CONFIG_STATUS <<\_ACEOF # NAME is the cpp macro being defined and VALUE is the value it is being given. # # ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='[ ].*$,\1#\2' +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' ac_dC=' ' ac_dD=',;t' # ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' ac_uB='$,\1#\2define\3' ac_uC=' ' ac_uD=',;t' @@ -6763,11 +7468,11 @@ for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case $ac_file in - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; * ) ac_file_in=$ac_file.in ;; esac @@ -6781,28 +7486,29 @@ echo "$as_me: creating $ac_file" >&6;} case $f in -) echo $tmp/stdin ;; [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } - echo $f;; + # Do quote $f, to prevent DOS paths from being IFS'd. + echo "$f";; *) # Relative - if test -f "$f"; then - # Build tree - echo $f - elif test -f "$srcdir/$f"; then - # Source tree - echo $srcdir/$f - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 + if test -f "$f"; then + # Build tree + echo "$f" + elif test -f "$srcdir/$f"; then + # Source tree + echo "$srcdir/$f" + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 echo "$as_me: error: cannot find input file: $f" >&2;} { (exit 1); exit 1; }; } - fi;; + fi;; esac done` || { (exit 1); exit 1; } # Remove the trailing spaces. - sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in _ACEOF @@ -6825,9 +7531,9 @@ s/[\\&,]/\\&/g s,[\\$`],\\&,g t clear : clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp t end -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp : end _ACEOF # If some macros were called several times there might be several times @@ -6841,13 +7547,13 @@ rm -f confdef2sed.sed # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. cat >>conftest.undefs <<\_ACEOF -s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS -echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail @@ -6856,7 +7562,7 @@ do # Write a limited-size here document to $tmp/defines.sed. echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#define' lines. - echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS @@ -6883,7 +7589,7 @@ do # Write a limited-size here document to $tmp/undefs.sed. echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS # Speed up: don't consider the non `#undef' - echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS # Work around the forget-to-reset-the-flag bug. echo 't clr' >>$CONFIG_STATUS echo ': clr' >>$CONFIG_STATUS @@ -6917,10 +7623,10 @@ echo "$as_me: $ac_file is unchanged" >&6;} else ac_dir=`(dirname "$ac_file") 2>/dev/null || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -6936,10 +7642,10 @@ echo X"$ac_file" | as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -6971,10 +7677,10 @@ for _am_header in $config_headers :; do done echo "timestamp for $ac_file" >`(dirname $ac_file) 2>/dev/null || $as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X$ac_file : 'X\(//\)[^/]' \| \ - X$ac_file : 'X\(//\)$' \| \ - X$ac_file : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X$ac_file : 'X\(//\)[^/]' \| \ + X$ac_file : 'X\(//\)$' \| \ + X$ac_file : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X$ac_file | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -6993,16 +7699,41 @@ for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` ac_dir=`(dirname "$ac_dest") 2>/dev/null || $as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_dest" : 'X\(//\)[^/]' \| \ - X"$ac_dest" : 'X\(//\)$' \| \ - X"$ac_dest" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$ac_dest" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } /^X\(\/\/\)$/{ s//\1/; q; } /^X\(\/\).*/{ s//\1/; q; } s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. if test "$ac_dir" != .; then @@ -7028,12 +7759,45 @@ case $srcdir in ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_builddir$srcdir ;; esac -# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be -# absolute. -ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` -ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` -ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` -ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + +# Do not use `cd foo && pwd` to compute absolute paths, because +# the directories may not exist. +case `pwd` in +.) ac_abs_builddir="$ac_dir";; +*) + case "$ac_dir" in + .) ac_abs_builddir=`pwd`;; + [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; + *) ac_abs_builddir=`pwd`/"$ac_dir";; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_builddir=${ac_top_builddir}.;; +*) + case ${ac_top_builddir}. in + .) ac_abs_top_builddir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; + *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_srcdir=$ac_srcdir;; +*) + case $ac_srcdir in + .) ac_abs_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; + *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; + esac;; +esac +case $ac_abs_builddir in +.) ac_abs_top_srcdir=$ac_top_srcdir;; +*) + case $ac_top_srcdir in + .) ac_abs_top_srcdir=$ac_abs_builddir;; + [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; + *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; + esac;; +esac { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 @@ -7051,10 +7815,10 @@ echo "$as_me: executing $ac_dest commands" >&6;} if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`(dirname "$mf") 2>/dev/null || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -7090,10 +7854,10 @@ echo X"$mf" | test -f "$dirpart/$file" && continue fdir=`(dirname "$file") 2>/dev/null || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } @@ -7109,10 +7873,10 @@ echo X"$file" | as_dirs="$as_dir $as_dirs" as_dir=`(dirname "$as_dir") 2>/dev/null || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } /^X\(\/\/\)[^/].*/{ s//\1/; q; } diff --git a/configure.in b/configure.in index 305dc4c..ad483f7 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Init. -AC_INIT(dosbox,0.60) +AC_INIT(dosbox,0.61) AC_PREREQ(2.50) AC_CONFIG_SRCDIR(README) @@ -86,19 +86,51 @@ AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],[Enable debug mode]),[ AH_TEMPLATE(C_CORE_INLINE,[Define to 1 to use inlined memory functions in cpu core]) AC_ARG_ENABLE(core-inline,AC_HELP_STRING([--enable-core-inline],[Enable inlined memory handling in CPU Core]),[ if test x$enable_core_inline = xyes ; then - AC_MSG_RESULT([enabling inlined memory handling in CPU Core]), + AC_MSG_RESULT([enabling inlined memory handling in CPU Core]) AC_DEFINE(C_CORE_INLINE,1) fi ],) + +dnl The target cpu checks for dynamic cores +AH_TEMPLATE(C_HOSTCPU,[The type of cpu this host has]) +AC_MSG_CHECKING(for target cpu type) +case "$target_cpu" in + i386|i486|i586|i686) + AC_DEFINE(C_HOSTCPU,X86) + AC_MSG_RESULT(x86 compatible) + c_hostcpu="x86" + ;; + *) + AC_DEFINE(C_HOSTCPU,UNKOWN) + AC_MSG_RESULT(unknown) + ;; +esac +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 + AC_MSG_RESULT(no) +else + if test x$c_hostcpu = xx86 ; then + AC_DEFINE(C_DYNAMIC_X86,1) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + 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]),[ - if test x$enable_fpu = xno ; then - AC_MSG_RESULT([disabling FPU supportd]) - else - AC_DEFINE(C_FPU,1) - fi -],AC_DEFINE(C_FPU,1)) +AC_ARG_ENABLE(fpu,AC_HELP_STRING([--disable-fpu],[Disable fpu support]),,enable_fpu=yes) +AC_MSG_CHECKING(whether fpu emulation will be enabled) +if test x$enable_fpu = xyes ; then + AC_MSG_RESULT(yes) + AC_DEFINE(C_FPU,1) +else + AC_MSG_RESULT(no) +fi AH_TEMPLATE(C_SSHOT,[Define to 1 to enable screenshots, requires libpng]) AC_CHECK_HEADER(png.h,have_png_h=yes,) @@ -120,6 +152,23 @@ else AC_MSG_WARN([Can't find SDL_net, internal modem disabled]) fi +AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support]) +AC_ARG_ENABLE(opengl,AC_HELP_STRING([--disable-opengl],[Disable opengl support]),,enable_opengl=yes) +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_MSG_CHECKING(whether opengl display output will be enabled) +if test x$enable_opengl = xyes -a x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then + AC_MSG_RESULT(yes) + LIBS="$LIBS -lGL" + AC_DEFINE(C_OPENGL,1) +elif test x$enable_opengl = xyes -a x$have_gl_h = xyes -a x$have_opengl32_lib = xyes ; then + AC_MSG_RESULT(yes) + LIBS="$LIBS -lopengl32" + AC_DEFINE(C_OPENGL,1) +else + AC_MSG_RESULT(no) +fi dnl Some host detection and actions for them case "$target" in @@ -134,6 +183,9 @@ 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]) + ;; esac @@ -141,9 +193,9 @@ AC_OUTPUT([ Makefile src/Makefile src/cpu/Makefile -src/cpu/core_16/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 @@ -155,6 +207,7 @@ src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc/Makefile +visualc_net/Makefile include/Makefile docs/Makefile ]) diff --git a/docs/Makefile.in b/docs/Makefile.in index ca0b56c..579bd4b 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -255,7 +255,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -274,7 +274,6 @@ clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile - distclean-am: clean-am distclean-generic dvi: dvi-am @@ -297,7 +296,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/include/Makefile.am b/include/Makefile.am index d910b84..d0ec949 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -26,7 +26,9 @@ regs.h \ render.h \ serialport.h \ setup.h \ +shell.h \ support.h \ timer.h \ +vga.h \ video.h diff --git a/include/Makefile.in b/include/Makefile.in index 112a016..87fe5a3 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -157,8 +157,10 @@ regs.h \ render.h \ serialport.h \ setup.h \ +shell.h \ support.h \ timer.h \ +vga.h \ video.h subdir = include @@ -281,7 +283,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -300,7 +302,6 @@ clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile - distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am @@ -323,7 +324,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/include/bios.h b/include/bios.h index ef37fa8..18e2fb1 100644 --- a/include/bios.h +++ b/include/bios.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -114,6 +114,7 @@ private: }; +void BIOS_ZeroExtendedSize(void); void char_out(Bit8u chr,Bit32u att,Bit8u page); void INT10_StartUp(void); void INT16_StartUp(void); diff --git a/include/callback.h b/include/callback.h index 9b083be..eb299fc 100644 --- a/include/callback.h +++ b/include/callback.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,9 +47,10 @@ void CALLBACK_Idle(void); void CALLBACK_RunRealInt(Bit8u intnum); void CALLBACK_RunRealFar(Bit16u seg,Bit16u off); -bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type); -bool CALLBACK_SetupAt(Bitu callback,CallBack_Handler handler,Bitu type,Bitu linearAddress); +bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* description=0); +bool CALLBACK_SetupAt(Bitu callback,CallBack_Handler handler,Bitu type,Bitu linearAddress, const char* description=0); +const char* CALLBACK_GetDescription(Bitu callback); bool CALLBACK_Free(Bitu callback); void CALLBACK_SCF(bool val); diff --git a/include/cpu.h b/include/cpu.h index 40ea13f..f741895 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,18 +33,14 @@ extern Bits CPU_CycleMax; typedef Bits (CPU_Decoder)(void); extern CPU_Decoder * cpudecoder; +Bits CPU_Core_Normal_Run(void); +Bits CPU_Core_Normal_Trap_Run(void); +Bits CPU_Core_Full_Run(void); +Bits CPU_Core_Dyn_X86_Run(void); //CPU Stuff -void SetCPU16bit( ); -enum CODE_TYPE { - CODE_REAL, - CODE_PMODE16, - CODE_PMODE32, - CODE_INIT, -}; - -extern bool parity_lookup[256]; +extern Bit16u parity_lookup[256]; void CPU_LLDT(Bitu selector); void CPU_LTR(Bitu selector); @@ -70,34 +66,38 @@ bool CPU_LMSW(Bitu word); void CPU_VERR(Bitu selector); void CPU_VERW(Bitu selector); -bool CPU_JMP(bool use32,Bitu selector,Bitu offset); -bool CPU_CALL(bool use32,Bitu selector,Bitu offset); -bool CPU_RET(bool use32,Bitu bytes); +void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen=0); +void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu opLen=0); +void CPU_RET(bool use32,Bitu bytes,Bitu opLen=0); -bool Interrupt(Bitu num); -bool CPU_IRET(bool use32); -void CPU_SetSegGeneral(SegNames seg,Bitu value); +#define CPU_INT_SOFTWARE 0x1 +#define CPU_INT_EXCEPTION 0x2 +#define CPU_INT_HAS_ERROR 0x4 + + +void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen=0); +INLINE void CPU_HW_Interrupt(Bitu num) { + CPU_Interrupt(num,0); +} +INLINE void CPU_SW_Interrupt(Bitu num,Bitu OpLen) { + CPU_Interrupt(num,CPU_INT_SOFTWARE,OpLen); +} + +void CPU_Exception(Bitu which,Bitu error=0); +void CPU_StartException(void); +void CPU_SetupException(Bitu which,Bitu error=0); + +void CPU_IRET(bool use32); +bool CPU_SetSegGeneral(SegNames seg,Bitu value); +void CPU_HLT(Bitu opLen); void CPU_CPUID(void); -void CPU_HLT(void); - Bitu CPU_Pop16(void); Bitu CPU_Pop32(void); void CPU_Push16(Bitu value); void CPU_Push32(Bitu value); -void CPU_SetFlags(Bitu word); - - -INLINE void CPU_SetFlagsd(Bit32u word) { - CPU_SetFlags(word); -}; - -INLINE void CPU_SetFlagsw(Bit16u word) { - CPU_SetFlags((flags.word&0xffff0000)|word); -}; - - +void CPU_SetFlags(Bitu word,Bitu mask); // ********************************************************************* // Descriptor @@ -146,33 +146,25 @@ INLINE void CPU_SetFlagsw(Bit16u word) { #define DESC_CODE_R_C_A 0x1e #define DESC_CODE_R_C_NA 0x1f -#pragma pack(1) -/* TSS Struct from Bochs - http://bochs.sf.net */ -struct TSS_386 { - Bit16u back, RESERVED0; /* Backlink */ - Bit32u esp0; /* The CK stack pointer */ - Bit16u ss0, RESERVED1; /* The CK stack selector */ - Bit32u esp1; /* The parent KL stack pointer */ - Bit16u ss1, RESERVED2; /* The parent KL stack selector */ - Bit32u esp2; /* Unused */ - Bit16u ss2, RESERVED3; /* Unused */ - Bit32u cr3; /* The page directory pointer */ - Bit32u eip; /* The instruction pointer */ - Bit32u eflags; /* The flags */ - Bit32u eax, ecx, edx, ebx; /* The general purpose registers */ - Bit32u esp, ebp, esi, edi; /* The special purpose registers */ - Bit16u es, RESERVED4; /* The extra selector */ - Bit16u cs, RESERVED5; /* The code selector */ - Bit16u ss, RESERVED6; /* The application stack selector */ - Bit16u ds, RESERVED7; /* The data selector */ - Bit16u fs, RESERVED8; /* And another extra selector */ - Bit16u gs, RESERVED9; /* ... and another one */ - Bit16u ldt, RESERVED10; /* The local descriptor table */ - Bit16u trap; /* The trap flag (for debugging) */ - Bit16u io; /* The I/O Map base address */ -} GCC_ATTRIBUTE(packed);; +#ifdef _MSC_VER +#pragma pack (1) +#endif struct S_Descriptor { +#ifdef WORDS_BIGENDIAN + Bit32u base_0_15 :16; + Bit32u limit_0_15 :16; + Bit32u base_24_31 :8; + Bit32u g :1; + Bit32u big :1; + Bit32u r :1; + Bit32u avl :1; + Bit32u limit_16_19 :4; + Bit32u p :1; + Bit32u dpl :2; + Bit32u type :5; + Bit32u base_16_23 :8; +#else Bit32u limit_0_15 :16; Bit32u base_0_15 :16; Bit32u base_16_23 :8; @@ -185,9 +177,20 @@ struct S_Descriptor { Bit32u big :1; Bit32u g :1; Bit32u base_24_31 :8; +#endif }GCC_ATTRIBUTE(packed); struct G_Descriptor { +#ifdef WORDS_BIGENDIAN + Bit32u selector: 16; + Bit32u offset_0_15 :16; + Bit32u offset_16_31 :16; + Bit32u p :1; + Bit32u dpl :2; + Bit32u type :5; + Bit32u reserved :3; + Bit32u paramcount :5; +#else Bit32u offset_0_15 :16; Bit32u selector :16; Bit32u paramcount :5; @@ -196,57 +199,53 @@ struct G_Descriptor { Bit32u dpl :2; Bit32u p :1; Bit32u offset_16_31 :16; +#endif } GCC_ATTRIBUTE(packed); -#pragma pack() - - -struct TaskSegment_32 { - Bit32u esp0; /* The CK stack pointer */ - Bit32u esp1; /* The parent KL stack pointer */ - Bit32u esp2; /* Unused */ - Bit32u cr3; /* The page directory pointer */ - Bit32u eip; /* The instruction pointer */ - Bit32u eflags; /* The flags */ - Bit32u eax, ecx, edx, ebx; /* The general purpose registers */ - Bit32u esp, ebp, esi, edi; /* The special purpose registers */ - Bit16u back; /* Backlink */ +struct TSS_16 { + Bit16u back; /* Back link to other task */ + Bit16u sp0; /* The CK stack pointer */ Bit16u ss0; /* The CK stack selector */ + Bit16u sp1; /* The parent KL stack pointer */ Bit16u ss1; /* The parent KL stack selector */ + Bit16u sp2; /* Unused */ Bit16u ss2; /* Unused */ + Bit16u ip; /* The instruction pointer */ + Bit16u flags; /* The flags */ + Bit16u ax, cx, dx, bx; /* The general purpose registers */ + Bit16u sp, bp, si, di; /* The special purpose registers */ Bit16u es; /* The extra selector */ Bit16u cs; /* The code selector */ Bit16u ss; /* The application stack selector */ Bit16u ds; /* The data selector */ - Bit16u fs; /* And another extra selector */ - Bit16u gs; /* ... and another one */ Bit16u ldt; /* The local descriptor table */ - Bit16u trap; /* The trap flag (for debugging) */ - Bit16u io; /* The I/O Map base address */ -}; +} GCC_ATTRIBUTE(packed); -void CPU_ReadTaskSeg32(PhysPt base,TaskSegment_32 * seg); +struct TSS_32 { + Bit32u back; /* Back link to other task */ + Bit32u esp0; /* The CK stack pointer */ + Bit32u ss0; /* The CK stack selector */ + Bit32u esp1; /* The parent KL stack pointer */ + Bit32u ss1; /* The parent KL stack selector */ + Bit32u esp2; /* Unused */ + Bit32u ss2; /* Unused */ + Bit32u cr3; /* The page directory pointer */ + Bit32u eip; /* The instruction pointer */ + Bit32u eflags; /* The flags */ + Bit32u eax, ecx, edx, ebx; /* The general purpose registers */ + Bit32u esp, ebp, esi, edi; /* The special purpose registers */ + Bit32u es; /* The extra selector */ + Bit32u cs; /* The code selector */ + Bit32u ss; /* The application stack selector */ + Bit32u ds; /* The data selector */ + Bit32u fs; /* And another extra selector */ + Bit32u gs; /* ... and another one */ + Bit32u ldt; /* The local descriptor table */ +} GCC_ATTRIBUTE(packed); -class TaskStateSegment -{ -public: - bool Get_ss_esp(Bitu which,Bitu & _ss,Bitu & _esp) { - PhysPt reader=seg_base+offsetof(TSS_386,esp0)+which*8; - _esp=mem_readd(reader); - _ss=mem_readw(reader+4); - return true; - } - bool Get_cr3(Bitu which,Bitu & _cr3) { - _cr3=mem_readd(seg_base+offsetof(TSS_386,cr3));; - return true; - } - -private: - PhysPt seg_base; - Bitu seg_limit; - Bitu seg_value; -}; - +#ifdef _MSC_VER +#pragma pack() +#endif class Descriptor { public: @@ -316,7 +315,7 @@ protected: class GDTDescriptorTable : public DescriptorTable { public: - bool GetDescriptor (Bitu selector, Descriptor& desc) { + bool GetDescriptor(Bitu selector, Descriptor& desc) { Bitu address=selector & ~7; if (selector & 4) { if (address>=ldt_limit) return false; @@ -328,7 +327,18 @@ public: return true; } } - + bool SetDescriptor(Bitu selector, Descriptor& desc) { + Bitu address=selector & ~7; + if (selector & 4) { + if (address>=ldt_limit) return false; + desc.Save(ldt_base+address); + return true; + } else { + if (address>=table_limit) return false; + desc.Save(table_base+address); + return true; + } + } Bitu SLDT(void) { return ldt_value; } @@ -347,29 +357,55 @@ private: Bitu ldt_value; }; +class TSS_Descriptor : public Descriptor { +public: + Bitu IsBusy(void) { + return saved.seg.type & 2; + } + Bitu Is386(void) { + return saved.seg.type & 8; + } + void SetBusy(bool busy) { + if (busy) saved.seg.type|=2; + else saved.seg.type&=~2; + } +}; + + struct CPUBlock { Bitu cpl; /* Current Privilege */ Bitu cr0; - bool v86; /* Are we in a v86 task */ bool pmode; /* Is Protected mode enabled */ GDTDescriptorTable gdt; DescriptorTable idt; - struct { - Bit16u val; - PhysPt base; - Bitu type; - } tr; struct { Bitu mask; bool big; } stack; struct { - CODE_TYPE type; /* What kind of code are we running */ bool big; } code; + struct { + Bitu cs,eip; + CPU_Decoder * old_decoder; + } hlt; + struct { + Bitu which,error; + } exception; + Bits direction; }; extern CPUBlock cpu; +INLINE void CPU_SetFlagsd(Bitu word) { + Bitu mask=cpu.cpl ? FMASK_NORMAL : FMASK_ALL; + CPU_SetFlags(word,mask); +}; + +INLINE void CPU_SetFlagsw(Bitu word) { + Bitu mask=(cpu.cpl ? FMASK_NORMAL : FMASK_ALL) & 0xffff; + CPU_SetFlags(word,mask); +}; + #endif diff --git a/include/cross.h b/include/cross.h index 730bdc8..7dd7882 100644 --- a/include/cross.h +++ b/include/cross.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: cross.h,v 1.7 2004/02/02 19:22:23 qbix79 Exp $ */ + #ifndef _CROSS_H #define _CROSS_H @@ -37,7 +39,7 @@ #if defined (WIN32) /* Win 32 */ -#define CROSS_FILENAME(blah) +#define CROSS_FILENAME(blah) {if(blah && *blah && (blah[strlen(blah)-1] == '\\')) strcat(blah,".");} #define CROSS_FILESPLIT '\\' #define F_OK 0 #else diff --git a/include/debug.h b/include/debug.h index 28f0297..bb44a99 100644 --- a/include/debug.h +++ b/include/debug.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/include/dma.h b/include/dma.h index 58f78c6..4c2c955 100644 --- a/include/dma.h +++ b/include/dma.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,14 +16,180 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: dma.h,v 1.9 2004/01/10 14:03:33 qbix79 Exp $ */ + +#ifndef __DMA_H +#define __DMA_H + +#include "mem.h" + +#define DMA_MODE_DEMAND 0 +#define DMA_MODE_SINGLE 1 +#define DMA_MODE_BLOCK 2 +#define DMA_MODE_CASCADE 3 + +#define DMA_BASEADDR 0 +#define DMA_TRANSCOUNT 1 +#define DMA_PAGEREG 2 + +#define DMA_CMDREG 0 +#define DMA_MODEREG 1 +#define DMA_CLEARREG 2 +#define DMA_DMACREG 3 +#define DMA_CLRMASKREG 4 +#define DMA_SINGLEREG 5 +#define DMA_WRITEALLREG 6 + +static Bit8u ChannelPorts [3][8] = { 0x00, 0x02, 0x04, 0x06, 0xff, 0xc4, 0xc8, 0xcc, + 0x01, 0x03, 0x05, 0x07, 0xff, 0xc6, 0xca, 0xce, + 0x87, 0x83, 0x81, 0x82, 0xff, 0x8b, 0x89, 0x8a }; + +static Bit8u ControllerPorts [2][7] = { 0x08, 0x0b, 0x0c, 0x0d, 0x0e, 0x0a, 0xf, + 0xd0, 0xd6, 0xd8, 0xda, 0xdc, 0xd4, 0xde }; + + typedef void (* DMA_EnableCallBack)(bool enable); +typedef void (* DMA_NewCallBack)(void *useChannel, bool tc); void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback); +void DMA_CheckEnabled(void * usechan); + Bitu DMA_8_Read(Bitu channel,Bit8u * buffer,Bitu count); Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count); Bitu DMA_16_Read(Bitu channel,Bit8u * buffer,Bitu count); Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count); +extern Bit8u read_dmaB(Bit32u port); +extern Bit16u read_dmaW(Bit32u port); + +extern void write_dmaB(Bit32u port,Bit8u val); +extern void write_dmaW(Bit32u port,Bit16u val); + +class DmaController { +public: + bool flipflop; + Bit8u ctrlnum; +public: + + DmaController(Bit8u num) { + int i; + for(i=0;i<7;i++) { + IO_RegisterReadBHandler(ControllerPorts[num][i],read_dmaB); + IO_RegisterReadWHandler(ControllerPorts[num][i],read_dmaW); + + IO_RegisterWriteBHandler(ControllerPorts[num][i],write_dmaB); + IO_RegisterWriteWHandler(ControllerPorts[num][i],write_dmaW); + } + flipflop = true; + ctrlnum = num; + } + + Bit16u portRead(Bit32u port, bool eightbit); + void portWrite(Bit32u port, Bit16u val, bool eightbit); + +}; + + + +class DmaChannel { +public: + + Bit8u channum; + Bit16u baseaddr; + Bit16u current_addr; + Bit16u pageaddr; + PhysPt physaddr; + PhysPt curraddr; + Bit32s transcnt; + Bit32s currcnt; + DmaController *myController; + bool DMA16; + bool addr_changed; +public: + Bit8u dmamode; + bool dir; + bool autoinit; + Bit8u trantype; + bool masked; + bool enabled; + DMA_EnableCallBack enable_callback; + DMA_NewCallBack newcallback; + + DmaChannel(Bit8u num, DmaController *useController, bool sb) { + int i; + masked = true; + enabled = false; + enable_callback = NULL; + newcallback = NULL; + if(num == 4) return; + addr_changed=false; + + for(i=0;i<3;i++) { + IO_RegisterReadBHandler(ChannelPorts[i][num],read_dmaB); + IO_RegisterReadWHandler(ChannelPorts[i][num],read_dmaW); + + IO_RegisterWriteBHandler(ChannelPorts[i][num],write_dmaB); + IO_RegisterWriteWHandler(ChannelPorts[i][num],write_dmaW); + } + myController = useController; + channum = num; + DMA16 = sb; + baseaddr = 0; + pageaddr = 0; + physaddr = 0; + curraddr = 0; + transcnt = 0; + currcnt = 0; + dir = false; + autoinit = false; + } + + void RegisterCallback(DMA_NewCallBack useCallBack) { newcallback = useCallBack; } + + void reset(void) { + addr_changed=false; + curraddr = physaddr; + currcnt = transcnt+1; + current_addr = baseaddr; + //LOG(LOG_DMA,LOG_NORMAL)("Setup at address %X:%X count %X",pageaddr,baseaddr,currcnt); + } + + void MakeCallback(bool tc) { + if (newcallback != NULL) { + if(tc) { + (*newcallback)(this, true); + } else { + if ((enabled) && (!masked) && (transcnt!=0)) { + (*newcallback)(this, false); + } + } + + } + } + + Bit32u Read(Bit32s requestsize, Bit8u * buffer); + + Bit32u Write(Bit32s requestsize, Bit8u * buffer); + + void calcPhys(void); + + Bit16u portRead(Bit32u port, bool eightbit); + + void portWrite(Bit32u port, Bit16u val, bool eightbit); + + // Notify channel when mask changes + void Notify(void); + +}; + + +extern DmaChannel *DmaChannels[8]; +extern DmaController *DmaControllers[2]; + + + +#endif + diff --git a/include/dos_inc.h b/include/dos_inc.h index 43ba1d1..0100c2c 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -106,6 +106,8 @@ bool DOS_Canonicalize(char * name,char * big); bool DOS_CreateTempFile(char * name,Bit16u * entry); bool DOS_FileExists(char * name); +/* Helper Functions */ +bool DOS_MakeName(char * name,char * fullname,Bit8u * drive); /* Drive Handing Routines */ Bit8u DOS_GetDefaultDrive(void); void DOS_SetDefaultDrive(Bit8u drive); @@ -117,6 +119,7 @@ bool DOS_RemoveDir(char * dir); bool DOS_Rename(char * oldname,char * 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); /* IOCTL Stuff */ bool DOS_IOCTL(void); diff --git a/include/dos_system.h b/include/dos_system.h index 6407218..bd5bfd3 100644 --- a/include/dos_system.h +++ b/include/dos_system.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_system.h,v 1.16 2003/10/09 13:50:27 finsterr Exp $ */ +/* $Id: dos_system.h,v 1.20 2004/01/12 20:25:57 finsterr Exp $ */ #ifndef DOSSYSTEM_H_ #define DOSSYSTEM_H_ @@ -117,6 +117,11 @@ public: class CFileInfo { public: + CFileInfo(void) { + orgname[0] = shortname[0] = 0; + nextEntry = shortNr = compareCount = 0; + isDir = false; + } ~CFileInfo(void) { for (Bit32u i=0; i> 8); }; -INLINE void writed(HostPt off,Bit32u val) { +INLINE void host_writed(HostPt off,Bit32u val) { off[0]=(Bit8u)(val); off[1]=(Bit8u)(val >> 8); off[2]=(Bit8u)(val >> 16); @@ -86,22 +83,22 @@ INLINE void writed(HostPt off,Bit32u val) { #else -INLINE Bit8u readb(HostPt off) { +INLINE Bit8u host_readb(HostPt off) { return *(Bit8u *)off; }; -INLINE Bit16u readw(HostPt off) { +INLINE Bit16u host_readw(HostPt off) { return *(Bit16u *)off; }; -INLINE Bit32u readd(HostPt off) { +INLINE Bit32u host_readd(HostPt off) { return *(Bit32u *)off; }; -INLINE void writeb(HostPt off,Bit8u val) { +INLINE void host_writeb(HostPt off,Bit8u val) { *(Bit8u *)(off)=val; }; -INLINE void writew(HostPt off,Bit16u val) { +INLINE void host_writew(HostPt off,Bit16u val) { *(Bit16u *)(off)=val; }; -INLINE void writed(HostPt off,Bit32u val) { +INLINE void host_writed(HostPt off,Bit32u val) { *(Bit32u *)(off)=val; }; @@ -131,7 +128,6 @@ void phys_writew(PhysPt addr,Bit16u val); void phys_writed(PhysPt addr,Bit32u val); /* These don't check for alignment, better be sure it's correct */ -Bit32u phys_page_readd(Bitu page,Bitu off); void MEM_BlockWrite(PhysPt pt,void * data,Bitu size); void MEM_BlockRead(PhysPt pt,void * data,Bitu size); diff --git a/include/mixer.h b/include/mixer.h index 3144a8b..9309a7f 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/include/mouse.h b/include/mouse.h index 07fce5a..1851f5c 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/include/paging.h b/include/paging.h index 73169bc..4640d17 100644 --- a/include/paging.h +++ b/include/paging.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,49 +22,58 @@ #include "mem.h" class PageDirectory; -struct PageEntry; -struct PageLink; #define MEM_PAGE_SIZE (4096) #define XMS_START (0x110) +#define TLB_SIZE (1024*1024) -enum EntryTypes { //The type of memory contained in this link - ENTRY_VGA, - ENTRY_CHANGES, - ENTRY_INIT, - ENTRY_NA, - ENTRY_ROM, - ENTRY_LFB, - ENTRY_RAM, - ENTRY_ALLOC, -}; +#define PFLAG_READABLE 0x1 +#define PFLAG_WRITEABLE 0x2 +#define PFLAG_HASROM 0x4 +#define PFLAG_HASCODE 0x8 //Page contains dynamic code +#define PFLAG_NOCODE 0x10 //No dynamic code can be generated here +#define PFLAG_INIT 0x20 //No dynamic code can be generated here -enum VGA_RANGES { - VGA_RANGE_A000, - VGA_RANGE_B000, - VGA_RANGE_B800, -}; +#define LINK_START ((1024+64)/4) //Start right after the HMA + +//Allow 128 mb of memory to be linked +#define PAGING_LINKS (128*1024/4) -class PageChange { +class PageHandler { public: - virtual void Changed(PageLink * link,Bitu start,Bitu end)=0; + virtual Bitu readb(PhysPt addr); + virtual Bitu readw(PhysPt addr); + virtual Bitu readd(PhysPt addr); + virtual void writeb(PhysPt addr,Bitu val); + virtual void writew(PhysPt addr,Bitu val); + virtual void writed(PhysPt addr,Bitu val); + virtual HostPt GetHostPt(Bitu phys_page); + Bitu flags; }; /* Some other functions */ void PAGING_Enable(bool enabled); bool PAGING_Enabled(void); -void MEM_CheckLinks(PageEntry * theentry); - -PageDirectory * MEM_DefaultDirectory(void); Bitu PAGING_GetDirBase(void); void PAGING_SetDirBase(Bitu cr3); +void PAGING_InitTLB(void); +void PAGING_ClearTLB(void); -PageLink * MEM_LinkPage(Bitu phys_page,PhysPt lin_base); +void PAGING_LinkPage(Bitu lin_page,Bitu phys_page); +void PAGING_UnlinkPages(Bitu lin_page,Bitu pages); +/* This maps the page directly, only use when paging is disabled */ +void PAGING_MapPage(Bitu lin_page,Bitu phys_page); +bool PAGING_MakePhysPage(Bitu & page); -void MEM_UnlinkPage(PageLink * link); void MEM_SetLFB(Bitu _page,Bitu _pages,HostPt _pt); +void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler); + +Bit32u MEM_PhysReadD(Bitu addr); + + + #pragma pack(1) typedef struct { @@ -87,57 +96,23 @@ union X86PageEntry { X86_PageEntryBlock block; }; -struct PageLink { - HostPt read; - HostPt write; - PageChange * change; - PhysPt lin_base; - PageEntry * entry; - union { - PageDirectory * dir; - Bitu table; - } data; - PageLink * next; -}; - -struct PageEntry { - PageLink * links; - EntryTypes type; - union { - HostPt mem; - PhysPt vga_base; - PageDirectory * dir; - } data; - MemHandle next_handle; -}; - -class PageDirectory { -public: - PageDirectory(); - ~PageDirectory(); - void ClearDirectory(void); - void SetBase(PhysPt page); - void LinkPage(Bitu lin_page,Bitu phys_page); - bool InitPage(Bitu lin_address); - bool InitPageLinear(Bitu lin_address); - void InvalidateTable(Bitu table); - void InvalidateLink(Bitu table,Bitu index); - PageDirectory * next; - PageLink *links[1024*1024]; - PageLink *tables[1024]; - PageLink *link_dir; //Handler for main directory table - PageEntry entry_init; //Handler for pages that need init - PageLink link_init; //Handler for pages that need init - Bit32u base_page; //Base got from CR3 - PageChange * table_change; - PageChange * dir_change; -}; - struct PagingBlock { - PageDirectory * cache; - PageDirectory * dir; - PageLink * free_link; Bitu cr3; + Bitu cr2; + struct { + Bitu page; + PhysPt addr; + } base; + struct { + HostPt read[TLB_SIZE]; + HostPt write[TLB_SIZE]; + PageHandler * handler[TLB_SIZE]; + Bit32u phys_page[TLB_SIZE]; + } tlb; + struct { + Bitu used; + Bit32u entries[PAGING_LINKS]; + } links; bool enabled; }; @@ -145,24 +120,7 @@ extern PagingBlock paging; /* Some support functions */ -static INLINE PageLink * GetPageLink(PhysPt address) { - Bitu index=(address>>12); - return paging.dir->links[index]; -} - -void PAGING_AddFreePageLink(PageLink * link); - -PageLink * PAGING_GetFreePageLink(void); -void MEM_SetupVGA(VGA_RANGES range,HostPt base); - -/* Page Handler functions */ - -Bit8u ENTRY_readb(PageEntry * pentry,PhysPt address); -Bit16u ENTRY_readw(PageEntry * pentry,PhysPt address); -Bit32u ENTRY_readd(PageEntry * pentry,PhysPt address); -void ENTRY_writeb(PageEntry * pentry,PhysPt address,Bit8u val); -void ENTRY_writew(PageEntry * pentry,PhysPt address,Bit16u val); -void ENTRY_writed(PageEntry * pentry,PhysPt address,Bit32u val); +PageHandler * MEM_GetPageHandler(Bitu phys_page); /* Unaligned address handlers */ Bit16u mem_unalignedreadw(PhysPt address); @@ -173,52 +131,51 @@ void mem_unalignedwrited(PhysPt address,Bit32u val); /* Special inlined memory reading/writing */ INLINE Bit8u mem_readb_inline(PhysPt address) { - PageLink * plink=GetPageLink(address); - - if (plink->read) return readb(plink->read+address); - else return ENTRY_readb(plink->entry,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); } INLINE Bit16u mem_readw_inline(PhysPt address) { if (address & 1) return mem_unalignedreadw(address); - PageLink * plink=GetPageLink(address); - if (plink->read) return readw(plink->read+address); - else return ENTRY_readw(plink->entry,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); } INLINE Bit32u mem_readd_inline(PhysPt address) { if (address & 3) return mem_unalignedreadd(address); - PageLink * plink=GetPageLink(address); - if (plink->read) return readd(plink->read+address); - else return ENTRY_readd(plink->entry,address); + Bitu index=(address>>12); + if (paging.tlb.read[index]) return host_readd(paging.tlb.read[index]+address); + else return paging.tlb.handler[index]->readd(address); } INLINE void mem_writeb_inline(PhysPt address,Bit8u val) { - PageLink * plink=GetPageLink(address); + Bitu index=(address>>12); - if (plink->write) writeb(plink->write+address,val); - else ENTRY_writeb(plink->entry,address,val); + if (paging.tlb.write[index]) host_writeb(paging.tlb.write[index]+address,val); + else paging.tlb.handler[index]->writeb(address,val); } INLINE void mem_writew_inline(PhysPt address,Bit16u val) { if (address & 1) {mem_unalignedwritew(address,val);return;} - PageLink * plink=GetPageLink(address); + Bitu index=(address>>12); - if (plink->write) writew(plink->write+address,val); - else ENTRY_writew(plink->entry,address,val); + if (paging.tlb.write[index]) host_writew(paging.tlb.write[index]+address,val); + else paging.tlb.handler[index]->writew(address,val); } INLINE void mem_writed_inline(PhysPt address,Bit32u val) { if (address & 3) {mem_unalignedwrited(address,val);return;} - PageLink * plink=GetPageLink(address); + Bitu index=(address>>12); + if (paging.tlb.write[index]) host_writed(paging.tlb.write[index]+address,val); + else paging.tlb.handler[index]->writed(address,val); - if (plink->write) writed(plink->write+address,val); - else ENTRY_writed(plink->entry,address,val); } #endif diff --git a/include/pic.h b/include/pic.h index d40a5f9..05566d7 100644 --- a/include/pic.h +++ b/include/pic.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,20 +49,20 @@ INLINE Bit64u PIC_MicroCount(void) { return PIC_Ticks*1000+PIC_Index(); } -void PIC_ActivateIRQ(Bit32u irq); +void PIC_ActivateIRQ(Bitu irq); -void PIC_DeActivateIRQ(Bit32u irq); +void PIC_DeActivateIRQ(Bitu irq); void PIC_runIRQs(void); -void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name); -void PIC_FreeIRQ(Bit32u irq); +void PIC_RegisterIRQ(Bitu irq,PIC_EOIHandler handler,char * name); +void PIC_FreeIRQ(Bitu irq); bool PIC_RunQueue(void); -void PIC_AddIRQ(Bitu irq,Bitu delay); void PIC_AddEvent(PIC_EventHandler handler,Bitu delay); void PIC_RemoveEvents(PIC_EventHandler handler); +void PIC_SetIRQMask(Bitu irq, bool masked); #endif diff --git a/include/programs.h b/include/programs.h index 3ce261a..a40090d 100644 --- a/include/programs.h +++ b/include/programs.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/include/regs.h b/include/regs.h index a3a266f..92eb004 100644 --- a/include/regs.h +++ b/include/regs.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,40 +21,33 @@ #include -struct Flag_Info { - union { - Bit8u b; - Bit16u w; - Bit32u d; - } var1,var2,result; - Bitu type; - Bitu prev_type; - Bitu oldcf; - Bitu word; -}; - - #define FLAG_CF 0x00000001 #define FLAG_PF 0x00000004 #define FLAG_AF 0x00000010 #define FLAG_ZF 0x00000040 #define FLAG_SF 0x00000080 +#define FLAG_OF 0x00000800 + #define FLAG_TF 0x00000100 #define FLAG_IF 0x00000200 #define FLAG_DF 0x00000400 -#define FLAG_OF 0x00000800 - -#define FLAG_MASK (FLAG_CF | FLAG_PF | FLAG_AF | FLAG_ZF | FLAG_SF | FLAG_OF) #define FLAG_IOPL 0x00003000 #define FLAG_NT 0x00004000 #define FLAG_VM 0x00020000 +#define FLAG_AC 0x00040000 +#define FLAG_ID 0x00200000 +#define FMASK_TEST (FLAG_CF | FLAG_PF | FLAG_AF | FLAG_ZF | FLAG_SF | FLAG_OF) +#define FMASK_NORMAL (FMASK_TEST | FLAG_DF | FLAG_TF | FLAG_IF | FLAG_AC ) +#define FMASK_ALL (FMASK_NORMAL | FLAG_IOPL | FLAG_NT) -#define SETFLAGBIT(TYPE,TEST) if (TEST) flags.word|=FLAG_ ## TYPE; else flags.word&=~FLAG_ ## TYPE +#define SETFLAGBIT(TYPE,TEST) if (TEST) reg_flags|=FLAG_ ## TYPE; else reg_flags&=~FLAG_ ## TYPE -#define GETFLAG(TYPE) (flags.word & FLAG_ ## TYPE) -#define GETFLAGBOOL(TYPE) ((flags.word & FLAG_ ## TYPE) ? true : false ) +#define GETFLAG(TYPE) (reg_flags & FLAG_ ## TYPE) +#define GETFLAGBOOL(TYPE) ((reg_flags & FLAG_ ## TYPE) ? true : false ) + +#define GETFLAG_IOPL ((reg_flags & FLAG_IOPL) >> 12) struct Segment { Bit16u val; @@ -91,17 +84,13 @@ union GenReg32 { #endif struct CPU_Regs { - GenReg32 regs[8],ip; + GenReg32 regs[8],ip; + Bitu flags; }; extern Segments Segs; -extern Flag_Info flags; extern CPU_Regs cpu_regs; - -//#define SegPhys(index) Segs[index].phys -//#define SegValue(index) Segs[index].val - INLINE PhysPt SegPhys(SegNames index) { return Segs.phys[index]; } @@ -109,7 +98,6 @@ INLINE PhysPt SegPhys(SegNames index) { INLINE Bit16u SegValue(SegNames index) { return Segs.val[index]; } - INLINE RealPt RealMakeSeg(SegNames index,Bit16u off) { return RealMake(SegValue(index),off); @@ -121,7 +109,6 @@ INLINE void SegSet16(Bitu index,Bit16u val) { Segs.phys[index]=val << 4; } - enum { REGI_AX, REGI_CX, REGI_DX, REGI_BX, REGI_SP, REGI_BP, REGI_SI, REGI_DI @@ -140,7 +127,6 @@ enum { #define reg_16(reg) (cpu_regs.regs[(reg)].word[W_INDEX]) #define reg_32(reg) (cpu_regs.regs[(reg)].dword[DW_INDEX]) - #define reg_al cpu_regs.regs[REGI_AX].byte[BL_INDEX] #define reg_ah cpu_regs.regs[REGI_AX].byte[BH_INDEX] #define reg_ax cpu_regs.regs[REGI_AX].word[W_INDEX] @@ -176,5 +162,7 @@ enum { #define reg_ip cpu_regs.ip.word[W_INDEX] #define reg_eip cpu_regs.ip.dword[DW_INDEX] +#define reg_flags cpu_regs.flags + #endif diff --git a/include/render.h b/include/render.h index 2f63708..dd1adfc 100644 --- a/include/render.h +++ b/include/render.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,30 +16,25 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#ifndef __RENDER_H +#define __RENDER_H enum RENDER_Operation { OP_None, OP_Shot, OP_Normal2x, OP_AdvMame2x, - OP_Blit, }; -enum { - DoubleNone= 0x00, - DoubleWidth= 0x01, - DoubleHeight= 0x02, - DoubleBoth= 0x03 -}; - - - -typedef void (* RENDER_Part_Handler)(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy); -typedef void (* RENDER_Draw_Handler)(RENDER_Part_Handler part_handler); - -void RENDER_DoUpdate(void); - -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags,RENDER_Draw_Handler draw_handler); +typedef void (* RENDER_Line_Handler)(Bit8u * src); +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh); +bool RENDER_StartUpdate(void); +void RENDER_EndUpdate(void); void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); +extern RENDER_Line_Handler RENDER_DrawLine; +extern Bit8u * RENDER_TempLine; + + +#endif + diff --git a/include/serialport.h b/include/serialport.h index 1347ac6..386e760 100644 --- a/include/serialport.h +++ b/include/serialport.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/include/setup.h b/include/setup.h index f66b619..ffc9915 100644 --- a/include/setup.h +++ b/include/setup.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: setup.h,v 1.15 2004/01/29 09:26:43 qbix79 Exp $ */ + #ifndef _SETUP_H_ #define _SETUP_H_ @@ -53,6 +55,7 @@ union Value{ bool _bool; int _int; std::string* _string; + float _float; }; class Property { @@ -75,6 +78,15 @@ public: void GetValuestring(char* str); ~Prop_int(){ } }; +class Prop_float:public Property { +public: + Prop_float(const char* _propname, float _value):Property(_propname){ + __value._float=_value; + } + void SetValue(char* input); + void GetValuestring(char* str); + ~Prop_float(){ } +}; class Prop_bool:public Property { public: @@ -143,11 +155,13 @@ class Section_prop:public Section { void Add_string(const char* _propname, char* _value=NULL); void Add_bool(const char* _propname, bool _value=false); void Add_hex(const char* _propname, int _value=0); + void Add_float(const char* _propname, float _value=0.0); int Get_int(const char* _propname); const char* Get_string(const char* _propname); bool Get_bool(const char* _propname); - int Get_hex(const char* _propname); + int Get_hex(const char* _propname); + float Get_float(const char* _propname); void HandleInputline(char *gegevens); void PrintData(FILE* outfile); @@ -180,7 +194,7 @@ public: void ShutDown(); void StartUp(); void PrintConfig(const char* configfilename); - void ParseConfigFile(const char* configfilename); + bool ParseConfigFile(const char* configfilename); void ParseEnv(char ** envp); std::list sectionlist; diff --git a/src/shell/shell_inc.h b/include/shell.h similarity index 94% rename from src/shell/shell_inc.h rename to include/shell.h index fdc8831..cea4638 100644 --- a/src/shell/shell_inc.h +++ b/include/shell.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell_inc.h,v 1.17 2003/09/08 18:19:28 qbix79 Exp $ */ +/* $Id: shell.h,v 1.2 2004/01/10 14:03:33 qbix79 Exp $ */ + +#ifndef SHELL_H_ +#define SHELL_H_ + #include #include @@ -96,6 +100,8 @@ public: void CMD_CALL(char * args); void SyntaxError(void); void CMD_PAUSE(char * args); + void CMD_SUBST(char* args); + void CMD_LOADHIGH(char* args); /* The shell's variables */ Bit16u input_handle; BatchFile * bf; @@ -140,3 +146,4 @@ static inline char* ExpandDot(char*args, char* buffer) } +#endif diff --git a/include/support.h b/include/support.h index 8e26058..1b66334 100644 --- a/include/support.h +++ b/include/support.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,9 @@ //#define nocasestrcmp(a,b) stricmp(a,b) #endif +#ifdef HAVE_STRINGS_H +#include +#endif void strreplace(char * str,char o,char n); char *ltrim(char *str); diff --git a/include/timer.h b/include/timer.h index 6511f93..aada3d5 100644 --- a/include/timer.h +++ b/include/timer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/vga.h b/include/vga.h similarity index 86% rename from src/hardware/vga.h rename to include/vga.h index 51d0edc..b218647 100644 --- a/src/hardware/vga.h +++ b/include/vga.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,8 +23,9 @@ #include "dosbox.h" enum VGAModes { - M_TEXT16, - M_CGA2,M_CGA4, + M_TEXT2,M_TEXT16, + M_HERC, + M_CGA2,M_CGA4,M_CGA16, M_TANDY16, M_EGA2,M_EGA4,M_EGA16, M_VGA, @@ -42,16 +43,6 @@ enum VGAModes { #define S3_CLOCK(_M,_N,_R) ((S3_CLOCK_REF * ((_M) + 2)) / (((_N) + 2) * (1 << (_R)))) #define S3_MAX_CLOCK 150000 /* KHz */ -/* Different functions that should be handle by memory handler */ - -#define MH_ROTATEOP 0x0001; -#define MH_SETRESET 0x0002; -#define MH_BITMASK 0x0004; - - -typedef Bit8u VGA_ReadHandler(PhysPt off); -typedef void VGA_WriteHandler(PhysPt off,Bit8u val); - typedef struct { bool attrindex; } VGA_Internal; @@ -73,18 +64,12 @@ typedef struct { bool chained; /* Enable or Disabled Chain 4 Mode */ bool blinking; /* Attribute bit 7 is blinking */ - bool vline_double; - Bit8u vline_height; - /* Pixel Scrolling */ Bit8u pel_panning; /* Amount of pixels to skip when starting horizontal line */ Bit8u hlines_skip; Bit8u bytes_skip; /* Specific stuff memory write/read handling */ - - VGA_ReadHandler * readhandler; - VGA_WriteHandler * writehandler; Bit8u read_mode; Bit8u write_mode; @@ -106,18 +91,40 @@ typedef struct { typedef struct { bool resizing; + bool drawing; Bitu width; Bitu height; Bitu pitch; - Bitu blank; - bool double_width; - bool double_height; - Bitu lines; + Bitu blocks; + Bitu panning; + Bitu address; + Bitu address_add; + Bitu address_line_total; + Bitu address_line; + Bitu lines_total; + Bitu lines_left; + Bitu lines_scaled; + Bitu split_line; + Bitu parts_total; + Bitu parts_lines; + Bitu parts_left; + struct { + Bitu vtotal; + Bitu vstart; + Bitu vend; + Bitu htotal; + Bitu hstart; + Bitu hend; + Bitu parts; + } micro; + Bitu scaleh; + bool double_scan; + bool double_scan_active; Bit8u font_height; Bit8u font[64*1024]; Bitu font1_start; Bitu font2_start; - Bitu rows,cols; + Bitu blinking; struct { Bit8u sline,eline; Bit8u count,delay; @@ -150,6 +157,12 @@ typedef struct { } VGA_S3; typedef struct { + Bit8u mode_control; + Bit8u enable_bits; +} VGA_HERC; + +typedef struct { + Bit8u mode_control; Bit8u color_select; } VGA_CGA; @@ -157,6 +170,10 @@ typedef struct { Bit8u mem_bank; Bit8u disp_bank; Bit8u reg_index; + Bit8u mode_control1; + Bit8u palette_mask; + Bit8u border_color; + Bit8u mode_control2; } VGA_TANDY; typedef struct { @@ -267,6 +284,7 @@ typedef struct { VGA_Dac dac; VGA_Latch latch; VGA_S3 s3; + VGA_HERC herc; VGA_CGA cga; VGA_TANDY tandy; VGA_Memory mem; @@ -298,12 +316,18 @@ void VGA_SetClock(Bitu which,Bitu target); void VGA_DACSetEntirePalette(void); void VGA_StartRetrace(void); void VGA_StartUpdateLFB(void); +void VGA_SetBlinking(Bitu enabled); extern VGA_Type vga; extern Bit32u ExpandTable[256]; extern Bit32u FillTable[16]; +extern Bit32u CGA_2_Table[16]; extern Bit32u CGA_4_Table[256]; +extern Bit32u CGA_16_Table[256]; +extern Bit32u TXT_Font_Table[16]; +extern Bit32u TXT_FG_Table[16]; +extern Bit32u TXT_BG_Table[16]; extern Bit32u Expand16Table[4][16]; extern Bit32u Expand16BigTable[0x10000]; diff --git a/include/video.h b/include/video.h index 33997cc..ced09ad 100644 --- a/include/video.h +++ b/include/video.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +19,7 @@ #ifndef __VIDEO_H #define __VIDEO_H - -typedef void (* GFX_ModeCallBack)(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags); - -typedef void (* GFX_DrawCallBack)(void * data); +typedef void (* GFX_ResetCallBack)(void); struct GFX_PalEntry { Bit8u r; @@ -31,30 +28,21 @@ struct GFX_PalEntry { Bit8u unused; }; -#define GFX_FIXED_BPP 0x01 -#define GFX_RESIZEABLE 0x02 -#define GFX_SHADOW 0x04 -#define GFX_BLITTING 0x08 - - - -#define MODE_SET 0x01 -#define MODE_FULLSCREEN 0x02 -#define MODE_RESIZE 0x04 +#define GFX_HASSCALING 0x0001 +#define GFX_HASCONVERT 0x0002 void GFX_Events(void); void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries); +Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags); Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue); -void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu flags,GFX_ModeCallBack mode_callback, GFX_DrawCallBack draw_callback); +void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack cb_reset); void GFX_Start(void); void GFX_Stop(void); void GFX_SwitchFullScreen(void); - -void GFX_Render_Blit(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy); - -void GFX_DoUpdate(void); +bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch); +void GFX_EndUpdate(void); #endif diff --git a/src/Makefile.in b/src/Makefile.in index 5ff859c..3094690 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -443,7 +443,7 @@ install-am: all-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -462,7 +462,6 @@ clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) - -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -487,7 +486,6 @@ installcheck-am: installcheck-binPROGRAMS maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) - -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/src/cpu/Makefile.am b/src/cpu/Makefile.am index 6eee892..261369f 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -1,6 +1,7 @@ -SUBDIRS = core_16 core_full core_normal +SUBDIRS = core_full core_normal core_dyn_x86 AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libcpu.a -libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp core_full.cpp instructions.h \ - paging.cpp lazyflags.h core_normal.cpp \ No newline at end of file +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_dyn_x86.cpp \ No newline at end of file diff --git a/src/cpu/Makefile.in b/src/cpu/Makefile.in index 54f19d8..f02809b 100644 --- a/src/cpu/Makefile.in +++ b/src/cpu/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -129,12 +129,13 @@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ -SUBDIRS = core_16 core_full core_normal +SUBDIRS = core_full core_normal core_dyn_x86 AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libcpu.a -libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp core_full.cpp instructions.h \ - paging.cpp lazyflags.h core_normal.cpp +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_dyn_x86.cpp subdir = src/cpu ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -146,17 +147,18 @@ LIBRARIES = $(noinst_LIBRARIES) libcpu_a_AR = $(AR) cru libcpu_a_LIBADD = am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \ - modrm.$(OBJEXT) slow_16.$(OBJEXT) core_full.$(OBJEXT) \ - paging.$(OBJEXT) core_normal.$(OBJEXT) + modrm.$(OBJEXT) core_full.$(OBJEXT) paging.$(OBJEXT) \ + core_normal.$(OBJEXT) core_dyn_x86.$(OBJEXT) libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/callback.Po ./$(DEPDIR)/core_full.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/core_normal.Po ./$(DEPDIR)/cpu.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/flags.Po ./$(DEPDIR)/modrm.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/paging.Po ./$(DEPDIR)/slow_16.Po +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/callback.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/core_dyn_x86.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/core_full.Po ./$(DEPDIR)/core_normal.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/cpu.Po ./$(DEPDIR)/flags.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/modrm.Po ./$(DEPDIR)/paging.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -203,13 +205,13 @@ distclean-compile: -rm -f *.tab.c @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_full.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_normal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flags.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modrm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/paging.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slow_16.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ @@ -419,7 +421,7 @@ install-am: all-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -438,7 +440,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) - -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -463,7 +464,6 @@ installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) - -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index 81ec286..97900ef 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,10 +16,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: callback.cpp,v 1.16 2003/09/29 21:06:49 qbix79 Exp $ */ +/* $Id: callback.cpp,v 1.19 2004/01/07 20:23:48 qbix79 Exp $ */ #include #include +#include #include "dosbox.h" #include "callback.h" @@ -34,6 +35,8 @@ CallBack_Handler CallBack_Handlers[CB_MAX]; +char* CallBack_Description[CB_MAX]; + static Bitu call_stop,call_idle,call_default; static Bitu illegal_handler(void) { @@ -95,9 +98,8 @@ void CALLBACK_RunRealFar(Bit16u seg,Bit16u off) { void CALLBACK_RunRealInt(Bit8u intnum) { Bit32u oldeip=reg_eip; Bit16u oldcs=SegValue(cs); - reg_eip=call_stop<<4; + reg_eip=(CB_MAX*16)+(intnum*6); SegSet16(cs,CB_SEG); - Interrupt(intnum); DOSBOX_RunMachine(); reg_eip=oldeip; SegSet16(cs,oldcs); @@ -117,9 +119,22 @@ void CALLBACK_SCF(bool val) { mem_writew(SegPhys(ss)+reg_sp+4,(tempf | newCF)); }; +void CALLBACK_SetDescription(Bitu nr, const char* descr) +{ + if (descr) { + CallBack_Description[nr] = new char[strlen(descr)+1]; + strcpy(CallBack_Description[nr],descr); + } else + CallBack_Description[nr] = 0; +}; +const char* CALLBACK_GetDescription(Bitu nr) +{ + if (nr>=CB_MAX) return 0; + return CallBack_Description[nr]; +}; -bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type) { +bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr) { if (callback>=CB_MAX) return false; switch (type) { case CB_RETF: @@ -147,10 +162,11 @@ bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type) { } CallBack_Handlers[callback]=handler; + CALLBACK_SetDescription(callback,descr); return true; } -bool CALLBACK_SetupAt(Bitu callback,CallBack_Handler handler,Bitu type,Bitu linearAddress) { +bool CALLBACK_SetupAt(Bitu callback,CallBack_Handler handler,Bitu type,Bitu linearAddress,const char* descr) { if (callback>=CB_MAX) return false; switch (type) { case CB_RETF: @@ -176,6 +192,7 @@ bool CALLBACK_SetupAt(Bitu callback,CallBack_Handler handler,Bitu type,Bitu line E_Exit("CALLBACK:Setup:Illegal type %d",type); } CallBack_Handlers[callback]=handler; + CALLBACK_SetDescription(callback,descr); return true; } @@ -205,7 +222,19 @@ void CALLBACK_Init(Section* sec) { for (i=0;i<0x40;i++) { real_writed(0,i*4,CALLBACK_RealPointer(call_default)); } + /* Setup block of 0xCD 0xxx instructions */ + PhysPt rint_base=CB_BASE+CB_MAX*16; + for (i=0;i<=0xff;i++) { + phys_writeb(rint_base,0xCD); + phys_writeb(rint_base+1,i); + phys_writeb(rint_base+2,0xFE); + phys_writeb(rint_base+3,0x38); + phys_writew(rint_base+4,call_stop); + rint_base+=6; + + } real_writed(0,0x67*4,CALLBACK_RealPointer(call_default)); + real_writed(0,0x5c*4,CALLBACK_RealPointer(call_default)); //Network stuff //real_writed(0,0xf*4,0); some games don't like it } diff --git a/src/cpu/core_16/Makefile.am b/src/cpu/core_16/Makefile.am deleted file mode 100644 index 2971ca9..0000000 --- a/src/cpu/core_16/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ - -noinst_HEADERS = helpers.h main.h prefix_66.h prefix_of.h support.h table_ea.h \ - prefix_66_of.h diff --git a/src/cpu/core_16/helpers.h b/src/cpu/core_16/helpers.h deleted file mode 100644 index 1109984..0000000 --- a/src/cpu/core_16/helpers.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2002 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 Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -#define GetEAa \ - PhysPt eaa=(*lookupEATable)[rm](); - -#define GetRMEAa \ - GetRM; \ - GetEAa; - - -#define RMEbGb(inst) \ - { \ - GetRMrb; \ - if (rm >= 0xc0 ) {GetEArb;inst(*earb,*rmrb,LoadRb,SaveRb);} \ - else {GetEAa;inst(eaa,*rmrb,LoadMb,SaveMb);} \ - } - -#define RMGbEb(inst) \ - { \ - GetRMrb; \ - if (rm >= 0xc0 ) {GetEArb;inst(*rmrb,*earb,LoadRb,SaveRb);} \ - else {GetEAa;inst(*rmrb,LoadMb(eaa),LoadRb,SaveRb);} \ - } - -#define RMEb(inst) \ - { \ - if (rm >= 0xc0 ) {GetEArb;inst(*earb,LoadRb,SaveRb);} \ - else {GetEAa;inst(eaa,LoadMb,SaveMb);} \ - } - -#define RMEwGw(inst) \ - { \ - GetRMrw; \ - if (rm >= 0xc0 ) {GetEArw;inst(*earw,*rmrw,LoadRw,SaveRw);} \ - else {GetEAa;inst(eaa,*rmrw,LoadMw,SaveMw);} \ - } - -#define RMEwGwOp3(inst,op3) \ - { \ - GetRMrw; \ - if (rm >= 0xc0 ) {GetEArw;inst(*earw,*rmrw,op3,LoadRw,SaveRw);} \ - else {GetEAa;inst(eaa,*rmrw,op3,LoadMw,SaveMw);} \ - } - -#define RMGwEw(inst) \ - { \ - GetRMrw; \ - if (rm >= 0xc0 ) {GetEArw;inst(*rmrw,*earw,LoadRw,SaveRw);} \ - else {GetEAa;inst(*rmrw,LoadMw(eaa),LoadRw,SaveRw);} \ - } - -#define RMGwEwOp3(inst,op3) \ - { \ - GetRMrw; \ - if (rm >= 0xc0 ) {GetEArw;inst(*rmrw,*earw,op3,LoadRw,SaveRw);} \ - else {GetEAa;inst(*rmrw,LoadMw(eaa),op3,LoadRw,SaveRw);} \ - } - -#define RMEw(inst) \ - { \ - if (rm >= 0xc0 ) {GetEArw;inst(*earw,LoadRw,SaveRw);} \ - else {GetEAa;inst(eaa,LoadMw,SaveMw);} \ - } - -#define RMEdGd(inst) \ - { \ - GetRMrd; \ - if (rm >= 0xc0 ) {GetEArd;inst(*eard,*rmrd,LoadRd,SaveRd);} \ - else {GetEAa;inst(eaa,*rmrd,LoadMd,SaveMd);} \ - } - -#define RMEdGdOp3(inst,op3) \ - { \ - GetRMrd; \ - if (rm >= 0xc0 ) {GetEArd;inst(*eard,*rmrd,op3,LoadRd,SaveRd);} \ - else {GetEAa;inst(eaa,*rmrd,op3,LoadMd,SaveMd);} \ - } - - -#define RMGdEd(inst) \ - { \ - GetRMrd; \ - if (rm >= 0xc0 ) {GetEArd;inst(*rmrd,*eard,LoadRd,SaveRd);} \ - else {GetEAa;inst(*rmrd,LoadMd(eaa),LoadRd,SaveRd);} \ - } - -#define RMGdEdOp3(inst,op3) \ - { \ - GetRMrd; \ - if (rm >= 0xc0 ) {GetEArd;inst(*rmrd,*eard,op3,LoadRd,SaveRd);} \ - else {GetEAa;inst(*rmrd,LoadMd(eaa),op3,LoadRd,SaveRd);} \ - } - - - - -#define RMEw(inst) \ - { \ - if (rm >= 0xc0 ) {GetEArw;inst(*earw,LoadRw,SaveRw);} \ - else {GetEAa;inst(eaa,LoadMw,SaveMw);} \ - } - -#define RMEd(inst) \ - { \ - if (rm >= 0xc0 ) {GetEArd;inst(*eard,LoadRd,SaveRd);} \ - else {GetEAa;inst(eaa,LoadMd,SaveMd);} \ - } - -#define ALIb(inst) \ - { inst(reg_al,Fetchb(),LoadRb,SaveRb)} - -#define AXIw(inst) \ - { inst(reg_ax,Fetchw(),LoadRw,SaveRw);} - -#define EAXId(inst) \ - { inst(reg_eax,Fetchd(),LoadRd,SaveRd);} - -#define FPU_ESC(code) { \ - Bit8u rm=Fetchb(); \ - if (rm>=0xc0) { \ - FPU_ESC ## code ## _Normal(rm); \ - } else { \ - GetEAa;FPU_ESC ## code ## _EA(rm,eaa); \ - } \ -} - diff --git a/src/cpu/core_16/main.h b/src/cpu/core_16/main.h deleted file mode 100644 index 1bda624..0000000 --- a/src/cpu/core_16/main.h +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * Copyright (C) 2002 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 Library 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. - */ - -restart: - switch(Fetchb()) { - case 0x00: /* ADD Eb,Gb */ - RMEbGb(ADDB);break; - case 0x01: /* ADD Ew,Gw */ - RMEwGw(ADDW);break; - case 0x02: /* ADD Gb,Eb */ - RMGbEb(ADDB);break; - case 0x03: /* ADD Gw,Ew */ - RMGwEw(ADDW);break; - case 0x04: /* ADD AL,Ib */ - ALIb(ADDB);break; - case 0x05: /* ADD AX,Iw */ - AXIw(ADDW);break; - case 0x06: /* PUSH ES */ - Push_16(SegValue(es));break; - case 0x07: /* POP ES */ - SegSet16(es,Pop_16());break; - case 0x08: /* OR Eb,Gb */ - RMEbGb(ORB);break; - case 0x09: /* OR Ew,Gw */ - RMEwGw(ORW);break; - case 0x0a: /* OR Gb,Eb */ - RMGbEb(ORB);break; - case 0x0b: /* OR Gw,Ew */ - RMGwEw(ORW);break; - case 0x0c: /* OR AL,Ib */ - ALIb(ORB);break; - case 0x0d: /* OR AX,Iw */ - AXIw(ORW);break; - case 0x0e: /* PUSH CS */ - Push_16(SegValue(cs));break; - case 0x0f: /* 2 byte opcodes*/ - #include "prefix_of.h" - break; - case 0x10: /* ADC Eb,Gb */ - RMEbGb(ADCB);break; - case 0x11: /* ADC Ew,Gw */ - RMEwGw(ADCW);break; - case 0x12: /* ADC Gb,Eb */ - RMGbEb(ADCB);break; - case 0x13: /* ADC Gw,Ew */ - RMGwEw(ADCW);break; - case 0x14: /* ADC AL,Ib */ - ALIb(ADCB);break; - case 0x15: /* ADC AX,Iw */ - AXIw(ADCW);break; - case 0x16: /* PUSH SS */ - Push_16(SegValue(ss));break; - case 0x17: /* POP SS */ - SegSet16(ss,Pop_16()); - CPU_Cycles++;//Be sure we run another instruction - break; - case 0x18: /* SBB Eb,Gb */ - RMEbGb(SBBB);break; - case 0x19: /* SBB Ew,Gw */ - RMEwGw(SBBW);break; - case 0x1a: /* SBB Gb,Eb */ - RMGbEb(SBBB);break; - case 0x1b: /* SBB Gw,Ew */ - RMGwEw(SBBW);break; - case 0x1c: /* SBB AL,Ib */ - ALIb(SBBB);break; - case 0x1d: /* SBB AX,Iw */ - AXIw(SBBW);break; - case 0x1e: /* PUSH DS */ - Push_16(SegValue(ds));break; - case 0x1f: /* POP DS */ - SegSet16(ds,Pop_16());break; - case 0x20: /* AND Eb,Gb */ - RMEbGb(ANDB);break; - case 0x21: /* AND Ew,Gw */ - RMEwGw(ANDW);break; - case 0x22: /* AND Gb,Eb */ - RMGbEb(ANDB);break; - case 0x23: /* AND Gw,Ew */ - RMGwEw(ANDW);break; - case 0x24: /* AND AL,Ib */ - ALIb(ANDB);break; - case 0x25: /* AND AX,Iw */ - AXIw(ANDW);break; - case 0x26: /* SEG ES: */ - SegPrefix(es);break; - case 0x27: /* DAA */ - DAA(); - break; - case 0x28: /* SUB Eb,Gb */ - RMEbGb(SUBB);break; - case 0x29: /* SUB Ew,Gw */ - RMEwGw(SUBW);break; - case 0x2a: /* SUB Gb,Eb */ - RMGbEb(SUBB);break; - case 0x2b: /* SUB Gw,Ew */ - RMGwEw(SUBW);break; - case 0x2c: /* SUB AL,Ib */ - ALIb(SUBB);break; - case 0x2d: /* SUB AX,Iw */ - AXIw(SUBW);break; - case 0x2e: /* SEG CS: */ - SegPrefix(cs);break; - case 0x2f: /* DAS */ - DAS(); - break; - case 0x30: /* XOR Eb,Gb */ - RMEbGb(XORB);break; - case 0x31: /* XOR Ew,Gw */ - RMEwGw(XORW);break; - case 0x32: /* XOR Gb,Eb */ - RMGbEb(XORB);break; - case 0x33: /* XOR Gw,Ew */ - RMGwEw(XORW);break; - case 0x34: /* XOR AL,Ib */ - ALIb(XORB);break; - case 0x35: /* XOR AX,Iw */ - AXIw(XORW);break; - case 0x36: /* SEG SS: */ - SegPrefix(ss);break; - case 0x37: /* AAA */ - AAA(); - break; - case 0x38: /* CMP Eb,Gb */ - RMEbGb(CMPB);break; - case 0x39: /* CMP Ew,Gw */ - RMEwGw(CMPW);break; - case 0x3a: /* CMP Gb,Eb */ - RMGbEb(CMPB);break; - case 0x3b: /* CMP Gw,Ew */ - RMGwEw(CMPW);break; - case 0x3c: /* CMP AL,Ib */ - ALIb(CMPB);break; - case 0x3d: /* CMP AX,Iw */ - AXIw(CMPW);break; - case 0x3e: /* SEG DS: */ - SegPrefix(ds);break; - case 0x3f: /* AAS */ - AAS(); - break; - case 0x40: /* INC AX */ - INCW(reg_ax,LoadRw,SaveRw);break; - case 0x41: /* INC CX */ - INCW(reg_cx,LoadRw,SaveRw);break; - case 0x42: /* INC DX */ - INCW(reg_dx,LoadRw,SaveRw);break; - case 0x43: /* INC BX */ - INCW(reg_bx,LoadRw,SaveRw);break; - case 0x44: /* INC SP */ - INCW(reg_sp,LoadRw,SaveRw);break; - case 0x45: /* INC BP */ - INCW(reg_bp,LoadRw,SaveRw);break; - case 0x46: /* INC SI */ - INCW(reg_si,LoadRw,SaveRw);break; - case 0x47: /* INC DI */ - INCW(reg_di,LoadRw,SaveRw);break; - case 0x48: /* DEC AX */ - DECW(reg_ax,LoadRw,SaveRw);break; - case 0x49: /* DEC CX */ - DECW(reg_cx,LoadRw,SaveRw);break; - case 0x4a: /* DEC DX */ - DECW(reg_dx,LoadRw,SaveRw);break; - case 0x4b: /* DEC BX */ - DECW(reg_bx,LoadRw,SaveRw);break; - case 0x4c: /* DEC SP */ - DECW(reg_sp,LoadRw,SaveRw);break; - case 0x4d: /* DEC BP */ - DECW(reg_bp,LoadRw,SaveRw);break; - case 0x4e: /* DEC SI */ - DECW(reg_si,LoadRw,SaveRw);break; - case 0x4f: /* DEC DI */ - DECW(reg_di,LoadRw,SaveRw);break; - case 0x50: /* PUSH AX */ - Push_16(reg_ax);break; - case 0x51: /* PUSH CX */ - Push_16(reg_cx);break; - case 0x52: /* PUSH DX */ - Push_16(reg_dx);break; - case 0x53: /* PUSH BX */ - Push_16(reg_bx);break; - case 0x54: /* PUSH SP */ -//TODO Check if this is correct i think it's SP+2 or something - Push_16(reg_sp);break; - case 0x55: /* PUSH BP */ - Push_16(reg_bp);break; - case 0x56: /* PUSH SI */ - Push_16(reg_si);break; - case 0x57: /* PUSH DI */ - Push_16(reg_di);break; - case 0x58: /* POP AX */ - reg_ax=Pop_16();break; - case 0x59: /* POP CX */ - reg_cx=Pop_16();break; - case 0x5a: /* POP DX */ - reg_dx=Pop_16();break; - case 0x5b: /* POP BX */ - reg_bx=Pop_16();break; - case 0x5c: /* POP SP */ - reg_sp=Pop_16();break; - case 0x5d: /* POP BP */ - reg_bp=Pop_16();break; - case 0x5e: /* POP SI */ - reg_si=Pop_16();break; - case 0x5f: /* POP DI */ - reg_di=Pop_16();break; - case 0x60: /* PUSHA */ - { - Bit16u old_sp=reg_sp; - Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx); - Push_16(old_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di); - } - break; - case 0x61: /* POPA */ - reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP - reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16(); - break; - case 0x62: /* BOUND */ - { - Bit16s bound_min, bound_max; - GetRMrw;GetEAa; - bound_min=LoadMw(eaa); - bound_max=LoadMw(eaa+2); - if ( (((Bit16s)*rmrw) < bound_min) || (((Bit16s)*rmrw) > bound_max) ) { - EXCEPTION(5); - } - } - break; - case 0x63: /* ARPL */ - NOTDONE;break; -#ifdef CPU_386 - case 0x64: /* SEG FS: */ - SegPrefix(fs);break; - case 0x65: /* SEG GS: */ - SegPrefix(gs);break; - case 0x66: /* Operand Size Prefix */ - #include "prefix_66.h" - break; - case 0x67: /* Address Size Prefix */ -#ifdef CPU_PREFIX_67 - core_16.prefixes^=PREFIX_ADDR; - lookupEATable=EAPrefixTable[core_16.prefixes]; - goto restart; -#else - NOTDONE; -#endif - break; -#endif - case 0x68: /* PUSH Iw */ - Push_16(Fetchw());break; - case 0x69: /* IMUL Gw,Ew,Iw */ - RMGwEwOp3(DIMULW,Fetchws()); - break; - case 0x6a: /* PUSH Ib */ - Push_16(Fetchbs()); - break; - case 0x6b: /* IMUL Gw,Ew,Ib */ - RMGwEwOp3(DIMULW,Fetchbs()); - break; - case 0x6c: /* INSB */ - { - stringDI; - SaveMb(to,IO_Read(reg_dx)); - if (GETFLAG(DF)) reg_di--; else reg_di++; - break; - } - case 0x6d: /* INSW */ - { - stringDI; - SaveMb(to,IO_Read(reg_dx)); - SaveMb((to+1),IO_Read(reg_dx+1)); - if (GETFLAG(DF)) reg_di-=2; else reg_di+=2; - break; - } - case 0x6e: /* OUTSB */ - { - stringSI; - IO_Write(reg_dx,LoadMb(from)); - if (GETFLAG(DF)) reg_si--; else reg_si++; - break; - } - case 0x6f: /* OUTSW */ - { - stringSI; - IO_Write(reg_dx,LoadMb(from)); - IO_Write(reg_dx+1,LoadMb(from+1)); - if (GETFLAG(DF)) reg_si-=2; else reg_si+=2; - break; - } - case 0x70: /* JO */ - JumpSIb(get_OF());break; - case 0x71: /* JNO */ - JumpSIb(!get_OF());break; - case 0x72: /* JB */ - JumpSIb(get_CF());break; - case 0x73: /* JNB */ - JumpSIb(!get_CF());break; - case 0x74: /* JZ */ - JumpSIb(get_ZF());break; - case 0x75: /* JNZ */ - JumpSIb(!get_ZF()); break; - case 0x76: /* JBE */ - JumpSIb(get_CF() || get_ZF());break; - case 0x77: /* JNBE */ - JumpSIb(!get_CF() && !get_ZF());break; - case 0x78: /* JS */ - JumpSIb(get_SF());break; - case 0x79: /* JNS */ - JumpSIb(!get_SF());break; - case 0x7a: /* JP */ - JumpSIb(get_PF());break; - case 0x7b: /* JNP */ - JumpSIb(!get_PF());break; - case 0x7c: /* JL */ - JumpSIb(get_SF() != get_OF());break; - case 0x7d: /* JNL */ - JumpSIb(get_SF() == get_OF());break; - case 0x7e: /* JLE */ - JumpSIb(get_ZF() || (get_SF() != get_OF()));break; - case 0x7f: /* JNLE */ - JumpSIb((get_SF() == get_OF()) && !get_ZF());break; - case 0x80: /* Grpl Eb,Ib */ - case 0x82: /* Grpl Eb,Ib Mirror instruction*/ - { - GetRM; - if (rm>= 0xc0) { - GetEArb;Bit8u ib=Fetchb(); - switch (rm & 0x38) { - case 0x00:ADDB(*earb,ib,LoadRb,SaveRb);break; - case 0x08: ORB(*earb,ib,LoadRb,SaveRb);break; - case 0x10:ADCB(*earb,ib,LoadRb,SaveRb);break; - case 0x18:SBBB(*earb,ib,LoadRb,SaveRb);break; - case 0x20:ANDB(*earb,ib,LoadRb,SaveRb);break; - case 0x28:SUBB(*earb,ib,LoadRb,SaveRb);break; - case 0x30:XORB(*earb,ib,LoadRb,SaveRb);break; - case 0x38:CMPB(*earb,ib,LoadRb,SaveRb);break; - } - } else { - GetEAa;Bit8u ib=Fetchb(); - switch (rm & 0x38) { - case 0x00:ADDB(eaa,ib,LoadMb,SaveMb);break; - case 0x08: ORB(eaa,ib,LoadMb,SaveMb);break; - case 0x10:ADCB(eaa,ib,LoadMb,SaveMb);break; - case 0x18:SBBB(eaa,ib,LoadMb,SaveMb);break; - case 0x20:ANDB(eaa,ib,LoadMb,SaveMb);break; - case 0x28:SUBB(eaa,ib,LoadMb,SaveMb);break; - case 0x30:XORB(eaa,ib,LoadMb,SaveMb);break; - case 0x38:CMPB(eaa,ib,LoadMb,SaveMb);break; - } - } - break; - } - case 0x81: /* Grpl Ew,Iw */ - { - GetRM; - if (rm>= 0xc0) { - GetEArw;Bit16u iw=Fetchw(); - switch (rm & 0x38) { - case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; - case 0x08: ORW(*earw,iw,LoadRw,SaveRw);break; - case 0x10:ADCW(*earw,iw,LoadRw,SaveRw);break; - case 0x18:SBBW(*earw,iw,LoadRw,SaveRw);break; - case 0x20:ANDW(*earw,iw,LoadRw,SaveRw);break; - case 0x28:SUBW(*earw,iw,LoadRw,SaveRw);break; - case 0x30:XORW(*earw,iw,LoadRw,SaveRw);break; - case 0x38:CMPW(*earw,iw,LoadRw,SaveRw);break; - } - } else { - GetEAa;Bit16u iw=Fetchw(); - switch (rm & 0x38) { - case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; - case 0x08: ORW(eaa,iw,LoadMw,SaveMw);break; - case 0x10:ADCW(eaa,iw,LoadMw,SaveMw);break; - case 0x18:SBBW(eaa,iw,LoadMw,SaveMw);break; - case 0x20:ANDW(eaa,iw,LoadMw,SaveMw);break; - case 0x28:SUBW(eaa,iw,LoadMw,SaveMw);break; - case 0x30:XORW(eaa,iw,LoadMw,SaveMw);break; - case 0x38:CMPW(eaa,iw,LoadMw,SaveMw);break; - } - } - break; - } - case 0x83: /* Grpl Ew,Ix */ - { - GetRM; - if (rm>= 0xc0) { - GetEArw;Bit16u iw=(Bit16s)Fetchbs(); - switch (rm & 0x38) { - case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; - case 0x08: ORW(*earw,iw,LoadRw,SaveRw);break; - case 0x10:ADCW(*earw,iw,LoadRw,SaveRw);break; - case 0x18:SBBW(*earw,iw,LoadRw,SaveRw);break; - case 0x20:ANDW(*earw,iw,LoadRw,SaveRw);break; - case 0x28:SUBW(*earw,iw,LoadRw,SaveRw);break; - case 0x30:XORW(*earw,iw,LoadRw,SaveRw);break; - case 0x38:CMPW(*earw,iw,LoadRw,SaveRw);break; - } - } else { - GetEAa;Bit16u iw=(Bit16s)Fetchbs(); - switch (rm & 0x38) { - case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; - case 0x08: ORW(eaa,iw,LoadMw,SaveMw);break; - case 0x10:ADCW(eaa,iw,LoadMw,SaveMw);break; - case 0x18:SBBW(eaa,iw,LoadMw,SaveMw);break; - case 0x20:ANDW(eaa,iw,LoadMw,SaveMw);break; - case 0x28:SUBW(eaa,iw,LoadMw,SaveMw);break; - case 0x30:XORW(eaa,iw,LoadMw,SaveMw);break; - case 0x38:CMPW(eaa,iw,LoadMw,SaveMw);break; - } - } - break; - } - case 0x84: /* TEST Eb,Gb */ - RMEbGb(TESTB); - break; - case 0x85: /* TEST Ew,Gw */ - RMEwGw(TESTW); - break; - case 0x86: /* XCHG Eb,Gb */ - { - GetRMrb;Bit8u oldrmrb=*rmrb; - if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;*earb=oldrmrb;} - else {GetEAa;*rmrb=LoadMb(eaa);SaveMb(eaa,oldrmrb);} - break; - } - case 0x87: /* XCHG Ew,Gw */ - { - GetRMrw;Bit16u oldrmrw=*rmrw; - if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;*earw=oldrmrw;} - else {GetEAa;*rmrw=LoadMw(eaa);SaveMw(eaa,oldrmrw);} - break; - } - case 0x88: /* MOV Eb,Gb */ - { - GetRMrb; - if (rm >= 0xc0 ) {GetEArb;*earb=*rmrb;} - else {GetEAa;SaveMb(eaa,*rmrb);} - break; - } - case 0x89: /* MOV Ew,Gw */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;*earw=*rmrw;} - else {GetEAa;SaveMw(eaa,*rmrw);} - break; - } - case 0x8a: /* MOV Gb,Eb */ - { - GetRMrb; - if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;} - else {GetEAa;*rmrb=LoadMb(eaa);} - break; - } - case 0x8b: /* MOV Gw,Ew */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} - else {GetEAa;*rmrw=LoadMw(eaa);} - break; - } - case 0x8c: /* Mov Ew,Sw */ - { - GetRM;Bit16u val; - switch (rm & 0x38) { - case 0x00: /* MOV Ew,ES */ - val=SegValue(es);break; - case 0x08: /* MOV Ew,CS */ - val=SegValue(cs);break; - case 0x10: /* MOV Ew,SS */ - val=SegValue(ss);break; - case 0x18: /* MOV Ew,DS */ - val=SegValue(ds);break; - case 0x20: /* MOV Ew,FS */ - val=SegValue(fs);break; - case 0x28: /* MOV Ew,GS */ - val=SegValue(gs);break; - default: - val=0; - E_Exit("CPU:8c:Illegal RM Byte"); - } - if (rm >= 0xc0 ) {GetEArw;*earw=val;} - else {GetEAa;SaveMw(eaa,val);} - break; - } - case 0x8d: /* LEA */ - { - core_16.segbase=0; - core_16.prefixes|=PREFIX_SEG; - lookupEATable=EAPrefixTable[core_16.prefixes]; - GetRMrw;GetEAa; - *rmrw=(Bit16u)eaa; - break; - } - case 0x8e: /* MOV Sw,Ew */ - { - GetRM;Bit16u val; - if (rm >= 0xc0 ) {GetEArw;val=*earw;} - else {GetEAa;val=LoadMw(eaa);} - switch (rm & 0x38) { - case 0x00: /* MOV ES,Ew */ - SegSet16(es,val);break; - case 0x08: /* MOV CS,Ew Illegal*/ - E_Exit("CPU:Illegal MOV CS Call"); - break; - case 0x10: /* MOV SS,Ew */ - SegSet16(ss,val); - CPU_Cycles++;//Be sure we run another instruction - break; - case 0x18: /* MOV DS,Ew */ - SegSet16(ds,val);break; - case 0x20: /* MOV FS,Ew */ - SegSet16(fs,val);break; - case 0x28: /* MOV GS,Ew */ - SegSet16(gs,val);break; - default: - E_Exit("CPU:8e:Illegal RM Byte"); - } - break; - } - case 0x8f: /* POP Ew */ - { - GetRM; - if (rm >= 0xc0 ) {GetEArw;*earw=Pop_16();} - else {GetEAa;SaveMw(eaa,Pop_16());} - break; - } - case 0x90: /* NOP */ - break; - case 0x91: /* XCHG CX,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_cx;reg_cx=temp; } - break; - case 0x92: /* XCHG DX,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_dx;reg_dx=temp; } - break; - case 0x93: /* XCHG BX,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_bx;reg_bx=temp; } - break; - case 0x94: /* XCHG SP,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_sp;reg_sp=temp; } - break; - case 0x95: /* XCHG BP,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_bp;reg_bp=temp; } - break; - case 0x96: /* XCHG SI,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_si;reg_si=temp; } - break; - case 0x97: /* XCHG DI,AX */ - { Bit16u temp=reg_ax;reg_ax=reg_di;reg_di=temp; } - break; - case 0x98: /* CBW */ - reg_ax=(Bit8s)reg_al;break; - case 0x99: /* CWD */ - if (reg_ax & 0x8000) reg_dx=0xffff; - else reg_dx=0; - break; - case 0x9a: /* CALL Ap */ - { - Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); - Push_16(SegValue(cs));Push_16(GETIP); - SegSet16(cs,newcs);SETIP(newip); - break; - } - case 0x9b: /* WAIT */ - break; /* No waiting here */ - case 0x9c: /* PUSHF */ - FillFlags(); - Push_16(flags.word); - break; - case 0x9d: /* POPF */ - SETFLAGSw(Pop_16()); - CheckTF(); -#ifdef CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; -#endif - break; - case 0x9e: /* SAHF */ - SETFLAGSb(reg_ah); - break; - case 0x9f: /* LAHF */ - { - FillFlags(); - reg_ah=(Bit8u)flags.word; - break; - } - case 0xa0: /* MOV AL,Ob */ - { - reg_al=LoadMb(GetEADirect[core_16.prefixes]()); - } - break; - case 0xa1: /* MOV AX,Ow */ - { - reg_ax=LoadMw(GetEADirect[core_16.prefixes]()); - } - break; - case 0xa2: /* MOV Ob,AL */ - { - SaveMb(GetEADirect[core_16.prefixes](),reg_al); - } - break; - case 0xa3: /* MOV Ow,AX */ - { - SaveMw(GetEADirect[core_16.prefixes](),reg_ax); - } - break; - case 0xa4: /* MOVSB */ - { - stringSI;stringDI; - SaveMb(to,LoadMb(from));; - if (GETFLAG(DF)) { reg_si--;reg_di--; } - else {reg_si++;reg_di++;} - break; - } - case 0xa5: /* MOVSW */ - { - stringSI;stringDI; - SaveMw(to,LoadMw(from)); - if (GETFLAG(DF)) { reg_si-=2;reg_di-=2; } - else {reg_si+=2;reg_di+=2;} - break; - } - case 0xa6: /* CMPSB */ - { - stringSI;stringDI; - CMPB(from,LoadMb(to),LoadMb,0); - if (GETFLAG(DF)) { reg_si--;reg_di--; } - else {reg_si++;reg_di++;} - break; - } - case 0xa7: /* CMPSW */ - { - stringSI;stringDI; - CMPW(from,LoadMw(to),LoadMw,0); - if (GETFLAG(DF)) { reg_si-=2;reg_di-=2; } - else {reg_si+=2;reg_di+=2;} - break; - } - case 0xa8: /* TEST AL,Ib */ - ALIb(TESTB);break; - case 0xa9: /* TEST AX,Iw */ - AXIw(TESTW);break; - case 0xaa: /* STOSB */ - { - stringDI; - SaveMb(to,reg_al); - if (GETFLAG(DF)) { reg_di--; } - else {reg_di++;} - break; - } - case 0xab: /* STOSW */ - { - stringDI; - SaveMw(to,reg_ax); - if (GETFLAG(DF)) { reg_di-=2; } - else {reg_di+=2;} - break; - } - case 0xac: /* LODSB */ - { - stringSI; - reg_al=LoadMb(from); - if (GETFLAG(DF)) { reg_si--; } - else {reg_si++;} - break; - } - case 0xad: /* LODSW */ - { - stringSI; - reg_ax=LoadMw(from); - if (GETFLAG(DF)) { reg_si-=2;} - else {reg_si+=2;} - break; - } - case 0xae: /* SCASB */ - { - stringDI; - CMPB(reg_al,LoadMb(to),LoadRb,0); - if (GETFLAG(DF)) { reg_di--; } - else {reg_di++;} - break; - } - case 0xaf: /* SCASW */ - { - stringDI; - CMPW(reg_ax,LoadMw(to),LoadRw,0); - if (GETFLAG(DF)) { reg_di-=2; } - else {reg_di+=2;} - break; - } - case 0xb0: /* MOV AL,Ib */ - reg_al=Fetchb();break; - case 0xb1: /* MOV CL,Ib */ - reg_cl=Fetchb();break; - case 0xb2: /* MOV DL,Ib */ - reg_dl=Fetchb();break; - case 0xb3: /* MOV BL,Ib */ - reg_bl=Fetchb();break; - case 0xb4: /* MOV AH,Ib */ - reg_ah=Fetchb();break; - case 0xb5: /* MOV CH,Ib */ - reg_ch=Fetchb();break; - case 0xb6: /* MOV DH,Ib */ - reg_dh=Fetchb();break; - case 0xb7: /* MOV BH,Ib */ - reg_bh=Fetchb();break; - case 0xb8: /* MOV AX,Iw */ - reg_ax=Fetchw();break; - case 0xb9: /* MOV CX,Iw */ - reg_cx=Fetchw();break; - case 0xba: /* MOV DX,Iw */ - reg_dx=Fetchw();break; - case 0xbb: /* MOV BX,Iw */ - reg_bx=Fetchw();break; - case 0xbc: /* MOV SP,Iw */ - reg_sp=Fetchw();break; - case 0xbd: /* MOV BP.Iw */ - reg_bp=Fetchw();break; - case 0xbe: /* MOV SI,Iw */ - reg_si=Fetchw();break; - case 0xbf: /* MOV DI,Iw */ - reg_di=Fetchw();break; - case 0xc0: /* GRP2 Eb,Ib */ - GRP2B(Fetchb());break; - case 0xc1: /* GRP2 Ew,Ib */ - GRP2W(Fetchb());break; - case 0xc2: /* RETN Iw */ - { - Bit16u addsp=Fetchw(); - SETIP(Pop_16());reg_sp+=addsp; - break; - } - case 0xc3: /* RETN */ - SETIP(Pop_16()); - break; - case 0xc4: /* LES */ - { - GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SegSet16(es,LoadMw(eaa+2)); - break; - } - case 0xc5: /* LDS */ - { - GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SegSet16(ds,LoadMw(eaa+2)); - break; - } - case 0xc6: /* MOV Eb,Ib */ - { - GetRM; - if (rm>0xc0) {GetEArb;*earb=Fetchb();} - else {GetEAa;SaveMb(eaa,Fetchb());} - break; - } - case 0xc7: /* MOV EW,Iw */ - { - GetRM; - if (rm>0xc0) {GetEArw;*earw=Fetchw();} - else {GetEAa;SaveMw(eaa,Fetchw());} - break; - } - case 0xc8: /* ENTER Iw,Ib */ - { - Bit16u bytes=Fetchw();Bit8u level=Fetchb(); - Push_16(reg_bp);reg_bp=reg_sp;reg_sp-=bytes; - PhysPt reader=SegBase(ss)+reg_bp; - for (Bit8u i=1;i>3) { - case 0x00: /* TEST Eb,Ib */ - case 0x01: /* TEST Eb,Ib Undocumented*/ - { - if (rm >= 0xc0 ) {GetEArb;TESTB(*earb,Fetchb(),LoadRb,0)} - else {GetEAa;TESTB(eaa,Fetchb(),LoadMb,0);} - break; - } - case 0x02: /* NOT Eb */ - { - if (rm >= 0xc0 ) {GetEArb;*earb=~*earb;} - else {GetEAa;SaveMb(eaa,~LoadMb(eaa));} - break; - } - case 0x03: /* NEG Eb */ - { - flags.type=t_NEGb; - if (rm >= 0xc0 ) { - GetEArb;flags.var1.b=*earb;flags.result.b=0-flags.var1.b; - *earb=flags.result.b; - } else { - GetEAa;flags.var1.b=LoadMb(eaa);flags.result.b=0-flags.var1.b; - SaveMb(eaa,flags.result.b); - } - break; - } - case 0x04: /* MUL AL,Eb */ - RMEb(MULB); - break; - case 0x05: /* IMUL AL,Eb */ - RMEb(IMULB); - break; - case 0x06: /* DIV Eb */ - RMEb(DIVB); - break; - case 0x07: /* IDIV Eb */ - RMEb(IDIVB); - break; - } - break; - } - case 0xf7: /* GRP3 Ew(,Iw) */ - { GetRM; - switch ((rm & 0x38)>>3) { - case 0x00: /* TEST Ew,Iw */ - case 0x01: /* TEST Ew,Iw Undocumented*/ - { - if (rm >= 0xc0 ) {GetEArw;TESTW(*earw,Fetchw(),LoadRw,SaveRw);} - else {GetEAa;TESTW(eaa,Fetchw(),LoadMw,SaveMw);} - break; - } - case 0x02: /* NOT Ew */ - { - if (rm >= 0xc0 ) {GetEArw;*earw=~*earw;} - else {GetEAa;SaveMw(eaa,~LoadMw(eaa));} - break; - } - case 0x03: /* NEG Ew */ - { - flags.type=t_NEGw; - if (rm >= 0xc0 ) { - GetEArw;flags.var1.w=*earw;flags.result.w=0-flags.var1.w; - *earw=flags.result.w; - } else { - GetEAa;flags.var1.w=LoadMw(eaa);flags.result.w=0-flags.var1.w; - SaveMw(eaa,flags.result.w); - } - break; - } - case 0x04: /* MUL AX,Ew */ - RMEw(MULW); - break; - case 0x05: /* IMUL AX,Ew */ - RMEw(IMULW) - break; - case 0x06: /* DIV Ew */ - RMEw(DIVW) - break; - case 0x07: /* IDIV Ew */ - RMEw(IDIVW) - break; - } - break; - } - case 0xf8: /* CLC */ - SETFLAGBIT(CF,false); - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; - break; - case 0xf9: /* STC */ - SETFLAGBIT(CF,true); - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; - break; - case 0xfa: /* CLI */ - SETFLAGBIT(IF,false); - break; - case 0xfb: /* STI */ - SETFLAGBIT(IF,true); -#ifdef CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; -#endif - break; - case 0xfc: /* CLD */ - SETFLAGBIT(DF,false); - break; - case 0xfd: /* STD */ - SETFLAGBIT(DF,true); - break; - case 0xfe: /* GRP4 Eb */ - { - GetRM; - switch (rm & 0x38) { - case 0x00: /* INC Eb */ - RMEb(INCB); - break; - case 0x08: /* DEC Eb */ - RMEb(DECB); - break; - case 0x38: /* CallBack */ - { - Bitu cb=Fetchw(); - LEAVECORE; - return cb; - } - - default: - E_Exit("Illegal GRP4 Call %d",(rm>>3) & 7); - break; - } - break; - } - case 0xff: /* GRP5 Ew */ - { - GetRM; - switch (rm & 0x38) { - case 0x00: /* INC Ew */ - RMEw(INCW); - break; - case 0x08: /* DEC Ew */ - RMEw(DECW); - break; - case 0x10: /* CALL Ev */ - if (rm >= 0xc0 ) {GetEArw;Push_16(GETIP);SETIP(*earw);} - else {GetEAa;Push_16(GETIP);SETIP(LoadMw(eaa));} - break; - case 0x18: /* CALL Ep */ - { - Push_16(SegValue(cs)); - GetEAa;Push_16(GETIP); - Bit16u newip=LoadMw(eaa); - Bit16u newcs=LoadMw(eaa+2); - SegSet16(cs,newcs); - SETIP(newip); - } - break; - case 0x20: /* JMP Ev */ - if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);} - else {GetEAa;SETIP(LoadMw(eaa));} - break; - case 0x28: /* JMP Ep */ - { - GetEAa; - Bit16u newip=LoadMw(eaa); - Bit16u newcs=LoadMw(eaa+2); - SegSet16(cs,newcs); - SETIP(newip); - } - break; - case 0x30: /* PUSH Ev */ - if (rm >= 0xc0 ) {GetEArw;Push_16(*earw);} - else {GetEAa;Push_16(LoadMw(eaa));} - break; - default: - E_Exit("CPU:GRP5:Illegal Call %2X",rm & 0x38); - break; - } - break; - } - default: - NOTDONE; - break; - } - diff --git a/src/cpu/core_16/prefix_66.h b/src/cpu/core_16/prefix_66.h deleted file mode 100644 index 47ee3d6..0000000 --- a/src/cpu/core_16/prefix_66.h +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (C) 2002 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 Library 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. - */ - -restart_66: -switch(Fetchb()) { - case 0x01: /* ADD Ed,Gd */ - RMEdGd(ADDD);break; - case 0x03: /* ADD Gd,Ed */ - RMGdEd(ADDD);break; - case 0x05: /* ADD EAX,Id */ - EAXId(ADDD);break; - case 0x09: /* OR Ed,Gd */ - RMEdGd(ORD);break; - case 0x0b: /* OR Gd,Ed */ - RMGdEd(ORD);break; - case 0x0d: /* OR EAX,Id */ - EAXId(ORD);break; - case 0x0f: /* 2 Byte opcodes */ -#include "prefix_66_of.h" - break; - case 0x11: /* ADC Ed,Gd */ - RMEdGd(ADCD);break; - case 0x13: /* ADC Gd,Ed */ - RMGdEd(ADCD);break; - case 0x15: /* ADC EAX,Id */ - EAXId(ADCD);break; - case 0x19: /* SBB Ed,Gd */ - RMEdGd(SBBD);break; - case 0x1b: /* SBB Gd,Ed */ - RMGdEd(SBBD);break; - case 0x1d: /* SBB EAX,Id */ - EAXId(SBBD);break; - case 0x21: /* AND Ed,Gd */ - RMEdGd(ANDD);break; - case 0x23: /* AND Gd,Ed */ - RMGdEd(ANDD);break; - case 0x25: /* AND EAX,Id */ - EAXId(ANDD);break; - case 0x29: /* SUB Ed,Gd */ - RMEdGd(SUBD);break; - case 0x2b: /* SUB Gd,Ed */ - RMGdEd(SUBD);break; - case 0x2d: /* SUB EAX,Id */ - EAXId(SUBD);break; - case 0x31: /* XOR Ed,Gd */ - RMEdGd(XORD);break; - case 0x33: /* XOR Gd,Ed */ - RMGdEd(XORD);break; - case 0x35: /* XOR EAX,Id */ - EAXId(XORD);break; - case 0x39: /* CMP Ed,Gd */ - RMEdGd(CMPD);break; - case 0x3b: /* CMP Gd,Ed */ - RMGdEd(CMPD);break; - case 0x3d: /* CMP EAX,Id */ - EAXId(CMPD);break; - case 0x26: /* SEG ES: */ - SegPrefix_66(es);break; - case 0x2e: /* SEG CS: */ - SegPrefix_66(cs);break; - case 0x36: /* SEG SS: */ - SegPrefix_66(ss);break; - case 0x3e: /* SEG DS: */ - SegPrefix_66(ds);break; - case 0x40: /* INC EAX */ - INCD(reg_eax,LoadRd,SaveRd);break; - case 0x41: /* INC ECX */ - INCD(reg_ecx,LoadRd,SaveRd);break; - case 0x42: /* INC EDX */ - INCD(reg_edx,LoadRd,SaveRd);break; - case 0x43: /* INC EBX */ - INCD(reg_ebx,LoadRd,SaveRd);break; - case 0x44: /* INC ESP */ - INCD(reg_esp,LoadRd,SaveRd);break; - case 0x45: /* INC EBP */ - INCD(reg_ebp,LoadRd,SaveRd);break; - case 0x46: /* INC ESI */ - INCD(reg_esi,LoadRd,SaveRd);break; - case 0x47: /* INC EDI */ - INCD(reg_edi,LoadRd,SaveRd);break; - case 0x48: /* DEC EAX */ - DECD(reg_eax,LoadRd,SaveRd);break; - case 0x49: /* DEC ECX */ - DECD(reg_ecx,LoadRd,SaveRd);break; - case 0x4a: /* DEC EDX */ - DECD(reg_edx,LoadRd,SaveRd);break; - case 0x4b: /* DEC EBX */ - DECD(reg_ebx,LoadRd,SaveRd);break; - case 0x4c: /* DEC ESP */ - DECD(reg_esp,LoadRd,SaveRd);break; - case 0x4d: /* DEC EBP */ - DECD(reg_ebp,LoadRd,SaveRd);break; - case 0x4e: /* DEC ESI */ - DECD(reg_esi,LoadRd,SaveRd);break; - case 0x4f: /* DEC EDI */ - DECD(reg_edi,LoadRd,SaveRd);break; - case 0x50: /* PUSH EAX */ - Push_32(reg_eax);break; - case 0x51: /* PUSH ECX */ - Push_32(reg_ecx);break; - case 0x52: /* PUSH EDX */ - Push_32(reg_edx);break; - case 0x53: /* PUSH EBX */ - Push_32(reg_ebx);break; - case 0x54: /* PUSH ESP */ - Push_32(reg_esp);break; - case 0x55: /* PUSH EBP */ - Push_32(reg_ebp);break; - case 0x56: /* PUSH ESI */ - Push_32(reg_esi);break; - case 0x57: /* PUSH EDI */ - Push_32(reg_edi);break; - case 0x58: /* POP EAX */ - reg_eax=Pop_32();break; - case 0x59: /* POP ECX */ - reg_ecx=Pop_32();break; - case 0x5a: /* POP EDX */ - reg_edx=Pop_32();break; - case 0x5b: /* POP EBX */ - reg_ebx=Pop_32();break; - case 0x5c: /* POP ESP */ - reg_esp=Pop_32();break; - case 0x5d: /* POP EBP */ - reg_ebp=Pop_32();break; - case 0x5e: /* POP ESI */ - reg_esi=Pop_32();break; - case 0x5f: /* POP EDI */ - reg_edi=Pop_32();break; - case 0x60: /* PUSHAD */ - Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx); - Push_32(reg_esp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi); - break; - case 0x61: /* POPAD */ - reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP - reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); - break; - case 0x64: /* SEG FS: */ - SegPrefix_66(fs);break; - case 0x65: /* SEG GS: */ - SegPrefix_66(gs);break; - case 0x67: /* Address Size Prefix */ -#ifdef CPU_PREFIX_67 - core_16.prefixes^=PREFIX_ADDR; - lookupEATable=EAPrefixTable[core_16.prefixes]; - goto restart_66; -#else - NOTDONE; -#endif - case 0x68: /* PUSH Id */ - Push_32(Fetchd());break; - case 0x69: /* IMUL Gd,Ed,Id */ - RMGdEdOp3(DIMULD,Fetchds()); - break; - case 0x6a: /* PUSH Ib */ - Push_32(Fetchbs());break; - case 0x6b: /* IMUL Gd,Ed,Ib */ - RMGdEdOp3(DIMULD,Fetchbs()); - break; - case 0x81: /* Grpl Ed,Id */ - { - GetRM; - if (rm>= 0xc0) { - GetEArd;Bit32u id=Fetchd(); - switch (rm & 0x38) { - case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; - case 0x08: ORD(*eard,id,LoadRd,SaveRd);break; - case 0x10:ADCD(*eard,id,LoadRd,SaveRd);break; - case 0x18:SBBD(*eard,id,LoadRd,SaveRd);break; - case 0x20:ANDD(*eard,id,LoadRd,SaveRd);break; - case 0x28:SUBD(*eard,id,LoadRd,SaveRd);break; - case 0x30:XORD(*eard,id,LoadRd,SaveRd);break; - case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break; - } - } else { - GetEAa;Bit32u id=Fetchd(); - switch (rm & 0x38) { - case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; - case 0x08: ORD(eaa,id,LoadMd,SaveMd);break; - case 0x10:ADCD(eaa,id,LoadMd,SaveMd);break; - case 0x18:SBBD(eaa,id,LoadMd,SaveMd);break; - case 0x20:ANDD(eaa,id,LoadMd,SaveMd);break; - case 0x28:SUBD(eaa,id,LoadMd,SaveMd);break; - case 0x30:XORD(eaa,id,LoadMd,SaveMd);break; - case 0x38:CMPD(eaa,id,LoadMd,SaveMd);break; - } - } - } - break; - case 0x83: /* Grpl Ed,Ix */ - { - GetRM; - if (rm>= 0xc0) { - GetEArd;Bit32u id=(Bit32s)Fetchbs(); - switch (rm & 0x38) { - case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; - case 0x08: ORD(*eard,id,LoadRd,SaveRd);break; - case 0x10:ADCD(*eard,id,LoadRd,SaveRd);break; - case 0x18:SBBD(*eard,id,LoadRd,SaveRd);break; - case 0x20:ANDD(*eard,id,LoadRd,SaveRd);break; - case 0x28:SUBD(*eard,id,LoadRd,SaveRd);break; - case 0x30:XORD(*eard,id,LoadRd,SaveRd);break; - case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break; - } - } else { - GetEAa;Bit32u id=(Bit32s)Fetchbs(); - switch (rm & 0x38) { - case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; - case 0x08: ORD(eaa,id,LoadMd,SaveMd);break; - case 0x10:ADCD(eaa,id,LoadMd,SaveMd);break; - case 0x18:SBBD(eaa,id,LoadMd,SaveMd);break; - case 0x20:ANDD(eaa,id,LoadMd,SaveMd);break; - case 0x28:SUBD(eaa,id,LoadMd,SaveMd);break; - case 0x30:XORD(eaa,id,LoadMd,SaveMd);break; - case 0x38:CMPD(eaa,id,LoadMd,SaveMd);break; - } - } - } - break; - case 0x85: /* TEST Ed,Gd */ - RMEdGd(TESTD);break; - case 0x87: /* XCHG Ev,Gv */ - { - GetRMrd;Bit32u oldrmrd=*rmrd; - if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard=oldrmrd;} - else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,oldrmrd);} - break; - } - case 0x89: /* MOV Ed,Gd */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArd;*eard=*rmrd;} - else {GetEAa;SaveMd(eaa,*rmrd);} - break; - } - case 0x8b: /* MOV Gd,Ed */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;} - else {GetEAa;*rmrd=LoadMd(eaa);} - break; - } - case 0x8c: - LOG(LOG_CPU,LOG_NORMAL)("CPU:66:8c looped back"); - break; - case 0x8d: /* LEA */ - { - core_16.segbase=0; - core_16.prefixes|=PREFIX_SEG; - lookupEATable=EAPrefixTable[core_16.prefixes]; - GetRMrd;GetEAa; - *rmrd=(Bit32u)eaa; - break; - } - case 0x8f: /* POP Ed */ - { - GetRM; - if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();} - else {GetEAa;SaveMd(eaa,Pop_32());} - break; - } - case 0x90: /* NOP */ - break; - case 0x91: /* XCHG ECX,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_ecx;reg_ecx=temp; } - break; - case 0x92: /* XCHG EDX,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_edx;reg_edx=temp; } - break; - case 0x93: /* XCHG EBX,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_ebx;reg_ebx=temp; } - break; - case 0x94: /* XCHG ESP,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_esp;reg_esp=temp; } - break; - case 0x95: /* XCHG EBP,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_ebp;reg_ebp=temp; } - break; - case 0x96: /* XCHG ESI,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_esi;reg_esi=temp; } - break; - case 0x97: /* XCHG EDI,EAX */ - { Bit32u temp=reg_eax;reg_eax=reg_edi;reg_edi=temp; } - break; - case 0x98: /* CWD */ - reg_eax=(Bit16s)reg_ax;break; - case 0x99: /* CDQ */ - if (reg_eax & 0x80000000) reg_edx=0xffffffff; - else reg_edx=0; - break; - case 0x9c: /* PUSHFD */ - FillFlags(); - Push_32(flags.word); - break; - case 0x9d: /* POPFD */ - SETFLAGSd(Pop_32()) - CheckTF(); -#ifdef CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; -#endif - break; - case 0xa1: /* MOV EAX,Ow */ - reg_eax=LoadMd(GetEADirect[core_16.prefixes]()); - break; - case 0xa3: /* MOV Ow,EAX */ - SaveMd(GetEADirect[core_16.prefixes](),reg_eax); - break; - case 0xa5: /* MOVSD */ - { - stringSI;stringDI;SaveMd(to,LoadMd(from)); - if (GETFLAG(DF)) { reg_si-=4;reg_di-=4; } - else { reg_si+=4;reg_di+=4;} - } - break; - case 0xa7: /* CMPSD */ - { - stringSI;stringDI; CMPD(to,LoadMd(from),LoadMd,0); - if (GETFLAG(DF)) { reg_si-=4;reg_di-=4; } - else { reg_si+=4;reg_di+=4;} - } - break; - case 0xa9: /* TEST EAX,Id */ - EAXId(TESTD); - break; - case 0xab: /* STOSD */ - { - stringDI; - SaveMd(to,reg_eax); - if (GETFLAG(DF)) { reg_di-=4; } - else {reg_di+=4;} - break; - } - case 0xad: /* LODSD */ - { - stringSI; - reg_eax=LoadMd(from); - if (GETFLAG(DF)) { reg_si-=4;} - else {reg_si+=4;} - break; - } - case 0xaf: /* SCASD */ - { - stringDI; - CMPD(reg_eax,LoadMd(to),LoadRd,0); - if (GETFLAG(DF)) { reg_di-=4; } - else {reg_di+=4;} - break; - } - case 0xb8: /* MOV EAX,Id */ - reg_eax=Fetchd();break; - case 0xb9: /* MOV ECX,Id */ - reg_ecx=Fetchd();break; - case 0xba: /* MOV EDX,Iw */ - reg_edx=Fetchd();break; - case 0xbb: /* MOV EBX,Id */ - reg_ebx=Fetchd();break; - case 0xbc: /* MOV ESP,Id */ - reg_esp=Fetchd();break; - case 0xbd: /* MOV EBP.Id */ - reg_ebp=Fetchd();break; - case 0xbe: /* MOV ESI,Id */ - reg_esi=Fetchd();break; - case 0xbf: /* MOV EDI,Id */ - reg_edi=Fetchd();break; - case 0xc1: /* GRP2 Ed,Ib */ - GRP2D(Fetchb());break; - case 0xc4: /* LES */ - { - GetRMrd;GetEAa; - *rmrd=LoadMd(eaa);SegSet16(es,LoadMw(eaa+4)); - break; - } - case 0xc5: /* LDS */ - { - GetRMrd;GetEAa; - *rmrd=LoadMd(eaa);SegSet16(ds,LoadMw(eaa+4)); - break; - } - case 0xc7: /* MOV Ed,Id */ - { - GetRM; - if (rm>0xc0) {GetEArd;*eard=Fetchd();} - else {GetEAa;SaveMd(eaa,Fetchd());} - break; - } - case 0xd1: /* GRP2 Ed,1 */ - GRP2D(1);break; - case 0xd3: /* GRP2 Ed,CL */ - GRP2D(reg_cl);break; - case 0xed: /* IN EAX,DX */ - reg_eax=IO_Read(reg_dx) | - (IO_Read(reg_dx+1) << 8) | - (IO_Read(reg_dx+2) << 16) | - (IO_Read(reg_dx+3) << 24); - break; - case 0xef: /* OUT DX,EAX */ - IO_Write(reg_dx,(Bit8u)(reg_eax>>0)); - IO_Write(reg_dx+1,(Bit8u)(reg_eax>>8)); - IO_Write(reg_dx+2,(Bit8u)(reg_eax>>16)); - IO_Write(reg_dx+3,(Bit8u)(reg_eax>>24)); - break; - case 0xf2: /* REPNZ */ - Repeat_Normal(false,true); - continue; - case 0xf3: /* REPZ */ - Repeat_Normal(true,true); - continue; - case 0xf7: /* GRP3 Ed(,Id) */ - { - GetRM; - switch ((rm & 0x38)>>3) { - case 0x00: /* TEST Ed,Id */ - case 0x01: /* TEST Ed,Id Undocumented*/ - { - if (rm >= 0xc0 ) {GetEArd;TESTD(*eard,Fetchd(),LoadRd,SaveRd);} - else {GetEAa;TESTD(eaa,Fetchd(),LoadMd,SaveMd);} - break; - } - case 0x02: /* NOT Ed */ - { - if (rm >= 0xc0 ) {GetEArd;*eard=~*eard;} - else {GetEAa;SaveMd(eaa,~LoadMd(eaa));} - break; - } - case 0x03: /* NEG Ed */ - { - flags.type=t_NEGd; - if (rm >= 0xc0 ) { - GetEArd;flags.var1.d=*eard;flags.result.d=0-flags.var1.d; - *eard=flags.result.d; - } else { - GetEAa;flags.var1.d=LoadMd(eaa);flags.result.d=0-flags.var1.d; - SaveMd(eaa,flags.result.d); - } - break; - } - case 0x04: /* MUL EAX,Ed */ - RMEd(MULD); - break; - case 0x05: /* IMUL EAX,Ed */ - RMEd(IMULD); - break; - case 0x06: /* DIV Ed */ - RMEd(DIVD); - break; - case 0x07: /* IDIV Ed */ - RMEd(IDIVD); - break; - } - break; - } - case 0xff: /* Group 5 */ - { - GetRM; - switch (rm & 0x38) { - case 0x00: /* INC Ed */ - RMEd(INCD); - break; - case 0x08: /* DEC Ed */ - RMEd(DECD); - break; - case 0x30: /* Push Ed */ - if (rm >= 0xc0 ) {GetEArd;Push_32(*eard);} - else {GetEAa;Push_32(LoadMd(eaa));} - break; - default: - E_Exit("CPU:66:GRP5:Illegal call %2X",rm & 0x38); - break; - } - break; - } - default: - NOTDONE66; - } - - diff --git a/src/cpu/core_16/prefix_66_of.h b/src/cpu/core_16/prefix_66_of.h deleted file mode 100644 index 0738eda..0000000 --- a/src/cpu/core_16/prefix_66_of.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2002 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 Library 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. - */ - -switch (Fetchb()) { - case 0x01: /* Group 7 Ed */ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm < 0xc0) { //First ones all use EA - GetEAa;Bitu limit,base; - switch (which) { - case 0x00: /* SGDT */ - CPU_SGDT(limit,base); - SaveMw(eaa,limit); - SaveMd(eaa+2,base); - break; - case 0x01: /* SIDT */ - CPU_SIDT(limit,base); - SaveMw(eaa,limit); - SaveMd(eaa+2,base); - break; - case 0x02: /* LGDT */ - CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2)); - break; - case 0x03: /* LIDT */ - CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2)); - break; - case 0x04: /* SMSW */ - CPU_SMSW(limit); - SaveMw(eaa,limit); - break; - case 0x06: /* LMSW */ - limit=LoadMw(eaa); - if (!CPU_LMSW(limit)) goto decode_end; - break; - } - } else { - GetEArw;Bitu limit; - switch (which) { - case 0x04: /* SMSW */ - CPU_SMSW(limit); - *earw=limit; - break; - case 0x06: /* LMSW */ - if (!CPU_LMSW(*earw)) goto decode_end; - break; - default: - LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which); - break; - } - - } - } - break; - case 0xa4: /* SHLD Ed,Gd,Ib */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArd;DSHLD(*eard,*rmrd,Fetchb(),LoadRd,SaveRd);} - else {GetEAa;DSHLD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);} - break; - } - case 0xac: /* SHRD Ed,Gd,Ib */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArd;DSHRD(*eard,*rmrd,Fetchb(),LoadRd,SaveRd);} - else {GetEAa;DSHRD(eaa,*rmrd,Fetchb(),LoadMd,SaveMd);} - break; - } - case 0xad: /* SHRD Ed,Gd,Cl */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArd;DSHRD(*eard,*rmrd,reg_cl,LoadRd,SaveRd);} - else {GetEAa;DSHRD(eaa,*rmrd,reg_cl,LoadMd,SaveMd);} - break; - } - - case 0xb6: /* MOVZX Gd,Eb */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;} - else {GetEAa;*rmrd=LoadMb(eaa);} - break; - } - case 0xaf: /* IMUL Gd,Ed */ - { - RMGdEdOp3(DIMULD,*rmrd); - break; - }; - case 0xb7: /* MOVXZ Gd,Ew */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArw;*rmrd=*earw;} - else {GetEAa;*rmrd=LoadMw(eaa);} - break; - } - case 0xba: /* GRP8 Ed,Ib */ - { - GetRM; - if (rm >= 0xc0 ) { - GetEArd; - Bit32u mask=1 << (Fetchb() & 31); - SETFLAGBIT(CF,(*eard & mask)); - switch (rm & 0x38) { - case 0x20: /* BT */ - break; - case 0x28: /* BTS */ - *eard|=mask; - break; - case 0x30: /* BTR */ - *eard&=~mask; - break; - case 0x38: /* BTC */ - if (GETFLAG(CF)) *eard&=~mask; - else *eard|=mask; - break; - default: - E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38); - } - } else { - GetEAa;Bit32u old=LoadMd(eaa); - Bit32u mask=1 << (Fetchb() & 31); - SETFLAGBIT(CF,(old & mask)); - switch (rm & 0x38) { - case 0x20: /* BT */ - break; - case 0x28: /* BTS */ - SaveMd(eaa,old|mask); - break; - case 0x30: /* BTR */ - SaveMd(eaa,old & ~mask); - break; - case 0x38: /* BTC */ - if (GETFLAG(CF)) old&=~mask; - else old|=mask; - SaveMd(eaa,old); - break; - default: - E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38); - } - } - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; - break; - } - case 0xbb: /* BTC Ed,Gd */ - { - GetRMrd; - Bit32u mask=1 << (*rmrd & 31); - if (rm >= 0xc0 ) { - GetEArd; - SETFLAGBIT(CF,(*eard & mask)); - *eard^=mask; - } else { - GetEAa;Bit32u old=LoadMd(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMd(eaa,old ^ mask); - } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } - break; - } - case 0xbc: /* BSF Gd,Ed */ - { - GetRMrd; - Bit32u result,value; - if (rm >= 0xc0) { GetEArd; value=*eard; } - else { GetEAa; value=LoadMd(eaa); } - if (value==0) { - SETFLAGBIT(ZF,true); - } else { - result = 0; - while ((value & 0x01)==0) { result++; value>>=1; } - SETFLAGBIT(ZF,false); - *rmrd = result; - } - flags.type=t_UNKNOWN; - break; - } - case 0xbd: /* BSR Gd,Ed */ - { - GetRMrd; - Bit32u result,value; - if (rm >= 0xc0) { GetEArd; value=*eard; } - else { GetEAa; value=LoadMd(eaa); } - if (value==0) { - SETFLAGBIT(ZF,true); - } else { - result = 35; // Operandsize-1 - while ((value & 0x80000000)==0) { result--; value<<=1; } - SETFLAGBIT(ZF,false); - *rmrd = result; - } - flags.type=t_UNKNOWN; - break; - } - case 0xbe: /* MOVSX Gd,Eb */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArb;*rmrd=*(Bit8s *)earb;} - else {GetEAa;*rmrd=LoadMbs(eaa);} - break; - } - case 0xbf: /* MOVSX Gd,Ew */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArw;*rmrd=*(Bit16s *)earw;} - else {GetEAa;*rmrd=LoadMws(eaa);} - break; - } - default: - SUBIP(1); - E_Exit("CPU:Opcode 66:0F:%2X Unhandled",Fetchb()); -} diff --git a/src/cpu/core_16/prefix_of.h b/src/cpu/core_16/prefix_of.h deleted file mode 100644 index f28113c..0000000 --- a/src/cpu/core_16/prefix_of.h +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (C) 2002 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 Library 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. - */ - -switch(Fetchb()) { - case 0x00: /* GRP 6 */ - { - GetRM;Bitu which=(rm>>3)&7; - switch (which) { - case 0x00: /* SLDT */ - case 0x01: /* STR */ - { - Bitu saveval; - if (!which) CPU_SLDT(saveval); - else CPU_STR(saveval); - if (rm>0xc0) {GetEArw;*earw=saveval;} - else {GetEAa;SaveMw(eaa,saveval);} - } - break; - case 0x02:case 0x03:case 0x04:case 0x05: - { - Bitu loadval; - if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} - else {GetEAa;loadval=LoadMw(eaa);} - break; - switch (which) { - case 0x02:CPU_LLDT(loadval);break; - case 0x03:CPU_LTR(loadval);break; - case 0x04:CPU_VERR(loadval);break; - case 0x05:CPU_VERW(loadval);break; - } - } - default: - LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); - } - } - break; - case 0x01: /* Group 7 Ew */ - { - GetRM;Bitu which=(rm>>3)&7; - if (rm < 0xc0) { //First ones all use EA - GetEAa;Bitu limit,base; - switch (which) { - case 0x00: /* SGDT */ - CPU_SGDT(limit,base); - SaveMw(eaa,limit); - SaveMd(eaa+2,base); - break; - case 0x01: /* SIDT */ - CPU_SIDT(limit,base); - SaveMw(eaa,limit); - SaveMd(eaa+2,base); - break; - case 0x02: /* LGDT */ - CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF); - break; - case 0x03: /* LIDT */ - CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF); - break; - case 0x04: /* SMSW */ - CPU_SMSW(limit); - SaveMw(eaa,limit); - break; - case 0x06: /* LMSW */ - limit=LoadMw(eaa); - if (!CPU_LMSW(limit)) goto decode_end; - break; - } - } else { - GetEArw;Bitu limit; - switch (which) { - case 0x04: /* SMSW */ - CPU_SMSW(limit); - *earw=limit; - break; - case 0x06: /* LMSW */ - if (!CPU_LMSW(*earw)) goto decode_end; - break; - default: - LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which); - break; - } - } - } - break; - case 0x20: /* MOV Rd.CRx */ - { - GetRM; - Bitu which=(rm >> 3) & 7; - if (rm >= 0xc0 ) { - GetEArd; - *eard=CPU_GET_CRX(which); - } else { - GetEAa; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%d with non-register",which); - } - } - break; - case 0x22: /* MOV CRx,Rd */ - { - GetRM; - Bitu which=(rm >> 3) & 7; - if (rm >= 0xc0 ) { - GetEArd; - if (!CPU_SET_CRX(which,*eard)) goto decode_end; - } else { - GetEAa; - LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which); - } - } - break; - case 0x23: /* MOV DRx,Rd */ - { - GetRM; - Bitu which=(rm >> 3) & 7; - if (rm >= 0xc0 ) { - GetEArd; - } else { - GetEAa; - LOG(LOG_CPU,LOG_ERROR)("MOV DR%,XXX with non-register",which); - } - } - break; - case 0x80: /* JO */ - JumpSIw(get_OF());break; - case 0x81: /* JNO */ - JumpSIw(!get_OF());break; - case 0x82: /* JB */ - JumpSIw(get_CF());break; - case 0x83: /* JNB */ - JumpSIw(!get_CF());break; - case 0x84: /* JZ */ - JumpSIw(get_ZF());break; - case 0x85: /* JNZ */ - JumpSIw(!get_ZF()); break; - case 0x86: /* JBE */ - JumpSIw(get_CF() || get_ZF());break; - case 0x87: /* JNBE */ - JumpSIw(!get_CF() && !get_ZF());break; - case 0x88: /* JS */ - JumpSIw(get_SF());break; - case 0x89: /* JNS */ - JumpSIw(!get_SF());break; - case 0x8a: /* JP */ - JumpSIw(get_PF());break; - case 0x8b: /* JNP */ - JumpSIw(!get_PF());break; - case 0x8c: /* JL */ - JumpSIw(get_SF() != get_OF());break; - case 0x8d: /* JNL */ - JumpSIw(get_SF() == get_OF());break; - case 0x8e: /* JLE */ - JumpSIw(get_ZF() || (get_SF() != get_OF()));break; - case 0x8f: /* JNLE */ - JumpSIw((get_SF() == get_OF()) && !get_ZF());break; - - case 0x90: /* SETO */ - SETcc(get_OF());break; - case 0x91: /* SETNO */ - SETcc(!get_OF());break; - case 0x92: /* SETB */ - SETcc(get_CF());break; - case 0x93: /* SETNB */ - SETcc(!get_CF());break; - case 0x94: /* SETZ */ - SETcc(get_ZF());break; - case 0x95: /* SETNZ */ - SETcc(!get_ZF()); break; - case 0x96: /* SETBE */ - SETcc(get_CF() || get_ZF());break; - case 0x97: /* SETNBE */ - SETcc(!get_CF() && !get_ZF());break; - case 0x98: /* SETS */ - SETcc(get_SF());break; - case 0x99: /* SETNS */ - SETcc(!get_SF());break; - case 0x9a: /* SETP */ - SETcc(get_PF());break; - case 0x9b: /* SETNP */ - SETcc(!get_PF());break; - case 0x9c: /* SETL */ - SETcc(get_SF() != get_OF());break; - case 0x9d: /* SETNL */ - SETcc(get_SF() == get_OF());break; - case 0x9e: /* SETLE */ - SETcc(get_ZF() || (get_SF() != get_OF()));break; - case 0x9f: /* SETNLE */ - SETcc((get_SF() == get_OF()) && !get_ZF());break; - - case 0xa0: /* PUSH FS */ - Push_16(SegValue(fs));break; - case 0xa1: /* POP FS */ - SegSet16(fs,Pop_16());break; - case 0xa2: - CPU_CPUID(); - break; - case 0xa3: /* BT Ew,Gw */ - { - GetRMrw; - Bit16u mask=1 << (*rmrw & 15); - if (rm >= 0xc0 ) { - GetEArw; - SETFLAGBIT(CF,(*earw & mask)); - } else { - GetEAa;Bit16u old=LoadMw(eaa); - SETFLAGBIT(CF,(old & mask)); - } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } - break; - } - case 0xa4: /* SHLD Ew,Gw,Ib */ - RMEwGwOp3(DSHLW,Fetchb()); - break; - case 0xa5: /* SHLD Ew,Gw,CL */ - RMEwGwOp3(DSHLW,reg_cl); - break; - case 0xa8: /* PUSH GS */ - Push_16(SegValue(gs));break; - case 0xa9: /* POP GS */ - SegSet16(gs,Pop_16());break; - case 0xab: /* BTS Ew,Gw */ - { - GetRMrw; - Bit16u mask=1 << (*rmrw & 15); - if (rm >= 0xc0 ) { - GetEArw; - SETFLAGBIT(CF,(*earw & mask)); - *earw|=mask; - } else { - GetEAa;Bit16u old=LoadMw(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMw(eaa,old | mask); - } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } - break; - } - case 0xac: /* SHRD Ew,Gw,Ib */ - RMEwGwOp3(DSHRW,Fetchb()); - break; - case 0xad: /* SHRD Ew,Gw,CL */ - RMEwGwOp3(DSHRW,reg_cl); - break; - case 0xaf: /* IMUL Gw,Ew */ - RMGwEwOp3(DIMULW,*rmrw); - break; - - case 0xb2: /* LSS */ - { - GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SegSet16(ss,LoadMw(eaa+2)); - CPU_Cycles++;//Be sure we run another instruction - break; - } - case 0xb3: /* BTR Ew,Gw */ - { - GetRMrw; - Bit16u mask=1 << (*rmrw & 15); - if (rm >= 0xc0 ) { - GetEArw; - SETFLAGBIT(CF,(*earw & mask)); - *earw&= ~mask; - } else { - GetEAa;Bit16u old=LoadMw(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMw(eaa,old & ~mask); - } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } - break; - } - case 0xb4: /* LFS */ - { - GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SegSet16(fs,LoadMw(eaa+2)); - break; - } - case 0xb5: /* LGS */ - { - GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);SegSet16(gs,LoadMw(eaa+2)); - break; - } - case 0xb6: /* MOVZX Gw,Eb */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArb;*rmrw=*earb;} - else {GetEAa;*rmrw=LoadMb(eaa);} - break; - } - case 0xb7: /* MOVZX Gw,Ew */ - case 0xbf: /* MOVSX Gw,Ew */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} - else {GetEAa;*rmrw=LoadMw(eaa);} - break; - } - case 0xba: /* GRP8 Ew,Ib */ - { - GetRM; - if (rm >= 0xc0 ) { - GetEArw; - Bit16u mask=1 << (Fetchb() & 15); - SETFLAGBIT(CF,(*earw & mask)); - switch (rm & 0x38) { - case 0x20: /* BT */ - break; - case 0x28: /* BTS */ - *earw|=mask; - break; - case 0x30: /* BTR */ - *earw&= ~mask; - break; - case 0x38: /* BTC */ - *earw^=mask; - break; - default: - E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38); - } - } else { - GetEAa;Bit16u old=LoadMw(eaa); - Bit16u mask=1 << (Fetchb() & 15); - SETFLAGBIT(CF,(old & mask)); - switch (rm & 0x38) { - case 0x20: /* BT */ - break; - case 0x28: /* BTS */ - SaveMw(eaa,old|mask); - break; - case 0x30: /* BTR */ - SaveMw(eaa,old & ~mask); - break; - case 0x38: /* BTC */ - SaveMw(eaa,old ^ mask); - break; - default: - E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38); - } - } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } - break; - } - case 0xbb: /* BTC Ew,Gw */ - { - GetRMrw; - Bit16u mask=1 << (*rmrw & 15); - if (rm >= 0xc0 ) { - GetEArw; - SETFLAGBIT(CF,(*earw & mask)); - *earw^=mask; - } else { - GetEAa;Bit16u old=LoadMw(eaa); - SETFLAGBIT(CF,(old & mask)); - SaveMw(eaa,old ^ mask); - } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } - break; - } - case 0xbc: /* 0xbc BSF Gw,Ew */ - { - GetRMrw; - Bit16u result,value; - if (rm >= 0xc0) { GetEArw; value=*earw; } - else { GetEAa; value=LoadMw(eaa); } - if (value==0) { - SETFLAGBIT(ZF,true); - } else { - result = 0; - while ((value & 0x01)==0) { result++; value>>=1; } - SETFLAGBIT(ZF,false); - *rmrw = result; - } - flags.type=t_UNKNOWN; - break; - } - case 0xbd: /* 0xbd BSR Gw,Ew */ - { - GetRMrw; - Bit16u result,value; - if (rm >= 0xc0) { GetEArw; value=*earw; } - else { GetEAa; value=LoadMw(eaa); } - if (value==0) { - SETFLAGBIT(ZF,true); - } else { - result = 15; // Operandsize-1 - while ((value & 0x8000)==0) { result--; value<<=1; } - SETFLAGBIT(ZF,false); - *rmrw = result; - } - flags.type=t_UNKNOWN; - break; - } - case 0xbe: /* MOVSX Gw,Eb */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArb;*rmrw=*(Bit8s *)earb;} - else {GetEAa;*rmrw=LoadMbs(eaa);} - break; - } - case 0xc8: BSWAP(reg_eax); break; - case 0xc9: BSWAP(reg_ecx); break; - case 0xca: BSWAP(reg_edx); break; - case 0xcb: BSWAP(reg_ebx); break; - case 0xcc: BSWAP(reg_esp); break; - case 0xcd: BSWAP(reg_ebp); break; - case 0xce: BSWAP(reg_esi); break; - case 0xcf: BSWAP(reg_edi); break; - - default: - SUBIP(1); - E_Exit("CPU:Opcode 0F:%2X Unhandled",Fetchb()); - } diff --git a/src/cpu/core_16/support.h b/src/cpu/core_16/support.h deleted file mode 100644 index 8770a7d..0000000 --- a/src/cpu/core_16/support.h +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (C) 2002 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 Library General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -#define SUBIP(a) core_16.ip_lookup-=a -#define SETIP(a) core_16.ip_lookup=SegBase(cs)+a -#define GETIP (Bit16u)(core_16.ip_lookup-SegBase(cs)) -#define SAVEIP reg_ip=GETIP -#define LOADIP core_16.ip_lookup=SegBase(cs)+reg_ip - -#define LEAVECORE \ - SAVEIP; \ - FillFlags(); - -static INLINE void ADDIP(Bit16u add) { - core_16.ip_lookup=SegBase(cs)+((Bit16u)(((Bit16u)(core_16.ip_lookup-SegBase(cs)))+(Bit16u)add)); -} - -static INLINE void ADDIPFAST(Bit16s blah) { - core_16.ip_lookup+=blah; -} - -#define CheckTF() \ - if (GETFLAG(TF)) { \ - cpudecoder=CPU_Real_16_Slow_Decode_Trap; \ - goto decode_end; \ - } - - -#define EXCEPTION(blah) \ - { \ - Bit8u new_num=blah; \ - core_16.ip_lookup=core_16.ip_start; \ - LEAVECORE; \ - if (Interrupt(new_num)) { \ - if (GETFLAG(TF)) { \ - cpudecoder=CPU_Real_16_Slow_Decode_Trap; \ - return CBRET_NONE; \ - } \ - goto decode_start; \ - } else return CBRET_NONE; \ - } - -static INLINE Bit8u Fetchb() { - Bit8u temp=LoadMb(core_16.ip_lookup); - core_16.ip_lookup+=1; - return temp; -} - -static INLINE Bit16u Fetchw() { - Bit16u temp=LoadMw(core_16.ip_lookup); - core_16.ip_lookup+=2; - return temp; -} -static INLINE Bit32u Fetchd() { - Bit32u temp=LoadMd(core_16.ip_lookup); - core_16.ip_lookup+=4; - return temp; -} - -static INLINE Bit8s Fetchbs() { - return Fetchb(); -} -static INLINE Bit16s Fetchws() { - return Fetchw(); -} - -static INLINE Bit32s Fetchds() { - return Fetchd(); -} - -static INLINE void Push_16(Bit16u blah) { - reg_sp-=2; - SaveMw(SegBase(ss)+reg_sp,blah); -}; - -static INLINE void Push_32(Bit32u blah) { - reg_sp-=4; - SaveMd(SegBase(ss)+reg_sp,blah); -}; - -static INLINE Bit16u Pop_16() { - Bit16u temp=LoadMw(SegBase(ss)+reg_sp); - reg_sp+=2; - return temp; -}; - -static INLINE Bit32u Pop_32() { - Bit32u temp=LoadMd(SegBase(ss)+reg_sp); - reg_sp+=4; - return temp; -}; - -#define JumpSIb(blah) \ - if (blah) { \ - ADDIPFAST(Fetchbs()); \ - } else { \ - ADDIPFAST(1); \ - } - -#define JumpSIw(blah) \ - if (blah) { \ - ADDIPFAST(Fetchws()); \ - } else { \ - ADDIPFAST(2); \ - } - -#define SETcc(cc) \ - { \ - GetRM; \ - if (rm >= 0xc0 ) {GetEArb;*earb=(cc) ? 1 : 0;} \ - else {GetEAa;SaveMb(eaa,(cc) ? 1 : 0);} \ - } - -#define NOTDONE \ - SUBIP(1);E_Exit("CPU:Opcode %2X Unhandled",Fetchb()); - -#define NOTDONE66 \ - SUBIP(1);E_Exit("CPU:Opcode 66:%2X Unhandled",Fetchb()); - - -#define stringDI \ - PhysPt to; \ - to=SegBase(es)+reg_di - -#define stringSI \ - PhysPt from; \ - if (core_16.prefixes & PREFIX_SEG) { \ - from=(core_16.segbase+reg_si); \ - } else { \ - from=SegBase(ds)+reg_si; \ - } - -#include "helpers.h" -#include "table_ea.h" -#include "../modrm.h" - -static void Repeat_Normal(bool testz,bool prefix_66) { - - PhysPt base_si,base_di; - - Bit16s direct; - if (GETFLAG(DF)) direct=-1; - else direct=1; - base_di=SegBase(es); - if (core_16.prefixes & PREFIX_ADDR) E_Exit("Unhandled 0x67 prefixed string op"); -rep_again: - if (core_16.prefixes & PREFIX_SEG) { - base_si=(core_16.segbase); - } else { - base_si=SegBase(ds); - } - switch (Fetchb()) { - case 0x26: /* ES Prefix */ - core_16.segbase=SegBase(es); - core_16.prefixes|=PREFIX_SEG; - goto rep_again; - case 0x2e: /* CS Prefix */ - core_16.segbase=SegBase(cs); - core_16.prefixes|=PREFIX_SEG; - goto rep_again; - case 0x36: /* SS Prefix */ - core_16.segbase=SegBase(ss); - core_16.prefixes|=PREFIX_SEG; - goto rep_again; - case 0x3e: /* DS Prefix */ - core_16.segbase=SegBase(ds); - core_16.prefixes|=PREFIX_SEG; - goto rep_again; - case 0x64: /* FS Prefix */ - core_16.segbase=SegBase(fs); - core_16.prefixes|=PREFIX_SEG; - goto rep_again; - case 0x65: /* GS Prefix */ - core_16.segbase=SegBase(gs); - core_16.prefixes|=PREFIX_SEG; - goto rep_again; - case 0x66: /* Size Prefix */ - prefix_66=!prefix_66; - goto rep_again; - case 0x6c: /* REP INSB */ - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMb(base_di+reg_di,IO_Read(reg_dx)); - reg_di+=direct; - } - break; - case 0x6d: /* REP INSW/D */ - if (prefix_66) { - direct*=4; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMb(base_di+reg_di+0,IO_Read(reg_dx+0)); - SaveMb(base_di+reg_di+1,IO_Read(reg_dx+1)); - SaveMb(base_di+reg_di+2,IO_Read(reg_dx+2)); - SaveMb(base_di+reg_di+3,IO_Read(reg_dx+3)); - reg_di+=direct; - } - } else { - direct*=2; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMb(base_di+reg_di+0,IO_Read(reg_dx+0)); - SaveMb(base_di+reg_di+1,IO_Read(reg_dx+1)); - reg_di+=direct; - } - } - break; - case 0x6e: /* REP OUTSB */ - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - IO_Write(reg_dx,LoadMb(base_si+reg_si)); - reg_si+=direct; - } - break; - case 0x6f: /* REP OUTSW/D */ - if (prefix_66) { - direct*=4; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - IO_Write(reg_dx+0,LoadMb(base_si+reg_si+0)); - IO_Write(reg_dx+1,LoadMb(base_si+reg_si+1)); - IO_Write(reg_dx+2,LoadMb(base_si+reg_si+2)); - IO_Write(reg_dx+3,LoadMb(base_si+reg_si+3)); - reg_si+=direct; - } - } else { - direct*=2; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - IO_Write(reg_dx+0,LoadMb(base_si+reg_si+0)); - IO_Write(reg_dx+1,LoadMb(base_si+reg_si+1)); - reg_si+=direct; - } - } - break; - case 0xa4: /* REP MOVSB */ - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMb(base_di+reg_di,LoadMb(base_si+reg_si)); - reg_si+=direct;reg_di+=direct; - } - break; - case 0xa5: /* REP MOVSW/D */ - if (prefix_66) { - direct*=4; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMd(base_di+reg_di,LoadMd(base_si+reg_si)); - reg_si+=direct;reg_di+=direct; - } - } else { - direct*=2; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMw(base_di+reg_di,LoadMw(base_si+reg_si)); - reg_si+=direct;reg_di+=direct; - } - } - break; - case 0xa6: /* REP CMPSB */ - { - Bit8u op1,op2; - if (!reg_cx) { CPU_Cycles--;goto normalexit; } - for (;CPU_Cycles>0;CPU_Cycles--) { - op1=LoadMb(base_si+reg_si);op2=LoadMb(base_di+reg_di); - reg_cx--;reg_si+=direct;reg_di+=direct; - if ((op1==op2)!=testz || !reg_cx) { CMPB(op1,op2,LoadRb,0);goto normalexit; } - } - CMPB(op1,op2,LoadRb,0); - } - break; - case 0xa7: /* REP CMPSW */ - { - if (!reg_cx) { CPU_Cycles--;goto normalexit; } - if (prefix_66) { - direct*=4;Bit32u op1,op2; - for (;CPU_Cycles>0;CPU_Cycles--) { - op1=LoadMd(base_si+reg_si);op2=LoadMd(base_di+reg_di); - reg_cx--;reg_si+=direct;reg_di+=direct; - if ((op1==op2)!=testz || !reg_cx) { CMPD(op1,op2,LoadRd,0);goto normalexit; } - } - CMPD(op1,op2,LoadRd,0); - } else { - direct*=2;Bit16u op1,op2; - for (;CPU_Cycles>0;CPU_Cycles--) { - op1=LoadMw(base_si+reg_si);op2=LoadMw(base_di+reg_di); - reg_cx--,reg_si+=direct;reg_di+=direct; - if ((op1==op2)!=testz || !reg_cx) { CMPW(op1,op2,LoadRw,0);goto normalexit; } - } - CMPW(op1,op2,LoadRw,0); - } - } - break; - case 0xaa: /* REP STOSB */ - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMb(base_di+reg_di,reg_al); - reg_di+=direct; - } - break; - case 0xab: /* REP STOSW */ - if (prefix_66) { - direct*=4; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMd(base_di+reg_di,reg_eax); - reg_di+=direct; - } - } else { - direct*=2; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - SaveMw(base_di+reg_di,reg_ax); - reg_di+=direct; - } - } - break; - case 0xac: /* REP LODSB */ - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - reg_al=LoadMb(base_si+reg_si); - reg_si+=direct; - } - break; - case 0xad: /* REP LODSW */ - if (prefix_66) { - direct*=4; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - reg_eax=LoadMd(base_si+reg_si); - reg_si+=direct; - } - } else { - direct*=2; - for (;CPU_Cycles>0;CPU_Cycles--) { - if (!reg_cx) goto normalexit; reg_cx--; - reg_ax=LoadMw(base_si+reg_si); - reg_si+=direct; - } - } - break; - case 0xae: /* REP SCASB */ - { - Bit8u op2; - if (!reg_cx) { CPU_Cycles--;goto normalexit; } - for (;CPU_Cycles>0;CPU_Cycles--) { - op2=LoadMb(base_di+reg_di); - reg_cx--;reg_di+=direct; - if ((reg_al==op2)!=testz || !reg_cx) { CMPB(reg_al,op2,LoadRb,0);goto normalexit; } - } - CMPB(reg_al,op2,LoadRb,0); - } - break; - case 0xaf: /* REP SCASW */ - { - if (!reg_cx) { CPU_Cycles--;goto normalexit; } - if (prefix_66) { - direct*=4;Bit32u op2; - for (;CPU_Cycles>0;CPU_Cycles--) { - op2=LoadMd(base_di+reg_di); - reg_cx--;reg_di+=direct; - if ((reg_eax==op2)!=testz || !reg_cx) { CMPD(reg_eax,op2,LoadRd,0);goto normalexit; } - } - CMPD(reg_eax,op2,LoadRd,0); - } else { - direct*=2;Bit16u op2; - for (;CPU_Cycles>0;CPU_Cycles--) { - op2=LoadMw(base_di+reg_di); - reg_cx--;reg_di+=direct; - if ((reg_ax==op2)!=testz || !reg_cx) { CMPW(reg_ax,op2,LoadRw,0);goto normalexit; } - } - CMPW(reg_ax,op2,LoadRw,0); - } - } - break; - default: - core_16.ip_lookup--; - LOG(LOG_CPU,LOG_ERROR)("Unhandled REP Prefix %X",Fetchb()); - goto normalexit; - } - /* If we end up here it's because the CPU_Cycles counter is 0, so restart instruction */ - core_16.ip_lookup=core_16.ip_start; -normalexit:; -} - diff --git a/src/cpu/core_16/table_ea.h b/src/cpu/core_16/table_ea.h deleted file mode 100644 index cf7131f..0000000 --- a/src/cpu/core_16/table_ea.h +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (C) 2002 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 Library 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 variables for EA Loolkup */ - -typedef PhysPt (*GetEATable[256])(void); -typedef PhysPt (*EA_LookupHandler)(void); - -static GetEATable * lookupEATable; - -#define PREFIX_NONE 0x0 -#define PREFIX_SEG 0x1 -#define PREFIX_ADDR 0x2 -#define PREFIX_SEG_ADDR 0x3 - - -/* Gets initialized at the bottem, can't seem to declare forward references */ -static GetEATable * EAPrefixTable[4]; - - -#define SegPrefix(blah) \ - core_16.segbase=SegBase(blah); \ - core_16.prefixes|=PREFIX_SEG; \ - lookupEATable=EAPrefixTable[core_16.prefixes]; \ - goto restart; - -#define SegPrefix_66(blah) \ - core_16.segbase=SegBase(blah); \ - core_16.prefixes|=PREFIX_SEG; \ - lookupEATable=EAPrefixTable[core_16.prefixes]; \ - goto restart_66; - - -/* The MOD/RM Decoder for EA for this decoder's addressing modes */ -static PhysPt EA_16_00_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); } -static PhysPt EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); } -static PhysPt EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); } -static PhysPt EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); } -static PhysPt EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); } -static PhysPt EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); } -static PhysPt EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());} -static PhysPt EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); } - -static PhysPt EA_16_40_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_41_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_42_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_43_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_44_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchbs()); } -static PhysPt EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); } -static PhysPt EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); } -static PhysPt EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchbs()); } - -static PhysPt EA_16_80_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_81_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_82_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_83_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_84_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchws()); } -static PhysPt EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); } -static PhysPt EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); } -static PhysPt EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); } - -static GetEATable GetEA_16_n={ -/* 00 */ - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, - EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, -/* 01 */ - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, - EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, -/* 10 */ - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, - EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, -/* 11 These are illegal so make em 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - - - -static PhysPt EA_16_00_s(void) { return core_16.segbase+(Bit16u)(reg_bx+(Bit16s)reg_si); } -static PhysPt EA_16_01_s(void) { return core_16.segbase+(Bit16u)(reg_bx+(Bit16s)reg_di); } -static PhysPt EA_16_02_s(void) { return core_16.segbase+(Bit16u)(reg_bp+(Bit16s)reg_si); } -static PhysPt EA_16_03_s(void) { return core_16.segbase+(Bit16u)(reg_bp+(Bit16s)reg_di); } -static PhysPt EA_16_04_s(void) { return core_16.segbase+(Bit16u)(reg_si); } -static PhysPt EA_16_05_s(void) { return core_16.segbase+(Bit16u)(reg_di); } -static PhysPt EA_16_06_s(void) { return core_16.segbase+(Bit16u)(Fetchw()); } -static PhysPt EA_16_07_s(void) { return core_16.segbase+(Bit16u)(reg_bx); } - -static PhysPt EA_16_40_s(void) { return core_16.segbase+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_41_s(void) { return core_16.segbase+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_42_s(void) { return core_16.segbase+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); } -static PhysPt EA_16_43_s(void) { return core_16.segbase+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); } -static PhysPt EA_16_44_s(void) { return core_16.segbase+(Bit16u)(reg_si+Fetchbs()); } -static PhysPt EA_16_45_s(void) { return core_16.segbase+(Bit16u)(reg_di+Fetchbs()); } -static PhysPt EA_16_46_s(void) { return core_16.segbase+(Bit16u)(reg_bp+Fetchbs()); } -static PhysPt EA_16_47_s(void) { return core_16.segbase+(Bit16u)(reg_bx+Fetchbs()); } - -static PhysPt EA_16_80_s(void) { return core_16.segbase+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_81_s(void) { return core_16.segbase+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_82_s(void) { return core_16.segbase+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); } -static PhysPt EA_16_83_s(void) { return core_16.segbase+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); } -static PhysPt EA_16_84_s(void) { return core_16.segbase+(Bit16u)(reg_si+Fetchws()); } -static PhysPt EA_16_85_s(void) { return core_16.segbase+(Bit16u)(reg_di+Fetchws()); } -static PhysPt EA_16_86_s(void) { return core_16.segbase+(Bit16u)(reg_bp+Fetchws()); } -static PhysPt EA_16_87_s(void) { return core_16.segbase+(Bit16u)(reg_bx+Fetchws()); } - -static GetEATable GetEA_16_s={ -/* 00 */ - EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, - EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, - EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, - EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, - EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, - EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, - EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, - EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, -/* 01 */ - EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, - EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, - EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, - EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, - EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, - EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, - EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, - EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, -/* 10 */ - EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, - EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, - EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, - EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, - EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, - EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, - EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, - EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, -/* 11 These are illegal so make em 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static Bit32u SIBZero=0; -static Bit32u * SIBIndex[8]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_edi }; - -INLINE PhysPt Sib(Bitu mode) { - Bit8u sib=Fetchb(); - PhysPt base; - switch (sib&7) { - case 0: /* EAX Base */ - base=SegBase(ds)+reg_eax;break; - case 1: /* ECX Base */ - base=SegBase(ds)+reg_ecx;break; - case 2: /* EDX Base */ - base=SegBase(ds)+reg_edx;break; - case 3: /* EBX Base */ - base=SegBase(ds)+reg_ebx;break; - case 4: /* ESP Base */ - base=SegBase(ss)+reg_esp;break; - case 5: /* #1 Base */ - if (!mode) { - base=SegBase(ds)+Fetchd();break; - } else { - base=SegBase(ss)+reg_ebp;break; - } - case 6: /* ESI Base */ - base=SegBase(ds)+reg_esi;break; - case 7: /* EDI Base */ - base=SegBase(ds)+reg_edi;break; - } - base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); - return base; -}; - - -static PhysPt EA_32_00_n(void) { return SegBase(ds)+reg_eax; } -static PhysPt EA_32_01_n(void) { return SegBase(ds)+reg_ecx; } -static PhysPt EA_32_02_n(void) { return SegBase(ds)+reg_edx; } -static PhysPt EA_32_03_n(void) { return SegBase(ds)+reg_ebx; } -static PhysPt EA_32_04_n(void) { return Sib(0);} -static PhysPt EA_32_05_n(void) { return SegBase(ds)+Fetchd(); } -static PhysPt EA_32_06_n(void) { return SegBase(ds)+reg_esi; } -static PhysPt EA_32_07_n(void) { return SegBase(ds)+reg_edi; } - -static PhysPt EA_32_40_n(void) { return SegBase(ds)+reg_eax+Fetchbs(); } -static PhysPt EA_32_41_n(void) { return SegBase(ds)+reg_ecx+Fetchbs(); } -static PhysPt EA_32_42_n(void) { return SegBase(ds)+reg_edx+Fetchbs(); } -static PhysPt EA_32_43_n(void) { return SegBase(ds)+reg_ebx+Fetchbs(); } -static PhysPt EA_32_44_n(void) { PhysPt temp=Sib(1);return temp+Fetchbs();} -static PhysPt EA_32_45_n(void) { return SegBase(ss)+reg_ebp+Fetchbs(); } -static PhysPt EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); } -static PhysPt EA_32_47_n(void) { return SegBase(ds)+reg_edi+Fetchbs(); } - -static PhysPt EA_32_80_n(void) { return SegBase(ds)+reg_eax+Fetchds(); } -static PhysPt EA_32_81_n(void) { return SegBase(ds)+reg_ecx+Fetchds(); } -static PhysPt EA_32_82_n(void) { return SegBase(ds)+reg_edx+Fetchds(); } -static PhysPt EA_32_83_n(void) { return SegBase(ds)+reg_ebx+Fetchds(); } -static PhysPt EA_32_84_n(void) { PhysPt temp=Sib(2);return temp+Fetchds();} -static PhysPt EA_32_85_n(void) { return SegBase(ss)+reg_ebp+Fetchds(); } -static PhysPt EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); } -static PhysPt EA_32_87_n(void) { return SegBase(ds)+reg_edi+Fetchds(); } - -static GetEATable GetEA_32_n={ -/* 00 */ - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, - EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n, -/* 01 */ - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, - EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n, -/* 10 */ - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, - EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n, -/* 11 These are illegal so make em 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -INLINE PhysPt Sib_s(Bitu mode) { - Bit8u sib=Fetchb(); - PhysPt base; - switch (sib&7) { - case 0: /* EAX Base */ - base=reg_eax;break; - case 1: /* ECX Base */ - base=reg_ecx;break; - case 2: /* EDX Base */ - base=reg_edx;break; - case 3: /* EBX Base */ - base=reg_ebx;break; - case 4: /* ESP Base */ - base=reg_esp;break; - case 5: /* #1 Base */ - if (!mode) { - base=Fetchd();break; - } else { - base=reg_ebp;break; - } - case 6: /* ESI Base */ - base=reg_esi;break; - case 7: /* EDI Base */ - base=reg_edi;break; - } - base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); - return base; -}; - - -static PhysPt EA_32_00_s(void) { return core_16.segbase+(Bit32u)(reg_eax); } -static PhysPt EA_32_01_s(void) { return core_16.segbase+(Bit32u)(reg_ecx); } -static PhysPt EA_32_02_s(void) { return core_16.segbase+(Bit32u)(reg_edx); } -static PhysPt EA_32_03_s(void) { return core_16.segbase+(Bit32u)(reg_ebx); } -static PhysPt EA_32_04_s(void) { return core_16.segbase+(Bit32u)(Sib_s(0));} -static PhysPt EA_32_05_s(void) { return core_16.segbase+(Bit32u)(Fetchd()); } -static PhysPt EA_32_06_s(void) { return core_16.segbase+(Bit32u)(reg_esi); } -static PhysPt EA_32_07_s(void) { return core_16.segbase+(Bit32u)(reg_edi); } - -static PhysPt EA_32_40_s(void) { return core_16.segbase+(Bit32u)(reg_eax+Fetchbs()); } -static PhysPt EA_32_41_s(void) { return core_16.segbase+(Bit32u)(reg_ecx+Fetchbs()); } -static PhysPt EA_32_42_s(void) { return core_16.segbase+(Bit32u)(reg_edx+Fetchbs()); } -static PhysPt EA_32_43_s(void) { return core_16.segbase+(Bit32u)(reg_ebx+Fetchbs()); } -static PhysPt EA_32_44_s(void) { return core_16.segbase+(Bit32u)(Sib_s(1)+Fetchbs());} -static PhysPt EA_32_45_s(void) { return core_16.segbase+(Bit32u)(reg_ebp+Fetchbs()); } -static PhysPt EA_32_46_s(void) { return core_16.segbase+(Bit32u)(reg_esi+Fetchbs()); } -static PhysPt EA_32_47_s(void) { return core_16.segbase+(Bit32u)(reg_edi+Fetchbs()); } - -static PhysPt EA_32_80_s(void) { return core_16.segbase+(Bit32u)(reg_eax+Fetchds()); } -static PhysPt EA_32_81_s(void) { return core_16.segbase+(Bit32u)(reg_ecx+Fetchds()); } -static PhysPt EA_32_82_s(void) { return core_16.segbase+(Bit32u)(reg_edx+Fetchds()); } -static PhysPt EA_32_83_s(void) { return core_16.segbase+(Bit32u)(reg_ebx+Fetchds()); } -static PhysPt EA_32_84_s(void) { return core_16.segbase+(Bit32u)(Sib_s(2)+Fetchds());} -static PhysPt EA_32_85_s(void) { return core_16.segbase+(Bit32u)(reg_ebp+Fetchds()); } -static PhysPt EA_32_86_s(void) { return core_16.segbase+(Bit32u)(reg_esi+Fetchds()); } -static PhysPt EA_32_87_s(void) { return core_16.segbase+(Bit32u)(reg_edi+Fetchds()); } - - -static GetEATable GetEA_32_s={ -/* 00 */ - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, - EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, -/* 01 */ - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, - EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, -/* 10 */ - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, - EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, -/* 11 These are illegal so make em 0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static PhysPt GetEADirect_NONE(void) { - PhysPt result=SegBase(ds)+Fetchw(); - return result; -} -static PhysPt GetEADirect_SEG(void) { - PhysPt result=core_16.segbase+Fetchw(); - return result; -} -static PhysPt GetEADirect_ADDR(void) { - PhysPt result=SegBase(ds)+Fetchd(); - return result; -} -static PhysPt GetEADirect_SEG_ADDR(void) { - PhysPt result=core_16.segbase+Fetchd(); - return result; -} - -static EA_LookupHandler GetEADirect[4]={GetEADirect_NONE,GetEADirect_SEG,GetEADirect_ADDR,GetEADirect_SEG_ADDR}; diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp new file mode 100644 index 0000000..e6becba --- /dev/null +++ b/src/cpu/core_dyn_x86.cpp @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library 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_DYNAMIC_X86) + +#include +#include +#include +#include + +#include "callback.h" +#include "regs.h" +#include "mem.h" +#include "cpu.h" +#include "debug.h" +#include "paging.h" +#include "inout.h" + +#define CACHE_TOTAL (1024*1024*2) +#define CACHE_MAXSIZE (4096) +#define CACHE_BLOCKS (50*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 + +enum { + G_EAX,G_ECX,G_EDX,G_EBX, + G_ESP,G_EBP,G_ESI,G_EDI, + G_ES,G_CS,G_SS,G_DS,G_FS,G_GS, + G_FLAGS,G_SMASK,G_EIP, + G_EA,G_STACK,G_CYCLES, + G_TMPB,G_TMPW,G_SHIFT, + G_EXIT, + G_MAX, +}; + +enum SingleOps { + SOP_INC,SOP_DEC, + SOP_NOT,SOP_NEG, +}; + +enum DualOps { + DOP_ADD,DOP_ADC, + DOP_SUB,DOP_SBB, + DOP_CMP,DOP_XOR, + DOP_AND,DOP_OR, + DOP_MOV, + DOP_TEST, + DOP_XCHG, +}; + +enum ShiftOps { + SHIFT_ROL,SHIFT_ROR, + SHIFT_RCL,SHIFT_RCR, + SHIFT_SHL,SHIFT_SHR, + SHIFT_SAR, +}; + +enum BranchTypes { + BR_O,BR_NO,BR_B,BR_NB, + BR_Z,BR_NZ,BR_BE,BR_NBE, + BR_S,BR_NS,BR_P,BR_NP, + BR_L,BR_NL,BR_LE,BR_NLE +}; + +enum BlockType { + BT_Free=0, + BT_Normal, + BT_SingleLink, + BT_DualLink, + BT_CheckFlags, +}; + +enum BlockReturn { + BR_Normal=0, + BR_Cycles, + BR_Link1,BR_Link2, + BR_Opcode, + BR_CallBack, +}; + +#define DYNFLG_HAS16 0x1 //Would like 8-bit host reg support +#define DYNFLG_HAS8 0x2 //Would like 16-bit host reg support +#define DYNFLG_LOAD 0x4 //Load value when accessed +#define DYNFLG_SAVE 0x8 //Needs to be saved back at the end of block +#define DYNFLG_CHANGED 0x10 //Value is in a register and changed from load +#define DYNFLG_ACTIVE 0x20 //Register has an active value + +class GenReg; +class CodePageHandler; + +struct DynReg { + Bitu flags; + GenReg * genreg; + void * data; +}; + +enum DynAccess { + DA_d,DA_w, + DA_bh,DA_bl +}; + +enum ByteCombo { + BC_ll,BC_lh, + BC_hl,BC_hh, +}; + +static DynReg DynRegs[G_MAX]; +#define DREG(_WHICH_) &DynRegs[G_ ## _WHICH_ ] + +static struct { + Bitu ea,tmpb,tmpd,stack,shift; +} extra_regs; + +static void IllegalOption(void) { + E_Exit("Illegal option"); +} + +#include "core_dyn_x86/cache.h" + +static struct { + Bitu callback; +} core_dyn; + + +#include "core_dyn_x86/risc_x86.h" + +struct DynState { + DynReg regs[G_MAX]; +}; + +static void dyn_releaseregs(void) { + for (Bitu i=0;iregs[i].flags=DynRegs[i].flags; + state->regs[i].genreg=DynRegs[i].genreg; + } +} + +static void dyn_loadstate(DynState * state) { + for (Bitu i=0;iregs[i]); + } +} + + +static void dyn_synchstate(DynState * state) { + for (Bitu i=0;iregs[i]); + } +} +#include "core_dyn_x86/decoder.h" + +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; + mem_readb(ip_point); //Init whatever page we are in + PageHandler * handler=paging.tlb.handler[ip_page]; + CodePageHandler * chandler=0; + #if C_HEAVY_DEBUG + if (DEBUG_HeavyIsBreakpoint()) return debugCallback; + #endif + if (handler->flags & PFLAG_HASCODE) { + /* Find correct Dynamic Block to run */ + chandler=(CodePageHandler *)handler; +findblock:; + CacheBlock * block=chandler->FindCacheBlock(ip_point&4095); + if (!block) { + cache.block.running=0; + block=CreateCacheBlock(ip_point,cpu.code.big,128); +// DYN_LOG("Created block size %x type %d",block->cache.size,block->type); + chandler->AddCacheBlock(block); + if (block->page.end>=4096) { + DYN_LOG("block crosses page boundary"); + } + } +run_block: + BlockReturn ret=gen_runcode(block->cache.start); + switch (ret) { + case BR_Normal: + /* Maybe check if we staying in the same page? */ +#if C_HEAVY_DEBUG + if (DEBUG_HeavyIsBreakpoint()) return debugCallback; +#endif + goto restart_core; + case BR_Cycles: +#if C_HEAVY_DEBUG + if (DEBUG_HeavyIsBreakpoint()) return debugCallback; +#endif + return CBRET_NONE; + case BR_CallBack: + return core_dyn.callback; + case BR_Opcode: + CPU_CycleLeft+=CPU_Cycles; + CPU_Cycles=1; + return CPU_Core_Normal_Run(); + case BR_Link1: + case BR_Link2: + { + Bitu temp_ip=SegPhys(cs)+reg_eip; + Bitu temp_page=temp_ip >> 12; + CodePageHandler * temp_handler=(CodePageHandler *)paging.tlb.handler[temp_page]; + if (temp_handler->flags & PFLAG_HASCODE) { + block=temp_handler->FindCacheBlock(temp_ip & 4095); + if (!block) goto restart_core; + cache_linkblocks(cache.block.running,block,ret==BR_Link2); + goto run_block; + } + } + goto restart_core; + } + } else { + if (handler->flags & PFLAG_NOCODE) { + LOG_MSG("DYNX86:Can't run code in this page"); + return CPU_Core_Normal_Run(); + } + Bitu phys_page=ip_page; + if (!PAGING_MakePhysPage(phys_page)) { + LOG_MSG("DYNX86:Can't find physpage"); + return CPU_Core_Normal_Run(); + } + chandler=new CodePageHandler(handler); + MEM_SetPageHandler(phys_page,1,chandler); //Setup the handler + PAGING_UnlinkPages(ip_page,1); + goto findblock; + } + return 0; +} + + +void CPU_Core_Dyn_X86_Init(void) { + Bits i; + /* Setup the global registers and their flags */ + for (i=0;iflags|PFLAG_HASCODE; + flags&=~PFLAG_WRITEABLE; + memset(&hash_map,0,sizeof(hash_map)); + memset(&write_map,0,sizeof(write_map)); + } + void InvalidateRange(Bits start,Bits end) { + Bits maps=start>>DYN_HASH_SHIFT; + Bits map=maps; + Bits count=write_map[maps]; + while (map>=0 && count>0) { + CacheBlock * block=hash_map[map]; + CacheBlock * * where=&hash_map[map]; + while (block) { + CacheBlock * nextblock=block->hash.next; + if (start<=block->page.end && end>=block->page.start) { + for (Bitu i=block->page.first;i<=block->page.last;i++) write_map[i]--; + block->code_page=0; //Else resetblock will do double work + count--; + if (block==cache.block.running) LOG_MSG("Writing to current block"); + cache_resetblock(block); + *where=nextblock; + } else { + where=&block->hash.next; + } + block=nextblock; + } + map--; + } + } + void writeb(PhysPt addr,Bitu val){ + if (val!=host_readb(hostmem+(addr&4095))) { + InvalidateRange(addr&4095,addr&4095); + host_writeb(hostmem+(addr&4095),val); + } + } + void writew(PhysPt addr,Bitu val){ + if (val!=host_readw(hostmem+(addr&4095))) { + InvalidateRange(addr&4095,(addr&4095)+1); + host_writew(hostmem+(addr&4095),val); + } + } + void writed(PhysPt addr,Bitu val){ + if (val!=host_readd(hostmem+(addr&4095))) { + InvalidateRange(addr&4095,(addr&4095)+3); + host_writed(hostmem+(addr&4095),val); + } + } + void AddCacheBlock(CacheBlock * block) { + Bit16u first,last; + if (block->page.start<0) first=0; + else first=block->page.start>>DYN_HASH_SHIFT; + block->hash.next=hash_map[first]; + hash_map[first]=block; + if (block->page.end>=4096) last=DYN_PAGE_HASH-1; + else last=block->page.end>>DYN_HASH_SHIFT; + block->page.first=first; + block->page.last=last; + for (;first<=last;first++) { + write_map[first]++; + } + block->code_page=this; + } + void DelCacheBlock(CacheBlock * block) { + CacheBlock * * where=&hash_map[block->page.first]; + while (*where) { + if (*where==block) { + *where=block->hash.next; + break; + } + where=&((*where)->hash.next); + } + for (Bitu i=block->page.first;i<=block->page.last;i++) { + write_map[i]--; + } + } + CacheBlock * FindCacheBlock(Bitu start) { + CacheBlock * block=hash_map[start>>DYN_HASH_SHIFT]; + while (block) { + if (block->page.start==start) return block; + block=block->hash.next; + } + return 0; + } + HostPt GetHostPt(Bitu phys_page) { + hostmem=old_pagehandler->GetHostPt(phys_page); + return hostmem; + } +private: + PageHandler * old_pagehandler; + CacheBlock * hash_map[DYN_PAGE_HASH]; + Bit8u write_map[DYN_PAGE_HASH]; + HostPt hostmem; +}; + + +static INLINE void cache_addunsedblock(CacheBlock * block) { + block->list_next=cache.block.free; + cache.block.free=block; +} + +static CacheBlock * cache_getblock(void) { + CacheBlock * ret=cache.block.free; + if (!ret) E_Exit("Ran out of CacheBlocks" ); + cache.block.free=ret->list_next; + return ret; +} + +static INLINE void cache_clearlinkfrom(CacheBlock * block,CacheBlock * from) { + for (Bitu i=0;ilink.from[i]==from) block->link.from[i]=0; + } +} + +static INLINE void cache_clearlinkto(CacheBlock * block,CacheBlock * to) { + if (block->link.to[0]==to) block->link.to[0]=&cache.linkblocks[0]; + if (block->link.to[1]==to) block->link.to[1]=&cache.linkblocks[1]; +} + +static void cache_linkblocks(CacheBlock * from,CacheBlock * to,Bitu link) { + from->link.to[link]=to; + CacheBlock * clear=to->link.from[to->link.index]; + if (clear) { + DYN_LOG("backlink buffer full"); + cache_clearlinkto(to->link.from[to->link.index],to); + } + to->link.from[to->link.index]=from; + to->link.index++; + if (to->link.index>=DYN_LINKS) to->link.index=0; +} + +static void cache_resetblock(CacheBlock * block) { + Bits i; + DYN_LOG("Resetted block"); + block->type=BT_Free; + /* Clear all links to this block from other blocks */ + for (i=0;ilink.from[i]) cache_clearlinkto(block->link.from[i],block); + block->link.from[i]=0; + } + /* Clear all links from this block to other blocks */ + if (block->link.to[0]!=&cache.linkblocks[0]) { + cache_clearlinkfrom(block->link.to[0],block); + block->link.to[0]=&cache.linkblocks[0]; + } + if (block->link.to[1]!=&cache.linkblocks[1]) { + cache_clearlinkfrom(block->link.to[1],block); + block->link.to[1]=&cache.linkblocks[1]; + } + block->link.index=0; + if (block->code_page) block->code_page->DelCacheBlock(block); +} + +static CacheBlock * cache_openblock(void) { + CacheBlock * block=cache.block.active; + /* check for enough space in this block */ + Bitu size=block->cache.size; + CacheBlock * nextblock=block->list_next; + while (sizecache.size; + CacheBlock * tempblock=nextblock->list_next; + if (nextblock->type!=BT_Free) cache_resetblock(nextblock); + cache_addunsedblock(nextblock); + nextblock=tempblock; + } +skipresize: + block->cache.size=size; + block->list_next=nextblock; + cache.pos=block->cache.start; + return block; +} + +static void cache_closeblock(BlockType type) { + CacheBlock * block=cache.block.active; + /* Setup some structures in the block determined by type */ + block->type=type; + switch (type) { + case BT_Normal: + break; + case BT_SingleLink: + block->link.to[0]=&cache.linkblocks[0]; + break; + case BT_DualLink: + block->link.to[0]=&cache.linkblocks[0]; + block->link.to[1]=&cache.linkblocks[1]; + break; + } + /* Close the block with correct alignments */ + Bitu written=cache.pos-block->cache.start; + if (written>block->cache.size) { + if (!block->list_next) { + if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun"); + } else E_Exit("CacheBlock overrun"); + } else { + Bitu new_size; + Bitu left=block->cache.size-written; + /* Smaller than cache align then don't bother to resize */ + if (left>CACHE_ALIGN) { + new_size=((written-1)|(CACHE_ALIGN-1))+1; + } else new_size=block->cache.size; + CacheBlock * newblock=cache_getblock(); + newblock->cache.start=block->cache.start+new_size; + newblock->cache.size=block->cache.size-new_size; + newblock->list_next=block->list_next; + newblock->type=BT_Free; + block->cache.size=new_size; + block->list_next=newblock; + } + /* Advance the active block pointer */ + if (!block->list_next) { + DYN_LOG("Cache full restarting"); + cache.block.active=cache.block.first; + } else { + cache.block.active=block->list_next; + } +} + +static INLINE void cache_addb(Bit8u val) { + *cache.pos++=val; +} + +static INLINE void cache_addw(Bit16u val) { + *(Bit16u*)cache.pos=val; + cache.pos+=2; +} + +static INLINE void cache_addd(Bit32u val) { + *(Bit32u*)cache.pos=val; + cache.pos+=4; +} + + +static void gen_return(BlockReturn retcode); + +static void cache_init(void) { + Bits i; + memset(&cache_blocks,0,sizeof(cache_blocks)); + cache.block.free=&cache_blocks[0]; + for (i=0;icache.start=&cache_code[0]; + block->cache.size=CACHE_TOTAL; + block->list_next=0; //Last block in the list + cache.pos=&cache_code_link_blocks[0][0]; + cache.linkblocks[0].cache.start=cache.pos; + gen_return(BR_Link1); + cache.pos=&cache_code_link_blocks[1][0]; + cache.linkblocks[1].cache.start=cache.pos; + gen_return(BR_Link2); +} \ No newline at end of file diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h new file mode 100644 index 0000000..cc077ec --- /dev/null +++ b/src/cpu/core_dyn_x86/decoder.h @@ -0,0 +1,1411 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library 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. + */ + +enum REP_Type { + REP_NONE=0,REP_NZ,REP_Z +}; + +static struct DynDecode { + PhysPt code; + PhysPt code_start; + PhysPt op_start; + bool big_op; + bool big_addr; + REP_Type rep; + Bitu cycles; + CacheBlock * block; + struct { + Bitu val; + Bitu mod; + Bitu rm; + Bitu reg; + } modrm; + DynReg * segprefix; +} decode; + +static Bit8u INLINE decode_fetchb(void) { + return mem_readb(decode.code++); +} +static Bit16u INLINE decode_fetchw(void) { + decode.code+=2; + return mem_readw(decode.code-2); +} +static Bit32u INLINE decode_fetchd(void) { + decode.code+=4; + return mem_readd(decode.code-4); +} + +static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) { + if (high) gen_call_function((void *)&mem_readb,"%Dd%Rh",addr,dst); + else gen_call_function((void *)&mem_readb,"%Dd%Rl",addr,dst); +} +static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) { + if (high) gen_call_function((void *)&mem_writeb,"%Dd%Dh",addr,val); + else gen_call_function((void *)&mem_writeb,"%Dd%Dl",addr,val); +} + +static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) { + if (dword) gen_call_function((void *)&mem_readd,"%Dd%Rd",addr,dst); + else gen_call_function((void *)&mem_readw,"%Dd%Rw",addr,dst); +} + +static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) { + if (dword) gen_call_function((void *)&mem_writed,"%Dd%Dd",addr,val); + else gen_call_function((void *)&mem_writew,"%Dd%Dw",addr,val); +} + + +static void dyn_reduce_cycles(void) { + if (!decode.cycles) decode.cycles++; + gen_lea(DREG(CYCLES),DREG(CYCLES),0,0,-(Bits)decode.cycles); + gen_releasereg(DREG(CYCLES)); +} + +static void dyn_push(DynReg * dynreg) { + gen_storeflags(); + if (decode.big_op) { + gen_dop_word_imm(DOP_SUB,true,DREG(ESP),4); + } else { + gen_dop_word_imm(DOP_SUB,true,DREG(ESP),2); + } + gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP)); + gen_dop_word(DOP_AND,true,DREG(STACK),DREG(SMASK)); + gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); + if (decode.big_op) { + gen_call_function((void *)&mem_writed,"%Drd%Dd",DREG(STACK),dynreg); + } else { + //Can just push the whole 32-bit word as operand + gen_call_function((void *)&mem_writew,"%Drd%Dd",DREG(STACK),dynreg); + } + gen_releasereg(DREG(STACK)); + gen_restoreflags(); +} + +static void dyn_pop(DynReg * dynreg) { + gen_storeflags(); + gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP)); + gen_dop_word(DOP_AND,true,DREG(STACK),DREG(SMASK)); + gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS)); + if (decode.big_op) { + gen_call_function((void *)&mem_readd,"%Rd%Drd",dynreg,DREG(STACK)); + } else { + gen_call_function((void *)&mem_readw,"%Rw%Drd",dynreg,DREG(STACK)); + } + if (dynreg!=DREG(ESP)) { + if (decode.big_op) { + gen_dop_word_imm(DOP_ADD,true,DREG(ESP),4); + } else { + gen_dop_word_imm(DOP_ADD,true,DREG(ESP),2); + } + } + gen_releasereg(DREG(STACK)); + gen_restoreflags(); +} + +static void INLINE 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; + decode.modrm.rm=(decode.modrm.val & 7); +} + +static void dyn_fill_ea(bool addseg=true) { + DynReg * segbase; + if (!decode.big_addr) { + Bits imm; + switch (decode.modrm.mod) { + case 0:imm=0;break; + case 1:imm=(Bit8s)decode_fetchb();break; + case 2:imm=(Bit16s)decode_fetchw();break; + } + switch (decode.modrm.rm) { + case 0:/* BX+SI */ + gen_lea(DREG(EA),DREG(EBX),DREG(ESI),0,imm); + segbase=DREG(DS); + break; + case 1:/* BX+DI */ + gen_lea(DREG(EA),DREG(EBX),DREG(EDI),0,imm); + segbase=DREG(DS); + break; + case 2:/* BP+SI */ + gen_lea(DREG(EA),DREG(EBP),DREG(ESI),0,imm); + segbase=DREG(SS); + break; + case 3:/* BP+DI */ + gen_lea(DREG(EA),DREG(EBP),DREG(EDI),0,imm); + segbase=DREG(SS); + break; + case 4:/* SI */ + gen_lea(DREG(EA),DREG(ESI),0,0,imm); + segbase=DREG(DS); + break; + case 5:/* DI */ + gen_lea(DREG(EA),DREG(EDI),0,0,imm); + segbase=DREG(DS); + break; + case 6:/* imm/BP */ + if (!decode.modrm.mod) { + imm=(Bit16s)decode_fetchw(); + gen_dop_word_imm(DOP_MOV,true,DREG(EA),imm); + segbase=DREG(DS); + } else { + gen_lea(DREG(EA),DREG(EBP),0,0,imm); + segbase=DREG(SS); + } + break; + case 7: /* BX */ + gen_lea(DREG(EA),DREG(EBX),0,0,imm); + segbase=DREG(DS); + break; + } + gen_extend_word(false,DREG(EA),DREG(EA)); + } else { + Bits imm=0; + DynReg * base=0;DynReg * scaled=0;Bitu scale=0; + switch (decode.modrm.rm) { + case 0:base=DREG(EAX);segbase=DREG(DS);break; + case 1:base=DREG(ECX);segbase=DREG(DS);break; + case 2:base=DREG(EDX);segbase=DREG(DS);break; + case 3:base=DREG(EBX);segbase=DREG(DS);break; + case 4: /* SIB */ + { + Bitu sib=decode_fetchb(); + switch (sib & 7) { + case 0:base=DREG(EAX);segbase=DREG(DS);break; + case 1:base=DREG(ECX);segbase=DREG(DS);break; + case 2:base=DREG(EDX);segbase=DREG(DS);break; + case 3:base=DREG(EBX);segbase=DREG(DS);break; + case 4:base=DREG(ESP);segbase=DREG(SS);break; + case 5: + if (decode.modrm.mod) { + base=DREG(EBP);segbase=DREG(SS); + } else { + imm=(Bit32s)decode_fetchd();segbase=DREG(DS); + } + break; + case 6:base=DREG(ESI);segbase=DREG(DS);break; + case 7:base=DREG(EDI);segbase=DREG(DS);break; + } + static DynReg * scaledtable[8]={ + DREG(EAX),DREG(ECX),DREG(EDX),DREG(EBX), + 0,DREG(EBP),DREG(ESI),DREG(EDI), + }; + scaled=scaledtable[(sib >> 3) &7]; + scale=(sib >> 6); + } + break; /* SIB Break */ + case 5: + if (decode.modrm.mod) { + base=DREG(EBP);segbase=DREG(SS); + } else { + imm=(Bit32s)decode_fetchd();segbase=DREG(DS); + } + break; + case 6:base=DREG(ESI);segbase=DREG(DS);break; + case 7:base=DREG(EDI);segbase=DREG(DS);break; + } + switch (decode.modrm.mod) { + case 1:imm=(Bit8s)decode_fetchb();break; + case 2:imm=(Bit32s)decode_fetchd();break; + } + gen_lea(DREG(EA),base,scaled,scale,imm); + } + if (addseg) { + gen_lea(DREG(EA),DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0); + } +} + +#include "helpers.h" +#include "string.h" + +static void dyn_dop_ebgb(DualOps op) { + dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3]; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_byte(DREG(EA),DREG(TMPB),false); + gen_dop_byte(op,DREG(TMPB),0,rm_reg,decode.modrm.reg&4); + dyn_write_byte(DREG(EA),DREG(TMPB),false); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); + } else { + gen_dop_byte(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,decode.modrm.reg&4); + } +} + + +static void dyn_dop_gbeb(DualOps op) { + dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3]; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_byte(DREG(EA),DREG(TMPB),false); + gen_dop_byte(op,rm_reg,decode.modrm.reg&4,DREG(TMPB),0); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); + } else { + gen_dop_byte(op,rm_reg,decode.modrm.reg&4,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); + } +} + +static void dyn_mov_ebib(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + //TODO Maybe not use a temp register here and call mem_writeb directly? + dyn_fill_ea(); + gen_dop_byte_imm(DOP_MOV,DREG(TMPB),0,decode_fetchb()); + dyn_write_byte(DREG(EA),DREG(TMPB),false); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); + } else { + gen_dop_byte_imm(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb()); + } +} + +static void dyn_mov_ebgb(void) { + dyn_get_modrm(); + 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(DREG(EA),rm_reg,rm_regi); + gen_releasereg(DREG(EA)); + } else { + gen_dop_byte(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,rm_regi); + } +} + +static void dyn_mov_gbeb(void) { + dyn_get_modrm(); + DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_byte(DREG(EA),rm_reg,rm_regi); + gen_releasereg(DREG(EA)); + } else { + gen_dop_byte(DOP_MOV,rm_reg,rm_regi,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); + } +} + +static void dyn_dop_evgv(DualOps op) { + dyn_get_modrm(); + DynReg * rm_reg=&DynRegs[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_dop_word(op,decode.big_op,DREG(TMPW),rm_reg); + dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); + } else { + gen_dop_word(op,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg); + } +} + +static void dyn_imul_gvev(Bitu immsize) { + dyn_get_modrm();DynReg * src; + DynReg * rm_reg=&DynRegs[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea();dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + src=DREG(TMPW);gen_releasereg(DREG(EA)); + } else { + src=&DynRegs[decode.modrm.rm]; + } + switch (immsize) { + case 0:gen_imul_word(decode.big_op,rm_reg,src);break; + case 1:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit8s)decode_fetchb());break; + case 2:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit16s)decode_fetchw());break; + case 4:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit32s)decode_fetchd());break; + } + gen_releasereg(DREG(TMPW)); +} + +static void dyn_dop_gvev(DualOps op) { + dyn_get_modrm(); + DynReg * rm_reg=&DynRegs[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_dop_word(op,decode.big_op,rm_reg,DREG(TMPW)); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); + } else { + gen_dop_word(op,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]); + } +} + +static void dyn_mov_evgv(void) { + dyn_get_modrm(); + DynReg * rm_reg=&DynRegs[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_write_word(DREG(EA),rm_reg,decode.big_op); + gen_releasereg(DREG(EA)); + } else { + gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg); + } +} + +static void dyn_mov_gvev(void) { + dyn_get_modrm(); + DynReg * rm_reg=&DynRegs[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_word(DREG(EA),rm_reg,decode.big_op); + gen_releasereg(DREG(EA)); + } else { + gen_dop_word(DOP_MOV,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]); + } +} +static void dyn_mov_eviv(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + gen_dop_word_imm(DOP_MOV,decode.big_op,DREG(TMPW),decode.big_op ? decode_fetchd() : decode_fetchw()); + dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); + } else { + gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],decode.big_op ? decode_fetchd() : decode_fetchw()); + } +} + +static void dyn_mov_ev_gb(bool sign) { + dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_byte(DREG(EA),DREG(TMPB),false); + gen_releasereg(DREG(EA)); + gen_extend_byte(sign,decode.big_op,rm_reg,DREG(TMPB),0); + gen_releasereg(DREG(TMPB)); + } else { + gen_extend_byte(sign,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); + } +} + +static void dyn_mov_ev_gw(bool sign) { + if (!decode.big_op) { + dyn_mov_evgv(); + return; + } + dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_word(DREG(EA),DREG(TMPW),false); + gen_releasereg(DREG(EA)); + gen_extend_word(sign,rm_reg,DREG(TMPW)); + } else { + gen_extend_word(sign,rm_reg,&DynRegs[decode.modrm.rm]); + } +} + +static void dyn_dshift_ev_gv(bool left,bool immediate) { + dyn_get_modrm(); + DynReg * rm_reg=&DynRegs[decode.modrm.reg]; + DynReg * ea_reg; + if (decode.modrm.mod<3) { + dyn_fill_ea();ea_reg=DREG(TMPW); + dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + } else ea_reg=&DynRegs[decode.modrm.rm]; + if (immediate) gen_dshift_imm(decode.big_op,left,ea_reg,rm_reg,decode_fetchb()); + else gen_dshift_cl(decode.big_op,left,ea_reg,rm_reg,DREG(ECX)); + if (decode.modrm.mod<3) { + dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); + } +} + + +static DualOps grp1_table[8]={DOP_ADD,DOP_OR,DOP_ADC,DOP_SBB,DOP_AND,DOP_SUB,DOP_XOR,DOP_CMP}; +static void dyn_grp1_eb_ib(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_byte(DREG(EA),DREG(TMPB),false); + gen_dop_byte_imm(grp1_table[decode.modrm.reg],DREG(TMPB),0,decode_fetchb()); + if (grp1_table[decode.modrm.reg]!=DOP_CMP) dyn_write_byte(DREG(EA),DREG(TMPB),false); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); + } else { + gen_dop_byte_imm(grp1_table[decode.modrm.reg],&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb()); + } +} + +static void dyn_grp1_ev_ivx(bool withbyte) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); + gen_dop_word_imm(grp1_table[decode.modrm.reg],decode.big_op,DREG(TMPW),imm); + dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); + } else { + Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); + gen_dop_word_imm(grp1_table[decode.modrm.reg],decode.big_op,&DynRegs[decode.modrm.rm],imm); + } +} + + +static ShiftOps grp2_table[8]={ + SHIFT_ROL,SHIFT_ROR,SHIFT_RCL,SHIFT_RCR, + SHIFT_SHL,SHIFT_SHR,SHIFT_SHL,SHIFT_SAR +}; + +enum grp2_types { + grp2_1,grp2_imm,grp2_cl, +}; + +static void dyn_grp2_eb(grp2_types type) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_byte(DREG(EA),DREG(TMPB),false); + DynReg * shift; + switch (type) { + case grp2_cl:shift=DREG(ECX);break; + case grp2_1:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,1);break; + case grp2_imm:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,decode_fetchb());break; + } + gen_shift_byte(grp2_table[decode.modrm.reg],shift,DREG(TMPB),0); + dyn_write_byte(DREG(EA),DREG(TMPB),false); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB));gen_releasereg(DREG(SHIFT)); + } else { + DynReg * shift; + switch (type) { + case grp2_cl:shift=DREG(ECX);break; + case grp2_1:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,1);break; + case grp2_imm:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,decode_fetchb());break; + } + gen_shift_byte(grp2_table[decode.modrm.reg],shift,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); + gen_releasereg(DREG(SHIFT)); + } +} + +static void dyn_grp2_ev(grp2_types type) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + DynReg * shift; + switch (type) { + case grp2_cl:shift=DREG(ECX);break; + case grp2_1:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,1);break; + case grp2_imm:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,decode_fetchb());break; + } + gen_shift_word(grp2_table[decode.modrm.reg],shift,decode.big_op,DREG(TMPW)); + dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW));gen_releasereg(DREG(SHIFT)); + } else { + DynReg * shift; + switch (type) { + case grp2_cl:shift=DREG(ECX);break; + case grp2_1:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,1);break; + case grp2_imm:shift=DREG(SHIFT);gen_dop_byte_imm(DOP_MOV,DREG(SHIFT),0,decode_fetchb());break; + } + gen_shift_word(grp2_table[decode.modrm.reg],shift,decode.big_op,&DynRegs[decode.modrm.rm]); + gen_releasereg(DREG(SHIFT)); + } +} + +static void dyn_grp3_eb(void) { + DynState state;Bit8u * branch; + dyn_get_modrm();DynReg * src;Bit8u src_i; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_byte(DREG(EA),DREG(TMPB),false); + src=DREG(TMPB);src_i=0; + } else { + src=&DynRegs[decode.modrm.rm&3]; + src_i=decode.modrm.rm&4; + } + switch (decode.modrm.reg) { + case 0x0: /* test eb,ib */ + gen_dop_byte_imm(DOP_TEST,src,src_i,decode_fetchb()); + goto skipsave; + case 0x2: /* NOT Eb */ + gen_sop_byte(SOP_NOT,src,src_i); + break; + case 0x3: /* NEG Eb */ + gen_sop_byte(SOP_NEG,src,src_i); + break; + case 0x4: /* mul Eb */ + gen_mul_byte(false,DREG(EAX),src,src_i); + goto skipsave; + case 0x5: /* imul Eb */ + gen_mul_byte(true,DREG(EAX),src,src_i); + goto skipsave; + case 0x6: /* div Eb */ + case 0x7: /* idiv Eb */ + /* EAX could be used, so precache it */ + if (decode.modrm.mod==3) + gen_dop_byte(DOP_MOV,DREG(TMPB),0,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); + gen_storeflags();gen_releasereg(DREG(EAX)); + gen_call_function((decode.modrm.reg==6) ? (void *)&dyn_helper_divb : (void *)&dyn_helper_idivb, + "%Rd%Drl",DREG(TMPB),DREG(TMPB)); + gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB)); + branch=gen_create_branch(BR_Z); + dyn_savestate(&state); + dyn_reduce_cycles(); + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start); + dyn_save_flags(true); + dyn_releaseregs(); + gen_call_function((void *)&CPU_Exception,"%Id%Id",0,0); + dyn_load_flags(); + gen_return(BR_Normal); + dyn_loadstate(&state); + gen_fill_branch(branch); + gen_restoreflags(); + goto skipsave; + } + /* Save the result if memory op */ + if (decode.modrm.mod<3) dyn_write_byte(DREG(EA),DREG(TMPB),false); +skipsave: + gen_releasereg(DREG(TMPB));gen_releasereg(DREG(EA)); +} + +static void dyn_grp3_ev(void) { + DynState state;Bit8u * branch; + dyn_get_modrm();DynReg * src; + if (decode.modrm.mod<3) { + dyn_fill_ea();src=DREG(TMPW); + dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + } else src=&DynRegs[decode.modrm.rm]; + switch (decode.modrm.reg) { + case 0x0: /* test ev,iv */ + gen_dop_word_imm(DOP_TEST,decode.big_op,src,decode.big_op ? decode_fetchd() : decode_fetchw()); + goto skipsave; + case 0x2: /* NOT Ev */ + gen_sop_word(SOP_NOT,decode.big_op,src); + break; + case 0x3: /* NEG Eb */ + gen_sop_word(SOP_NEG,decode.big_op,src); + break; + case 0x4: /* mul Eb */ + gen_mul_word(false,DREG(EAX),DREG(EDX),decode.big_op,src); + goto skipsave; + case 0x5: /* imul Eb */ + gen_mul_word(true,DREG(EAX),DREG(EDX),decode.big_op,src); + goto skipsave; + case 0x6: /* div Eb */ + case 0x7: /* idiv Eb */ + /* EAX could be used, so precache it */ + if (decode.modrm.mod==3) + gen_dop_word(DOP_MOV,decode.big_op,DREG(TMPW),&DynRegs[decode.modrm.rm]); + gen_storeflags();gen_releasereg(DREG(EAX));gen_releasereg(DREG(EDX)); + void * func=(decode.modrm.reg==6) ? + (decode.big_op ? (void *)&dyn_helper_divd : (void *)&dyn_helper_divw) : + (decode.big_op ? (void *)&dyn_helper_idivd : (void *)&dyn_helper_idivw); + gen_call_function(func,"%Rd%Drd",DREG(TMPW),DREG(TMPW)); + gen_dop_word(DOP_OR,true,DREG(TMPW),DREG(TMPW)); + branch=gen_create_branch(BR_Z); + dyn_savestate(&state); + dyn_reduce_cycles(); + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start); + dyn_save_flags(true); + dyn_releaseregs(); + gen_call_function((void *)&CPU_Exception,"%Id%Id",0,0); + dyn_load_flags(); + gen_return(BR_Normal); + dyn_loadstate(&state); + gen_fill_branch(branch); + gen_restoreflags(); + goto skipsave; + } + /* Save the result if memory op */ + if (decode.modrm.mod<3) dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); +skipsave: + gen_releasereg(DREG(TMPW));gen_releasereg(DREG(EA)); +} + +static void dyn_mov_ev_seg(void) { + dyn_get_modrm(); + gen_load_host(&Segs.val[decode.modrm.reg],DREG(TMPW),2); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_write_word(DREG(EA),DREG(TMPW),false); + gen_releasereg(DREG(EA)); + } else { + gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW)); + } + gen_releasereg(DREG(TMPW)); +} + +static void dyn_load_seg(SegNames seg,DynReg * src,bool withpop) { + if (cpu.pmode) { + Bit8u * branch;DynState state; + gen_storeflags(); + gen_call_function((void *)&CPU_SetSegGeneral,"%Rd%Id%Drw",DREG(TMPB),seg,src); + gen_dop_byte(DOP_OR,DREG(TMPB),0,DREG(TMPB),0); + branch=gen_create_branch(BR_Z); + dyn_savestate(&state); + dyn_reduce_cycles(); + if (withpop) gen_dop_word_imm(DOP_SUB,true,DREG(ESP),decode.big_op ? 4 : 2); + gen_dop_word_imm(DOP_ADD,true,DREG(EIP),decode.op_start-decode.code_start); + dyn_save_flags(true); + dyn_releaseregs(); + gen_call_function((void *)&CPU_StartException,""); + dyn_load_flags(); + gen_return(BR_Normal); + dyn_loadstate(&state); + gen_fill_branch(branch); + gen_restoreflags(); + } else { + //TODO Maybe just calculate the base directly if in realmode + gen_call_function((void *)&CPU_SetSegGeneral,"%Id%Drw",seg,src); + } + gen_releasereg(&DynRegs[G_ES+seg]); + if (seg==ss) gen_releasereg(DREG(SMASK)); +} + +static void dyn_load_seg_off_ea(SegNames seg) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + gen_lea(DREG(TMPW),DREG(EA),0,0,decode.big_op ? 4:2); + dyn_read_word(DREG(TMPW),DREG(TMPW),false); + dyn_load_seg(seg,DREG(TMPW),false);gen_releasereg(DREG(TMPW)); + dyn_read_word(DREG(EA),&DynRegs[decode.modrm.reg],decode.big_op); + gen_releasereg(DREG(EA)); + } else { + IllegalOption(); + } +} + +static void dyn_mov_seg_ev(void) { + dyn_get_modrm(); + SegNames seg=(SegNames)decode.modrm.reg; + if (seg==cs) IllegalOption(); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_word(DREG(EA),DREG(EA),false); + dyn_load_seg(seg,DREG(EA),false); + gen_releasereg(DREG(EA)); + } else { + dyn_load_seg(seg,&DynRegs[decode.modrm.rm],false); + } +} + +static void dyn_push_seg(SegNames seg) { + gen_load_host(&Segs.val[seg],DREG(TMPW),2); + dyn_push(DREG(TMPW)); + gen_releasereg(DREG(TMPW)); +} + +static void dyn_pop_seg(SegNames seg) { + gen_storeflags(); + dyn_pop(DREG(TMPW)); + dyn_load_seg(seg,DREG(TMPW),true); + gen_releasereg(DREG(TMPW)); + gen_restoreflags(); +} + +static void dyn_pop_ev(void) { + gen_storeflags(); + dyn_pop(DREG(TMPW)); + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_releasereg(DREG(EA)); + } else { + gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW)); + } + gen_releasereg(DREG(TMPW)); + gen_restoreflags(); +} + +static void dyn_leave(void) { + gen_storeflags(); + gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(SMASK)); + gen_sop_word(SOP_NOT,true,DREG(TMPW)); + gen_dop_word(DOP_AND,true,DREG(ESP),DREG(TMPW)); + gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EBP)); + gen_dop_word(DOP_AND,true,DREG(TMPW),DREG(SMASK)); + gen_dop_word(DOP_OR,true,DREG(ESP),DREG(TMPW)); + dyn_pop(DREG(EBP)); + gen_releasereg(DREG(TMPW)); + gen_restoreflags(); +} + +static void dyn_segprefix(SegNames seg) { + if (decode.segprefix) IllegalOption(); + decode.segprefix=&DynRegs[G_ES+seg]; +} + +static void dyn_closeblock(BlockType type) { + //Shouldn't create empty block normally but let's do it like this + if (decode.code>decode.code_start) decode.code--; + Bitu start_page=decode.code_start >> 12; + Bitu end_page=decode.code>>12; + decode.block->page.start=(Bit16s)decode.code_start & 4095; + decode.block->page.end=(Bit16s)((end_page-start_page)*4096+(decode.code&4095)); + cache_closeblock(type); +} + +static void dyn_normal_exit(BlockReturn code) { + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_reduce_cycles(); + dyn_releaseregs(); + gen_return(code); + dyn_closeblock(BT_Normal); +} + +static void dyn_exit_link(bool dword,Bits eip_change) { + gen_lea(DREG(EIP),DREG(EIP),0,0,(decode.code-decode.code_start)+eip_change); + if (!dword) gen_extend_word(false,DREG(EIP),DREG(EIP)); + dyn_reduce_cycles(); + dyn_releaseregs(); +// gen_return(BR_Normal); + gen_jmp_ptr(&decode.block->link.to[0],offsetof(CacheBlock,cache.start)); + dyn_closeblock(BT_SingleLink); +} + +static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) { + dyn_reduce_cycles(); + dyn_releaseregs(); + Bitu eip_base=decode.code-decode.code_start; + Bit8u * data=gen_create_branch(btype); + /* Branch not taken */ + gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base); + gen_releasereg(DREG(EIP)); +// gen_return(BR_Normal); + gen_jmp_ptr(&decode.block->link.to[0],offsetof(CacheBlock,cache.start)); + gen_fill_branch(data); + /* Branch taken */ + gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base+eip_add); + gen_releasereg(DREG(EIP)); +// gen_return(BR_Normal); + gen_jmp_ptr(&decode.block->link.to[1],offsetof(CacheBlock,cache.start)); + dyn_closeblock(BT_DualLink); +} + +enum LoopTypes { + LOOP_NONE,LOOP_NE,LOOP_E, +}; + +static void dyn_loop(LoopTypes type) { + Bits eip_add=(Bit8s)decode_fetchb(); + Bitu eip_base=decode.code-decode.code_start; + gen_storeflags(); + dyn_reduce_cycles(); + Bit8u * branch1; + Bit8u * branch2=0; + gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); + dyn_releaseregs(); + branch1=gen_create_branch(BR_Z); + gen_restoreflags(true); + switch (type) { + case LOOP_NONE: + break; + case LOOP_E: + branch2=gen_create_branch(BR_NZ); + break; + case LOOP_NE: + branch2=gen_create_branch(BR_Z); + break; + } + gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base+eip_add); + gen_releasereg(DREG(EIP)); + gen_jmp_ptr(&decode.block->link.to[0],offsetof(CacheBlock,cache.start)); + gen_fill_branch(branch1); + if (branch2) gen_fill_branch(branch2); + /* Branch taken */ + gen_restoreflags(); + gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base); + gen_releasereg(DREG(EIP)); + gen_jmp_ptr(&decode.block->link.to[1],offsetof(CacheBlock,cache.start)); + dyn_closeblock(BT_DualLink); +} + +static void dyn_ret_near(Bitu bytes) { + dyn_reduce_cycles(); +//TODO maybe AND eip 0xffff, but shouldn't be needed + gen_storeflags(); + dyn_pop(DREG(EIP)); + if (bytes) gen_dop_word_imm(DOP_ADD,true,DREG(ESP),bytes); + dyn_releaseregs(); + gen_restoreflags(); + gen_return(BR_Normal); + dyn_closeblock(BT_Normal); +} + +static void dyn_ret_far(Bitu bytes) { + dyn_reduce_cycles(); +//TODO maybe AND eip 0xffff, but shouldn't be needed + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_save_flags(); + dyn_releaseregs(); + gen_call_function((void*)&CPU_RET,"%Id%Id%Id",decode.big_op,bytes,decode.code-decode.op_start); + dyn_load_flags(); + dyn_releaseregs();; + gen_return(BR_Normal); + dyn_closeblock(BT_Normal); +} + +static void dyn_call_near_imm(void) { + Bits imm; + if (decode.big_op) imm=(Bit32s)decode_fetchd(); + else imm=(Bit16s)decode_fetchw(); + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_push(DREG(EIP)); + gen_lea(DREG(EIP),DREG(EIP),0,0,imm); + if (!decode.big_op) gen_extend_word(false,DREG(EIP),DREG(EIP)); + dyn_reduce_cycles(); + dyn_releaseregs(); + gen_return(BR_Normal); +// gen_jmp_ptr(&decode.block->link.to[0],offsetof(CacheBlock,cache.start)); + dyn_closeblock(BT_SingleLink); +} + +static void dyn_call_far_imm(void) { + Bitu sel,off; + off=decode.big_op ? decode_fetchd() : decode_fetchw(); + sel=decode_fetchw(); + dyn_reduce_cycles(); + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_save_flags(); + dyn_releaseregs(); + gen_call_function((void*)&CPU_CALL,"%Id%Id%Id%Id",decode.big_op,sel,off,decode.code-decode.op_start); + dyn_load_flags(); + dyn_releaseregs(); + gen_return(BR_Normal); + dyn_closeblock(BT_Normal); +} + +static void dyn_jmp_far_imm(void) { + Bitu sel,off; + off=decode.big_op ? decode_fetchd() : decode_fetchw(); + sel=decode_fetchw(); + dyn_reduce_cycles(); + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_save_flags(); + dyn_releaseregs(); + gen_call_function((void*)&CPU_JMP,"%Id%Id%Id%Id",decode.big_op,sel,off,decode.code-decode.op_start); + dyn_load_flags(); + dyn_releaseregs(); + gen_return(BR_Normal); + dyn_closeblock(BT_Normal); +} + +static void dyn_iret(void) { + dyn_save_flags(); + dyn_reduce_cycles(); + gen_dop_word_imm(DOP_ADD,true,DREG(EIP),decode.code-decode.code_start); + dyn_releaseregs(); + gen_call_function((void*)&CPU_IRET,"%Id%Id",decode.big_op,decode.code-decode.op_start); + dyn_load_flags(); + dyn_releaseregs(); + gen_return(BR_Normal); + dyn_closeblock(BT_CheckFlags); +} + +static void dyn_interrupt(Bitu num) { + dyn_save_flags(); + dyn_reduce_cycles(); + gen_dop_word_imm(DOP_ADD,true,DREG(EIP),decode.code-decode.code_start); + dyn_releaseregs(); + gen_call_function((void*)&CPU_Interrupt,"%Id%Id%Id",num,CPU_INT_SOFTWARE,decode.code-decode.op_start); + dyn_load_flags(); + dyn_releaseregs(); + gen_return(BR_Normal); + dyn_closeblock(BT_Normal); +} + +static CacheBlock * CreateCacheBlock(PhysPt start,bool big,Bitu max_opcodes) { + Bits i; + decode.code_start=start; + decode.code=start; + Bitu cycles=0; + decode.block=cache_openblock(); + gen_save_host_direct(&cache.block.running,(Bit32u)decode.block); + for (i=0;i=G_EAX;i--) { + dyn_pop((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW)); + } + gen_restoreflags();gen_releasereg(DREG(TMPW)); + break; + //segprefix FS,GS + case 0x64:dyn_segprefix(fs);goto restart_prefix; + case 0x65:dyn_segprefix(gs);goto restart_prefix; + //Push immediates + //Operand size + case 0x66:decode.big_op=!big;goto restart_prefix; + //Address size + case 0x67:decode.big_addr=!big;goto restart_prefix; + case 0x68: /* PUSH Iv */ + gen_dop_word_imm(DOP_MOV,decode.big_op,DREG(TMPW),decode.big_op ? decode_fetchd() : decode_fetchw()); + dyn_push(DREG(TMPW)); + gen_releasereg(DREG(TMPW)); + break; + /* Imul Ivx */ + case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break; + case 0x6a: /* PUSH Ibx */ + gen_dop_word_imm(DOP_MOV,true,DREG(TMPW),(Bit8s)decode_fetchb()); + dyn_push(DREG(TMPW)); + gen_releasereg(DREG(TMPW)); + break; + /* Imul Ibx */ + case 0x6b:dyn_imul_gvev(1);break; + /* 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()); + return decode.block; + /* Group 1 */ + case 0x80:dyn_grp1_eb_ib();break; + case 0x81:dyn_grp1_ev_ivx(false);break; + case 0x82:dyn_grp1_eb_ib();break; + case 0x83:dyn_grp1_ev_ivx(true);break; + /* TEST Gb,Eb Gv,Ev */ + case 0x84:dyn_dop_gbeb(DOP_TEST);break; + case 0x85:dyn_dop_gvev(DOP_TEST);break; + /* XCHG Eb,Gb Ev,Gv */ + case 0x86:dyn_dop_ebgb(DOP_XCHG);break; + case 0x87:dyn_dop_evgv(DOP_XCHG);break; + /* MOV e,g and g,e */ + case 0x88:dyn_mov_ebgb();break; + case 0x89:dyn_mov_evgv();break; + case 0x8a:dyn_mov_gbeb();break; + case 0x8b:dyn_mov_gvev();break; + /* MOV ev,seg */ + case 0x8c:dyn_mov_ev_seg();break; + /* LEA Gv */ + case 0x8d: + dyn_get_modrm();dyn_fill_ea(false); + gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.reg],DREG(EA)); + gen_releasereg(DREG(EA)); + break; + /* Mov seg,ev */ + case 0x8e:dyn_mov_seg_ev();break; + /* POP Ev */ + case 0x8f:dyn_pop_ev();break; + //NOP + case 0x90: + break; + //XCHG ax,reg + case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: + gen_dop_word(DOP_XCHG,decode.big_op,DREG(EAX),&DynRegs[opcode&07]); + break; + /* CBW/CWDE */ + case 0x98: + /* + if (decode.big_op) gen_extend_word(true,DREG(EAX),DREG(EAX)); + else gen_extend_byte(true,false,DREG(EAX),DREG(EAX),0); + */ + gen_cbw(decode.big_op,DREG(EAX)); + break; + /* CWD/CDQ */ + case 0x99: + gen_cwd(decode.big_op,DREG(EAX),DREG(EDX)); + break; + /* CALL FAR Ip */ + case 0x9a:dyn_call_far_imm();return decode.block; + /* MOV AL,direct addresses */ + case 0xa0: + gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0, + decode.big_addr ? decode_fetchd() : decode_fetchw()); + dyn_read_byte(DREG(EA),DREG(EAX),false); + gen_releasereg(DREG(EA)); + break; + /* MOV AX,direct addresses */ + case 0xa1: + gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0, + decode.big_addr ? decode_fetchd() : decode_fetchw()); + dyn_read_word(DREG(EA),DREG(EAX),decode.big_op); + gen_releasereg(DREG(EA)); + break; + /* MOV direct address,AL */ + case 0xa2: + gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0, + decode.big_addr ? decode_fetchd() : decode_fetchw()); + dyn_write_byte(DREG(EA),DREG(EAX),false); + gen_releasereg(DREG(EA)); + break; + /* MOV direct addresses,AX */ + case 0xa3: + gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0, + decode.big_addr ? decode_fetchd() : decode_fetchw()); + dyn_write_word(DREG(EA),DREG(EAX),decode.big_op); + gen_releasereg(DREG(EA)); + break; + /* MOVSB/W/D*/ + case 0xa4:dyn_string(STR_MOVSB);break; + case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break; + /* TEST AL,AX Imm */ + case 0xa8:gen_dop_byte_imm(DOP_TEST,DREG(EAX),0,decode_fetchb());break; + case 0xa9:gen_dop_word_imm(DOP_TEST,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() : decode_fetchw());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; + //Mov Byte reg,Imm byte + case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7: + gen_dop_byte_imm(DOP_MOV,&DynRegs[opcode&3],opcode&4,decode_fetchb()); + break; + //Mov word reg imm byte,word, + case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf: + gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7],decode.big_op ? decode_fetchd() : decode_fetchw());break; + break; + //GRP2 Eb/Ev,Ib + case 0xc0:dyn_grp2_eb(grp2_imm);break; + case 0xc1:dyn_grp2_ev(grp2_imm);break; + //RET near Iw / Ret + case 0xc2:dyn_ret_near(decode_fetchw());return decode.block; + case 0xc3:dyn_ret_near(0);return decode.block; + //LES/LDS + case 0xc4:dyn_load_seg_off_ea(es);break; + case 0xc5:dyn_load_seg_off_ea(ds);break; + // MOV Eb/Ev,Ib/Iv + case 0xc6:dyn_mov_ebib();break; + case 0xc7:dyn_mov_eviv();break; + // LEAVE + case 0xc9:dyn_leave();break; + //RET far Iw / Ret + case 0xca:dyn_ret_far(decode_fetchw());return decode.block; + case 0xcb:dyn_ret_far(0);return decode.block; + /* Interrupt */ + case 0xcd:dyn_interrupt(decode_fetchb());return decode.block; + /* IRET */ + case 0xcf:dyn_iret();return decode.block; + //GRP2 Eb/Ev,1 + case 0xd0:dyn_grp2_eb(grp2_1);break; + case 0xd1:dyn_grp2_ev(grp2_1);break; + //GRP2 Eb/Ev,CL + case 0xd2:dyn_grp2_eb(grp2_cl);break; + case 0xd3:dyn_grp2_ev(grp2_cl);break; + //Loop's + case 0xe2:dyn_loop(LOOP_NONE);return decode.block; + //IN AL/AX,imm + case 0xe4:gen_call_function((void*)&IO_ReadB,"%Id%Rl",decode_fetchb(),DREG(EAX));break; + case 0xe5: + if (decode.big_op) { + gen_call_function((void*)&IO_ReadD,"%Id%Rd",decode_fetchb(),DREG(EAX)); + } else { + gen_call_function((void*)&IO_ReadW,"%Id%Rw",decode_fetchb(),DREG(EAX)); + } + break; + //OUT imm,AL + case 0xe6:gen_call_function((void*)&IO_WriteB,"%Id%Dl",decode_fetchb(),DREG(EAX));break; + case 0xe7: + if (decode.big_op) { + gen_call_function((void*)&IO_WriteD,"%Id%Dd",decode_fetchb(),DREG(EAX)); + } else { + gen_call_function((void*)&IO_WriteW,"%Id%Dw",decode_fetchb(),DREG(EAX)); + } + break; + case 0xe8: /* CALL Ivx */ + dyn_call_near_imm(); + return decode.block; + case 0xe9: /* Jmp Ivx */ + dyn_exit_link(decode.big_op,decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); + return decode.block; + /* CALL FAR Ip */ + case 0xea:dyn_jmp_far_imm();return decode.block; + /* Jmp Ibx */ + case 0xeb:dyn_exit_link(decode.big_op,(Bit8s)decode_fetchb());return decode.block; + /* IN AL/AX,DX*/ + case 0xec:gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),DREG(EAX));break; + case 0xed: + if (decode.big_op) { + gen_call_function((void*)&IO_ReadD,"%Dw%Rd",DREG(EDX),DREG(EAX)); + } else { + gen_call_function((void*)&IO_ReadW,"%Dw%Rw",DREG(EDX),DREG(EAX)); + } + break; + /* OUT DX,AL/AX */ + case 0xee:gen_call_function((void*)&IO_WriteB,"%Dw%Dl",DREG(EDX),DREG(EAX));break; + case 0xef: + if (decode.big_op) { + gen_call_function((void*)&IO_WriteD,"%Dw%Dd",DREG(EDX),DREG(EAX)); + } else { + gen_call_function((void*)&IO_WriteW,"%Dw%Dw",DREG(EDX),DREG(EAX)); + } + break; + case 0xf2: //REPNE/NZ + decode.rep=REP_NZ; + goto restart_prefix; + case 0xf3: //REPE/Z + decode.rep=REP_Z; + goto restart_prefix; + /* Change carry flag */ + case 0xf5: //CMC + case 0xf8: //CLC + case 0xf9: //STC + cache_addb(opcode);break; + /* GRP 3 Eb/EV */ + case 0xf6:dyn_grp3_eb();break; + case 0xf7:dyn_grp3_ev();break; + /* Change interrupt flag */ + case 0xfa: //CLI + gen_storeflags(); + gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FLAG_IF); + gen_restoreflags(); + break; + case 0xfb: //STI + gen_storeflags(); + gen_dop_word_imm(DOP_OR,true,DREG(FLAGS),FLAG_IF); + gen_restoreflags(); + if (max_opcodes<=0) max_opcodes=1; //Allow 1 extra opcode + break; + /* GRP 4 Eb and callback's */ + case 0xfe: + dyn_get_modrm(); + switch (decode.modrm.reg) { + case 0x0://INC Eb + case 0x1://DEC Eb + if (decode.modrm.mod<3) { + dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false); + gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,DREG(TMPB),0); + dyn_write_byte(DREG(EA),DREG(TMPB),false); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); + } else { + gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC, + &DynRegs[decode.modrm.rm&3],decode.modrm.rm&4); + } + break; + case 0x7: //CALBACK Iw + gen_save_host_direct(&core_dyn.callback,decode_fetchw()); + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_reduce_cycles(); + dyn_releaseregs(); + gen_return(BR_CallBack); + dyn_closeblock(BT_Normal); + return decode.block; + } + break; + case 0xff: + { + dyn_get_modrm();DynReg * src; + if (decode.modrm.mod<3) { + dyn_fill_ea(); + dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op); + src=DREG(TMPW); + } else src=&DynRegs[decode.modrm.rm]; + switch (decode.modrm.reg) { + case 0x0://INC Ev + case 0x1://DEC Ev + gen_sop_word(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op,src); + if (decode.modrm.mod<3){ + dyn_write_word(DREG(EA),DREG(TMPW),decode.big_op); + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPW)); + } + break; + case 0x2: /* CALL Ev */ + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_push(DREG(EIP)); + gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src); + goto core_close_block; + case 0x4: /* JMP Ev */ + gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src); + goto core_close_block; + case 0x3: /* CALL Ep */ + case 0x5: /* JMP Ep */ + dyn_save_flags(); + gen_lea(DREG(EA),DREG(EA),0,0,decode.big_op ? 4: 2); + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.code-decode.code_start); + dyn_read_word(DREG(EA),DREG(EA),false); + for (Bitu i=0;i0xff) return 1; + return 0; +} + +static Bitu dyn_helper_idivb(Bit8s val) { + if (!val) return 1; + Bits quo=(Bit16s)reg_ax / val; + reg_ah=(Bit8s)((Bit16s)reg_ax % val); + reg_al=(Bit8s)quo; + if (quo!=(Bit8s)reg_al) return 1; + return 0; +} + +static Bitu dyn_helper_divw(Bit16u val) { + if (!val) return 1; + Bitu num=(reg_dx<<16)|reg_ax; + Bitu quo=num/val; + reg_dx=(Bit16u)(num % val); + reg_ax=(Bit16u)quo; + if (quo!=reg_ax) return 1; + return 0; +} + +static Bitu dyn_helper_idivw(Bit16s val) { + if (!val) return 1; + Bits num=(reg_dx<<16)|reg_ax; + Bits quo=num/val; + reg_dx=(Bit16s)(num % val); + reg_ax=(Bit16s)quo; + if (quo!=(Bit16s)reg_ax) return 1; + return 0; +} + +static Bitu dyn_helper_divd(Bit32u val) { + if (!val) return 1; + Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; + Bit64u quo=num/val; + reg_edx=(Bit32u)(num % val); + reg_eax=(Bit32u)quo; + if (quo!=(Bit64u)reg_eax) return 1; + return 0; +} + +static Bitu dyn_helper_idivd(Bit32s val) { + if (!val) return 1; + Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; + Bit64s quo=num/val; + reg_edx=(Bit32s)(num % val); + reg_eax=(Bit32s)(quo); + if (quo!=(Bit64s)((Bit32s)reg_eax)) return 1; + return 0; +} diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h new file mode 100644 index 0000000..ad1e4d7 --- /dev/null +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -0,0 +1,799 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library 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. + */ + +static void gen_init(void); + +/* End of needed */ + +#define X86_REGS 7 +#define X86_REG_EAX 0x00 +#define X86_REG_ECX 0x01 +#define X86_REG_EDX 0x02 +#define X86_REG_EBX 0x03 +#define X86_REG_EBP 0x04 +#define X86_REG_ESI 0x05 +#define X86_REG_EDI 0x06 + +#define X86_REG_MASK(_REG_) (1 << X86_REG_ ## _REG_) + +static struct { + Bitu last_used; + Bitu stored_flags; + GenReg * regs[X86_REGS]; +} x86gen; + +class GenReg { +public: + GenReg(Bit8u _index,bool _protect) { + index=_index;protect=_protect; + notusable=false;dynreg=0; + } + DynReg * dynreg; + Bitu last_used; //Keeps track of last assigned regs + Bit8u index; + bool notusable; + bool protect; + void Load(DynReg * _dynreg) { + if (!_dynreg) return; + if (dynreg) Clear(); + dynreg=_dynreg; + last_used=x86gen.last_used; + dynreg->flags&=~DYNFLG_CHANGED; + dynreg->genreg=this; + if (dynreg->flags & (DYNFLG_LOAD|DYNFLG_ACTIVE)) { + cache_addw(0x058b+(index << (8+3))); //Mov reg,[data] + cache_addd((Bit32u)dynreg->data); + } + dynreg->flags|=DYNFLG_ACTIVE; + } + void Save(void) { + if (!dynreg) IllegalOption(); + dynreg->flags&=~DYNFLG_CHANGED; + cache_addw(0x0589+(index << (8+3))); //Mov [data],reg + cache_addd((Bit32u)dynreg->data); + } + void Release(void) { + if (!dynreg) return; + if (dynreg->flags&DYNFLG_CHANGED && dynreg->flags&DYNFLG_SAVE) { + Save(); + } + dynreg->flags&=~(DYNFLG_CHANGED|DYNFLG_ACTIVE); + dynreg->genreg=0;dynreg=0; + } + void Clear(void) { + if (!dynreg) return; + if (dynreg->flags&DYNFLG_CHANGED) { + Save(); + } + dynreg->genreg=0;dynreg=0; + } + + +}; + +static BlockReturn gen_runcode(Bit8u * code) { + BlockReturn retval; +#if defined (_MSC_VER) + __asm { +/* Prepare the flags */ + mov eax,[code] + push ebx + push ebp + push esi + push edi + mov ebx,[reg_flags] + and ebx,FMASK_TEST + push ebx + popfd + call eax +/* Restore the flags */ + pushfd + and dword ptr [reg_flags],~FMASK_TEST + pop ecx + and ecx,FMASK_TEST + or [reg_flags],ecx + pop edi + pop esi + pop ebp + pop ebx + mov [retval],eax + } +#else + __asm__ volatile ( + "movl %1,%%esi \n" + "andl %2,%%esi \n" + "pushl %%ebp \n" + "pushl %%esi \n" + "popfl \n" + "calll *%4 \n" + "popl %%ebp \n" + "pushfl \n" + "andl %3,(%1) \n" + "popl %%esi \n" + "andl %2,%%esi \n" + "orl %%esi,(%1) \n" + :"=a" (retval) + :"m" (reg_flags), "n" (FMASK_TEST),"n" (~FMASK_TEST),"r" (code) + :"%ecx","%edx","%ebx","%edi","%esi","cc","memory" + ); +#endif + return retval; +} + +static GenReg * FindDynReg(DynReg * dynreg) { + x86gen.last_used++; + if (dynreg->genreg) { + dynreg->genreg->last_used=x86gen.last_used; + return dynreg->genreg; + } + /* Find best match for selected global reg */ + Bits i; + Bits first_used,first_index; + first_used=-1; + if (dynreg->flags & DYNFLG_HAS8) { + /* Has to be eax,ebx,ecx,edx */ + for (i=first_index=0;i<=X86_REG_EDX;i++) { + GenReg * genreg=x86gen.regs[i]; + if (genreg->notusable) continue; + if (!(genreg->dynreg)) { + genreg->Load(dynreg); + return genreg; + } + if (genreg->last_usedlast_used; + first_index=i; + } + } + /* No free register found use earliest assigned one */ + GenReg * newreg=x86gen.regs[first_index]; + newreg->Load(dynreg); + return newreg; + } else { + for (i=first_index=X86_REGS-1;i>=0;i--) { + GenReg * genreg=x86gen.regs[i]; + if (genreg->notusable) continue; + if (!(genreg->dynreg)) { + genreg->Load(dynreg); + return genreg; + } + if (genreg->last_usedlast_used; + first_index=i; + } + } + /* No free register found use earliest assigned one */ + GenReg * newreg=x86gen.regs[first_index]; + newreg->Load(dynreg); + return newreg; + } +} + +static GenReg * ForceDynReg(GenReg * genreg,DynReg * dynreg) { + genreg->last_used=++x86gen.last_used; + if (dynreg->genreg==genreg) return genreg; + if (genreg->dynreg) genreg->Clear(); + if (dynreg->genreg) dynreg->genreg->Clear(); + genreg->Load(dynreg); + return genreg; +} + +static void gen_preloadreg(DynReg * dynreg) { + FindDynReg(dynreg); +} + +static void gen_releasereg(DynReg * dynreg) { + GenReg * genreg=dynreg->genreg; + if (genreg) genreg->Release(); + else dynreg->flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED); +} + +static void gen_setupreg(DynReg * dnew,DynReg * dsetup) { + dnew->flags=dsetup->flags; + if (dnew->genreg==dsetup->genreg) return; + /* Not the same genreg must be wrong */ + if (dnew->genreg) { + /* Check if the genreg i'm changing is actually linked to me */ + if (dnew->genreg->dynreg==dnew) dnew->genreg->dynreg=0; + } + dnew->genreg=dsetup->genreg; + if (dnew->genreg) dnew->genreg->dynreg=dnew; +} + +static void gen_synchreg(DynReg * dnew,DynReg * dsynch) { + /* First make sure the registers match */ + if (dnew->genreg!=dsynch->genreg) { + if (dnew->genreg) dnew->genreg->Clear(); + if (dsynch->genreg) { + dsynch->genreg->Load(dnew); + } + } + /* Always use the loadonce flag from either state */ + dnew->flags|=(dsynch->flags & dnew->flags&DYNFLG_ACTIVE); + if ((dnew->flags ^ dsynch->flags) & DYNFLG_CHANGED) { + /* Ensure the changed value gets saved */ + if (dnew->flags & DYNFLG_CHANGED) { + dnew->genreg->Save(); + } else dnew->flags|=DYNFLG_CHANGED; + } +} + +static void gen_storeflags(void) { + if (!x86gen.stored_flags) { + cache_addb(0x9c); //PUSHFD + } + x86gen.stored_flags++; +} + +static void gen_restoreflags(bool noreduce=false) { + if (noreduce) { + cache_addb(0x9d); + return; + } + if (x86gen.stored_flags) { + x86gen.stored_flags--; + if (!x86gen.stored_flags) + cache_addb(0x9d); //POPFD + } else IllegalOption(); +} + +static void gen_reinit(void) { + x86gen.last_used=0; + x86gen.stored_flags=0; + for (Bitu i=0;idynreg=0; + } +} + +static void gen_dop_byte(DualOps op,DynReg * dr1,Bit8u di1,DynReg * dr2,Bit8u di2) { + GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); + switch (op) { + case DOP_ADD:cache_addb(0x02);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_OR: cache_addb(0x0a);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_ADC:cache_addb(0x12);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_SBB:cache_addb(0x1a);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_AND:cache_addb(0x22);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_SUB:cache_addb(0x2a);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_XOR:cache_addb(0x32);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_CMP:cache_addb(0x3a);break; + case DOP_MOV:cache_addb(0x8a);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_XCHG:cache_addb(0x86);dr1->flags|=DYNFLG_CHANGED;dr2->flags|=DYNFLG_CHANGED;break; + case DOP_TEST:cache_addb(0x84);break; + default: + IllegalOption(); + } + cache_addb(0xc0+((gr1->index+di1)<<3)+gr2->index+di2); +} + +static void gen_dop_byte_imm(DualOps op,DynReg * dr1,Bit8u di1,Bitu imm) { + GenReg * gr1=FindDynReg(dr1); + switch (op) { + case DOP_ADD: + cache_addw(0xc080+((gr1->index+di1)<<8)); + dr1->flags|=DYNFLG_CHANGED; + break; + case DOP_OR: + cache_addw(0xc880+((gr1->index+di1)<<8)); + dr1->flags|=DYNFLG_CHANGED; + break; + case DOP_ADC: + cache_addw(0xd080+((gr1->index+di1)<<8)); + dr1->flags|=DYNFLG_CHANGED; + break; + case DOP_SBB: + cache_addw(0xd880+((gr1->index+di1)<<8)); + dr1->flags|=DYNFLG_CHANGED; + break; + case DOP_AND: + cache_addw(0xe080+((gr1->index+di1)<<8)); + dr1->flags|=DYNFLG_CHANGED; + break; + case DOP_SUB: + cache_addw(0xe880+((gr1->index+di1)<<8)); + dr1->flags|=DYNFLG_CHANGED; + break; + case DOP_XOR: + cache_addw(0xf080+((gr1->index+di1)<<8)); + dr1->flags|=DYNFLG_CHANGED; + break; + case DOP_CMP: + cache_addw(0xf880+((gr1->index+di1)<<8)); + break;//Doesn't change + case DOP_MOV: + cache_addb(0xb0+gr1->index+di1); + dr1->flags|=DYNFLG_CHANGED; + break; + case DOP_TEST: + cache_addw(0xc0f6+((gr1->index+di1)<<8)); + break;//Doesn't change + default: + IllegalOption(); + } + cache_addb(imm); +} + +static void gen_sop_byte(SingleOps op,DynReg * dr1,Bit8u di1) { + GenReg * gr1=FindDynReg(dr1); + switch (op) { + case SOP_INC:cache_addw(0xc0FE + ((gr1->index+di1)<<8));break; + case SOP_DEC:cache_addw(0xc8FE + ((gr1->index+di1)<<8));break; + case SOP_NOT:cache_addw(0xd0f6 + ((gr1->index+di1)<<8));break; + case SOP_NEG:cache_addw(0xd8f6 + ((gr1->index+di1)<<8));break; + default: + IllegalOption(); + } + dr1->flags|=DYNFLG_CHANGED; +} + + +static void gen_extend_word(bool sign,DynReg * ddr,DynReg * dsr) { + GenReg * gdr=FindDynReg(ddr);GenReg * gsr=FindDynReg(dsr); + if (sign) cache_addw(0xbf0f); + else cache_addw(0xb70f); + cache_addb(0xc0+(gdr->index<<3)+(gsr->index)); + ddr->flags|=DYNFLG_CHANGED; +} + +static void gen_extend_byte(bool sign,bool dword,DynReg * ddr,DynReg * dsr,Bit8u dsi) { + GenReg * gdr=FindDynReg(ddr);GenReg * gsr=FindDynReg(dsr); + if (!dword) cache_addb(0x66); + if (sign) cache_addw(0xbe0f); + else cache_addw(0xb60f); + cache_addb(0xc0+(gdr->index<<3)+(gsr->index+dsi)); + ddr->flags|=DYNFLG_CHANGED; +} + +static void gen_lea(DynReg * ddr,DynReg * dsr1,DynReg * dsr2,Bitu scale,Bits imm) { + GenReg * gdr=FindDynReg(ddr); + Bitu imm_size; + Bit8u rm_base=(gdr->index << 3); + if (dsr1) { + GenReg * gsr1=FindDynReg(dsr1); + if (!imm && (gsr1->index!=0x5)) { + 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 + } + if (dsr2) { + GenReg * gsr2=FindDynReg(dsr2); + cache_addb(0x8d); //LEA + cache_addb(rm_base+0x4); //The sib indicator + Bit8u sib=(gsr1->index)+(gsr2->index<<3)+(scale<<6); + cache_addb(sib); + } else { + cache_addb(0x8d); //LEA + cache_addb(rm_base+gsr1->index); + } + } else { + if (dsr2) { + GenReg * gsr2=FindDynReg(dsr2); + cache_addb(0x8d); //LEA + cache_addb(rm_base+0x4); //The sib indicator + Bit8u sib=(5+(gsr2->index<<3)+(scale<<6)); + cache_addb(sib); + imm_size=4; + } else { + cache_addb(0x8d); //LEA + cache_addb(rm_base+0x05); //dword imm + imm_size=4; + } + } + switch (imm_size) { + case 0: break; + case 1:cache_addb(imm);break; + case 4:cache_addd(imm);break; + } + ddr->flags|=DYNFLG_CHANGED; +} + +static void gen_dop_word(DualOps op,bool dword,DynReg * dr1,DynReg * dr2) { + GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); + if (!dword) cache_addb(0x66); + switch (op) { + case DOP_ADD:cache_addb(0x03);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_OR: cache_addb(0x0b);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_ADC:cache_addb(0x13);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_SBB:cache_addb(0x1b);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_AND:cache_addb(0x23);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_SUB:cache_addb(0x2b);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_XOR:cache_addb(0x33);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_CMP:cache_addb(0x3b);break; + case DOP_MOV:cache_addb(0x8b);dr1->flags|=DYNFLG_CHANGED;break; + case DOP_XCHG:cache_addb(0x87);dr1->flags|=DYNFLG_CHANGED;dr2->flags|=DYNFLG_CHANGED;break; + case DOP_TEST:cache_addb(0x85);break; + default: + IllegalOption(); + } + cache_addb(0xc0+(gr1->index<<3)+gr2->index); +} + +static void gen_dop_word_imm(DualOps op,bool dword,DynReg * dr1,Bits imm) { + GenReg * gr1=FindDynReg(dr1); + if (!dword) cache_addb(0x66); + switch (op) { + case DOP_ADD:cache_addw(0xc081+(gr1->index<<8));dr1->flags|=DYNFLG_CHANGED;break; + case DOP_OR: cache_addw(0xc881+(gr1->index<<8));dr1->flags|=DYNFLG_CHANGED;break; + case DOP_ADC:cache_addw(0xd081+(gr1->index<<8));dr1->flags|=DYNFLG_CHANGED;break; + case DOP_SBB:cache_addw(0xd881+(gr1->index<<8));dr1->flags|=DYNFLG_CHANGED;break; + case DOP_AND:cache_addw(0xe081+(gr1->index<<8));dr1->flags|=DYNFLG_CHANGED;break; + case DOP_SUB:cache_addw(0xe881+(gr1->index<<8));dr1->flags|=DYNFLG_CHANGED;break; + case DOP_XOR:cache_addw(0xf081+(gr1->index<<8));dr1->flags|=DYNFLG_CHANGED;break; + case DOP_CMP:cache_addw(0xf881+(gr1->index<<8));break;//Doesn't change + case DOP_MOV:cache_addb(0xb8+(gr1->index));dr1->flags|=DYNFLG_CHANGED;break; + case DOP_TEST:cache_addw(0xc0f7+(gr1->index<<8));break;//Doesn't change + default: + IllegalOption(); + } + if (dword) cache_addd(imm); + else cache_addw(imm); +} + +static void gen_imul_word(bool dword,DynReg * dr1,DynReg * dr2) { + GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); + if (!dword) cache_addb(0x66); + cache_addw(0xaf0f); + cache_addb(0xc0+(gr1->index<<3)+gr2->index); + dr1->flags|=DYNFLG_CHANGED; +} + +static void gen_imul_word_imm(bool dword,DynReg * dr1,DynReg * dr2,Bits imm) { + GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2); + if (!dword) cache_addb(0x66); + if ((imm>=-128 && imm<=127)) { + cache_addb(0x6b); + cache_addb(0xc0+(gr1->index<<3)+gr2->index); + cache_addb(imm); + } else { + cache_addb(0x69); + cache_addb(0xc0+(gr1->index<<3)+gr2->index); + if (dword) cache_addd(imm); + else cache_addw(imm); + } + dr1->flags|=DYNFLG_CHANGED; +} + + +static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) { + GenReg * gr1=FindDynReg(dr1); + if (!dword) cache_addb(0x66); + switch (op) { + case SOP_INC:cache_addb(0x40+gr1->index);break; + case SOP_DEC:cache_addb(0x48+gr1->index);break; + case SOP_NOT:cache_addw(0xd0f7+(gr1->index<<8));break; + case SOP_NEG:cache_addw(0xd8f7+(gr1->index<<8));break; + default: + IllegalOption(); + } + dr1->flags|=DYNFLG_CHANGED; +} + +static void gen_shift_byte(ShiftOps op,DynReg * drecx,DynReg * dr1,Bit8u di1) { + ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); + GenReg * gr1=FindDynReg(dr1); + switch (op) { + case SHIFT_ROL:cache_addw(0xc0d2+((gr1->index+di1)<<8));break; + case SHIFT_ROR:cache_addw(0xc8d2+((gr1->index+di1)<<8));break; + case SHIFT_RCL:cache_addw(0xd0d2+((gr1->index+di1)<<8));break; + case SHIFT_RCR:cache_addw(0xd8d2+((gr1->index+di1)<<8));break; + case SHIFT_SHL:cache_addw(0xe0d2+((gr1->index+di1)<<8));break; + case SHIFT_SHR:cache_addw(0xe8d2+((gr1->index+di1)<<8));break; + case SHIFT_SAR:cache_addw(0xf8d2+((gr1->index+di1)<<8));break; + default: + IllegalOption(); + } + dr1->flags|=DYNFLG_CHANGED; +} + +static void gen_shift_word(ShiftOps op,DynReg * drecx,bool dword,DynReg * dr1) { + ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); + GenReg * gr1=FindDynReg(dr1); + if (!dword) cache_addb(0x66); + switch (op) { + case SHIFT_ROL:cache_addw(0xc0d3+((gr1->index)<<8));break; + case SHIFT_ROR:cache_addw(0xc8d3+((gr1->index)<<8));break; + case SHIFT_RCL:cache_addw(0xd0d3+((gr1->index)<<8));break; + case SHIFT_RCR:cache_addw(0xd8d3+((gr1->index)<<8));break; + case SHIFT_SHL:cache_addw(0xe0d3+((gr1->index)<<8));break; + case SHIFT_SHR:cache_addw(0xe8d3+((gr1->index)<<8));break; + case SHIFT_SAR:cache_addw(0xf8d3+((gr1->index)<<8));break; + default: + IllegalOption(); + } + dr1->flags|=DYNFLG_CHANGED; +} + +static void gen_shift_word_imm(ShiftOps op,bool dword,DynReg * dr1,Bit8u imm) { + GenReg * gr1=FindDynReg(dr1); + if (!dword) cache_addb(0x66); + switch (op) { + case SHIFT_ROL:cache_addw(0xc0c1+((gr1->index)<<8));break; + case SHIFT_ROR:cache_addw(0xc8c1+((gr1->index)<<8));break; + case SHIFT_RCL:cache_addw(0xd0c1+((gr1->index)<<8));break; + case SHIFT_RCR:cache_addw(0xd8c1+((gr1->index)<<8));break; + case SHIFT_SHL:cache_addw(0xe0c1+((gr1->index)<<8));break; + case SHIFT_SHR:cache_addw(0xe8c1+((gr1->index)<<8));break; + case SHIFT_SAR:cache_addw(0xf8c1+((gr1->index)<<8));break; + default: + IllegalOption(); + } + cache_addb(imm); + dr1->flags|=DYNFLG_CHANGED; +} + +static void gen_cbw(bool dword,DynReg * dyn_ax) { + ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); + if (!dword) cache_addb(0x66); + cache_addb(0x98); + dyn_ax->flags|=DYNFLG_CHANGED; +} + +static void gen_cwd(bool dword,DynReg * dyn_ax,DynReg * dyn_dx) { + ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); + ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx); + if (!dword) cache_addb(0x66); + cache_addb(0x99); + dyn_ax->flags|=DYNFLG_CHANGED; + dyn_dx->flags|=DYNFLG_CHANGED; +} + +static void gen_mul_byte(bool imul,DynReg * dyn_ax,DynReg * dr1,Bit8u di1) { + ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); + GenReg * gr1=FindDynReg(dr1); + if (imul) cache_addw(0xe8f6+((gr1->index+di1)<<8)); + else cache_addw(0xe0f6+((gr1->index+di1)<<8)); + dyn_ax->flags|=DYNFLG_CHANGED; +} + +static void gen_mul_word(bool imul,DynReg * dyn_ax,DynReg * dyn_dx,bool dword,DynReg * dr1) { + ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax); + ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx); + GenReg * gr1=FindDynReg(dr1); + if (!dword) cache_addb(0x66); + if (imul) cache_addw(0xe8f7+(gr1->index<<8)); + else cache_addw(0xe0f7+(gr1->index<<8)); + dyn_ax->flags|=DYNFLG_CHANGED; + dyn_dx->flags|=DYNFLG_CHANGED; +} + +static void gen_dshift_imm(bool dword,bool left,DynReg * dr1,DynReg * dr2,Bitu imm) { + GenReg * gr1=FindDynReg(dr1); + GenReg * gr2=FindDynReg(dr2); + if (!dword) cache_addb(0x66); + if (left) cache_addw(0xa40f); //SHLD IMM + else cache_addw(0xac0f); //SHRD IMM + cache_addb(0xc0+gr1->index+(gr2->index<<3)); + cache_addb(imm); + dr1->flags|=DYNFLG_CHANGED; +} + +static void gen_dshift_cl(bool dword,bool left,DynReg * dr1,DynReg * dr2,DynReg * drecx) { + ForceDynReg(x86gen.regs[X86_REG_ECX],drecx); + GenReg * gr1=FindDynReg(dr1); + GenReg * gr2=FindDynReg(dr2); + if (!dword) cache_addb(0x66); + if (left) cache_addw(0xa50f); //SHLD CL + else cache_addw(0xad0f); //SHRD CL + cache_addb(0xc0+gr1->index+(gr2->index<<3)); + dr1->flags|=DYNFLG_CHANGED; +} + +static void gen_call_function(void * func,char * ops,...) { + Bits paramcount=0; + struct ParamInfo { + char * line; + Bitu value; + } pinfo[32]; + ParamInfo * retparam=0; + /* Clear the EAX Genreg for usage */ + x86gen.regs[X86_REG_EAX]->Clear(); + x86gen.regs[X86_REG_EAX]->notusable=true;; + /* Save the flags */ + gen_storeflags(); + /* Scan for the amount of params */ + if (ops) { + va_list params; + va_start(params,ops); + Bits pindex=0; + while (*ops) { + if (*ops=='%') { + pinfo[pindex].line=ops+1; + pinfo[pindex].value=va_arg(params,Bitu); + pindex++; + } + ops++; + } + paramcount=0; + while (pindex) { + pindex--; + char * scan=pinfo[pindex].line; + switch (*scan++) { + case 'I': /* immediate value */ + paramcount++; + cache_addb(0x68); //Push immediate + cache_addd(pinfo[pindex].value); //Push value + break; + case 'D': /* Dynamic register */ + { + bool release=false; + paramcount++; + DynReg * dynreg=(DynReg *)pinfo[pindex].value; + GenReg * genreg=FindDynReg(dynreg); + scanagain: + switch (*scan++) { + case 'd': + cache_addb(0x50+genreg->index); //Push reg + break; + case 'w': + cache_addw(0xb70f); //MOVZX EAX,reg + cache_addb(0xc0+genreg->index); + cache_addb(0x50); //Push EAX + break; + case 'l': + cache_addw(0xb60f); //MOVZX EAX,reg[0] + cache_addb(0xc0+genreg->index); + cache_addb(0x50); //Push EAX + break; + case 'h': + cache_addw(0xb60f); //MOVZX EAX,reg[1] + cache_addb(0xc4+genreg->index); + cache_addb(0x50); //Push EAX + break; + case 'r': /* release the reg afterwards */ + release=true; + goto scanagain; + default: + IllegalOption(); + } + if (release) gen_releasereg(dynreg); + } + break; + case 'R': /* Dynamic register to get the return value */ + retparam =&pinfo[pindex]; + pinfo[pindex].line=scan; + break; + default: + IllegalOption(); + } + } + } + /* Clear some unprotected registers */ + x86gen.regs[X86_REG_ECX]->Clear(); + x86gen.regs[X86_REG_EDX]->Clear(); + /* 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(paramcount*4); + } + /* Save the return value in correct register */ + if (retparam) { + DynReg * dynreg=(DynReg *)retparam->value; + GenReg * genreg=FindDynReg(dynreg); + switch (*retparam->line) { + case 'd': + cache_addw(0xc08b+(genreg->index <<(8+3))); //mov reg,eax + break; + case 'w': + cache_addb(0x66); + cache_addw(0xc08b+(genreg->index <<(8+3))); //mov reg,eax + break; + case 'l': + cache_addw(0xc08a+(genreg->index <<(8+3))); //mov reg,eax + break; + case 'h': + cache_addw(0xc08a+((genreg->index+4) <<(8+3))); //mov reg,eax + break; + } + dynreg->flags|=DYNFLG_CHANGED; + } + gen_restoreflags(); + /* Restore EAX registers to be used again */ + x86gen.regs[X86_REG_EAX]->notusable=false; +} + +static Bit8u * gen_create_branch(BranchTypes type) { + /* First free all registers */ + cache_addb(0x70+type); + cache_addb(0); + return (cache.pos-1); +} + +static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) { + *data=(from-data-1); +} + +static Bit8u * gen_create_jump(Bit8u * to=0) { + /* First free all registers */ + cache_addb(0xe9); + cache_addd(to-(cache.pos+4)); + return (cache.pos-4); +} + +static void gen_fill_jump(Bit8u * data,Bit8u * to=cache.pos) { + *(Bit32u*)data=(to-data-4); +} + + +static void gen_jmp_ptr(void * ptr,Bits imm=0) { + cache_addb(0xa1); + cache_addd((Bit32u)ptr); + cache_addb(0xff); //JMP EA + if (!imm) { //NO EBP + cache_addb(0x20); + } else if ((imm>=-128 && imm<=127)) { + cache_addb(0x60); + cache_addb(imm); + } else { + cache_addb(0xa0); + cache_addd(imm); + } +} + +static void gen_save_flags(DynReg * dynreg,bool stored) { + GenReg * genreg=FindDynReg(dynreg); + if (!stored) cache_addb(0x9c); //Pushfd + cache_addb(0x58+genreg->index); //POP 32 REG + dynreg->flags|=DYNFLG_CHANGED; +} + +static void gen_load_flags(DynReg * dynreg) { + GenReg * genreg=FindDynReg(dynreg); + cache_addb(0x50+genreg->index); //PUSH 32 + cache_addb(0x9d); //POPFD +} + +static void gen_save_host_direct(void * data,Bits imm) { + cache_addw(0x05c7); //MOV [],dword + cache_addd((Bit32u)data); + cache_addd(imm); +} + +static void gen_load_host(void * data,DynReg * dr1,Bitu size) { + GenReg * gr1=FindDynReg(dr1); + switch (size) { + case 1:cache_addw(0xb60f);break; //movzx byte + case 2:cache_addw(0xb70f);break; //movzx word + case 4:cache_addb(0x8b);break; //mov + default: + IllegalOption(); + } + cache_addb(0x5+(gr1->index<<3)); + cache_addd((Bit32u)data); + dr1->flags|=DYNFLG_CHANGED; +} + +static void gen_return(BlockReturn retcode) { + cache_addb(0xb8); + cache_addd(retcode); + cache_addb(0xc3); +} + +static void gen_init(void) { + x86gen.regs[X86_REG_EAX]=new GenReg(0,false); + x86gen.regs[X86_REG_ECX]=new GenReg(1,false); + x86gen.regs[X86_REG_EDX]=new GenReg(2,false); + x86gen.regs[X86_REG_EBX]=new GenReg(3,true); + x86gen.regs[X86_REG_EBP]=new GenReg(5,true); + x86gen.regs[X86_REG_ESI]=new GenReg(6,true); + x86gen.regs[X86_REG_EDI]=new GenReg(7,true); +} + + diff --git a/src/cpu/core_dyn_x86/string.h b/src/cpu/core_dyn_x86/string.h new file mode 100644 index 0000000..7a713d9 --- /dev/null +++ b/src/cpu/core_dyn_x86/string.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library 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. + */ + +enum STRING_OP { + STR_OUTSB=0,STR_OUTSW,STR_OUTSD, + STR_INSB=4,STR_INSW,STR_INSD, + STR_MOVSB=8,STR_MOVSW,STR_MOVSD, + STR_LODSB=12,STR_LODSW,STR_LODSD, + STR_STOSB=16,STR_STOSW,STR_STOSD, + STR_SCASB=20,STR_SCASW,STR_SCASD, + STR_CMPSB=24,STR_CMPSW,STR_CMPSD, +}; + +static void dyn_string(STRING_OP op) { + DynReg * si_base=decode.segprefix ? decode.segprefix : DREG(DS); + DynReg * di_base=DREG(ES); + DynReg * tmp_reg;bool usesi;bool usedi; + gen_storeflags(); + if (decode.rep) { + gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles); + gen_releasereg(DREG(CYCLES)); + decode.cycles=0; + } + /* Check what each string operation will be using */ + switch (op) { + case STR_MOVSB: case STR_MOVSW: case STR_MOVSD: + case STR_CMPSB: case STR_CMPSW: case STR_CMPSD: + tmp_reg=DREG(TMPB);usesi=true;usedi=true;break; + case STR_LODSB: case STR_LODSW: case STR_LODSD: + tmp_reg=DREG(EAX);usesi=true;usedi=false;break; + case STR_OUTSB: case STR_OUTSW: case STR_OUTSD: + tmp_reg=DREG(TMPB);usesi=true;usedi=false;break; + case STR_SCASB: case STR_SCASW: case STR_SCASD: + case STR_STOSB: case STR_STOSW: case STR_STOSD: + tmp_reg=DREG(EAX);usesi=false;usedi=true;break; + case STR_INSB: case STR_INSW: case STR_INSD: + tmp_reg=DREG(TMPB);usesi=false;usedi=true;break; + default: + IllegalOption(); + } + gen_load_host(&cpu.direction,DREG(TMPW),4); + switch (op & 3) { + case 0:break; + case 1:gen_shift_word_imm(SHIFT_SHL,true,DREG(TMPW),1);break; + case 2:gen_shift_word_imm(SHIFT_SHL,true,DREG(TMPW),2);break; + default: + IllegalOption(); + + } + if (usesi) { + gen_preloadreg(DREG(ESI)); + DynRegs[G_ESI].flags|=DYNFLG_CHANGED; + gen_preloadreg(si_base); + } + if (usedi) { + gen_preloadreg(DREG(EDI)); + DynRegs[G_EDI].flags|=DYNFLG_CHANGED; + gen_preloadreg(di_base); + } + if (decode.rep) { + gen_preloadreg(DREG(ECX)); + DynRegs[G_ECX].flags|=DYNFLG_CHANGED; + } + DynState rep_state; + dyn_savestate(&rep_state); + Bit8u * rep_start=cache.pos; + Bit8u * rep_ecx_jmp; + /* Check if ECX!=zero and decrease it */ + if (decode.rep) { + gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX)); + Bit8u * branch_ecx=gen_create_branch(BR_NZ); + rep_ecx_jmp=gen_create_jump(); + gen_fill_branch(branch_ecx); + gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX)); + } + if (usesi) { + if (!decode.big_addr) { + gen_extend_word(false,DREG(EA),DREG(ESI)); + gen_lea(DREG(EA),si_base,DREG(EA),0,0); + } else { + gen_lea(DREG(EA),si_base,DREG(ESI),0,0); + } + gen_dop_word(DOP_ADD,decode.big_addr,DREG(ESI),DREG(TMPW)); + switch (op&3) { + case 0:dyn_read_byte(DREG(EA),tmp_reg,false);break; + case 1:dyn_read_word(DREG(EA),tmp_reg,false);break; + case 2:dyn_read_word(DREG(EA),tmp_reg,true);break; + } + switch (op) { + case STR_OUTSB: + gen_call_function((void*)&IO_WriteB,"%Id%Dl",DREG(EDX),tmp_reg);break; + case STR_OUTSW: + gen_call_function((void*)&IO_WriteW,"%Id%Dw",DREG(EDX),tmp_reg);break; + case STR_OUTSD: + gen_call_function((void*)&IO_WriteD,"%Id%Dd",DREG(EDX),tmp_reg);break; + } + } + if (usedi) { + if (!decode.big_addr) { + gen_extend_word(false,DREG(EA),DREG(EDI)); + gen_lea(DREG(EA),di_base,DREG(EA),0,0); + } else { + gen_lea(DREG(EA),di_base,DREG(EDI),0,0); + } + gen_dop_word(DOP_ADD,decode.big_addr,DREG(EDI),DREG(TMPW)); + /* Maybe something special to be done to fill the value */ + switch (op) { + case STR_INSB: + gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),tmp_reg); + case STR_MOVSB: + case STR_STOSB: + dyn_write_byte(DREG(EA),tmp_reg,false); + break; + case STR_INSW: + gen_call_function((void*)&IO_ReadW,"%Dw%Rw",DREG(EDX),tmp_reg); + case STR_MOVSW: + case STR_STOSW: + dyn_write_word(DREG(EA),tmp_reg,false); + break; + case STR_INSD: + gen_call_function((void*)&IO_ReadD,"%Dw%Rd",DREG(EDX),tmp_reg); + case STR_MOVSD: + case STR_STOSD: + dyn_write_word(DREG(EA),tmp_reg,true); + break; + default: + IllegalOption(); + } + } + gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB)); + if (decode.rep) { + DynState cycle_state; + gen_sop_word(SOP_DEC,true,DREG(CYCLES)); + gen_releasereg(DREG(CYCLES)); + dyn_savestate(&cycle_state); + Bit8u * cycle_branch=gen_create_branch(BR_NLE); + gen_lea(DREG(EIP),DREG(EIP),0,0,decode.op_start-decode.code_start); + dyn_releaseregs(); + gen_restoreflags(true); + gen_return(BR_Cycles); + gen_fill_branch(cycle_branch); + dyn_loadstate(&cycle_state); + dyn_synchstate(&rep_state); + /* Jump back to start of ECX check */ + gen_create_jump(rep_start); + gen_fill_jump(rep_ecx_jmp); + } + gen_releasereg(DREG(TMPW)); + gen_restoreflags(); +} diff --git a/src/cpu/core_full.cpp b/src/cpu/core_full.cpp index dcaf00d..9d7868c 100644 --- a/src/cpu/core_full.cpp +++ b/src/cpu/core_full.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,6 +47,8 @@ typedef PhysPt EAPoint; #define LoadD(reg) reg #define SaveD(reg,val) reg=val + + #include "core_full/loadwrite.h" #include "core_full/support.h" #include "core_full/optable.h" @@ -59,15 +61,16 @@ typedef PhysPt EAPoint; #define EXCEPTION(blah) \ { \ Bit8u new_num=blah; \ - IPPoint=inst.start_entry; \ + IPPoint=inst.opcode_start; \ LEAVECORE; \ - Interrupt(new_num); \ + CPU_Exception(new_num,0); \ LoadIP(); \ goto nextopcode; \ } -Bits Full_DeCode(void) { +Bits CPU_Core_Full_Run(void) { FullData inst; +restart_core: if (!cpu.code.big) { inst.start_prefix=0x0;; inst.start_entry=0x0; @@ -77,8 +80,8 @@ Bits Full_DeCode(void) { } EAPoint IPPoint; LoadIP(); - flags.type=t_UNKNOWN; - while (CPU_Cycles>0) { + lflags.type=t_UNKNOWN; + while (CPU_Cycles-->0) { #if C_DEBUG cycle_count++; #if C_HEAVY_DEBUG @@ -89,7 +92,7 @@ Bits Full_DeCode(void) { }; #endif #endif - inst.start=IPPoint; + inst.opcode_start=IPPoint; inst.entry=inst.start_entry; inst.prefix=inst.start_prefix; restartopcode: @@ -99,13 +102,13 @@ restartopcode: #include "core_full/op.h" #include "core_full/save.h" nextopcode:; - CPU_Cycles--; } +exit_core: LEAVECORE; return CBRET_NONE; } -void CPU_Core_Full_Start(bool big) { - cpudecoder=&Full_DeCode; +void CPU_Core_Full_Init(void) { + } diff --git a/src/cpu/core_full/Makefile.in b/src/cpu/core_full/Makefile.in index c2c48a7..d7c58d3 100644 --- a/src/cpu/core_full/Makefile.in +++ b/src/cpu/core_full/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -253,7 +253,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -272,7 +272,6 @@ clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile - distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am @@ -295,7 +294,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/cpu/core_full/load.h b/src/cpu/core_full/load.h index b0adcce..74009c6 100644 --- a/src/cpu/core_full/load.h +++ b/src/cpu/core_full/load.h @@ -1,5 +1,12 @@ switch (inst.code.load) { /* General loading */ + case L_POPwRM: + inst.op1.w = Pop_16(); + goto case_L_MODRM; + case L_POPdRM: + inst.op1.d = Pop_32(); + goto case_L_MODRM; +case_L_MODRM: case L_MODRM: inst.rm=Fetchb(); inst.rm_index=(inst.rm >> 3) & 7; @@ -54,9 +61,12 @@ l_M_Ewx: if (inst.rm<0xc0) inst.op1.ds=(Bit16s)LoadMw(inst.rm_eaa); else inst.op1.ds=(Bit16s)reg_16(inst.rm_eai); break; + case M_EwIb: + inst.op2.d=Fetchb(); + goto l_M_Ew; case M_EwIbx: inst.op2.ds=Fetchbs(); - goto l_M_Ew; + goto l_M_Ew; case M_EwIw: inst.op2.d=Fetchw(); goto l_M_Ew; @@ -65,6 +75,11 @@ l_M_Ewx: goto l_M_EwGw; case M_EwGwIb: inst.imm.d=Fetchb(); + goto l_M_EwGw; + case M_EwGwt: + inst.op2.d=reg_16(inst.rm_index); + inst.rm_eaa+=((Bit16s)inst.op2.d >> 4) * 2; + goto l_M_Ew; l_M_EwGw: case M_EwGw: inst.op2.d=reg_16(inst.rm_index); @@ -89,6 +104,9 @@ l_M_Ew: if (inst.rm<0xc0) inst.op1.d=(Bit32s)LoadMd(inst.rm_eaa); else inst.op1.d=(Bit32s)reg_32(inst.rm_eai); break; + case M_EdIb: + inst.op2.d=Fetchb(); + goto l_M_Ed; case M_EdIbx: inst.op2.ds=Fetchbs(); goto l_M_Ed; @@ -98,8 +116,13 @@ l_M_Ew: case M_EdGdCL: inst.imm.d=reg_cl; goto l_M_EdGd; + case M_EdGdt: + inst.op2.d=reg_32(inst.rm_index); + inst.rm_eaa+=((Bit32s)inst.op2.d >> 5) * 4; + goto l_M_Ed; case M_EdGdIb: inst.imm.d=Fetchb(); + goto l_M_EdGd; l_M_EdGd: case M_EdGd: inst.op2.d=reg_32(inst.rm_index); @@ -224,8 +247,7 @@ l_M_Ed: inst.op1.d=reg_32(inst.code.extra); break; case L_FLG: - FillFlags(); - inst.op1.d = flags.word; + inst.op1.d = FillFlags(); break; case L_SEG: inst.op1.d=SegValue((SegNames)inst.code.extra); @@ -260,7 +282,7 @@ l_M_Ed: inst.repz=true; goto restartopcode; case L_PREOP: - inst.entry^=0x200; + inst.entry=inst.start_entry ^ 0x200; goto restartopcode; case L_PREADD: inst.prefix^=PREFIX_ADDR; @@ -273,49 +295,41 @@ l_M_Ed: inst.op1.d=4; break; case D_IRETw: - flags.type=t_UNKNOWN; - if (!CPU_IRET(false)) return CBRET_NONE; + LEAVECORE; + CPU_IRET(false); if (GETFLAG(IF) && PIC_IRQCheck) { return CBRET_NONE; } - LoadIP(); - goto nextopcode; + goto restart_core; case D_IRETd: - flags.type=t_UNKNOWN; - if (!CPU_IRET(true)) return CBRET_NONE; + LEAVECORE; + CPU_IRET(true); if (GETFLAG(IF) && PIC_IRQCheck) { return CBRET_NONE; } - LoadIP(); - goto nextopcode; + goto restart_core; case D_RETFwIw: - if (!CPU_RET(false,Fetchw())) { - FillFlags(); - return CBRET_NONE; + { + Bitu words=Fetchw(); + LEAVECORE; + CPU_RET(false,words); + goto restart_core; } - LoadIP(); - goto nextopcode; case D_RETFw: - if (!CPU_RET(false,0)) { - FillFlags(); - return CBRET_NONE; - } - LoadIP(); - goto nextopcode; + LEAVECORE; + CPU_RET(false,0); + goto restart_core; case D_RETFdIw: - if (!CPU_RET(true,Fetchw())) { - FillFlags(); - return CBRET_NONE; + { + Bitu words=Fetchw(); + LEAVECORE; + CPU_RET(true,words); + goto restart_core; } - LoadIP(); - goto nextopcode; case D_RETFd: - if (!CPU_RET(true,0)) { - FillFlags(); - return CBRET_NONE; - } - LoadIP(); - goto nextopcode; + LEAVECORE; + CPU_RET(true,0); + goto restart_core; /* Direct operations */ case L_STRING: #include "string.h" @@ -342,16 +356,37 @@ l_M_Ed: reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); goto nextopcode; + case D_POPSEGw: + if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_16())) { + LEAVECORE; + reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=2; + CPU_StartException();goto restart_core; + } + goto nextopcode; + case D_POPSEGd: + if (CPU_SetSegGeneral((SegNames)inst.code.extra,Pop_32())) { + LEAVECORE; + reg_eip-=(IPPoint-inst.opcode_start);reg_esp-=4; + CPU_StartException();goto restart_core; + } + goto nextopcode; case D_SETALC: reg_al = get_CF() ? 0xFF : 0; goto nextopcode; - case D_XLATw: - if (inst.prefix & PREFIX_SEG) reg_al=LoadMb(inst.seg.base+reg_bx+reg_al); - else reg_al=LoadMb(SegBase(ds)+reg_bx+reg_al); - goto nextopcode; - case D_XLATd: - if (inst.prefix & PREFIX_SEG) reg_al=LoadMb(inst.seg.base+reg_ebx+reg_al); - else reg_al=LoadMb(SegBase(ds)+reg_ebx+reg_al); + case D_XLAT: + if (inst.prefix & PREFIX_SEG) { + if (inst.prefix & PREFIX_ADDR) { + reg_al=LoadMb(inst.seg.base+(Bit32u)(reg_ebx+reg_al)); + } else { + reg_al=LoadMb(inst.seg.base+(Bit16u)(reg_bx+reg_al)); + } + } else { + if (inst.prefix & PREFIX_ADDR) { + reg_al=LoadMb(SegBase(ds)+(Bit32u)(reg_ebx+reg_al)); + } else { + reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al)); + } + } goto nextopcode; case D_CBW: reg_ax=(Bit8s)reg_al; @@ -378,25 +413,22 @@ l_M_Ed: } goto nextopcode; case D_STC: - SETFLAGBIT(CF,true); - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; + FillFlags();SETFLAGBIT(CF,true); goto nextopcode; case D_CLC: - SETFLAGBIT(CF,false); - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; + FillFlags();SETFLAGBIT(CF,false); goto nextopcode; case D_CMC: - SETFLAGBIT(CF,!get_CF()); - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; + FillFlags(); + SETFLAGBIT(CF,!(reg_flags & FLAG_CF)); goto nextopcode; case D_CLD: SETFLAGBIT(DF,false); + cpu.direction=1; goto nextopcode; case D_STD: SETFLAGBIT(DF,true); + cpu.direction=-1; goto nextopcode; case D_WAIT: case D_NOP: @@ -492,8 +524,11 @@ l_M_Ed: goto nextopcode; case D_HLT: LEAVECORE; - CPU_HLT(); + CPU_HLT(IPPoint-inst.opcode_start); return CBRET_NONE; + case D_CLTS: + //TODO Really clear it sometime + goto nextopcode; default: LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %X",inst.code.load,inst.entry); break; diff --git a/src/cpu/core_full/loadwrite.h b/src/cpu/core_full/loadwrite.h index 2a9bdb0..d26e7b2 100644 --- a/src/cpu/core_full/loadwrite.h +++ b/src/cpu/core_full/loadwrite.h @@ -27,26 +27,34 @@ static INLINE Bit32u the_Fetchd(EAPoint & loc) { #define Fetchws() (Bit16s)the_Fetchw(IPPoint) #define Fetchds() (Bit32s)the_Fetchd(IPPoint) - +#if 0 static INLINE void Push_16(Bit16u blah) { reg_esp-=2; - SaveMw(SegBase(ss) + (reg_esp & cpu.stack.mask),blah); + SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); } static INLINE void Push_32(Bit32u blah) { reg_esp-=4; - SaveMd(SegBase(ss) + (reg_esp & cpu.stack.mask),blah); + SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); } static INLINE Bit16u Pop_16(void) { - Bit16u temp=LoadMw(SegBase(ss) + (reg_esp & cpu.stack.mask)); + Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask)); reg_esp+=2; return temp; } static INLINE Bit32u Pop_32(void) { - Bit32u temp=LoadMd(SegBase(ss) + (reg_esp & cpu.stack.mask)); + Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask)); reg_esp+=4; return temp; } +#else + +#define Push_16 CPU_Push16 +#define Push_32 CPU_Push32 +#define Pop_16 CPU_Pop16 +#define Pop_32 CPU_Pop32 + +#endif diff --git a/src/cpu/core_full/op.h b/src/cpu/core_full/op.h index 3a5e420..5d4ee34 100644 --- a/src/cpu/core_full/op.h +++ b/src/cpu/core_full/op.h @@ -1,60 +1,62 @@ /* Do the actual opcode */ switch (inst.code.op) { case t_ADDb: case t_ADDw: case t_ADDd: - flags.var1.d=inst.op1.d; - flags.var2.d=inst.op2.d; - inst.op1.d=flags.result.d=flags.var1.d + flags.var2.d; - flags.type=inst.code.op; + lf_var1d=inst.op1.d; + lf_var2d=inst.op2.d; + inst.op1.d=lf_resd=lf_var1d + lf_var2d; + lflags.type=inst.code.op; break; case t_CMPb: case t_CMPw: case t_CMPd: case t_SUBb: case t_SUBw: case t_SUBd: - flags.var1.d=inst.op1.d; - flags.var2.d=inst.op2.d; - inst.op1.d=flags.result.d=flags.var1.d - flags.var2.d; - flags.type=inst.code.op; + lf_var1d=inst.op1.d; + lf_var2d=inst.op2.d; + inst.op1.d=lf_resd=lf_var1d - lf_var2d; + lflags.type=inst.code.op; break; case t_ORb: case t_ORw: case t_ORd: - flags.var1.d=inst.op1.d; - flags.var2.d=inst.op2.d; - inst.op1.d=flags.result.d=flags.var1.d | flags.var2.d; - flags.type=inst.code.op; + lf_var1d=inst.op1.d; + lf_var2d=inst.op2.d; + inst.op1.d=lf_resd=lf_var1d | lf_var2d; + lflags.type=inst.code.op; break; case t_XORb: case t_XORw: case t_XORd: - flags.var1.d=inst.op1.d; - flags.var2.d=inst.op2.d; - inst.op1.d=flags.result.d=flags.var1.d ^ flags.var2.d; - flags.type=inst.code.op; + lf_var1d=inst.op1.d; + lf_var2d=inst.op2.d; + inst.op1.d=lf_resd=lf_var1d ^ lf_var2d; + lflags.type=inst.code.op; break; case t_TESTb: case t_TESTw: case t_TESTd: case t_ANDb: case t_ANDw: case t_ANDd: - flags.var1.d=inst.op1.d; - flags.var2.d=inst.op2.d; - inst.op1.d=flags.result.d=flags.var1.d & flags.var2.d; - flags.type=inst.code.op; + lf_var1d=inst.op1.d; + lf_var2d=inst.op2.d; + inst.op1.d=lf_resd=lf_var1d & lf_var2d; + lflags.type=inst.code.op; break; case t_ADCb: case t_ADCw: case t_ADCd: - flags.oldcf=get_CF(); - flags.var1.d=inst.op1.d; - flags.var2.d=inst.op2.d; - inst.op1.d=flags.result.d=flags.var1.d + flags.var2.d + flags.oldcf; - flags.type=inst.code.op; + lflags.oldcf=(get_CF()!=0); + lf_var1d=inst.op1.d; + lf_var2d=inst.op2.d; + inst.op1.d=lf_resd=lf_var1d + lf_var2d + lflags.oldcf; + lflags.type=inst.code.op; break; case t_SBBb: case t_SBBw: case t_SBBd: - flags.oldcf=get_CF(); - flags.var1.d=inst.op1.d; - flags.var2.d=inst.op2.d; - inst.op1.d=flags.result.d=flags.var1.d - flags.var2.d - flags.oldcf; - flags.type=inst.code.op; + lflags.oldcf=(get_CF()!=0); + lf_var1d=inst.op1.d; + lf_var2d=inst.op2.d; + inst.op1.d=lf_resd=lf_var1d - lf_var2d - lflags.oldcf; + lflags.type=inst.code.op; break; case t_INCb: case t_INCw: case t_INCd: - SETFLAGBIT(CF,get_CF()); - inst.op1.d=flags.result.d=inst.op1.d+1; - flags.type=inst.code.op; + LoadCF; + lf_var1d=inst.op1.d; + inst.op1.d=lf_resd=inst.op1.d+1; + lflags.type=inst.code.op; break; case t_DECb: case t_DECw: case t_DECd: - SETFLAGBIT(CF,get_CF()); - inst.op1.d=flags.result.d=inst.op1.d-1; - flags.type=inst.code.op; + LoadCF; + lf_var1d=inst.op1.d; + inst.op1.d=lf_resd=inst.op1.d-1; + lflags.type=inst.code.op; break; /* Using the instructions.h defines */ case t_ROLb: @@ -149,19 +151,19 @@ switch (inst.code.op) { } case t_NEGb: - flags.var1.b=inst.op1.b; - inst.op1.b=flags.result.b=0-inst.op1.b; - flags.type=t_NEGb; + lf_var1b=inst.op1.b; + inst.op1.b=lf_resb=0-inst.op1.b; + lflags.type=t_NEGb; break; case t_NEGw: - flags.var1.w=inst.op1.w; - inst.op1.w=flags.result.w=0-inst.op1.w; - flags.type=t_NEGw; + lf_var1w=inst.op1.w; + inst.op1.w=lf_resw=0-inst.op1.w; + lflags.type=t_NEGw; break; case t_NEGd: - flags.var1.d=inst.op1.d; - inst.op1.d=flags.result.d=0-inst.op1.d; - flags.type=t_NEGd; + lf_var1d=inst.op1.d; + inst.op1.d=lf_resd=0-inst.op1.d; + lflags.type=t_NEGd; break; case O_NOT: @@ -218,22 +220,22 @@ switch (inst.code.op) { AAD(inst.op1.b); goto nextopcode; - case O_C_O: inst.cond=get_OF(); break; - case O_C_NO: inst.cond=!get_OF(); break; - case O_C_B: inst.cond=get_CF(); break; - case O_C_NB: inst.cond=!get_CF(); break; - case O_C_Z: inst.cond=get_ZF(); break; - case O_C_NZ: inst.cond=!get_ZF(); break; - case O_C_BE: inst.cond=get_CF() || get_ZF(); break; - case O_C_NBE: inst.cond=!get_CF() && !get_ZF(); break; - case O_C_S: inst.cond=get_SF(); break; - case O_C_NS: inst.cond=!get_SF(); break; - case O_C_P: inst.cond=get_PF(); break; - case O_C_NP: inst.cond=!get_PF(); break; - case O_C_L: inst.cond=get_SF() != get_OF(); break; - case O_C_NL: inst.cond=get_SF() == get_OF(); break; - case O_C_LE: inst.cond=get_ZF() || (get_SF() != get_OF()); break; - case O_C_NLE: inst.cond=(get_SF() == get_OF()) && !get_ZF(); break; + case O_C_O: inst.cond=TFLG_O; break; + case O_C_NO: inst.cond=TFLG_NO; break; + case O_C_B: inst.cond=TFLG_B; break; + case O_C_NB: inst.cond=TFLG_NB; break; + case O_C_Z: inst.cond=TFLG_Z; break; + case O_C_NZ: inst.cond=TFLG_NZ; break; + case O_C_BE: inst.cond=TFLG_BE; break; + case O_C_NBE: inst.cond=TFLG_NBE; break; + case O_C_S: inst.cond=TFLG_S; break; + case O_C_NS: inst.cond=TFLG_NS; break; + case O_C_P: inst.cond=TFLG_P; break; + case O_C_NP: inst.cond=TFLG_NP; break; + case O_C_L: inst.cond=TFLG_L; break; + case O_C_NL: inst.cond=TFLG_NL; break; + case O_C_LE: inst.cond=TFLG_LE; break; + case O_C_NLE: inst.cond=TFLG_NLE; break; case O_ALOP: reg_al=LoadMb(inst.rm_eaa); @@ -320,66 +322,48 @@ switch (inst.code.op) { Push_32(reg_eip); break; case O_CALLFw: - SaveIP(); - if (!CPU_CALL(false,inst.op2.d,inst.op1.d)) { - FillFlags(); - return CBRET_NONE; - } - LoadIP(); - goto nextopcode; + LEAVECORE; + CPU_CALL(false,inst.op2.d,inst.op1.d); + goto restart_core; case O_CALLFd: - SaveIP(); - if (!CPU_CALL(true,inst.op2.d,inst.op1.d)) { - FillFlags(); - return CBRET_NONE; - } - LoadIP(); - goto nextopcode; + LEAVECORE; + CPU_CALL(true,inst.op2.d,inst.op1.d); + goto restart_core; case O_JMPFw: - if (!CPU_JMP(false,inst.op2.d,inst.op1.d)){ - FillFlags(); - return CBRET_NONE; - } - LoadIP(); - goto nextopcode; + LEAVECORE; + CPU_JMP(false,inst.op2.d,inst.op1.d); + goto restart_core; case O_JMPFd: - if (!CPU_JMP(true,inst.op2.d,inst.op1.d)) { - FillFlags(); - return CBRET_NONE; - } - LoadIP(); - goto nextopcode; - + LEAVECORE; + CPU_JMP(true,inst.op2.d,inst.op1.d); + goto restart_core; case O_INT: LEAVECORE; #if C_DEBUG - if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint()) return debugCallback; - else if (DEBUG_IntBreakpoint(inst.op1.b)) return debugCallback; + if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint()) + return debugCallback; + else if (DEBUG_IntBreakpoint(inst.op1.b)) + return debugCallback; #endif - if (!Interrupt(inst.op1.b)) return CBRET_NONE; - LoadIP(); - break; + CPU_SW_Interrupt(inst.op1.b,IPPoint-inst.opcode_start); + goto restart_core; case O_INb: - reg_al=IO_Read(inst.op1.d); + reg_al=IO_ReadB(inst.op1.d); goto nextopcode; case O_INw: - reg_ax=IO_Read(inst.op1.d) | (IO_Read(inst.op1.d+1) << 8); + reg_ax=IO_ReadW(inst.op1.d); goto nextopcode; case O_INd: - reg_eax=IO_Read(inst.op1.d) | (IO_Read(inst.op1.d+1) << 8) | (IO_Read(inst.op1.d+2) << 16) | (IO_Read(inst.op1.d+3) << 24); + reg_eax=IO_ReadD(inst.op1.d); goto nextopcode; case O_OUTb: - IO_Write(inst.op1.d,reg_al); + IO_WriteB(inst.op1.d,reg_al); goto nextopcode; case O_OUTw: - IO_Write(inst.op1.d+0,(Bit8u)reg_ax); - IO_Write(inst.op1.d+1,(Bit8u)(reg_ax >> 8)); + IO_WriteW(inst.op1.d,reg_ax); goto nextopcode; case O_OUTd: - IO_Write(inst.op1.d+0,(Bit8u)reg_eax); - IO_Write(inst.op1.d+1,(Bit8u)(reg_eax >> 8)); - IO_Write(inst.op1.d+2,(Bit8u)(reg_eax >> 16)); - IO_Write(inst.op1.d+3,(Bit8u)(reg_eax >> 24)); + IO_WriteD(inst.op1.d,reg_eax); goto nextopcode; case O_CBACK: LEAVECORE; @@ -458,12 +442,19 @@ switch (inst.code.op) { LOG(LOG_CPU,LOG_ERROR)("Group 7 Illegal subfunction %X",inst.rm_index); } break; - case O_M_Cd_Rd: + case O_M_CRx_Rd: CPU_SET_CRX(inst.rm_index,inst.op1.d); break; - case O_M_Rd_Cd: + case O_M_Rd_CRx: inst.op1.d=CPU_GET_CRX(inst.rm_index); break; + case O_M_DRx_Rd: +// LOG(LOG_CPU,LOG_NORMAL)("MOV DR%d,%X",inst.rm_index,inst.op1.d); + break; + case O_M_Rd_DRx: + inst.op1.d=0; +// LOG(LOG_CPU,LOG_NORMAL)("MOV %X,DR%d",inst.op1.d,inst.rm_index); + break; case O_LAR: { FillFlags(); @@ -491,11 +482,12 @@ switch (inst.code.op) { FillFlags(); if (!inst.op1.w) { SETFLAGBIT(ZF,true); + goto nextopcode; } else { Bitu count=0; - while (count<16) { - if ((inst.op1.w>>count) & 1) break; - count++; + while (1) { + if (inst.op1.w & 0x1) break; + count++;inst.op1.w>>=1; } inst.op1.d=count; SETFLAGBIT(ZF,false); @@ -507,11 +499,12 @@ switch (inst.code.op) { FillFlags(); if (!inst.op1.d) { SETFLAGBIT(ZF,true); + goto nextopcode; } else { Bitu count=0; - while (count<32) { - if ((inst.op1.d>>count) & 1) break; - count++; + while (1) { + if (inst.op1.d & 0x1) break; + count++;inst.op1.d>>=1; } inst.op1.d=count; SETFLAGBIT(ZF,false); @@ -523,11 +516,12 @@ switch (inst.code.op) { FillFlags(); if (!inst.op1.w) { SETFLAGBIT(ZF,true); + goto nextopcode; } else { - Bits count=15; - while (count>0) { - if ((inst.op1.w>>count) & 1) break; - count--; + Bitu count=15; + while (1) { + if (inst.op1.w & 0x8000) break; + count--;inst.op1.w<<=1; } inst.op1.d=count; SETFLAGBIT(ZF,false); @@ -539,11 +533,12 @@ switch (inst.code.op) { FillFlags(); if (!inst.op1.d) { SETFLAGBIT(ZF,true); + goto nextopcode; } else { - Bits count=31; - while (count>0) { - if ((inst.op1.d>>count) & 1) break; - count--; + Bitu count=31; + while (1) { + if (inst.op1.d & 0x80000000) break; + count--;inst.op1.d<<=1; } inst.op1.d=count; SETFLAGBIT(ZF,false); @@ -551,56 +546,42 @@ switch (inst.code.op) { } break; case O_BTw: + FillFlags(); + SETFLAGBIT(CF,(inst.op1.d & (1 << (inst.op2.d & 15)))); + break; case O_BTSw: + FillFlags(); + SETFLAGBIT(CF,(inst.op1.d & (1 << (inst.op2.d & 15)))); + inst.op1.d|=(1 << (inst.op2.d & 15)); + break; case O_BTCw: + FillFlags(); + SETFLAGBIT(CF,(inst.op1.d & (1 << (inst.op2.d & 15)))); + inst.op1.d^=(1 << (inst.op2.d & 15)); + break; case O_BTRw: - { - Bitu val;PhysPt read; - Bitu mask=1 << (inst.op1.d & 15); - FillFlags(); - if (inst.rm<0xc0) { - read=inst.rm_eaa;//+2*(inst.op1.d / 16); - val=mem_readw(read); - } else { - val=reg_16(inst.rm_eai); - } - SETFLAGBIT(CF,(val&mask)>0); - if (inst.code.op==O_BTSw) val|=mask; - if (inst.code.op==O_BTRw) val&=~mask; - if (inst.code.op==O_BTCw) val^=mask; - if (inst.code.op==O_BTw) break; - if (inst.rm<0xc0) { - mem_writew(read,val); - } else { - reg_16(inst.rm_eai)=val; - } - } + FillFlags(); + SETFLAGBIT(CF,(inst.op1.d & (1 << (inst.op2.d & 15)))); + inst.op1.d&=~(1 << (inst.op2.d & 15)); break; case O_BTd: + FillFlags(); + SETFLAGBIT(CF,(inst.op1.d & (1 << (inst.op2.d & 31)))); + break; case O_BTSd: + FillFlags(); + SETFLAGBIT(CF,(inst.op1.d & (1 << (inst.op2.d & 31)))); + inst.op1.d|=(1 << (inst.op2.d & 31)); + break; case O_BTCd: + FillFlags(); + SETFLAGBIT(CF,(inst.op1.d & (1 << (inst.op2.d & 31)))); + inst.op1.d^=(1 << (inst.op2.d & 31)); + break; case O_BTRd: - { - Bitu val;PhysPt read; - Bitu mask=1 << (inst.op1.d & 31); - FillFlags(); - if (inst.rm<0xc0) { - read=inst.rm_eaa;//+4*(inst.op1.d / 32); - val=mem_readd(read); - } else { - val=reg_32(inst.rm_eai); - } - SETFLAGBIT(CF,(val&mask)>0); - if (inst.code.op==O_BTSd) val|=mask; - if (inst.code.op==O_BTRd) val&=~mask; - if (inst.code.op==O_BTCd) val^=mask; - if (inst.code.op==O_BTd) break; - if (inst.rm<0xc0) { - mem_writed(read,val); - } else { - reg_32(inst.rm_eai)=val; - } - } + FillFlags(); + SETFLAGBIT(CF,(inst.op1.d & (1 << (inst.op2.d & 31)))); + inst.op1.d&=~(1 << (inst.op2.d & 31)); break; case O_BSWAP: BSWAP(inst.op1.d); diff --git a/src/cpu/core_full/optable.h b/src/cpu/core_full/optable.h index aaee0ed..fdd3454 100644 --- a/src/cpu/core_full/optable.h +++ b/src/cpu/core_full/optable.h @@ -4,7 +4,7 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,t_ADDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ADDw ,S_Ew ,M_EwGw }, {L_MODRM ,t_ADDb ,S_Gb ,M_GbEb },{L_MODRM ,t_ADDw ,S_Gw ,M_GwEw }, {L_REGbIb ,t_ADDb ,S_REGb ,REGI_AL },{L_REGwIw ,t_ADDw ,S_REGw ,REGI_AX }, -{L_SEG ,0 ,S_PUSHw,es },{L_POPw ,0 ,S_SEGI ,es }, +{L_SEG ,0 ,S_PUSHw,es },{D_POPSEGw,0 ,0 ,es }, /* 0x08 - 0x0f */ {L_MODRM ,t_ORb ,S_Eb ,M_EbGb },{L_MODRM ,t_ORw ,S_Ew ,M_EwGw }, {L_MODRM ,t_ORb ,S_Gb ,M_GbEb },{L_MODRM ,t_ORw ,S_Gw ,M_GwEw }, @@ -15,12 +15,12 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,t_ADCb ,S_Eb ,M_EbGb },{L_MODRM ,t_ADCw ,S_Ew ,M_EwGw }, {L_MODRM ,t_ADCb ,S_Gb ,M_GbEb },{L_MODRM ,t_ADCw ,S_Gw ,M_GwEw }, {L_REGbIb ,t_ADCb ,S_REGb ,REGI_AL },{L_REGwIw ,t_ADCw ,S_REGw ,REGI_AX }, -{L_SEG ,0 ,S_PUSHw,ss },{L_POPw ,0 ,S_SEGI ,ss }, +{L_SEG ,0 ,S_PUSHw,ss },{D_POPSEGw,0 ,0 ,ss }, /* 0x18 - 0x1f */ {L_MODRM ,t_SBBb ,S_Eb ,M_EbGb },{L_MODRM ,t_SBBw ,S_Ew ,M_EwGw }, {L_MODRM ,t_SBBb ,S_Gb ,M_GbEb },{L_MODRM ,t_SBBw ,S_Gw ,M_GwEw }, {L_REGbIb ,t_SBBb ,S_REGb ,REGI_AL },{L_REGwIw ,t_SBBw ,S_REGw ,REGI_AX }, -{L_SEG ,0 ,S_PUSHw,ds },{L_POPw ,0 ,S_SEGI ,ds }, +{L_SEG ,0 ,S_PUSHw,ds },{D_POPSEGw,0 ,0 ,ds }, /* 0x20 - 0x27 */ {L_MODRM ,t_ANDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ANDw ,S_Ew ,M_EwGw }, @@ -100,7 +100,7 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,0 ,S_Eb ,M_Gb },{L_MODRM ,0 ,S_Ew ,M_Gw }, {L_MODRM ,0 ,S_Gb ,M_Eb },{L_MODRM ,0 ,S_Gw ,M_Ew }, {L_MODRM ,0 ,S_Ew ,M_SEG },{L_MODRM ,0 ,S_Gw ,M_EA }, -{L_MODRM ,0 ,S_SEGm ,M_Ew },{L_MODRM ,0 ,S_Ew ,M_POPw }, +{L_MODRM ,0 ,S_SEGm ,M_Ew },{L_POPwRM ,0 ,S_Ew ,M_None }, /* 0x90 - 0x97 */ {D_NOP ,0 ,0 ,0 },{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_CX}, @@ -150,7 +150,7 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,5 ,0 ,M_GRP_1 },{L_MODRM ,6 ,0 ,M_GRP_1 }, {L_MODRM ,5 ,0 ,M_GRP_CL },{L_MODRM ,6 ,0 ,M_GRP_CL }, {L_Ib ,O_AAM ,0 ,0 },{L_Ib ,O_AAD ,0 ,0 }, -{D_SETALC ,0 ,0 ,0 },{D_XLATw ,0 ,0 ,0 }, +{D_SETALC ,0 ,0 ,0 },{D_XLAT ,0 ,0 ,0 }, //TODO FPU /* 0xd8 - 0xdf */ {L_MODRM ,O_FPU ,0 ,0 },{L_MODRM ,O_FPU ,1 ,0 }, @@ -184,7 +184,7 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,O_GRP6w ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7w ,S_Ew ,M_Ew }, {L_MODRM ,O_LAR ,S_Gw ,M_Ew },{L_MODRM ,O_LSL ,S_Gw ,M_Ew }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{D_CLTS ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, /* 0x108 - 0x10f */ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, @@ -203,8 +203,8 @@ static OpCode OpCodeTable[1024]={ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, /* 0x120 - 0x127 */ -{L_MODRM ,O_M_Rd_Cd ,S_Ed ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,O_M_Cd_Rd ,0 ,M_Ed },{0 ,0 ,0 ,0 }, +{L_MODRM ,O_M_Rd_CRx ,S_Ed ,0 },{L_MODRM ,O_M_Rd_DRx ,S_Ed ,0 }, +{L_MODRM ,O_M_CRx_Rd ,0 ,M_Ed },{L_MODRM ,O_M_DRx_Rd ,0 ,M_Ed }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, @@ -293,24 +293,24 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,O_C_LE ,S_C_Eb,0 },{L_MODRM ,O_C_NLE ,S_C_Eb,0 }, /* 0x1a0 - 0x1a7 */ -{L_SEG ,0 ,S_PUSHw ,fs },{L_POPw ,0 ,S_SEGI ,fs }, -{D_CPUID ,0 ,0 ,0 },{L_MODRM ,O_BTw ,0 ,M_Gw }, +{L_SEG ,0 ,S_PUSHw ,fs },{D_POPSEGw,0 ,0 ,fs }, +{D_CPUID ,0 ,0 ,0 },{L_MODRM ,O_BTw ,S_Ew ,M_EwGwt }, {L_MODRM ,O_DSHLw ,S_Ew,M_EwGwIb },{L_MODRM ,O_DSHLw ,S_Ew ,M_EwGwCL }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, /* 0x1a8 - 0x1af */ -{L_SEG ,0 ,S_PUSHw ,gs },{L_POPw ,0 ,S_SEGI ,gs }, -{0 ,0 ,0 ,0 },{L_MODRM ,O_BTSw ,0 ,M_Gw }, +{L_SEG ,0 ,S_PUSHw ,gs },{D_POPSEGw,0 ,0 ,gs }, +{0 ,0 ,0 ,0 },{L_MODRM ,O_BTSw ,S_Ew ,M_EwGwt }, {L_MODRM ,O_DSHRw ,S_Ew,M_EwGwIb },{L_MODRM ,O_DSHRw ,S_Ew ,M_EwGwCL }, {0 ,0 ,0 ,0 },{L_MODRM ,O_IMULRw ,S_Gw ,M_EwxGwx }, /* 0x1b0 - 0x1b7 */ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,O_SEGSS ,S_SEGGw,M_Efw },{L_MODRM ,O_BTRw ,0 ,M_Gw }, +{L_MODRM ,O_SEGSS ,S_SEGGw,M_Efw },{L_MODRM ,O_BTRw ,S_Ew ,M_EwGwt }, {L_MODRM ,O_SEGFS ,S_SEGGw,M_Efw },{L_MODRM ,O_SEGGS ,S_SEGGw,M_Efw }, {L_MODRM ,0 ,S_Gw ,M_Eb },{L_MODRM ,0 ,S_Gw ,M_Ew }, /* 0x1b8 - 0x1bf */ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,0xe ,0 ,M_GRP },{L_MODRM ,O_BTCw ,0 ,M_Gw }, +{L_MODRM ,0xe ,0 ,M_GRP },{L_MODRM ,O_BTCw ,S_Ew ,M_EwGwt }, {L_MODRM ,O_BSFw ,S_Gw ,M_Ew },{L_MODRM ,O_BSRw ,S_Gw ,M_Ew }, {L_MODRM ,0 ,S_Gw ,M_Ebx },{L_MODRM ,0 ,S_Gw ,M_Ewx }, @@ -363,7 +363,7 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,t_ADDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ADDd ,S_Ed ,M_EdGd }, {L_MODRM ,t_ADDb ,S_Gb ,M_GbEb },{L_MODRM ,t_ADDd ,S_Gd ,M_GdEd }, {L_REGbIb ,t_ADDb ,S_REGb ,REGI_AL },{L_REGdId ,t_ADDd ,S_REGd ,REGI_AX }, -{L_SEG ,0 ,S_PUSHd,es },{L_POPd ,0 ,S_SEGI ,es }, +{L_SEG ,0 ,S_PUSHd,es },{D_POPSEGd,0 ,0 ,es }, /* 0x208 - 0x20f */ {L_MODRM ,t_ORb ,S_Eb ,M_EbGb },{L_MODRM ,t_ORd ,S_Ed ,M_EdGd }, {L_MODRM ,t_ORb ,S_Gb ,M_GbEb },{L_MODRM ,t_ORd ,S_Gd ,M_GdEd }, @@ -374,12 +374,12 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,t_ADCb ,S_Eb ,M_EbGb },{L_MODRM ,t_ADCd ,S_Ed ,M_EdGd }, {L_MODRM ,t_ADCb ,S_Gb ,M_GbEb },{L_MODRM ,t_ADCd ,S_Gd ,M_GdEd }, {L_REGbIb ,t_ADCb ,S_REGb ,REGI_AL },{L_REGdId ,t_ADCd ,S_REGd ,REGI_AX }, -{L_SEG ,0 ,S_PUSHd,ss },{L_POPd ,0 ,S_SEGI ,ss }, +{L_SEG ,0 ,S_PUSHd,ss },{D_POPSEGd,0 ,0 ,ss }, /* 0x218 - 0x21f */ {L_MODRM ,t_SBBb ,S_Eb ,M_EbGb },{L_MODRM ,t_SBBd ,S_Ed ,M_EdGd }, {L_MODRM ,t_SBBb ,S_Gb ,M_GbEb },{L_MODRM ,t_SBBd ,S_Gd ,M_GdEd }, {L_REGbIb ,t_SBBb ,S_REGb ,REGI_AL },{L_REGdId ,t_SBBd ,S_REGd ,REGI_AX }, -{L_SEG ,0 ,S_PUSHd,ds },{L_POPd ,0 ,S_SEGI ,ds }, +{L_SEG ,0 ,S_PUSHd,ds },{D_POPSEGd,0 ,0 ,ds }, /* 0x220 - 0x227 */ {L_MODRM ,t_ANDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ANDd ,S_Ed ,M_EdGd }, @@ -456,7 +456,7 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,0 ,S_Eb ,M_Gb },{L_MODRM ,0 ,S_Ed ,M_Gd }, {L_MODRM ,0 ,S_Gb ,M_Eb },{L_MODRM ,0 ,S_Gd ,M_Ed }, {L_MODRM ,0 ,S_EdMw ,M_SEG },{L_MODRM ,0 ,S_Gd ,M_EA }, -{L_MODRM ,0 ,S_SEGm ,M_Ew },{L_MODRM ,0 ,S_Ed ,M_POPd }, +{L_MODRM ,0 ,S_SEGm ,M_Ew },{L_POPdRM ,0 ,S_Ed ,M_None }, /* 0x290 - 0x297 */ {D_NOP ,0 ,0 ,0 },{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_CX}, @@ -506,7 +506,7 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,5 ,0 ,M_GRP_1 },{L_MODRM ,7 ,0 ,M_GRP_1 }, {L_MODRM ,5 ,0 ,M_GRP_CL },{L_MODRM ,7 ,0 ,M_GRP_CL }, {L_Ib ,O_AAM ,0 ,0 },{L_Ib ,O_AAD ,0 ,0 }, -{D_SETALC ,0 ,0 ,0 },{D_XLATd ,0 ,0 ,0 }, +{D_SETALC ,0 ,0 ,0 },{D_XLAT ,0 ,0 ,0 }, /* 0x2d8 - 0x2df */ {L_MODRM ,O_FPU ,0 ,0 },{L_MODRM ,O_FPU ,1 ,0 }, {L_MODRM ,O_FPU ,2 ,0 },{L_MODRM ,O_FPU ,3 ,0 }, @@ -540,7 +540,7 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,O_GRP6d ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7d ,S_Ew ,M_Ew }, {L_MODRM ,O_LAR ,S_Gd ,M_Ew },{L_MODRM ,O_LSL ,S_Gd ,M_Ew }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{D_CLTS ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, /* 0x308 - 0x30f */ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, @@ -559,8 +559,8 @@ static OpCode OpCodeTable[1024]={ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, /* 0x320 - 0x327 */ -{L_MODRM ,O_M_Rd_Cd ,S_Ed ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,O_M_Cd_Rd ,0 ,M_Ed },{0 ,0 ,0 ,0 }, +{L_MODRM ,O_M_Rd_CRx ,S_Ed ,0 },{L_MODRM ,O_M_Rd_DRx ,S_Ed ,0 }, +{L_MODRM ,O_M_CRx_Rd ,0 ,M_Ed },{L_MODRM ,O_M_DRx_Rd ,0 ,M_Ed }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, @@ -649,24 +649,24 @@ static OpCode OpCodeTable[1024]={ {L_MODRM ,O_C_LE ,S_C_Eb,0 },{L_MODRM ,O_C_NLE ,S_C_Eb,0 }, /* 0x3a0 - 0x3a7 */ -{L_SEG ,0 ,S_PUSHd ,fs },{L_POPd ,0 ,S_SEGI ,fs }, -{D_CPUID ,0 ,0 ,0 },{L_MODRM ,O_BTd ,0 ,M_Gd }, +{L_SEG ,0 ,S_PUSHd ,fs },{D_POPSEGd,0 ,0 ,fs }, +{D_CPUID ,0 ,0 ,0 },{L_MODRM ,O_BTd ,S_Ed ,M_EdGdt }, {L_MODRM ,O_DSHLd ,S_Ed,M_EdGdIb },{L_MODRM ,O_DSHLd ,S_Ed ,M_EdGdCL }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, /* 0x3a8 - 0x3af */ -{L_SEG ,0 ,S_PUSHd ,gs },{L_POPd ,0 ,S_SEGI ,gs }, -{0 ,0 ,0 ,0 },{L_MODRM ,O_BTSd ,0 ,M_Gd }, +{L_SEG ,0 ,S_PUSHd ,gs },{D_POPSEGd,0 ,0 ,gs }, +{0 ,0 ,0 ,0 },{L_MODRM ,O_BTSd ,S_Ed ,M_EdGdt }, {L_MODRM ,O_DSHRd ,S_Ed,M_EdGdIb },{L_MODRM ,O_DSHRd ,S_Ed ,M_EdGdCL }, {0 ,0 ,0 ,0 },{L_MODRM ,O_IMULRd ,S_Gd ,M_EdxGdx }, /* 0x3b0 - 0x3b7 */ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,O_SEGSS ,S_SEGGd,M_Efd },{L_MODRM ,O_BTRd ,0 ,M_Gd }, +{L_MODRM ,O_SEGSS ,S_SEGGd,M_Efd },{L_MODRM ,O_BTRd ,S_Ed ,M_EdGdt }, {L_MODRM ,O_SEGFS ,S_SEGGd,M_Efd },{L_MODRM ,O_SEGGS ,S_SEGGd,M_Efd }, {L_MODRM ,0 ,S_Gd ,M_Eb },{L_MODRM ,0 ,S_Gd ,M_Ew }, /* 0x3b8 - 0x3bf */ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{L_MODRM ,0xf ,0 ,M_GRP },{L_MODRM ,O_BTCd ,0 ,M_Gd }, +{L_MODRM ,0xf ,0 ,M_GRP },{L_MODRM ,O_BTCd ,S_Ed ,M_EdGdt }, {L_MODRM ,O_BSFd ,S_Gd ,M_Ed },{L_MODRM ,O_BSRd ,S_Gd ,M_Ed }, {L_MODRM ,0 ,S_Gd ,M_Ebx },{L_MODRM ,0 ,S_Gd ,M_Ewx }, @@ -796,13 +796,13 @@ static OpCode Groups[16][8]={ },{ /* 0x0e Group 8 Ew */ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,O_BTw ,0 ,M_Ib },{0 ,O_BTSw ,0 ,M_Ib }, -{0 ,O_BTRw ,0 ,M_Ib },{0 ,O_BTCw ,0 ,M_Ib }, +{0 ,O_BTw ,S_Ew ,M_EwIb },{0 ,O_BTSw ,S_Ew ,M_EwIb }, +{0 ,O_BTRw ,S_Ew ,M_EwIb },{0 ,O_BTCw ,S_Ew ,M_EwIb }, },{ /* 0x0f Group 8 Ed */ {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, {0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, -{0 ,O_BTd ,0 ,M_Ib },{0 ,O_BTSd ,0 ,M_Ib }, -{0 ,O_BTRd ,0 ,M_Ib },{0 ,O_BTCd ,0 ,M_Ib }, +{0 ,O_BTd ,S_Ed ,M_EdIb },{0 ,O_BTSd ,S_Ed ,M_EdIb }, +{0 ,O_BTRd ,S_Ed ,M_EdIb },{0 ,O_BTCd ,S_Ed ,M_EdIb }, diff --git a/src/cpu/core_full/save.h b/src/cpu/core_full/save.h index a5e97eb..157364c 100644 --- a/src/cpu/core_full/save.h +++ b/src/cpu/core_full/save.h @@ -55,19 +55,31 @@ switch (inst.code.save) { case S_REGd: reg_32(inst.code.extra)=inst.op1.d; break; - case S_SEGI: - CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op1.w); - break; case S_SEGm: - CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w); + if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst.op1.w)) { + LEAVECORE; + reg_eip-=(IPPoint-inst.opcode_start); + CPU_StartException(); + goto restart_core; + } break; case S_SEGGw: + if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) { + LEAVECORE; + reg_eip-=(IPPoint-inst.opcode_start); + CPU_StartException(); + goto restart_core; + } reg_16(inst.rm_index)=inst.op1.w; - CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w); break; case S_SEGGd: + if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w)) { + LEAVECORE; + reg_eip-=(IPPoint-inst.opcode_start); + CPU_StartException(); + goto restart_core; + } reg_32(inst.rm_index)=inst.op1.d; - CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w); break; case S_PUSHw: Push_16(inst.op1.w); diff --git a/src/cpu/core_full/string.h b/src/cpu/core_full/string.h index 183c2d9..5556f44 100644 --- a/src/cpu/core_full/string.h +++ b/src/cpu/core_full/string.h @@ -23,53 +23,49 @@ count=1; } else { /* Calculate amount of ops to do before cycles run out */ + CPU_Cycles++; if ((count>(Bitu)CPU_Cycles) && (inst.code.op0;count--) { - IO_Write(reg_dx,LoadMb(si_base+si_index)); + IO_WriteB(reg_dx,LoadMb(si_base+si_index)); si_index=(si_index+add_index) & add_mask; } break; case R_OUTSW: add_index<<=1; for (;count>0;count--) { - IO_Write(reg_dx,LoadMb(si_base+si_index)); - IO_Write(reg_dx+1,LoadMb(si_base+si_index+1)); + IO_WriteW(reg_dx,LoadMw(si_base+si_index)); si_index=(si_index+add_index) & add_mask; } break; case R_OUTSD: add_index<<=2; for (;count>0;count--) { - IO_Write(reg_dx,LoadMb(si_base+si_index)); - IO_Write(reg_dx+1,LoadMb(si_base+si_index+1)); - IO_Write(reg_dx+2,LoadMb(si_base+si_index+2)); - IO_Write(reg_dx+3,LoadMb(si_base+si_index+3)); + IO_WriteD(reg_dx,LoadMd(si_base+si_index)); si_index=(si_index+add_index) & add_mask; } break; case R_INSB: for (;count>0;count--) { - SaveMb(di_base+di_index,IO_Read(reg_dx)); + SaveMb(di_base+di_index,IO_ReadB(reg_dx)); di_index=(di_index+add_index) & add_mask; } break; case R_INSW: add_index<<=1; for (;count>0;count--) { - SaveMb(di_base+di_index,IO_Read(reg_dx)); - SaveMb(di_base+di_index+1,IO_Read(reg_dx+1)); + SaveMw(di_base+di_index,IO_ReadW(reg_dx)); di_index=(di_index+add_index) & add_mask; } break; diff --git a/src/cpu/core_full/support.h b/src/cpu/core_full/support.h index fd50313..9306928 100644 --- a/src/cpu/core_full/support.h +++ b/src/cpu/core_full/support.h @@ -2,7 +2,7 @@ enum { L_N=0, L_SKIP, /* Grouped ones using MOD/RM */ - L_MODRM, + L_MODRM,L_POPwRM,L_POPdRM, L_Ib,L_Iw,L_Id, L_Ibx,L_Iwx,L_Idx, //Sign extend @@ -15,8 +15,6 @@ enum { L_POPfw,L_POPfd, L_SEG, - - L_FLG,L_INTO, L_VAL, @@ -29,22 +27,23 @@ enum { D_IRETw,D_IRETd, D_PUSHAw,D_PUSHAd, D_POPAw,D_POPAd, + D_POPSEGw,D_POPSEGd, D_DAA,D_DAS, D_AAA,D_AAS, D_CBW,D_CWDE, D_CWD,D_CDQ, D_SETALC, - D_XLATw,D_XLATd, + D_XLAT, D_CLI,D_STI,D_STC,D_CLC,D_CMC,D_CLD,D_STD, D_NOP,D_WAIT, D_ENTERw,D_ENTERd, D_LEAVEw,D_LEAVEd, - L_ERROR, - + D_RETFw,D_RETFd, D_RETFwIw,D_RETFdIw, D_CPUID, - D_HLT, + D_HLT,D_CLTS, + L_ERROR, }; @@ -82,7 +81,8 @@ enum { O_GRP6w,O_GRP6d, O_GRP7w,O_GRP7d, - O_M_Cd_Rd,O_M_Rd_Cd, + O_M_CRx_Rd,O_M_Rd_CRx, + O_M_DRx_Rd,O_M_Rd_DRx, O_LAR,O_LSL, O_ARPL, @@ -106,7 +106,6 @@ enum { S_REGb,S_REGw,S_REGd, S_PUSHw,S_PUSHd, - S_SEGI, S_SEGm, S_SEGGw,S_SEGGd, @@ -131,10 +130,10 @@ enum { enum { M_None=0, M_Ebx,M_Eb,M_Gb,M_EbGb,M_GbEb, - M_Ewx,M_Ew,M_Gw,M_EwGw,M_GwEw,M_EwxGwx, - M_Edx,M_Ed,M_Gd,M_EdGd,M_GdEd,M_EdxGdx, + M_Ewx,M_Ew,M_Gw,M_EwGw,M_GwEw,M_EwxGwx,M_EwGwt, + M_Edx,M_Ed,M_Gd,M_EdGd,M_GdEd,M_EdxGdx,M_EdGdt, - M_EbIb, + M_EbIb,M_EwIb,M_EdIb, M_EwIw,M_EwIbx,M_EwxIbx,M_EwxIwx,M_EwGwIb,M_EwGwCL, M_EdId,M_EdIbx,M_EdGdIb,M_EdGdCL, @@ -156,7 +155,7 @@ struct OpCode { struct FullData { Bitu entry; - EAPoint start; + EAPoint opcode_start; Bitu rm; EAPoint rm_eaa; Bitu rm_off; diff --git a/src/cpu/core_normal.cpp b/src/cpu/core_normal.cpp index c7c77f7..ca04fbf 100644 --- a/src/cpu/core_normal.cpp +++ b/src/cpu/core_normal.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -115,6 +115,9 @@ static struct { PhysPt seg_prefix_base; bool rep_zero; GetEATable * ea_table; + struct { + bool skip; + } trap; } core; #include "instructions.h" @@ -148,14 +151,18 @@ static GetEATable * EAPrefixTable[8] = { #define EALookupTable (*(core.ea_table)) - -static Bits CPU_Core_Normal_Decode_Trap(void); - -static Bits CPU_Core_Normal_Decode(void) { +Bits CPU_Core_Normal_Run(void) { decode_start: + if (cpu.code.big) { + core.index_default=0x200; + core.prefix_default=PREFIX_ADDR; + } else { + core.index_default=0; + core.prefix_default=0; + } LOADIP; - flags.type=t_UNKNOWN; - while (CPU_Cycles>0) { + lflags.type=t_UNKNOWN; + while (CPU_Cycles-->0) { core.op_start=core.ip_lookup; core.opcode_index=core.index_default; core.prefixes=core.prefix_default; @@ -169,7 +176,6 @@ decode_start: }; #endif #endif - CPU_Cycles--; restart_prefix: core.ea_table=EAPrefixTable[core.prefixes]; restart_opcode: @@ -193,33 +199,23 @@ restart_opcode: return CBRET_NONE; } -static Bits CPU_Core_Normal_Decode_Trap(void) { +Bits CPU_Core_Normal_Trap_Run(void) { Bits oldCycles = CPU_Cycles; CPU_Cycles = 1; - Bits ret=CPU_Core_Normal_Decode(); - - Interrupt(1); - + core.trap.skip=false; + + Bits ret=CPU_Core_Normal_Run(); + if (!core.trap.skip) CPU_SW_Interrupt(1,0); CPU_Cycles = oldCycles-1; - cpudecoder = &CPU_Core_Normal_Decode; + cpudecoder = &CPU_Core_Normal_Run; return ret; } -void CPU_Core_Normal_Start(bool big) { - - if (GETFLAG(TF)) cpudecoder=CPU_Core_Normal_Decode_Trap; - else cpudecoder=CPU_Core_Normal_Decode; +void CPU_Core_Normal_Init(void) { - if (big) { - core.index_default=0x200; - core.prefix_default=PREFIX_ADDR; - } else { - core.index_default=0; - core.prefix_default=0; - } } diff --git a/src/cpu/core_normal/Makefile.in b/src/cpu/core_normal/Makefile.in index 5557fef..ff7272d 100644 --- a/src/cpu/core_normal/Makefile.in +++ b/src/cpu/core_normal/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -253,7 +253,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -272,7 +272,6 @@ clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile - distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-am @@ -295,7 +294,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/cpu/core_normal/helpers.h b/src/cpu/core_normal/helpers.h index 6a30e05..b7acd35 100644 --- a/src/cpu/core_normal/helpers.h +++ b/src/cpu/core_normal/helpers.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -141,3 +141,17 @@ } \ } +#define POPSEG(_SEG_,_VAL_,_ESP_CHANGE_) \ + if (CPU_SetSegGeneral(_SEG_,_VAL_)) { \ + LEAVECORE; \ + reg_eip-=(core.ip_lookup-core.op_start);reg_esp-=_ESP_CHANGE_; \ + CPU_StartException();goto decode_start; \ + } + +#define LOADSEG(_SEG_,_SEG_VAL_) \ + if (CPU_SetSegGeneral(_SEG_,_SEG_VAL_)) { \ + LEAVECORE; \ + reg_eip-=(core.ip_lookup-core.op_start); \ + CPU_StartException();goto decode_start; \ + } \ + diff --git a/src/cpu/core_normal/prefix_0f.h b/src/cpu/core_normal/prefix_0f.h index 0871fab..c350944 100644 --- a/src/cpu/core_normal/prefix_0f.h +++ b/src/cpu/core_normal/prefix_0f.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,7 +36,6 @@ Bitu loadval; if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} else {GetEAa;loadval=LoadMw(eaa);} - break; switch (which) { case 0x02:CPU_LLDT(loadval);break; case 0x03:CPU_LTR(loadval);break; @@ -44,6 +43,7 @@ case 0x05:CPU_VERW(loadval);break; } } + break; default: LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); } @@ -121,6 +121,8 @@ *rmrw=(Bit16u)limit; } break; + CASE_0F_B(0x06) /* CLTS */ + break; CASE_0F_B(0x20) /* MOV Rd.CRx */ { GetRM; @@ -134,13 +136,25 @@ } } break; + CASE_0F_B(0x21) /* MOV Rd,DRx */ + { + GetRM; + Bitu which=(rm >> 3) & 7; + if (rm >= 0xc0 ) { + GetEArd; + } else { + GetEAa; + LOG(LOG_CPU,LOG_ERROR)("MOV XXX,DR% with non-register",which); + } + } + break; CASE_0F_B(0x22) /* MOV CRx,Rd */ { GetRM; Bitu which=(rm >> 3) & 7; if (rm >= 0xc0 ) { GetEArd; - if (!CPU_SET_CRX(which,*eard)) goto decode_end; + CPU_SET_CRX(which,*eard); } else { GetEAa; LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which); @@ -160,88 +174,89 @@ } break; CASE_0F_W(0x80) /* JO */ - JumpSIw(get_OF());break; + JumpCond16_w(TFLG_O);break; CASE_0F_W(0x81) /* JNO */ - JumpSIw(!get_OF());break; + JumpCond16_w(TFLG_NO);break; CASE_0F_W(0x82) /* JB */ - JumpSIw(get_CF());break; + JumpCond16_w(TFLG_B);break; CASE_0F_W(0x83) /* JNB */ - JumpSIw(!get_CF());break; + JumpCond16_w(TFLG_NB);break; CASE_0F_W(0x84) /* JZ */ - JumpSIw(get_ZF());break; + JumpCond16_w(TFLG_Z);break; CASE_0F_W(0x85) /* JNZ */ - JumpSIw(!get_ZF());break; + JumpCond16_w(TFLG_NZ);break; CASE_0F_W(0x86) /* JBE */ - JumpSIw(get_CF() || get_ZF());break; + JumpCond16_w(TFLG_BE);break; CASE_0F_W(0x87) /* JNBE */ - JumpSIw(!get_CF() && !get_ZF());break; + JumpCond16_w(TFLG_NBE);break; CASE_0F_W(0x88) /* JS */ - JumpSIw(get_SF());break; + JumpCond16_w(TFLG_S);break; CASE_0F_W(0x89) /* JNS */ - JumpSIw(!get_SF());break; + JumpCond16_w(TFLG_NS);break; CASE_0F_W(0x8a) /* JP */ - JumpSIw(get_PF());break; + JumpCond16_w(TFLG_P);break; CASE_0F_W(0x8b) /* JNP */ - JumpSIw(!get_PF());break; + JumpCond16_w(TFLG_NP);break; CASE_0F_W(0x8c) /* JL */ - JumpSIw(get_SF() != get_OF());break; + JumpCond16_w(TFLG_L);break; CASE_0F_W(0x8d) /* JNL */ - JumpSIw(get_SF() == get_OF());break; + JumpCond16_w(TFLG_NL);break; CASE_0F_W(0x8e) /* JLE */ - JumpSIw(get_ZF() || (get_SF() != get_OF()));break; + JumpCond16_w(TFLG_LE);break; CASE_0F_W(0x8f) /* JNLE */ - JumpSIw((get_SF() == get_OF()) && !get_ZF());break; + JumpCond16_w(TFLG_NLE);break; CASE_0F_B(0x90) /* SETO */ - SETcc(get_OF());break; + SETcc(TFLG_O);break; CASE_0F_B(0x91) /* SETNO */ - SETcc(!get_OF());break; + SETcc(TFLG_NO);break; CASE_0F_B(0x92) /* SETB */ - SETcc(get_CF());break; + SETcc(TFLG_B);break; CASE_0F_B(0x93) /* SETNB */ - SETcc(!get_CF());break; + SETcc(TFLG_NB);break; CASE_0F_B(0x94) /* SETZ */ - SETcc(get_ZF());break; + SETcc(TFLG_Z);break; CASE_0F_B(0x95) /* SETNZ */ - SETcc(!get_ZF()); break; + SETcc(TFLG_NZ); break; CASE_0F_B(0x96) /* SETBE */ - SETcc(get_CF() || get_ZF());break; + SETcc(TFLG_BE);break; CASE_0F_B(0x97) /* SETNBE */ - SETcc(!get_CF() && !get_ZF());break; + SETcc(TFLG_NBE);break; CASE_0F_B(0x98) /* SETS */ - SETcc(get_SF());break; + SETcc(TFLG_S);break; CASE_0F_B(0x99) /* SETNS */ - SETcc(!get_SF());break; + SETcc(TFLG_NS);break; CASE_0F_B(0x9a) /* SETP */ - SETcc(get_PF());break; + SETcc(TFLG_P);break; CASE_0F_B(0x9b) /* SETNP */ - SETcc(!get_PF());break; + SETcc(TFLG_NP);break; CASE_0F_B(0x9c) /* SETL */ - SETcc(get_SF() != get_OF());break; + SETcc(TFLG_L);break; CASE_0F_B(0x9d) /* SETNL */ - SETcc(get_SF() == get_OF());break; + SETcc(TFLG_NL);break; CASE_0F_B(0x9e) /* SETLE */ - SETcc(get_ZF() || (get_SF() != get_OF()));break; + SETcc(TFLG_LE);break; CASE_0F_B(0x9f) /* SETNLE */ - SETcc((get_SF() == get_OF()) && !get_ZF());break; + SETcc(TFLG_NLE);break; CASE_0F_W(0xa0) /* PUSH FS */ Push_16(SegValue(fs));break; - CASE_0F_W(0xa1) /* POP FS */ - CPU_SetSegGeneral(fs,Pop_16());break; + CASE_0F_W(0xa1) /* POP FS */ + POPSEG(fs,Pop_16(),2); + break; CASE_0F_B(0xa2) /* CPUID */ CPU_CPUID();break; CASE_0F_W(0xa3) /* BT Ew,Gw */ { - GetRMrw; + FillFlags();GetRMrw; Bit16u mask=1 << (*rmrw & 15); if (rm >= 0xc0 ) { GetEArw; SETFLAGBIT(CF,(*earw & mask)); } else { - GetEAa;Bit16u old=LoadMw(eaa); + GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2; + Bit16u old=LoadMw(eaa); SETFLAGBIT(CF,(old & mask)); } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } CASE_0F_W(0xa4) /* SHLD Ew,Gw,Ib */ @@ -253,21 +268,21 @@ CASE_0F_W(0xa8) /* PUSH GS */ Push_16(SegValue(gs));break; CASE_0F_W(0xa9) /* POP GS */ - CPU_SetSegGeneral(gs,Pop_16());break; + POPSEG(gs,Pop_16(),2);break; CASE_0F_W(0xab) /* BTS Ew,Gw */ { - GetRMrw; + FillFlags();GetRMrw; Bit16u mask=1 << (*rmrw & 15); if (rm >= 0xc0 ) { GetEArw; SETFLAGBIT(CF,(*earw & mask)); *earw|=mask; } else { - GetEAa;Bit16u old=LoadMw(eaa); + GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2; + Bit16u old=LoadMw(eaa); SETFLAGBIT(CF,(old & mask)); SaveMw(eaa,old | mask); } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } CASE_0F_W(0xac) /* SHRD Ew,Gw,Ib */ @@ -282,35 +297,38 @@ CASE_0F_W(0xb2) /* LSS Ew */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);CPU_SetSegGeneral(ss,LoadMw(eaa+2)); + LOADSEG(ss,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa); break; } CASE_0F_W(0xb3) /* BTR Ew,Gw */ { - GetRMrw; + FillFlags();GetRMrw; Bit16u mask=1 << (*rmrw & 15); if (rm >= 0xc0 ) { GetEArw; SETFLAGBIT(CF,(*earw & mask)); *earw&= ~mask; } else { - GetEAa;Bit16u old=LoadMw(eaa); + GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2; + Bit16u old=LoadMw(eaa); SETFLAGBIT(CF,(old & mask)); SaveMw(eaa,old & ~mask); } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } CASE_0F_W(0xb4) /* LFS Ew */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);CPU_SetSegGeneral(fs,LoadMw(eaa+2)); + LOADSEG(fs,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa); break; } CASE_0F_W(0xb5) /* LGS Ew */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);CPU_SetSegGeneral(gs,LoadMw(eaa+2)); + LOADSEG(gs,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa); break; } CASE_0F_W(0xb6) /* MOVZX Gw,Eb */ @@ -330,7 +348,7 @@ } CASE_0F_W(0xba) /* GRP8 Ew,Ib */ { - GetRM; + FillFlags();GetRM; if (rm >= 0xc0 ) { GetEArw; Bit16u mask=1 << (Fetchb() & 15); @@ -370,23 +388,22 @@ E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38); } } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } CASE_0F_W(0xbb) /* BTC Ew,Gw */ { - GetRMrw; + FillFlags();GetRMrw; Bit16u mask=1 << (*rmrw & 15); if (rm >= 0xc0 ) { GetEArw; SETFLAGBIT(CF,(*earw & mask)); *earw^=mask; } else { - GetEAa;Bit16u old=LoadMw(eaa); + GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2; + Bit16u old=LoadMw(eaa); SETFLAGBIT(CF,(old & mask)); SaveMw(eaa,old ^ mask); } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } CASE_0F_W(0xbc) /* BSF Gw,Ew */ @@ -403,7 +420,7 @@ SETFLAGBIT(ZF,false); *rmrw = result; } - flags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; break; } CASE_0F_W(0xbd) /* BSR Gw,Ew */ @@ -420,7 +437,7 @@ SETFLAGBIT(ZF,false); *rmrw = result; } - flags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; break; } CASE_0F_W(0xbe) /* MOVSX Gw,Eb */ diff --git a/src/cpu/core_normal/prefix_66.h b/src/cpu/core_normal/prefix_66.h index 1530db9..df16c9a 100644 --- a/src/cpu/core_normal/prefix_66.h +++ b/src/cpu/core_normal/prefix_66.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,8 +24,8 @@ EAXId(ADDD);break; CASE_D(0x06) /* PUSH ES */ Push_32(SegValue(es));break; - CASE_D(0x07) /* POP ES */ - CPU_SetSegGeneral(es,(Bit16u)Pop_32());break; + CASE_D(0x07) /* POP ES */ + POPSEG(es,Pop_32(),4);break; CASE_D(0x09) /* OR Ed,Gd */ RMEdGd(ORD);break; CASE_D(0x0b) /* OR Gd,Ed */ @@ -40,10 +40,12 @@ RMGdEd(ADCD);break; CASE_D(0x15) /* ADC EAX,Id */ EAXId(ADCD);break; - CASE_D(0x16) /* PUSH SS */ + CASE_D(0x16) /* PUSH SS */ Push_32(SegValue(ss));break; - CASE_D(0x17) /* POP SS */ - CPU_SetSegGeneral(ss,(Bit16u)Pop_32());break; + CASE_D(0x17) /* POP SS */ + POPSEG(ss,Pop_32(),4); + CPU_Cycles++; + break; CASE_D(0x19) /* SBB Ed,Gd */ RMEdGd(SBBD);break; CASE_D(0x1b) /* SBB Gd,Ed */ @@ -53,7 +55,7 @@ CASE_D(0x1e) /* PUSH DS */ Push_32(SegValue(ds));break; CASE_D(0x1f) /* POP DS */ - CPU_SetSegGeneral(ds,(Bit16u)Pop_32());break; + POPSEG(ds,Pop_32(),4);break; CASE_D(0x21) /* AND Ed,Gd */ RMEdGd(ANDD);break; CASE_D(0x23) /* AND Gd,Ed */ @@ -143,9 +145,11 @@ CASE_D(0x5f) /* POP EDI */ reg_edi=Pop_32();break; CASE_D(0x60) /* PUSHAD */ + { + Bitu tmpesp = reg_esp; Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx); - Push_32(reg_esp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi); - break; + Push_32(tmpesp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi); + }; break; CASE_D(0x61) /* POPAD */ reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); @@ -186,6 +190,38 @@ CASE_D(0x6b) /* IMUL Gd,Ed,Ib */ RMGdEdOp3(DIMULD,Fetchbs()); break; + CASE_D(0x70) /* JO */ + JumpCond32_b(TFLG_O);break; + CASE_D(0x71) /* JNO */ + JumpCond32_b(TFLG_NO);break; + CASE_D(0x72) /* JB */ + JumpCond32_b(TFLG_B);break; + CASE_D(0x73) /* JNB */ + JumpCond32_b(TFLG_NB);break; + CASE_D(0x74) /* JZ */ + JumpCond32_b(TFLG_Z);break; + CASE_D(0x75) /* JNZ */ + JumpCond32_b(TFLG_NZ);break; + CASE_D(0x76) /* JBE */ + JumpCond32_b(TFLG_BE);break; + CASE_D(0x77) /* JNBE */ + JumpCond32_b(TFLG_NBE);break; + CASE_D(0x78) /* JS */ + JumpCond32_b(TFLG_S);break; + CASE_D(0x79) /* JNS */ + JumpCond32_b(TFLG_NS);break; + CASE_D(0x7a) /* JP */ + JumpCond32_b(TFLG_P);break; + CASE_D(0x7b) /* JNP */ + JumpCond32_b(TFLG_NP);break; + CASE_D(0x7c) /* JL */ + JumpCond32_b(TFLG_L);break; + CASE_D(0x7d) /* JNL */ + JumpCond32_b(TFLG_NL);break; + CASE_D(0x7e) /* JLE */ + JumpCond32_b(TFLG_LE);break; + CASE_D(0x7f) /* JNLE */ + JumpCond32_b(TFLG_NLE);break; CASE_D(0x81) /* Grpl Ed,Id */ { GetRM;Bitu which=(rm>>3)&7; @@ -307,9 +343,10 @@ } CASE_D(0x8f) /* POP Ed */ { + Bit32u val=Pop_32(); GetRM; - if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();} - else {GetEAa;SaveMd(eaa,Pop_32());} + if (rm >= 0xc0 ) {GetEArd;*eard=val;} + else {GetEAa;SaveMd(eaa,val);} break; } CASE_D(0x91) /* XCHG ECX,EAX */ @@ -341,27 +378,28 @@ CASE_D(0x9a) /* CALL FAR Ad */ { Bit32u newip=Fetchd();Bit16u newcs=Fetchw(); - SAVEIP; - if (CPU_CALL(true,newcs,newip)) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } - break; + LEAVECORE; + CPU_CALL(true,newcs,newip); + goto decode_start; } CASE_D(0x9c) /* PUSHFD */ FillFlags(); - Push_32(flags.word); + Push_32(reg_flags); break; CASE_D(0x9d) /* POPFD */ + if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { + LEAVECORE;reg_eip-=core.ip_lookup-core.op_start; + CPU_Exception(13,0); + goto decode_start; + } SETFLAGSd(Pop_32()) #if CPU_TRAP_CHECK if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Decode_Trap; + cpudecoder=CPU_Core_Normal_Trap_Run; goto decode_end; } #endif -#ifdef CPU_PIC_CHECK +#if CPU_PIC_CHECK if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; #endif @@ -420,13 +458,15 @@ CASE_D(0xc4) /* LES */ { GetRMrd;GetEAa; - *rmrd=LoadMd(eaa);CPU_SetSegGeneral(es,LoadMw(eaa+4)); + LOADSEG(es,LoadMw(eaa+4)); + *rmrd=LoadMd(eaa); break; } CASE_D(0xc5) /* LDS */ { GetRMrd;GetEAa; - *rmrd=LoadMd(eaa);CPU_SetSegGeneral(ds,LoadMw(eaa+4)); + LOADSEG(ds,LoadMw(eaa+4)); + *rmrd=LoadMd(eaa); break; } CASE_D(0xc7) /* MOV Ed,Id */ @@ -475,61 +515,43 @@ break; CASE_D(0xca) /* RETF Iw */ { - if (CPU_RET(true,Fetchw())) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } - break; - } + Bitu words=Fetchw(); + LEAVECORE; + CPU_RET(true,words,core.ip_lookup-core.op_start); + goto decode_start; + } CASE_D(0xcb) /* RETF */ { - if (CPU_RET(true,0)) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } - break; + LEAVECORE; + CPU_RET(true,0,core.ip_lookup-core.op_start); + goto decode_start; } CASE_D(0xcf) /* IRET */ { - if (CPU_IRET(true)) { + LEAVECORE; + CPU_IRET(true); #if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Decode_Trap; - return CBRET_NONE; - } + if (GETFLAG(TF)) { + cpudecoder=CPU_Core_Normal_Trap_Run; + return CBRET_NONE; + } #endif -#ifdef CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; +#if CPU_PIC_CHECK + if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; #endif //TODO TF check - goto decode_start; - } else return CBRET_NONE; - break; + goto decode_start; } CASE_D(0xd1) /* GRP2 Ed,1 */ GRP2D(1);break; CASE_D(0xd3) /* GRP2 Ed,CL */ GRP2D(reg_cl);break; CASE_D(0xe5) /* IN EAX,Ib */ - { - Bit16u port=Fetchb(); - reg_eax=IO_Read(port) | - (IO_Read(port+1) << 8 ) | - (IO_Read(port+2) << 16 ) | - (IO_Read(port+3) << 24 ); - break; - } + reg_eax=IO_ReadD(Fetchb()); + break; CASE_D(0xe7) /* OUT Ib,EAX */ - { - Bit16u port=Fetchb(); - IO_Write(port+0,(Bit8u)(reg_eax >> 0)); - IO_Write(port+1,(Bit8u)(reg_eax >> 8)); - IO_Write(port+2,(Bit8u)(reg_eax >> 16)); - IO_Write(port+3,(Bit8u)(reg_eax >> 24)); - break; - } + IO_WriteD(Fetchb(),reg_eax); + break; CASE_D(0xe8) /* CALL Jd */ { Bit32s newip=Fetchds(); @@ -544,25 +566,15 @@ { Bit32u newip=Fetchd(); Bit16u newcs=Fetchw(); - SAVEIP; - if (CPU_JMP(true,newcs,newip)) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } - break; + LEAVECORE; + CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start); + goto decode_start; } CASE_D(0xed) /* IN EAX,DX */ - reg_eax=IO_Read(reg_dx) | - (IO_Read(reg_dx+1) << 8) | - (IO_Read(reg_dx+2) << 16) | - (IO_Read(reg_dx+3) << 24); + reg_eax=IO_ReadD(reg_dx); break; CASE_D(0xef) /* OUT DX,EAX */ - IO_Write(reg_dx,(Bit8u)(reg_eax>>0)); - IO_Write(reg_dx+1,(Bit8u)(reg_eax>>8)); - IO_Write(reg_dx+2,(Bit8u)(reg_eax>>16)); - IO_Write(reg_dx+3,(Bit8u)(reg_eax>>24)); + IO_WriteD(reg_dx,reg_eax); break; CASE_D(0xf7) /* GRP3 Ed(,Id) */ { @@ -583,13 +595,13 @@ } case 0x03: /* NEG Ed */ { - flags.type=t_NEGd; + lflags.type=t_NEGd; if (rm >= 0xc0 ) { - GetEArd;flags.var1.d=*eard;flags.result.d=0-flags.var1.d; - *eard=flags.result.d; + GetEArd;lf_var1d=*eard;lf_resd=0-lf_var1d; + *eard=lf_resd; } else { - GetEAa;flags.var1.d=LoadMd(eaa);flags.result.d=0-flags.var1.d; - SaveMd(eaa,flags.result.d); + GetEAa;lf_var1d=LoadMd(eaa);lf_resd=0-lf_var1d; + SaveMd(eaa,lf_resd); } break; } @@ -627,12 +639,9 @@ GetEAa; Bit32u newip=LoadMd(eaa); Bit16u newcs=LoadMw(eaa+4); - SAVEIP; - if (CPU_CALL(true,newcs,newip)) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } + LEAVECORE; + CPU_CALL(true,newcs,newip); + goto decode_start; } break; case 0x04: /* JMP NEAR Ed */ @@ -644,12 +653,9 @@ GetEAa; Bit32u newip=LoadMd(eaa); Bit16u newcs=LoadMw(eaa+4); - SAVEIP; - if (CPU_JMP(true,newcs,newip)) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } + LEAVECORE; + CPU_JMP(true,newcs,newip,core.ip_lookup-core.op_start); + goto decode_start; } break; case 0x06: /* Push Ed */ diff --git a/src/cpu/core_normal/prefix_66_0f.h b/src/cpu/core_normal/prefix_66_0f.h index 7496d84..39be74b 100644 --- a/src/cpu/core_normal/prefix_66_0f.h +++ b/src/cpu/core_normal/prefix_66_0f.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,7 +36,6 @@ Bitu loadval; if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} else {GetEAa;loadval=LoadMw(eaa);} - break; switch (which) { case 0x02:CPU_LLDT(loadval);break; case 0x03:CPU_LTR(loadval);break; @@ -44,6 +43,7 @@ case 0x05:CPU_VERW(loadval);break; } } + break; default: LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); } @@ -120,59 +120,58 @@ } else { GetEAa;CPU_LSL(LoadMw(eaa),limit); } - *rmrd=(Bit16u)limit; + *rmrd=(Bit32u)limit; } break; CASE_0F_D(0x80) /* JO */ - JumpSId(get_OF());break; + JumpCond32_d(TFLG_O);break; CASE_0F_D(0x81) /* JNO */ - JumpSId(!get_OF());break; + JumpCond32_d(TFLG_NO);break; CASE_0F_D(0x82) /* JB */ - JumpSId(get_CF());break; + JumpCond32_d(TFLG_B);break; CASE_0F_D(0x83) /* JNB */ - JumpSId(!get_CF());break; + JumpCond32_d(TFLG_NB);break; CASE_0F_D(0x84) /* JZ */ - JumpSId(get_ZF());break; + JumpCond32_d(TFLG_Z);break; CASE_0F_D(0x85) /* JNZ */ - JumpSId(!get_ZF());break; + JumpCond32_d(TFLG_NZ);break; CASE_0F_D(0x86) /* JBE */ - JumpSId(get_CF() || get_ZF());break; + JumpCond32_d(TFLG_BE);break; CASE_0F_D(0x87) /* JNBE */ - JumpSId(!get_CF() && !get_ZF());break; + JumpCond32_d(TFLG_NBE);break; CASE_0F_D(0x88) /* JS */ - JumpSId(get_SF());break; + JumpCond32_d(TFLG_S);break; CASE_0F_D(0x89) /* JNS */ - JumpSId(!get_SF());break; + JumpCond32_d(TFLG_NS);break; CASE_0F_D(0x8a) /* JP */ - JumpSId(get_PF());break; + JumpCond32_d(TFLG_P);break; CASE_0F_D(0x8b) /* JNP */ - JumpSId(!get_PF());break; + JumpCond32_d(TFLG_NP);break; CASE_0F_D(0x8c) /* JL */ - JumpSId(get_SF() != get_OF());break; + JumpCond32_d(TFLG_L);break; CASE_0F_D(0x8d) /* JNL */ - JumpSId(get_SF() == get_OF());break; + JumpCond32_d(TFLG_NL);break; CASE_0F_D(0x8e) /* JLE */ - JumpSId(get_ZF() || (get_SF() != get_OF()));break; + JumpCond32_d(TFLG_LE);break; CASE_0F_D(0x8f) /* JNLE */ - JumpSId((get_SF() == get_OF()) && !get_ZF());break; + JumpCond32_d(TFLG_NLE);break; CASE_0F_D(0xa0) /* PUSH FS */ Push_32(SegValue(fs));break; CASE_0F_D(0xa1) /* POP FS */ - CPU_SetSegGeneral(fs,(Bit16u)Pop_32());break; - + POPSEG(fs,Pop_32(),4);break; CASE_0F_D(0xa3) /* BT Ed,Gd */ { - GetRMrd; + FillFlags();GetRMrd; Bit32u mask=1 << (*rmrd & 31); if (rm >= 0xc0 ) { GetEArd; SETFLAGBIT(CF,(*eard & mask)); } else { - GetEAa;Bit32u old=LoadMd(eaa); + GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; + Bit32u old=LoadMd(eaa); SETFLAGBIT(CF,(old & mask)); } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } CASE_0F_D(0xa4) /* SHLD Ed,Gd,Ib */ @@ -184,21 +183,21 @@ CASE_0F_D(0xa8) /* PUSH GS */ Push_32(SegValue(gs));break; CASE_0F_D(0xa9) /* POP GS */ - CPU_SetSegGeneral(gs,(Bit16u)Pop_32());break; + POPSEG(gs,Pop_32(),4);break; CASE_0F_D(0xab) /* BTS Ed,Gd */ { - GetRMrd; + FillFlags();GetRMrd; Bit32u mask=1 << (*rmrd & 31); if (rm >= 0xc0 ) { GetEArd; SETFLAGBIT(CF,(*eard & mask)); *eard|=mask; } else { - GetEAa;Bit32u old=LoadMd(eaa); + GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; + Bit32u old=LoadMd(eaa); SETFLAGBIT(CF,(old & mask)); SaveMd(eaa,old | mask); } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } @@ -208,25 +207,6 @@ CASE_0F_D(0xad) /* SHRD Ed,Gd,CL */ RMEdGdOp3(DSHRD,reg_cl); break; - CASE_0F_D(0xb4) /* LFS Ed */ - { - GetRMrd;GetEAa; - *rmrd=LoadMd(eaa);CPU_SetSegGeneral(fs,LoadMw(eaa+4)); - break; - } - CASE_0F_D(0xb5) /* LGS Ed */ - { - GetRMrd;GetEAa; - *rmrd=LoadMd(eaa);CPU_SetSegGeneral(gs,LoadMw(eaa+4)); - break; - } - CASE_0F_D(0xb6) /* MOVZX Gd,Eb */ - { - GetRMrd; - if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;} - else {GetEAa;*rmrd=LoadMb(eaa);} - break; - } CASE_0F_D(0xaf) /* IMUL Gd,Ed */ { RMGdEdOp3(DIMULD,*rmrd); @@ -235,7 +215,45 @@ CASE_0F_D(0xb2) /* LSS Ed */ { GetRMrd;GetEAa; - *rmrd=LoadMd(eaa);CPU_SetSegGeneral(ss,LoadMw(eaa+4)); + LOADSEG(ss,LoadMw(eaa+4)); + *rmrd=LoadMd(eaa); + break; + } + CASE_0F_D(0xb3) /* BTR Ed,Gd */ + { + FillFlags();GetRMrd; + Bit32u mask=1 << (*rmrd & 31); + if (rm >= 0xc0 ) { + GetEArd; + SETFLAGBIT(CF,(*eard & mask)); + *eard&= ~mask; + } else { + GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; + Bit32u old=LoadMd(eaa); + SETFLAGBIT(CF,(old & mask)); + SaveMd(eaa,old & ~mask); + } + break; + } + CASE_0F_D(0xb4) /* LFS Ed */ + { + GetRMrd;GetEAa; + LOADSEG(fs,LoadMw(eaa+4)); + *rmrd=LoadMd(eaa); + break; + } + CASE_0F_D(0xb5) /* LGS Ed */ + { + GetRMrd;GetEAa; + LOADSEG(gs,LoadMw(eaa+4)); + *rmrd=LoadMd(eaa); + break; + } + CASE_0F_D(0xb6) /* MOVZX Gd,Eb */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;} + else {GetEAa;*rmrd=LoadMb(eaa);} break; } CASE_0F_D(0xb7) /* MOVXZ Gd,Ew */ @@ -247,7 +265,7 @@ } CASE_0F_D(0xba) /* GRP8 Ed,Ib */ { - GetRM; + FillFlags();GetRM; if (rm >= 0xc0 ) { GetEArd; Bit32u mask=1 << (Fetchb() & 31); @@ -290,24 +308,22 @@ E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38); } } - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; break; } CASE_0F_D(0xbb) /* BTC Ed,Gd */ { - GetRMrd; + FillFlags();GetRMrd; Bit32u mask=1 << (*rmrd & 31); if (rm >= 0xc0 ) { GetEArd; SETFLAGBIT(CF,(*eard & mask)); *eard^=mask; } else { - GetEAa;Bit32u old=LoadMd(eaa); + GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4; + Bit32u old=LoadMd(eaa); SETFLAGBIT(CF,(old & mask)); SaveMd(eaa,old ^ mask); } - if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } break; } CASE_0F_D(0xbc) /* BSF Gd,Ed */ @@ -324,7 +340,7 @@ SETFLAGBIT(ZF,false); *rmrd = result; } - flags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; break; } CASE_0F_D(0xbd) /* BSR Gd,Ed */ @@ -341,7 +357,7 @@ SETFLAGBIT(ZF,false); *rmrd = result; } - flags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; break; } CASE_0F_D(0xbe) /* MOVSX Gd,Eb */ diff --git a/src/cpu/core_normal/prefix_none.h b/src/cpu/core_normal/prefix_none.h index 040e178..6d79d97 100644 --- a/src/cpu/core_normal/prefix_none.h +++ b/src/cpu/core_normal/prefix_none.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,8 +30,8 @@ AXIw(ADDW);break; CASE_W(0x06) /* PUSH ES */ Push_16(SegValue(es));break; - CASE_W(0x07) /* POP ES */ - CPU_SetSegGeneral(es,Pop_16());break; + CASE_W(0x07) /* POP ES */ + POPSEG(es,Pop_16(),2);break; CASE_B(0x08) /* OR Eb,Gb */ RMEbGb(ORB);break; CASE_W(0x09) /* OR Ew,Gw */ @@ -65,7 +65,9 @@ CASE_W(0x16) /* PUSH SS */ Push_16(SegValue(ss));break; CASE_W(0x17) /* POP SS */ - CPU_SetSegGeneral(ss,Pop_16());break; + POPSEG(ss,Pop_16(),2); + CPU_Cycles++; //Always do another instruction + break; CASE_B(0x18) /* SBB Eb,Gb */ RMEbGb(SBBB);break; CASE_W(0x19) /* SBB Ew,Gw */ @@ -81,7 +83,8 @@ CASE_W(0x1e) /* PUSH DS */ Push_16(SegValue(ds));break; CASE_W(0x1f) /* POP DS */ - CPU_SetSegGeneral(ds,Pop_16());break; + POPSEG(ds,Pop_16(),2); + break; CASE_B(0x20) /* AND Eb,Gb */ RMEbGb(ANDB);break; CASE_W(0x21) /* AND Ew,Gw */ @@ -187,7 +190,6 @@ CASE_W(0x53) /* PUSH BX */ Push_16(reg_bx);break; CASE_W(0x54) /* PUSH SP */ -//TODO Check if this is correct i think it's SP+2 or something Push_16(reg_sp);break; CASE_W(0x55) /* PUSH BP */ Push_16(reg_bp);break; @@ -253,7 +255,7 @@ CASE_B(0x65) /* SEG GS: */ DO_PREFIX_SEG(gs);break; CASE_B(0x66) /* Operand Size Prefix */ - core.opcode_index^=OPCODE_SIZE; + core.opcode_index=core.index_default^OPCODE_SIZE; goto restart_opcode; CASE_B(0x67) /* Address Size Prefix */ DO_PREFIX_ADDR(); @@ -276,38 +278,38 @@ DoString(R_OUTSB);break; CASE_W(0x6f) /* OUTSW */ DoString(R_OUTSW);break; - CASE_B(0x70) /* JO */ - JumpSIb(get_OF());break; - CASE_B(0x71) /* JNO */ - JumpSIb(!get_OF());break; - CASE_B(0x72) /* JB */ - JumpSIb(get_CF());break; - CASE_B(0x73) /* JNB */ - JumpSIb(!get_CF());break; - CASE_B(0x74) /* JZ */ - JumpSIb(get_ZF());break; - CASE_B(0x75) /* JNZ */ - JumpSIb(!get_ZF());break; - CASE_B(0x76) /* JBE */ - JumpSIb(get_CF() || get_ZF());break; - CASE_B(0x77) /* JNBE */ - JumpSIb(!get_CF() && !get_ZF());break; - CASE_B(0x78) /* JS */ - JumpSIb(get_SF());break; - CASE_B(0x79) /* JNS */ - JumpSIb(!get_SF());break; - CASE_B(0x7a) /* JP */ - JumpSIb(get_PF());break; - CASE_B(0x7b) /* JNP */ - JumpSIb(!get_PF());break; - CASE_B(0x7c) /* JL */ - JumpSIb(get_SF() != get_OF());break; - CASE_B(0x7d) /* JNL */ - JumpSIb(get_SF() == get_OF());break; - CASE_B(0x7e) /* JLE */ - JumpSIb(get_ZF() || (get_SF() != get_OF()));break; - CASE_B(0x7f) /* JNLE */ - JumpSIb((get_SF() == get_OF()) && !get_ZF());break; + CASE_W(0x70) /* JO */ + JumpCond16_b(TFLG_O);break; + CASE_W(0x71) /* JNO */ + JumpCond16_b(TFLG_NO);break; + CASE_W(0x72) /* JB */ + JumpCond16_b(TFLG_B);break; + CASE_W(0x73) /* JNB */ + JumpCond16_b(TFLG_NB);break; + CASE_W(0x74) /* JZ */ + JumpCond16_b(TFLG_Z);break; + CASE_W(0x75) /* JNZ */ + JumpCond16_b(TFLG_NZ);break; + CASE_W(0x76) /* JBE */ + JumpCond16_b(TFLG_BE);break; + CASE_W(0x77) /* JNBE */ + JumpCond16_b(TFLG_NBE);break; + CASE_W(0x78) /* JS */ + JumpCond16_b(TFLG_S);break; + CASE_W(0x79) /* JNS */ + JumpCond16_b(TFLG_NS);break; + CASE_W(0x7a) /* JP */ + JumpCond16_b(TFLG_P);break; + CASE_W(0x7b) /* JNP */ + JumpCond16_b(TFLG_NP);break; + CASE_W(0x7c) /* JL */ + JumpCond16_b(TFLG_L);break; + CASE_W(0x7d) /* JNL */ + JumpCond16_b(TFLG_NL);break; + CASE_W(0x7e) /* JLE */ + JumpCond16_b(TFLG_LE);break; + CASE_W(0x7f) /* JNLE */ + JumpCond16_b(TFLG_NLE);break; CASE_B(0x80) /* Grpl Eb,Ib */ CASE_B(0x82) /* Grpl Eb,Ib Mirror instruction*/ { @@ -489,20 +491,17 @@ if (rm >= 0xc0 ) {GetEArw;val=*earw;} else {GetEAa;val=LoadMw(eaa);} switch (which) { + case 0x02: /* MOV SS,Ew */ + CPU_Cycles++; //Always do another instruction case 0x00: /* MOV ES,Ew */ - CPU_SetSegGeneral(es,val);break; + case 0x03: /* MOV DS,Ew */ + case 0x05: /* MOV GS,Ew */ + case 0x04: /* MOV FS,Ew */ + LOADSEG((SegNames)which,val); + break; case 0x01: /* MOV CS,Ew Illegal*/ E_Exit("CPU:Illegal MOV CS Call"); break; - case 0x02: /* MOV SS,Ew */ - CPU_SetSegGeneral(ss,val); - break; - case 0x03: /* MOV DS,Ew */ - CPU_SetSegGeneral(ds,val);break; - case 0x04: /* MOV FS,Ew */ - CPU_SetSegGeneral(fs,val);break; - case 0x05: /* MOV GS,Ew */ - CPU_SetSegGeneral(gs,val);break; default: E_Exit("CPU:8E:Illegal RM Byte"); } @@ -510,9 +509,10 @@ } CASE_W(0x8f) /* POP Ew */ { + Bit16u val=Pop_16(); GetRM; - if (rm >= 0xc0 ) {GetEArw;*earw=Pop_16();} - else {GetEAa;SaveMw(eaa,Pop_16());} + if (rm >= 0xc0 ) {GetEArw;*earw=val;} + else {GetEAa;SaveMw(eaa,val);} break; } CASE_B(0x90) /* NOP */ @@ -546,29 +546,30 @@ CASE_W(0x9a) /* CALL Ap */ { Bit16u newip=Fetchw();Bit16u newcs=Fetchw(); - SAVEIP; - if (CPU_CALL(false,newcs,newip)) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } - break; + LEAVECORE; + CPU_CALL(false,newcs,newip,core.ip_lookup-core.op_start); + goto decode_start; } CASE_B(0x9b) /* WAIT */ break; /* No waiting here */ CASE_W(0x9c) /* PUSHF */ FillFlags(); - Push_16(flags.word); + Push_16(reg_flags); break; CASE_W(0x9d) /* POPF */ + if ((reg_flags & FLAG_VM) && ((reg_flags & FLAG_IOPL)!=FLAG_IOPL)) { + LEAVECORE;reg_eip-=core.ip_lookup-core.op_start; + CPU_Exception(13,0); + goto decode_start; + } SETFLAGSw(Pop_16()); #if CPU_TRAP_CHECK if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Decode_Trap; + cpudecoder=CPU_Core_Normal_Trap_Run; goto decode_end; } #endif -#ifdef CPU_PIC_CHECK +#if CPU_PIC_CHECK if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; #endif break; @@ -577,7 +578,7 @@ break; CASE_B(0x9f) /* LAHF */ FillFlags(); - reg_ah=flags.word&0xff; + reg_ah=reg_flags&0xff; break; CASE_B(0xa0) /* MOV AL,Ob */ { @@ -675,13 +676,15 @@ CASE_W(0xc4) /* LES */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);CPU_SetSegGeneral(es,LoadMw(eaa+2)); + LOADSEG(es,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa); break; } CASE_W(0xc5) /* LDS */ { GetRMrw;GetEAa; - *rmrw=LoadMw(eaa);CPU_SetSegGeneral(ds,LoadMw(eaa+2)); + LOADSEG(ds,LoadMw(eaa+2)); + *rmrw=LoadMw(eaa); break; } CASE_B(0xc6) /* MOV Eb,Ib */ @@ -736,23 +739,16 @@ reg_bp=Pop_16(); break; CASE_W(0xca) /* RETF Iw */ - { - if (CPU_RET(false,Fetchw())) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } - break; + { + Bitu words=Fetchw(); + LEAVECORE; + CPU_RET(false,words,core.ip_lookup-core.op_start); + goto decode_start; } CASE_W(0xcb) /* RETF */ - { - if (CPU_RET(false,0)) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } - break; - } + LEAVECORE; + CPU_RET(false,0,core.ip_lookup-core.op_start); + goto decode_start; CASE_B(0xcc) /* INT3 */ LEAVECORE; #if C_DEBUG @@ -760,7 +756,10 @@ return debugCallback; } #endif - if (!Interrupt(3)) return CBRET_NONE; + CPU_SW_Interrupt(3,(core.ip_lookup-core.op_start)); +#if CPU_TRAP_CHECK + core.trap.skip=true; +#endif goto decode_start; CASE_B(0xcd) /* INT Ib */ { @@ -771,35 +770,39 @@ return debugCallback; } #endif - if (!Interrupt(num)) return CBRET_NONE; - goto decode_start; //Restore IP with a LOADIP + CPU_SW_Interrupt(num,core.ip_lookup-core.op_start); +#if CPU_TRAP_CHECK + core.trap.skip=true; +#endif + goto decode_start; } break; CASE_B(0xce) /* INTO */ if (get_OF()) { LEAVECORE; - if (!Interrupt(4)) return CBRET_NONE; - goto decode_start; //Restore IP with a LOADIP + CPU_SW_Interrupt(4,core.ip_lookup-core.op_start); +#if CPU_TRAP_CHECK + core.trap.skip=true; +#endif + goto decode_start; + } break; CASE_W(0xcf) /* IRET */ { - if (CPU_IRET(false)) { -#ifdef CPU_PIC_CHECK - if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; + LEAVECORE; + CPU_IRET(false); +#if CPU_PIC_CHECK + if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; #endif #if CPU_TRAP_CHECK - if (GETFLAG(TF)) { - cpudecoder=CPU_Core_Normal_Decode_Trap; - return CBRET_NONE; - } + if (GETFLAG(TF)) { + cpudecoder=CPU_Core_Normal_Trap_Run; + return CBRET_NONE; + } #endif goto decode_start; - } else { - return CBRET_NONE; } - break; - } CASE_B(0xd0) /* GRP2 Eb,1 */ GRP2B(1);break; CASE_W(0xd1) /* GRP2 Ew,1 */ @@ -901,31 +904,17 @@ break; } CASE_B(0xe4) /* IN AL,Ib */ - { - Bit16u port=Fetchb(); - reg_al=IO_Read(port); - break; - } + reg_al=IO_ReadB(Fetchb()); + break; CASE_W(0xe5) /* IN AX,Ib */ - { - Bit16u port=Fetchb(); - reg_al=IO_Read(port); - reg_ah=IO_Read(port+1); - break; - } + reg_ax=IO_ReadW(Fetchb()); + break; CASE_B(0xe6) /* OUT Ib,AL */ - { - Bit16u port=Fetchb(); - IO_Write(port,reg_al); - break; - } + IO_WriteB(Fetchb(),reg_al); + break; CASE_W(0xe7) /* OUT Ib,AX */ - { - Bit16u port=Fetchb(); - IO_Write(port,reg_al); - IO_Write(port+1,reg_ah); - break; - } + IO_WriteW(Fetchb(),reg_ax); + break; CASE_W(0xe8) /* CALL Jw */ { Bit16s newip=Fetchws(); @@ -940,13 +929,9 @@ { Bit16u newip=Fetchw(); Bit16u newcs=Fetchw(); - SAVEIP; - if (CPU_JMP(false,newcs,newip)) { - LOADIP; - } else { - FillFlags();return CBRET_NONE; - } - break; + LEAVECORE; + CPU_JMP(false,newcs,newip,core.ip_lookup-core.op_start); + goto decode_start; } CASE_B(0xeb) /* JMP Jb */ ADDIPFAST(Fetchbs());break; @@ -956,9 +941,9 @@ reg_al=IO_Read(reg_dx);reg_ah=IO_Read(reg_dx+1); break; CASE_B(0xee) /* OUT DX,AL */ - IO_Write(reg_dx,reg_al);break; + IO_WriteB(reg_dx,reg_al);break; CASE_W(0xef) /* OUT DX,AX */ - IO_Write(reg_dx,reg_al);IO_Write(reg_dx+1,reg_ah);break; + IO_WriteW(reg_dx,reg_ax);break; CASE_B(0xf0) /* LOCK */ LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK"); break; @@ -970,12 +955,11 @@ break; CASE_B(0xf4) /* HLT */ LEAVECORE; - CPU_HLT(); - return CBRET_NONE; + CPU_HLT(core.ip_lookup-core.op_start); + return CBRET_NONE; //Needs to return for hlt cpu core CASE_B(0xf5) /* CMC */ - SETFLAGBIT(CF,!get_CF()); - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; + FillFlags(); + SETFLAGBIT(CF,!(reg_flags & FLAG_CF)); break; CASE_B(0xf6) /* GRP3 Eb(,Ib) */ { @@ -996,13 +980,13 @@ } case 0x03: /* NEG Eb */ { - flags.type=t_NEGb; + lflags.type=t_NEGb; if (rm >= 0xc0 ) { - GetEArb;flags.var1.b=*earb;flags.result.b=0-flags.var1.b; - *earb=flags.result.b; + GetEArb;lf_var1b=*earb;lf_resb=0-lf_var1b; + *earb=lf_resb; } else { - GetEAa;flags.var1.b=LoadMb(eaa);flags.result.b=0-flags.var1.b; - SaveMb(eaa,flags.result.b); + GetEAa;lf_var1b=LoadMb(eaa);lf_resb=0-lf_var1b; + SaveMb(eaa,lf_resb); } break; } @@ -1040,13 +1024,13 @@ } case 0x03: /* NEG Ew */ { - flags.type=t_NEGw; + lflags.type=t_NEGw; if (rm >= 0xc0 ) { - GetEArw;flags.var1.w=*earw;flags.result.w=0-flags.var1.w; - *earw=flags.result.w; + GetEArw;lf_var1w=*earw;lf_resw=0-lf_var1w; + *earw=lf_resw; } else { - GetEAa;flags.var1.w=LoadMw(eaa);flags.result.w=0-flags.var1.w; - SaveMw(eaa,flags.result.w); + GetEAa;lf_var1w=LoadMw(eaa);lf_resw=0-lf_var1w; + SaveMw(eaa,lf_resw); } break; } @@ -1066,29 +1050,39 @@ break; } CASE_B(0xf8) /* CLC */ + FillFlags(); SETFLAGBIT(CF,false); - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; break; CASE_B(0xf9) /* STC */ + FillFlags(); SETFLAGBIT(CF,true); - if (flags.type!=t_CF) flags.prev_type=flags.type; - flags.type=t_CF; break; CASE_B(0xfa) /* CLI */ + if (cpu.pmode && (GETFLAG_IOPL= 0xc0 ) {GetEArw;Push_16(*earw);} diff --git a/src/cpu/core_normal/string.h b/src/cpu/core_normal/string.h index 4fce863..c2f3013 100644 --- a/src/cpu/core_normal/string.h +++ b/src/cpu/core_normal/string.h @@ -46,43 +46,38 @@ static void DoString(STRING_OP type) { count_left=0; } } - add_index=GETFLAG(DF) ? -1 : 1; + add_index=cpu.direction; if (count) switch (type) { case R_OUTSB: for (;count>0;count--) { - IO_Write(reg_dx,LoadMb(si_base+si_index)); + IO_WriteB(reg_dx,LoadMb(si_base+si_index)); si_index=(si_index+add_index) & add_mask; } break; case R_OUTSW: add_index<<=1; for (;count>0;count--) { - IO_Write(reg_dx,LoadMb(si_base+si_index)); - IO_Write(reg_dx+1,LoadMb(si_base+si_index+1)); + IO_WriteW(reg_dx,LoadMw(si_base+si_index)); si_index=(si_index+add_index) & add_mask; } break; case R_OUTSD: add_index<<=2; for (;count>0;count--) { - IO_Write(reg_dx,LoadMb(si_base+si_index)); - IO_Write(reg_dx+1,LoadMb(si_base+si_index+1)); - IO_Write(reg_dx+2,LoadMb(si_base+si_index+2)); - IO_Write(reg_dx+3,LoadMb(si_base+si_index+3)); + IO_WriteD(reg_dx,LoadMd(si_base+si_index)); si_index=(si_index+add_index) & add_mask; } break; case R_INSB: for (;count>0;count--) { - SaveMb(di_base+di_index,IO_Read(reg_dx)); + SaveMb(di_base+di_index,IO_ReadB(reg_dx)); di_index=(di_index+add_index) & add_mask; } break; case R_INSW: add_index<<=1; for (;count>0;count--) { - SaveMb(di_base+di_index,IO_Read(reg_dx)); - SaveMb(di_base+di_index+1,IO_Read(reg_dx+1)); + SaveMw(di_base+di_index,IO_ReadW(reg_dx)); di_index=(di_index+add_index) & add_mask; } break; diff --git a/src/cpu/core_normal/support.h b/src/cpu/core_normal/support.h index d0e4d2a..e9ce3c8 100644 --- a/src/cpu/core_normal/support.h +++ b/src/cpu/core_normal/support.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,9 +37,11 @@ static INLINE void ADDIPd(Bits add) { LOADIP; } - static INLINE void ADDIPFAST(Bits blah) { - core.ip_lookup+=blah; +// core.ip_lookup+=blah; + SAVEIP; + reg_eip=(reg_eip+blah); + LOADIP; } #define EXCEPTION(blah) \ @@ -47,9 +49,8 @@ static INLINE void ADDIPFAST(Bits blah) { Bit8u new_num=blah; \ core.ip_lookup=core.op_start; \ LEAVECORE; \ - if (Interrupt(new_num)) { \ - goto decode_start; \ - } else return CBRET_NONE; \ + CPU_Exception(new_num); \ + goto decode_start; \ } static INLINE Bit8u Fetchb() { @@ -80,6 +81,8 @@ static INLINE Bit32s Fetchds() { return Fetchd(); } +#if 0 + static INLINE void Push_16(Bit16u blah) { reg_esp-=2; SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); @@ -102,14 +105,31 @@ static INLINE Bit32u Pop_32() { return temp; }; -#define JumpSIb(blah) \ +#else + +#define Push_16 CPU_Push16 +#define Push_32 CPU_Push32 +#define Pop_16 CPU_Pop16 +#define Pop_32 CPU_Pop32 + +#endif + +//TODO Could probably make all byte operands fast? +#define JumpCond16_b(blah) \ if (blah) { \ - ADDIPFAST(Fetchbs()); \ + ADDIPw(Fetchbs()); \ } else { \ ADDIPFAST(1); \ } -#define JumpSIw(blah) \ +#define JumpCond32_b(blah) \ + if (blah) { \ + ADDIPd(Fetchbs()); \ + } else { \ + ADDIPFAST(1); \ + } + +#define JumpCond16_w(blah) \ if (blah) { \ ADDIPw(Fetchws()); \ } else { \ @@ -117,7 +137,7 @@ static INLINE Bit32u Pop_32() { } -#define JumpSId(blah) \ +#define JumpCond32_d(blah) \ if (blah) { \ ADDIPd(Fetchds()); \ } else { \ diff --git a/src/cpu/core_normal/table_ea.h b/src/cpu/core_normal/table_ea.h index a93182e..c6e95fc 100644 --- a/src/cpu/core_normal/table_ea.h +++ b/src/cpu/core_normal/table_ea.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 31ced96..cf8995c 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cpu.cpp,v 1.35 2003/10/14 23:31:51 harekiet Exp $ */ +/* $Id: cpu.cpp,v 1.53 2004/01/14 17:09:41 harekiet Exp $ */ #include #include "dosbox.h" @@ -26,58 +26,53 @@ #include "keyboard.h" #include "setup.h" #include "paging.h" +#include "support.h" + +Bitu DEBUG_EnableDebugger(void); #if 1 #undef LOG #define LOG(X,Y) #endif -Flag_Info flags; CPU_Regs cpu_regs; CPUBlock cpu; Segments Segs; -Bits CPU_Cycles=0; -Bits CPU_CycleLeft=0; -Bits CPU_CycleMax=1500; - +Bits CPU_Cycles = 0; +Bits CPU_CycleLeft = 0; +Bits CPU_CycleMax = 2500; +Bits CPU_CycleUp = 0; +Bits CPU_CycleDown = 0; CPU_Decoder * cpudecoder; -void CPU_Real_16_Slow_Start(bool big); -void CPU_Core_Full_Start(bool big); -void CPU_Core_Normal_Start(bool big); +static struct { + Bitu which,errorcode; +} exception; -#if 1 - -#define realcore_start CPU_Core_Normal_Start -#define pmodecore_start CPU_Core_Normal_Start - -#else - -#define realcore_start CPU_Core_Full_Start -#define pmodecore_start CPU_Core_Full_Start - -#endif +void CPU_Core_Full_Init(void); +void CPU_Core_Normal_Init(void); +void CPU_Core_Dyn_X86_Init(void); void CPU_Push16(Bitu value) { - reg_esp-=2; + reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp-2)&cpu.stack.mask); mem_writew(SegPhys(ss) + (reg_esp & cpu.stack.mask) ,value); } void CPU_Push32(Bitu value) { - reg_esp-=4; + reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp-4)&cpu.stack.mask); mem_writed(SegPhys(ss) + (reg_esp & cpu.stack.mask) ,value); } Bitu CPU_Pop16(void) { Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp+=2; + reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+2)&cpu.stack.mask); return val; } Bitu CPU_Pop32(void) { Bitu val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); - reg_esp+=4; + reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+4)&cpu.stack.mask); return val; } @@ -91,30 +86,205 @@ PhysPt SelBase(Bitu sel) { } } -void CPU_SetFlags(Bitu word) { - flags.word=(word|2)&~0x28; +void CPU_SetFlags(Bitu word,Bitu mask) { + reg_flags=(reg_flags & ~mask)|(word & mask)|2|FLAG_ID; + cpu.direction=1-((reg_flags & FLAG_DF) >> 9); } -bool CPU_CheckCodeType(CODE_TYPE type) { - if (cpu.code.type==type) return true; - cpu.code.type=type; - switch (cpu.code.type) { - case CODE_REAL: - realcore_start(false); - cpu.code.big = false; - break; - case CODE_PMODE16: - pmodecore_start(false); - break; - case CODE_PMODE32: - pmodecore_start(true); - break; +class TaskStateSegment { +public: + TaskStateSegment() { + valid=false; } - return false; + bool IsValid(void) { + return valid; + } + Bitu Get_back(void) { + return mem_readw(base); + } + void SaveSelector(void) { + cpu.gdt.SetDescriptor(selector,desc); + } + void Get_SSx_ESPx(Bitu level,Bitu & _ss,Bitu & _esp) { + if (is386) { + PhysPt where=base+offsetof(TSS_32,esp0)+level*8; + _esp=mem_readd(where); + _ss=mem_readw(where+4); + } else { + PhysPt where=base+offsetof(TSS_16,sp0)+level*4; + _esp=mem_readw(where); + _ss=mem_readw(where+2); + } + } + bool SetSelector(Bitu new_sel) { + valid=false; + selector=new_sel; + if (!cpu.gdt.GetDescriptor(selector,desc)) return false; + switch (desc.Type()) { + case DESC_286_TSS_A: case DESC_286_TSS_B: + case DESC_386_TSS_A: case DESC_386_TSS_B: + break; + default: + valid=false; + return false; + } + valid=true; + base=desc.GetBase(); + limit=desc.GetLimit(); + is386=desc.Is386(); + return true; + } + TSS_Descriptor desc; + Bitu selector; + PhysPt base; + Bitu limit; + Bitu is386; + bool valid; +}; + +TaskStateSegment cpu_tss; + +enum TSwitchType { + TSwitch_JMP,TSwitch_CALL_INT,TSwitch_IRET +}; + +bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype) { + TaskStateSegment new_tss; + if (!new_tss.SetSelector(new_tss_selector)) + E_Exit("Illegal TSS for switch"); + /* Save current context in current TSS */ + /* Check if we need to clear busy bit of old TASK */ + if (tstype==TSwitch_JMP || tstype==TSwitch_IRET) { + cpu_tss.desc.SetBusy(false); + cpu_tss.SaveSelector(); + } + Bitu new_cr3=0; + Bitu new_es,new_cs,new_ss,new_ds,new_fs,new_gs; + Bitu new_ldt; + if (cpu_tss.is386) { + mem_writed(cpu_tss.base+offsetof(TSS_32,eflags),reg_flags); + mem_writed(cpu_tss.base+offsetof(TSS_32,eip),reg_eip); + + mem_writed(cpu_tss.base+offsetof(TSS_32,eax),reg_eax); + mem_writed(cpu_tss.base+offsetof(TSS_32,ecx),reg_ecx); + mem_writed(cpu_tss.base+offsetof(TSS_32,edx),reg_edx); + mem_writed(cpu_tss.base+offsetof(TSS_32,ebx),reg_ebx); + mem_writed(cpu_tss.base+offsetof(TSS_32,esp),reg_esp); + mem_writed(cpu_tss.base+offsetof(TSS_32,ebp),reg_ebp); + mem_writed(cpu_tss.base+offsetof(TSS_32,esi),reg_esi); + mem_writed(cpu_tss.base+offsetof(TSS_32,edi),reg_edi); + + mem_writed(cpu_tss.base+offsetof(TSS_32,es),SegValue(es)); + mem_writed(cpu_tss.base+offsetof(TSS_32,cs),SegValue(cs)); + mem_writed(cpu_tss.base+offsetof(TSS_32,ss),SegValue(ss)); + mem_writed(cpu_tss.base+offsetof(TSS_32,ds),SegValue(ds)); + mem_writed(cpu_tss.base+offsetof(TSS_32,fs),SegValue(fs)); + mem_writed(cpu_tss.base+offsetof(TSS_32,gs),SegValue(gs)); + } else { + E_Exit("286 task switch"); + } + /* Load new context from new TSS */ + if (new_tss.is386) { + new_cr3=mem_readd(new_tss.base+offsetof(TSS_32,cr3)); + reg_eip=mem_readd(new_tss.base+offsetof(TSS_32,eip)); + CPU_SetFlags(mem_readd(new_tss.base+offsetof(TSS_32,eflags)),FMASK_ALL | FLAG_VM); + reg_eax=mem_readd(new_tss.base+offsetof(TSS_32,eax)); + reg_ecx=mem_readd(new_tss.base+offsetof(TSS_32,ecx)); + reg_edx=mem_readd(new_tss.base+offsetof(TSS_32,edx)); + reg_ebx=mem_readd(new_tss.base+offsetof(TSS_32,ebx)); + reg_esp=mem_readd(new_tss.base+offsetof(TSS_32,esp)); + reg_ebp=mem_readd(new_tss.base+offsetof(TSS_32,ebp)); + reg_edi=mem_readd(new_tss.base+offsetof(TSS_32,edi)); + reg_esi=mem_readd(new_tss.base+offsetof(TSS_32,esi)); + + new_es=mem_readw(new_tss.base+offsetof(TSS_32,es)); + new_cs=mem_readw(new_tss.base+offsetof(TSS_32,cs)); + new_ss=mem_readw(new_tss.base+offsetof(TSS_32,ss)); + new_ds=mem_readw(new_tss.base+offsetof(TSS_32,ds)); + new_fs=mem_readw(new_tss.base+offsetof(TSS_32,fs)); + new_gs=mem_readw(new_tss.base+offsetof(TSS_32,gs)); + new_ldt=mem_readw(new_tss.base+offsetof(TSS_32,ldt)); + } else { + E_Exit("286 task switch"); + } + /* Setup a back link to the old TSS in new TSS */ + if (tstype==TSwitch_CALL_INT) { + if (new_tss.is386) { + mem_writed(new_tss.base+offsetof(TSS_32,back),cpu_tss.selector); + } else { + mem_writew(new_tss.base+offsetof(TSS_16,back),cpu_tss.selector); + } + /* And make the new task's eflag have the nested task bit */ + reg_flags|=FLAG_NT; + } + /* Set the busy bit in the new task */ + if (tstype==TSwitch_JMP || tstype==TSwitch_IRET) { + new_tss.desc.SetBusy(true); + new_tss.SaveSelector(); + } + /* Setup the new cr3 */ + PAGING_SetDirBase(new_cr3); + /* Load the new selectors */ + if (reg_flags & FLAG_VM) { +// LOG_MSG("Entering v86 task"); + SegSet16(cs,new_cs); + cpu.code.big=false; + cpu.cpl=3; //We don't have segment caches so this will do + } else { + //DEBUG_EnableDebugger(); + /* Protected mode task */ + CPU_LLDT(new_ldt); + /* Load the new CS*/ + Descriptor cs_desc; + cpu.cpl=new_cs & 3; + cpu.gdt.GetDescriptor(new_cs,cs_desc); + if (!cs_desc.saved.seg.p) { + E_Exit("Task switch with non present code-segment"); + return false; + } + switch (cs_desc.Type()) { + case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: + case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: + if (cpu.cpl != cs_desc.DPL()) E_Exit("Task CS RPL != DPL"); + goto doconforming; + case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: + case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: +doconforming: + Segs.phys[cs]=cs_desc.GetBase(); + cpu.code.big=cs_desc.Big()>0; + Segs.val[cs]=new_cs; + break; + default: + E_Exit("Task switch CS Type %d",cs_desc.Type()); + } + } + CPU_SetSegGeneral(es,new_es); + CPU_SetSegGeneral(ss,new_ss); + CPU_SetSegGeneral(ds,new_ds); + CPU_SetSegGeneral(fs,new_fs); + CPU_SetSegGeneral(gs,new_gs); + CPU_LTR(new_tss_selector); +// LOG_MSG("Task CPL %X CS:%X IP:%X SS:%X SP:%X eflags %x",cpu.cpl,SegValue(cs),reg_eip,SegValue(ss),reg_esp,reg_flags); + return true; +} + +void CPU_StartException(void) { + CPU_Interrupt(cpu.exception.which,CPU_INT_EXCEPTION | ((cpu.exception.which>=8) ? CPU_INT_HAS_ERROR : 0)); +} + +void CPU_SetupException(Bitu which,Bitu error) { + cpu.exception.which=which; + cpu.exception.error=error; +} + +void CPU_Exception(Bitu which,Bitu error ) { +// LOG_MSG("Exception %d CS:%X IP:%X FLAGS:%X",num,SegValue(cs),reg_eip,reg_flags); + CPU_SetupException(which,error); + CPU_StartException(); } Bit8u lastint; -bool Interrupt(Bitu num) { +void CPU_Interrupt(Bitu num,Bitu type,Bitu opLen) { lastint=num; #if C_DEBUG switch (num) { @@ -125,203 +295,282 @@ bool Interrupt(Bitu num) { #endif E_Exit("Call to interrupt 0xCD this is BAD"); case 0x03: - if (DEBUG_Breakpoint()) return true; + if (DEBUG_Breakpoint()) { + CPU_Cycles=0; + return; + } }; #endif - if (!cpu.pmode) { /* Save everything on a 16-bit stack */ - CPU_Push16(flags.word & 0xffff); + CPU_Push16(reg_flags & 0xffff); CPU_Push16(SegValue(cs)); CPU_Push16(reg_ip); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); /* Get the new CS:IP from vector table */ - reg_eip=mem_readw(num << 2); - Segs.val[cs]=mem_readw((num << 2)+2); + PhysPt base=cpu.idt.GetBase(); + reg_eip=mem_readw(base+(num << 2)); + Segs.val[cs]=mem_readw(base+(num << 2)+2); Segs.phys[cs]=Segs.val[cs]<<4; cpu.code.big=false; - return CPU_CheckCodeType(CODE_REAL); + return; } else { /* Protected Mode Interrupt */ +// if (type&CPU_INT_SOFTWARE && cpu.v86) goto realmode_interrupt; +// DEBUG_EnableDebugger(); +// LOG_MSG("interrupt start CPL %d v86 %d",cpu.cpl,cpu.v86); + if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE)) { +// LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12); + if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { + reg_eip-=opLen; + CPU_Exception(13,0); + return; + } + } Descriptor gate; //TODO Check for software interrupt and check gate's dplcpu.cpl) E_Exit("Interrupt to higher privilege"); - switch (desc.Type()) { + Descriptor cs_desc; + Bitu gate_sel=gate.GetSelector(); + Bitu gate_off=gate.GetOffset(); + cpu.gdt.GetDescriptor(gate_sel,cs_desc); + Bitu cs_dpl=cs_desc.DPL(); + if (cs_dpl>cpu.cpl) E_Exit("Interrupt to higher privilege"); + switch (cs_desc.Type()) { case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (dpl0; - LOG(LOG_CPU,LOG_NORMAL)("INT:Gate to %X:%X big %d %s",selector,reg_eip,desc.Big(),gate.Type() & 0x8 ? "386" : "286"); - reg_eip=offset; - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + SETFLAGBIT(VM,false); + Segs.val[cs]=(gate_sel&0xfffc) | cpu.cpl; + Segs.phys[cs]=cs_desc.GetBase(); + cpu.code.big=cs_desc.Big()>0; + LOG(LOG_CPU,LOG_NORMAL)("INT:Gate to %X:%X big %d %s",gate_sel,gate_off,cs_desc.Big(),gate.Type() & 0x8 ? "386" : "286"); + reg_eip=gate_off; + return; } + case DESC_TASK_GATE: + CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT); + if (type & CPU_INT_HAS_ERROR) { + //TODO Be sure about this, seems somewhat unclear + if (cpu_tss.is386) CPU_Push32(cpu.exception.error); + else CPU_Push16(cpu.exception.error); + } + return; default: E_Exit("Illegal descriptor type %X for int %X",gate.Type(),num); } } assert(1); - return false; + return ; // make compiler happy } - -bool CPU_Exception(Bitu exception,Bit32u error_code) { - if (!cpu.pmode) { /* RealMode Interrupt */ - /* Save everything on a 16-bit stack */ - CPU_Push16(flags.word & 0xffff); - CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip); - SETFLAGBIT(IF,false); - SETFLAGBIT(TF,false); - /* Get the new CS:IP from vector table */ - reg_eip=mem_readw(exception << 2); - Segs.val[cs]=mem_readw((exception << 2)+2); - Segs.phys[cs]=Segs.val[cs]<<4; - cpu.code.big=false; - return CPU_CheckCodeType(CODE_REAL); - } else { /* Protected Mode Exception */ - - - - } - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); -} - -bool CPU_IRET(bool use32) { - if (!cpu.pmode || cpu.v86) { /* RealMode IRET */ +void CPU_IRET(bool use32) { + if (!cpu.pmode) { /* RealMode IRET */ +realmode_iret: if (use32) { reg_eip=CPU_Pop32(); SegSet16(cs,CPU_Pop32()); - CPU_SetFlags(CPU_Pop32()); + CPU_SetFlagsd(CPU_Pop32()); } else { reg_eip=CPU_Pop16(); SegSet16(cs,CPU_Pop16()); CPU_SetFlagsw(CPU_Pop16()); } cpu.code.big=false; - return CPU_CheckCodeType(CODE_REAL); + return; } else { /* Protected mode IRET */ - /* Check if this is task IRET */ + if (reg_flags & FLAG_VM) { + if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { + reg_eip--; + CPU_Exception(13,0); + return; + } else goto realmode_iret; + } +// DEBUG_EnableDebugger(); +// LOG_MSG("IRET start CPL %d v86 %d",cpu.cpl,cpu.v86); + /* Check if this is task IRET */ if (GETFLAG(NT)) { - if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set"); - E_Exit("Task IRET"); - - + if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set"); + if (!cpu_tss.IsValid()) E_Exit("TASK Iret without valid TSS"); + Bitu back_link=cpu_tss.Get_back(); + CPU_SwitchTask(back_link,TSwitch_IRET); + return; } - Bitu selector,offset,old_flags; + Bitu n_cs_sel,n_eip,n_flags; if (use32) { - offset=CPU_Pop32(); - selector=CPU_Pop32() & 0xffff; - old_flags=CPU_Pop32(); - if (old_flags & FLAG_VM) E_Exit("No vm86 support"); + n_eip=CPU_Pop32(); + n_cs_sel=CPU_Pop32() & 0xffff; + n_flags=CPU_Pop32(); + if (n_flags & FLAG_VM) { + cpu.cpl=3; + CPU_SetFlags(n_flags,FMASK_ALL | FLAG_VM); + Bitu n_ss,n_esp,n_es,n_ds,n_fs,n_gs; + n_esp=CPU_Pop32(); + n_ss=CPU_Pop32() & 0xffff; + + n_es=CPU_Pop32() & 0xffff; + n_ds=CPU_Pop32() & 0xffff; + n_fs=CPU_Pop32() & 0xffff; + n_gs=CPU_Pop32() & 0xffff; + CPU_SetSegGeneral(ss,n_ss); + CPU_SetSegGeneral(es,n_es); + CPU_SetSegGeneral(ds,n_ds); + CPU_SetSegGeneral(fs,n_fs); + CPU_SetSegGeneral(gs,n_gs); + reg_eip=n_eip & 0xffff; + reg_esp=n_esp; + cpu.code.big=false; + SegSet16(cs,n_cs_sel); + LOG(LOG_CPU,LOG_NORMAL)("IRET:Back to V86: CS:%X IP %X SS:%X SP %X FLAGS:%X",SegValue(cs),reg_eip,SegValue(ss),reg_esp,reg_flags); + return; + } } else { - offset=CPU_Pop16(); - selector=CPU_Pop16(); - old_flags=(flags.word & 0xffff0000) | CPU_Pop16(); + n_eip=CPU_Pop16(); + n_cs_sel=CPU_Pop16(); + n_flags=(reg_flags & 0xffff0000) | CPU_Pop16(); + if (n_flags & FLAG_VM) E_Exit("VM Flag in 16-bit iret"); } - Bitu rpl=selector & 3; - Descriptor desc; - cpu.gdt.GetDescriptor(selector,desc); - if (rpl=cpu.cpl)) E_Exit("IRET:Same level:C:DPL=cpu.cpl)) E_Exit("IRET:Same level:C:DPL0; - Segs.val[cs]=(selector & 0xfffc) | cpu.cpl;; - reg_eip=offset; - CPU_SetFlags(old_flags); - LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level return to %X:%X big %d",selector,offset,cpu.code.big); + Segs.phys[cs]=n_cs_desc.GetBase(); + cpu.code.big=n_cs_desc.Big()>0; + Segs.val[cs]=n_cs_sel; + reg_eip=n_eip; + CPU_SetFlagsd(n_flags); + LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big); } else { - /* Return to higher privilege */ - switch (desc.Type()) { + /* Return to outer level */ + switch (n_cs_desc.Type()) { case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: - if (!(cpu.cpl==rpl)) E_Exit("IRET:Outer level:NC:RPL != DPL"); + if (n_cs_desc.DPL()!=n_cs_rpl) E_Exit("IRET:Outer level:NC:CS RPL != CS DPL"); break; case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: - if (!(desc.DPL()>cpu.cpl)) E_Exit("IRET:Outer level:C:DPL <= CPL"); + if (n_cs_desc.DPL()<=cpu.cpl) E_Exit("IRET:Outer level:C:DPL <= CPL"); break; default: - E_Exit("IRET from illegal descriptor type %X",desc.Type()); + E_Exit("IRET:Outer level:Illegal descriptor type %X",n_cs_desc.Type()); } - Segs.phys[cs]=desc.GetBase(); - cpu.code.big=desc.Big()>0; - Segs.val[cs]=selector; - cpu.cpl=rpl; - reg_eip=offset; - Bitu new_ss,new_esp; + Segs.phys[cs]=n_cs_desc.GetBase(); + cpu.code.big=n_cs_desc.Big()>0; + Segs.val[cs]=n_cs_sel; + cpu.cpl=n_cs_rpl; + reg_eip=n_eip; + CPU_SetFlagsd(n_flags); + Bitu n_ss,n_esp; if (use32) { - new_esp=CPU_Pop32(); - new_ss=CPU_Pop32() & 0xffff; + n_esp=CPU_Pop32(); + n_ss=CPU_Pop32() & 0xffff; } else { - new_esp=CPU_Pop16(); - new_ss=CPU_Pop16(); + n_esp=CPU_Pop16(); + n_ss=CPU_Pop16(); + } + CPU_SetSegGeneral(ss,n_ss); + if (cpu.stack.big) { + reg_esp=n_esp; + } else { + reg_sp=n_esp; } - reg_esp=new_esp; - CPU_SetSegGeneral(ss,new_ss); //TODO Maybe validate other segments, but why would anyone use them? - LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level return to %X:X big %d",selector,offset,cpu.code.big); + LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:X big %d",n_cs_sel,n_eip,cpu.code.big); } - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + return; } - return false; } -bool CPU_JMP(bool use32,Bitu selector,Bitu offset) { - if (!cpu.pmode || cpu.v86) { +void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu opLen) { + if (!cpu.pmode || (reg_flags & FLAG_VM)) { if (!use32) { reg_eip=offset&0xffff; } else { @@ -329,11 +578,16 @@ bool CPU_JMP(bool use32,Bitu selector,Bitu offset) { } SegSet16(cs,selector); cpu.code.big=false; - return CPU_CheckCodeType(CODE_REAL); + return; } else { Bitu rpl=selector & 3; Descriptor desc; cpu.gdt.GetDescriptor(selector,desc); + if (!desc.saved.seg.p) { + reg_eip -= opLen; + CPU_Exception(0x0B,selector & 0xfffc); + return; + } switch (desc.Type()) { case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: @@ -351,19 +605,24 @@ CODE_jmp: cpu.code.big=desc.Big()>0; Segs.val[cs]=(selector & 0xfffc) | cpu.cpl; reg_eip=offset; - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + return; + case DESC_386_TSS_A: + if (desc.DPL()0; Segs.val[cs]=(selector & 0xfffc) | cpu.cpl; - reg_eip=offset; - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); - case DESC_286_CALL_GATE: { - if (call.DPL()0; - reg_eip = neweip; - // Set CPL to stack segment DPL - // Set RPL of CS to CPL - cpu.cpl = newcpl; - Segs.val[cs] = (newcs & 0xfffc) | newcpl; - // 4. Load SS descriptor - // 5. Push long pointer of old stack onto new stack - Bitu oldsp = reg_sp; - CPU_Push16(SegValue(ss)); - CPU_Push16(oldsp); - // 6. Get word count from call gate, mask to 5 bits - Bitu wordCount = call.saved.gate.paramcount; - if (wordCount>0) LOG(LOG_CPU,LOG_NORMAL)("CPU: Callgate 286 wordcount : %d)",wordCount); - // 7. Copy parameters from old stack onto new stack - while (wordCount>0) { - CPU_Push16(mem_readw(SegPhys(ss)+oldsp)); - oldsp += 2; wordCount--; + return; + case DESC_386_CALL_GATE: + case DESC_286_CALL_GATE: + { + if (call.DPL()0; - // Set RPL of CS to CPL - cpu.cpl = seldpl; - Segs.val[cs] = (newcs & 0xfffc) | seldpl; - reg_eip = neweip; - // Push return address onto new stack - CPU_Push16(oldcs); - CPU_Push16(oldip); -// LOG(LOG_MISC,LOG_ERROR)("CPU: Callgate (Same) %04X:%04X",newcs,neweip); - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); - }; break; - }; + Bitu n_cs_dpl = n_cs_desc.DPL(); + Bitu n_cs_rpl = n_cs_sel & 3; + Bitu n_eip = call.GetOffset(); + switch (n_cs_desc.Type()) { + case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA: + case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA: + /* Check if we goto innter priviledge */ + if (n_cs_dpl < cpu.cpl) { + /* Get new SS:ESP out of TSS */ + Bitu n_ss_sel,n_esp; + Descriptor n_ss_desc; + cpu_tss.Get_SSx_ESPx(n_cs_dpl,n_ss_sel,n_esp); + if (!cpu.gdt.GetDescriptor(n_ss_sel,n_ss_desc)) E_Exit("Call:Gate:Invalid SS selector."); + /* New CPL is new SS DPL */ + cpu.cpl = n_ss_desc.DPL(); + /* Load the new SS:ESP and save data on it */ + Bitu o_esp = reg_esp; + Bitu o_ss = SegValue(ss); + PhysPt o_stack = SegPhys(ss)+(reg_esp & cpu.stack.mask); + + CPU_SetSegGeneral(ss,n_ss_sel); + if (cpu.stack.big) reg_esp=n_esp; + else reg_sp=n_esp; + if (call.Type()==DESC_386_CALL_GATE) { + CPU_Push32(o_ss); //save old stack + CPU_Push32(o_esp); + for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++) + CPU_Push32(mem_readd(o_stack+i*4)); + CPU_Push32(SegValue(cs)); + CPU_Push32(reg_eip); + } else { + CPU_Push16(o_ss); //save old stack + CPU_Push16(o_esp); + for (Bitu i=0;i<(call.saved.gate.paramcount&31);i++) + CPU_Push16(mem_readw(o_stack+i*2)); + CPU_Push16(SegValue(cs)); + CPU_Push16(reg_eip); + } + + /* Switch to new CS:EIP */ + Segs.phys[cs] = n_cs_desc.GetBase(); + Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl; + cpu.code.big = n_cs_desc.Big()>0; + reg_eip = n_eip; + if (!use32) reg_eip&=0xffff; + break; + } + case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA: + case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA: +call_gate_same_privilege: + E_Exit("Call gate to same priviledge"); + break; + } + } /* Call Gates */ + break; + case DESC_386_TSS_A: + if (call.DPL()0; Segs.val[cs]=selector; reg_eip=offset; + if (cpu.stack.big) { + reg_esp+=bytes; + } else { + reg_sp+=bytes; + } LOG(LOG_CPU,LOG_NORMAL)("RET - Same level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL()); - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + return; } else { - /* Return to higher level */ - Bitu newsp = CPU_Pop16(); - Bitu newss = CPU_Pop16(); + /* Return to outer level */ + if (bytes) E_Exit("RETF outeer level with immediate value"); + Bitu n_esp,n_ss; + if (use32) { + n_esp = CPU_Pop32(); + n_ss = CPU_Pop32() & 0xffff; + } else { + n_esp = CPU_Pop16(); + n_ss = CPU_Pop16(); + } cpu.cpl = rpl; - CPU_SetSegGeneral(ss,newss); - reg_esp = newsp; + CPU_SetSegGeneral(ss,n_ss); + if (cpu.stack.big) { + reg_esp = n_esp; + } else { + reg_sp = n_esp; + } Segs.phys[cs]=desc.GetBase(); cpu.code.big=desc.Big()>0; Segs.val[cs]=selector; reg_eip=offset; // LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL()); - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + return; } LOG(LOG_CPU,LOG_NORMAL)("Prot ret %X:%X",selector,offset); - return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + return; } - return false; + assert(1); } @@ -561,26 +854,27 @@ void CPU_SLDT(Bitu & selector) { selector=cpu.gdt.SLDT(); } -Bitu tr=0; void CPU_LLDT(Bitu selector) { cpu.gdt.LLDT(selector); LOG(LOG_CPU,LOG_NORMAL)("LDT Set to %X",selector); } void CPU_STR(Bitu & selector) { - selector=tr; + selector=cpu_tss.selector; } void CPU_LTR(Bitu selector) { - tr=selector; - LOG(LOG_CPU,LOG_NORMAL)("TR Set to %X",selector); + cpu_tss.SetSelector(selector); } +Bitu gdt_count=0; void CPU_LGDT(Bitu limit,Bitu base) { - LOG(LOG_CPU,LOG_NORMAL)("GDT Set to base:%X limit:%X",base,limit); + LOG(LOG_CPU,LOG_NORMAL)("GDT Set to base:%X limit:%X count %d",base,limit,gdt_count++); cpu.gdt.SetLimit(limit); cpu.gdt.SetBase(base); +// if (gdt_count>20) DEBUG_EnableDebugger(); +// DEBUG_EnableDebugger(); } void CPU_LIDT(Bitu limit,Bitu base) { @@ -619,6 +913,9 @@ bool CPU_SET_CRX(Bitu cr,Bitu value) { } return false; //Only changes with next CS change } + case 2: + paging.cr2=value; + break; case 3: PAGING_SetDirBase(value); break; @@ -633,6 +930,8 @@ Bitu CPU_GET_CRX(Bitu cr) { switch (cr) { case 0: return cpu.cr0; + case 2: + return paging.cr2; case 3: return PAGING_GetDirBase(); default: @@ -648,8 +947,9 @@ void CPU_SMSW(Bitu & word) { } bool CPU_LMSW(Bitu word) { - word&=0xffff; - word|=(cpu.cr0&0xffff0000); + word&=0xf; + if (cpu.cr0 & 1) word|=1; + word|=(cpu.cr0&0xfffffff0); return CPU_SET_CRX(0,word); } @@ -670,10 +970,6 @@ void CPU_LAR(Bitu selector,Bitu & ar) { SETFLAGBIT(ZF,false); return; } - if (!desc.saved.seg.p) { - SETFLAGBIT(ZF,false); - return; - } switch (desc.Type()){ case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: @@ -718,10 +1014,6 @@ void CPU_LSL(Bitu selector,Bitu & limit) { SETFLAGBIT(ZF,false); return; } - if (!desc.saved.seg.p) { - SETFLAGBIT(ZF,false); - return; - } switch (desc.Type()){ case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: @@ -760,10 +1052,6 @@ void CPU_VERR(Bitu selector) { SETFLAGBIT(ZF,false); return; } - if (!desc.saved.seg.p) { - SETFLAGBIT(ZF,false); - return; - } switch (desc.Type()){ case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: //Conforming readable code segments can be always read @@ -792,10 +1080,6 @@ void CPU_VERW(Bitu selector) { SETFLAGBIT(ZF,false); return; } - if (!desc.saved.seg.p) { - SETFLAGBIT(ZF,false); - return; - } switch (desc.Type()){ case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: @@ -811,19 +1095,35 @@ void CPU_VERW(Bitu selector) { SETFLAGBIT(ZF,true); } - -void CPU_SetSegGeneral(SegNames seg,Bitu value) { - Segs.val[seg]=value; - if (!cpu.pmode || cpu.v86) { +bool CPU_SetSegGeneral(SegNames seg,Bitu value) { + value &= 0xffff; + if (!cpu.pmode || (reg_flags & FLAG_VM)) { + Segs.val[seg]=value; Segs.phys[seg]=value << 4; -//TODO maybe just always do this when they enable/real/v86 mode if (seg==ss) { cpu.stack.big=false; cpu.stack.mask=0xffff; } + return false; } else { Descriptor desc; cpu.gdt.GetDescriptor(value,desc); + + if (value!=0) { + if (!desc.saved.seg.p) { + if (seg==ss) E_Exit("CPU_SetSegGeneral: Stack segment not present."); + // Throw Exception 0x0B - Segment not present + CPU_SetupException(0x0B,value & 0xfffc); + return true; + } else if (seg==ss) { + // Stack segment loaded with illegal segment ? + if ((desc.saved.seg.typeDESC_DATA_ED_RW_A)) { + CPU_SetupException(0x0D,value & 0xfffc); + return true; + } + } + } + Segs.val[seg]=value; Segs.phys[seg]=desc.GetBase(); if (seg==ss) { if (desc.Big()) { @@ -834,6 +1134,7 @@ void CPU_SetSegGeneral(SegNames seg,Bitu value) { cpu.stack.mask=0xffff; } } + return false; } } @@ -857,58 +1158,40 @@ void CPU_CPUID(void) { } } -void CPU_ReadTaskSeg32(PhysPt base,TaskSegment_32 * seg) { - seg->back =mem_readw(base+offsetof(TSS_386,back )); - seg->esp0 =mem_readd(base+offsetof(TSS_386,esp0 )); - seg->ss0 =mem_readw(base+offsetof(TSS_386,ss0 )); - seg->esp1 =mem_readd(base+offsetof(TSS_386,esp1 )); - seg->ss1 =mem_readw(base+offsetof(TSS_386,ss1 )); - seg->esp2 =mem_readd(base+offsetof(TSS_386,esp2 )); - seg->ss2 =mem_readw(base+offsetof(TSS_386,ss2 )); - - seg->cr3 =mem_readd(base+offsetof(TSS_386,cr3 )); - seg->eflags =mem_readd(base+offsetof(TSS_386,eflags )); - seg->eip =mem_readd(base+offsetof(TSS_386,eip )); - - seg->eax =mem_readd(base+offsetof(TSS_386,eax )); - seg->ecx =mem_readd(base+offsetof(TSS_386,ecx )); - seg->edx =mem_readd(base+offsetof(TSS_386,edx )); - seg->ebx =mem_readd(base+offsetof(TSS_386,ebx )); - seg->esp =mem_readd(base+offsetof(TSS_386,esp )); - seg->ebp =mem_readd(base+offsetof(TSS_386,ebp )); - seg->esi =mem_readd(base+offsetof(TSS_386,esi )); - seg->edi =mem_readd(base+offsetof(TSS_386,edi )); - - seg->es =mem_readw(base+offsetof(TSS_386,es )); - seg->cs =mem_readw(base+offsetof(TSS_386,cs )); - seg->ss =mem_readw(base+offsetof(TSS_386,ss )); - seg->ds =mem_readw(base+offsetof(TSS_386,ds )); - seg->fs =mem_readw(base+offsetof(TSS_386,fs )); - seg->gs =mem_readw(base+offsetof(TSS_386,gs )); - - seg->ldt =mem_readw(base+offsetof(TSS_386,ldt )); - seg->trap =mem_readw(base+offsetof(TSS_386,trap )); - seg->io =mem_readw(base+offsetof(TSS_386,io )); - -} - static Bits HLT_Decode(void) { /* Once an interrupt occurs, it should change cpu core */ - CPU_Cycles=0; + if (reg_eip!=cpu.hlt.eip || SegValue(cs) != cpu.hlt.cs) { + cpudecoder=cpu.hlt.old_decoder; + } else { + CPU_Cycles=0; + } return 0; } -void CPU_HLT(void) { +void CPU_HLT(Bitu opLen) { + if (cpu.cpl) { + reg_eip-=opLen; + CPU_Exception(13,0); + return; + } CPU_Cycles=0; - cpu.code.type=CODE_INIT; + cpu.hlt.cs=SegValue(cs); + cpu.hlt.eip=reg_eip; + cpu.hlt.old_decoder=cpudecoder; cpudecoder=&HLT_Decode; + return; } extern void GFX_SetTitle(Bits cycles ,Bits frameskip); static void CPU_CycleIncrease(void) { Bits old_cycles=CPU_CycleMax; - CPU_CycleMax=(Bits)(CPU_CycleMax*1.2); + if(CPU_CycleUp < 100){ + CPU_CycleMax = (Bits)(CPU_CycleMax * (1 + (float)CPU_CycleUp / 100.0)); + } else { + CPU_CycleMax = (Bits)(CPU_CycleMax + CPU_CycleUp); + } + CPU_CycleLeft=0;CPU_Cycles=0; if (CPU_CycleMax==old_cycles) CPU_CycleMax++; LOG_MSG("CPU:%d cycles",CPU_CycleMax); @@ -916,9 +1199,13 @@ static void CPU_CycleIncrease(void) { } static void CPU_CycleDecrease(void) { - CPU_CycleMax=(Bits)(CPU_CycleMax/1.2); + if(CPU_CycleDown < 100){ + CPU_CycleMax = (Bits)(CPU_CycleMax / (1 + (float)CPU_CycleDown / 100.0)); + } else { + CPU_CycleMax = (Bits)(CPU_CycleMax - CPU_CycleDown); + } CPU_CycleLeft=0;CPU_Cycles=0; - if (!CPU_CycleMax) CPU_CycleMax=1; + if (CPU_CycleMax <= 0) CPU_CycleMax=1; LOG_MSG("CPU:%d cycles",CPU_CycleMax); GFX_SetTitle(CPU_CycleMax,-1); } @@ -942,24 +1229,49 @@ void CPU_Init(Section* sec) { SegSet16(gs,0); SegSet16(ss,0); - reg_eip=0; - CPU_SetFlags(FLAG_IF); //Enable interrupts + CPU_SetFlags(FLAG_IF,FMASK_ALL); //Enable interrupts cpu.cr0=0xffffffff; - CPU_SET_CRX(0,0); //Initialize - cpu.v86=false; + CPU_SET_CRX(0,0); //Initialize cpu.code.big=false; - cpu.code.type=CODE_INIT; //So a new cpu core will be started cpu.stack.mask=0xffff; cpu.stack.big=false; - - CPU_JMP(false,0,0); //Setup the first cpu core + cpu.idt.SetBase(0); + cpu.idt.SetLimit(1023); + + /* Init the cpu cores */ + CPU_Core_Normal_Init(); + CPU_Core_Full_Init(); +#if (C_DYNAMIC_X86) + CPU_Core_Dyn_X86_Init(); +#endif KEYBOARD_AddEvent(KBD_f11,KBD_MOD_CTRL,CPU_CycleDecrease); KEYBOARD_AddEvent(KBD_f12,KBD_MOD_CTRL,CPU_CycleIncrease); CPU_Cycles=0; CPU_CycleMax=section->Get_int("cycles");; - if (!CPU_CycleMax) CPU_CycleMax=1500; + CPU_CycleUp=section->Get_int("cycleup"); + CPU_CycleDown=section->Get_int("cycledown"); + const char * core=section->Get_string("core"); + cpudecoder=&CPU_Core_Normal_Run; + if (!strcasecmp(core,"normal")) { + cpudecoder=&CPU_Core_Normal_Run; + } else if (!strcasecmp(core,"full")) { + cpudecoder=&CPU_Core_Full_Run; + } +#if (C_DYNAMIC_X86) + else if (!strcasecmp(core,"dynamic")) { + cpudecoder=&CPU_Core_Dyn_X86_Run; + } +#endif + else { + LOG_MSG("CPU:Unknown core type %s, switcing back to normal.",core); + } + CPU_JMP(false,0,0); //Setup the first cpu core + + if (!CPU_CycleMax) CPU_CycleMax = 2500; + if(!CPU_CycleUp) CPU_CycleUp = 500; + if(!CPU_CycleDown) CPU_CycleDown = 20; CPU_CycleLeft=0; GFX_SetTitle(CPU_CycleMax,-1); } diff --git a/src/cpu/flags.cpp b/src/cpu/flags.cpp index 4f3e07c..bb67384 100644 --- a/src/cpu/flags.cpp +++ b/src/cpu/flags.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,15 +26,15 @@ #include "lazyflags.h" #include "pic.h" +LazyFlags lflags; /* CF Carry Flag -- Set on high-order bit carry or borrow; cleared otherwise. */ Bitu get_CF(void) { - switch (flags.type) { + switch (lflags.type) { case t_UNKNOWN: - case t_CF: case t_INCb: case t_INCw: case t_INCd: @@ -48,77 +48,77 @@ Bitu get_CF(void) { return GETFLAG(CF); break; case t_ADDb: - return (flags.result.b8) return false; - else return (flags.var1.b >> (8-flags.var2.b)) & 1; + if (lf_var2b>8) return false; + else return (lf_var1b >> (8-lf_var2b)) & 1; case t_SHLw: - if (flags.var2.b>16) return false; - else return (flags.var1.w >> (16-flags.var2.b)) & 1; + if (lf_var2b>16) return false; + else return (lf_var1w >> (16-lf_var2b)) & 1; case t_SHLd: case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */ case t_DSHLd: - return (flags.var1.d >> (32 - flags.var2.b)) & 1; + return (lf_var1d >> (32 - lf_var2b)) & 1; case t_RCRb: case t_SHRb: - return (flags.var1.b >> (flags.var2.b - 1)) & 1; + return (lf_var1b >> (lf_var2b - 1)) & 1; case t_RCRw: case t_SHRw: - return (flags.var1.w >> (flags.var2.b - 1)) & 1; + return (lf_var1w >> (lf_var2b - 1)) & 1; case t_RCRd: case t_SHRd: case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ case t_DSHRd: - return (flags.var1.d >> (flags.var2.b - 1)) & 1; + return (lf_var1d >> (lf_var2b - 1)) & 1; case t_SARb: - return (((Bit8s) flags.var1.b) >> (flags.var2.b - 1)) & 1; + return (((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1; case t_SARw: - return (((Bit16s) flags.var1.w) >> (flags.var2.b - 1)) & 1; + return (((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1; case t_SARd: - return (((Bit32s) flags.var1.d) >> (flags.var2.b - 1)) & 1; + return (((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1; case t_NEGb: - return (flags.var1.b!=0); + return lf_var1b; case t_NEGw: - return (flags.var1.w!=0); + return lf_var1w; case t_NEGd: - return (flags.var1.d!=0); + return lf_var1d; case t_ROLb: - return flags.result.b & 1; + return lf_resb & 1; case t_ROLw: - return flags.result.w & 1; + return lf_resw & 1; case t_ROLd: - return flags.result.d & 1; + return lf_resd & 1; case t_RORb: - return (flags.result.b & 0x80)>0; + return (lf_resb & 0x80); case t_RORw: - return (flags.result.w & 0x8000)>0; + return (lf_resw & 0x8000); case t_RORd: - return (flags.result.d & 0x80000000)>0; + return (lf_resd & 0x80000000); case t_ORb: case t_ORw: case t_ORd: @@ -135,7 +135,7 @@ Bitu get_CF(void) { case t_DIV: return false; /* Unkown */ default: - LOG(LOG_CPU,LOG_ERROR)("get_CF Unknown %d",flags.type); + LOG(LOG_CPU,LOG_ERROR)("get_CF Unknown %d",lflags.type); } return 0; } @@ -145,8 +145,7 @@ Bitu get_CF(void) { arithmetic. */ Bitu get_AF(void) { - Bitu type=flags.type; -again: + Bitu type=lflags.type; switch (type) { case t_UNKNOWN: case t_ROLb: @@ -162,45 +161,42 @@ again: case t_RCLd: case t_RCRd: return GETFLAG(AF); - case t_CF: - type=flags.prev_type; - goto again; case t_ADDb: case t_ADCb: case t_SBBb: case t_SUBb: case t_CMPb: - return (((flags.var1.b ^ flags.var2.b) ^ flags.result.b) & 0x10)>0; + return ((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10; case t_ADDw: case t_ADCw: case t_SBBw: case t_SUBw: case t_CMPw: - return (((flags.var1.w ^ flags.var2.w) ^ flags.result.w) & 0x10)>0; + return ((lf_var1w ^ lf_var2w) ^ lf_resw) & 0x10; case t_ADCd: case t_ADDd: case t_SBBd: case t_SUBd: case t_CMPd: - return (((flags.var1.d ^ flags.var2.d) ^ flags.result.d) & 0x10)>0; + return ((lf_var1d ^ lf_var2d) ^ lf_resd) & 0x10; case t_INCb: - return (flags.result.b & 0x0f) == 0; + return (lf_resb & 0x0f) == 0; case t_INCw: - return (flags.result.w & 0x0f) == 0; + return (lf_resw & 0x0f) == 0; case t_INCd: - return (flags.result.d & 0x0f) == 0; + return (lf_resd & 0x0f) == 0; case t_DECb: - return (flags.result.b & 0x0f) == 0x0f; + return (lf_resb & 0x0f) == 0x0f; case t_DECw: - return (flags.result.w & 0x0f) == 0x0f; + return (lf_resw & 0x0f) == 0x0f; case t_DECd: - return (flags.result.d & 0x0f) == 0x0f; + return (lf_resd & 0x0f) == 0x0f; case t_NEGb: - return (flags.var1.b & 0x0f) > 0; + return lf_var1b & 0x0f; case t_NEGw: - return (flags.var1.w & 0x0f) > 0; + return lf_var1w & 0x0f; case t_NEGd: - return (flags.var1.d & 0x0f) > 0; + return lf_var1d & 0x0f; case t_ORb: case t_ORw: case t_ORd: @@ -230,7 +226,7 @@ again: case t_MUL: return false; /* Unkown */ default: - LOG(LOG_CPU,LOG_ERROR)("get_AF Unknown %d",flags.type); + LOG(LOG_CPU,LOG_ERROR)("get_AF Unknown %d",lflags.type); } return 0; } @@ -239,8 +235,7 @@ again: */ Bitu get_ZF(void) { - Bitu type=flags.type; -again: + Bitu type=lflags.type; switch (type) { case t_UNKNOWN: case t_ROLb: @@ -256,9 +251,6 @@ again: case t_RCLd: case t_RCRd: return GETFLAG(ZF); - case t_CF: - type=flags.prev_type; - goto again; case t_ADDb: case t_ORb: case t_ADCb: @@ -274,7 +266,7 @@ again: case t_SHRb: case t_SARb: case t_NEGb: - return (flags.result.b==0); + return (lf_resb==0); case t_ADDw: case t_ORw: case t_ADCw: @@ -292,7 +284,7 @@ again: case t_DSHLw: case t_DSHRw: case t_NEGw: - return (flags.result.w==0); + return (lf_resw==0); case t_ADDd: case t_ORd: case t_ADCd: @@ -310,12 +302,12 @@ again: case t_DSHLd: case t_DSHRd: case t_NEGd: - return (flags.result.d==0); + return (lf_resd==0); case t_DIV: case t_MUL: return false; /* Unkown */ default: - LOG(LOG_CPU,LOG_ERROR)("get_ZF Unknown %d",flags.type); + LOG(LOG_CPU,LOG_ERROR)("get_ZF Unknown %d",lflags.type); } return false; } @@ -323,8 +315,7 @@ again: positive, 1 if negative). */ Bitu get_SF(void) { - Bitu type=flags.type; -again: + Bitu type=lflags.type; switch (type) { case t_UNKNOWN: case t_ROLb: @@ -340,9 +331,6 @@ again: case t_RCLd: case t_RCRd: return GETFLAG(SF); - case t_CF: - type=flags.prev_type; - goto again; case t_ADDb: case t_ORb: case t_ADCb: @@ -358,7 +346,7 @@ again: case t_SHRb: case t_SARb: case t_NEGb: - return (flags.result.b>=0x80); + return (lf_resb&0x80); case t_ADDw: case t_ORw: case t_ADCw: @@ -376,7 +364,7 @@ again: case t_DSHLw: case t_DSHRw: case t_NEGw: - return (flags.result.w>=0x8000); + return (lf_resw&0x8000); case t_ADDd: case t_ORd: case t_ADCd: @@ -394,136 +382,86 @@ again: case t_DSHLd: case t_DSHRd: case t_NEGd: - return (flags.result.d>=0x80000000); + return (lf_resd&0x80000000); case t_DIV: case t_MUL: return false; /* Unkown */ default: - LOG(LOG_CPU,LOG_ERROR)("get_SF Unkown %d",flags.type); + LOG(LOG_CPU,LOG_ERROR)("get_SF Unkown %d",lflags.type); } return false; } Bitu get_OF(void) { - Bit8u var1b7, var2b7, resultb7; - Bit16u var1w15, var2w15, resultw15; - Bit32u var1d31, var2d31, resultd31; - - Bitu type=flags.type; -again: + Bitu type=lflags.type; switch (type) { case t_UNKNOWN: case t_MUL: - case t_RCLb: - case t_RCLw: - case t_RCLd: - case t_SARb: - case t_SARw: - case t_SARd: return GETFLAG(OF); - case t_CF: - type=flags.prev_type; - goto again; case t_ADDb: case t_ADCb: -// return (((flags.result.b) ^ (flags.var2.b)) & ((flags.result.b) ^ (flags.var1.b)) & 0x80)>0; - var1b7 = flags.var1.b & 0x80; - var2b7 = flags.var2.b & 0x80; - resultb7 = flags.result.b & 0x80; - return (var1b7 == var2b7) && (resultb7 ^ var2b7); + return ((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var2b)) & 0x80; case t_ADDw: case t_ADCw: -// return (((flags.result.w) ^ (flags.var2.w)) & ((flags.result.w) ^ (flags.var1.w)) & 0x8000)>0; - var1w15 = flags.var1.w & 0x8000; - var2w15 = flags.var2.w & 0x8000; - resultw15 = flags.result.w & 0x8000; - return (var1w15 == var2w15) && (resultw15 ^ var2w15); + return ((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var2w)) & 0x8000; case t_ADDd: case t_ADCd: -//TODO fix dword Overflow - var1d31 = flags.var1.d & 0x80000000; - var2d31 = flags.var2.d & 0x80000000; - resultd31 = flags.result.d & 0x80000000; - return (var1d31 == var2d31) && (resultd31 ^ var2d31); + return ((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var2d)) & 0x80000000; case t_SBBb: case t_SUBb: case t_CMPb: -// return (((flags.var1.b) ^ (flags.var2.b)) & ((flags.var1.b) ^ (flags.result.b)) & 0x80)>0; - var1b7 = flags.var1.b & 0x80; - var2b7 = flags.var2.b & 0x80; - resultb7 = flags.result.b & 0x80; - return (var1b7 ^ var2b7) && (var1b7 ^ resultb7); + return ((lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb)) & 0x80; case t_SBBw: case t_SUBw: case t_CMPw: -// return (((flags.var1.w) ^ (flags.var2.w)) & ((flags.var1.w) ^ (flags.result.w)) & 0x8000)>0; - var1w15 = flags.var1.w & 0x8000; - var2w15 = flags.var2.w & 0x8000; - resultw15 = flags.result.w & 0x8000; - return (var1w15 ^ var2w15) && (var1w15 ^ resultw15); + return ((lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw)) & 0x8000; case t_SBBd: case t_SUBd: case t_CMPd: - var1d31 = flags.var1.d & 0x80000000; - var2d31 = flags.var2.d & 0x80000000; - resultd31 = flags.result.d & 0x80000000; - return (var1d31 ^ var2d31) && (var1d31 ^ resultd31); + return ((lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd)) & 0x80000000; case t_INCb: - return (flags.result.b == 0x80); + return (lf_resb == 0x80); case t_INCw: - return (flags.result.w == 0x8000); + return (lf_resw == 0x8000); case t_INCd: - return (flags.result.d == 0x80000000); + return (lf_resd == 0x80000000); case t_DECb: - return (flags.result.b == 0x7f); + return (lf_resb == 0x7f); case t_DECw: - return (flags.result.w == 0x7fff); + return (lf_resw == 0x7fff); case t_DECd: - return (flags.result.d == 0x7fffffff); + return (lf_resd == 0x7fffffff); case t_NEGb: - return (flags.var1.b == 0x80); + return (lf_var1b == 0x80); case t_NEGw: - return (flags.var1.w == 0x8000); + return (lf_var1w == 0x8000); case t_NEGd: - return (flags.var1.d == 0x80000000); + return (lf_var1d == 0x80000000); case t_ROLb: - return ((flags.result.b & 0x80) ^ (flags.result.b & 1 ? 0x80 : 0)) != 0; - case t_ROLw: - return ((flags.result.w & 0x8000) ^ (flags.result.w & 1 ? 0x8000 : 0)) != 0; - case t_ROLd: - return ((flags.result.d & 0x80000000) ^ (flags.result.d & 1 ? 0x80000000 : 0)) != 0; - case t_SHLb: - if (flags.var2.b>9) return false; - return ((flags.result.b & 0x80) ^ - ((flags.var1.b << (flags.var2.b - 1)) & 0x80)) != 0; - case t_SHLw: - if (flags.var2.b>17) return false; - return ((flags.result.w & 0x8000) ^ - ((flags.var1.w << (flags.var2.b - 1)) & 0x8000)) != 0; - case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */ - return ((flags.result.w & 0x8000) ^ - (((flags.var1.d << (flags.var2.b - 1)) >> 16) & 0x8000)) != 0; - case t_SHLd: - case t_DSHLd: - return ((flags.result.d & 0x80000000) ^ - ((flags.var1.d << (flags.var2.b - 1)) & 0x80000000)) != 0; case t_RORb: + case t_RCLb: case t_RCRb: - return ((flags.result.b ^ (flags.result.b << 1)) & 0x80) > 0; - case t_RORw: - case t_RCRw: - case t_DSHRw: - return ((flags.result.w ^ (flags.result.w << 1)) & 0x8000) > 0; - case t_RORd: - case t_RCRd: - case t_DSHRd: - return ((flags.result.d ^ (flags.result.d << 1)) & 0x80000000) > 0; + case t_SHLb: case t_SHRb: - return (flags.result.b >= 0x40); + return (lf_resb ^ lf_var1b) & 0x80; + case t_ROLw: + case t_RORw: + case t_RCLw: + case t_RCRw: + case t_SHLw: case t_SHRw: - return (flags.result.w >= 0x4000); + case t_DSHRw: + case t_DSHLw: + return (lf_resw ^ lf_var1w) & 0x8000; + case t_ROLd: + case t_RORd: + case t_RCLd: + case t_RCRd: + case t_SHLd: case t_SHRd: - return (flags.result.d >= 0x40000000); + case t_DSHRd: + case t_DSHLd: + return (lf_resd ^ lf_var1d) & 0x80000000; case t_ORb: case t_ORw: case t_ORd: @@ -536,286 +474,495 @@ again: case t_TESTb: case t_TESTw: case t_TESTd: - return false; /* Return false */ + case t_SARb: + case t_SARw: + case t_SARd: + return false; /* Return false */ case t_DIV: return false; /* Unkown */ default: - LOG(LOG_CPU,LOG_ERROR)("get_OF Unkown %d",flags.type); + LOG(LOG_CPU,LOG_ERROR)("get_OF Unkown %d",lflags.type); } return false; } -bool parity_lookup[256] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 +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, + 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, + 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, + FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, + 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, + FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, + FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, + 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, + 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, + FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, + FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, + 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, + FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, + 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, + 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, + 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) { - switch (flags.type) { + switch (lflags.type) { case t_UNKNOWN: return GETFLAG(PF); default: - return (parity_lookup[flags.result.b]);; + return (parity_lookup[lf_resb]);; }; return false; } -void FillFlags(void) { - Bitu new_word=(flags.word & ~FLAG_MASK); +#if 0 + +Bitu FillFlags(void) { +// if (lflags.type==t_UNKNOWN) return reg_flags; + Bitu new_word=(reg_flags & ~FLAG_MASK); if (get_CF()) new_word|=FLAG_CF; if (get_PF()) new_word|=FLAG_PF; if (get_AF()) new_word|=FLAG_AF; if (get_ZF()) new_word|=FLAG_ZF; if (get_SF()) new_word|=FLAG_SF; if (get_OF()) new_word|=FLAG_OF; - flags.word=new_word; - flags.type=t_UNKNOWN; + reg_flags=new_word; + lflags.type=t_UNKNOWN; + return reg_flags; } -#if 0 +#else -Bitu get_Flags(void) { - Bitu new_flags=0; - switch (flags.type) { +#define DOFLAG_PF reg_flags=(reg_flags & ~FLAG_PF) | parity_lookup[lf_resb]; + +#define DOFLAG_AF reg_flags=(reg_flags & ~FLAG_AF) | (((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10); + +#define DOFLAG_ZFb SETFLAGBIT(ZF,lf_resb==0); +#define DOFLAG_ZFw SETFLAGBIT(ZF,lf_resw==0); +#define DOFLAG_ZFd SETFLAGBIT(ZF,lf_resd==0); + +#define DOFLAG_SFb reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resb & 0x80) >> 0); +#define DOFLAG_SFw reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resw & 0x8000) >> 8); +#define DOFLAG_SFd reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resd & 0x80000000) >> 24); + +#define SETCF(NEWBIT) reg_flags=(reg_flags & ~FLAG_CF)|(NEWBIT); + +#define SET_FLAG SETFLAGBIT +Bitu FillFlags(void) { + switch (lflags.type) { + case t_UNKNOWN: + break; case t_ADDb: - SET_FLAG(FLAG_CF,(flags.result.b0); + SET_FLAG(CF,(lf_resb0); + SET_FLAG(CF,(lf_resw0); + SET_FLAG(CF,(lf_resd0); + SET_FLAG(CF,(lf_resb < lf_var1b) || (lflags.oldcf && (lf_resb == lf_var1b))); + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + SET_FLAG(OF,((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var1b)) & 0x80); + DOFLAG_PF; break; case t_ADCw: - SET_FLAG(FLAG_CF,(flags.result.w < flags.var1.w) || (flags.oldcf && (flags.result.w == flags.var1.w))); - SET_FLAG(FLAG_AF,(((flags.var1.w ^ flags.var2.w) ^ flags.result.w) & 0x10)>0); + SET_FLAG(CF,(lf_resw < lf_var1w) || (lflags.oldcf && (lf_resw == lf_var1w))); + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var1w)) & 0x8000); + DOFLAG_PF; break; case t_ADCd: - SET_FLAG(FLAG_CF,(flags.result.d < flags.var1.d) || (flags.oldcf && (flags.result.d == flags.var1.d))); - SET_FLAG(FLAG_AF,(((flags.var1.d ^ flags.var2.d) ^ flags.result.d) & 0x10)>0); + SET_FLAG(CF,(lf_resd < lf_var1d) || (lflags.oldcf && (lf_resd == lf_var1d))); + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var1d)) & 0x80000000); + DOFLAG_PF; break; - + case t_SBBb: - SET_FLAG(FLAG_CF,(flags.var1.b < flags.result.b) || (flags.oldcf && (flags.var2.b==0xff))); - SET_FLAG(FLAG_AF,(((flags.var1.b ^ flags.var2.b) ^ flags.result.b) & 0x10)>0); + SET_FLAG(CF,(lf_var1b < lf_resb) || (lflags.oldcf && (lf_var2b==0xff))); + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + SET_FLAG(OF,(lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb) & 0x80); + DOFLAG_PF; break; case t_SBBw: - SET_FLAG(FLAG_CF,(flags.var1.w < flags.result.w) || (flags.oldcf && (flags.var2.w==0xffff))); - SET_FLAG(FLAG_AF,(((flags.var1.w ^ flags.var2.w) ^ flags.result.w) & 0x10)>0); + SET_FLAG(CF,(lf_var1w < lf_resw) || (lflags.oldcf && (lf_var2w==0xffff))); + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,(lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw) & 0x8000); + DOFLAG_PF; break; case t_SBBd: - SET_FLAG(FLAG_CF,(flags.var1.d < flags.result.d) || (flags.oldcf && (flags.var2.d==0xffffffff))); - SET_FLAG(FLAG_AF,(((flags.var1.d ^ flags.var2.d) ^ flags.result.d) & 0x10)>0); + SET_FLAG(CF,(lf_var1d < lf_resd) || (lflags.oldcf && (lf_var2d==0xffffffff))); + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,(lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd) & 0x80000000); + DOFLAG_PF; break; case t_SUBb: case t_CMPb: - SET_FLAG(FLAG_CF,(flags.var1.b0); + SET_FLAG(CF,(lf_var1b0); + SET_FLAG(CF,(lf_var1w0); + SET_FLAG(CF,(lf_var1d8) SET_FLAG(FLAG_CF,false); - else SET_FLAG(FLAG_CF,(flags.var1.b >> (8-flags.var2.b)) & 1); + if (lf_var2b>8) SET_FLAG(CF,false); + else SET_FLAG(CF,(lf_var1b >> (8-lf_var2b)) & 1); + DOFLAG_ZFb; + DOFLAG_SFb; + SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); + DOFLAG_PF; break; case t_SHLw: - if (flags.var2.b>16) SET_FLAG(FLAG_CF,false); - else SET_FLAG(FLAG_CF,(flags.var1.w >> (16-flags.var2.b)) & 1); + if (lf_var2b>16) SET_FLAG(CF,false); + else SET_FLAG(CF,(lf_var1w >> (16-lf_var2b)) & 1); + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); + DOFLAG_PF; break; case t_SHLd: - SET_FLAG(FLAG_CF,(flags.var1.d >> (32 - flags.var2.b)) & 1); + SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1); + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); + DOFLAG_PF; break; - case t_DSHLw: /* Hmm this is not correct for shift higher than 16 */ - SET_FLAG(FLAG_CF,(flags.var1.d >> (32 - flags.var2.b)) & 1); + case t_DSHLw: + SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1); + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); + DOFLAG_PF; break; case t_DSHLd: - SET_FLAG(FLAG_CF,(flags.var1.d >> (32 - flags.var2.b)) & 1); + SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1); + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); + DOFLAG_PF; break; case t_SHRb: - SET_FLAG(FLAG_CF,(flags.var1.b >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(lf_var1b >> (lf_var2b - 1)) & 1); + DOFLAG_ZFb; + DOFLAG_SFb; + SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); + DOFLAG_PF; break; case t_SHRw: - SET_FLAG(FLAG_CF,(flags.var1.w >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(lf_var1w >> (lf_var2b - 1)) & 1); + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); + DOFLAG_PF; break; case t_SHRd: - SET_FLAG(FLAG_CF,(flags.var1.d >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); + DOFLAG_PF; break; case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ - SET_FLAG(FLAG_CF,(flags.var1.d >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); + DOFLAG_PF; break; case t_DSHRd: - SET_FLAG(FLAG_CF,(flags.var1.d >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); + DOFLAG_PF; break; case t_SARb: - SET_FLAG(FLAG_CF,(((Bit8s) flags.var1.b) >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1); + DOFLAG_ZFb; + DOFLAG_SFb; + SET_FLAG(OF,false); + DOFLAG_PF; break; case t_SARw: - SET_FLAG(FLAG_CF,(((Bit16s) flags.var1.w) >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1); + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,false); + DOFLAG_PF; break; case t_SARd: - SET_FLAG(FLAG_CF,(((Bit32s) flags.var1.d) >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1); + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,false); + DOFLAG_PF; break; case t_ROLb: - SET_FLAG(FLAG_CF,flags.result.b & 1); + SET_FLAG(CF,lf_resb & 1); + SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); break; case t_ROLw: - SET_FLAG(FLAG_CF,flags.result.w & 1); + SET_FLAG(CF,lf_resw & 1); + SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); break; case t_ROLd: - SET_FLAG(FLAG_CF,flags.result.d & 1); + SET_FLAG(CF,lf_resd & 1); + SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); break; case t_RORb: - SET_FLAG(FLAG_CF,(flags.result.b & 0x80)>0); + SET_FLAG(CF,(lf_resb & 0x80)); + SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); break; case t_RORw: - SET_FLAG(FLAG_CF,(flags.result.w & 0x8000)>0); + SET_FLAG(CF,(lf_resw & 0x8000)); + SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); break; case t_RORd: - SET_FLAG(FLAG_CF,(flags.result.d & 0x80000000)>0); + SET_FLAG(CF,(lf_resd & 0x80000000)); + SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); break; + case t_RCLb: + SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); + break; + case t_RCLw: + SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); + break; + case t_RCLd: + SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); + break; case t_RCRb: - SET_FLAG(FLAG_CF,(flags.var1.b >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(lf_var1b >> (lf_var2b - 1)) & 1); + SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); break; case t_RCRw: - SET_FLAG(FLAG_CF,(flags.var1.w >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(lf_var1w >> (lf_var2b - 1)) & 1); + SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); break; case t_RCRd: - SET_FLAG(FLAG_CF,(flags.var1.d >> (flags.var2.b - 1)) & 1); + SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); + SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); break; - case t_INCb: - SET_FLAG(FLAG_OF,(flags.result.b == 0x80)); - SET_FLAG(FLAG_AF,((flags.result.b & 0x0f) == 0)); + SET_FLAG(AF,(lf_resb & 0x0f) == 0); + DOFLAG_ZFb; + DOFLAG_SFb; + SET_FLAG(OF,(lf_resb == 0x80)); + DOFLAG_PF; break; case t_INCw: - SET_FLAG(FLAG_OF,(flags.result.w == 0x8000)); - SET_FLAG(FLAG_AF,((flags.result.w & 0x0f) == 0)); + SET_FLAG(AF,(lf_resw & 0x0f) == 0); + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,(lf_resw == 0x8000)); + DOFLAG_PF; break; case t_INCd: - SET_FLAG(FLAG_OF,(flags.result.d == 0x80000000)); - SET_FLAG(FLAG_AF,((flags.result.d & 0x0f) == 0)); + SET_FLAG(AF,(lf_resd & 0x0f) == 0); + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,(lf_resd == 0x80000000)); + DOFLAG_PF; break; - case t_DECb: - SET_FLAG(FLAG_OF,(flags.result.b == 0x7f)); + SET_FLAG(AF,(lf_resb & 0x0f) == 0); + DOFLAG_ZFb; + DOFLAG_SFb; + SET_FLAG(OF,(lf_resb == 0x7f)); + DOFLAG_PF; break; case t_DECw: - SET_FLAG(FLAG_OF,(flags.result.w == 0x7fff)); + SET_FLAG(AF,(lf_resw & 0x0f) == 0); + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,(lf_resw == 0x7fff)); + DOFLAG_PF; break; case t_DECd: - SET_FLAG(FLAG_OF,(flags.result.d == 0x7fffffff)); + SET_FLAG(AF,(lf_resd & 0x0f) == 0); + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,(lf_resd == 0x7fffffff)); + DOFLAG_PF; break; - case t_NEGb: - SET_FLAG(FLAG_CF,(flags.var1.b!=0)); + SET_FLAG(CF,(lf_var1b!=0)); + SET_FLAG(AF,(lf_resb & 0x0f) == 0); + DOFLAG_ZFb; + DOFLAG_SFb; + SET_FLAG(OF,(lf_var1b == 0x80)); + DOFLAG_PF; break; case t_NEGw: - SET_FLAG(FLAG_CF,(flags.var1.w!=0)); + SET_FLAG(CF,(lf_var1w!=0)); + SET_FLAG(AF,(lf_resw & 0x0f) == 0); + DOFLAG_ZFw; + DOFLAG_SFw; + SET_FLAG(OF,(lf_var1w == 0x8000)); + DOFLAG_PF; break; case t_NEGd: - SET_FLAG(FLAG_CF,(flags.var1.d!=0)); + SET_FLAG(CF,(lf_var1d!=0)); + SET_FLAG(AF,(lf_resd & 0x0f) == 0); + DOFLAG_ZFd; + DOFLAG_SFd; + SET_FLAG(OF,(lf_var1d == 0x80000000)); + DOFLAG_PF; break; case t_DIV: - SET_FLAG(FLAG_CF,false); /* Unkown */ + case t_MUL: break; + default: - LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",flags.type); + LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type); return 0; } - flags.word=new_flags; - return 0; + lflags.type=t_UNKNOWN; + return reg_flags; } #endif diff --git a/src/cpu/instructions.h b/src/cpu/instructions.h index 7f0d731..3f94113 100644 --- a/src/cpu/instructions.h +++ b/src/cpu/instructions.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,442 +20,439 @@ /* All Byte genereal instructions */ #define ADDB(op1,op2,load,save) \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b+flags.var2.b; \ - save(op1,flags.result.b); \ - flags.type=t_ADDb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b+lf_var2b; \ + save(op1,lf_resb); \ + lflags.type=t_ADDb; #define ADCB(op1,op2,load,save) \ - flags.oldcf=get_CF(); \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b+flags.var2.b+flags.oldcf; \ - save(op1,flags.result.b); \ - flags.type=t_ADCb; + lflags.oldcf=get_CF()!=0; \ + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b+lf_var2b+lflags.oldcf; \ + save(op1,lf_resb); \ + lflags.type=t_ADCb; #define SBBB(op1,op2,load,save) \ - flags.oldcf=get_CF(); \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b-(flags.var2.b+flags.oldcf); \ - save(op1,flags.result.b); \ - flags.type=t_SBBb; + lflags.oldcf=get_CF()!=0; \ + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b-(lf_var2b+lflags.oldcf); \ + save(op1,lf_resb); \ + lflags.type=t_SBBb; #define SUBB(op1,op2,load,save) \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b-flags.var2.b; \ - save(op1,flags.result.b); \ - flags.type=t_SUBb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b-lf_var2b; \ + save(op1,lf_resb); \ + lflags.type=t_SUBb; #define ORB(op1,op2,load,save) \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b | flags.var2.b; \ - save(op1,flags.result.b); \ - flags.type=t_ORb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b | lf_var2b; \ + save(op1,lf_resb); \ + lflags.type=t_ORb; #define XORB(op1,op2,load,save) \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b ^ flags.var2.b; \ - save(op1,flags.result.b); \ - flags.type=t_XORb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b ^ lf_var2b; \ + save(op1,lf_resb); \ + lflags.type=t_XORb; #define ANDB(op1,op2,load,save) \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b & flags.var2.b; \ - save(op1,flags.result.b); \ - flags.type=t_ANDb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b & lf_var2b; \ + save(op1,lf_resb); \ + lflags.type=t_ANDb; #define CMPB(op1,op2,load,save) \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b-flags.var2.b; \ - flags.type=t_CMPb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b-lf_var2b; \ + lflags.type=t_CMPb; #define TESTB(op1,op2,load,save) \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b & flags.var2.b; \ - flags.type=t_TESTb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b & lf_var2b; \ + lflags.type=t_TESTb; /* All Word General instructions */ #define ADDW(op1,op2,load,save) \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w+flags.var2.w; \ - save(op1,flags.result.w); \ - flags.type=t_ADDw; + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w+lf_var2w; \ + save(op1,lf_resw); \ + lflags.type=t_ADDw; #define ADCW(op1,op2,load,save) \ - flags.oldcf=get_CF(); \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w+flags.var2.w+flags.oldcf; \ - save(op1,flags.result.w); \ - flags.type=t_ADCw; + lflags.oldcf=get_CF()!=0; \ + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w+lf_var2w+lflags.oldcf; \ + save(op1,lf_resw); \ + lflags.type=t_ADCw; #define SBBW(op1,op2,load,save) \ - flags.oldcf=get_CF(); \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w-(flags.var2.w+flags.oldcf); \ - save(op1,flags.result.w); \ - flags.type=t_SBBw; + lflags.oldcf=get_CF()!=0; \ + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w-(lf_var2w+lflags.oldcf); \ + save(op1,lf_resw); \ + lflags.type=t_SBBw; #define SUBW(op1,op2,load,save) \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w-flags.var2.w; \ - save(op1,flags.result.w); \ - flags.type=t_SUBw; + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w-lf_var2w; \ + save(op1,lf_resw); \ + lflags.type=t_SUBw; #define ORW(op1,op2,load,save) \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w | flags.var2.w; \ - save(op1,flags.result.w); \ - flags.type=t_ORw; + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w | lf_var2w; \ + save(op1,lf_resw); \ + lflags.type=t_ORw; #define XORW(op1,op2,load,save) \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w ^ flags.var2.w; \ - save(op1,flags.result.w); \ - flags.type=t_XORw; + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w ^ lf_var2w; \ + save(op1,lf_resw); \ + lflags.type=t_XORw; #define ANDW(op1,op2,load,save) \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w & flags.var2.w; \ - save(op1,flags.result.w); \ - flags.type=t_ANDw; + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w & lf_var2w; \ + save(op1,lf_resw); \ + lflags.type=t_ANDw; #define CMPW(op1,op2,load,save) \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w-flags.var2.w; \ - flags.type=t_CMPw; + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w-lf_var2w; \ + lflags.type=t_CMPw; #define TESTW(op1,op2,load,save) \ - flags.var1.w=load(op1);flags.var2.w=op2; \ - flags.result.w=flags.var1.w & flags.var2.w; \ - flags.type=t_TESTw; + lf_var1w=load(op1);lf_var2w=op2; \ + lf_resw=lf_var1w & lf_var2w; \ + lflags.type=t_TESTw; /* All DWORD General Instructions */ #define ADDD(op1,op2,load,save) \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d+flags.var2.d; \ - save(op1,flags.result.d); \ - flags.type=t_ADDd; + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d+lf_var2d; \ + save(op1,lf_resd); \ + lflags.type=t_ADDd; #define ADCD(op1,op2,load,save) \ - flags.oldcf=get_CF(); \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d+flags.var2.d+flags.oldcf; \ - save(op1,flags.result.d); \ - flags.type=t_ADCd; + lflags.oldcf=get_CF()!=0; \ + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d+lf_var2d+lflags.oldcf; \ + save(op1,lf_resd); \ + lflags.type=t_ADCd; #define SBBD(op1,op2,load,save) \ - flags.oldcf=get_CF(); \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d-(flags.var2.d+flags.oldcf); \ - save(op1,flags.result.d); \ - flags.type=t_SBBd; + lflags.oldcf=get_CF()!=0; \ + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d-(lf_var2d+lflags.oldcf); \ + save(op1,lf_resd); \ + lflags.type=t_SBBd; #define SUBD(op1,op2,load,save) \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d-flags.var2.d; \ - save(op1,flags.result.d); \ - flags.type=t_SUBd; + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d-lf_var2d; \ + save(op1,lf_resd); \ + lflags.type=t_SUBd; #define ORD(op1,op2,load,save) \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d | flags.var2.d; \ - save(op1,flags.result.d); \ - flags.type=t_ORd; + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d | lf_var2d; \ + save(op1,lf_resd); \ + lflags.type=t_ORd; #define XORD(op1,op2,load,save) \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d ^ flags.var2.d; \ - save(op1,flags.result.d); \ - flags.type=t_XORd; + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d ^ lf_var2d; \ + save(op1,lf_resd); \ + lflags.type=t_XORd; #define ANDD(op1,op2,load,save) \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d & flags.var2.d; \ - save(op1,flags.result.d); \ - flags.type=t_ANDd; + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d & lf_var2d; \ + save(op1,lf_resd); \ + lflags.type=t_ANDd; #define CMPD(op1,op2,load,save) \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d-flags.var2.d; \ - flags.type=t_CMPd; + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d-lf_var2d; \ + lflags.type=t_CMPd; #define TESTD(op1,op2,load,save) \ - flags.var1.d=load(op1);flags.var2.d=op2; \ - flags.result.d=flags.var1.d & flags.var2.d; \ - flags.type=t_TESTd; + lf_var1d=load(op1);lf_var2d=op2; \ + lf_resd=lf_var1d & lf_var2d; \ + lflags.type=t_TESTd; #define INCB(op1,load,save) \ - LoadCF;flags.result.b=load(op1)+1; \ - save(op1,flags.result.b); \ - flags.type=t_INCb; \ + LoadCF;lf_var1b=load(op1); \ + lf_resb=lf_var1b+1; \ + save(op1,lf_resb); \ + lflags.type=t_INCb; \ #define INCW(op1,load,save) \ - LoadCF;flags.result.w=load(op1)+1; \ - save(op1,flags.result.w); \ - flags.type=t_INCw; + LoadCF;lf_var1w=load(op1); \ + lf_resw=lf_var1w+1; \ + save(op1,lf_resw); \ + lflags.type=t_INCw; #define INCD(op1,load,save) \ - LoadCF;flags.result.d=load(op1)+1; \ - save(op1,flags.result.d); \ - flags.type=t_INCd; + LoadCF;lf_var1d=load(op1); \ + lf_resd=lf_var1d+1; \ + save(op1,lf_resd); \ + lflags.type=t_INCd; #define DECB(op1,load,save) \ - LoadCF;flags.result.b=load(op1)-1; \ - save(op1,flags.result.b); \ - flags.type=t_DECb; + LoadCF;lf_var1b=load(op1); \ + lf_resb=lf_var1b-1; \ + save(op1,lf_resb); \ + lflags.type=t_DECb; #define DECW(op1,load,save) \ - LoadCF;flags.result.w=load(op1)-1; \ - save(op1,flags.result.w); \ - flags.type=t_DECw; + LoadCF;lf_var1w=load(op1); \ + lf_resw=lf_var1w-1; \ + save(op1,lf_resw); \ + lflags.type=t_DECw; #define DECD(op1,load,save) \ - LoadCF;flags.result.d=load(op1)-1; \ - save(op1,flags.result.d); \ - flags.type=t_DECd; + LoadCF;lf_var1d=load(op1); \ + lf_resd=lf_var1d-1; \ + save(op1,lf_resd); \ + lflags.type=t_DECd; #define ROLB(op1,op2,load,save) \ LoadZF;LoadSF;LoadAF; \ - flags.var1.b=load(op1); \ - flags.var2.b=op2&0x07; \ - flags.result.b=(flags.var1.b << flags.var2.b) | \ - (flags.var1.b >> (8-flags.var2.b)); \ - save(op1,flags.result.b); \ - flags.type=t_ROLb; \ + lf_var1b=load(op1); \ + lf_var2b=op2&0x07; \ + lf_resb=(lf_var1b << lf_var2b) | \ + (lf_var1b >> (8-lf_var2b)); \ + save(op1,lf_resb); \ + lflags.type=t_ROLb; \ #define ROLW(op1,op2,load,save) \ LoadZF;LoadSF;LoadAF; \ - flags.var1.w=load(op1); \ - flags.var2.b=op2&0x0F; \ - flags.result.w=(flags.var1.w << flags.var2.b) | \ - (flags.var1.w >> (16-flags.var2.b)); \ - save(op1,flags.result.w); \ - flags.type=t_ROLw; \ + lf_var1w=load(op1); \ + lf_var2b=op2&0x0F; \ + lf_resw=(lf_var1w << lf_var2b) | \ + (lf_var1w >> (16-lf_var2b)); \ + save(op1,lf_resw); \ + lflags.type=t_ROLw; \ #define ROLD(op1,op2,load,save) \ LoadZF;LoadSF;LoadAF; \ - flags.var1.d=load(op1); \ - flags.var2.b=op2; \ - flags.result.d=(flags.var1.d << flags.var2.b) | \ - (flags.var1.d >> (32-flags.var2.b)); \ - save(op1,flags.result.d); \ - flags.type=t_ROLd; \ + lf_var1d=load(op1); \ + lf_var2b=op2; \ + lf_resd=(lf_var1d << lf_var2b) | \ + (lf_var1d >> (32-lf_var2b)); \ + save(op1,lf_resd); \ + lflags.type=t_ROLd; \ #define RORB(op1,op2,load,save) \ LoadZF;LoadSF;LoadAF; \ - flags.var1.b=load(op1); \ - flags.var2.b=op2&0x07; \ - flags.result.b=(flags.var1.b >> flags.var2.b) | \ - (flags.var1.b << (8-flags.var2.b)); \ - save(op1,flags.result.b); \ - flags.type=t_RORb; \ + lf_var1b=load(op1); \ + lf_var2b=op2&0x07; \ + lf_resb=(lf_var1b >> lf_var2b) | \ + (lf_var1b << (8-lf_var2b)); \ + save(op1,lf_resb); \ + lflags.type=t_RORb; \ #define RORW(op1,op2,load,save) \ if (op2&0x0F) { \ LoadZF;LoadSF;LoadAF; \ - flags.var1.w=load(op1); \ - flags.var2.b=op2&0x0F; \ - flags.result.w=(flags.var1.w >> flags.var2.b) | \ - (flags.var1.w << (16-flags.var2.b)); \ - save(op1,flags.result.w); \ - flags.type=t_RORw; \ + lf_var1w=load(op1); \ + lf_var2b=op2&0x0F; \ + lf_resw=(lf_var1w >> lf_var2b) | \ + (lf_var1w << (16-lf_var2b)); \ + save(op1,lf_resw); \ + lflags.type=t_RORw; \ } #define RORD(op1,op2,load,save) \ if (op2) { \ LoadZF;LoadSF;LoadAF; \ - flags.var1.d=load(op1); \ - flags.var2.b=op2; \ - flags.result.d=(flags.var1.d >> flags.var2.b) | \ - (flags.var1.d << (32-flags.var2.b)); \ - save(op1,flags.result.d); \ - flags.type=t_RORd; \ + lf_var1d=load(op1); \ + lf_var2b=op2; \ + lf_resd=(lf_var1d >> lf_var2b) | \ + (lf_var1d << (32-lf_var2b)); \ + save(op1,lf_resd); \ + lflags.type=t_RORd; \ } #define RCLB(op1,op2,load,save) \ if (op2%9) { \ - LoadZF;LoadSF;LoadAF; \ - Bit8u cf=get_CF(); \ - flags.var1.b=load(op1); \ - flags.var2.b=op2%9; \ - flags.type=t_RCLb; \ - flags.result.b=(flags.var1.b << flags.var2.b) | \ - (cf << (flags.var2.b-1)) | \ - (flags.var1.b >> (9-flags.var2.b)); \ - SETFLAGBIT(CF,((flags.var1.b >> (8-flags.var2.b)) & 1)); \ - SETFLAGBIT(OF,(flags.var1.b ^ flags.result.b) & 0x80); \ - save(op1,flags.result.b); \ + Bit8u cf=(Bit8u)FillFlags()&0x1; \ + lf_var1b=load(op1); \ + lf_var2b=op2%9; \ + lflags.type=t_RCLb; \ + lf_resb=(lf_var1b << lf_var2b) | \ + (cf << (lf_var2b-1)) | \ + (lf_var1b >> (9-lf_var2b)); \ + SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1)); \ + save(op1,lf_resb); \ } #define RCLW(op1,op2,load,save) \ if (op2%17) { \ - LoadZF;LoadSF;LoadAF; \ - Bit16u cf=get_CF(); \ - flags.var1.w=load(op1); \ - flags.var2.b=op2%17; \ - flags.type=t_RCLw; \ - flags.result.w=(flags.var1.w << flags.var2.b) | \ - (cf << (flags.var2.b-1)) | \ - (flags.var1.w >> (17-flags.var2.b)); \ - SETFLAGBIT(CF,((flags.var1.w >> (16-flags.var2.b)) & 1)); \ - SETFLAGBIT(OF,(flags.var1.w ^ flags.result.w) & 0x8000); \ - save(op1,flags.result.w); \ + Bit16u cf=(Bit16u)FillFlags()&0x1; \ + lf_var1w=load(op1); \ + lf_var2b=op2%17; \ + lflags.type=t_RCLw; \ + lf_resw=(lf_var1w << lf_var2b) | \ + (cf << (lf_var2b-1)) | \ + (lf_var1w >> (17-lf_var2b)); \ + SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1)); \ + save(op1,lf_resw); \ } #define RCLD(op1,op2,load,save) \ if (op2) { \ - LoadZF;LoadSF;LoadAF; \ - Bit32u cf=get_CF(); \ - flags.var1.d=load(op1); \ - flags.var2.b=op2; \ - flags.type=t_RCLd; \ - if (flags.var2.b==1) { \ - flags.result.d=(flags.var1.d << 1) | cf; \ + Bit32u cf=(Bit32u)FillFlags()&0x1; \ + lf_var1d=load(op1); \ + lf_var2b=op2; \ + lflags.type=t_RCLd; \ + if (lf_var2b==1) { \ + lf_resd=(lf_var1d << 1) | cf; \ } else { \ - flags.result.d=(flags.var1.d << flags.var2.b) | \ - (cf << (flags.var2.b-1)) | \ - (flags.var1.d >> (33-flags.var2.b)); \ + lf_resd=(lf_var1d << lf_var2b) | \ + (cf << (lf_var2b-1)) | \ + (lf_var1d >> (33-lf_var2b)); \ } \ - SETFLAGBIT(CF,((flags.var1.d >> (32-flags.var2.b)) & 1)); \ - SETFLAGBIT(OF,(flags.var1.d ^ flags.result.d) & 0x80000000); \ - save(op1,flags.result.d); \ + SETFLAGBIT(CF,((lf_var1d >> (32-lf_var2b)) & 1)); \ + save(op1,lf_resd); \ } #define RCRB(op1,op2,load,save) \ if (op2%9) { \ - LoadZF;LoadSF;LoadAF; \ - Bit8u cf=get_CF(); \ - flags.var1.b=load(op1); \ - flags.var2.b=op2%9; \ - flags.type=t_RCRb; \ - flags.result.b=(flags.var1.b >> flags.var2.b) | \ - (cf << (8-flags.var2.b)) | \ - (flags.var1.b << (9-flags.var2.b)); \ - save(op1,flags.result.b); \ + Bit8u cf=(Bit8u)FillFlags()&0x1; \ + lf_var1b=load(op1); \ + lf_var2b=op2%9; \ + lflags.type=t_RCRb; \ + lf_resb=(lf_var1b >> lf_var2b) | \ + (cf << (8-lf_var2b)) | \ + (lf_var1b << (9-lf_var2b)); \ + save(op1,lf_resb); \ } #define RCRW(op1,op2,load,save) \ if (op2%17) { \ - LoadZF;LoadSF;LoadAF; \ - Bit16u cf=get_CF(); \ - flags.var1.w=load(op1); \ - flags.var2.b=op2%17; \ - flags.type=t_RCRw; \ - flags.result.w=(flags.var1.w >> flags.var2.b) | \ - (cf << (16-flags.var2.b)) | \ - (flags.var1.w << (17-flags.var2.b)); \ - save(op1,flags.result.w); \ + Bit16u cf=(Bit16u)FillFlags()&0x1; \ + lf_var1w=load(op1); \ + lf_var2b=op2%17; \ + lflags.type=t_RCRw; \ + lf_resw=(lf_var1w >> lf_var2b) | \ + (cf << (16-lf_var2b)) | \ + (lf_var1w << (17-lf_var2b)); \ + save(op1,lf_resw); \ } #define RCRD(op1,op2,load,save) \ if (op2) { \ - LoadZF;LoadSF;LoadAF; \ - Bit32u cf=get_CF(); \ - flags.var1.d=load(op1); \ - flags.var2.b=op2; \ - flags.type=t_RCRd; \ - if (flags.var2.b==1) { \ - flags.result.d=flags.var1.d >> 1 | cf << 31; \ + Bit32u cf=(Bit32u)FillFlags()&0x1; \ + lf_var1d=load(op1); \ + lf_var2b=op2; \ + lflags.type=t_RCRd; \ + if (lf_var2b==1) { \ + lf_resd=lf_var1d >> 1 | cf << 31; \ } else { \ - flags.result.d=(flags.var1.d >> flags.var2.b) | \ - (cf << (32-flags.var2.b)) | \ - (flags.var1.d << (33-flags.var2.b)); \ + lf_resd=(lf_var1d >> lf_var2b) | \ + (cf << (32-lf_var2b)) | \ + (lf_var1d << (33-lf_var2b)); \ } \ - save(op1,flags.result.d); \ + save(op1,lf_resd); \ } #define SHLB(op1,op2,load,save) \ if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b << flags.var2.b; \ - save(op1,flags.result.b); \ - flags.type=t_SHLb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b << lf_var2b; \ + save(op1,lf_resb); \ + lflags.type=t_SHLb; #define SHLW(op1,op2,load,save) \ if (!op2) break; \ - flags.var1.w=load(op1);flags.var2.b=op2 ; \ - flags.result.w=flags.var1.w << flags.var2.b; \ - save(op1,flags.result.w); \ - flags.type=t_SHLw; + lf_var1w=load(op1);lf_var2b=op2 ; \ + lf_resw=lf_var1w << lf_var2b; \ + save(op1,lf_resw); \ + lflags.type=t_SHLw; #define SHLD(op1,op2,load,save) \ if (!op2) break; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ - flags.result.d=flags.var1.d << flags.var2.b; \ - save(op1,flags.result.d); \ - flags.type=t_SHLd; + lf_var1d=load(op1);lf_var2b=op2; \ + lf_resd=lf_var1d << lf_var2b; \ + save(op1,lf_resd); \ + lflags.type=t_SHLd; #define SHRB(op1,op2,load,save) \ if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - flags.result.b=flags.var1.b >> flags.var2.b; \ - save(op1,flags.result.b); \ - flags.type=t_SHRb; + lf_var1b=load(op1);lf_var2b=op2; \ + lf_resb=lf_var1b >> lf_var2b; \ + save(op1,lf_resb); \ + lflags.type=t_SHRb; #define SHRW(op1,op2,load,save) \ if (!op2) break; \ - flags.var1.w=load(op1);flags.var2.b=op2; \ - flags.result.w=flags.var1.w >> flags.var2.b; \ - save(op1,flags.result.w); \ - flags.type=t_SHRw; + lf_var1w=load(op1);lf_var2b=op2; \ + lf_resw=lf_var1w >> lf_var2b; \ + save(op1,lf_resw); \ + lflags.type=t_SHRw; #define SHRD(op1,op2,load,save) \ if (!op2) break; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ - flags.result.d=flags.var1.d >> flags.var2.b; \ - save(op1,flags.result.d); \ - flags.type=t_SHRd; + lf_var1d=load(op1);lf_var2b=op2; \ + lf_resd=lf_var1d >> lf_var2b; \ + save(op1,lf_resd); \ + lflags.type=t_SHRd; #define SARB(op1,op2,load,save) \ if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ - if (flags.var2.b>8) flags.var2.b=8; \ - if (flags.var1.b & 0x80) { \ - flags.result.b=(flags.var1.b >> flags.var2.b)| \ - (0xff << (8 - flags.var2.b)); \ + lf_var1b=load(op1);lf_var2b=op2; \ + if (lf_var2b>8) lf_var2b=8; \ + if (lf_var1b & 0x80) { \ + lf_resb=(lf_var1b >> lf_var2b)| \ + (0xff << (8 - lf_var2b)); \ } else { \ - flags.result.b=flags.var1.b >> flags.var2.b; \ + lf_resb=lf_var1b >> lf_var2b; \ } \ - save(op1,flags.result.b); \ - flags.type=t_SARb; + save(op1,lf_resb); \ + lflags.type=t_SARb; #define SARW(op1,op2,load,save) \ if (!op2) break; \ - flags.var1.w=load(op1);flags.var2.b=op2; \ - if (flags.var2.b>16) flags.var2.b=16; \ - if (flags.var1.w & 0x8000) { \ - flags.result.w=(flags.var1.w >> flags.var2.b)| \ - (0xffff << (16 - flags.var2.b)); \ + lf_var1w=load(op1);lf_var2b=op2; \ + if (lf_var2b>16) lf_var2b=16; \ + if (lf_var1w & 0x8000) { \ + lf_resw=(lf_var1w >> lf_var2b)| \ + (0xffff << (16 - lf_var2b)); \ } else { \ - flags.result.w=flags.var1.w >> flags.var2.b; \ + lf_resw=lf_var1w >> lf_var2b; \ } \ - save(op1,flags.result.w); \ - flags.type=t_SARw; + save(op1,lf_resw); \ + lflags.type=t_SARw; #define SARD(op1,op2,load,save) \ if (!op2) break; \ - flags.var2.b=op2;flags.var1.d=load(op1); \ - if (flags.var1.d & 0x80000000) { \ - flags.result.d=(flags.var1.d >> flags.var2.b)| \ - (0xffffffff << (32 - flags.var2.b)); \ + lf_var2b=op2;lf_var1d=load(op1); \ + if (lf_var1d & 0x80000000) { \ + lf_resd=(lf_var1d >> lf_var2b)| \ + (0xffffffff << (32 - lf_var2b)); \ } else { \ - flags.result.d=flags.var1.d >> flags.var2.b; \ + lf_resd=lf_var1d >> lf_var2b; \ } \ - save(op1,flags.result.d); \ - flags.type=t_SARd; + save(op1,lf_resd); \ + lflags.type=t_SARd; @@ -474,7 +471,7 @@ } \ SETFLAGBIT(SF,(reg_al&0x80)); \ SETFLAGBIT(ZF,(reg_al==0)); \ - flags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; #define DAS() \ @@ -490,7 +487,7 @@ } else { \ SETFLAGBIT(CF,false); \ } \ - flags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; #define AAA() \ @@ -505,7 +502,7 @@ SETFLAGBIT(CF,false); \ } \ reg_al &= 0x0F; \ - flags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; #define AAS() \ if (((reg_al & 0x0f)>9) || get_AF()) { \ @@ -519,14 +516,14 @@ SETFLAGBIT(CF,false); \ } \ reg_al &= 0x0F; \ - flags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; #define AAM(op1) \ { \ Bit8u BLAH=op1; \ reg_ah=reg_al / BLAH; \ reg_al=reg_al % BLAH; \ - flags.type=t_UNKNOWN; \ + lflags.type=t_UNKNOWN; \ SETFLAGBIT(SF,(reg_al & 0x80)); \ SETFLAGBIT(ZF,(reg_al == 0)); \ SETFLAGBIT(PF,parity_lookup[reg_al]); \ @@ -547,11 +544,11 @@ SETFLAGBIT(SF,reg_al >= 0x80); \ SETFLAGBIT(ZF,reg_al == 0); \ SETFLAGBIT(PF,parity_lookup[reg_al]); \ - flags.type=t_UNKNOWN; \ + lflags.type=t_UNKNOWN; \ } #define MULB(op1,load,save) \ - flags.type=t_MUL; \ + lflags.type=t_MUL; \ reg_ax=reg_al*load(op1); \ if (reg_ax & 0xff00) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ @@ -564,7 +561,7 @@ Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \ reg_ax=(Bit16u)(tempu); \ reg_dx=(Bit16u)(tempu >> 16); \ - flags.type=t_MUL; \ + lflags.type=t_MUL; \ if (reg_dx) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ } else { \ @@ -577,7 +574,7 @@ Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \ reg_eax=(Bit32u)(tempu); \ reg_edx=(Bit32u)(tempu >> 32); \ - flags.type=t_MUL; \ + lflags.type=t_MUL; \ if (reg_edx) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ } else { \ @@ -654,7 +651,7 @@ #define IMULB(op1,load,save) \ { \ - flags.type=t_MUL; \ + lflags.type=t_MUL; \ reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \ if ((reg_ax & 0xff80)==0xff80 || \ (reg_ax & 0xff80)==0x0000) { \ @@ -670,7 +667,7 @@ Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \ reg_ax=(Bit16s)(temps); \ reg_dx=(Bit16s)(temps >> 16); \ - flags.type=t_MUL; \ + lflags.type=t_MUL; \ if (((temps & 0xffff8000)==0xffff8000 || \ (temps & 0xffff8000)==0x0000)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -685,7 +682,7 @@ ((Bit64s)((Bit32s)(load(op1)))); \ reg_eax=(Bit32u)(temps); \ reg_edx=(Bit32u)(temps >> 32); \ - flags.type=t_MUL; \ + lflags.type=t_MUL; \ if ((reg_edx==0xffffffff) && \ (reg_eax & 0x80000000) ) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -702,7 +699,7 @@ Bits res; \ res=((Bit16s)op2) * ((Bit16s)op3); \ save(op1,res & 0xffff); \ - flags.type=t_MUL; \ + lflags.type=t_MUL; \ if ((res> -32768) && (res<32767)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ } else { \ @@ -714,7 +711,7 @@ { \ Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \ save(op1,(Bit32s)res); \ - flags.type=t_MUL; \ + lflags.type=t_MUL; \ if ((res>-((Bit64s)(2147483647)+1)) && \ (res<(Bit64s)2147483647)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -827,39 +824,39 @@ #define DSHLW(op1,op2,op3,load,save) \ Bit8u val=op3 & 0x1F; \ if (!val) break; \ - flags.var2.b=val;flags.var1.d=(load(op1)<<16)|op2; \ - Bit32u tempd=flags.var1.d << flags.var2.b; \ - if (flags.var2.b>16) tempd |= (op2 << (flags.var2.b - 16)); \ - flags.result.w=(Bit16u)(tempd >> 16); \ - save(op1,flags.result.w); \ - flags.type=t_DSHLw; + lf_var2b=val;lf_var1d=(load(op1)<<16)|op2; \ + Bit32u tempd=lf_var1d << lf_var2b; \ + if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16)); \ + lf_resw=(Bit16u)(tempd >> 16); \ + save(op1,lf_resw); \ + lflags.type=t_DSHLw; #define DSHLD(op1,op2,op3,load,save) \ Bit8u val=op3 & 0x1F; \ if (!val) break; \ - flags.var2.b=val;flags.var1.d=load(op1); \ - flags.result.d=(flags.var1.d << flags.var2.b) | (op2 >> (32-flags.var2.b)); \ - save(op1,flags.result.d); \ - flags.type=t_DSHLd; + lf_var2b=val;lf_var1d=load(op1); \ + lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b)); \ + save(op1,lf_resd); \ + lflags.type=t_DSHLd; /* double-precision shift right has high bits in second argument */ #define DSHRW(op1,op2,op3,load,save) \ Bit8u val=op3 & 0x1F; \ if (!val) break; \ - flags.var2.b=val;flags.var1.d=(op2<<16)|load(op1); \ - Bit32u tempd=flags.var1.d >> flags.var2.b; \ - if (flags.var2.b>16) tempd |= (op2 << (32-flags.var2.b )); \ - flags.result.w=(Bit16u)(tempd); \ - save(op1,flags.result.w); \ - flags.type=t_DSHRw; + lf_var2b=val;lf_var1d=(op2<<16)|load(op1); \ + Bit32u tempd=lf_var1d >> lf_var2b; \ + if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b )); \ + lf_resw=(Bit16u)(tempd); \ + save(op1,lf_resw); \ + lflags.type=t_DSHRw; #define DSHRD(op1,op2,op3,load,save) \ Bit8u val=op3 & 0x1F; \ if (!val) break; \ - flags.var2.b=val;flags.var1.d=load(op1); \ - flags.result.d=(flags.var1.d >> flags.var2.b) | (op2 << (32-flags.var2.b)); \ - save(op1,flags.result.d); \ - flags.type=t_DSHRd; + lf_var2b=val;lf_var1d=load(op1); \ + lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b)); \ + save(op1,lf_resd); \ + lflags.type=t_DSHRd; #define BSWAP(op1) \ op1 = (op1>>24)|((op1>>8)&0xFF00)|((op1<<8)&0xFF0000)|((op1<<24)&0xFF000000); diff --git a/src/cpu/lazyflags.h b/src/cpu/lazyflags.h index 2ab6ca1..897b481 100644 --- a/src/cpu/lazyflags.h +++ b/src/cpu/lazyflags.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#if !defined __LAZYFLAGS_H +#define __LAZYFLAG_H + //Flag Handling Bitu get_CF(void); Bitu get_AF(void); @@ -24,25 +27,51 @@ Bitu get_SF(void); Bitu get_OF(void); Bitu get_PF(void); -void FillFlags(void); +Bitu FillFlags(void); + +#include "regs.h" + +struct LazyFlags { + GenReg32 var1,var2,res; + Bitu type; + Bitu prev_type; + Bitu oldcf; +}; + +extern LazyFlags lfags; + +#define lf_var1b lflags.var1.byte[BL_INDEX] +#define lf_var2b lflags.var2.byte[BL_INDEX] +#define lf_resb lflags.res.byte[BL_INDEX] + +#define lf_var1w lflags.var1.word[W_INDEX] +#define lf_var2w lflags.var2.word[W_INDEX] +#define lf_resw lflags.res.word[W_INDEX] + +#define lf_var1d lflags.var1.dword[DW_INDEX] +#define lf_var2d lflags.var2.dword[DW_INDEX] +#define lf_resd lflags.res.dword[DW_INDEX] + + +extern LazyFlags lflags; #define SETFLAGSb(FLAGB) \ { \ SETFLAGBIT(OF,get_OF()); \ - flags.type=t_UNKNOWN; \ - CPU_SetFlags((flags.word&0xffffff00)|((FLAGB) & 0xff)); \ + lflags.type=t_UNKNOWN; \ + CPU_SetFlags(FLAGB,FMASK_NORMAL & 0xff); \ } #define SETFLAGSw(FLAGW) \ { \ - flags.type=t_UNKNOWN; \ + lflags.type=t_UNKNOWN; \ CPU_SetFlagsw(FLAGW); \ } #define SETFLAGSd(FLAGD) \ { \ - flags.type=t_UNKNOWN; \ - CPU_SetFlags(FLAGD); \ + lflags.type=t_UNKNOWN; \ + CPU_SetFlagsd(FLAGD); \ } #define LoadCF SETFLAGBIT(CF,get_CF()); @@ -51,6 +80,23 @@ void FillFlags(void); #define LoadOF SETFLAGBIT(OF,get_OF()); #define LoadAF SETFLAGBIT(AF,get_AF()); +#define TFLG_O (get_OF()) +#define TFLG_NO (!get_OF()) +#define TFLG_B (get_CF()) +#define TFLG_NB (!get_CF()) +#define TFLG_Z (get_ZF()) +#define TFLG_NZ (!get_ZF()) +#define TFLG_BE (get_CF() || get_ZF()) +#define TFLG_NBE (!get_CF() && !get_ZF()) +#define TFLG_S (get_SF()) +#define TFLG_NS (!get_SF()) +#define TFLG_P (get_PF()) +#define TFLG_NP (!get_PF()) +#define TFLG_L ((get_SF()!=0) != (get_OF()!=0)) +#define TFLG_NL ((get_SF()!=0) == (get_OF()!=0)) +#define TFLG_LE (get_ZF() || ((get_SF()!=0) != (get_OF()!=0))) +#define TFLG_NLE (!get_ZF() && ((get_SF()!=0) == (get_OF()!=0))) + //Types of Flag changing instructions enum { t_UNKNOWN=0, @@ -73,8 +119,7 @@ enum { t_RCLb,t_RCLw,t_RCLd, t_RCRb,t_RCRw,t_RCRd, t_NEGb,t_NEGw,t_NEGd, - t_CF,t_ZF, - + t_DSHLw,t_DSHLd, t_DSHRw,t_DSHRd, t_MUL,t_DIV, @@ -82,3 +127,4 @@ enum { t_LASTFLAG }; +#endif diff --git a/src/cpu/modrm.cpp b/src/cpu/modrm.cpp index 56a695e..b9bad89 100644 --- a/src/cpu/modrm.cpp +++ b/src/cpu/modrm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/cpu/modrm.h b/src/cpu/modrm.h index 42a34d0..181d529 100644 --- a/src/cpu/modrm.h +++ b/src/cpu/modrm.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/cpu/paging.cpp b/src/cpu/paging.cpp index 8f6c68b..4db18bd 100644 --- a/src/cpu/paging.cpp +++ b/src/cpu/paging.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,169 +23,267 @@ #include "dosbox.h" #include "mem.h" #include "paging.h" -#include "../hardware/vga.h" - +#include "regs.h" +#include "lazyflags.h" +#include "cpu.h" +#include "debug.h" #define LINK_TOTAL (64*1024) -static PageLink link_list[LINK_TOTAL]; -struct PagingBlock paging; +PagingBlock paging; +static Bit32u mapfirstmb[LINK_START]; -class PageDirChange : public PageChange { -public: - PageDirChange(PageDirectory * mydir) { dir=mydir;} - void Changed(PageLink * link,Bitu start,Bitu end) { - start>>=2;end>>=2; - for (;start<=end;start++) { - dir->InvalidateTable(start); - } - } -private: - PageDirectory * dir; +Bitu PageHandler::readb(PhysPt addr) { + E_Exit("No byte handler for read from %d",addr); + return 0; +} +Bitu PageHandler::readw(PhysPt addr) { + return + (readb(addr+0) << 0) | + (readb(addr+1) << 8); +} +Bitu PageHandler::readd(PhysPt addr) { + return + (readb(addr+0) << 0) | + (readb(addr+1) << 8) | + (readb(addr+2) << 16) | + (readb(addr+3) << 24); +} + +void PageHandler::writeb(PhysPt addr,Bitu val) { + E_Exit("No byte handler for write to %d",addr); }; -class PageTableChange : public PageChange { -public: - PageTableChange(PageDirectory * mydir) { dir=mydir;} - void Changed(PageLink * link,Bitu start,Bitu end) { - start>>=2;end>>=2; - for (;start<=end;start++) { - dir->InvalidateLink(link->data.table,start); - } - } -private: - PageDirectory * dir; +void PageHandler::writew(PhysPt addr,Bitu val) { + writeb(addr+0,(Bit8u) (val >> 0)); + writeb(addr+1,(Bit8u) (val >> 8)); +} +void PageHandler::writed(PhysPt addr,Bitu val) { + writeb(addr+0,(Bit8u) (val >> 0)); + writeb(addr+1,(Bit8u) (val >> 8)); + writeb(addr+2,(Bit8u) (val >> 16)); + writeb(addr+3,(Bit8u) (val >> 24)); }; +HostPt PageHandler::GetHostPt(Bitu phys_page) { + return 0; +} -PageDirectory::PageDirectory() { - entry_init.data.dir=this; - entry_init.type=ENTRY_INIT; - link_init.read=0; - link_init.write=0; - link_init.entry=&entry_init; - table_change = new PageTableChange(this); - dir_change = new PageDirChange(this); +struct PF_Entry { + Bitu cs; + Bitu eip; + Bitu page_addr; +}; + +#define PF_QUEUESIZE 16 +struct { + Bitu used; + PF_Entry entries[PF_QUEUESIZE]; +} pf_queue; + +static Bits PageFaultCore(void) { + CPU_CycleLeft+=CPU_Cycles; + CPU_Cycles=1; + Bitu ret=CPU_Core_Full_Run(); + CPU_CycleLeft+=CPU_Cycles; + if (ret<0) E_Exit("Got a dosbox close machine in pagefault core?"); + if (ret) + return ret; + if (!pf_queue.used) E_Exit("PF Core without PF"); + PF_Entry * entry=&pf_queue.entries[pf_queue.used-1]; + X86PageEntry pentry; + pentry.load=MEM_PhysReadD(entry->page_addr); + if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip) + return -1; + return 0; } -PageDirectory::~PageDirectory() { - delete table_change; - delete dir_change; +#if C_DEBUG +Bitu DEBUG_EnableDebugger(void); +#endif + +void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu type) { + /* Save the state of the cpu cores */ + LazyFlags old_lflags; + memcpy(&old_lflags,&lflags,sizeof(LazyFlags)); + CPU_Decoder * old_cpudecoder; + old_cpudecoder=cpudecoder; + cpudecoder=&PageFaultCore; + paging.cr2=lin_addr; + PF_Entry * entry=&pf_queue.entries[pf_queue.used++]; + LOG(LOG_PAGING,LOG_NORMAL)("PageFault at %X type %d queue %d",lin_addr,type,pf_queue.used); + entry->cs=SegValue(cs); + entry->eip=reg_eip; + entry->page_addr=page_addr; + //Caused by a write by default? + CPU_Exception(14,0x2 ); +#if C_DEBUG +// DEBUG_EnableDebugger(); +#endif + DOSBOX_RunMachine(); + pf_queue.used--; + LOG(LOG_PAGING,LOG_NORMAL)("Left PageFault for %x queue %d",lin_addr,pf_queue.used); + memcpy(&lflags,&old_lflags,sizeof(LazyFlags)); + cpudecoder=old_cpudecoder; } -void PageDirectory::ClearDirectory(void) { - Bitu i; - for (i=0;i<1024*1024;i++) links[i]=&link_init; - for (i=0;i<1024;i++) { - tables[i]=0; + + +void MEM_PhysWriteD(Bitu addr,Bit32u val); +class InitPageHandler : public PageHandler { +public: + InitPageHandler() {flags=PFLAG_INIT|PFLAG_NOCODE;} + Bitu readb(PhysPt addr) { + InitPage(addr); + return mem_readb(addr); } -} -void PageDirectory::SetBase(PhysPt page) { - base_page=page; - ClearDirectory(); - /* Setup handler for PageDirectory changes */ - link_dir=MEM_LinkPage(base_page,0); - if (!link_dir) E_Exit("PAGING:Directory setup on illegal address"); - link_dir->data.dir=this; - link_dir->change=dir_change; - MEM_CheckLinks(link_dir->entry); -} -void PageDirectory::LinkPage(Bitu lin_page,Bitu phys_page) { - if (links[lin_page] != &link_init) MEM_UnlinkPage(links[lin_page]); - PageLink * link=MEM_LinkPage(phys_page,lin_page*4096); - if (link) links[lin_page]=link; - else links[lin_page]=&link_init; -} - -bool PageDirectory::InitPage(Bitu lin_address) { - Bitu lin_page=lin_address >> 12; - Bitu table=lin_page >> 10; - Bitu index=lin_page & 0x3ff; - /* Check if there already is table linked */ - if (!tables[table]) { - X86PageEntry table_entry; - table_entry.load=phys_page_readd(base_page,0); - if (!table_entry.block.p) { - LOG(LOG_PAGING,LOG_ERROR)("NP TABLE"); - return false; - } - PageLink * link=MEM_LinkPage(table_entry.block.base,table_entry.block.base); - if (!link) return false; - link->data.table=table; - link->change=table_change; - MEM_CheckLinks(link->entry); - tables[table]=link; + Bitu readw(PhysPt addr) { + InitPage(addr); + return mem_readw(addr); } - X86PageEntry entry; - entry.load=phys_page_readd(tables[table]->lin_base,index); - if (!entry.block.p) { - LOG(LOG_PAGING,LOG_ERROR)("NP PAGE"); - return false; + Bitu readd(PhysPt addr) { + InitPage(addr); + return mem_readd(addr); } - PageLink * link=MEM_LinkPage(entry.block.base,lin_page*4096); - if (!link) return false; - links[lin_page]=link; - return true; -} - - -bool PageDirectory::InitPageLinear(Bitu lin_address) { - Bitu phys_page=lin_address >> 12; - PageLink * link=MEM_LinkPage(phys_page,phys_page*4096); - if (link) { - /* Set the page entry in our table */ - links[phys_page]=link; - return true; + void writeb(PhysPt addr,Bitu val) { + InitPage(addr); + mem_writeb(addr,val); } - return false; -} - - -void PageDirectory::InvalidateTable(Bitu table) { - if (tables[table]) { - MEM_UnlinkPage(tables[table]); - tables[table]=0; - for (Bitu i=(table*1024);i<(table+1)*1024;i++) { - if (links[i]!=&link_init) { - MEM_UnlinkPage(links[i]); - links[i]=&link_init; + void writew(PhysPt addr,Bitu val) { + InitPage(addr); + mem_writew(addr,val); + } + void writed(PhysPt addr,Bitu val) { + InitPage(addr); + mem_writed(addr,val); + } + void InitPage(Bitu lin_addr) { + Bitu lin_page=lin_addr >> 12; + Bitu phys_page; + if (paging.enabled) { + Bitu d_index=lin_page >> 10; + Bitu t_index=lin_page & 0x3ff; + Bitu table_addr=(paging.base.page<<12)+d_index*4; + X86PageEntry table; + table.load=MEM_PhysReadD(table_addr); + if (!table.block.p) { + LOG(LOG_PAGING,LOG_ERROR)("NP Table"); + PAGING_PageFault(lin_addr,table_addr,0); + table.load=MEM_PhysReadD(table_addr); + if (!table.block.p) + E_Exit("Pagefault didn't correct table"); } + table.block.a=table.block.d=1; //Set access/Dirty + MEM_PhysWriteD(table_addr,table.load); + X86PageEntry entry; + Bitu entry_addr=(table.block.base<<12)+t_index*4; + entry.load=MEM_PhysReadD(entry_addr); + if (!entry.block.p) { + LOG(LOG_PAGING,LOG_ERROR)("NP Page"); + PAGING_PageFault(lin_addr,entry_addr,0); + entry.load=MEM_PhysReadD(entry_addr); + if (!entry.block.p) + E_Exit("Pagefault didn't correct page"); + } + entry.block.a=entry.block.d=1; //Set access/Dirty + MEM_PhysWriteD(entry_addr,entry.load); + phys_page=entry.block.base; + } else { + if (lin_page> 10; + Bitu t_index=page & 0x3ff; + X86PageEntry table; + table.load=MEM_PhysReadD((paging.base.page<<12)+d_index*4); + if (!table.block.p) return false; + X86PageEntry entry; + entry.load=MEM_PhysReadD((table.block.base<<12)+t_index*4); + if (!entry.block.p) return false; + page=entry.block.base; + } else { + if (page0;paging.links.used--) { + Bitu page=*entries++; + paging.tlb.read[page]=0; + paging.tlb.write[page]=0; + paging.tlb.handler[page]=&init_page_handler; + } + paging.links.used=0; +} + +void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) { + for (;pages>0;pages--) { + paging.tlb.read[lin_page]=0; + paging.tlb.write[lin_page]=0; + paging.tlb.handler[lin_page]=&init_page_handler; + } +} + +void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) { + PageHandler * handler=MEM_GetPageHandler(phys_page); + Bitu lin_base=lin_page << 12; + + if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE) + E_Exit("Illegal page"); + HostPt host_mem=handler->GetHostPt(phys_page); + paging.tlb.phys_page[lin_page]=phys_page; + if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=host_mem-lin_base; + else paging.tlb.read[lin_page]=0; + if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=host_mem-lin_base; + else paging.tlb.write[lin_page]=0; + if (paging.links.used>=PAGING_LINKS) E_Exit("Not enough paging links"); + paging.links.entries[paging.links.used++]=lin_page; + paging.tlb.handler[lin_page]=handler; +} + +void PAGING_MapPage(Bitu lin_page,Bitu phys_page) { + if (lin_page> 12; - LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,base_page); + + paging.base.page=cr3 >> 12; + paging.base.addr=cr3 & ~4095; + LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page); if (paging.enabled) { - /* Check if we already have this one cached */ - PageDirectory * dir=paging.cache; - while (dir) { - if (dir->base_page==base_page) { - paging.dir=dir; - return; - } - dir=dir->next; - } - /* Couldn't find cached directory, make a new one */ - dir=new PageDirectory(); - dir->next=paging.cache; - paging.cache=dir; - dir->SetBase(base_page); - paging.dir=dir; + PAGING_ClearTLB(); } } @@ -195,59 +293,25 @@ void PAGING_Enable(bool enabled) { paging.enabled=enabled; if (!enabled) { LOG(LOG_PAGING,LOG_NORMAL)("Disabled"); - paging.dir=MEM_DefaultDirectory(); } else { LOG(LOG_PAGING,LOG_NORMAL)("Enabled"); -#if !(C_DEBUG) - E_Exit("CPU Paging features aren't supported"); -#endif PAGING_SetDirBase(paging.cr3); } + PAGING_ClearTLB(); } bool PAGING_Enabled(void) { return paging.enabled; } - -void PAGING_FreePageLink(PageLink * link) { - MEM_UnlinkPage(link); - PAGING_AddFreePageLink(link); -} - -void PAGING_LinkPage(PageDirectory * dir,Bitu lin_page,Bitu phys_page) { - PageLink * link=MEM_LinkPage(phys_page,lin_page*4096); - /* Only replace if we can */ - if (link) { - PAGING_FreePageLink(dir->links[lin_page]); - dir->links[lin_page]=link; - } -} - -void PAGING_AddFreePageLink(PageLink * link) { - link->read=0; - link->write=0; - link->change=0; - link->next=paging.free_link; - link->entry=0; - paging.free_link=link; -} - -PageLink * PAGING_GetFreePageLink(void) { - PageLink * ret; - if (paging.free_link) ret=paging.free_link; - else E_Exit("PAGING:Ran out of PageEntries"); - paging.free_link=ret->next; - ret->next=0; - return ret; -} - void PAGING_Init(Section * sec) { - Bitu i; - /* Setup the free pages tables for fast page allocation */ - paging.cache=0; - paging.free_link=0; - for (i=0;i0) { -#if C_DEBUG - cycle_count++; -#if C_HEAVY_DEBUG - LEAVECORE; - if (DEBUG_HeavyIsBreakpoint()) return debugCallback; -#endif -#endif - core_16.ip_start=core_16.ip_lookup; - core_16.prefixes=0; - lookupEATable=EAPrefixTable[0]; - #include "core_16/main.h" - CPU_Cycles--; - } -decode_end: - LEAVECORE; - return CBRET_NONE; -} - -static Bits CPU_Real_16_Slow_Decode_Trap(void) { - - Bits oldCycles = CPU_Cycles; - CPU_Cycles = 1; - Bits ret=CPU_Real_16_Slow_Decode(); - -// LOG_DEBUG("TRAP: Trap Flag executed"); - Interrupt(1); - - CPU_Cycles = oldCycles-1; - cpudecoder = &CPU_Real_16_Slow_Decode; - - return ret; -} - - -void CPU_Real_16_Slow_Start(bool big) { - if (big) E_Exit("Core 16 only runs 16-bit code"); - cpudecoder=&CPU_Real_16_Slow_Decode; - EAPrefixTable[2]=&GetEA_32_n; - EAPrefixTable[3]=&GetEA_32_s; - EAPrefixTable[0]=&GetEA_16_n; - EAPrefixTable[1]=&GetEA_16_s; - -}; diff --git a/src/debug/Makefile.in b/src/debug/Makefile.in index dadd5a1..6be3c1d 100644 --- a/src/debug/Makefile.in +++ b/src/debug/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -318,7 +318,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -338,7 +338,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -363,7 +362,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index ba74632..b39a7ad 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: debug.cpp,v 1.52 2004/01/27 14:52:28 qbix79 Exp $ */ + #include "programs.h" #include @@ -34,8 +36,9 @@ #include "mixer.h" #include "debug_inc.h" #include "timer.h" +#include "paging.h" #include "../ints/xms.h" -#include "../shell/shell_inc.h" +#include "shell.h" #ifdef WIN32 void WIN32_Console(); @@ -51,8 +54,12 @@ static void DrawCode(void); static bool DEBUG_Log_Loop(int count); static void DEBUG_RaiseTimerIrq(void); char* AnalyzeInstruction(char* inst, bool saveSelector); -void SaveMemory(Bit16u seg, Bit16u ofs1, Bit32s num); +void SaveMemory(Bitu seg, Bitu ofs1, Bit32s num); Bit32u GetHexValue(char* str, char*& hex); +void LogGDT(void); +void LogLDT(void); +void LogIDT(void); +void OutputVecTable(char* filename); class DEBUG; @@ -60,6 +67,13 @@ DEBUG* pDebugcom = 0; bool exitLoop = false; bool logHeavy = false; +// Heavy Debugging Vars for logging +#if C_HEAVY_DEBUG +static FILE* cpuLogFile = 0; +static bool cpuLog = false; +static int cpuLogCounter = 0; +#endif + static struct { Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip; } oldregs; @@ -110,13 +124,18 @@ Bit32u PhysMakeProt(Bit16u selector, Bit32u offset) Bit32u GetAddress(Bit16u seg, Bit32u offset) { - if (cpu.pmode) return PhysMakeProt(seg,offset); + if (seg==SegValue(cs)) return SegPhys(cs)+offset; + if (cpu.pmode) { + Descriptor desc; + if (cpu.gdt.GetDescriptor(seg,desc)) return PhysMakeProt(seg,offset); + } return (seg<<4)+offset; -}; +} + bool GetDescriptorInfo(char* selname, char* out1, char* out2) { - Bit16u sel; + Bitu sel; Descriptor desc; if (strstr(selname,"cs") || strstr(selname,"CS")) sel = SegValue(cs); else @@ -174,7 +193,7 @@ std::list CDebugVar::varList; bool skipFirstInstruction = false; -enum EBreakpoint { BKPNT_UNKNOWN, BKPNT_PHYSICAL, BKPNT_INTERRUPT, BKPNT_MEMORY }; +enum EBreakpoint { BKPNT_UNKNOWN, BKPNT_PHYSICAL, BKPNT_INTERRUPT, BKPNT_MEMORY, BKPNT_MEMORY_PROT, BKPNT_MEMORY_LINEAR }; #define BPINT_ALL 0x100 @@ -341,19 +360,29 @@ bool CBreakpoint::CheckBreakpoint(Bitu seg, Bitu off) } #if C_HEAVY_DEBUG // Memory breakpoint support - else if ((bp->GetType()==BKPNT_MEMORY) && bp->IsActive()) { + else if (bp->IsActive()) { + if ((bp->GetType()==BKPNT_MEMORY) || (bp->GetType()==BKPNT_MEMORY_PROT) || (bp->GetType()==BKPNT_MEMORY_LINEAR)) { + // Watch Protected Mode Memoryonly in pmode + if (bp->GetType()==BKPNT_MEMORY_PROT) { + // Check if pmode is active + if (!cpu.pmode) return false; + // Check if descriptor is valid + Descriptor desc; + if (!cpu.gdt.GetDescriptor(bp->GetSegment(),desc)) return false; + if (desc.GetLimit()==0) return false; + } - Bitu address = GetAddress(bp->GetSegment(),bp->GetOffset()); -// Bitu address = bp->GetSegment()*16 + bp->GetOffset(); - Bit8u value = mem_readb(address); - if (bp->GetValue() != value) { - // Yup, memory value changed - - DEBUG_ShowMsg("DEBUG: Memory breakpoint: %04X:%04X - %02X -> %02X",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value); - bp->SetValue(value); - return true; - }; - + Bitu address; + if (bp->GetType()==BKPNT_MEMORY_LINEAR) address = bp->GetOffset(); + else address = GetAddress(bp->GetSegment(),bp->GetOffset()); + Bit8u value = mem_readb(address); + if (bp->GetValue() != value) { + // Yup, memory value changed + DEBUG_ShowMsg("DEBUG: Memory breakpoint %s: %04X:%04X - %02X -> %02X",(bp->GetType()==BKPNT_MEMORY_PROT)?"(Prot)":"",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value); + bp->SetValue(value); + return true; + }; + } }; #endif }; @@ -574,7 +603,9 @@ static void DrawData(void) { mvwprintw (dbg.win_data,1+y,0,"%04X:%04X ",dataSeg,add); for (int x=0; x<16; x++) { address = GetAddress(dataSeg,add); - if (address<8*1024*1024) ch = mem_readb(address); else ch = 0; + if (!(paging.tlb.handler[address >> 12]->flags & PFLAG_INIT)) { + ch = mem_readb(address); + } else ch = 0; mvwprintw (dbg.win_data,1+y,11+3*x,"%02X",ch); if (ch<32) ch='.'; mvwprintw (dbg.win_data,1+y,60+x,"%c",ch); @@ -606,31 +637,35 @@ static void DrawRegisters(void) { /*Individual flags*/ - SetColor((flags.word ^ oldflags)&FLAG_CF); + SetColor((reg_flags ^ oldflags)&FLAG_CF); mvwprintw (dbg.win_reg,1,53,"%01X",GETFLAG(CF) ? 1:0); - SetColor((flags.word ^ oldflags)&FLAG_ZF); + SetColor((reg_flags ^ oldflags)&FLAG_ZF); mvwprintw (dbg.win_reg,1,56,"%01X",GETFLAG(ZF) ? 1:0); - SetColor((flags.word ^ oldflags)&FLAG_SF); + SetColor((reg_flags ^ oldflags)&FLAG_SF); mvwprintw (dbg.win_reg,1,59,"%01X",GETFLAG(SF) ? 1:0); - SetColor((flags.word ^ oldflags)&FLAG_OF); + SetColor((reg_flags ^ oldflags)&FLAG_OF); mvwprintw (dbg.win_reg,1,62,"%01X",GETFLAG(OF) ? 1:0); - SetColor((flags.word ^ oldflags)&FLAG_AF); + SetColor((reg_flags ^ oldflags)&FLAG_AF); mvwprintw (dbg.win_reg,1,65,"%01X",GETFLAG(AF) ? 1:0); - SetColor((flags.word ^ oldflags)&FLAG_PF); + SetColor((reg_flags ^ oldflags)&FLAG_PF); mvwprintw (dbg.win_reg,1,68,"%01X",GETFLAG(PF) ? 1:0); - SetColor((flags.word ^ oldflags)&FLAG_DF); + SetColor((reg_flags ^ oldflags)&FLAG_DF); mvwprintw (dbg.win_reg,1,71,"%01X",GETFLAG(DF) ? 1:0); - SetColor((flags.word ^ oldflags)&FLAG_IF); + SetColor((reg_flags ^ oldflags)&FLAG_IF); mvwprintw (dbg.win_reg,1,74,"%01X",GETFLAG(IF) ? 1:0); - SetColor((flags.word ^ oldflags)&FLAG_TF); + SetColor((reg_flags ^ oldflags)&FLAG_TF); mvwprintw (dbg.win_reg,1,77,"%01X",GETFLAG(TF) ? 1:0); - oldflags=flags.word; + oldflags=reg_flags; - if (cpu.pmode) mvwprintw(dbg.win_reg,0,76,"Prot"); - else mvwprintw(dbg.win_reg,0,76,"Real"); + if (cpu.pmode) { + if (reg_flags & FLAG_VM) mvwprintw(dbg.win_reg,0,76,"VM86"); + else if (cpu.code.big) mvwprintw(dbg.win_reg,0,76,"Pr32"); + else mvwprintw(dbg.win_reg,0,76,"Pr16"); + } else + mvwprintw(dbg.win_reg,0,76,"Real"); // Selector info, if available if ((cpu.pmode) && curSelectorName[0]) { @@ -788,21 +823,21 @@ bool ChangeRegister(char* str) if (strstr(hex,"EBP")==hex) { hex+=3; reg_ebp = GetHexValue(hex,hex); } else if (strstr(hex,"ESP")==hex) { hex+=3; reg_esp = GetHexValue(hex,hex); } else if (strstr(hex,"EIP")==hex) { hex+=3; reg_eip = GetHexValue(hex,hex); } else - if (strstr(hex,"AX")==hex) { hex+=2; reg_ax = GetHexValue(hex,hex); } else - if (strstr(hex,"BX")==hex) { hex+=2; reg_bx = GetHexValue(hex,hex); } else - if (strstr(hex,"CX")==hex) { hex+=2; reg_cx = GetHexValue(hex,hex); } else - if (strstr(hex,"DX")==hex) { hex+=2; reg_dx = GetHexValue(hex,hex); } else - if (strstr(hex,"SI")==hex) { hex+=2; reg_si = GetHexValue(hex,hex); } else - if (strstr(hex,"DI")==hex) { hex+=2; reg_di = GetHexValue(hex,hex); } else - if (strstr(hex,"BP")==hex) { hex+=2; reg_bp = GetHexValue(hex,hex); } else - if (strstr(hex,"SP")==hex) { hex+=2; reg_sp = GetHexValue(hex,hex); } else - if (strstr(hex,"IP")==hex) { hex+=2; reg_ip = GetHexValue(hex,hex); } else - if (strstr(hex,"CS")==hex) { hex+=2; SegSet16(cs,GetHexValue(hex,hex)); } else - if (strstr(hex,"DS")==hex) { hex+=2; SegSet16(ds,GetHexValue(hex,hex)); } else - if (strstr(hex,"ES")==hex) { hex+=2; SegSet16(es,GetHexValue(hex,hex)); } else - if (strstr(hex,"FS")==hex) { hex+=2; SegSet16(fs,GetHexValue(hex,hex)); } else - if (strstr(hex,"GS")==hex) { hex+=2; SegSet16(gs,GetHexValue(hex,hex)); } else - if (strstr(hex,"SS")==hex) { hex+=2; SegSet16(ss,GetHexValue(hex,hex)); } else + if (strstr(hex,"AX")==hex) { hex+=2; reg_ax = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"BX")==hex) { hex+=2; reg_bx = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"CX")==hex) { hex+=2; reg_cx = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"DX")==hex) { hex+=2; reg_dx = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"SI")==hex) { hex+=2; reg_si = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"DI")==hex) { hex+=2; reg_di = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"BP")==hex) { hex+=2; reg_bp = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"SP")==hex) { hex+=2; reg_sp = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"IP")==hex) { hex+=2; reg_ip = (Bit16u)GetHexValue(hex,hex); } else + if (strstr(hex,"CS")==hex) { hex+=2; SegSet16(cs,(Bit16u)GetHexValue(hex,hex)); } else + if (strstr(hex,"DS")==hex) { hex+=2; SegSet16(ds,(Bit16u)GetHexValue(hex,hex)); } else + if (strstr(hex,"ES")==hex) { hex+=2; SegSet16(es,(Bit16u)GetHexValue(hex,hex)); } else + if (strstr(hex,"FS")==hex) { hex+=2; SegSet16(fs,(Bit16u)GetHexValue(hex,hex)); } else + if (strstr(hex,"GS")==hex) { hex+=2; SegSet16(gs,(Bit16u)GetHexValue(hex,hex)); } else + if (strstr(hex,"SS")==hex) { hex+=2; SegSet16(ss,(Bit16u)GetHexValue(hex,hex)); } else if (strstr(hex,"AF")==hex) { hex+=2; SETFLAGBIT(AF,GetHexValue(hex,hex)); } else if (strstr(hex,"CF")==hex) { hex+=2; SETFLAGBIT(CF,GetHexValue(hex,hex)); } else if (strstr(hex,"DF")==hex) { hex+=2; SETFLAGBIT(PF,GetHexValue(hex,hex)); } else @@ -825,7 +860,7 @@ bool ParseCommand(char* str) found = strstr(str,"MEMDUMP "); if (found) { // Insert variable found+=8; - Bit16u seg = GetHexValue(found,found); found++; + Bit16u seg = (Bit16u)GetHexValue(found,found); found++; Bit32u ofs = GetHexValue(found,found); found++; Bit32u num = GetHexValue(found,found); found++; SaveMemory(seg,ofs,num); @@ -835,8 +870,8 @@ bool ParseCommand(char* str) found = strstr(str,"IV "); if (found) { // Insert variable found+=3; - Bit16u seg = GetHexValue(found,found); found++; - Bit32u ofs = GetHexValue(found,found); found++; + Bit16u seg = (Bit16u)GetHexValue(found,found); found++; + Bit32u ofs = (Bit16u)GetHexValue(found,found); found++; char name[16]; for (int i=0; i<16; i++) { if ((found[i]!=' ') && (found[i]!=0)) name[i] = found[i]; @@ -880,7 +915,7 @@ bool ParseCommand(char* str) found = strstr(str,"BP "); if (found) { // Add new breakpoint found+=3; - Bit16u seg = GetHexValue(found,found);found++; // skip ":" + Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" Bit32u ofs = GetHexValue(found,found); CBreakpoint::AddBreakpoint(seg,ofs,false); DEBUG_ShowMsg("DEBUG: Set breakpoint at %04X:%04X",seg,ofs); @@ -890,18 +925,37 @@ bool ParseCommand(char* str) found = strstr(str,"BPM "); if (found) { // Add new breakpoint found+=3; - Bit16u seg = GetHexValue(found,found);found++; // skip ":" + Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" Bit32u ofs = GetHexValue(found,found); CBreakpoint::AddMemBreakpoint(seg,ofs); DEBUG_ShowMsg("DEBUG: Set memory breakpoint at %04X:%04X",seg,ofs); return true; } + found = strstr(str,"BPPM "); + if (found) { // Add new breakpoint + found+=4; + Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" + Bit32u ofs = GetHexValue(found,found); + CBreakpoint* bp = CBreakpoint::AddMemBreakpoint(seg,ofs); + if (bp) bp->SetType(BKPNT_MEMORY_PROT); + DEBUG_ShowMsg("DEBUG: Set prot-mode memory breakpoint at %04X:%08X",seg,ofs); + return true; + } + found = strstr(str,"BPLM "); + if (found) { // Add new breakpoint + found+=4; + Bitu ofs = GetHexValue(found,found); + CBreakpoint* bp = CBreakpoint::AddMemBreakpoint(0,ofs); + if (bp) bp->SetType(BKPNT_MEMORY_LINEAR); + DEBUG_ShowMsg("DEBUG: Set linear memory breakpoint at %08X",ofs); + return true; + } #endif found = strstr(str,"BPINT"); if (found) { // Add Interrupt Breakpoint found+=5; - Bit8u intNr = GetHexValue(found,found); found++; - Bit8u valAH = GetHexValue(found,found); + Bit8u intNr = (Bit8u)GetHexValue(found,found); found++; + Bit8u valAH = (Bit8u)GetHexValue(found,found); if ((valAH==0x00) && (*found=='*')) { CBreakpoint::AddIntBreakpoint(intNr,BPINT_ALL,false); DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X",intNr); @@ -922,7 +976,7 @@ bool ParseCommand(char* str) found = strstr(str,"BPDEL"); if (found) { // Delete Breakpoints found+=5; - Bit8u bpNr = GetHexValue(found,found); + Bit8u bpNr = (Bit8u)GetHexValue(found,found); if ((bpNr==0x00) && (*found=='*')) { // Delete all CBreakpoint::DeleteAll(); DEBUG_ShowMsg("DEBUG: Breakpoints deleted."); @@ -935,7 +989,7 @@ bool ParseCommand(char* str) found = strstr(str,"C "); if (found==(char*)str) { // Set code overview found++; - Bit16u codeSeg = GetHexValue(found,found); found++; + Bit16u codeSeg = (Bit16u)GetHexValue(found,found); found++; Bit32u codeOfs = GetHexValue(found,found); DEBUG_ShowMsg("DEBUG: Set code overview to %04X:%04X",codeSeg,codeOfs); codeViewData.useCS = codeSeg; @@ -945,19 +999,32 @@ bool ParseCommand(char* str) found = strstr(str,"D "); if (found==(char*)str) { // Set data overview found++; - dataSeg = GetHexValue(found,found); found++; + dataSeg = (Bit16u)GetHexValue(found,found); found++; dataOfs = GetHexValue(found,found); DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs); return true; } +#if C_HEAVY_DEBUG found = strstr(str,"LOG "); if (found) { // Create Cpu log file found+=4; DEBUG_ShowMsg("DEBUG: Starting log"); - DEBUG_Log_Loop(GetHexValue(found,found)); - DEBUG_ShowMsg("DEBUG: Logfile LOGCPU.TXT created."); +// DEBUG_Log_Loop(GetHexValue(found,found)); + cpuLogFile = fopen("LOGCPU.TXT","wt"); + if (!cpuLogFile) { + DEBUG_ShowMsg("DEBUG: Logfile couldnt be created."); + return false; + } + cpuLog = true; + cpuLogCounter = GetHexValue(found,found); + + debugging=false; + CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); + ignoreAddressOnce = SegPhys(cs)+reg_eip; + DOSBOX_SetNormalLoop(); return true; } +#endif found = strstr(str,"SR "); if (found) { // Set register value found+=2; @@ -968,13 +1035,13 @@ bool ParseCommand(char* str) found = strstr(str,"SM "); if (found) { // Set memory with following values found+=3; - Bit16u seg = GetHexValue(found,found); found++; + Bit16u seg = (Bit16u)GetHexValue(found,found); found++; Bit32u ofs = GetHexValue(found,found); found++; Bit16u count = 0; while (*found) { while (*found==' ') found++; if (*found) { - Bit8u value = GetHexValue(found,found); found++; + Bit8u value = (Bit8u)GetHexValue(found,found); found++; mem_writeb(GetAddress(seg,ofs+count),value); count++; } @@ -985,23 +1052,23 @@ bool ParseCommand(char* str) found = strstr(str,"INTT "); if (found) { // Create Cpu log file found+=4; - Bit8u intNr = GetHexValue(found,found); + Bit8u intNr = (Bit8u)GetHexValue(found,found); DEBUG_ShowMsg("DEBUG: Tracing INT %02X",intNr); - Interrupt(intNr); + CPU_HW_Interrupt(intNr); SetCodeWinStart(); return true; } found = strstr(str,"INT "); if (found) { // Create Cpu log file found+=4; - Bit8u intNr = GetHexValue(found,found); + Bit8u intNr = (Bit8u)GetHexValue(found,found); DEBUG_ShowMsg("DEBUG: Starting INT %02X",intNr); CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip, true); CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip-1,true); debugging=false; DrawCode(); DOSBOX_SetNormalLoop(); - Interrupt(intNr); + CPU_HW_Interrupt(intNr); return true; } found = strstr(str,"SELINFO "); @@ -1015,7 +1082,46 @@ bool ParseCommand(char* str) DEBUG_ShowMsg("%s",out2); }; -/* found = strstr(str,"EXCEPTION "); + found = strstr(str,"GDT"); + if (found) { + LogGDT(); + } + + found = strstr(str,"LDT"); + if (found) { + LogLDT(); + } + + found = strstr(str,"IDT"); + if (found) { + LogIDT(); + } + + found = strstr(str,"INTVEC "); + if (found) + { + found += 7; + while (found[0]==' ') found++; + if (found[0] != 0) + OutputVecTable(found); + } + + found = strstr(str,"INTHAND "); + if (found) + { + found += 8; + while (found[0]==' ') found++; + if (found[0] != 0) + { + Bit8u intNr = (Bit8u)GetHexValue(found,found); + DEBUG_ShowMsg("DEBUG: Set code overview to interrupt handler %X",intNr); + codeViewData.useCS = mem_readw(intNr*4+2); + codeViewData.useEIP = mem_readw(intNr*4); + return true; + } + } + + /* found = strstr(str,"EXCEPTION "); if (found) { found += 9; Bit8u num = GetHexValue(found,found); @@ -1051,6 +1157,8 @@ bool ParseCommand(char* str) wprintw(dbg.win_out,"BPINT [intNr] [ah] - Set interrupt breakpoint with ah\n"); #if C_HEAVY_DEBUG wprintw(dbg.win_out,"BPM [segment]:[offset] - Set memory breakpoint (memory change)\n"); + wprintw(dbg.win_out,"BPPM [selector]:[offset]- Set pmode-memory breakpoint (memory change)\n"); + wprintw(dbg.win_out,"BPLM [linear address] - Set linear memory breakpoint (memory change)\n"); #endif wprintw(dbg.win_out,"BPLIST - List breakpoints\n"); wprintw(dbg.win_out,"BPDEL [bpNr] / * - Delete breakpoint nr / all\n"); @@ -1069,6 +1177,10 @@ bool ParseCommand(char* str) wprintw(dbg.win_out,"MEMDUMP [seg]:[off] [len] - Write memory to file memdump.txt\n"); wprintw(dbg.win_out,"SELINFO [segName] - Show selector info\n"); + + wprintw(dbg.win_out,"INTVEC [filename] - Writes interrupt vector table to file\n"); + wprintw(dbg.win_out,"INTHAND [intNum] - Set code view to interrupt handler\n"); + wprintw(dbg.win_out,"H - Help\n"); wrefresh(dbg.win_out); @@ -1097,7 +1209,7 @@ char* AnalyzeInstruction(char* inst, bool saveSelector) prefix[0] = tolower(*segpos); prefix[1] = tolower(*(segpos+1)); prefix[2] = 0; - seg = GetHexValue(segpos,segpos); + seg = (Bit16u)GetHexValue(segpos,segpos); } else { if (strstr(pos,"SP") || strstr(pos,"BP")) { seg = SegValue(ss); @@ -1121,25 +1233,27 @@ char* AnalyzeInstruction(char* inst, bool saveSelector) pos++; }; Bit32u address = GetAddress(seg,adr); -// if (address<(XMS_GetSize()+1)*1024*1024) { - static char outmask[] = "%s:[%04X]=%02X"; - - if (cpu.pmode) outmask[6] = '8'; - switch (DasmLastOperandSize()) { - case 8 : { Bit8u val = mem_readb(address); - outmask[12] = '2'; - sprintf(result,outmask,prefix,adr,val); - } break; - case 16: { Bit16u val = mem_readw(address); - outmask[12] = '4'; - sprintf(result,outmask,prefix,adr,val); - } break; - case 32: { Bit32u val = mem_readd(address); - outmask[12] = '8'; - sprintf(result,outmask,prefix,adr,val); - } break; + if (!(paging.tlb.handler[address >> 12]->flags & PFLAG_INIT)) { + static char outmask[] = "%s:[%04X]=%02X"; + + if (cpu.pmode) outmask[6] = '8'; + switch (DasmLastOperandSize()) { + case 8 : { Bit8u val = mem_readb(address); + outmask[12] = '2'; + sprintf(result,outmask,prefix,adr,val); + } break; + case 16: { Bit16u val = mem_readw(address); + outmask[12] = '4'; + sprintf(result,outmask,prefix,adr,val); + } break; + case 32: { Bit32u val = mem_readd(address); + outmask[12] = '8'; + sprintf(result,outmask,prefix,adr,val); + } break; + } + } else { + sprintf(result,"[illegal]"); } -// } // Variable found ? CDebugVar* var = CDebugVar::FindVar(address); if (var) { @@ -1159,6 +1273,16 @@ char* AnalyzeInstruction(char* inst, bool saveSelector) strcpy(curSelectorName,prefix); }; }; + // If it is a callback add additional info + pos = strstr(inst,"callback"); + if (pos) { + pos += 9; + Bitu nr = GetHexValue(pos,pos); + const char* descr = CALLBACK_GetDescription(nr); + if (descr) { + strcat(inst," ("); strcat(inst,descr); strcat(inst,")"); + } + }; return result; }; @@ -1189,7 +1313,7 @@ Bit32u DEBUG_CheckKeys(void) { }; int key=getch(); - Bit32u ret=0; + Bits ret=0; if (key>0) { switch (toupper(key)) { case '1': @@ -1274,7 +1398,6 @@ Bit32u DEBUG_CheckKeys(void) { skipFirstInstruction = true; // for heavy debugger CPU_Cycles = 1; Bitu ret=(*cpudecoder)(); - if (ret>0) ret=(*CallBack_Handlers[ret])(); SetCodeWinStart(); CBreakpoint::ignoreOnce = 0; } @@ -1284,11 +1407,20 @@ Bit32u DEBUG_CheckKeys(void) { skipFirstInstruction = true; // for heavy debugger CPU_Cycles = 1; ret = (*cpudecoder)(); - if (ret>0) ret=(*CallBack_Handlers[ret])(); SetCodeWinStart(); CBreakpoint::ignoreOnce = 0; break; } + if (ret<0) return ret; + if (ret>0){ + ret=(*CallBack_Handlers[ret])(); + if (ret) { + exitLoop=true; + CPU_Cycles=CPU_CycleLeft=0; + return ret; + } + } + ret=0; DEBUG_DrawScreen(); } return ret; @@ -1324,10 +1456,64 @@ void DEBUG_DrawScreen(void) { DrawCode(); DrawRegisters(); } + static void DEBUG_RaiseTimerIrq(void) { PIC_ActivateIRQ(0); } +void LogGDT(void) +{ + char out1[512]; + Descriptor desc; + Bitu length = cpu.gdt.GetLimit(); + PhysPt address = cpu.gdt.GetBase(); + PhysPt max = address + length; + Bitu i = 0; + LOG(LOG_MISC,LOG_ERROR)("GDT Base:%08X Limit:%08X",address,length); + while (address0) { + static char buffer[4096]; + LogInstruction(SegValue(cs),reg_eip,buffer); + fprintf(cpuLogFile,"%s",buffer); + cpuLogCounter--; + } + if (cpuLogCounter<=0) { + fclose(cpuLogFile); + DEBUG_ShowMsg("DEBUG: cpu log LOGCPU.TXT created"); + cpuLog = false; + DEBUG_EnableDebugger(); + return true; + } + } // LogInstruction if (logHeavy) DEBUG_HeavyLogInstruction(); @@ -1670,10 +1887,7 @@ bool DEBUG_HeavyIsBreakpoint(void) return false; } PhysPt where = SegPhys(cs)+reg_eip; - if (CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) { -// exitLoop = true; -// DEBUG_Enable(); return true; } return false; diff --git a/src/debug/debug_disasm.cpp b/src/debug/debug_disasm.cpp index 11aa326..f0c0460 100644 --- a/src/debug/debug_disasm.cpp +++ b/src/debug/debug_disasm.cpp @@ -220,8 +220,7 @@ static char *op386map1[256] = { "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb", "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb", /* 8 */ -/* "%g0 %Eb,%Ib", "%g0 %Ev,%Iv", "%g0 %Ev,%Ib", "%g0 %Ev,%Ib", */ - "%g0 %Eb,%Ib", "%g0 %Ev,%Iv", "%g0 %Ev,%Ix", "%g0 %Ev,%Ix", + "%g0 %Eb,%Ib", "%g0 %Ev,%Iv", "%g0 %Eb,%Ib", "%g0 %Ev,%Ix", "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv", "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev", "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev", diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index 840233c..deb4537 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -216,7 +216,7 @@ void DBGUI_StartUp(void) { nodelay(dbg.win_main,true); keypad(dbg.win_main,true); #ifndef WIN32 - resizeterm(50,80); + resizeterm(50,81); touchwin(dbg.win_main); old_cursor_state = curs_set(0); #endif diff --git a/src/debug/debug_inc.h b/src/debug/debug_inc.h index e3d5834..41524ab 100644 --- a/src/debug/debug_inc.h +++ b/src/debug/debug_inc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/debug/debug_win32.cpp b/src/debug/debug_win32.cpp index cfed35e..2da75fe 100644 --- a/src/debug/debug_win32.cpp +++ b/src/debug/debug_win32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/debug/disasm_tables.h b/src/debug/disasm_tables.h index 0ed79e8..9a080f2 100644 --- a/src/debug/disasm_tables.h +++ b/src/debug/disasm_tables.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/dos/Makefile.am b/src/dos/Makefile.am index 821a71b..7bd9b5a 100644 --- a/src/dos/Makefile.am +++ b/src/dos/Makefile.am @@ -1,9 +1,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libdos.a -EXTRA_DIST = Ntddcdrm.h Ntddscsi.h Ntddstor.h scsidefs.h wnaspi32.h +EXTRA_DIST = scsidefs.h wnaspi32.h libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \ dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \ drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp \ dev_con.h dos_mscdex.cpp \ - cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp + cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp diff --git a/src/dos/Makefile.in b/src/dos/Makefile.in index 4b63d39..c1d0fb9 100644 --- a/src/dos/Makefile.in +++ b/src/dos/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -132,12 +132,12 @@ target_vendor = @target_vendor@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libdos.a -EXTRA_DIST = Ntddcdrm.h Ntddscsi.h Ntddstor.h scsidefs.h wnaspi32.h +EXTRA_DIST = scsidefs.h wnaspi32.h libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \ dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \ drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp \ dev_con.h dos_mscdex.cpp \ - cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp + cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp subdir = src/dos ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -154,7 +154,8 @@ am_libdos_a_OBJECTS = dos.$(OBJEXT) dos_devices.$(OBJEXT) \ dos_programs.$(OBJEXT) dos_tables.$(OBJEXT) drives.$(OBJEXT) \ drive_virtual.$(OBJEXT) drive_local.$(OBJEXT) \ drive_cache.$(OBJEXT) dos_mscdex.$(OBJEXT) cdrom.$(OBJEXT) \ - cdrom_ioctl_win32.$(OBJEXT) cdrom_aspi_win32.$(OBJEXT) + cdrom_ioctl_win32.$(OBJEXT) cdrom_aspi_win32.$(OBJEXT) \ + cdrom_ioctl_linux.$(OBJEXT) libdos_a_OBJECTS = $(am_libdos_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) @@ -162,6 +163,7 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/cdrom.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cdrom_aspi_win32.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_linux.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_win32.Po ./$(DEPDIR)/dos.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_classes.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_devices.Po \ @@ -213,6 +215,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_aspi_win32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_linux.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_win32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_classes.Po@am__quote@ @@ -354,7 +357,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -374,7 +377,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -399,7 +401,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/dos/Ntddcdrm.h b/src/dos/Ntddcdrm.h deleted file mode 100644 index 6590a4e..0000000 --- a/src/dos/Ntddcdrm.h +++ /dev/null @@ -1,548 +0,0 @@ -/*++ BUILD Version: 0001 // Increment this if a change has global effects - -Copyright (c) Microsoft Corporation. All rights reserved. - -Module Name: - - ntddcdrm.h - -Abstract: - - This module contains structures and definitions - associated with CDROM IOCTls. - -Author: - - Mike Glass - -Revision History: - ---*/ - -// begin_winioctl - -#ifndef _NTDDCDRM_ -#define _NTDDCDRM_ - -#if _MSC_VER >= 1200 -#pragma warning(push) -#endif - -#if _MSC_VER > 1000 -#pragma once -#endif - -// -// remove some level 4 warnings for this header file: -#pragma warning(disable:4200) // array[0] -#pragma warning(disable:4201) // nameless struct/unions -#pragma warning(disable:4214) // bit fields other than int - -#ifdef __cplusplus -extern "C" { -#endif - -// -// NtDeviceIoControlFile IoControlCode values for this device. -// -// Warning: Remember that the low two bits of the code specify how the -// buffers are passed to the driver! -// - -#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM - -#define IOCTL_CDROM_UNLOAD_DRIVER CTL_CODE(IOCTL_CDROM_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS) - -// -// CDROM Audio Device Control Functions -// - -#define IOCTL_CDROM_READ_TOC CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_SEEK_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_STOP_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_PAUSE_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_RESUME_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_GET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_PLAY_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_SET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_READ_Q_CHANNEL CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_GET_CONTROL CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_GET_LAST_SESSION CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) -#define IOCTL_CDROM_DISK_TYPE CTL_CODE(IOCTL_CDROM_BASE, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_CDROM_BASE, 0x0014, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_CDROM_READ_TOC_EX CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_GET_CONFIGURATION CTL_CODE(IOCTL_CDROM_BASE, 0x0016, METHOD_BUFFERED, FILE_READ_ACCESS) - -// end_winioctl - -// -// The following device control codes are common for all class drivers. The -// functions codes defined here must match all of the other class drivers. -// -// Warning: these codes will be replaced in the future with the IOCTL_STORAGE -// codes included below -// - -#define IOCTL_CDROM_CHECK_VERIFY CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_EJECT_MEDIA CTL_CODE(IOCTL_CDROM_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_LOAD_MEDIA CTL_CODE(IOCTL_CDROM_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_RESERVE CTL_CODE(IOCTL_CDROM_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_RELEASE CTL_CODE(IOCTL_CDROM_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_FIND_NEW_DEVICES CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) - -// -// The following file contains the IOCTL_STORAGE class ioctl definitions -// - -#include "ntddstor.h" - -// begin_winioctl - -// -// The following device control code is for the SIMBAD simulated bad -// sector facility. See SIMBAD.H in this directory for related structures. -// - -#define IOCTL_CDROM_SIMBAD CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS) - -// -// Maximum CD Rom size -// - -#define MAXIMUM_NUMBER_TRACKS 100 -#define MAXIMUM_CDROM_SIZE 804 -#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2 // two bytes min transferred - -// -// READ_TOC_EX structure -// -typedef struct _CDROM_READ_TOC_EX { - UCHAR Format : 4; - UCHAR Reserved1 : 3; // future expansion - UCHAR Msf : 1; - UCHAR SessionTrack; - UCHAR Reserved2; // future expansion - UCHAR Reserved3; // future expansion -} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX; - -#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00 -#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01 -#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02 -#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03 -#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04 -#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05 - -// -// CD ROM Table OF Contents (TOC) -// Format 0 - Get table of contents -// - -typedef struct _TRACK_DATA { - UCHAR Reserved; - UCHAR Control : 4; - UCHAR Adr : 4; - UCHAR TrackNumber; - UCHAR Reserved1; - UCHAR Address[4]; -} TRACK_DATA, *PTRACK_DATA; - -typedef struct _CDROM_TOC { - - // - // Header - // - - UCHAR Length[2]; // add two bytes for this field - UCHAR FirstTrack; - UCHAR LastTrack; - - // - // Track data - // - - TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; -} CDROM_TOC, *PCDROM_TOC; - -#define CDROM_TOC_SIZE sizeof(CDROM_TOC) - -// -// CD ROM Table OF Contents -// Format 1 - Session Information -// - -typedef struct _CDROM_TOC_SESSION_DATA { - - // - // Header - // - - UCHAR Length[2]; // add two bytes for this field - UCHAR FirstCompleteSession; - UCHAR LastCompleteSession; - - // - // One track, representing the first track - // of the last finished session - // - - TRACK_DATA TrackData[1]; - -} CDROM_TOC_SESSION_DATA, *PCDROM_TOC_SESSION_DATA; - - -// -// CD ROM Table OF Contents -// Format 2 - Full TOC -// - -typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK { - UCHAR SessionNumber; - UCHAR Control : 4; - UCHAR Adr : 4; - UCHAR Reserved1; - UCHAR Point; - UCHAR MsfExtra[3]; - UCHAR Zero; - UCHAR Msf[3]; -} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK; - -typedef struct _CDROM_TOC_FULL_TOC_DATA { - - // - // Header - // - - UCHAR Length[2]; // add two bytes for this field - UCHAR FirstCompleteSession; - UCHAR LastCompleteSession; - - // - // one to N descriptors included - // - - CDROM_TOC_FULL_TOC_DATA_BLOCK Descriptors[0]; - -} CDROM_TOC_FULL_TOC_DATA, *PCDROM_TOC_FULL_TOC_DATA; - -// -// CD ROM Table OF Contents -// Format 3 - Program Memory Area -// -typedef struct _CDROM_TOC_PMA_DATA { - - // - // Header - // - - UCHAR Length[2]; // add two bytes for this field - UCHAR Reserved1; - UCHAR Reserved2; - - // - // one to N descriptors included - // - - CDROM_TOC_FULL_TOC_DATA_BLOCK Descriptors[0]; - -} CDROM_TOC_PMA_DATA, *PCDROM_TOC_PMA_DATA; - -// -// CD ROM Table OF Contents -// Format 4 - Absolute Time In Pregroove -// - -typedef struct _CDROM_TOC_ATIP_DATA_BLOCK { - - UCHAR CdrwReferenceSpeed : 3; - UCHAR Reserved3 : 1; - UCHAR WritePower : 3; - UCHAR True1 : 1; - UCHAR Reserved4 : 6; - UCHAR UnrestrictedUse : 1; - UCHAR Reserved5 : 1; - UCHAR A3Valid : 1; - UCHAR A2Valid : 1; - UCHAR A1Valid : 1; - UCHAR DiscSubType : 3; - UCHAR IsCdrw : 1; - UCHAR True2 : 1; - UCHAR Reserved7; - - UCHAR LeadInMsf[3]; - UCHAR Reserved8; - - UCHAR LeadOutMsf[3]; - UCHAR Reserved9; - - UCHAR A1Values[3]; - UCHAR Reserved10; - - UCHAR A2Values[3]; - UCHAR Reserved11; - - UCHAR A3Values[3]; - UCHAR Reserved12; - -} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK; - -typedef struct _CDROM_TOC_ATIP_DATA { - - // - // Header - // - - UCHAR Length[2]; // add two bytes for this field - UCHAR Reserved1; - UCHAR Reserved2; - - // - // zero? to N descriptors included. - // - - CDROM_TOC_ATIP_DATA_BLOCK Descriptors[0]; - -} CDROM_TOC_ATIP_DATA, *PCDROM_TOC_ATIP_DATA; - -// -// CD ROM Table OF Contents -// Format 5 - CD Text Info -// -typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK { - UCHAR PackType; - UCHAR TrackNumber : 7; - UCHAR ExtensionFlag : 1; // should be zero! - UCHAR SequenceNumber; - UCHAR CharacterPosition : 4; - UCHAR BlockNumber : 3; - UCHAR Unicode : 1; - union { - UCHAR Text[12]; - WCHAR WText[6]; - }; - UCHAR CRC[2]; -} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK; - -typedef struct _CDROM_TOC_CD_TEXT_DATA { - - // - // Header - // - - UCHAR Length[2]; // add two bytes for this field - UCHAR Reserved1; - UCHAR Reserved2; - - // - // the text info comes in discrete blocks of - // a heavily-overloaded structure - // - - CDROM_TOC_CD_TEXT_DATA_BLOCK Descriptors[0]; - -} CDROM_TOC_CD_TEXT_DATA, *PCDROM_TOC_CD_TEXT_DATA; - -// -// These are the types used for PackType field in CDROM_TOC_CD_TEXT_DATA_BLOCK -// and also for requesting specific info from IOCTL_CDROM_READ_CD_TEXT -// -#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80 -#define CDROM_CD_TEXT_PACK_PERFORMER 0x81 -#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82 -#define CDROM_CD_TEXT_PACK_COMPOSER 0x83 -#define CDROM_CD_TEXT_PACK_ARRANGER 0x84 -#define CDROM_CD_TEXT_PACK_MESSAGES 0x85 -#define CDROM_CD_TEXT_PACK_DISC_ID 0x86 -#define CDROM_CD_TEXT_PACK_GENRE 0x87 -#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88 -#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89 -// 0x8a - 0x8d are reserved.... -#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e -#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f - -// -// Play audio starting at MSF and ending at MSF -// - -typedef struct _CDROM_PLAY_AUDIO_MSF { - UCHAR StartingM; - UCHAR StartingS; - UCHAR StartingF; - UCHAR EndingM; - UCHAR EndingS; - UCHAR EndingF; -} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF; - -// -// Seek to MSF -// - -typedef struct _CDROM_SEEK_AUDIO_MSF { - UCHAR M; - UCHAR S; - UCHAR F; -} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; - - -// -// Flags for the disk type -// - -typedef struct _CDROM_DISK_DATA { - - ULONG DiskData; - -} CDROM_DISK_DATA, *PCDROM_DISK_DATA; - -#define CDROM_DISK_AUDIO_TRACK (0x00000001) -#define CDROM_DISK_DATA_TRACK (0x00000002) - -// -// CD ROM Data Mode Codes, used with IOCTL_CDROM_READ_Q_CHANNEL -// - -#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 -#define IOCTL_CDROM_CURRENT_POSITION 0x01 -#define IOCTL_CDROM_MEDIA_CATALOG 0x02 -#define IOCTL_CDROM_TRACK_ISRC 0x03 - -typedef struct _CDROM_SUB_Q_DATA_FORMAT { - UCHAR Format; - UCHAR Track; -} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; - - -// -// CD ROM Sub-Q Channel Data Format -// - -typedef struct _SUB_Q_HEADER { - UCHAR Reserved; - UCHAR AudioStatus; - UCHAR DataLength[2]; -} SUB_Q_HEADER, *PSUB_Q_HEADER; - -typedef struct _SUB_Q_CURRENT_POSITION { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Control : 4; - UCHAR ADR : 4; - UCHAR TrackNumber; - UCHAR IndexNumber; - UCHAR AbsoluteAddress[4]; - UCHAR TrackRelativeAddress[4]; -} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; - -typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Reserved[3]; - UCHAR Reserved1 : 7; - UCHAR Mcval : 1; - UCHAR MediaCatalog[15]; -} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; - -typedef struct _SUB_Q_TRACK_ISRC { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Reserved0; - UCHAR Track; - UCHAR Reserved1; - UCHAR Reserved2 : 7; - UCHAR Tcval : 1; - UCHAR TrackIsrc[15]; -} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; - -typedef union _SUB_Q_CHANNEL_DATA { - SUB_Q_CURRENT_POSITION CurrentPosition; - SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; - SUB_Q_TRACK_ISRC TrackIsrc; -} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; - -// -// Audio Status Codes -// - -#define AUDIO_STATUS_NOT_SUPPORTED 0x00 -#define AUDIO_STATUS_IN_PROGRESS 0x11 -#define AUDIO_STATUS_PAUSED 0x12 -#define AUDIO_STATUS_PLAY_COMPLETE 0x13 -#define AUDIO_STATUS_PLAY_ERROR 0x14 -#define AUDIO_STATUS_NO_STATUS 0x15 - -// -// ADR Sub-channel Q Field -// - -#define ADR_NO_MODE_INFORMATION 0x0 -#define ADR_ENCODES_CURRENT_POSITION 0x1 -#define ADR_ENCODES_MEDIA_CATALOG 0x2 -#define ADR_ENCODES_ISRC 0x3 - -// -// Sub-channel Q Control Bits -// - -#define AUDIO_WITH_PREEMPHASIS 0x1 -#define DIGITAL_COPY_PERMITTED 0x2 -#define AUDIO_DATA_TRACK 0x4 -#define TWO_FOUR_CHANNEL_AUDIO 0x8 - -// -// Get Audio control parameters -// - -typedef struct _CDROM_AUDIO_CONTROL { - UCHAR LbaFormat; - USHORT LogicalBlocksPerSecond; -} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL; - -// -// Volume control - Volume takes a value between 1 and 0xFF. -// SCSI-II CDROM audio suppports up to 4 audio ports with -// Independent volume control. -// - -typedef struct _VOLUME_CONTROL { - UCHAR PortVolume[4]; -} VOLUME_CONTROL, *PVOLUME_CONTROL; - -typedef enum _TRACK_MODE_TYPE { - YellowMode2, - XAForm2, - CDDA -} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; - -// -// Passed to cdrom to describe the raw read, ie. Mode 2, Form 2, CDDA... -// - -typedef struct __RAW_READ_INFO { - LARGE_INTEGER DiskOffset; - ULONG SectorCount; - TRACK_MODE_TYPE TrackMode; -} RAW_READ_INFO, *PRAW_READ_INFO; - -#ifdef __cplusplus -} -#endif - - -#if _MSC_VER >= 1200 -#pragma warning(pop) // un-sets any local warning changes -#else -#pragma warning(default:4200) // array[0] is not a warning for this file -#pragma warning(default:4201) // nameless struct/unions -#pragma warning(default:4214) // bit fields other than int -#endif - - -#endif // _NTDDCDRM_ - -// end_winioctl - - diff --git a/src/dos/Ntddscsi.h b/src/dos/Ntddscsi.h deleted file mode 100644 index 61f5b25..0000000 --- a/src/dos/Ntddscsi.h +++ /dev/null @@ -1,313 +0,0 @@ -/*++ BUILD Version: 0001 // Increment this if a change has global effects - -Copyright (c) Microsoft Corporation. All rights reserved. - -Module Name: - - ntddscsi.h - -Abstract: - - This is the include file that defines all constants and types for - accessing the SCSI port adapters. - -Author: - - Jeff Havens - -Revision History: - ---*/ - - -// -// Interface GUIDs -// -// need these GUIDs outside conditional includes so that user can -// #include in precompiled header -// #include in a single source file -// #include in that source file a second time to instantiate the GUIDs -// -#ifdef DEFINE_GUID -// -// Make sure FAR is defined... -// -#ifndef FAR -#ifdef _WIN32 -#define FAR -#else -#define FAR _far -#endif -#endif - -DEFINE_GUID(ScsiRawInterfaceGuid, 0x53f56309L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(WmiScsiAddressGuid, 0x53f5630fL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -#endif - -#ifndef _NTDDSCSIH_ -#define _NTDDSCSIH_ - -#ifdef __cplusplus -extern "C" { -#endif - -// -// Device Name - this string is the name of the device. It is the name -// that should be passed to NtOpenFile when accessing the device. -// -// Note: For devices that support multiple units, it should be suffixed -// with the Ascii representation of the unit number. -// - -#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER - -#define DD_SCSI_DEVICE_NAME "\\Device\\ScsiPort" - - -// -// NtDeviceIoControlFile IoControlCode values for this device. -// -// Warning: Remember that the low two bits of the code specify how the -// buffers are passed to the driver! -// - -#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) -#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) -#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) -#define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_GET_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0408, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_FREE_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0409, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -// -// Define the SCSI pass through structure. -// - -typedef struct _SCSI_PASS_THROUGH { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - ULONG DataBufferOffset; //ULONG_PTR DataBufferOffset; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -}SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; - -// -// Define the SCSI pass through direct structure. -// - -typedef struct _SCSI_PASS_THROUGH_DIRECT { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - PVOID DataBuffer; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -}SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; - - -// -// Define the SCSI pass through direct structure for Win64 (thunking). -// -#if defined(_WIN64) -typedef struct _SCSI_PASS_THROUGH32 { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - ULONG32 DataBufferOffset; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -}SCSI_PASS_THROUGH32, *PSCSI_PASS_THROUGH32; - -// -// Define the SCSI pass through direct structure. -// - -typedef struct _SCSI_PASS_THROUGH_DIRECT32 { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - VOID * POINTER_32 DataBuffer; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -}SCSI_PASS_THROUGH_DIRECT32, *PSCSI_PASS_THROUGH_DIRECT32; - -#endif - -// -// Define SCSI information. -// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. -// - -typedef struct _SCSI_BUS_DATA { - UCHAR NumberOfLogicalUnits; - UCHAR InitiatorBusId; - ULONG InquiryDataOffset; -}SCSI_BUS_DATA, *PSCSI_BUS_DATA; - -// -// Define SCSI adapter bus information structure.. -// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. -// - -typedef struct _SCSI_ADAPTER_BUS_INFO { - UCHAR NumberOfBuses; - SCSI_BUS_DATA BusData[1]; -} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; - -// -// Define SCSI adapter bus information. -// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. -// - -typedef struct _SCSI_INQUIRY_DATA { - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - BOOLEAN DeviceClaimed; - ULONG InquiryDataLength; - ULONG NextInquiryDataOffset; - UCHAR InquiryData[1]; -}SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; - -// -// Define header for I/O control SRB. -// - -typedef struct _SRB_IO_CONTROL { - ULONG HeaderLength; - UCHAR Signature[8]; - ULONG Timeout; - ULONG ControlCode; - ULONG ReturnCode; - ULONG Length; -} SRB_IO_CONTROL, *PSRB_IO_CONTROL; - -// -// SCSI port driver capabilities structure. -// - -typedef struct _IO_SCSI_CAPABILITIES { - - // - // Length of this structure - // - - ULONG Length; - - // - // Maximum transfer size in single SRB - // - - ULONG MaximumTransferLength; - - // - // Maximum number of physical pages per data buffer - // - - ULONG MaximumPhysicalPages; - - // - // Async calls from port to class - // - - ULONG SupportedAsynchronousEvents; - - // - // Alignment mask for data transfers. - // - - ULONG AlignmentMask; - - // - // Supports tagged queuing - // - - BOOLEAN TaggedQueuing; - - // - // Host adapter scans down for bios devices. - // - - BOOLEAN AdapterScansDown; - - // - // The host adapter uses programmed I/O. - // - - BOOLEAN AdapterUsesPio; - -} IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES; - -typedef struct _SCSI_ADDRESS { - ULONG Length; - UCHAR PortNumber; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; -}SCSI_ADDRESS, *PSCSI_ADDRESS; - -// -// Define structure for returning crash dump pointers. -// - -struct _ADAPTER_OBJECT; - -typedef struct _DUMP_POINTERS { - struct _ADAPTER_OBJECT *AdapterObject; - PVOID MappedRegisterBase; - PVOID DumpData; - PVOID CommonBufferVa; - LARGE_INTEGER CommonBufferPa; - ULONG CommonBufferSize; - BOOLEAN AllocateCommonBuffers; - BOOLEAN UseDiskDump; - UCHAR Spare1[2]; - PVOID DeviceObject; -} DUMP_POINTERS, *PDUMP_POINTERS; - -// -// Define values for pass-through DataIn field. -// - -#define SCSI_IOCTL_DATA_OUT 0 -#define SCSI_IOCTL_DATA_IN 1 -#define SCSI_IOCTL_DATA_UNSPECIFIED 2 - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/dos/Ntddstor.h b/src/dos/Ntddstor.h deleted file mode 100644 index 766f19c..0000000 --- a/src/dos/Ntddstor.h +++ /dev/null @@ -1,746 +0,0 @@ -/*++ BUILD Version: 0001 // Increment this if a change has global effects - -Copyright (c) Microsoft Corporation. All rights reserved. - -Module Name: - - ntddstor.h - -Abstract: - - This is the include file that defines all common constants and types - accessing the storage class drivers - -Author: - - Peter Wieland 19-Jun-1996 - -Revision History: - ---*/ - - -// -// Interface GUIDs -// -// need these GUIDs outside conditional includes so that user can -// #include in precompiled header -// #include in a single source file -// #include in that source file a second time to instantiate the GUIDs -// -#ifdef DEFINE_GUID -// -// Make sure FAR is defined... -// -#ifndef FAR -#ifdef _WIN32 -#define FAR -#else -#define FAR _far -#endif -#endif - -// begin_wioctlguids -DEFINE_GUID(GUID_DEVINTERFACE_DISK, 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_CDROM, 0x53f56308L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_PARTITION, 0x53f5630aL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_TAPE, 0x53f5630bL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_WRITEONCEDISK, 0x53f5630cL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_VOLUME, 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_MEDIUMCHANGER, 0x53f56310L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_FLOPPY, 0x53f56311L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_CDCHANGER, 0x53f56312L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT, 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); -// end_wioctlguids - -// begin_wioctlobsoleteguids -#define DiskClassGuid GUID_DEVINTERFACE_DISK -#define CdRomClassGuid GUID_DEVINTERFACE_CDROM -#define PartitionClassGuid GUID_DEVINTERFACE_PARTITION -#define TapeClassGuid GUID_DEVINTERFACE_TAPE -#define WriteOnceDiskClassGuid GUID_DEVINTERFACE_WRITEONCEDISK -#define VolumeClassGuid GUID_DEVINTERFACE_VOLUME -#define MediumChangerClassGuid GUID_DEVINTERFACE_MEDIUMCHANGER -#define FloppyClassGuid GUID_DEVINTERFACE_FLOPPY -#define CdChangerClassGuid GUID_DEVINTERFACE_CDCHANGER -#define StoragePortClassGuid GUID_DEVINTERFACE_STORAGEPORT -// end_wioctlobsoleteguids -#endif - -// begin_winioctl - -#ifndef _NTDDSTOR_H_ -#define _NTDDSTOR_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// -// IoControlCode values for storage devices -// - -#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE - -// -// The following device control codes are common for all class drivers. They -// should be used in place of the older IOCTL_DISK, IOCTL_CDROM and IOCTL_TAPE -// common codes -// - -#define IOCTL_STORAGE_CHECK_VERIFY CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_MEDIA_REMOVAL CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_EJECT_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_LOAD_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_LOAD_MEDIA2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_RESERVE CTL_CODE(IOCTL_STORAGE_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_RELEASE CTL_CODE(IOCTL_STORAGE_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_FIND_NEW_DEVICES CTL_CODE(IOCTL_STORAGE_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_STORAGE_EJECTION_CONTROL CTL_CODE(IOCTL_STORAGE_BASE, 0x0250, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_MCN_CONTROL CTL_CODE(IOCTL_STORAGE_BASE, 0x0251, METHOD_BUFFERED, FILE_ANY_ACCESS) - -#define IOCTL_STORAGE_GET_MEDIA_TYPES CTL_CODE(IOCTL_STORAGE_BASE, 0x0300, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_GET_MEDIA_TYPES_EX CTL_CODE(IOCTL_STORAGE_BASE, 0x0301, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_GET_HOTPLUG_INFO CTL_CODE(IOCTL_STORAGE_BASE, 0x0305, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_SET_HOTPLUG_INFO CTL_CODE(IOCTL_STORAGE_BASE, 0x0306, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -#define IOCTL_STORAGE_RESET_BUS CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_RESET_DEVICE CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_BREAK_RESERVATION CTL_CODE(IOCTL_STORAGE_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define IOCTL_STORAGE_GET_DEVICE_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0420, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_PREDICT_FAILURE CTL_CODE(IOCTL_STORAGE_BASE, 0x0440, METHOD_BUFFERED, FILE_ANY_ACCESS) - -// end_winioctl - - -#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) - - -// begin_winioctl - -// -// These ioctl codes are obsolete. They are defined here to avoid resuing them -// and to allow class drivers to respond to them more easily. -// - -#define OBSOLETE_IOCTL_STORAGE_RESET_BUS CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) -#define OBSOLETE_IOCTL_STORAGE_RESET_DEVICE CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - - -// -// IOCTL_STORAGE_GET_HOTPLUG_INFO -// - -typedef struct _STORAGE_HOTPLUG_INFO { - ULONG Size; // version - BOOLEAN MediaRemovable; // ie. zip, jaz, cdrom, mo, etc. vs hdd - BOOLEAN MediaHotplug; // ie. does the device succeed a lock even though its not lockable media? - BOOLEAN DeviceHotplug; // ie. 1394, USB, etc. - BOOLEAN WriteCacheEnableOverride; // This field should not be relied upon because it is no longer used -} STORAGE_HOTPLUG_INFO, *PSTORAGE_HOTPLUG_INFO; - -// -// IOCTL_STORAGE_GET_DEVICE_NUMBER -// -// input - none -// -// output - STORAGE_DEVICE_NUMBER structure -// The values in the STORAGE_DEVICE_NUMBER structure are guaranteed -// to remain unchanged until the system is rebooted. They are not -// guaranteed to be persistant across boots. -// - -typedef struct _STORAGE_DEVICE_NUMBER { - - // - // The FILE_DEVICE_XXX type for this device. - // - - DEVICE_TYPE DeviceType; - - // - // The number of this device - // - - ULONG DeviceNumber; - - // - // If the device is partitionable, the partition number of the device. - // Otherwise -1 - // - - ULONG PartitionNumber; -} STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER; - -// -// Define the structures for scsi resets -// - -typedef struct _STORAGE_BUS_RESET_REQUEST { - UCHAR PathId; -} STORAGE_BUS_RESET_REQUEST, *PSTORAGE_BUS_RESET_REQUEST; - -// -// IOCTL_STORAGE_MEDIA_REMOVAL disables the mechanism -// on a storage device that ejects media. This function -// may or may not be supported on storage devices that -// support removable media. -// -// TRUE means prevent media from being removed. -// FALSE means allow media removal. -// -#if defined (_MSC_VER) /* MS Visual C++ */ -typedef struct _PREVENT_MEDIA_REMOVAL { - BOOLEAN PreventMediaRemoval; -} PREVENT_MEDIA_REMOVAL, *PPREVENT_MEDIA_REMOVAL; -#endif - -// begin_ntminitape - - -typedef struct _TAPE_STATISTICS { - ULONG Version; - ULONG Flags; - LARGE_INTEGER RecoveredWrites; - LARGE_INTEGER UnrecoveredWrites; - LARGE_INTEGER RecoveredReads; - LARGE_INTEGER UnrecoveredReads; - UCHAR CompressionRatioReads; - UCHAR CompressionRatioWrites; -} TAPE_STATISTICS, *PTAPE_STATISTICS; - -#define RECOVERED_WRITES_VALID 0x00000001 -#define UNRECOVERED_WRITES_VALID 0x00000002 -#define RECOVERED_READS_VALID 0x00000004 -#define UNRECOVERED_READS_VALID 0x00000008 -#define WRITE_COMPRESSION_INFO_VALID 0x00000010 -#define READ_COMPRESSION_INFO_VALID 0x00000020 - -typedef struct _TAPE_GET_STATISTICS { - ULONG Operation; -} TAPE_GET_STATISTICS, *PTAPE_GET_STATISTICS; - -#define TAPE_RETURN_STATISTICS 0L -#define TAPE_RETURN_ENV_INFO 1L -#define TAPE_RESET_STATISTICS 2L - -// -// IOCTL_STORAGE_GET_MEDIA_TYPES_EX will return an array of DEVICE_MEDIA_INFO -// structures, one per supported type, embedded in the GET_MEDIA_TYPES struct. -// - -typedef enum _STORAGE_MEDIA_TYPE { - // - // Following are defined in ntdddisk.h in the MEDIA_TYPE enum - // - // Unknown, // Format is unknown - // F5_1Pt2_512, // 5.25", 1.2MB, 512 bytes/sector - // F3_1Pt44_512, // 3.5", 1.44MB, 512 bytes/sector - // F3_2Pt88_512, // 3.5", 2.88MB, 512 bytes/sector - // F3_20Pt8_512, // 3.5", 20.8MB, 512 bytes/sector - // F3_720_512, // 3.5", 720KB, 512 bytes/sector - // F5_360_512, // 5.25", 360KB, 512 bytes/sector - // F5_320_512, // 5.25", 320KB, 512 bytes/sector - // F5_320_1024, // 5.25", 320KB, 1024 bytes/sector - // F5_180_512, // 5.25", 180KB, 512 bytes/sector - // F5_160_512, // 5.25", 160KB, 512 bytes/sector - // RemovableMedia, // Removable media other than floppy - // FixedMedia, // Fixed hard disk media - // F3_120M_512, // 3.5", 120M Floppy - // F3_640_512, // 3.5" , 640KB, 512 bytes/sector - // F5_640_512, // 5.25", 640KB, 512 bytes/sector - // F5_720_512, // 5.25", 720KB, 512 bytes/sector - // F3_1Pt2_512, // 3.5" , 1.2Mb, 512 bytes/sector - // F3_1Pt23_1024, // 3.5" , 1.23Mb, 1024 bytes/sector - // F5_1Pt23_1024, // 5.25", 1.23MB, 1024 bytes/sector - // F3_128Mb_512, // 3.5" MO 128Mb 512 bytes/sector - // F3_230Mb_512, // 3.5" MO 230Mb 512 bytes/sector - // F8_256_128, // 8", 256KB, 128 bytes/sector - // F3_200Mb_512, // 3.5", 200M Floppy (HiFD) - // - - DDS_4mm = 0x20, // Tape - DAT DDS1,2,... (all vendors) - MiniQic, // Tape - miniQIC Tape - Travan, // Tape - Travan TR-1,2,3,... - QIC, // Tape - QIC - MP_8mm, // Tape - 8mm Exabyte Metal Particle - AME_8mm, // Tape - 8mm Exabyte Advanced Metal Evap - AIT1_8mm, // Tape - 8mm Sony AIT - DLT, // Tape - DLT Compact IIIxt, IV - NCTP, // Tape - Philips NCTP - IBM_3480, // Tape - IBM 3480 - IBM_3490E, // Tape - IBM 3490E - IBM_Magstar_3590, // Tape - IBM Magstar 3590 - IBM_Magstar_MP, // Tape - IBM Magstar MP - STK_DATA_D3, // Tape - STK Data D3 - SONY_DTF, // Tape - Sony DTF - DV_6mm, // Tape - 6mm Digital Video - DMI, // Tape - Exabyte DMI and compatibles - SONY_D2, // Tape - Sony D2S and D2L - CLEANER_CARTRIDGE, // Cleaner - All Drive types that support Drive Cleaners - CD_ROM, // Opt_Disk - CD - CD_R, // Opt_Disk - CD-Recordable (Write Once) - CD_RW, // Opt_Disk - CD-Rewriteable - DVD_ROM, // Opt_Disk - DVD-ROM - DVD_R, // Opt_Disk - DVD-Recordable (Write Once) - DVD_RW, // Opt_Disk - DVD-Rewriteable - MO_3_RW, // Opt_Disk - 3.5" Rewriteable MO Disk - MO_5_WO, // Opt_Disk - MO 5.25" Write Once - MO_5_RW, // Opt_Disk - MO 5.25" Rewriteable (not LIMDOW) - MO_5_LIMDOW, // Opt_Disk - MO 5.25" Rewriteable (LIMDOW) - PC_5_WO, // Opt_Disk - Phase Change 5.25" Write Once Optical - PC_5_RW, // Opt_Disk - Phase Change 5.25" Rewriteable - PD_5_RW, // Opt_Disk - PhaseChange Dual Rewriteable - ABL_5_WO, // Opt_Disk - Ablative 5.25" Write Once Optical - PINNACLE_APEX_5_RW, // Opt_Disk - Pinnacle Apex 4.6GB Rewriteable Optical - SONY_12_WO, // Opt_Disk - Sony 12" Write Once - PHILIPS_12_WO, // Opt_Disk - Philips/LMS 12" Write Once - HITACHI_12_WO, // Opt_Disk - Hitachi 12" Write Once - CYGNET_12_WO, // Opt_Disk - Cygnet/ATG 12" Write Once - KODAK_14_WO, // Opt_Disk - Kodak 14" Write Once - MO_NFR_525, // Opt_Disk - Near Field Recording (Terastor) - NIKON_12_RW, // Opt_Disk - Nikon 12" Rewriteable - IOMEGA_ZIP, // Mag_Disk - Iomega Zip - IOMEGA_JAZ, // Mag_Disk - Iomega Jaz - SYQUEST_EZ135, // Mag_Disk - Syquest EZ135 - SYQUEST_EZFLYER, // Mag_Disk - Syquest EzFlyer - SYQUEST_SYJET, // Mag_Disk - Syquest SyJet - AVATAR_F2, // Mag_Disk - 2.5" Floppy - MP2_8mm, // Tape - 8mm Hitachi - DST_S, // Ampex DST Small Tapes - DST_M, // Ampex DST Medium Tapes - DST_L, // Ampex DST Large Tapes - VXATape_1, // Ecrix 8mm Tape - VXATape_2, // Ecrix 8mm Tape - STK_9840, // STK 9840 - LTO_Ultrium, // IBM, HP, Seagate LTO Ultrium - LTO_Accelis, // IBM, HP, Seagate LTO Accelis - DVD_RAM, // Opt_Disk - DVD-RAM - AIT_8mm, // AIT2 or higher - ADR_1, // OnStream ADR Mediatypes - ADR_2 -} STORAGE_MEDIA_TYPE, *PSTORAGE_MEDIA_TYPE; - -#define MEDIA_ERASEABLE 0x00000001 -#define MEDIA_WRITE_ONCE 0x00000002 -#define MEDIA_READ_ONLY 0x00000004 -#define MEDIA_READ_WRITE 0x00000008 - -#define MEDIA_WRITE_PROTECTED 0x00000100 -#define MEDIA_CURRENTLY_MOUNTED 0x80000000 - -// -// Define the different storage bus types -// Bus types below 128 (0x80) are reserved for Microsoft use -// - -typedef enum _STORAGE_BUS_TYPE { - BusTypeUnknown = 0x00, - BusTypeScsi, - BusTypeAtapi, - BusTypeAta, - BusType1394, - BusTypeSsa, - BusTypeFibre, - BusTypeUsb, - BusTypeRAID, - BusTypeMaxReserved = 0x7F -} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE; - -typedef struct _DEVICE_MEDIA_INFO { - union { - struct { - LARGE_INTEGER Cylinders; - STORAGE_MEDIA_TYPE MediaType; - ULONG TracksPerCylinder; - ULONG SectorsPerTrack; - ULONG BytesPerSector; - ULONG NumberMediaSides; - ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values. - } DiskInfo; - - struct { - LARGE_INTEGER Cylinders; - STORAGE_MEDIA_TYPE MediaType; - ULONG TracksPerCylinder; - ULONG SectorsPerTrack; - ULONG BytesPerSector; - ULONG NumberMediaSides; - ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values. - } RemovableDiskInfo; - - struct { - STORAGE_MEDIA_TYPE MediaType; - ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values. - ULONG CurrentBlockSize; - STORAGE_BUS_TYPE BusType; - - // - // Bus specific information describing the medium supported. - // - - union { - struct { - UCHAR MediumType; - UCHAR DensityCode; - } ScsiInformation; - } BusSpecificData; - - } TapeInfo; - } DeviceSpecific; -} DEVICE_MEDIA_INFO, *PDEVICE_MEDIA_INFO; - -typedef struct _GET_MEDIA_TYPES { - ULONG DeviceType; // FILE_DEVICE_XXX values - ULONG MediaInfoCount; - DEVICE_MEDIA_INFO MediaInfo[1]; -} GET_MEDIA_TYPES, *PGET_MEDIA_TYPES; - - -// -// IOCTL_STORAGE_PREDICT_FAILURE -// -// input - none -// -// output - STORAGE_PREDICT_FAILURE structure -// PredictFailure returns zero if no failure predicted and non zero -// if a failure is predicted. -// -// VendorSpecific returns 512 bytes of vendor specific information -// if a failure is predicted -// -typedef struct _STORAGE_PREDICT_FAILURE -{ - ULONG PredictFailure; - UCHAR VendorSpecific[512]; -} STORAGE_PREDICT_FAILURE, *PSTORAGE_PREDICT_FAILURE; - -// end_ntminitape -// end_winioctl - -// -// Property Query Structures -// - -// -// IOCTL_STORAGE_QUERY_PROPERTY -// -// Input Buffer: -// a STORAGE_PROPERTY_QUERY structure which describes what type of query -// is being done, what property is being queried for, and any additional -// parameters which a particular property query requires. -// -// Output Buffer: -// Contains a buffer to place the results of the query into. Since all -// property descriptors can be cast into a STORAGE_DESCRIPTOR_HEADER, -// the IOCTL can be called once with a small buffer then again using -// a buffer as large as the header reports is necessary. -// - - -// -// Types of queries -// - -typedef enum _STORAGE_QUERY_TYPE { - PropertyStandardQuery = 0, // Retrieves the descriptor - PropertyExistsQuery, // Used to test whether the descriptor is supported - PropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptor - PropertyQueryMaxDefined // use to validate the value -} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; - -// -// define some initial property id's -// - -typedef enum _STORAGE_PROPERTY_ID { - StorageDeviceProperty = 0, - StorageAdapterProperty, - StorageDeviceIdProperty -} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID; - -// -// Query structure - additional parameters for specific queries can follow -// the header -// - -typedef struct _STORAGE_PROPERTY_QUERY { - - // - // ID of the property being retrieved - // - - STORAGE_PROPERTY_ID PropertyId; - - // - // Flags indicating the type of query being performed - // - - STORAGE_QUERY_TYPE QueryType; - - // - // Space for additional parameters if necessary - // - - UCHAR AdditionalParameters[1]; - -} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY; - -// -// Standard property descriptor header. All property pages should use this -// as their first element or should contain these two elements -// - -typedef struct _STORAGE_DESCRIPTOR_HEADER { - - ULONG Version; - - ULONG Size; - -} STORAGE_DESCRIPTOR_HEADER, *PSTORAGE_DESCRIPTOR_HEADER; - -// -// Device property descriptor - this is really just a rehash of the inquiry -// data retrieved from a scsi device -// -// This may only be retrieved from a target device. Sending this to the bus -// will result in an error -// - -typedef struct _STORAGE_DEVICE_DESCRIPTOR { - - // - // Sizeof(STORAGE_DEVICE_DESCRIPTOR) - // - - ULONG Version; - - // - // Total size of the descriptor, including the space for additional - // data and id strings - // - - ULONG Size; - - // - // The SCSI-2 device type - // - - UCHAR DeviceType; - - // - // The SCSI-2 device type modifier (if any) - this may be zero - // - - UCHAR DeviceTypeModifier; - - // - // Flag indicating whether the device's media (if any) is removable. This - // field should be ignored for media-less devices - // - - BOOLEAN RemovableMedia; - - // - // Flag indicating whether the device can support mulitple outstanding - // commands. The actual synchronization in this case is the responsibility - // of the port driver. - // - - BOOLEAN CommandQueueing; - - // - // Byte offset to the zero-terminated ascii string containing the device's - // vendor id string. For devices with no such ID this will be zero - // - - ULONG VendorIdOffset; - - // - // Byte offset to the zero-terminated ascii string containing the device's - // product id string. For devices with no such ID this will be zero - // - - ULONG ProductIdOffset; - - // - // Byte offset to the zero-terminated ascii string containing the device's - // product revision string. For devices with no such string this will be - // zero - // - - ULONG ProductRevisionOffset; - - // - // Byte offset to the zero-terminated ascii string containing the device's - // serial number. For devices with no serial number this will be zero - // - - ULONG SerialNumberOffset; - - // - // Contains the bus type (as defined above) of the device. It should be - // used to interpret the raw device properties at the end of this structure - // (if any) - // - - STORAGE_BUS_TYPE BusType; - - // - // The number of bytes of bus-specific data which have been appended to - // this descriptor - // - - ULONG RawPropertiesLength; - - // - // Place holder for the first byte of the bus specific property data - // - - UCHAR RawDeviceProperties[1]; - -} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR; - - -// -// Adapter properties -// -// This descriptor can be retrieved from a target device object of from the -// device object for the bus. Retrieving from the target device object will -// forward the request to the underlying bus -// - -typedef struct _STORAGE_ADAPTER_DESCRIPTOR { - - ULONG Version; - - ULONG Size; - - ULONG MaximumTransferLength; - - ULONG MaximumPhysicalPages; - - ULONG AlignmentMask; - - BOOLEAN AdapterUsesPio; - - BOOLEAN AdapterScansDown; - - BOOLEAN CommandQueueing; - - BOOLEAN AcceleratedTransfer; - - UCHAR BusType; - - USHORT BusMajorVersion; - - USHORT BusMinorVersion; - -} STORAGE_ADAPTER_DESCRIPTOR, *PSTORAGE_ADAPTER_DESCRIPTOR; - -// -// Storage identification descriptor. -// The definitions here are based on the SCSI/SBP vital product data -// device identifier page. -// - -typedef enum _STORAGE_IDENTIFIER_CODE_SET { - StorageIdCodeSetReserved = 0, - StorageIdCodeSetBinary = 1, - StorageIdCodeSetAscii = 2 -} STORAGE_IDENTIFIER_CODE_SET, *PSTORAGE_IDENTIFIER_CODE_SET; - -typedef enum _STORAGE_IDENTIFIER_TYPE { - StorageIdTypeVendorSpecific = 0, - StorageIdTypeVendorId = 1, - StorageIdTypeEUI64 = 2, - StorageIdTypeFCPHName = 3, - StorageIdTypePortRelative = 4 -} STORAGE_IDENTIFIER_TYPE, *PSTORAGE_IDENTIFIER_TYPE; - -typedef enum _STORAGE_ASSOCIATION_TYPE { - StorageIdAssocDevice = 0, - StorageIdAssocPort = 1 -} STORAGE_ASSOCIATION_TYPE, *PSTORAGE_ASSOCIATION_TYPE; - -typedef struct _STORAGE_IDENTIFIER { - STORAGE_IDENTIFIER_CODE_SET CodeSet; - STORAGE_IDENTIFIER_TYPE Type; - USHORT IdentifierSize; - USHORT NextOffset; - - // - // Add new fields here since existing code depends on - // the above layout not changing. - // - - STORAGE_ASSOCIATION_TYPE Association; - - // - // The identifier is a variable length array of bytes. - // - - UCHAR Identifier[1]; -} STORAGE_IDENTIFIER, *PSTORAGE_IDENTIFIER; - -typedef struct _STORAGE_DEVICE_ID_DESCRIPTOR { - - ULONG Version; - - ULONG Size; - - // - // The number of identifiers reported by the device. - // - - ULONG NumberOfIdentifiers; - - // - // The following field is actually a variable length array of identification - // descriptors. Unfortunately there's no C notation for an array of - // variable length structures so we're forced to just pretend. - // - - UCHAR Identifiers[1]; -} STORAGE_DEVICE_ID_DESCRIPTOR, *PSTORAGE_DEVICE_ID_DESCRIPTOR; - - -#pragma warning(push) -#pragma warning(disable:4200) -typedef struct _STORAGE_MEDIA_SERIAL_NUMBER_DATA { - - USHORT Reserved; - - // - // the SerialNumberLength will be set to zero - // if the command is supported and the media - // does not have a valid serial number. - // - - USHORT SerialNumberLength; - - // - // the following data is binary, and is not guaranteed - // to be NULL terminated. this is an excercise for the - // caller. - // - - UCHAR SerialNumber[0]; - -} STORAGE_MEDIA_SERIAL_NUMBER_DATA, *PSTORAGE_MEDIA_SERIAL_NUMBER_DATA; -#pragma warning(push) - - -// begin_winioctl - -#ifdef __cplusplus -} -#endif - -#endif // _NTDDSTOR_H_ -// end_winioctl - diff --git a/src/dos/cdrom.cpp b/src/dos/cdrom.cpp index 6d8febe..423b8bc 100644 --- a/src/dos/cdrom.cpp +++ b/src/dos/cdrom.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/dos/cdrom.h b/src/dos/cdrom.h index 3c307cf..0159d86 100644 --- a/src/dos/cdrom.h +++ b/src/dos/cdrom.h @@ -5,9 +5,11 @@ #define MAX_ASPI_CDROM 5 #include +#include "dosbox.h" #include "mem.h" #include "SDL.h" + #define RAW_SECTOR_SIZE 2352 #define COOKED_SECTOR_SIZE 2048 @@ -181,4 +183,21 @@ private: #endif /* WIN 32 */ +#if defined (LINUX) + +class CDROM_Interface_Ioctl : public CDROM_Interface_SDL +{ +public: + CDROM_Interface_Ioctl (void); + + bool SetDevice (char* path, int forceCD); + bool GetUPC (unsigned char& attr, char* upc); + bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num); + +private: + char device_name[512]; +}; + +#endif /* LINUX */ + #endif /* __CDROM_INTERFACE__ */ diff --git a/src/dos/cdrom_aspi_win32.cpp b/src/dos/cdrom_aspi_win32.cpp index c3ed83c..7e547ce 100644 --- a/src/dos/cdrom_aspi_win32.cpp +++ b/src/dos/cdrom_aspi_win32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,13 +16,28 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: cdrom_aspi_win32.cpp,v 1.10 2004/01/10 14:03:34 qbix79 Exp $ */ + #if defined (WIN32) #include -#include "cdrom.h" -#include "scsidefs.h" // Aspi stuff #include "dosbox.h" +#include "cdrom.h" + +//Are actually system includes but leave for now +#include "wnaspi32.h" + +#if defined (_MSC_VER) +#include // Ioctl stuff +#include +#include // Ioctl stuff +#else +#include "ddk/ntddcdrm.h" // Ioctl stuff +#include "ddk/ntddscsi.h" +#endif + +#include "scsidefs.h" // ***************************************************************** // Windows ASPI functions (should work for all WIN with ASPI layer) @@ -292,7 +307,7 @@ bool CDROM_Interface_Aspi::GetAudioTrackInfo (int track, TMSF& start, unsigned c start.min = (unsigned char)(toc.tracks[track-1].lAddr >> 8) &0xFF; start.sec = (unsigned char)(toc.tracks[track-1].lAddr >> 16) &0xFF; start.fr = (unsigned char)(toc.tracks[track-1].lAddr >> 24) &0xFF; - attr = toc.tracks[track-1].cAdrCtrl; + attr = (toc.tracks[track-1].cAdrCtrl << 4) & 0xEF; return true; }; return false; @@ -503,7 +518,7 @@ bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track if (s.SRB_Status!=SS_COMP) return false; - attr = (pos.ADR<<4) | pos.Control; + attr = (pos.Control<<4) &0xEF; track = pos.TrackNumber; index = pos.IndexNumber; absPos.min = pos.AbsoluteAddress[1]; @@ -716,4 +731,4 @@ bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long se return (s.SRB_Status==SS_COMP); }; -#endif \ No newline at end of file +#endif diff --git a/src/dos/cdrom_ioctl_linux.cpp b/src/dos/cdrom_ioctl_linux.cpp new file mode 100644 index 0000000..f505079 --- /dev/null +++ b/src/dos/cdrom_ioctl_linux.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library 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 +#include "cdrom.h" + +#if defined (LINUX) +#include +#include +#include +#include +#include +#include + +CDROM_Interface_Ioctl::CDROM_Interface_Ioctl(void) : CDROM_Interface_SDL() +{ + strcpy(device_name, ""); +} + +bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc) +{ + int cdrom_fd = open(device_name, O_RDONLY | O_NONBLOCK); + if (cdrom_fd <= 0) return false; + + struct cdrom_mcn cdrom_mcn; + int ret = ioctl(cdrom_fd, CDROM_GET_MCN, &cdrom_mcn); + + close(cdrom_fd); + + if (ret > 0) { + attr = 0; + strncpy(upc, (char*)cdrom_mcn.medium_catalog_number, 14); + } + + return (ret > 0); +} + +bool CDROM_Interface_Ioctl::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) +{ + int cdrom_fd = open(device_name, O_RDONLY | O_NONBLOCK); + if (cdrom_fd <= 0) return false; + + Bitu buflen = raw ? num * CD_FRAMESIZE_RAW : num * CD_FRAMESIZE; + Bit8u* buf = new Bit8u[buflen]; + int ret; + + if (raw) { + struct cdrom_read cdrom_read; + cdrom_read.cdread_lba = sector; + cdrom_read.cdread_bufaddr = (char*)buf; + cdrom_read.cdread_buflen = buflen; + + ret = ioctl(cdrom_fd, CDROMREADRAW, &cdrom_read); + } else { + ret = lseek(cdrom_fd, sector * CD_FRAMESIZE, SEEK_SET); + if (ret >= 0) ret = read(cdrom_fd, buf, buflen); + if (ret != buflen) ret = -1; + } + close(cdrom_fd); + + MEM_BlockWrite(buffer, buf, buflen); + delete[] buf; + + return (ret > 0); +} + +bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) +{ + bool success = CDROM_Interface_SDL::SetDevice(path, forceCD); + + if (success) { + const char* tmp = SDL_CDName(forceCD); + if (tmp) strncpy(device_name, tmp, 512); + else success = false; + } + + return success; +} + +#endif diff --git a/src/dos/cdrom_ioctl_win32.cpp b/src/dos/cdrom_ioctl_win32.cpp index 3d15e36..f73f9c0 100644 --- a/src/dos/cdrom_ioctl_win32.cpp +++ b/src/dos/cdrom_ioctl_win32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: cdrom_ioctl_win32.cpp,v 1.10 2004/01/10 14:03:34 qbix79 Exp $ */ + #if defined (WIN32) // ***************************************************************** @@ -23,9 +25,15 @@ // ***************************************************************** #include -#include // Ioctl stuff #include -#include "ntddcdrm.h" // Ioctl stuff + +#if defined (_MSC_VER) +#include // Ioctl stuff +#include // Ioctl stuff +#else +#include "ddk/ntddcdrm.h" // Ioctl stuff +#endif + #include "cdrom.h" CDROM_Interface_Ioctl::CDROM_Interface_Ioctl() @@ -75,7 +83,7 @@ bool CDROM_Interface_Ioctl::GetAudioTrackInfo(int track, TMSF& start, unsigned c // Close(); if (!bStat) return false; - attr = (toc.TrackData[track-1].Adr << 4) | toc.TrackData[track].Control; + attr = (toc.TrackData[track-1].Control << 4) & 0xEF; start.min = toc.TrackData[track-1].Address[1]; start.sec = toc.TrackData[track-1].Address[2]; start.fr = toc.TrackData[track-1].Address[3]; @@ -97,7 +105,7 @@ bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& trac // Close(); if (!bStat) return false; - attr = (sub.CurrentPosition.ADR << 4) | sub.CurrentPosition.Control; + attr = (sub.CurrentPosition.Control << 4) & 0xEF; track = sub.CurrentPosition.TrackNumber; index = sub.CurrentPosition.IndexNumber; relPos.min = sub.CurrentPosition.TrackRelativeAddress[1]; diff --git a/src/dos/dev_con.h b/src/dos/dev_con.h index f9e4b97..c204eae 100644 --- a/src/dos/dev_con.h +++ b/src/dos/dev_con.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dev_con.h,v 1.14 2003/09/08 18:06:44 qbix79 Exp $ */ +/* $Id: dev_con.h,v 1.16 2004/01/10 14:03:34 qbix79 Exp $ */ #include "dos_inc.h" #include "../ints/int10.h" @@ -56,7 +56,7 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { if ((cache) && (*size)) { data[count++]=cache; if(dos.echo) { - INT10_TeletypeOutput(cache,7,false); + INT10_TeletypeOutput(cache,7); } cache=0; @@ -71,8 +71,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { *size=count; reg_ax=oldax; if(dos.echo) { - INT10_TeletypeOutput(13,7,false); //maybe don't do this ( no need for it actually ) (but it's compatible) - INT10_TeletypeOutput(10,7,false); + INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible) + INT10_TeletypeOutput(10,7); } return true; break; @@ -80,8 +80,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS else if(count) { //Remove data if it exists (extended keys don't go right) data[count--]=0; - INT10_TeletypeOutput(8,7,false); - INT10_TeletypeOutput(' ',7,false); + INT10_TeletypeOutput(8,7); + INT10_TeletypeOutput(' ',7); } else { continue; //no data read yet so restart whileloop. } @@ -98,7 +98,7 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { } if(dos.echo) { //what to do if *size==1 and character is BS ????? - INT10_TeletypeOutput(reg_al,7,false); + INT10_TeletypeOutput(reg_al,7); } } *size=count; @@ -124,7 +124,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { } else { // pass attribute only if ansi is enabled - INT10_TeletypeOutput(data[count],ansi.attr,ansi.enabled); + INT10_TeletypeOutputAttr(data[count],ansi.attr,ansi.enabled); count++; continue; }; @@ -315,7 +315,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: esc[%dJ called : not supported",ansi.data[0]); break; } - for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutput(' ',ansi.attr,true); + for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true); ClearAnsi(); INT10_SetCursorPos(0,0,0); break; @@ -334,7 +334,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { ClearAnsi(); break; case 'K':/* erase till end of line */ - for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutput(' ',ansi.attr,true); + for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutputAttr(' ',ansi.attr,true); ClearAnsi(); /* maybe set cursor back to starting place ???? */ break; case 'l':/* (if code =7) disable linewrap */ diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index b2d9680..a5aea47 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos.cpp,v 1.57 2003/10/14 23:33:33 harekiet Exp $ */ +/* $Id: dos.cpp,v 1.65 2004/02/02 11:38:44 qbix79 Exp $ */ #include #include @@ -44,10 +44,10 @@ void DOS_SetError(Bit16u code) { #define DOSNAMEBUF 256 static Bitu DOS_21Handler(void) { - - DOS_PSP psp(dos.psp); - psp.SetStack(RealMake(SegValue(ss),reg_sp)); - + if (((reg_ah != 0x50) && (reg_ah != 0x51) && (reg_ah != 0x62) && (reg_ah != 0x64)) && (reg_ah<0x6c)) { + DOS_PSP psp(dos.psp); + psp.SetStack(RealMake(SegValue(ss),reg_sp-20)); + } char name1[DOSNAMEBUF+1]; char name2[DOSNAMEBUF+1]; switch (reg_ah) { @@ -519,6 +519,7 @@ static Bitu DOS_21Handler(void) { case 0x00: /* Get */ { if (DOS_GetFileAttr(name1,®_cx)) { + reg_ax=reg_cx; /* Undocumented */ CALLBACK_SCF(false); } else { CALLBACK_SCF(true); @@ -527,7 +528,12 @@ static Bitu DOS_21Handler(void) { break; case 0x01: /* Set */ LOG(LOG_MISC,LOG_ERROR)("DOS:Set File Attributes for %s not supported",name1); - CALLBACK_SCF(false); + if (DOS_SetFileAttr(name1,reg_cx)) { + CALLBACK_SCF(false); + } else { + CALLBACK_SCF(true); + reg_ax=dos.errorcode; + } break; default: LOG(LOG_MISC,LOG_ERROR)("DOS:0x43:Illegal subfunction %2X",reg_al); @@ -594,6 +600,7 @@ static Bitu DOS_21Handler(void) { { Bit16u size=reg_bx; if (DOS_ResizeMemory(SegValue(es),&size)) { + reg_ax=SegValue(es); CALLBACK_SCF(false); } else { reg_ax=dos.errorcode; @@ -744,7 +751,7 @@ static Bitu DOS_21Handler(void) { DOS_CloseFile(handle); DOS_SetError(DOSERR_ACCESS_DENIED); reg_ax=dos.errorcode; - CALLBACK_SCF(false); + CALLBACK_SCF(true); break; } if (DOS_CreateFile(name1,reg_cx,&handle)) { @@ -757,7 +764,7 @@ static Bitu DOS_21Handler(void) { break; } case 0x60: /* Canonicalize filename or path */ - MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); + MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF); if (DOS_Canonicalize(name1,name2)) { MEM_BlockWrite(SegPhys(es)+reg_di,name2,strlen(name2)+1); CALLBACK_SCF(false); @@ -891,7 +898,6 @@ static Bitu DOS_27Handler(void) return CBRET_NONE; } static Bitu DOS_25Handler(void) { - flags.type=0; if(Drives[reg_al]==0){ reg_ax=0x8002; SETFLAGBIT(CF,true); @@ -905,7 +911,6 @@ static Bitu DOS_25Handler(void) { } static Bitu DOS_26Handler(void) { LOG(LOG_DOSMISC,LOG_NORMAL)("int 26 called: hope for the best!"); - flags.type=0; if(Drives[reg_al]==0){ reg_ax=0x8002; SETFLAGBIT(CF,true); diff --git a/src/dos/dos_classes.cpp b/src/dos/dos_classes.cpp index 668873f..100d216 100644 --- a/src/dos/dos_classes.cpp +++ b/src/dos/dos_classes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_classes.cpp,v 1.32 2003/10/09 13:47:06 finsterr Exp $ */ +/* $Id: dos_classes.cpp,v 1.33 2004/01/10 14:03:34 qbix79 Exp $ */ #include #include diff --git a/src/dos/dos_devices.cpp b/src/dos/dos_devices.cpp index 3cab0a7..1ee2b47 100644 --- a/src/dos/dos_devices.cpp +++ b/src/dos/dos_devices.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/dos/dos_execute.cpp b/src/dos/dos_execute.cpp index 4c4147f..ad99179 100644 --- a/src/dos/dos_execute.cpp +++ b/src/dos/dos_execute.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id */ + #include #include "dosbox.h" #include "mem.h" @@ -118,6 +120,7 @@ bool DOS_Terminate(bool tsr) { /* Set the CS:IP stored in int 0x22 back on the stack */ mem_writew(SegPhys(ss)+reg_sp+0,RealOff(old22)); mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(old22)); + mem_writew(SegPhys(ss)+reg_sp+4,0x200); //stack isn't preserved // Free memory owned by process if (!tsr) DOS_FreeProcessMemory(mempsp); return true; @@ -185,8 +188,11 @@ bool DOS_ChildPSP(Bit16u segment, Bit16u size) psp.MakeNew(size); DOS_PSP psp_parent(psp.GetParent()); psp.CopyFileTable(&psp_parent,true); + psp.SetEnvironment(psp_parent.GetEnvironment()); + psp.SetSize(size); return true; }; + static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { /* Fix the PSP for psp and environment MCB's */ @@ -251,7 +257,7 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { /* Convert the header to correct endian, i hope this works */ HostPt endian=(HostPt)&head; for (i=0;i #include @@ -53,6 +53,11 @@ void DOS_SetDefaultDrive(Bit8u drive) { } bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { + if(strlen(name) == 0) { + DOS_SetError(DOSERR_FILE_NOT_FOUND); + return false; + } + char tempdir[DOS_PATHLENGTH]; char upname[DOS_PATHLENGTH]; Bitu r,w; @@ -81,7 +86,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 '*': case '?': case '&': - case '\'': case '+': + case '\'': case '+': case '^': upname[w++]=c; break; default: @@ -359,7 +364,15 @@ bool DOS_OpenFile(char * 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); - + + Bit16u attr; + if(DOS_GetFileAttr(name,&attr)){ //DON'T ALLOW directories to be openened + if((attr & DOS_ATTR_DIRECTORY) || (attr & DOS_ATTR_VOLUME)){ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; + } + } + DOS_PSP psp(dos.psp); Bit8u handle=DOS_FindDevice((char *)name); bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i; @@ -447,6 +460,21 @@ bool DOS_GetFileAttr(char * name,Bit16u * attr) { } } +bool DOS_SetFileAttr(char * 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) +{ + Bit16u attrTemp; + char fullname[DOS_PATHLENGTH];Bit8u drive; + if (!DOS_MakeName(name,fullname,&drive)) return false; + if (strcmp(Drives[drive]->GetInfo(),"CDRom.")==0) { + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; + } + return Drives[drive]->GetFileAttr(fullname,&attrTemp); +} + bool DOS_Canonicalize(char * name,char * big) { //TODO Add Better support for devices and shit but will it be needed i doubt it :) Bit8u drive; diff --git a/src/dos/dos_ioctl.cpp b/src/dos/dos_ioctl.cpp index c3a2896..2aa4ae6 100644 --- a/src/dos/dos_ioctl.cpp +++ b/src/dos/dos_ioctl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_ioctl.cpp,v 1.16 2003/10/14 08:38:35 qbix79 Exp $ */ +/* $Id: dos_ioctl.cpp,v 1.18 2004/01/10 14:03:34 qbix79 Exp $ */ #include #include "dosbox.h" @@ -78,8 +78,9 @@ bool DOS_IOCTL(void) { drive=reg_bl;if (!drive) drive=dos.current_drive;else drive--; if (Drives[drive]) { reg_dx=0; - //TODO Cdrom drives are remote + if (Drives[drive]->isRemote()) reg_dx|=(1 << 12); //TODO Set bit 9 on drives that don't support direct I/O + reg_al=0; return true; } else { DOS_SetError(DOSERR_INVALID_DRIVE); diff --git a/src/dos/dos_memory.cpp b/src/dos/dos_memory.cpp index 2feba96..e2e3d9d 100644 --- a/src/dos/dos_memory.cpp +++ b/src/dos/dos_memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -165,6 +165,11 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) { bool DOS_FreeMemory(Bit16u segment) { //TODO Check if allowed to free this segment + if ((segment-1) < MEM_START){ + LOG(LOG_DOSMISC,LOG_ERROR)("Program tried to free %X ---ERROR",segment); + return false; + } + DOS_MCB mcb(segment-1); mcb.SetPSPSeg(MCB_FREE); DOS_CompressMemory(); diff --git a/src/dos/dos_misc.cpp b/src/dos/dos_misc.cpp index 33b56f1..ddfa2d2 100644 --- a/src/dos/dos_misc.cpp +++ b/src/dos/dos_misc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index 26a2cb9..4559914 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,9 @@ #include "cdrom.h" +#define MSCDEX_LOG LOG(LOG_MISC,LOG_ERROR) +//#define MSCDEX_LOG + #define MSCDEX_VERSION_HIGH 2 #define MSCDEX_VERSION_LOW 23 #define MSCDEX_MAX_DRIVES 5 @@ -106,6 +109,7 @@ public: bool GetCopyrightName (Bit16u drive, PhysPt data); bool GetAbstractName (Bit16u drive, PhysPt data); bool GetDocumentationName(Bit16u drive, PhysPt data); + bool GetDirectoryEntry (Bit16u drive, bool copyFlag, PhysPt pathname, PhysPt buffer, Bitu& error); bool ReadVTOC (Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error); bool ReadSectors (Bit16u drive, Bit32u sector, Bit16u num, PhysPt data); bool ReadSectors (Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, PhysPt data); @@ -125,8 +129,10 @@ public: private: + PhysPt GetDefaultBuffer (void); + Bit16u numDrives; - + typedef struct SDriveInfo { Bit8u drive; // drive letter in dosbox Bit8u physDrive; // drive letter in system @@ -139,6 +145,7 @@ private: Bit32u volumeSize; // for media change } TDriveInfo; + PhysPt defaultBuffer; TDriveInfo dinfo[MSCDEX_MAX_DRIVES]; CDROM_Interface* cdrom[MSCDEX_MAX_DRIVES]; @@ -150,13 +157,18 @@ CMscdex::CMscdex(void) { numDrives = 0; rootDriverHeaderSeg = 0; - + defaultBuffer = 0; + memset(dinfo,0,sizeof(dinfo)); for (Bit32u i=0; i0)); DOS_DeviceHeader devHeader(PhysMake(seg,0)); devHeader.SetNextDeviceHeader (0xFFFFFFFF); - devHeader.SetDriveLetter ('A'+_drive); + devHeader.SetDriveLetter (_drive+1); devHeader.SetNumSubUnits (1); devHeader.SetName ("MSCD001 "); @@ -205,8 +217,7 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) real_writeb(seg,off+4,(Bit8u)0xCB); //A RETF Instruction devHeader.SetStrategy(off); - // Create Callback Interrupt - off += 5; + // Create Callback Interruptoff += 5; Bitu call_interrupt=CALLBACK_Allocate(); CallBack_Handlers[call_interrupt]=MSCDEX_Interrupt_Handler; real_writeb(seg,off+0,(Bit8u)0xFE); //GRP 4 @@ -249,6 +260,14 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) break; } #endif + #if defined (LINUX) + // Always use IOCTL in Linux +// if (useCdromInterface==CDROM_USE_IOCTL) { + cdrom[numDrives] = new CDROM_Interface_Ioctl(); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface."); + break; +// } + #endif cdrom[numDrives] = new CDROM_Interface_SDL(); LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: SDL Interface."); } break; @@ -268,7 +287,7 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) return 6; }; if (!cdrom[numDrives]->SetDevice(physicalPath,forceCD)) return 3; - subUnit = numDrives; + subUnit = (Bit8u)numDrives; // Set drive DOS_DeviceHeader devHeader(PhysMake(rootDriverHeaderSeg,0)); devHeader.SetNumSubUnits(devHeader.GetNumSubUnits()+1); @@ -282,6 +301,16 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) return 4; }; +PhysPt CMscdex::GetDefaultBuffer(void) +{ + if (defaultBuffer==0) { + Bit16u seg,size = 128; + if (!DOS_AllocateMemory(&seg,&size)) E_Exit("MSCDEX: cannot allocate default buffer."); + defaultBuffer = PhysMake(seg,0); + }; + return defaultBuffer; +}; + void CMscdex::GetDriverInfo (PhysPt data) { for (Bit16u i=0; i=numDrives) return false; - Bit8u min = (start>>16) & 0xFF; - Bit8u sec = (start>> 8) & 0xFF; - Bit8u fr = (start>> 0) & 0xFF; + Bit8u min = (Bit8u)(start>>16) & 0xFF; + Bit8u sec = (Bit8u)(start>> 8) & 0xFF; + Bit8u fr = (Bit8u)(start>> 0) & 0xFF; Bit32u sector = min*60*75+sec*75+fr - 150; return dinfo[subUnit].lastResult = PlayAudioSector(subUnit,sector,length); }; @@ -511,9 +540,9 @@ bool CMscdex::ReadSectors(Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, Ph bool CMscdex::ReadSectorsMSF(Bit8u subUnit, bool raw, Bit32u start, Bit16u num, PhysPt data) { if (subUnit>=numDrives) return false; - Bit8u min = (start>>16) & 0xFF; - Bit8u sec = (start>> 8) & 0xFF; - Bit8u fr = (start>> 0) & 0xFF; + Bit8u min = (Bit8u)(start>>16) & 0xFF; + Bit8u sec = (Bit8u)(start>> 8) & 0xFF; + Bit8u fr = (Bit8u)(start>> 0) & 0xFF; Bit32u sector = min*60*75+sec*75+fr - 150; // TODO: Check, if num has to be converted too ?! return ReadSectors(subUnit,raw,sector,num,data); @@ -525,6 +554,77 @@ bool CMscdex::ReadSectors(Bit16u drive, Bit32u sector, Bit16u num, PhysPt data) return ReadSectors(GetSubUnit(drive),false,sector,num,data); }; +bool CMscdex::GetDirectoryEntry(Bit16u drive, bool copyFlag, PhysPt pathname, PhysPt buffer, Bitu& error) +{ + char volumeID[6] = {0}; + char searchName[256]; + char entryName[256]; + bool foundComplete = false; + bool foundName; + char* useName; + Bitu entryLength,nameLength; + // clear error + error = 0; + MEM_StrCopy(pathname+1,searchName,mem_readb(pathname)); + upcase(searchName); + char* searchPos = searchName; +// LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Get DirEntry : Find : %s",searchName); + // read vtoc + PhysPt defBuffer = GetDefaultBuffer(); + if (!ReadSectors(GetSubUnit(drive),false,16,1,defBuffer)) return false; + // TODO: has to be iso 9960 + MEM_StrCopy(defBuffer+1,volumeID,5); volumeID[5] = 0; + bool iso = (strcmp("CD001",volumeID)==0); + if (!iso) E_Exit("MSCDEX: GetDirEntry: Not an ISO 9960 CD."); + // get directory position + Bitu dirEntrySector = mem_readd(defBuffer+156+2); + Bits dirSize = mem_readd(defBuffer+156+10); + Bitu index; + while (dirSize>0) { + index = 0; + if (!ReadSectors(GetSubUnit(drive),false,dirEntrySector,1,defBuffer)) return false; + // Get string part + foundName = false; + useName = searchPos; + searchPos = strchr(searchPos,'\\'); + if (searchPos) { *searchPos = 0; searchPos++; } + else foundComplete = true; + + do { + entryLength = mem_readb(defBuffer+index); + if (entryLength==0) break; + nameLength = mem_readb(defBuffer+index+32); + MEM_StrCopy(defBuffer+index+33,entryName,nameLength); + if (strcmp(entryName,useName)==0) { +// LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Get DirEntry : Found : %s",useName); + foundName = true; + break; + } + index += entryLength; + } while (index+33<=2048); + + if (foundName) { + // TO DO : name gefunden, Daten in den Buffer kopieren + if (foundComplete) { + if (copyFlag) E_Exit("MSCDEX: GetDirEntry: Unsupported copyflag"); + // Direct copy + MEM_BlockCopy(buffer,defBuffer+index,entryLength); + error = iso ? 1:0; + return true; + } + // directory wechseln + dirEntrySector = mem_readd(defBuffer+index+2); + dirSize = mem_readd(defBuffer+index+10); + } else { + // continue search in next sector + dirSize -= 2048; + dirEntrySector++; + } + }; + error = 2; // file not found + return false; // not found +}; + bool CMscdex::GetCurrentPos(Bit8u subUnit, TMSF& pos) { if (subUnit>=numDrives) return false; @@ -625,14 +725,14 @@ static Bitu MSCDEX_Interrupt_Handler(void) Bit8u subUnit = mem_readb(data+1); Bit8u funcNr = mem_readb(data+2); -// LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Driver Function %02X",funcNr); + MSCDEX_LOG("MSCDEX: Driver Function %02X",funcNr); switch (funcNr) { case 0x03 : { /* IOCTL INPUT */ PhysPt buffer = PhysMake(mem_readw(data+0x10),mem_readw(data+0x0E)); subFuncNr = mem_readb(buffer); -// LOG(LOG_MISC,LOG_ERROR)("MSCDEX: IOCTL INPUT Subfunction %02X",subFuncNr); + MSCDEX_LOG("MSCDEX: IOCTL INPUT Subfunction %02X",subFuncNr); switch (subFuncNr) { case 0x00 : /* Get Device Header address */ mem_writed(buffer+1,RealMake(mscdex->rootDriverHeaderSeg,0)); @@ -784,6 +884,7 @@ static Bitu MSCDEX_Interrupt_Handler(void) // Set Statusword mem_writew(data+3,mscdex->GetStatusWord(subUnit)); + MSCDEX_LOG("MSCDEX: Status : %04X",mem_readw(data+3)); return CBRET_NONE; } @@ -792,7 +893,7 @@ static bool MSCDEX_Handler(void) if (reg_ah!=0x15) return false; PhysPt data = PhysMake(SegValue(es),reg_bx); -// LOG(LOG_MISC,LOG_ERROR)("MSCDEX: INT 2F %04X",reg_ax); + MSCDEX_LOG("MSCDEX: INT 2F %04X",reg_ax); switch (reg_ax) { case 0x1500: /* Install check */ @@ -860,8 +961,14 @@ static bool MSCDEX_Handler(void) case 0x150D: /* Get drives */ mscdex->GetDrives(data); return true; + case 0x150F: { // Get directory entry + Bitu error; + bool success = mscdex->GetDirectoryEntry(reg_cl,reg_ch&1,data,PhysMake(reg_si,reg_di),error); + reg_ax = error; + CALLBACK_SCF(!success); + }; return true; case 0x1510: /* Device driver request */ - mscdex->SendDriverRequest(reg_cx & 0xFF,data); + mscdex->SendDriverRequest(reg_cx,data); return true; default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unknwon call : %04X",reg_ax); return true; diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 3d3d8d0..c7e67db 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_programs.cpp,v 1.20 2003/09/08 18:10:08 qbix79 Exp $ */ +/* $Id: dos_programs.cpp,v 1.22 2004/01/10 14:03:34 qbix79 Exp $ */ #include #include @@ -28,7 +28,7 @@ #include "regs.h" #include "callback.h" #include "cdrom.h" -#include "../shell/shell_inc.h" + void MSCDEX_SetCDInterface(int intNr, int forceCD); diff --git a/src/dos/dos_tables.cpp b/src/dos/dos_tables.cpp index e903519..93d2554 100644 --- a/src/dos/dos_tables.cpp +++ b/src/dos/dos_tables.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,10 +49,11 @@ Bit16u DOS_GetMemory(Bit16u pages) { void DOS_SetupTables(void) { dos_memseg=0xd000; Bit16u seg;Bitu i; - dos.tables.indosflag=RealMake(DOS_GetMemory(1),0); dos.tables.mediaid=RealMake(DOS_GetMemory(2),0); dos.tables.tempdta=RealMake(DOS_GetMemory(4),0); for (i=0;i #include +int fileInfoCounter = 0; bool SortByName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) { @@ -127,7 +128,7 @@ void DOS_Drive_Cache::SetLabel(const char* vname) Bit16u DOS_Drive_Cache::GetFreeID(CFileInfo* dir) { - for (Bit32u i=0; inextEntry>0) dirSearch[srchNr]->nextEntry--; + if (dirSearch[srchNr] && (dirSearch[srchNr]->nextEntry>0)) dirSearch[srchNr]->nextEntry--; if (!ignoreLastDir) { // Check if there are any open search dir that are affected by this... @@ -246,11 +247,13 @@ void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) // LOG_DEBUG("DIR: Caching out %s : dir %s",expand,dir->orgname); // delete file objects... - for(Bit32u i=0; ifileList.size(); i++) delete dir->fileList[i]; + for(Bit32u i=0; ifileList.size(); i++) { + if (dirSearch[srchNr]==dir->fileList[i]) dirSearch[srchNr] = 0; + delete dir->fileList[i]; dir->fileList[i] = 0; + } // clear lists dir->fileList.clear(); dir->longNameList.clear(); - dir->shortNr = 0; save_dir = 0; }; @@ -283,6 +286,25 @@ bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) return false; }; +int DOS_Drive_Cache::CompareShortname(const char* compareName, const char* shortName) +{ + char* cpos = strchr(shortName,'~'); + if (cpos) { + Bits compareCount1 = (int)cpos - (int)shortName; + char* endPos = strchr(cpos,'.'); + Bitu numberSize = endPos ? int(endPos)-int(cpos) : strlen(cpos); + + char* lpos = strchr(compareName,'.'); + Bits compareCount2 = lpos ? int(lpos)-int(compareName) : strlen(compareName); + if (compareCount2>8) compareCount2 = 8; + + compareCount2 -= numberSize; + if (compareCount2>compareCount1) compareCount1 = compareCount2; + return strncmp(compareName,shortName,compareCount1); + } + return strcmp(compareName,shortName); +}; + Bit16u DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name) { Bits foundNr = 0; @@ -292,7 +314,8 @@ Bit16u DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name) while (low<=high) { mid = (low+high)/2; - res = strncmp(name,curDir->longNameList[mid]->shortname,curDir->longNameList[mid]->compareCount); + res = CompareShortname(name,curDir->longNameList[mid]->shortname); + if (res>0) low = mid+1; else if (res<0) high = mid-1; else { @@ -300,7 +323,7 @@ Bit16u DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name) do { foundNr = curDir->longNameList[mid]->shortNr; mid++; - } while(midlongNameList.size() && (strncmp(name,curDir->longNameList[mid]->shortname,curDir->longNameList[mid]->compareCount)==0)); + } while(midlongNameList.size() && (CompareShortname(name,curDir->longNameList[mid]->shortname)==0)); break; }; } @@ -409,7 +432,7 @@ void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info) strcat(info->shortname,"~"); strcat(info->shortname,buffer); // Create compare Count - info->compareCount = tocopy; +// info->compareCount = tocopy; // Add (and cut) Extension, if available if (pos) { // Step to last extension... @@ -435,7 +458,7 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* char dir [CROSS_LEN]; char work [CROSS_LEN]; const char* start = path; - char* pos; + const char* pos; CFileInfo* curDir = dirBase; Bit16u id; @@ -455,7 +478,7 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* strcpy(work,basePath); if (OpenDir(curDir,work,id)) { char buffer[CROSS_LEN]; - char * result; + char* result = 0; strcpy(buffer,dirPath); ReadDir(id,result); strcpy(dirPath,buffer); @@ -485,7 +508,7 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* if (!IsCachedIn(curDir)) { if (OpenDir(curDir,expandedPath,id)) { char buffer[CROSS_LEN]; - char * result; + char* result = 0; strcpy(buffer,dirPath); ReadDir(id,result); strcpy(dirPath,buffer); @@ -599,7 +622,7 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) bool DOS_Drive_Cache::SetResult(CFileInfo* dir, char* &result, Bit16u entryNr) { - static char res[CROSS_LEN]; + static char res[CROSS_LEN] = { 0 }; result = res; if (entryNr>=dir->fileList.size()) return false; @@ -616,7 +639,7 @@ bool DOS_Drive_Cache::FindFirst(char* path, Bitu dtaAddress, Bitu& id) { Bit16u dirID; Bitu dirFindFirstID = 0xffff; - + // Cache directory in if (!OpenDir(path,dirID)) return false; // Seacrh if dta was already used before @@ -641,7 +664,6 @@ bool DOS_Drive_Cache::FindFirst(char* path, Bitu dtaAddress, Bitu& id) dirFindFirst[dirFindFirstID] = new CFileInfo(); dirFindFirst[dirFindFirstID]-> nextEntry = 0; dirFindFirst[dirFindFirstID]-> compareCount = dtaAddress; -// strcpy(dirFindFirst[dirFindFirstID]->orgname,path); // Copy entries to use with FindNext for (Bitu i=0; ifileList.size(); i++) { @@ -704,7 +726,7 @@ bool DOS_No_Drive_Cache::OpenDir(const char* path, Bit16u& id) bool DOS_No_Drive_Cache::ReadDir(Bit16u id, char* &result) { - static char res[CROSS_LEN]; + static char res[CROSS_LEN] = { 0 }; dirent * ent; if (!srch_opendir) return false; diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index 509d083..98c0a1d 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: drive_local.cpp,v 1.44 2004/01/11 16:48:32 qbix79 Exp $ */ + #include #include #include @@ -51,7 +53,11 @@ bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) { strcat(newname,name); CROSS_FILENAME(newname); FILE * hand=fopen(dirCache.GetExpandName(newname),"wb+"); - if (!hand) return false; + if (!hand){ + LOG_MSG("Warning: file creation failed: %s",newname); + return false; + } + dirCache.AddEntry(newname, true); /* Make the 16 bit device information */ *file=new localFile(name,hand,0x202); @@ -79,7 +85,17 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { FILE * hand=fopen(newname,type); // Bit32u err=errno; - if (!hand) return false; + if (!hand) { + if((flags&3) != OPEN_READ) { + FILE * hmm=fopen(newname,"rb"); + if (hmm) { + fclose(hmm); + LOG_MSG("Warning: file %s exists and failed to open in write mode.\nPlease Remove write-protection",newname); + } + } + return false; + } + *file=new localFile(name,hand,0x202); (*file)->flags=flags; //for the inheritance flag and maybe check for others. // (*file)->SetFileName(newname); @@ -100,12 +116,16 @@ bool localDrive::FileUnlink(char * name) { bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { - + char tempDir[CROSS_LEN]; strcpy(tempDir,basedir); strcat(tempDir,_dir); CROSS_FILENAME(tempDir); + if (allocation.mediaid==0xF0 ) { + EmptyCache(); //rescan floppie-content on each findfirst + } + char end[2]={CROSS_FILESPLIT,0}; if (tempDir[strlen(tempDir)-1]!=CROSS_FILESPLIT) strcat(tempDir,end); @@ -121,7 +141,13 @@ bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { Bit8u sAttr; dta.GetSearchParams(sAttr,tempDir); if ((sAttr & DOS_ATTR_VOLUME) && (*_dir==0)) { - // Get Volume Label (DOS_ATTR_VOLUME) and only in basedir + // Get Volume Label (DOS_ATTR_VOLUME) and only in basedir + if ( strcmp(dirCache.GetLabel(), "") == 0 ) { + LOG(LOG_DOSMISC,LOG_ERROR)("DRIVELABEL REQUESTED: none present, returned NOLABEL"); + dta.SetResult("NOLABEL",0,0,0,DOS_ATTR_VOLUME); + return true; + } + if (WildFileCmp(dirCache.GetLabel(),tempDir)) { // Get Volume Label dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); @@ -132,7 +158,7 @@ bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { } bool localDrive::FindNext(DOS_DTA & dta) { - + char * dir_ent; struct stat stat_block; char full_name[CROSS_LEN]; @@ -311,6 +337,10 @@ Bit8u localDrive::GetMediaByte(void) { return allocation.mediaid; } +bool localDrive::isRemote(void) { + return false; +} + localDrive::localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid) { strcpy(basedir,startdir); sprintf(info,"local directory %s",startdir); @@ -372,7 +402,6 @@ bool localFile::Seek(Bit32u * pos,Bit32u type) { } bool localFile::Close() { - // only close if one reference left if (refCtr==1) { fclose(fhandle); @@ -499,3 +528,7 @@ void cdromDrive::SetDir(const char* path) } localDrive::SetDir(path); }; + +bool cdromDrive::isRemote(void) { + return true; +} diff --git a/src/dos/drive_virtual.cpp b/src/dos/drive_virtual.cpp index 64663fd..d40a9a5 100644 --- a/src/dos/drive_virtual.cpp +++ b/src/dos/drive_virtual.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -227,3 +227,6 @@ Bit8u Virtual_Drive::GetMediaByte(void) { return 0xF8; } +bool Virtual_Drive::isRemote(void) { + return false; +} diff --git a/src/dos/drives.cpp b/src/dos/drives.cpp index 65d6483..e5720ff 100644 --- a/src/dos/drives.cpp +++ b/src/dos/drives.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ bool WildFileCmp(const char * file, const char * wild) char file_ext[4]; char wild_name[9]; char wild_ext[4]; - char * find_ext; + const char * find_ext; Bitu r; strcpy(file_name," "); diff --git a/src/dos/drives.h b/src/dos/drives.h index 52ddad8..3691fba 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,11 +16,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: drives.h,v 1.19 2004/01/10 14:03:34 qbix79 Exp $ */ + #ifndef _DRIVES_H__ #define _DRIVES_H__ #include #include "dos_system.h" +#include "shell.h" /* for DOS_Shell */ bool WildFileCmp(const char * file, const char * wild); @@ -41,10 +44,10 @@ public: virtual bool FileExists(const char* name); virtual bool FileStat(const char* name, FileStat_Block * const stat_block); virtual Bit8u GetMediaByte(void); - + virtual bool isRemote(void); private: char basedir[CROSS_LEN]; - + friend void DOS_Shell::CMD_SUBST(char* args); struct { char srch_dir[CROSS_LEN]; } srchInfo[MAX_OPENDIRS]; @@ -71,6 +74,7 @@ public: virtual bool GetFileAttr(char * name,Bit16u * attr); virtual bool FindFirst(char * _dir,DOS_DTA & dta); virtual void SetDir(const char* path); + virtual bool isRemote(void); private: Bit8u subUnit; }; @@ -95,6 +99,7 @@ public: bool FileStat(const char* name, FileStat_Block* const stat_block); Bit8u GetMediaByte(void); void EmptyCache(void){} + bool isRemote(void); private: VFILE_Block * search_file; }; diff --git a/src/dos/scsidefs.h b/src/dos/scsidefs.h index 7db5c9e..061ca90 100644 --- a/src/dos/scsidefs.h +++ b/src/dos/scsidefs.h @@ -1,579 +1,288 @@ -//*************************************************************************** -// -// Name: SCSIDEFS.H -// -// Description: SCSI definitions ('C' Language) -// -//*************************************************************************** - -//*************************************************************************** -// %%% TARGET STATUS VALUES %%% -//*************************************************************************** -#define STATUS_GOOD 0x00 // Status Good -#define STATUS_CHKCOND 0x02 // Check Condition -#define STATUS_CONDMET 0x04 // Condition Met -#define STATUS_BUSY 0x08 // Busy -#define STATUS_INTERM 0x10 // Intermediate -#define STATUS_INTCDMET 0x14 // Intermediate-condition met -#define STATUS_RESCONF 0x18 // Reservation conflict -#define STATUS_COMTERM 0x22 // Command Terminated -#define STATUS_QFULL 0x28 // Queue full - -//*************************************************************************** -// %%% SCSI MISCELLANEOUS EQUATES %%% -//*************************************************************************** -#define MAXLUN 7 // Maximum Logical Unit Id -#define MAXTARG 7 // Maximum Target Id -#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs -#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's - -//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ -// -// %%% SCSI COMMAND OPCODES %%% -// -///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ - -//*************************************************************************** -// %%% Commands for all Device Types %%% -//*************************************************************************** -#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_COPY 0x18 // Copy (O) -#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) -#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) -#define SCSI_LOG_SELECT 0x4C // Log Select (O) -#define SCSI_LOG_SENSE 0x4D // Log Sense (O) -#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) -#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) -#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) -#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) -#define SCSI_READ_BUFF 0x3C // Read Buffer (O) -#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) -#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) -#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) - -//*************************************************************************** -// %%% Commands Unique to Direct Access Devices %%% -//*************************************************************************** -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) -#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) -#define SCSI_PREFETCH 0x34 // Prefetch (O) -#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) -#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) -#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) -#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) -#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) -#define SCSI_READ_LONG 0x3E // Read Long (O) -#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) -#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) -#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) -#define SCSI_REZERO 0x01 // Rezero Unit (O) -#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) -#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) -#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) -#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) -#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) -#define SCSI_SET_LIMIT 0x33 // Set Limits (O) -#define SCSI_START_STP 0x1B // Start/Stop Unit (O) -#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) -#define SCSI_VERIFY 0x2F // Verify (O) -#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) -#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) -#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) -#define SCSI_WRITE_LONG 0x3F // Write Long (O) -#define SCSI_WRITE_SAME 0x41 // Write Same (O) - -//*************************************************************************** -// %%% Commands Unique to Sequential Access Devices %%% -//*************************************************************************** -#define SCSI_ERASE 0x19 // Erase (MANDATORY) -#define SCSI_LOAD_UN 0x1B // Load/Unload (O) -#define SCSI_LOCATE 0x2B // Locate (O) -#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) -#define SCSI_READ_POS 0x34 // Read Position (O) -#define SCSI_READ_REV 0x0F // Read Reverse (O) -#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) -#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) -#define SCSI_REWIND 0x01 // Rewind (MANDATORY) -#define SCSI_SPACE 0x11 // Space (MANDATORY) -#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) -#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) - -//*************************************************************************** -// %%% Commands Unique to Printer Devices %%% -//*************************************************************************** -#define SCSI_PRINT 0x0A // Print (MANDATORY) -#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) -#define SCSI_STOP_PNT 0x1B // Stop Print (O) -#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) - -//*************************************************************************** -// %%% Commands Unique to Processor Devices %%% -//*************************************************************************** -#define SCSI_RECEIVE 0x08 // Receive (O) -#define SCSI_SEND 0x0A // Send (O) - -//*************************************************************************** -// %%% Commands Unique to Write-Once Devices %%% -//*************************************************************************** -#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) -#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) -#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) -#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) -#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) -#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) -#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) -#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) -#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) -#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) -#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) -#define SCSI_WRITE12 0xAA // Write 12-Byte (O) -#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) -#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) - -//*************************************************************************** -// %%% Commands Unique to CD-ROM Devices %%% -//*************************************************************************** -#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) -#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) -#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) -#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) -#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) -#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) -#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) -#define SCSI_READHEADER 0x44 // Read Header (O) -#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) -#define SCSI_READ_TOC 0x43 // Read TOC (O) - -//*************************************************************************** -// %%% Commands Unique to Scanner Devices %%% -//*************************************************************************** -#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) -#define SCSI_GETWINDOW 0x25 // Get Window (O) -#define SCSI_OBJECTPOS 0x31 // Object Postion (O) -#define SCSI_SCAN 0x1B // Scan (O) -#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) - -//*************************************************************************** -// %%% Commands Unique to Optical Memory Devices %%% -//*************************************************************************** -#define SCSI_UpdateBlk 0x3D // Update Block (O) - -//*************************************************************************** -// %%% Commands Unique to Medium Changer Devices %%% -//*************************************************************************** -#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) -#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) -#define SCSI_POSTOELEM 0x2B // Position to Element (O) -#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) -#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) - -//*************************************************************************** -// %%% Commands Unique to Communication Devices %%% -//*************************************************************************** -#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) -#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) -#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) -#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) -#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) -#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) - -//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ -// -// %%% END OF SCSI COMMAND OPCODES %%% -// -///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ - -//*************************************************************************** -// %%% Request Sense Data Format %%% -//*************************************************************************** -typedef struct { - - BYTE ErrorCode; // Error Code (70H or 71H) - BYTE SegmentNum; // Number of current segment descriptor - BYTE SenseKey; // Sense Key(See bit definitions too) - BYTE InfoByte0; // Information MSB - BYTE InfoByte1; // Information MID - BYTE InfoByte2; // Information MID - BYTE InfoByte3; // Information LSB - BYTE AddSenLen; // Additional Sense Length - BYTE ComSpecInf0; // Command Specific Information MSB - BYTE ComSpecInf1; // Command Specific Information MID - BYTE ComSpecInf2; // Command Specific Information MID - BYTE ComSpecInf3; // Command Specific Information LSB - BYTE AddSenseCode; // Additional Sense Code - BYTE AddSenQual; // Additional Sense Code Qualifier - BYTE FieldRepUCode; // Field Replaceable Unit Code - BYTE SenKeySpec15; // Sense Key Specific 15th byte - BYTE SenKeySpec16; // Sense Key Specific 16th byte - BYTE SenKeySpec17; // Sense Key Specific 17th byte - BYTE AddSenseBytes; // Additional Sense Bytes - -} SENSE_DATA_FMT; - -//*************************************************************************** -// %%% REQUEST SENSE ERROR CODE %%% -//*************************************************************************** -#define SERROR_CURRENT 0x70 // Current Errors -#define SERROR_DEFERED 0x71 // Deferred Errors - -//*************************************************************************** -// %%% REQUEST SENSE BIT DEFINITIONS %%% -//*************************************************************************** -#define SENSE_VALID 0x80 // Byte 0 Bit 7 -#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 -#define SENSE_EOM 0x40 // Byte 2 Bit 6 -#define SENSE_ILI 0x20 // Byte 2 Bit 5 - -//*************************************************************************** -// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% -//*************************************************************************** -#define KEY_NOSENSE 0x00 // No Sense -#define KEY_RECERROR 0x01 // Recovered Error -#define KEY_NOTREADY 0x02 // Not Ready -#define KEY_MEDIUMERR 0x03 // Medium Error -#define KEY_HARDERROR 0x04 // Hardware Error -#define KEY_ILLGLREQ 0x05 // Illegal Request -#define KEY_UNITATT 0x06 // Unit Attention -#define KEY_DATAPROT 0x07 // Data Protect -#define KEY_BLANKCHK 0x08 // Blank Check -#define KEY_VENDSPEC 0x09 // Vendor Specific -#define KEY_COPYABORT 0x0A // Copy Abort -#define KEY_EQUAL 0x0C // Equal (Search) -#define KEY_VOLOVRFLW 0x0D // Volume Overflow -#define KEY_MISCOMP 0x0E // Miscompare (Search) -#define KEY_RESERVED 0x0F // Reserved - -//*************************************************************************** -// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% -//*************************************************************************** -#define DTYPE_DASD 0x00 // Disk Device -#define DTYPE_SEQD 0x01 // Tape Device -#define DTYPE_PRNT 0x02 // Printer -#define DTYPE_PROC 0x03 // Processor -#define DTYPE_WORM 0x04 // Write-once read-multiple -#define DTYPE_CROM 0x05 // CD-ROM device -#define DTYPE_CDROM 0x05 // CD-ROM device -#define DTYPE_SCAN 0x06 // Scanner device -#define DTYPE_OPTI 0x07 // Optical memory device -#define DTYPE_JUKE 0x08 // Medium Changer device -#define DTYPE_COMM 0x09 // Communications device -#define DTYPE_RESL 0x0A // Reserved (low) -#define DTYPE_RESH 0x1E // Reserved (high) -#define DTYPE_UNKNOWN 0x1F // Unknown or no device type - -//*************************************************************************** -// %%% ANSI APPROVED VERSION DEFINITIONS %%% -//*************************************************************************** -#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand -#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) -#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 -#define ANSI_RESLO 0x3 // Reserved (low) -#define ANSI_RESHI 0x7 // Reserved (high) - - -//////////////////////////////////////////////////////////////// - -typedef struct { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - ULONG DataBufferOffset; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; - - -typedef struct { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - PVOID DataBuffer; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; - - -typedef struct { - SCSI_PASS_THROUGH spt; - ULONG Filler; - UCHAR ucSenseBuf[32]; - UCHAR ucDataBuf[512]; -} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; - - -typedef struct { - SCSI_PASS_THROUGH_DIRECT spt; - ULONG Filler; - UCHAR ucSenseBuf[32]; -} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; - - - -typedef struct { - UCHAR NumberOfLogicalUnits; - UCHAR InitiatorBusId; - ULONG InquiryDataOffset; -} SCSI_BUS_DATA, *PSCSI_BUS_DATA; - - -typedef struct { - UCHAR NumberOfBusses; - SCSI_BUS_DATA BusData[1]; -} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; - - -typedef struct { - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - BOOLEAN DeviceClaimed; - ULONG InquiryDataLength; - ULONG NextInquiryDataOffset; - UCHAR InquiryData[1]; -} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; - - -typedef struct { - ULONG Length; - UCHAR PortNumber; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; -} SCSI_ADDRESS, *PSCSI_ADDRESS; - - -/* - * method codes - */ -#define METHOD_BUFFERED 0 -#define METHOD_IN_DIRECT 1 -#define METHOD_OUT_DIRECT 2 -#define METHOD_NEITHER 3 - -/* - * file access values - */ -#define FILE_ANY_ACCESS 0 -#define FILE_READ_ACCESS (0x0001) -#define FILE_WRITE_ACCESS (0x0002) - - -#define IOCTL_SCSI_BASE 0x00000004 - -/* - * constants for DataIn member of SCSI_PASS_THROUGH* structures - */ -#define SCSI_IOCTL_DATA_OUT 0 -#define SCSI_IOCTL_DATA_IN 1 -#define SCSI_IOCTL_DATA_UNSPECIFIED 2 - -/* - * Standard IOCTL define - */ -#define CTL_CODE( DevType, Function, Method, Access ) ( \ - ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ -) - -#define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS ) - -#define FILE_DEVICE_MASS_STORAGE 0x0000002d -#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE - -#define IOCTL_STORAGE_CHECK_VERIFY CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_MEDIA_REMOVAL CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_EJECT_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_LOAD_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_LOAD_MEDIA2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_STORAGE_RESERVE CTL_CODE(IOCTL_STORAGE_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_RELEASE CTL_CODE(IOCTL_STORAGE_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_STORAGE_FIND_NEW_DEVICES CTL_CODE(IOCTL_STORAGE_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) - -#define FILE_DEVICE_CD_ROM 0x00000002 -#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM -#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) -#define IOCTL_CDROM_READ_Q_CHANNEL CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_CDROM_SEEK_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) - -typedef struct _CDROM_SEEK_AUDIO_MSF { - UCHAR M; - UCHAR S; - UCHAR F; -} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; - -// -// CD ROM Sub-Q Channel Data Format -// - -#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 -#define IOCTL_CDROM_CURRENT_POSITION 0x01 -#define IOCTL_CDROM_MEDIA_CATALOG 0x02 -#define IOCTL_CDROM_TRACK_ISRC 0x03 - -typedef struct _CDROM_SUB_Q_DATA_FORMAT { - UCHAR Format; - UCHAR Track; -} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; - -typedef struct _SUB_Q_HEADER { - UCHAR Reserved; - UCHAR AudioStatus; - UCHAR DataLength[2]; -} SUB_Q_HEADER, *PSUB_Q_HEADER; - -typedef struct _SUB_Q_CURRENT_POSITION { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Control : 4; - UCHAR ADR : 4; - UCHAR TrackNumber; - UCHAR IndexNumber; - UCHAR AbsoluteAddress[4]; - UCHAR TrackRelativeAddress[4]; -} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; - -typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Reserved[3]; - UCHAR Reserved1 : 7; - UCHAR Mcval : 1; - UCHAR MediaCatalog[15]; -} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; - -typedef struct _SUB_Q_TRACK_ISRC { - SUB_Q_HEADER Header; - UCHAR FormatCode; - UCHAR Reserved0; - UCHAR Track; - UCHAR Reserved1; - UCHAR Reserved2 : 7; - UCHAR Tcval : 1; - UCHAR TrackIsrc[15]; -} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; - -typedef union _SUB_Q_CHANNEL_DATA { - SUB_Q_CURRENT_POSITION CurrentPosition; - SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; - SUB_Q_TRACK_ISRC TrackIsrc; -} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; - - -// IOCTL_DISK_SET_CACHE allows the caller to get or set the state of the disk -// read/write caches. -// -// If the structure is provided as the input buffer for the ioctl the read & -// write caches will be enabled or disabled depending on the parameters -// provided. -// -// If the structure is provided as an output buffer for the ioctl the state -// of the read & write caches will be returned. If both input and outut buffers -// are provided the output buffer will contain the cache state BEFORE any -// changes are made - - -typedef enum { - EqualPriority, - KeepPrefetchedData, - KeepReadData -} DISK_CACHE_RETENTION_PRIORITY; - -#define FILE_DEVICE_DISK 0x00000007 -#define IOCTL_DISK_BASE FILE_DEVICE_DISK -#define IOCTL_DISK_GET_CACHE_INFORMATION CTL_CODE(IOCTL_DISK_BASE, 0x0035, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_DISK_SET_CACHE_INFORMATION CTL_CODE(IOCTL_DISK_BASE, 0x0036, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) - -typedef struct _DISK_CACHE_INFORMATION { - - // - // on return indicates that the device is capable of saving any parameters - // in non-volatile storage. On send indicates that the device should - // save the state in non-volatile storage. - // - - BOOLEAN ParametersSavable; - - // - // Indicates whether the write and read caches are enabled. - // - - BOOLEAN ReadCacheEnabled; - BOOLEAN WriteCacheEnabled; - - // - // Controls the likelyhood of data remaining in the cache depending on how - // it got there. Data cached from a READ or WRITE operation may be given - // higher, lower or equal priority to data entered into the cache for other - // means (like prefetch) - // - - DISK_CACHE_RETENTION_PRIORITY ReadRetentionPriority; - DISK_CACHE_RETENTION_PRIORITY WriteRetentionPriority; - - // - // Requests for a larger number of blocks than this may have prefetching - // disabled. If this value is set to 0 prefetch will be disabled. - // - - USHORT DisablePrefetchTransferLength; - - // - // If TRUE then ScalarPrefetch (below) will be valid. If FALSE then - // the minimum and maximum values should be treated as a block count - // (BlockPrefetch) - // - - BOOLEAN PrefetchScalar; - - // - // Contains the minimum and maximum amount of data which will be - // will be prefetched into the cache on a disk operation. This value - // may either be a scalar multiplier of the transfer length of the request, - // or an abolute number of disk blocks. PrefetchScalar (above) indicates - // which interpretation is used. - // - - union { - struct { - USHORT Minimum; - USHORT Maximum; - - // - // The maximum number of blocks which will be prefetched - useful - // with the scalar limits to set definite upper limits. - // - - USHORT MaximumBlocks; - } ScalarPrefetch; - - struct { - USHORT Minimum; - USHORT Maximum; - } BlockPrefetch; - }; - -} DISK_CACHE_INFORMATION, *PDISK_CACHE_INFORMATION; - +/* Got it from Bochs */ + +///////////////////////////////////////////////////////////////////////// +// $Id: scsidefs.h,v 1.2 2004/01/02 14:34:48 qbix79 Exp $ +///////////////////////////////////////////////////////////////////////// +// +// +// iodev/scsidefs.h +// $Id: scsidefs.h,v 1.2 2004/01/02 14:34:48 qbix79 Exp $ +// +// This file was copied from ... ? +// + +//*************************************************************************** +// +// Name: SCSIDEFS.H +// +// Description: SCSI definitions ('C' Language) +// +//*************************************************************************** + +//*************************************************************************** +// %%% TARGET STATUS VALUES %%% +//*************************************************************************** +#define STATUS_GOOD 0x00 // Status Good +#define STATUS_CHKCOND 0x02 // Check Condition +#define STATUS_CONDMET 0x04 // Condition Met +#define STATUS_BUSY 0x08 // Busy +#define STATUS_INTERM 0x10 // Intermediate +#define STATUS_INTCDMET 0x14 // Intermediate-condition met +#define STATUS_RESCONF 0x18 // Reservation conflict +#define STATUS_COMTERM 0x22 // Command Terminated +#define STATUS_QFULL 0x28 // Queue full + +//*************************************************************************** +// %%% SCSI MISCELLANEOUS EQUATES %%% +//*************************************************************************** +#define MAXLUN 7 // Maximum Logical Unit Id +#define MAXTARG 7 // Maximum Target Id +#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs +#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's + +//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// %%% SCSI COMMAND OPCODES %%% +// +///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +//*************************************************************************** +// %%% Commands for all Device Types %%% +//*************************************************************************** +#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_COPY 0x18 // Copy (O) +#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) +#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) +#define SCSI_LOG_SELECT 0x4C // Log Select (O) +#define SCSI_LOG_SENSE 0x4D // Log Sense (O) +#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) +#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) +#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) +#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) +#define SCSI_READ_BUFF 0x3C // Read Buffer (O) +#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) +#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) +#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) + +//*************************************************************************** +// %%% Commands Unique to Direct Access Devices %%% +//*************************************************************************** +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) +#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) +#define SCSI_PREFETCH 0x34 // Prefetch (O) +#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) +#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) +#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) +#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) +#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) +#define SCSI_READ_LONG 0x3E // Read Long (O) +#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) +#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) +#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) +#define SCSI_REZERO 0x01 // Rezero Unit (O) +#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) +#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) +#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) +#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) +#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) +#define SCSI_SET_LIMIT 0x33 // Set Limits (O) +#define SCSI_START_STP 0x1B // Start/Stop Unit (O) +#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) +#define SCSI_VERIFY 0x2F // Verify (O) +#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) +#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) +#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) +#define SCSI_WRITE_LONG 0x3F // Write Long (O) +#define SCSI_WRITE_SAME 0x41 // Write Same (O) + +//*************************************************************************** +// %%% Commands Unique to Sequential Access Devices %%% +//*************************************************************************** +#define SCSI_ERASE 0x19 // Erase (MANDATORY) +#define SCSI_LOAD_UN 0x1B // Load/Unload (O) +#define SCSI_LOCATE 0x2B // Locate (O) +#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) +#define SCSI_READ_POS 0x34 // Read Position (O) +#define SCSI_READ_REV 0x0F // Read Reverse (O) +#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) +#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) +#define SCSI_REWIND 0x01 // Rewind (MANDATORY) +#define SCSI_SPACE 0x11 // Space (MANDATORY) +#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) +#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) + +//*************************************************************************** +// %%% Commands Unique to Printer Devices %%% +//*************************************************************************** +#define SCSI_PRINT 0x0A // Print (MANDATORY) +#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) +#define SCSI_STOP_PNT 0x1B // Stop Print (O) +#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) + +//*************************************************************************** +// %%% Commands Unique to Processor Devices %%% +//*************************************************************************** +#define SCSI_RECEIVE 0x08 // Receive (O) +#define SCSI_SEND 0x0A // Send (O) + +//*************************************************************************** +// %%% Commands Unique to Write-Once Devices %%% +//*************************************************************************** +#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) +#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) +#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) +#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) +#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) +#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) +#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) +#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) +#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) +#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) +#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) +#define SCSI_WRITE12 0xAA // Write 12-Byte (O) +#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) +#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) + +//*************************************************************************** +// %%% Commands Unique to CD-ROM Devices %%% +//*************************************************************************** +#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) +#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) +#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) +#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) +#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) +#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) +#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) +#define SCSI_READHEADER 0x44 // Read Header (O) +#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) +#define SCSI_READ_TOC 0x43 // Read TOC (O) + +//*************************************************************************** +// %%% Commands Unique to Scanner Devices %%% +//*************************************************************************** +#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) +#define SCSI_GETWINDOW 0x25 // Get Window (O) +#define SCSI_OBJECTPOS 0x31 // Object Postion (O) +#define SCSI_SCAN 0x1B // Scan (O) +#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) + +//*************************************************************************** +// %%% Commands Unique to Optical Memory Devices %%% +//*************************************************************************** +#define SCSI_UpdateBlk 0x3D // Update Block (O) + +//*************************************************************************** +// %%% Commands Unique to Medium Changer Devices %%% +//*************************************************************************** +#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) +#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) +#define SCSI_POSTOELEM 0x2B // Position to Element (O) +#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) +#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) + +//*************************************************************************** +// %%% Commands Unique to Communication Devices %%% +//*************************************************************************** +#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) +#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) +#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) +#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) +#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) +#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) + +//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// %%% END OF SCSI COMMAND OPCODES %%% +// +///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +//*************************************************************************** +// %%% Request Sense Data Format %%% +//*************************************************************************** +typedef struct { + + BYTE ErrorCode; // Error Code (70H or 71H) + BYTE SegmentNum; // Number of current segment descriptor + BYTE SenseKey; // Sense Key(See bit definitions too) + BYTE InfoByte0; // Information MSB + BYTE InfoByte1; // Information MID + BYTE InfoByte2; // Information MID + BYTE InfoByte3; // Information LSB + BYTE AddSenLen; // Additional Sense Length + BYTE ComSpecInf0; // Command Specific Information MSB + BYTE ComSpecInf1; // Command Specific Information MID + BYTE ComSpecInf2; // Command Specific Information MID + BYTE ComSpecInf3; // Command Specific Information LSB + BYTE AddSenseCode; // Additional Sense Code + BYTE AddSenQual; // Additional Sense Code Qualifier + BYTE FieldRepUCode; // Field Replaceable Unit Code + BYTE SenKeySpec15; // Sense Key Specific 15th byte + BYTE SenKeySpec16; // Sense Key Specific 16th byte + BYTE SenKeySpec17; // Sense Key Specific 17th byte + BYTE AddSenseBytes; // Additional Sense Bytes + +} SENSE_DATA_FMT; + +//*************************************************************************** +// %%% REQUEST SENSE ERROR CODE %%% +//*************************************************************************** +#define SERROR_CURRENT 0x70 // Current Errors +#define SERROR_DEFERED 0x71 // Deferred Errors + +//*************************************************************************** +// %%% REQUEST SENSE BIT DEFINITIONS %%% +//*************************************************************************** +#define SENSE_VALID 0x80 // Byte 0 Bit 7 +#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 +#define SENSE_EOM 0x40 // Byte 2 Bit 6 +#define SENSE_ILI 0x20 // Byte 2 Bit 5 + +//*************************************************************************** +// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% +//*************************************************************************** +#define KEY_NOSENSE 0x00 // No Sense +#define KEY_RECERROR 0x01 // Recovered Error +#define KEY_NOTREADY 0x02 // Not Ready +#define KEY_MEDIUMERR 0x03 // Medium Error +#define KEY_HARDERROR 0x04 // Hardware Error +#define KEY_ILLGLREQ 0x05 // Illegal Request +#define KEY_UNITATT 0x06 // Unit Attention +#define KEY_DATAPROT 0x07 // Data Protect +#define KEY_BLANKCHK 0x08 // Blank Check +#define KEY_VENDSPEC 0x09 // Vendor Specific +#define KEY_COPYABORT 0x0A // Copy Abort +#define KEY_EQUAL 0x0C // Equal (Search) +#define KEY_VOLOVRFLW 0x0D // Volume Overflow +#define KEY_MISCOMP 0x0E // Miscompare (Search) +#define KEY_RESERVED 0x0F // Reserved + +//*************************************************************************** +// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% +//*************************************************************************** +#define DTYPE_DASD 0x00 // Disk Device +#define DTYPE_SEQD 0x01 // Tape Device +#define DTYPE_PRNT 0x02 // Printer +#define DTYPE_PROC 0x03 // Processor +#define DTYPE_WORM 0x04 // Write-once read-multiple +#define DTYPE_CROM 0x05 // CD-ROM device +#define DTYPE_CDROM 0x05 // CD-ROM device +#define DTYPE_SCAN 0x06 // Scanner device +#define DTYPE_OPTI 0x07 // Optical memory device +#define DTYPE_JUKE 0x08 // Medium Changer device +#define DTYPE_COMM 0x09 // Communications device +#define DTYPE_RESL 0x0A // Reserved (low) +#define DTYPE_RESH 0x1E // Reserved (high) +#define DTYPE_UNKNOWN 0x1F // Unknown or no device type + +//*************************************************************************** +// %%% ANSI APPROVED VERSION DEFINITIONS %%% +//*************************************************************************** +#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand +#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) +#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 +#define ANSI_RESLO 0x3 // Reserved (low) +#define ANSI_RESHI 0x7 // Reserved (high) diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 09311a5..4a37dba 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: dosbox.cpp,v 1.61 2004/02/02 15:42:38 harekiet Exp $ */ + #include #include #include @@ -38,6 +40,7 @@ #include "support.h" Config * control; +MachineType machine; /* The whole load of startups for all the subfunctions */ void MSG_Init(Section_prop *); @@ -110,10 +113,10 @@ static Bitu Normal_Loop(void) { if (ret>0) { Bitu blah=(*CallBack_Handlers[ret])(); if (blah) return blah; -#if C_DEBUG - if (DEBUG_ExitLoop()) return 0; -#endif } +#if C_DEBUG + if (DEBUG_ExitLoop()) return 0; +#endif } else { if (RemainTicks>0) { TIMER_AddTick(); @@ -127,7 +130,7 @@ increaseticks: if (NewTicks>LastTicks) { RemainTicks=NewTicks-LastTicks; if (RemainTicks>20) { -// LOG_DEBUG("Ticks to handle overflow %d",RemainTicks); +// LOG_MSG("Ticks to handle overflow %d",RemainTicks); RemainTicks=20; } LastTicks=NewTicks; @@ -162,6 +165,17 @@ static void DOSBOX_RealInit(Section * sec) { RemainTicks=0;LastTicks=GetTicks(); DOSBOX_SetLoop(&Normal_Loop); MSG_Init(section); + + machine=MCH_AUTO;std::string cmd_machine; + const char * mtype; + if (control->cmdline->FindString("-machine",cmd_machine,true)) mtype=cmd_machine.c_str(); + else mtype=section->Get_string("machine"); + if (strcasecmp(mtype,"cga")==0) machine=MCH_CGA; + else if (strcasecmp(mtype,"tandy")==0) machine=MCH_TANDY; + else if (strcasecmp(mtype,"hercules")==0) machine=MCH_HERC; + else if (strcasecmp(mtype,"vga")==0) machine=MCH_VGA; + else if (strcasecmp(mtype,"auto")==0) machine=MCH_AUTO; + else LOG_MSG("DOSBOX:Unknown machine type %s",mtype); } @@ -172,10 +186,13 @@ void DOSBOX_Init(void) { /* Setup all the different modules making up DOSBox */ secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit); - secprop->Add_string("language",""); + secprop->Add_string("language",""); + secprop->Add_string("machine","auto"); + #if C_DEBUG LOG_StartUp(); #endif + secprop->AddInitFunction(&IO_Init); secprop->AddInitFunction(&PAGING_Init); secprop->AddInitFunction(&MEM_Init); @@ -190,24 +207,38 @@ void DOSBOX_Init(void) { MSG_Add("DOSBOX_CONFIGFILE_HELP", "language -- Select another language file.\n" "memsize -- Amount of memory dosbox has in megabytes.\n" + "machine -- The type of machine tries to emulate:auto,hercules,cga,tandy,vga.\n" + " Try a specific type if your game has problems with auto.\n" ); secprop=control->AddSection_prop("render",&RENDER_Init); secprop->Add_int("frameskip",0); secprop->Add_string("snapdir","snaps"); + secprop->Add_bool("aspect",false); secprop->Add_string("scaler","normal2x"); MSG_Add("RENDER_CONFIGFILE_HELP", "frameskip -- How many frames dosbox skips before drawing one.\n" "snapdir -- Directory where screenshots get saved.\n" + "aspect -- Do aspect correction.\n" "scaler -- Scaler used to enlarge/enhance low resolution modes.\n" " Supported are none,normal2x,advmame2x\n" ); secprop=control->AddSection_prop("cpu",&CPU_Init); - secprop->Add_int("cycles",1800); + secprop->Add_string("core","normal"); + secprop->Add_int("cycles",2500); + secprop->Add_int("cycleup",500); + secprop->Add_int("cycledown",20); MSG_Add("CPU_CONFIGFILE_HELP", - "cycles -- Amount of instructions dosbox tries to emulate each millsecond.\n" + "core -- CPU Core used in emulation: normal,full" +#if (C_DYNAMIC_X86) + ",dynamic" +#endif + ".\n" + "cycles -- Amount of instructions dosbox tries to emulate each millisecond.\n" " Setting this higher than your machine can handle is bad!\n" + "cycleup -- Amount of cycles to increase/decrease with keycombo.\n" + "cycledown Setting it lower than 100 will be a percentage.\n" ); #if C_FPU secprop->AddInitFunction(&FPU_Init); @@ -223,7 +254,7 @@ void DOSBOX_Init(void) { secprop->Add_int("rate",22050); secprop->Add_int("blocksize",2048); secprop->Add_string("wavedir","waves"); - + MSG_Add("MIXER_CONFIGFILE_HELP", "nosound -- Enable silent mode, sound is still emulated though.\n" "rate -- Mixer sample rate, setting any devices higher than this will\n" @@ -239,7 +270,7 @@ void DOSBOX_Init(void) { secprop->Add_bool("mpu401",true); secprop->Add_string("device","default"); secprop->Add_string("config",""); - + MSG_Add("MIDI_CONFIGFILE_HELP", "mpu401 -- Enable MPU-401 Emulation.\n" "device -- Device that will receive the MIDI data from MPU-401.\n" @@ -260,6 +291,7 @@ void DOSBOX_Init(void) { secprop->AddInitFunction(&ADLIB_Init); secprop->Add_bool("adlib",true); secprop->Add_int("adlibrate",22050); + secprop->Add_string("adlibmode","adlib"); secprop->AddInitFunction(&CMS_Init); secprop->Add_bool("cms",false); secprop->Add_int("cmsrate",22050); @@ -275,6 +307,27 @@ void DOSBOX_Init(void) { "cmsrate -- Sample rate of cms emulation.\n" ); + secprop=control->AddSection_prop("gus",&GUS_Init); + secprop->Add_bool("gus",true); + secprop->Add_int("rate",22050); + secprop->Add_hex("base",0x240); + secprop->Add_int("irq1",5); + secprop->Add_int("irq2",5); + secprop->Add_int("dma1",3); + secprop->Add_int("dma2",3); + secprop->Add_string("ultradir","C:\\ULTRASND"); + + MSG_Add("GUS_CONFIGFILE_HELP", + "gus -- Enable the Gravis Ultrasound emulation.\n" + "base,irq1,irq2,dma1,dma2 -- The IO/IRQ/DMA addresses of the \n" + " Gravis Ultrasound. (Same IRQ's and DMA's are OK.)\n" + "rate -- Sample rate of Ultrasound emulation.\n" + "ultradir -- Path to Ultrasound directory. In this directory\n" + " there should be a MIDI directory that contains\n" + " the patch files for GUS playback. Patch sets used\n" + " with Timidity should work fine.\n" + ); + secprop=control->AddSection_prop("speaker",&PCSPEAKER_Init); secprop->Add_bool("pcspeaker",true); secprop->Add_int("pcrate",22050); @@ -284,7 +337,7 @@ void DOSBOX_Init(void) { secprop->AddInitFunction(&DISNEY_Init); secprop->Add_bool("disney",true); - MSG_Add("SPEAKER_CONFIGFILE_HELP", + MSG_Add("SPEAKER_CONFIGFILE_HELP", "pcspeaker -- Enable PC-Speaker emulation.\n" "pcrate -- Sample rate of the PC-Speaker sound generation.\n" "tandy -- Enable Tandy 3-Voice emulation.\n" @@ -301,15 +354,18 @@ void DOSBOX_Init(void) { secprop->Add_bool("xms",true); secprop->AddInitFunction(&EMS_Init); secprop->Add_bool("ems",true); +#if (C_DEBUG) secprop->AddInitFunction(&DPMI_Init); - secprop->Add_bool("dpmi",true); - + secprop->Add_bool("dpmi",false); +#endif MSG_Add("DOS_CONFIGFILE_HELP", "xms -- Enable XMS support.\n" "ems -- Enable EMS support.\n" +#if (C_DEBUG) "dpmi -- Enable builtin DPMI host support.\n" " This might help in getting some games to work, but might crash others.\n" " So be sure to try both settings.\n" +#endif ); // Mscdex secprop->AddInitFunction(&MSCDEX_Init); @@ -326,7 +382,8 @@ void DOSBOX_Init(void) { "listenport -- TCP Port the momdem listens on for incoming connections.\n" ); #endif - + + secline=control->AddSection_line("autoexec",&AUTOEXEC_Init); MSG_Add("AUTOEXEC_CONFIGFILE_HELP", diff --git a/src/fpu/Makefile.in b/src/fpu/Makefile.in index a9c3142..40b0e40 100644 --- a/src/fpu/Makefile.in +++ b/src/fpu/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -313,7 +313,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -333,7 +333,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -358,7 +357,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/fpu/fpu.cpp b/src/fpu/fpu.cpp index 1012d2f..e63a9e5 100644 --- a/src/fpu/fpu.cpp +++ b/src/fpu/fpu.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: fpu.cpp,v 1.17 2004/01/19 18:54:15 qbix79 Exp $ */ + #include "dosbox.h" #if C_FPU @@ -258,6 +260,13 @@ void FPU_ESC1_Normal(Bitu rm) { case 0x01: /* FXCH STi */ FPU_FXCH(TOP,ST(sub)); break; + case 0x02: /* FNOP */ + FPU_FNOP(); + break; + case 0x03: /* FSTP STi */ + FPU_FST(TOP,ST(sub)); + FPU_FPOP(); + break; case 0x04: switch(sub){ case 0x00: /* FCHS */ @@ -375,7 +384,7 @@ void FPU_ESC1_Normal(Bitu rm) { void FPU_ESC2_EA(Bitu rm,PhysPt addr) { /* 32 bits integer operants */ Bit32s blah = mem_readd(addr); - fpu.regs[8].d = static_cast(blah); + fpu.regs[8].d = static_cast(blah); EATREE(rm); } @@ -453,8 +462,7 @@ void FPU_ESC3_Normal(Bitu rm) { void FPU_ESC4_EA(Bitu rm,PhysPt addr) { - /* REGULAR TREE WITH 64 BITS REALS ? double ? */ -// E_Exit("how to load a double in esc 4 ea"); + /* REGULAR TREE WITH 64 BITS REALS: double */ fpu.regs[8].l.lower=mem_readd(addr); fpu.regs[8].l.upper=mem_readd(addr+4); EATREE(rm); @@ -478,16 +486,16 @@ void FPU_ESC4_Normal(Bitu rm) { FPU_FCOM(TOP,ST(sub)); FPU_FPOP(); break; - case 0x04: /* FSUBRP STi,ST*/ + case 0x04: /* FSUBR STi,ST*/ FPU_FSUBR(ST(sub),TOP); break; - case 0x05: /* FSUBP STi,ST*/ + case 0x05: /* FSUB STi,ST*/ FPU_FSUB(ST(sub),TOP); break; - case 0x06: /* FDIVRP STi,ST*/ + case 0x06: /* FDIVR STi,ST*/ FPU_FDIVR(ST(sub),TOP); break; - case 0x07: /* FDIVP STi,ST*/ + case 0x07: /* FDIV STi,ST*/ FPU_FDIV(ST(sub),TOP); break; default: @@ -564,7 +572,7 @@ void FPU_ESC5_Normal(Bitu rm) { void FPU_ESC6_EA(Bitu rm,PhysPt addr) { /* 16 bit (word integer) operants */ Bit16s blah = mem_readw(addr); - fpu.regs[8].d = static_cast(blah); + fpu.regs[8].d = static_cast(blah); EATREE(rm); } @@ -620,7 +628,7 @@ void FPU_ESC7_EA(Bitu rm,PhysPt addr) { case 0x00: /* FILD Bit16s */ { Bit16s blah = mem_readw(addr); - FPU_PUSH( static_cast(blah)); + FPU_PUSH( static_cast(blah)); } break; case 0x01: /* FISTTP Bit16s */ @@ -634,18 +642,25 @@ void FPU_ESC7_EA(Bitu rm,PhysPt addr) { mem_writew(addr,static_cast(FROUND(fpu.regs[TOP].d))); FPU_FPOP(); break; - case 0x05: /* FILD Bit32s */ + case 0x05: /* FILD Bit64s */ { - Bit32s blah = mem_readd(addr); - FPU_PUSH( static_cast(blah)); + FPU_Reg blah; + blah.l.lower = mem_readd(addr); + blah.l.upper = mem_readd(addr+4); + FPU_PUSH(static_cast(blah.ll)); } break; case 0x06: /* FBSTP packed BCD */ FPU_FBST(addr); FPU_FPOP(); break; - case 0x07: /* FISTP Bit32s */ - mem_writed(addr,static_cast(FROUND(fpu.regs[TOP].d))); + case 0x07: /* FISTP Bit64s */ + { + FPU_Reg blah; + blah.ll = static_cast(FROUND(fpu.regs[TOP].d)); + mem_writed(addr,blah.l.lower); + mem_writed(addr+4,blah.l.upper); + } FPU_FPOP(); break; case 0x04: /* FBLD packed BCD */ @@ -660,6 +675,14 @@ void FPU_ESC7_Normal(Bitu rm) { Bitu group=(rm >> 3) & 7; Bitu sub=(rm & 7); switch (group){ + case 0x01: /* FXCH STi*/ + FPU_FXCH(TOP,ST(sub)); + break; + case 0x02: /* FSTP STi*/ + case 0x03: /* FSTP STi*/ + FPU_FST(TOP,ST(sub)); + FPU_FPOP(); + break; case 0x04: switch(sub){ case 0x00: /* FNSTSW AX*/ diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h index 217b391..f681b80 100644 --- a/src/fpu/fpu_instructions.h +++ b/src/fpu/fpu_instructions.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: fpu_instructions.h,v 1.13 2003/10/07 10:42:01 qbix79 Exp $ */ +/* $Id: fpu_instructions.h,v 1.16 2004/01/11 09:41:52 qbix79 Exp $ */ static void FPU_FINIT(void) { @@ -96,7 +96,7 @@ static void FPU_FSQRT(void){ return; } static void FPU_FPATAN(void){ - fpu.regs[ST(1)].d = atan(fpu.regs[ST(1)].d/fpu.regs[TOP].d); + fpu.regs[ST(1)].d = atan2(fpu.regs[ST(1)].d,fpu.regs[TOP].d); FPU_FPOP(); FPU_SET_C2(0); //flags and such :) @@ -199,10 +199,11 @@ static double FROUND(double in){ static void FPU_FPREM(void){ Real64 valtop = fpu.regs[TOP].d; Real64 valdiv = fpu.regs[ST(1)].d; - Real64 res = floor(valtop/valdiv); - Bit64s ressaved = static_cast(res); - res=valtop - res*valdiv; - fpu.regs[TOP].d = res; + Bit64s ressaved = static_cast( (valtop/valdiv) ); +// Some backups +// Real64 res=valtop - ressaved*valdiv; +// res= fmod(valtop,valdiv); + fpu.regs[TOP].d = valtop - ressaved*valdiv; FPU_SET_C0(static_cast(ressaved&4)); FPU_SET_C3(static_cast(ressaved&2)); FPU_SET_C1(static_cast(ressaved&1)); @@ -309,13 +310,13 @@ static void FPU_F2XM1(void){ return; } -static void FPU_FYL2X(void){ +static void FPU_FYL2X(void){ fpu.regs[ST(1)].d*=log(fpu.regs[TOP].d)/log(static_cast(2.0)); FPU_FPOP(); return; } static void FPU_FSCALE(void){ - fpu.regs[TOP].d *=pow(2.0,static_cast(static_cast(FROUND(fpu.regs[ST(1)].d)))); + fpu.regs[TOP].d *= pow(2.0,static_cast(static_cast(fpu.regs[ST(1)].d))); return; //2^x where x is chopped. } diff --git a/src/fpu/fpu_types.h b/src/fpu/fpu_types.h index c459feb..e229571 100644 --- a/src/fpu/fpu_types.h +++ b/src/fpu/fpu_types.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index fafd8e7..0aea374 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -1,6 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libgui.a -libgui_a_SOURCES = sdlmain.cpp render.cpp render_normal.h render_scale2x.h \ +libgui_a_SOURCES = sdlmain.cpp \ + render.cpp render_normal.h render_scale2x.h render_templates.h \ midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h diff --git a/src/gui/Makefile.in b/src/gui/Makefile.in index ada1052..eab517b 100644 --- a/src/gui/Makefile.in +++ b/src/gui/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -132,7 +132,8 @@ target_vendor = @target_vendor@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libgui.a -libgui_a_SOURCES = sdlmain.cpp render.cpp render_normal.h render_scale2x.h \ +libgui_a_SOURCES = sdlmain.cpp \ + render.cpp render_normal.h render_scale2x.h render_templates.h \ midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h subdir = src/gui @@ -318,7 +319,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -338,7 +339,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -363,7 +363,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp index 8145d7b..bbbb2d9 100644 --- a/src/gui/midi.cpp +++ b/src/gui/midi.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/gui/midi_alsa.h b/src/gui/midi_alsa.h index 9f13a65..a3e6a5d 100644 --- a/src/gui/midi_alsa.h +++ b/src/gui/midi_alsa.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,12 +16,16 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: midi_alsa.h,v 1.7 2004/01/26 15:10:16 qbix79 Exp $ */ + +#define ALSA_PCM_OLD_HW_PARAMS_API +#define ALSA_PCM_OLD_SW_PARAMS_API #include #include #define ADDR_DELIM ".:" -#if SND_LIB_MINOR >= 6 +#if ((SND_LIB_MINOR >= 6) && (SND_LIB_MAJOR == 0)) || (SND_LIB_MAJOR >= 1) #define snd_seq_flush_output(x) snd_seq_drain_output(x) #define snd_seq_set_client_group(x,name) /*nop */ #define my_snd_seq_open(seqp) snd_seq_open(seqp, "hw", SND_SEQ_OPEN_OUTPUT, 0) @@ -104,6 +108,10 @@ public: snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]); send_event(0); break; + case 0xD0: + snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]); + send_event(0); + break; case 0xE0:{ long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000; snd_seq_ev_set_pitchbend(&ev, chanID, theBend); diff --git a/src/gui/midi_coreaudio.h b/src/gui/midi_coreaudio.h index 8b95418..0d7f963 100644 --- a/src/gui/midi_coreaudio.h +++ b/src/gui/midi_coreaudio.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/gui/midi_oss.h b/src/gui/midi_oss.h index 65500a6..62e1dfa 100644 --- a/src/gui/midi_oss.h +++ b/src/gui/midi_oss.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/gui/midi_win32.h b/src/gui/midi_win32.h index bdac5de..b08652b 100644 --- a/src/gui/midi_win32.h +++ b/src/gui/midi_win32.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/gui/render.cpp b/src/gui/render.cpp index c0cbf0d..b059c91 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,10 +16,12 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: render.cpp,v 1.19 2003/10/15 08:20:50 harekiet Exp $ */ +/* $Id: render.cpp,v 1.25 2004/01/31 22:38:27 harekiet Exp $ */ #include #include +#include +#include #include "dosbox.h" #include "video.h" @@ -29,7 +31,8 @@ #include "cross.h" #include "support.h" -#define MAX_RES 2048 +#define RENDER_MAXWIDTH 1280 +#define RENDER_MAXHEIGHT 1024 struct PalData { struct { @@ -43,6 +46,7 @@ struct PalData { union { Bit32u bpp32[256]; Bit16u bpp16[256]; + Bit32u yuv[256]; } lookup; }; @@ -53,43 +57,54 @@ static struct { Bitu height; Bitu bpp; Bitu pitch; - Bitu flags; - float ratio; - RENDER_Draw_Handler draw_handler; + Bitu scalew; + Bitu scaleh; + double ratio; } src; struct { Bitu width; Bitu height; Bitu pitch; - Bitu bpp; /* The type of BPP the operation requires for input */ + Bitu line; + Bitu bpp; RENDER_Operation type; RENDER_Operation want_type; - RENDER_Part_Handler part_handler; - void * dest; - void * buffer; - void * pixels; + RENDER_Line_Handler line_handler; + Bit8u * draw; + Bit8u * buffer; + Bit8u * pixels; } op; struct { Bitu count; Bitu max; } frameskip; - Bitu flags; PalData pal; + struct { + Bit8u hlines[RENDER_MAXHEIGHT]; + } normal; #if (C_SSHOT) struct { RENDER_Operation type; - Bitu pitch; + Bitu bpp,width,height,line; const char * dir; + Bit8u * buffer,* draw; + bool usesrc; } shot; #endif - bool screenshot; bool active; + bool aspect; + bool updating; } render; +Bit8u render_line_cache[4][RENDER_MAXWIDTH*4]; //Bit32u pixels +RENDER_Line_Handler RENDER_DrawLine; +Bit8u * RENDER_TempLine; + /* Forward declerations */ static void RENDER_ResetPal(void); /* Include the different rendering routines */ +#include "render_templates.h" #include "render_normal.h" #include "render_scale2x.h" @@ -97,6 +112,13 @@ static void RENDER_ResetPal(void); #if (C_SSHOT) #include +static void RENDER_ShotDraw(Bit8u * src) { + if (render.shot.usesrc) { + memcpy(render.shot.draw,src,render.shot.line); + render.shot.draw+=render.shot.line; + } else render.op.line_handler(src); +} + /* Take a screenshot of the data that should be rendered */ static void TakeScreenShot(Bit8u * bitmap) { Bitu last=0;char file_name[CROSS_LEN]; @@ -153,8 +175,8 @@ static void TakeScreenShot(Bit8u * bitmap) { png_set_compression_method(png_ptr, 8); png_set_compression_buffer_size(png_ptr, 8192); - if (render.src.bpp==8) { - png_set_IHDR(png_ptr, info_ptr, render.src.width, render.src.height, + if (render.shot.bpp==8) { + png_set_IHDR(png_ptr, info_ptr, render.shot.width, render.shot.height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); for (i=0;i<256;i++) { @@ -164,14 +186,14 @@ static void TakeScreenShot(Bit8u * bitmap) { } png_set_PLTE(png_ptr, info_ptr, palette,256); } else { - png_set_IHDR(png_ptr, info_ptr, render.src.width, render.src.height, - 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + png_set_IHDR(png_ptr, info_ptr, render.shot.width, render.shot.height, + render.shot.bpp, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } /*Allocate an array of scanline pointers*/ - row_pointers=(png_bytep*)malloc(render.src.height*sizeof(png_bytep)); - for (i=0;irender.pal.last) return; + Bitu i; switch (render.op.bpp) { case 8: GFX_SetPalette(render.pal.first,render.pal.last-render.pal.first+1,(GFX_PalEntry *)&render.pal.rgb[render.pal.first]); break; case 16: - for (;render.pal.first<=render.pal.last;render.pal.first++) { - render.pal.lookup.bpp16[render.pal.first]=GFX_GetRGB( - render.pal.rgb[render.pal.first].red, - render.pal.rgb[render.pal.first].green, - render.pal.rgb[render.pal.first].blue); + for (i=render.pal.first;i<=render.pal.last;i++) { + Bit8u r=render.pal.rgb[i].red; + Bit8u g=render.pal.rgb[i].green; + Bit8u b=render.pal.rgb[i].blue; + render.pal.lookup.bpp16[i]=GFX_GetRGB(r,g,b); } break; + case 24: case 32: - for (;render.pal.first<=render.pal.last;render.pal.first++) { - render.pal.lookup.bpp32[render.pal.first]= - GFX_GetRGB( - render.pal.rgb[render.pal.first].red, - render.pal.rgb[render.pal.first].green, - render.pal.rgb[render.pal.first].blue); + for (i=render.pal.first;i<=render.pal.last;i++) { + Bit8u r=render.pal.rgb[i].red; + Bit8u g=render.pal.rgb[i].green; + Bit8u b=render.pal.rgb[i].blue; + render.pal.lookup.bpp32[i]=GFX_GetRGB(r,g,b); } break; - }; + } /* Setup pal index to startup values */ render.pal.first=256; render.pal.last=0; @@ -241,141 +263,206 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) { if (render.pal.last1.0) gfx_scaleh*=render.src.ratio; + else gfx_scalew*=(1/render.src.ratio); + + Bitu gfx_flags; + Bitu bpp=GFX_GetBestMode(render.src.bpp,gfx_flags); + Bitu index; + switch (bpp) { + case 8: index=0;break; + case 16:index=1;break; + case 24:index=2;break; + case 32:index=3;break; + } + /* Initial scaler testing */ + switch (render.op.want_type) { + case OP_Normal2x: + case OP_None: + render.op.type=render.op.want_type; +normalop: + if (gfx_flags & GFX_HASSCALING) { + gfx_scalew*=scalew; + gfx_scaleh*=scaleh; + render.op.line_handler=Normal_8[index]; + for (Bitu i=0;i1 && (render.op.type==OP_None)) { + render.op.line_handler=Normal_8[index]; + scalew>>=1;gfx_scaleh/=2; + } else { + render.op.line_handler=Normal_2x_8[index]; + } + } else render.op.line_handler=Normal_8[index]; + width*=scalew; + double lines=0.0; + height=0; + for (Bitu i=0;i0) ? temp_lines-1 : 0; + height+=temp_lines; + } + } + break; + case OP_AdvMame2x: + if (scalew!=2){ + render.op.type=OP_Normal2x; + goto normalop; + } + if (gfx_flags & GFX_HASSCALING) { + height=scaleh*height; + } else { + height=(Bitu)(gfx_scaleh*scaleh*height); + } + width<<=1; + { + Bits i; + double src_add=(double)height/(double)render.src.height; + double src_index=0; + double src_lines=0; + Bitu src_done=0; + Bitu height=0; + am2x.cmd_index=am2x.cmd_data; + am2x.buf_pos=0;am2x.buf_used=0; + for (i=0;i<=(Bits)render.src.height;i++) { + src_lines+=src_add; + Bitu lines=(Bitu)src_lines; + src_lines-=lines; + switch (lines) { + case 0: + break; + case 1: + AdvMame2x_AddLine(i,i,i); + break; + case 2: + AdvMame2x_AddLine(i-1,i,i+1); + AdvMame2x_AddLine(i+1,i,i-1); + break; + default: + AdvMame2x_AddLine(i-1,i,i+1); + for (lines-=2;lines>0;lines--) AdvMame2x_AddLine(i,i,i); + AdvMame2x_AddLine(i+1,i,i-1); + break; + } + AdvMame2x_CheckLines(i); + } + render.op.line_handler=AdvMame2x_8_Table[index]; + } + break; + } + render.op.bpp=bpp; render.op.width=width; render.op.height=height; - render.op.bpp=bpp; - render.op.pitch=pitch; - render.op.type=OP_Blit; - render.op.part_handler=GFX_Render_Blit; + GFX_SetSize(width,height,bpp,gfx_scalew,gfx_scaleh,&RENDER_ReInit); RENDER_ResetPal(); + render.active=true; } -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags,RENDER_Draw_Handler draw_handler) { +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,double ratio,Bitu scalew,Bitu scaleh) { if ((!width) || (!height) || (!pitch)) { - render.active=false;return; + render.active=false; + return; } - GFX_Stop(); render.src.width=width; render.src.height=height; render.src.bpp=bpp; render.src.pitch=pitch; - render.src.ratio=ratio; - render.src.flags=flags; - render.src.draw_handler=draw_handler; - - GFX_ModeCallBack mode_callback=0; - switch (render.op.want_type) { - - case OP_None: -normalop: - switch (render.src.flags) { - case DoubleNone: - flags=0; - break; - case DoubleWidth: - width*=2; - flags=GFX_SHADOW; - break; - case DoubleHeight: - height*=2; - flags=0; - break; - case DoubleBoth: - render.src.flags=0; - flags=0; - break; - } - mode_callback=Render_Normal_CallBack; - break; - case OP_Normal2x: - switch (render.src.flags) { - case DoubleBoth: - width*=2;height*=2; - flags=GFX_SHADOW; - mode_callback=Render_Normal_CallBack; - break; - default: - goto normalop; - } - break; - case OP_AdvMame2x: - switch (render.src.flags) { - case DoubleBoth: - mode_callback=Render_Scale2x_CallBack; - width*=2;height*=2; -#if defined (SCALE2X_MMX) - flags=GFX_SHADOW; -#else - flags=GFX_SHADOW; -#endif - break; - default: - goto normalop; - } - - break; - default: - goto normalop; - - } - GFX_SetSize(width,height,bpp,flags,mode_callback,RENDER_DrawScreen); - GFX_Start(); + render.src.ratio=render.aspect ? ratio : 1.0; + render.src.scalew=scalew; + render.src.scaleh=scaleh; + RENDER_ReInit(); } extern void GFX_SetTitle(Bits cycles, Bits frameskip); @@ -396,10 +483,13 @@ void RENDER_Init(Section * sec) { render.pal.first=256; render.pal.last=0; + render.aspect=section->Get_bool("aspect"); render.frameskip.max=section->Get_int("frameskip"); render.frameskip.count=0; + render.updating=true; #if (C_SSHOT) render.shot.dir=section->Get_string("snapdir"); + render.shot.usesrc=true; KEYBOARD_AddEvent(KBD_f5,KBD_MOD_CTRL,EnableScreenShot); #endif const char * scaler;std::string cline; diff --git a/src/gui/render_normal.h b/src/gui/render_normal.h index 32e131a..95ae4ea 100644 --- a/src/gui/render_normal.h +++ b/src/gui/render_normal.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,166 +16,44 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define LOOPSIZE 4 +static Bit8u normal_cache[RENDER_MAXWIDTH*2*4]; -#define SIZE_8 1 -#define SIZE_16 2 -#define SIZE_32 4 - -#define MAKE_8(FROM) Bit8u val=*(Bit8u *)(FROM); -#define MAKE_16(FROM) Bit16u val=render.pal.lookup.bpp16[*(Bit8u *)(FROM)]; -#define MAKE_32(FROM) Bit32u val=render.pal.lookup.bpp32[*(Bit8u *)(FROM)]; - -#define SAVE_8(WHERE) *(Bit8u *)(WHERE)=val; -#define SAVE_16(WHERE) *(Bit16u *)(WHERE)=val; -#define SAVE_32(WHERE) *(Bit32u *)(WHERE)=val; - -#define LINES_DN 1 -#define LINES_DW 1 -#define LINES_DH 2 -#define LINES_DB 2 - -#define PIXELS_DN 1 -#define PIXELS_DW 2 -#define PIXELS_DH 1 -#define PIXELS_DB 2 - -#define NORMAL_DN(BPP,FROM,DEST) \ - MAKE_ ## BPP(FROM); \ - SAVE_ ## BPP(DEST); \ - -#define NORMAL_DW(BPP,FROM,DEST) \ - MAKE_ ## BPP (FROM); \ - SAVE_ ## BPP (DEST); \ - SAVE_ ## BPP (DEST + SIZE_ ## BPP); \ - -#define NORMAL_DH(BPP,FROM,DEST) \ - MAKE_ ## BPP (FROM); \ - SAVE_ ## BPP (DEST); \ - SAVE_ ## BPP ((DEST) + render.op.pitch); \ - - -#define NORMAL_DB(BPP,FROM,DEST) \ - MAKE_ ## BPP (FROM); \ - SAVE_ ## BPP (DEST); \ - SAVE_ ## BPP ((DEST)+SIZE_ ## BPP ); \ - SAVE_ ## BPP ((DEST)+render.op.pitch ); \ - SAVE_ ## BPP ((DEST)+render.op.pitch+SIZE_ ## BPP ); \ - - -#define NORMAL_LOOP(COUNT,FUNC,BPP) \ - if (COUNT>0) {NORMAL_ ## FUNC (BPP,(src+0),(dest+0 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ - if (COUNT>1) {NORMAL_ ## FUNC (BPP,(src+1),(dest+1 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ - if (COUNT>2) {NORMAL_ ## FUNC (BPP,(src+2),(dest+2 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ - if (COUNT>3) {NORMAL_ ## FUNC (BPP,(src+3),(dest+3 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ - if (COUNT>4) {NORMAL_ ## FUNC (BPP,(src+4),(dest+4 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ - if (COUNT>5) {NORMAL_ ## FUNC (BPP,(src+5),(dest+5 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ - if (COUNT>6) {NORMAL_ ## FUNC (BPP,(src+6),(dest+6 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ - if (COUNT>7) {NORMAL_ ## FUNC (BPP,(src+7),(dest+7 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ - -#define MAKENORMAL(FUNC,BPP) \ -static void Normal_ ## FUNC ## _ ##BPP(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { \ - Bit8u * dest=(Bit8u *)render.op.pixels+y*LINES_ ## FUNC*render.op.pitch+x*PIXELS_ ## FUNC * SIZE_ ## BPP; \ - Bitu next_src=render.src.pitch-dx; \ - Bitu next_dest=(LINES_ ## FUNC*render.op.pitch) - (dx*PIXELS_ ## FUNC * SIZE_ ## BPP); \ - dx/=LOOPSIZE; \ - for (;dy>0;dy--) { \ - for (Bitu tempx=dx;tempx>0;tempx--) { \ - NORMAL_LOOP(LOOPSIZE,FUNC,BPP); \ - src+=LOOPSIZE;dest+=LOOPSIZE*PIXELS_ ## FUNC * SIZE_ ## BPP; \ - } \ - src+=next_src;dest+=next_dest; \ - } \ -} - -MAKENORMAL(DW,8); -MAKENORMAL(DB,8); - -MAKENORMAL(DN,16); -MAKENORMAL(DW,16); -MAKENORMAL(DH,16); -MAKENORMAL(DB,16); - -MAKENORMAL(DN,32); -MAKENORMAL(DW,32); -MAKENORMAL(DH,32); -MAKENORMAL(DB,32); - -/* Special versions for the 8-bit ones that can do direct line copying */ - -static void Normal_DN_8(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=render.op.pitch-dx; - Bitu rem=dx&3;dx>>=2; - for (;dy>0;dy--) { - Bitu tempx; - for (tempx=dx;tempx>0;tempx--) { - Bit32u temp=*(Bit32u *)src;src+=4; - *(Bit32u *)dest=temp; - dest+=4; +template +static void Normal(Bit8u * src) { + Bitu line_size=LineSize(render.src.width) * (xdouble ? 2 : 1); + Bit8u * line; + if (sbpp == dbpp && !xdouble) { + line=src; + BituMove(render.op.pixels,line,line_size); + } else { + Bit8u * line_dst=&normal_cache[0]; + Bit8u * real_dst=render.op.pixels; + line=line_dst; + Bit8u * temp_src=src; + for (Bitu tempx=render.src.width;tempx;tempx--) { + Bitu val=ConvBPP(LoadSrc(temp_src)); + AddDst(line_dst,val); + AddDst(real_dst,val); + if (xdouble) { + AddDst(line_dst,val); + AddDst(real_dst,val); + } } - for (tempx=rem;tempx>0;tempx--) { - *dest++=*src++; - } - src+=next_src;dest+=next_dest; + } + render.op.pixels+=render.op.pitch; + for (Bitu lines=render.normal.hlines[render.op.line++];lines;lines--) { + BituMove(render.op.pixels,line,line_size); + render.op.pixels+=render.op.pitch; } } -static void Normal_DH_8(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch+x; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=(2*render.op.pitch)-dx; - Bitu rem=dx&3;dx>>=2; - for (;dy>0;dy--) { - Bitu tempx; - for (tempx=dx;tempx>0;tempx--) { - Bit32u temp=*(Bit32u *)src;src+=4; - *(Bit32u *)dest=temp; - *(Bit32u *)(dest+render.op.pitch)=temp; - dest+=4; - } - for (tempx=rem;tempx>0;tempx--) { - *dest=*src; - *(dest+render.op.pitch)=*src; - dest++; - } - src+=next_src;dest+=next_dest; - } -} -static RENDER_Part_Handler Render_Normal_8_Table[4]= { - Normal_DN_8,Normal_DW_8,Normal_DH_8,Normal_DB_8, +static RENDER_Line_Handler Normal_8[4]={ + Normal<8,8 ,false>,Normal<8,16,false>, + Normal<8,24,false>,Normal<8,32,false>, }; -static RENDER_Part_Handler Render_Normal_16_Table[4]= { - Normal_DN_16,Normal_DW_16,Normal_DH_16,Normal_DB_16, +static RENDER_Line_Handler Normal_2x_8[4]={ + Normal<8,8 ,true>,Normal<8,16,true>, + Normal<8,24,true>,Normal<8,32,true>, }; - -static RENDER_Part_Handler Render_Normal_32_Table[4]= { - Normal_DN_32,Normal_DW_32,Normal_DH_32,Normal_DB_32, -}; - -static void Render_Normal_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags) { - if (!(flags & MODE_SET)) return; - render.op.width=width; - render.op.height=height; - render.op.bpp=bpp; - render.op.pitch=pitch; - render.op.type=OP_None; - switch (bpp) { - case 8: - render.op.part_handler=Render_Normal_8_Table[render.src.flags]; - break; - case 16: - render.op.part_handler=Render_Normal_16_Table[render.src.flags]; - break; - case 32: - render.op.part_handler=Render_Normal_32_Table[render.src.flags]; - break; - default: - E_Exit("RENDER:Unsupported display depth of %d",bpp); - break; - } - RENDER_ResetPal(); -} diff --git a/src/gui/render_scale2x.h b/src/gui/render_scale2x.h index 979b9dc..00705f4 100644 --- a/src/gui/render_scale2x.h +++ b/src/gui/render_scale2x.h @@ -29,531 +29,90 @@ */ /* - * This file contains a C and MMX implentation of the Scale2x effect. - * - * You can found an high level description of the effect at : - * + * This algorithm was based on the scale2x/advmame2x effect. * http://scale2x.sourceforge.net/scale2x.html - * - * Alternatively at the previous license terms, you are allowed to use this - * code in your program with these conditions: - * - the program is not used in commercial activities. - * - the whole source code of the program is released with the binary. - * - derivative works of the program are allowed. - */ - -/* - * Made some changes to only support the 8-bit version. - * Also added mulitple destination bpp targets. */ #ifndef __SCALE2X_H #define __SCALE2X_H -#include +#define AM2XBUF 16 -/***************************************************************************/ -/* basic types */ +static struct { + Bits buf[AM2XBUF][4]; + Bitu buf_used;Bitu buf_pos; + Bit8u cmd_data[4096]; //1024 lines should be enough? + Bit8u * cmd_index; + Bit8u * cache[4]; + Bitu cache_index; +} am2x; -typedef Bit8u scale2x_uint8; -typedef Bit16u scale2x_uint16; -typedef Bit32u scale2x_uint32; -static void scale2x_line_8(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) -{ - assert(count >= 2); +static void AdvMame2x_AddLine(Bits s0,Bits s1,Bits s2) { + if (s0<0) s0=0; + if (s1<0) s1=0; + if (s2<0) s2=0; + if (s0>=(Bits)render.src.height) s0=render.src.height-1; + if (s1>=(Bits)render.src.height) s1=render.src.height-1; + if (s2>=(Bits)render.src.height) s2=render.src.height-1; + Bitu pos=(am2x.buf_used+am2x.buf_pos)&(AM2XBUF-1); + am2x.buf[pos][0]=s0; + am2x.buf[pos][1]=s1; + am2x.buf[pos][2]=s2; + s0=s0 > s1 ? s0 : s1; + s0=s0 > s2 ? s0 : s2; + am2x.buf[pos][3]=s0; + am2x.buf_used++; +} - /* first pixel */ - dst0[0] = src1[0]; - dst1[0] = src1[0]; - if (src1[1] == src0[0] && src2[0] != src0[0]) - dst0[1] = src0[0]; - else - dst0[1] = src1[0]; - if (src1[1] == src2[0] && src0[0] != src2[0]) - dst1[1] = src2[0]; - else - dst1[1] = src1[0]; - ++src0; - ++src1; - ++src2; - dst0 += 2; - dst1 += 2; +static void AdvMame2x_CheckLines(Bits last) { + Bitu lines=0;Bit8u * line_count=am2x.cmd_index++; + while (am2x.buf_used) { + if (am2x.buf[am2x.buf_pos][3]>last) break; + *am2x.cmd_index++=am2x.buf[am2x.buf_pos][0]&3; + *am2x.cmd_index++=am2x.buf[am2x.buf_pos][1]&3; + *am2x.cmd_index++=am2x.buf[am2x.buf_pos][2]&3; + am2x.buf_used--;lines++; + am2x.buf_pos=(am2x.buf_pos+1)&(AM2XBUF-1); + } + *line_count=lines; +} +template +static void AdvMame2x_line(Bit8u * dst, const Bit8u * src0, const Bit8u * src1, const Bit8u * src2, Bitu count) { + AddDst(dst,ConvBPP(src1[0])); + AddDst(dst,ConvBPP((src1[1] == src0[0] && src2[0] != src0[0]) ? src0[0] : src1[0])); + src0++;src1++;src2++;count-=2; /* central pixels */ - count -= 2; while (count) { - if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) - dst0[0] = src0[0]; - else - dst0[0] = src1[0]; - if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) - dst0[1] = src0[0]; - else - dst0[1] = src1[0]; - - if (src1[-1] == src2[0] && src0[0] != src2[0] && src1[1] != src2[0]) - dst1[0] = src2[0]; - else - dst1[0] = src1[0]; - if (src1[1] == src2[0] && src0[0] != src2[0] && src1[-1] != src2[0]) - dst1[1] = src2[0]; - else - dst1[1] = src1[0]; - - ++src0; - ++src1; - ++src2; - dst0 += 2; - dst1 += 2; - --count; + AddDst(dst,ConvBPP((src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) ? src0[0] : src1[0])); + AddDst(dst,ConvBPP((src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) ? src0[0] : src1[0])); + src0++;src1++;src2++;count--; } - /* last pixel */ - if (src1[-1] == src0[0] && src2[0] != src0[0]) - dst0[0] = src0[0]; - else - dst0[0] = src1[0]; - if (src1[-1] == src2[0] && src0[0] != src2[0]) - dst1[0] = src2[0]; - else - dst1[0] = src1[0]; - dst0[1] = src1[0]; - dst1[1] = src1[0]; + AddDst(dst,ConvBPP((src1[-1] == src0[0] && src2[0] != src0[0]) ? src0[0] : src1[0])); + AddDst(dst,ConvBPP(src1[0])); } -static void scale2x_line_16(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) -{ - assert(count >= 2); - - /* first pixel */ - dst0[0] = render.pal.lookup.bpp16[src1[0]]; - dst1[0] = render.pal.lookup.bpp16[src1[0]]; - if (src1[1] == src0[0] && src2[0] != src0[0]) - dst0[1] = render.pal.lookup.bpp16[src0[0]]; - else - dst0[1] = render.pal.lookup.bpp16[src1[0]]; - if (src1[1] == src2[0] && src0[0] != src2[0]) - dst1[1] = render.pal.lookup.bpp16[src2[0]]; - else - dst1[1] = render.pal.lookup.bpp16[src1[0]]; - ++src0; - ++src1; - ++src2; - dst0 += 2; - dst1 += 2; - - /* central pixels */ - count -= 2; - while (count) { - if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) - dst0[0] = render.pal.lookup.bpp16[src0[0]]; - else - dst0[0] = render.pal.lookup.bpp16[src1[0]]; - if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) - dst0[1] = render.pal.lookup.bpp16[src0[0]]; - else - dst0[1] = render.pal.lookup.bpp16[src1[0]]; - - if (src1[-1] == src2[0] && src0[0] != src2[0] && src1[1] != src2[0]) - dst1[0] = render.pal.lookup.bpp16[src2[0]]; - else - dst1[0] = render.pal.lookup.bpp16[src1[0]]; - if (src1[1] == src2[0] && src0[0] != src2[0] && src1[-1] != src2[0]) - dst1[1] = render.pal.lookup.bpp16[src2[0]]; - else - dst1[1] = render.pal.lookup.bpp16[src1[0]]; - - ++src0; - ++src1; - ++src2; - dst0 += 2; - dst1 += 2; - --count; +template +static void AdvMame2x(Bit8u * src) { + RENDER_TempLine=render_line_cache[render.op.line&3]; + am2x.cache[render.op.line&3]=src; + Bitu lines=*am2x.cmd_index++; + while (lines--) { + Bit8u * src0=am2x.cache[*am2x.cmd_index++]; + Bit8u * src1=am2x.cache[*am2x.cmd_index++]; + Bit8u * src2=am2x.cache[*am2x.cmd_index++]; + AdvMame2x_line(render.op.pixels,src0,src1,src2,render.src.width); + render.op.pixels+=render.op.pitch; } - - /* last pixel */ - if (src1[-1] == src0[0] && src2[0] != src0[0]) - dst0[0] = render.pal.lookup.bpp16[src0[0]]; - else - dst0[0] = render.pal.lookup.bpp16[src1[0]]; - if (src1[-1] == src2[0] && src0[0] != src2[0]) - dst1[0] = render.pal.lookup.bpp16[src2[0]]; - else - dst1[0] = render.pal.lookup.bpp16[src1[0]]; - dst0[1] = render.pal.lookup.bpp16[src1[0]]; - dst1[1] = render.pal.lookup.bpp16[src1[0]]; + render.op.line++; } -static void scale2x_line_32(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) -{ - assert(count >= 2); - /* first pixel */ - dst0[0] = render.pal.lookup.bpp32[src1[0]]; - dst1[0] = render.pal.lookup.bpp32[src1[0]]; - if (src1[1] == src0[0] && src2[0] != src0[0]) - dst0[1] = render.pal.lookup.bpp32[src0[0]]; - else - dst0[1] = render.pal.lookup.bpp32[src1[0]]; - if (src1[1] == src2[0] && src0[0] != src2[0]) - dst1[1] = render.pal.lookup.bpp32[src2[0]]; - else - dst1[1] = render.pal.lookup.bpp32[src1[0]]; - ++src0; - ++src1; - ++src2; - dst0 += 2; - dst1 += 2; +static RENDER_Line_Handler AdvMame2x_8_Table[4]={ + AdvMame2x<8,8>,AdvMame2x<8,16>,AdvMame2x<8,24>,AdvMame2x<8,32> +}; - /* central pixels */ - count -= 2; - while (count) { - if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) - dst0[0] = render.pal.lookup.bpp32[src0[0]]; - else - dst0[0] = render.pal.lookup.bpp32[src1[0]]; - if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) - dst0[1] = render.pal.lookup.bpp32[src0[0]]; - else - dst0[1] = render.pal.lookup.bpp32[src1[0]]; - - if (src1[-1] == src2[0] && src0[0] != src2[0] && src1[1] != src2[0]) - dst1[0] = render.pal.lookup.bpp32[src2[0]]; - else - dst1[0] = render.pal.lookup.bpp32[src1[0]]; - if (src1[1] == src2[0] && src0[0] != src2[0] && src1[-1] != src2[0]) - dst1[1] = render.pal.lookup.bpp32[src2[0]]; - else - dst1[1] = render.pal.lookup.bpp32[src1[0]]; - - ++src0; - ++src1; - ++src2; - dst0 += 2; - dst1 += 2; - --count; - } - - /* last pixel */ - if (src1[-1] == src0[0] && src2[0] != src0[0]) - dst0[0] = render.pal.lookup.bpp32[src0[0]]; - else - dst0[0] = render.pal.lookup.bpp32[src1[0]]; - if (src1[-1] == src2[0] && src0[0] != src2[0]) - dst1[0] = render.pal.lookup.bpp32[src2[0]]; - else - dst1[0] = render.pal.lookup.bpp32[src1[0]]; - dst0[1] = render.pal.lookup.bpp32[src1[0]]; - dst1[1] = render.pal.lookup.bpp32[src1[0]]; -} - -static void Scale2x_8(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - if (dy<3) return; - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch; - /* First line */ - scale2x_line_8(dest,dest+render.op.pitch,src,src,src+render.src.pitch,dx); - dest+=render.op.pitch*2; - src+=render.src.pitch; - dy-=2; - /* Middle part */ - for (;dy>0;dy--) { - scale2x_line_8((Bit8u *)dest,(Bit8u *)(dest+render.op.pitch),src-render.src.pitch,src,src+render.src.pitch,dx); - dest+=render.op.pitch*2; - src+=render.src.pitch; - } - /* Last Line */ - scale2x_line_8((Bit8u *)dest,(Bit8u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); -} - -static void Scale2x_16(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - if (dy<3) return; - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch; - /* First line */ - scale2x_line_16((Bit16u *)dest,(Bit16u *)(dest+render.op.pitch),src,src,src+render.src.pitch,dx); - dest+=render.op.pitch*2; - src+=render.src.pitch; - dy-=2; - /* Middle part */ - for (;dy>0;dy--) { - scale2x_line_16((Bit16u *)dest,(Bit16u *)(dest+render.op.pitch),src-render.src.pitch,src,src+render.src.pitch,dx); - dest+=render.op.pitch*2; - src+=render.src.pitch; - } - /* Last Line */ - scale2x_line_16((Bit16u *)dest,(Bit16u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); -} - -static void Scale2x_32(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - if (dy<3) return; - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch; - /* First line */ - scale2x_line_32((Bit32u *)dest,(Bit32u *)(dest+render.op.pitch),src,src,src+render.src.pitch,dx); - dest+=render.op.pitch*2; - src+=render.src.pitch; - dy-=2; - /* Middle part */ - for (;dy>0;dy--) { - scale2x_line_32((Bit32u *)dest,(Bit32u *)(dest+render.op.pitch),src-render.src.pitch,src,src+render.src.pitch,dx); - dest+=render.op.pitch*2; - src+=render.src.pitch; - } - /* Last Line */ - scale2x_line_32((Bit32u *)dest,(Bit32u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); -} - -#if defined(__GNUC__) && defined(__i386__) - -#define SCALE2X_MMX 1 - -static __inline__ void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) -{ - assert(count >= 16); - assert(count % 8 == 0); - - /* always do the first and last run */ - count -= 2*8; - - __asm__ __volatile__( -/* first run */ - /* set the current, current_pre, current_next registers */ - "movq 0(%1),%%mm0\n" - "movq 0(%1),%%mm7\n" - "movq 8(%1),%%mm1\n" - "psllq $56,%%mm0\n" - "psllq $56,%%mm1\n" - "psrlq $56,%%mm0\n" - "movq %%mm7,%%mm2\n" - "movq %%mm7,%%mm3\n" - "psllq $8,%%mm2\n" - "psrlq $8,%%mm3\n" - "por %%mm2,%%mm0\n" - "por %%mm3,%%mm1\n" - - /* current_upper */ - "movq (%0),%%mm6\n" - - /* compute the upper-left pixel for dst on %%mm2 */ - /* compute the upper-right pixel for dst on %%mm4 */ - "movq %%mm0,%%mm2\n" - "movq %%mm1,%%mm4\n" - "movq %%mm0,%%mm3\n" - "movq %%mm1,%%mm5\n" - "pcmpeqb %%mm6,%%mm2\n" - "pcmpeqb %%mm6,%%mm4\n" - "pcmpeqb (%2),%%mm3\n" - "pcmpeqb (%2),%%mm5\n" - "pandn %%mm2,%%mm3\n" - "pandn %%mm4,%%mm5\n" - "movq %%mm0,%%mm2\n" - "movq %%mm1,%%mm4\n" - "pcmpeqb %%mm1,%%mm2\n" - "pcmpeqb %%mm0,%%mm4\n" - "pandn %%mm3,%%mm2\n" - "pandn %%mm5,%%mm4\n" - "movq %%mm2,%%mm3\n" - "movq %%mm4,%%mm5\n" - "pand %%mm6,%%mm2\n" - "pand %%mm6,%%mm4\n" - "pandn %%mm7,%%mm3\n" - "pandn %%mm7,%%mm5\n" - "por %%mm3,%%mm2\n" - "por %%mm5,%%mm4\n" - - /* set *dst */ - "movq %%mm2,%%mm3\n" - "punpcklbw %%mm4,%%mm2\n" - "punpckhbw %%mm4,%%mm3\n" - "movq %%mm2,(%3)\n" - "movq %%mm3,8(%3)\n" - - /* next */ - "addl $8,%0\n" - "addl $8,%1\n" - "addl $8,%2\n" - "addl $16,%3\n" - -/* central runs */ - "shrl $3,%4\n" - "jz 1f\n" - - "0:\n" - - /* set the current, current_pre, current_next registers */ - "movq -8(%1),%%mm0\n" - "movq (%1),%%mm7\n" - "movq 8(%1),%%mm1\n" - "psrlq $56,%%mm0\n" - "psllq $56,%%mm1\n" - "movq %%mm7,%%mm2\n" - "movq %%mm7,%%mm3\n" - "psllq $8,%%mm2\n" - "psrlq $8,%%mm3\n" - "por %%mm2,%%mm0\n" - "por %%mm3,%%mm1\n" - - /* current_upper */ - "movq (%0),%%mm6\n" - - /* compute the upper-left pixel for dst on %%mm2 */ - /* compute the upper-right pixel for dst on %%mm4 */ - "movq %%mm0,%%mm2\n" - "movq %%mm1,%%mm4\n" - "movq %%mm0,%%mm3\n" - "movq %%mm1,%%mm5\n" - "pcmpeqb %%mm6,%%mm2\n" - "pcmpeqb %%mm6,%%mm4\n" - "pcmpeqb (%2),%%mm3\n" - "pcmpeqb (%2),%%mm5\n" - "pandn %%mm2,%%mm3\n" - "pandn %%mm4,%%mm5\n" - "movq %%mm0,%%mm2\n" - "movq %%mm1,%%mm4\n" - "pcmpeqb %%mm1,%%mm2\n" - "pcmpeqb %%mm0,%%mm4\n" - "pandn %%mm3,%%mm2\n" - "pandn %%mm5,%%mm4\n" - "movq %%mm2,%%mm3\n" - "movq %%mm4,%%mm5\n" - "pand %%mm6,%%mm2\n" - "pand %%mm6,%%mm4\n" - "pandn %%mm7,%%mm3\n" - "pandn %%mm7,%%mm5\n" - "por %%mm3,%%mm2\n" - "por %%mm5,%%mm4\n" - - /* set *dst */ - "movq %%mm2,%%mm3\n" - "punpcklbw %%mm4,%%mm2\n" - "punpckhbw %%mm4,%%mm3\n" - "movq %%mm2,(%3)\n" - "movq %%mm3,8(%3)\n" - - /* next */ - "addl $8,%0\n" - "addl $8,%1\n" - "addl $8,%2\n" - "addl $16,%3\n" - - "decl %4\n" - "jnz 0b\n" - "1:\n" - -/* final run */ - /* set the current, current_pre, current_next registers */ - "movq (%1),%%mm1\n" - "movq (%1),%%mm7\n" - "movq -8(%1),%%mm0\n" - "psrlq $56,%%mm1\n" - "psrlq $56,%%mm0\n" - "psllq $56,%%mm1\n" - "movq %%mm7,%%mm2\n" - "movq %%mm7,%%mm3\n" - "psllq $8,%%mm2\n" - "psrlq $8,%%mm3\n" - "por %%mm2,%%mm0\n" - "por %%mm3,%%mm1\n" - - /* current_upper */ - "movq (%0),%%mm6\n" - - /* compute the upper-left pixel for dst on %%mm2 */ - /* compute the upper-right pixel for dst on %%mm4 */ - "movq %%mm0,%%mm2\n" - "movq %%mm1,%%mm4\n" - "movq %%mm0,%%mm3\n" - "movq %%mm1,%%mm5\n" - "pcmpeqb %%mm6,%%mm2\n" - "pcmpeqb %%mm6,%%mm4\n" - "pcmpeqb (%2),%%mm3\n" - "pcmpeqb (%2),%%mm5\n" - "pandn %%mm2,%%mm3\n" - "pandn %%mm4,%%mm5\n" - "movq %%mm0,%%mm2\n" - "movq %%mm1,%%mm4\n" - "pcmpeqb %%mm1,%%mm2\n" - "pcmpeqb %%mm0,%%mm4\n" - "pandn %%mm3,%%mm2\n" - "pandn %%mm5,%%mm4\n" - "movq %%mm2,%%mm3\n" - "movq %%mm4,%%mm5\n" - "pand %%mm6,%%mm2\n" - "pand %%mm6,%%mm4\n" - "pandn %%mm7,%%mm3\n" - "pandn %%mm7,%%mm5\n" - "por %%mm3,%%mm2\n" - "por %%mm5,%%mm4\n" - - /* set *dst */ - "movq %%mm2,%%mm3\n" - "punpcklbw %%mm4,%%mm2\n" - "punpckhbw %%mm4,%%mm3\n" - "movq %%mm2,(%3)\n" - "movq %%mm3,8(%3)\n" - - "emms" - - : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) - : - : "cc" - ); -} - -static void scale2x_line_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) -{ - assert(count >= 16); - assert(count % 8 == 0); - - scale2x_8_mmx_single(dst0, src0, src1, src2, count); - scale2x_8_mmx_single(dst1, src2, src1, src0, count); -} - -static void Scale2x_8_mmx(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - if (dy<3) return; - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch; - /* First line */ - scale2x_line_8_mmx(dest,dest+render.op.pitch,src,src,src+render.src.pitch,dx); - dest+=render.op.pitch*2; - src+=render.src.pitch; - dy-=2; - /* Middle part */ - for (;dy>0;dy--) { - scale2x_line_8_mmx((Bit8u *)dest,(Bit8u *)(dest+render.op.pitch),src-render.src.pitch,src,src+render.src.pitch,dx); - dest+=render.op.pitch*2; - src+=render.src.pitch; - } - /* Last Line */ - scale2x_line_8_mmx((Bit8u *)dest,(Bit8u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); -} - -#endif - -static void Render_Scale2x_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags) { - if (!(flags & MODE_SET)) return; - render.op.width=width; - render.op.height=height; - render.op.bpp=bpp; - render.op.pitch=pitch; - render.op.type=OP_AdvMame2x; - switch (bpp) { - case 8: -#if defined(SCALE2X_MMX) - render.op.part_handler=Scale2x_8_mmx; -#else - render.op.part_handler=Scale2x_8; -#endif - break; - case 16: - render.op.part_handler=Scale2x_16;; - break; - case 32: - render.op.part_handler=Scale2x_32; - break; - default: - E_Exit("RENDER:Unsupported display depth of %d",bpp); - break; - } - RENDER_ResetPal(); -} #endif diff --git a/src/gui/render_templates.h b/src/gui/render_templates.h new file mode 100644 index 0000000..d5228cd --- /dev/null +++ b/src/gui/render_templates.h @@ -0,0 +1,59 @@ +#ifdef __GNUC__ +template static INLINE void AddDst(Bit8u * & dst,Bitu val) __attribute__ ((always_inline)); +template static INLINE Bitu LineSize(Bitu pixels) __attribute__ ((always_inline)); +template static INLINE Bitu LoadSrc(Bit8u * & src) __attribute__ ((always_inline)); +template static INLINE Bitu ConvBPP(Bitu val) __attribute__ ((always_inline)); +#endif + +template static INLINE void AddDst(Bit8u * & dst,Bitu val) { + switch (dbpp) { + case 8: *(Bit8u*)dst=val;dst+=1;break; + case 16:*(Bit16u*)dst=val;dst+=2;break; + case 24:*(Bit32u*)dst=val;dst+=3;break; + case 32:*(Bit32u*)dst=val;dst+=4;break; + } +} + +template +static INLINE Bitu LineSize(Bitu pixels) { + switch (bpp) { + case 8:return pixels; + case 16:return pixels*2; + case 24:return pixels*3; + case 32:return pixels*4; + } + return 0; +} + +static INLINE void BituMove(Bit8u * dst,Bit8u * src,Bitu pixels) { + pixels/=sizeof(Bitu); + while (pixels--) { + *(Bitu*)dst=*(Bitu*)src; + src+=sizeof(Bitu); + dst+=sizeof(Bitu); + } +} + +template +static INLINE Bitu LoadSrc(Bit8u * & src) { + Bitu val; + switch (sbpp) { + case 8:val=*(Bit8u *) src;src+=1;break; + case 16:val=*(Bit16u *) src;src+=2;break; + case 24:val=(*(Bit32u *)src)&0xffffff;src+=3;break; + case 32:val=*(Bit32u *)src;src+=4;break; + } + return val; +} + + +template +static INLINE Bitu ConvBPP(Bitu val) { + if (sbpp==8) switch (dbpp) { + case 8:return val; + case 16:return render.pal.lookup.bpp16[val]; + case 24:return render.pal.lookup.bpp32[val]; + case 32:return render.pal.lookup.bpp32[val]; + } + return 0; +} diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index bd5e217..6d6efd9 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sdlmain.cpp,v 1.51 2003/10/14 23:32:32 harekiet Exp $ */ +/* $Id: sdlmain.cpp,v 1.60 2004/01/30 21:11:34 harekiet Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -29,7 +29,6 @@ #include #include "SDL.h" -#include "SDL_thread.h" #include "dosbox.h" #include "video.h" @@ -39,10 +38,45 @@ #include "pic.h" #include "timer.h" #include "setup.h" +#include "support.h" #include "debug.h" +#if C_OPENGL +#include "SDL_opengl.h" + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif + +#ifdef __WIN32__ +#define NVIDIA_PixelDataRange 1 +#ifndef WGL_NV_allocate_memory +#define WGL_NV_allocate_memory 1 +typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, float writefreq, float priority); +typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer); +PFNWGLALLOCATEMEMORYNVPROC db_glAllocateMemoryNV = NULL; +PFNWGLFREEMEMORYNVPROC db_glFreeMemoryNV = NULL; +#endif +#else + +#endif + +#if defined(NVIDIA_PixelDataRange) +#ifndef GL_NV_pixel_data_range +#define GL_NV_pixel_data_range 1 +#define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878 +typedef void (APIENTRYP PFNGLPIXELDATARANGENVPROC) (GLenum target, GLsizei length, GLvoid *pointer); +typedef void (APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC) (GLenum target); +PFNGLPIXELDATARANGENVPROC glPixelDataRangeNV = NULL; +#endif +#endif + +#endif //C_OPENGL + //#define DISABLE_JOYSTICK -#define C_GFXTHREADED 1 //Enabled by default #if !(ENVIRON_INCLUDED) extern char** environ; @@ -56,29 +90,60 @@ extern char** environ; #include #define STDOUT_FILE TEXT("stdout.txt") #define STDERR_FILE TEXT("stderr.txt") +#define DEFAULT_CONFIG_FILE "/dosbox.conf" +#elif defined(MACOSX) +#define DEFAULT_CONFIG_FILE "/Library/Preferences/DOSBox Preferences" +#else /*linux freebsd*/ +#define DEFAULT_CONFIG_FILE "/.dosboxrc" #endif +enum SCREEN_TYPES { + SCREEN_SURFACE, + SCREEN_OVERLAY, + SCREEN_OPENGL +}; + + struct SDL_Block { - volatile bool active; //If this isn't set don't draw - volatile bool drawing; - Bitu width; - Bitu height; - Bitu bpp; - Bitu flags; - GFX_ModeCallBack mode_callback; - bool full_screen; + bool active; //If this isn't set don't draw + bool updating; + struct { + Bit32u width; + Bit32u height; + Bitu bpp; + double scalex,scaley; + GFX_ResetCallBack reset; + } draw; bool wait_on_error; + struct { + Bit32u width,height,bpp; + bool fixed; + bool fullscreen; + bool doublebuf; + SCREEN_TYPES type; + SCREEN_TYPES want_type; + double hwscale; + } desktop; +#if C_OPENGL + struct { + Bitu pitch; + void * framebuf; + GLuint texture; + GLuint displaylist; + GLint max_texsize; + bool bilinear; + bool packed_pixel; + bool paletted_texture; +#if defined(NVIDIA_PixelDataRange) + bool pixel_data_range; +#endif + } opengl; +#endif + SDL_Rect clip; SDL_Surface * surface; - SDL_Surface * blit_surface; + SDL_Overlay * overlay; SDL_Joystick * joy; SDL_cond *cond; -#if C_GFXTHREADED - SDL_mutex *mutex; - SDL_Thread *thread; - SDL_sem *sem; - volatile bool kill_thread; -#endif - GFX_DrawCallBack draw_callback; struct { bool autolock; bool autoenable; @@ -102,57 +167,232 @@ void GFX_SetTitle(Bits cycles,Bits frameskip){ } /* Reset the screen with current values in the sdl structure */ -static void ResetScreen(void) { - GFX_Stop(); - if (sdl.full_screen) { - if (sdl.flags & GFX_SHADOW) { - withshadow: - /* TODO Maybe allocate a shadow surface and blit yourself and do real double buffering too */ - sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_SWSURFACE|SDL_FULLSCREEN); +Bitu GFX_GetBestMode(Bitu bpp,Bitu & gfx_flags) { + gfx_flags=0; + switch (sdl.desktop.want_type) { + case SCREEN_SURFACE: + if (sdl.desktop.fullscreen) { + bpp=SDL_VideoModeOK(640,480,bpp,SDL_FULLSCREEN|SDL_HWSURFACE | + (sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0) | ((bpp==8) ? SDL_HWPALETTE : 0) ); } else { - Bitu test_bpp=SDL_VideoModeOK(sdl.width,sdl.height,sdl.bpp,SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN|SDL_DOUBLEBUF); - if (test_bpp != sdl.bpp) - goto withshadow; - sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN|SDL_DOUBLEBUF); - } - } else { - if (sdl.flags & GFX_FIXED_BPP) { - withfixed: - sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_HWSURFACE); - } else { - sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,0,SDL_HWSURFACE); - if (sdl.surface->format->BitsPerPixel==24) - goto withfixed; + bpp=sdl.desktop.bpp; } + gfx_flags|=GFX_HASCONVERT; + break; + case SCREEN_OVERLAY: + bpp=32; + gfx_flags|=GFX_HASSCALING; + break; +#if C_OPENGL + case SCREEN_OPENGL: + bpp=32; + gfx_flags|=GFX_HASSCALING; + break; +#endif } - if (sdl.surface==0) { - E_Exit("SDL:Can't get a surface error:%s.",SDL_GetError()); - } - /* Create special surface for direct blitting if needed */ - if (sdl.blit_surface) SDL_FreeSurface(sdl.blit_surface); - sdl.blit_surface=SDL_CreateRGBSurfaceFrom(0,0,0,sdl.surface->format->BytesPerPixel,0, - sdl.surface->format->Rmask,sdl.surface->format->Gmask,sdl.surface->format->Bmask,sdl.surface->format->Amask - ); - - - GFX_SetTitle(-1,-1); - - Bitu flags=MODE_SET; - if (sdl.full_screen) flags|=MODE_FULLSCREEN; - if (sdl.mode_callback) sdl.mode_callback(sdl.surface->w,sdl.surface->h,sdl.surface->format->BitsPerPixel,sdl.surface->pitch,flags); - GFX_Start(); + return bpp; } -void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu flags,GFX_ModeCallBack mode_callback, GFX_DrawCallBack draw_callback){ +static void ResetScreen(void) { GFX_Stop(); - sdl.width=width; - sdl.height=height; - sdl.bpp=bpp; - sdl.flags=flags; - sdl.mode_callback=mode_callback; - sdl.draw_callback=draw_callback; - ResetScreen(); + if (sdl.draw.reset) (sdl.draw.reset)(); + GFX_Start(); +} + +static int int_log2 (int val) { + int log = 0; + while ((val >>= 1) != 0) + log++; + return log; +} + +void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,double scalex,double scaley,GFX_ResetCallBack reset) { + if (sdl.updating) GFX_EndUpdate(); + sdl.draw.width=width; + sdl.draw.height=height; + sdl.draw.bpp=bpp; + sdl.draw.reset=reset; + sdl.draw.scalex=scalex; + sdl.draw.scaley=scaley; + + switch (sdl.desktop.want_type) { + case SCREEN_SURFACE: +dosurface: + sdl.desktop.type=SCREEN_SURFACE; + sdl.clip.w=width; + sdl.clip.h=height; + if (sdl.desktop.fullscreen) { + if (sdl.desktop.fixed) { + sdl.clip.x=(Sint16)((sdl.desktop.width-width)/2); + sdl.clip.y=(Sint16)((sdl.desktop.height-height)/2); + sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,bpp, + SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0)|SDL_HWPALETTE); + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.surface=SDL_SetVideoMode(width,height,bpp, + SDL_FULLSCREEN|SDL_HWSURFACE|(sdl.desktop.doublebuf ? SDL_DOUBLEBUF : 0)|SDL_HWPALETTE); + } + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.surface=SDL_SetVideoMode(width,height,bpp,SDL_HWSURFACE); + } + break; + case SCREEN_OVERLAY: + if (sdl.overlay) SDL_FreeYUVOverlay(sdl.overlay); + sdl.overlay=0; + if (bpp!=32) goto dosurface; + if (sdl.desktop.fullscreen) { + if (sdl.desktop.fixed) { + double ratio_w=(double)sdl.desktop.width/(width*scalex); + double ratio_h=(double)sdl.desktop.height/(height*scaley); + if ( ratio_w < ratio_h) { + sdl.clip.w=(Bit16u)sdl.desktop.width; + sdl.clip.h=(Bit16u)(height*scaley*ratio_w); + } else { + sdl.clip.w=(Bit16u)(width*scalex*ratio_h); + sdl.clip.h=(Bit16u)sdl.desktop.height; + } + sdl.clip.x=(Sint16)((sdl.desktop.width-sdl.clip.w)/2); + sdl.clip.y=(Sint16)((sdl.desktop.height-sdl.clip.h)/2); + sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,0, + SDL_FULLSCREEN|SDL_HWSURFACE); + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.clip.w=(Bit16u)(width*scalex); + sdl.clip.h=(Bit16u)(height*scaley); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, + SDL_FULLSCREEN|SDL_HWSURFACE); + } + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.clip.w=(Bit16u)(width*scalex*sdl.desktop.hwscale); + sdl.clip.h=(Bit16u)(height*scaley*sdl.desktop.hwscale); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0,SDL_HWSURFACE); + } + sdl.overlay=SDL_CreateYUVOverlay(width*2,height,SDL_UYVY_OVERLAY,sdl.surface); + if (!sdl.overlay) { + LOG_MSG("SDL:Failed to create overlay, switching back to surface"); + goto dosurface; + } + sdl.desktop.type=SCREEN_OVERLAY; + break; +#if C_OPENGL + case SCREEN_OPENGL: + { + if (sdl.opengl.framebuf) { +#if defined(NVIDIA_PixelDataRange) + if (sdl.opengl.pixel_data_range) db_glFreeMemoryNV(sdl.opengl.framebuf); + else +#endif + free(sdl.opengl.framebuf); + } + sdl.opengl.framebuf=0; + if (bpp!=32) goto dosurface; + int texsize=2 << int_log2(width > height ? width : height); + if (texsize>sdl.opengl.max_texsize) { + LOG_MSG("SDL:OPENGL:No support for texturesize of %d, falling back to surface",texsize); + goto dosurface; + } + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); + if (sdl.desktop.fullscreen) { + if (sdl.desktop.fixed) { + double ratio_w=(double)sdl.desktop.width/(width*scalex); + double ratio_h=(double)sdl.desktop.height/(height*scaley); + if ( ratio_w < ratio_h) { + sdl.clip.w=(Bit16u)sdl.desktop.width; + sdl.clip.h=(Bit16u)(height*scaley*ratio_w); + } else { + sdl.clip.w=(Bit16u)(width*scalex*ratio_h); + sdl.clip.h=(Bit16u)sdl.desktop.height; + } + sdl.clip.x=(Sint16)((sdl.desktop.width-sdl.clip.w)/2); + sdl.clip.y=(Sint16)((sdl.desktop.height-sdl.clip.h)/2); + sdl.surface=SDL_SetVideoMode(sdl.desktop.width,sdl.desktop.height,0, + SDL_OPENGL|SDL_FULLSCREEN|SDL_HWSURFACE); + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.clip.w=(Bit16u)(width*scalex); + sdl.clip.h=(Bit16u)(height*scaley); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, + SDL_OPENGL|SDL_FULLSCREEN|SDL_HWSURFACE); + } + } else { + sdl.clip.x=0;sdl.clip.y=0; + sdl.clip.w=(Bit16u)(width*scalex*sdl.desktop.hwscale); + sdl.clip.h=(Bit16u)(height*scaley*sdl.desktop.hwscale); + sdl.surface=SDL_SetVideoMode(sdl.clip.w,sdl.clip.h,0, + SDL_OPENGL|SDL_HWSURFACE); + } + if (!sdl.surface || sdl.surface->format->BitsPerPixel<15) { + LOG_MSG("SDL:OPENGL:Can't open drawing surface, are you running in 16bpp(or higher) mode?"); + goto dosurface; + } + /* Create the texture and display list */ +#if defined(NVIDIA_PixelDataRange) + if (sdl.opengl.pixel_data_range) { + sdl.opengl.framebuf=db_glAllocateMemoryNV(width*height*4,0.0,1.0,1.0); + glPixelDataRangeNV(GL_WRITE_PIXEL_DATA_RANGE_NV,width*height*4,sdl.opengl.framebuf); + glEnableClientState(GL_WRITE_PIXEL_DATA_RANGE_NV); + } else { +#else + { +#endif + sdl.opengl.framebuf=malloc(width*height*4); //32 bit color + } + sdl.opengl.pitch=width*4; + glViewport(sdl.clip.x,sdl.clip.y,sdl.clip.w,sdl.clip.h); + glMatrixMode (GL_PROJECTION); + glDeleteTextures(1,&sdl.opengl.texture); + glGenTextures(1,&sdl.opengl.texture); + glBindTexture(GL_TEXTURE_2D,sdl.opengl.texture); + // No borders + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + if (sdl.opengl.bilinear) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texsize, texsize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, 0); + + glClearColor (0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glShadeModel (GL_FLAT); + glDisable (GL_DEPTH_TEST); + glDisable (GL_LIGHTING); + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_2D); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + + GLfloat tex_width=((GLfloat)(width)/(GLfloat)texsize); + GLfloat tex_height=((GLfloat)(height)/(GLfloat)texsize); + + if (glIsList(sdl.opengl.displaylist)) glDeleteLists(sdl.opengl.displaylist, 1); + sdl.opengl.displaylist = glGenLists(1); + glNewList(sdl.opengl.displaylist, GL_COMPILE); + glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); + glBegin(GL_QUADS); + // lower left + glTexCoord2f(0,tex_height); glVertex2f(-1.0f,-1.0f); + // lower right + glTexCoord2f(tex_width,tex_height); glVertex2f(1.0f, -1.0f); + // upper right + glTexCoord2f(tex_width,0); glVertex2f(1.0f, 1.0f); + // upper left + glTexCoord2f(0,0); glVertex2f(-1.0f, 1.0f); + glEnd(); + glEndList(); + sdl.desktop.type=SCREEN_OPENGL; + break; + }//OPENGL +#endif //C_OPENGL + }//CASE + GFX_Start(); } @@ -168,9 +408,8 @@ static void CaptureMouse(void) { } static void SwitchFullScreen(void) { - sdl.full_screen=!sdl.full_screen; - if (sdl.full_screen) { -//TODO Give an resize event + sdl.desktop.fullscreen=!sdl.desktop.fullscreen; + if (sdl.desktop.fullscreen) { if (!sdl.mouse.locked) CaptureMouse(); } else { if (sdl.mouse.locked) CaptureMouse(); @@ -182,70 +421,70 @@ void GFX_SwitchFullScreen(void) { SwitchFullScreen(); } -/* Special render part handler that blits directly to the output screen */ -void GFX_Render_Blit(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - sdl.blit_surface->w=dx; - sdl.blit_surface->h=dy; - sdl.blit_surface->pitch=dx; - sdl.blit_surface->pixels=src; - SDL_UnlockSurface(sdl.surface); - SDL_Rect dest; - dest.x=x; - dest.y=y; - SDL_BlitSurface(sdl.blit_surface,0,sdl.surface,&dest); -} - -static void SDL_DrawScreen(void) { - sdl.drawing=true; +bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch) { + if (!sdl.active || sdl.updating) return false; + sdl.updating=true; + switch (sdl.desktop.type) { + case SCREEN_SURFACE: if (SDL_MUSTLOCK(sdl.surface)) { if (SDL_LockSurface(sdl.surface)) { - sdl.drawing=false; - return; + LOG_MSG("SDL Lock failed"); + sdl.updating=false; + return false; } } - sdl.draw_callback(sdl.surface->pixels); + pixels=(Bit8u *)sdl.surface->pixels; + pixels+=sdl.clip.y*sdl.surface->pitch; + pixels+=sdl.clip.x*sdl.surface->format->BytesPerPixel; + pitch=sdl.surface->pitch; + return true; + case SCREEN_OVERLAY: + SDL_LockYUVOverlay(sdl.overlay); + pixels=(Bit8u *)*(sdl.overlay->pixels); + pitch=*(sdl.overlay->pitches); + return true; +#if C_OPENGL + case SCREEN_OPENGL: + pixels=(Bit8u *)sdl.opengl.framebuf; + pitch=sdl.opengl.pitch; + return true; +#endif + } + return false; +} + +void GFX_EndUpdate(void) { + if (!sdl.updating) return; + sdl.updating=false; + switch (sdl.desktop.type) { + case SCREEN_SURFACE: if (SDL_MUSTLOCK(sdl.surface)) { SDL_UnlockSurface(sdl.surface); } SDL_Flip(sdl.surface); - sdl.drawing=false; -} + break; + case SCREEN_OVERLAY: + SDL_UnlockYUVOverlay(sdl.overlay); + SDL_DisplayYUVOverlay(sdl.overlay,&sdl.clip); + break; +#if C_OPENGL + case SCREEN_OPENGL: + glBindTexture(GL_TEXTURE_2D, sdl.opengl.texture); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + sdl.draw.width, sdl.draw.height, GL_BGRA_EXT, + GL_UNSIGNED_INT_8_8_8_8_REV, sdl.opengl.framebuf); + glCallList(sdl.opengl.displaylist); + SDL_GL_SwapBuffers(); + break; +#endif -#if C_GFXTHREADED -int SDL_DisplayThread(void * data) { - while (!SDL_SemWait(sdl.sem)) { - if (sdl.kill_thread) return 0; - if (!sdl.active) continue; - if (sdl.drawing) continue; - SDL_mutexP(sdl.mutex); - SDL_DrawScreen(); - SDL_mutexV(sdl.mutex); } - return 0; -} -#endif - -void GFX_DoUpdate(void) { - if (!sdl.active) - return; - if (sdl.drawing)return; -#if C_GFXTHREADED - SDL_SemPost(sdl.sem); -#else - SDL_DrawScreen(); -#endif - } void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { -#if C_GFXTHREADED - if (SDL_mutexP(sdl.mutex)) { - E_Exit("SDL:Can't lock Mutex"); - }; -#endif /* I should probably not change the GFX_PalEntry :) */ - if (sdl.full_screen) { + if (sdl.surface->flags & SDL_HWPALETTE) { if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,(SDL_Color *)entries,start,count)) { E_Exit("SDL:Can't set palette"); } @@ -254,26 +493,29 @@ void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { E_Exit("SDL:Can't set palette"); } } -#if C_GFXTHREADED - if (SDL_mutexV(sdl.mutex)) { - E_Exit("SDL:Can't release Mutex"); - }; -#endif } Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) { - return SDL_MapRGB(sdl.surface->format,red,green,blue); + switch (sdl.desktop.type) { + case SCREEN_SURFACE: + return SDL_MapRGB(sdl.surface->format,red,green,blue); + case SCREEN_OVERLAY: + { + Bit8u y = ( 9797*(red) + 19237*(green) + 3734*(blue) ) >> 15; + Bit8u u = (18492*((blue)-(y)) >> 15) + 128; + Bit8u v = (23372*((red)-(y)) >> 15) + 128; + return (u << 0) | (y << 8) | (v << 16) | (y << 24); + } + case SCREEN_OPENGL: +// return ((red << 0) | (green << 8) | (blue << 16)) | (255 << 24); + //USE BGRA + return ((blue << 0) | (green << 8) | (red << 16)) | (255 << 24); + } + return 0; } void GFX_Stop() { -#if C_GFXTHREADED - SDL_mutexP(sdl.mutex); -#endif sdl.active=false; -#if C_GFXTHREADED - SDL_mutexV(sdl.mutex); -#endif - } void GFX_Start() { @@ -283,15 +525,7 @@ void GFX_Start() { static void GUI_ShutDown(Section * sec) { GFX_Stop(); if (sdl.mouse.locked) CaptureMouse(); - if (sdl.full_screen) SwitchFullScreen(); -#if C_GFXTHREADED - sdl.kill_thread=true; - SDL_SemPost(sdl.sem); - SDL_WaitThread(sdl.thread,0); - SDL_DestroyMutex(sdl.mutex); - SDL_DestroySemaphore(sdl.sem); -#endif - + if (sdl.desktop.fullscreen) SwitchFullScreen(); } static void KillSwitch(void){ @@ -302,27 +536,83 @@ static void GUI_StartUp(Section * sec) { sec->AddDestroyFunction(&GUI_ShutDown); Section_prop * section=static_cast(sec); sdl.active=false; - sdl.full_screen=false; + sdl.updating=false; + sdl.desktop.fullscreen=section->Get_bool("fullscreen"); sdl.wait_on_error=section->Get_bool("waitonerror"); sdl.mouse.locked=false; sdl.mouse.requestlock=false; - sdl.mouse.autoenable=section->Get_bool("autolock"); + sdl.desktop.fixed=section->Get_bool("fullfixed"); + sdl.desktop.width=section->Get_int("fullwidth"); + sdl.desktop.height=section->Get_int("fullheight"); + sdl.desktop.doublebuf=section->Get_bool("fulldouble"); + sdl.desktop.hwscale=section->Get_float("hwscale"); + if (sdl.desktop.hwscale<0.1f) { + LOG_MSG("SDL:Can't hwscale lower than 0.1"); + sdl.desktop.hwscale=0.1f; + } + if (!sdl.desktop.width) { +#ifdef WIN32 + sdl.desktop.width=GetSystemMetrics(SM_CXSCREEN); +#else + sdl.desktop.width=1024; +#endif + } + if (!sdl.desktop.height) { +#ifdef WIN32 + sdl.desktop.height=GetSystemMetrics(SM_CYSCREEN); +#else + sdl.desktop.height=768; +#endif + } + sdl.mouse.autoenable=section->Get_bool("autolock"); sdl.mouse.autolock=false; sdl.mouse.sensitivity=section->Get_int("sensitivity"); - sdl.blit_surface=0; -#if C_GFXTHREADED - sdl.kill_thread=false; - sdl.mutex=SDL_CreateMutex(); - sdl.sem=SDL_CreateSemaphore(0); - sdl.thread=SDL_CreateThread(&SDL_DisplayThread,0); + const char * output=section->Get_string("output"); + if (!strcasecmp(output,"surface")) { + sdl.desktop.want_type=SCREEN_SURFACE; + } else if (!strcasecmp(output,"overlay")) { + sdl.desktop.want_type=SCREEN_OVERLAY; +#if C_OPENGL + } else if (!strcasecmp(output,"opengl")) { + sdl.desktop.want_type=SCREEN_OPENGL; + sdl.opengl.bilinear=true; + } else if (!strcasecmp(output,"openglnb")) { + sdl.desktop.want_type=SCREEN_OPENGL; + sdl.opengl.bilinear=false; #endif + } else { + LOG_MSG("SDL:Unsupported output device %s, switching back to surface",output); + sdl.desktop.want_type=SCREEN_SURFACE; + } + + sdl.overlay=0; +#if C_OPENGL + sdl.surface=SDL_SetVideoMode(640,400,0,SDL_OPENGL); + sdl.opengl.framebuf=0; + sdl.opengl.texture=0; + sdl.opengl.displaylist=0; + glGetIntegerv (GL_MAX_TEXTURE_SIZE, &sdl.opengl.max_texsize); +#if defined(__WIN32__) && defined(NVIDIA_PixelDataRange) + glPixelDataRangeNV = (PFNGLPIXELDATARANGENVPROC) wglGetProcAddress("glPixelDataRangeNV"); + db_glAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC) wglGetProcAddress("wglAllocateMemoryNV"); + db_glFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC) wglGetProcAddress("wglFreeMemoryNV"); +#endif + const char * gl_ext = (const char *)glGetString (GL_EXTENSIONS); + sdl.opengl.packed_pixel=strstr(gl_ext,"EXT_packed_pixels") > 0; + sdl.opengl.paletted_texture=strstr(gl_ext,"EXT_paletted_texture") > 0; +#if defined(NVIDIA_PixelDataRange) + sdl.opengl.pixel_data_range=strstr(gl_ext,"GL_NV_pixel_data_range") >0 && + glPixelDataRangeNV && db_glAllocateMemoryNV && db_glFreeMemoryNV; +#endif +#endif //OPENGL /* Initialize screen for first time */ sdl.surface=SDL_SetVideoMode(640,400,0,0); - if (sdl.surface->format->BitsPerPixel==24) { + sdl.desktop.bpp=sdl.surface->format->BitsPerPixel; + if (sdl.desktop.bpp==24) { LOG_MSG("SDL:You are running in 24 bpp mode, this will slow down things!"); } - GFX_SetSize(640,400,8,0,0,0); - SDL_EnableKeyRepeat(250,30); + GFX_SetSize(640,400,8,1.0,1.0,0); + SDL_EnableKeyRepeat(250,40); SDL_EnableUNICODE(1); /* Get some Keybinds */ KEYBOARD_AddEvent(KBD_f9,KBD_MOD_CTRL,KillSwitch); @@ -475,11 +765,8 @@ static void HandleKey(SDL_KeyboardEvent * key) { } static void HandleMouseMotion(SDL_MouseMotionEvent * motion) { - if (sdl.mouse.locked) { + if (sdl.mouse.locked) Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100,(float)motion->yrel*sdl.mouse.sensitivity/100); - } else { -// Mouse_CursorSet((float)motion->x/(float)sdl.width,(float)motion->y/(float)sdl.height); - } } static void HandleMouseButton(SDL_MouseButtonEvent * button) { @@ -538,14 +825,6 @@ static void HandleJoystickButton(SDL_JoyButtonEvent * jbutton) { } -static void HandleVideoResize(SDL_ResizeEvent * resize) { - - - - - -} - static Bit8u laltstate = SDL_KEYUP; void GFX_Events() { @@ -582,7 +861,7 @@ void GFX_Events() { HandleJoystickButton(&event.jbutton); break; case SDL_VIDEORESIZE: - HandleVideoResize(&event.resize); +// HandleVideoResize(&event.resize); break; case SDL_QUIT: throw(0); @@ -640,19 +919,32 @@ int main(int argc, char* argv[]) { ) < 0 ) E_Exit("Can't init SDL %s",SDL_GetError()); Section_prop * sdl_sec=control->AddSection_prop("sdl",&GUI_StartUp); sdl_sec->Add_bool("fullscreen",false); + sdl_sec->Add_bool("fulldouble",false); + sdl_sec->Add_bool("fullfixed",false); + sdl_sec->Add_int("fullwidth",0); + sdl_sec->Add_int("fullheight",0); + sdl_sec->Add_string("output","surface"); + sdl_sec->Add_float("hwscale",1.0); sdl_sec->Add_bool("autolock",true); sdl_sec->Add_int("sensitivity",100); sdl_sec->Add_bool("waitonerror",true); - /* Init all the dosbox subsystems */ - + MSG_Add("SDL_CONFIGFILE_HELP", "fullscreen -- Start dosbox directly in fullscreen.\n" + "fulldouble -- Use double buffering in fullscreen.\n" + "fullfixed -- Don't resize the screen when in fullscreen.\n" + "fullwidth/height -- What resolution to use for fullscreen, use together with fullfixed.\n" + "output -- What to use for output: surface,overlay" +#if C_OPENGL + ",opengl,openglnb" +#endif + ".\n" + "hwscale -- Extra scaling of window if the output device supports hardware scaling.\n" "autolock -- Mouse will automatically lock, if you click on the screen.\n" "sensitiviy -- Mouse sensitivity.\n" "waitonerror -- Wait before closing the console if dosbox has an error.\n" ); - - + /* Init all the dosbox subsystems */ DOSBOX_Init(); std::string config_file; if (control->cmdline->FindString("-conf",config_file,true)) { @@ -660,8 +952,19 @@ int main(int argc, char* argv[]) { } else { config_file="dosbox.conf"; } - /* Parse the config file */ - control->ParseConfigFile(config_file.c_str()); + /* Parse the config file + * try open config file in $HOME if can't open dosbox.conf or specified file + */ + if (control->ParseConfigFile(config_file.c_str()) == false) { + if ((getenv("HOME") != NULL)) { + config_file = (std::string)getenv("HOME") + + (std::string)DEFAULT_CONFIG_FILE; + if (control->ParseConfigFile(config_file.c_str()) == false) { + LOG_MSG("CONFIG: Using default settings. Create a configfile to change them"); + } + + } + } #if (ENVIRON_LINKED) control->ParseEnv(environ); #endif @@ -677,13 +980,15 @@ int main(int argc, char* argv[]) { } #endif if (control->cmdline->FindExist("-fullscreen") || sdl_sec->Get_bool("fullscreen")) { - SwitchFullScreen(); + if(!sdl.desktop.fullscreen) { //only switch if not allready in fullscreen + SwitchFullScreen(); + } } /* Start up main machine */ control->StartUp(); /* Shutdown everything */ } catch (char * error) { - if (sdl.full_screen) SwitchFullScreen(); + if (sdl.desktop.fullscreen) SwitchFullScreen(); if (sdl.mouse.locked) CaptureMouse(); LOG_MSG("Exit to error: %s",error); if(sdl.wait_on_error) { @@ -698,8 +1003,8 @@ int main(int argc, char* argv[]) { } catch (int){ - if (sdl.full_screen) SwitchFullScreen(); + if (sdl.desktop.fullscreen) SwitchFullScreen(); if (sdl.mouse.locked) CaptureMouse(); } - return 0; + return 0; }; diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am index efe5959..d5bb84f 100644 --- a/src/hardware/Makefile.am +++ b/src/hardware/Makefile.am @@ -6,7 +6,7 @@ noinst_LIBRARIES = libhardware.a libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \ memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \ - vga.cpp vga.h vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp \ + vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp \ vga_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h cmos.cpp disney.cpp \ gus.cpp mpu401.cpp serialport.cpp softmodem.cpp diff --git a/src/hardware/Makefile.in b/src/hardware/Makefile.in index 6e218a9..341f63d 100644 --- a/src/hardware/Makefile.in +++ b/src/hardware/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -137,7 +137,7 @@ noinst_LIBRARIES = libhardware.a libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler.cpp joystick.cpp keyboard.cpp \ memory.cpp mixer.cpp pcspeaker.cpp pic.cpp sblaster.cpp tandy_sound.cpp timer.cpp \ - vga.cpp vga.h vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp \ + vga.cpp vga_attr.cpp vga_crtc.cpp vga_dac.cpp vga_draw.cpp vga_gfx.cpp \ vga_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h cmos.cpp disney.cpp \ gus.cpp mpu401.cpp serialport.cpp softmodem.cpp @@ -372,7 +372,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -392,7 +392,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -417,7 +416,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/hardware/adlib.cpp b/src/hardware/adlib.cpp index 41db8d0..f792f9f 100644 --- a/src/hardware/adlib.cpp +++ b/src/hardware/adlib.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -109,6 +109,10 @@ static Bit8u read_p388(Bit32u port) { static void write_p388(Bit32u port,Bit8u val) { regsel=val; + + // The following writes this value to ultrasounds equivalent register. + // I don't know of any other way to do this + IO_Write(0x248,val); } static void write_p389(Bit32u port,Bit8u val) { diff --git a/src/hardware/cmos.cpp b/src/hardware/cmos.cpp index e44933b..47a63a3 100644 --- a/src/hardware/cmos.cpp +++ b/src/hardware/cmos.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/disney.cpp b/src/hardware/disney.cpp index 423582d..4baf3e2 100644 --- a/src/hardware/disney.cpp +++ b/src/hardware/disney.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -101,7 +101,7 @@ static void DISNEY_CallBack(Bit8u * stream,Bit32u len) { void DISNEY_Init(Section* sec) { MSG_Add("DISNEY_CONFIGFILE_HELP","Nothing to setup yet!\n"); Section_prop * section=static_cast(sec); - if(!section->Get_bool("enabled")) return; + if(!section->Get_bool("disney")) return; IO_RegisterWriteHandler(DISNEY_BASE,disney_write,"DISNEY"); IO_RegisterWriteHandler(DISNEY_BASE+1,disney_write,"DISNEY"); diff --git a/src/hardware/dma.cpp b/src/hardware/dma.cpp index 7a35d16..e951d8e 100644 --- a/src/hardware/dma.cpp +++ b/src/hardware/dma.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,11 +20,6 @@ Based the port handling from the bochs dma code. */ -/* - TODO - Implement 16-bit dma -*/ - #include #include "dosbox.h" #include "mem.h" @@ -32,259 +27,385 @@ #include "dma.h" #include "pic.h" -#define DMA_MODE_DEMAND 0 -#define DMA_MODE_SINGLE 1 -#define DMA_MODE_BLOCK 2 -#define DMA_MODE_CASCADE 3 - -struct DMA_CHANNEL { - struct { - Bit8u mode_type; - bool address_decrement; - bool autoinit_enable; - Bit8u transfer_type; - } mode; - Bit16u base_address; - Bit16u base_count; - Bit16u current_address; - Bitu current_count; - Bit8u page; - bool masked; - PhysPt address; - bool addr_changed; - bool enabled; - DMA_EnableCallBack enable_callback; -}; +DmaChannel *DmaChannels[8]; +DmaController *DmaControllers[2]; -struct DMA_CONTROLLER { - bool flipflop; - Bit8u status_reg; - Bit8u command_reg; - DMA_CHANNEL chan[4]; -}; +Bit16u DmaController::portRead(Bit32u port, bool eightbit) { + LOG_MSG("Reading DMA controller at %x", port); + return 0xffff; +} -static DMA_CONTROLLER dma[2]; - -void DMA_CheckEnabled(DMA_CHANNEL * chan); -void DMA_SetEnabled(DMA_CHANNEL * chan,bool enabled); - -static Bit8u read_dma(Bit32u port) { - /* only use first dma for now */ - DMA_CONTROLLER * cont=&dma[0]; - DMA_CHANNEL * chan=&cont->chan[port>>1]; - Bit8u ret; - switch (port) { - case 0x00:case 0x02:case 0x04:case 0x06: - if (cont->flipflop) { - ret=chan->current_address & 0xff; - } else { - ret=(chan->current_address>>8)&0xff; - } - cont->flipflop=!cont->flipflop; - break; - case 0x01:case 0x03:case 0x05:case 0x07: - if (cont->flipflop) { - ret=(Bit8u)((chan->current_count-1) & 0xff); - } else { - ret=(Bit8u)(((chan->current_count-1)>>8)&0xff); - } - cont->flipflop=!cont->flipflop; - break; - case 0x08: /* Read Status */ - ret=cont->status_reg; - cont->status_reg&=~0xf; /* Clear lower 4 bits on read */ - break; - case 0x0a: - case 0x0e: - /* Seem to return 0 on a real controller */ - ret=0x0; - break; - default: - LOG(LOG_DMA,LOG_ERROR)("DMA:Unhandled read from %X",port); +void DmaController::portWrite(Bit32u port, Bit16u val, bool eightbit) { + bool found; + found = false; + if(port == ControllerPorts[ctrlnum][DMA_CLRMASKREG]) { + found = true; + flipflop = true; + // Disable DMA requests + // Clear command and status registers } -// LOG_MSG("DMA Read port %x result %x",port,ret); - return ret; -} - -static void write_dma(Bit32u port,Bit8u val) { - /* only use first dma for now */ - DMA_CONTROLLER * cont=&dma[0]; - DMA_CHANNEL * chan; - switch (port) { - case 0x00:case 0x02:case 0x04:case 0x06: - chan=&cont->chan[port>>1]; - if (cont->flipflop) { - chan->base_address=(chan->base_address & 0xff00) | val; - } else { - chan->base_address=(chan->base_address & 0x00ff) | (val<<8); - } - cont->flipflop=!cont->flipflop; - chan->addr_changed=true; - break; - case 0x01:case 0x03:case 0x05:case 0x07: - chan=&cont->chan[port>>1]; - if (cont->flipflop) { - chan->base_count=(chan->base_count & 0xff00) | val; - } else { - chan->base_count=(chan->base_count & 0x00ff) | (val<<8); - } - cont->flipflop=!cont->flipflop; - chan->addr_changed=true; - DMA_CheckEnabled(chan); - break; - case 0x08: /* Command Register */ - if (val != 4) LOG(LOG_DMA,LOG_ERROR)("DMA1:Illegal command %2X",val); - cont->command_reg=val; - break; - case 0x09: /* Request Register */ - if (val&4) { - /* Set Request bit */ - Bitu channel = val & 0x03; - cont->status_reg |= (1 << (channel+4)); - } else { - Bitu channel = val & 0x03; - cont->status_reg &= ~(1 << (channel+4)); - } - break; - case 0x0a: /* single mask bit register */ - chan=&cont->chan[val & 0x3]; - if ((val & 4)>0) { - DMA_SetEnabled(chan,false); - chan->masked=(val & 4)>0; //Set it later - } else { - chan->masked=(val & 4)>0; - DMA_CheckEnabled(chan); - } - break; - case 0x0b: /* mode register */ - chan=&cont->chan[val & 0x3]; - chan->mode.mode_type = (val >> 6) & 0x03; - chan->mode.address_decrement = (val & 0x20) > 0; - chan->mode.autoinit_enable = (val & 0x10) > 0; - chan->mode.transfer_type = (val >> 2) & 0x03; - if (chan->mode.address_decrement) { - LOG(LOG_DMA,LOG_ERROR)("DMA:Address Decrease not supported yet"); - } - DMA_CheckEnabled(chan); - break; - case 0x0c: /* Clear Flip/Flip */ - cont->flipflop=true; - break; - default: - LOG(LOG_DMA,LOG_ERROR)("DMA:Unhandled write %X to %X",static_cast(val),port); - }; -}; - -void write_dma_page(Bit32u port,Bit8u val) { - Bitu channel; - switch (port) { - case 0x81: /* dma0 page register, channel 2 */ - channel=2;break; - case 0x82: /* dma0 page register, channel 3 */ - channel=3;break; - case 0x83: /* dma0 page register, channel 1 */ - channel=1;break; - case 0x87: /* dma0 page register, channel 0 */ - channel=0;break; + if(port == ControllerPorts[ctrlnum][DMA_SINGLEREG]) { + found = true; + int dmachan; + dmachan = (ctrlnum * 2) + (val & 0x3); + DmaChannels[dmachan]->masked = ((val & 0x4) == 0x4); + DmaChannels[dmachan]->Notify(); } - dma[0].chan[channel].page=val; - dma[0].chan[channel].addr_changed=true; -} + if(port == ControllerPorts[ctrlnum][DMA_WRITEALLREG]) { + found = true; + int dmachan,i,r; + dmachan = (ctrlnum * 2); + r = 0; + for(i=dmachan;imasked = (((val >> r) & 0x1) == 0x1); + DmaChannels[i]->Notify(); + r++; + } -Bit8u read_dma_page(Bit32u port) { - Bitu channel; - switch (port) { - case 0x81: /* dma0 page register, channel 2 */ - channel=2;break; - case 0x82: /* dma0 page register, channel 3 */ - channel=3;break; - case 0x83: /* dma0 page register, channel 1 */ - channel=1;break; - case 0x87: /* dma0 page register, channel 0 */ - channel=0;break; } - return dma[0].chan[channel].page; + if(port == ControllerPorts[ctrlnum][DMA_CLEARREG]) { + found = true; + flipflop = true; + } + if(port == ControllerPorts[ctrlnum][DMA_MODEREG]) { + found = true; + int dmachan; + dmachan = (ctrlnum * 2) + (val & 0x3); + DmaChannels[dmachan]->trantype = (val >> 2) & 0x3; + DmaChannels[dmachan]->autoinit = ((val & 0x10) == 0x10); + DmaChannels[dmachan]->dir = ((val & 0x20) == 0x20); + DmaChannels[dmachan]->dmamode = (val >> 6) & 0x3; + DmaChannels[dmachan]->Notify(); + } + if(!found) LOG_MSG("Write to DMA port %x with %x", port, val); + } -INLINE void ResetDMA8(DMA_CHANNEL * chan) { - chan->addr_changed=false; - chan->address=(chan->page << 16)+chan->base_address; - chan->current_count=chan->base_count+1; - chan->current_address=chan->base_address; - LOG(LOG_DMA,LOG_NORMAL)("Setup at address %X:%X count %X",chan->page<<12,chan->base_address,chan->current_count); + +Bit32u DmaChannel::Read(Bit32s requestsize, Bit8u * buffer) { + Bit32s bytesread; + bytesread = 0; + if(autoinit) { + while(requestsize>0) { + if(currcnt>=requestsize) { + MEM_BlockRead(curraddr,buffer,requestsize); + curraddr+=requestsize; + buffer+=requestsize; + currcnt-=requestsize; + bytesread+=requestsize; + requestsize=0; + break; + } else { + MEM_BlockRead(curraddr,buffer,currcnt); + bytesread+=currcnt; + buffer+=currcnt; + requestsize-=currcnt; + reset(); + MakeCallback(true); + } + } + if(currcnt==0) { + reset(); + MakeCallback(true); + } + return bytesread; + + } else { + if(currcnt>=requestsize) { + MEM_BlockRead(curraddr,buffer,requestsize); + curraddr+=requestsize; + buffer+=requestsize; + currcnt-=requestsize; + bytesread+=requestsize; + } else { + MEM_BlockRead(curraddr,buffer,currcnt); + buffer+=currcnt; + requestsize-=currcnt; + bytesread+=currcnt; + currcnt=0; + } + } + if(currcnt==0) MakeCallback(true); + return bytesread; } +Bit32u DmaChannel::Write(Bit32s requestsize, Bit8u * buffer) { + Bit32s byteswrite; + byteswrite = 0; + if(autoinit) { + while(requestsize>0) { + if(currcnt>=requestsize) { + MEM_BlockWrite(curraddr,buffer,requestsize); + curraddr+=requestsize; + buffer+=requestsize; + currcnt-=requestsize; + byteswrite+=requestsize; + requestsize=0; + break; + } else { + MEM_BlockWrite(curraddr,buffer,currcnt); + byteswrite+=currcnt; + buffer+=currcnt; + requestsize-=currcnt; + reset(); + MakeCallback(true); + } + } + if(currcnt==0) { + reset(); + MakeCallback(true); + } + return byteswrite; + + } else { + if(currcnt>=requestsize) { + MEM_BlockWrite(curraddr,buffer,requestsize); + curraddr+=requestsize; + buffer+=requestsize; + currcnt-=requestsize; + byteswrite+=requestsize; + } else { + MEM_BlockWrite(curraddr,buffer,currcnt); + buffer+=currcnt; + requestsize-=currcnt; + byteswrite+=currcnt; + currcnt=0; + } + } + if(currcnt==0) MakeCallback(true); + return byteswrite; +} + + +void DmaChannel::calcPhys(void) { + if (DMA16) { + physaddr = (baseaddr << 1) | ((pageaddr >> 1) << 17); + } else { + physaddr = (baseaddr) | (pageaddr << 16); + } + curraddr = physaddr; + current_addr = baseaddr; +} + +#define ff myController->flipflop + +Bit16u DmaChannel::portRead(Bit32u port, bool eightbit) { + if (port == ChannelPorts[DMA_BASEADDR][channum]) { + if(eightbit) { + if(ff) { + ff = !ff; + return current_addr & 0xff; + } else { + ff = !ff; + return current_addr >> 8; + } + } else { + return current_addr; + } + } + if (port == ChannelPorts[DMA_TRANSCOUNT][channum]) { + if(eightbit) { + if(ff) { + ff = !ff; + return (Bit8u)(currcnt-1); + } else { + ff = !ff; + return (Bit8u)((currcnt-1) >> 8); + } + } else { + return (Bit16u)currcnt; + } + } + if (port == ChannelPorts[DMA_PAGEREG][channum]) return pageaddr; + return 0xffff; +} + +void DmaChannel::portWrite(Bit32u port, Bit16u val, bool eightbit) { + if (port == ChannelPorts[DMA_BASEADDR][channum]) { + if(eightbit) { + if(ff) { + baseaddr = (baseaddr & 0xff00) | (Bit8u)val; + } else { + baseaddr = (baseaddr & 0xff) | (val << 8); + } + ff = !ff; + } else { + baseaddr = val; + } + calcPhys(); + addr_changed = true; + } + if (port == ChannelPorts[DMA_TRANSCOUNT][channum]) { + if(eightbit) { + if(ff) { + transcnt = (transcnt & 0xff00) | (Bit8u)val; + } else { + transcnt = (transcnt & 0xff) | (val << 8); + } + ff = !ff; + } else { + transcnt = val; + } + currcnt = transcnt+1; + addr_changed = true; + DMA_CheckEnabled(this); + MakeCallback(false); + + } + if (port == ChannelPorts[DMA_PAGEREG][channum]) { + pageaddr = val; + calcPhys(); + reset(); + } + +} + +#undef ff + +// Notify channel when mask changes +void DmaChannel::Notify(void) { + if(!masked) { + DMA_CheckEnabled(this); + MakeCallback(false); + } +} + + +static Bit16u readDMAPorts(Bit32u port, bool eightbit) { + int i,j; + + // Check for controller access + for(i=0;i<2;i++) { + for(j=0;j<7;j++) { + if(ControllerPorts[i][j] == port) { + return DmaControllers[i]->portRead(port, eightbit); + } + } + } + + // Check for DMA access + for(i=0;i<8;i++) { + for(j=0;j<3;j++) { + if(ChannelPorts[j][i] == port) { + return DmaChannels[i]->portRead(port, eightbit); + } + } + } + + LOG_MSG("Unmatched read port %x", port); + + return 0xffff; + +} + +static void writeDMAPorts(Bit32u port, Bit16u val, bool eightbit) { + int i,j; + + // Check for controller access + for(i=0;i<2;i++) { + for(j=0;j<7;j++) { + if(ControllerPorts[i][j] == port) { + DmaControllers[i]->portWrite(port,val,eightbit); + return; + } + } + } + + // Check for DMA access + for(i=0;i<8;i++) { + for(j=0;j<3;j++) { + if(ChannelPorts[j][i] == port) { + DmaChannels[i]->portWrite(port,val,eightbit); + return; + } + } + } + + LOG_MSG("Unmatched write port %x - val %x", port, val); + +} + +Bit8u read_dmaB(Bit32u port) { return (Bit8u)readDMAPorts(port,true); } + +Bit16u read_dmaW(Bit32u port) { return readDMAPorts(port,false); } + +void write_dmaB(Bit32u port,Bit8u val) { writeDMAPorts(port,val,true); } + +void write_dmaW(Bit32u port,Bit16u val) { writeDMAPorts(port,val,false); } + + +// Deprecated DMA read/write routines -- Keep compatibility with Sound Blaster Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { - DMA_CHANNEL * chan=&dma[0].chan[dmachan]; + DmaChannel *chan=DmaChannels[dmachan]; + if (chan->masked) return 0; if (!count) return 0; - if (chan->addr_changed) ResetDMA8(chan); - if (chan->current_count>count) { - MEM_BlockRead(chan->address,buffer,count); - chan->address+=count; - chan->current_address+=count; - chan->current_count-=count; + if (chan->addr_changed) chan->reset(); + + if (chan->currcnt>(Bits)count) { + MEM_BlockRead(chan->curraddr,buffer,count); + chan->curraddr+=count; + chan->current_addr+=count; + chan->currcnt-=count; return count; } else { - /* Copy remaining piece of first buffer */ - MEM_BlockRead(chan->address,buffer,chan->current_count); - if (!chan->mode.autoinit_enable) { - /* Set the end of counter bit */ - dma[0].status_reg|=(1 << dmachan); - count=chan->current_count; - chan->address+=count; - chan->current_count=0; + // Copy remaining piece of first buffer + MEM_BlockRead(chan->curraddr,buffer,chan->currcnt); + if (!chan->autoinit) { + // Set the end of counter bit + //dma[0].status_reg|=(1 << dmachan); + count=chan->currcnt; + chan->curraddr+=count; + chan->current_addr+=count; + chan->currcnt=0; chan->enabled=false; - LOG(LOG_DMA,LOG_NORMAL)("8-bit Channel %d reached terminal count"); + LOG(LOG_DMA,LOG_NORMAL)("8-bit Channel %d reached terminal count",chan->channum); return count; } else { - buffer+=chan->current_count; - Bitu left=count-(Bit16u)chan->current_count; - /* Autoinit reset the dma channel */ - ResetDMA8(chan); - /* Copy the rest of the buffer */ - MEM_BlockRead(chan->address,buffer,left); - chan->address+=left; - chan->current_address+=left; - chan->current_count-=left; + buffer+=chan->currcnt; + Bitu left=count-(Bit16u)chan->currcnt; + // Autoinit reset the dma channel + chan->reset(); + // Copy the rest of the buffer + MEM_BlockRead(chan->curraddr,buffer,left); + chan->curraddr+=left; + chan->current_addr+=left; + chan->currcnt-=left; return count; } } } Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { - DMA_CHANNEL * chan=&dma[0].chan[dmachan]; + DmaChannel *chan=DmaChannels[dmachan]; + if (chan->masked) return 0; if (!count) return 0; - if (chan->addr_changed) ResetDMA8(chan); - if (chan->current_count>count) { - MEM_BlockWrite(chan->address,buffer,count); - chan->address+=count; - chan->current_address+=count; - chan->current_count-=count; + if (chan->currcnt>(Bits)count) { + MEM_BlockWrite(chan->curraddr,buffer,count); + chan->curraddr+=count; + chan->currcnt-=count; return count; } else { - /* Copy remaining piece of first buffer */ - MEM_BlockWrite(chan->address,buffer,chan->current_count); - if (!chan->mode.autoinit_enable) { - /* Set the end of counter bit */ - dma[0].status_reg|=(1 << dmachan); - count=chan->current_count; - chan->current_address+=count;; - chan->current_count=0; - chan->enabled=false; + // Copy remaining piece of first buffer + MEM_BlockWrite(chan->curraddr,buffer,chan->currcnt); + if (!chan->autoinit) { + // Set the end of counter bit + //dma[0].status_reg|=(1 << dmachan); + count=chan->currcnt; + chan->curraddr+=count;; + chan->currcnt=0; return count; } else { - buffer+=chan->current_count; - Bitu left=count-(Bit16u)chan->current_count; - /* Autoinit reset the dma channel */ - ResetDMA8(chan); - /* Copy the rest of the buffer */ - MEM_BlockWrite(chan->address,buffer,left); - chan->address+=left; - chan->current_address+=left; - chan->current_count-=left; + buffer+=chan->currcnt; + Bitu left=count-(Bit16u)chan->currcnt; + // Autoinit reset the dma channel + chan->reset(); + // Copy the rest of the buffer + MEM_BlockWrite(chan->curraddr,buffer,left); + chan->curraddr+=left; + chan->currcnt-=left; return count; } } @@ -302,18 +423,24 @@ Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { return 0; } -void DMA_SetEnabled(DMA_CHANNEL * chan,bool enabled) { +void DMA_SetEnabled(void * usechan,bool enabled) { + DmaChannel * chan; + chan = (DmaChannel *)usechan; + if (chan->enabled == enabled) return; chan->enabled=enabled; if (chan->enable_callback) (*chan->enable_callback)(enabled); } -void DMA_CheckEnabled(DMA_CHANNEL * chan) { +void DMA_CheckEnabled(void * usechan) { + DmaChannel * chan; + chan = (DmaChannel *)usechan; + bool enabled; if (chan->masked) enabled=false; else { - if (chan->mode.autoinit_enable) enabled=true; - else if (chan->current_count || chan->addr_changed) enabled=true; + if (chan->autoinit) enabled=true; + else if (chan->currcnt) enabled=true; else enabled=false; } DMA_SetEnabled(chan,enabled); @@ -321,31 +448,28 @@ void DMA_CheckEnabled(DMA_CHANNEL * chan) { void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback) { - DMA_CHANNEL * chan; - if (channel<4) { - chan=&dma[0].chan[channel]; - } else if (channel<8) { - chan=&dma[1].chan[channel-4]; - } else return; + DmaChannel * chan; + chan = DmaChannels[channel]; chan->enabled=false; chan->enable_callback=callback; DMA_CheckEnabled(chan); } -void DMA_Init(Section* sec) { - Bitu i; - for (i=0;i<0x10;i++) { - IO_RegisterWriteHandler(i,write_dma,"DMA1"); - IO_RegisterReadHandler(i,read_dma,"DMA1"); - } - IO_RegisterWriteHandler(0x81,write_dma_page,"DMA Pages"); - IO_RegisterWriteHandler(0x82,write_dma_page,"DMA Pages"); - IO_RegisterWriteHandler(0x83,write_dma_page,"DMA Pages"); - IO_RegisterWriteHandler(0x87,write_dma_page,"DMA Pages"); - IO_RegisterReadHandler(0x81,read_dma_page,"DMA Pages"); - IO_RegisterReadHandler(0x82,read_dma_page,"DMA Pages"); - IO_RegisterReadHandler(0x83,read_dma_page,"DMA Pages"); - IO_RegisterReadHandler(0x87,read_dma_page,"DMA Pages"); +void DMA_Init(Section* sec) { + + Bitu i; + + DmaControllers[0] = new DmaController(0); + DmaControllers[1] = new DmaController(1); + + for(i=0;i<4;i++) { + DmaChannels[i] = new DmaChannel(i,DmaControllers[0],false); + } + for(i=4;i<8;i++) { + DmaChannels[i] = new DmaChannel(i,DmaControllers[1],true); + } } + + diff --git a/src/hardware/gameblaster.cpp b/src/hardware/gameblaster.cpp index 29f6568..f877bf4 100644 --- a/src/hardware/gameblaster.cpp +++ b/src/hardware/gameblaster.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/gus.cpp b/src/hardware/gus.cpp index bb71639..b5a1e51 100644 --- a/src/hardware/gus.cpp +++ b/src/hardware/gus.cpp @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2002-2004 The DOSBox Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library 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 #include "dosbox.h" #include "inout.h" @@ -7,17 +25,1092 @@ #include "hardware.h" #include "setup.h" #include "programs.h" +#include "math.h" +#include "regs.h" + + +#define GUS_BASE myGUS.portbase +#define GUS_RATE myGUS.rate +#define LOG_GUS + +static MIXER_Channel * gus_chan; + +static Bit16u vol8bit[256]; +static Bit16s vol16bit[4096]; + +static Bit8u irqtable[8] = { 0, 2, 5, 3, 7, 11, 12, 15 }; + +static Bit8u dmatable[6] = { 3, 1, 5, 5, 6, 7 }; + +static Bit8u GUSRam[1024*1024]; // 1024K of GUS Ram + +struct GFGus { + Bit8u gRegSelect; + Bit16u gRegData; + Bit32u gDramAddr; + Bit16u gCurChannel; + + Bit8u DMAControl; + Bit16u dmaAddr; + Bit8u TimerControl; + Bit8u SampControl; + Bit8u mixControl; + + Bit32u basefreq; + Bit16u activechan; + Bit32s mupersamp; + Bit32s muperchan; + + + Bit16u timerReg; + struct GusTimer { + Bit16u bytetimer; + Bit32s countdown; + Bit32s setting; + bool active; + } timers[2]; + + + Bit32u rate; + Bit16u portbase; + Bit16u dma1; + Bit16u dma2; + + Bit16u irq1; + Bit16u irq2; + + char ultradir[512]; + + bool irqenabled; + + // IRQ status register values + struct IRQStat { + bool MIDITx; + bool MIDIRx; + bool T1; + bool T2; + bool Resv; + bool WaveTable; + bool VolRamp; + bool DMATC; + } irq; + +} myGUS; + +#define GUSFIFOSIZE 1024 + +static void UseDMA(DmaChannel *useDMA); + +struct IRQFifoEntry { + Bit8u channum; + bool WaveIRQ; + bool RampIRQ; +}; + +struct IRQFifoDef { + IRQFifoEntry entry[GUSFIFOSIZE]; + Bit16s stackpos; +} IRQFifo; + + +// Routines to manage IRQ requests coming from the GUS +static void pushIRQ(Bit8u channum, bool WaveIRQ, bool RampIRQ) { + IRQFifo.stackpos++; + if(IRQFifo.stackpos < GUSFIFOSIZE) { + myGUS.irq.WaveTable = WaveIRQ; + myGUS.irq.VolRamp = RampIRQ; + + IRQFifo.entry[IRQFifo.stackpos].channum = channum; + IRQFifo.entry[IRQFifo.stackpos].RampIRQ = RampIRQ; + IRQFifo.entry[IRQFifo.stackpos].WaveIRQ = WaveIRQ; + } else { + LOG_GUS("GUS IRQ Fifo full!"); + } +} + +static void popIRQ(IRQFifoEntry * tmpentry) { + if(IRQFifo.stackpos<0) { + tmpentry->channum = 0; + tmpentry->RampIRQ = false; + tmpentry->WaveIRQ = false; + return; + } + memcpy(tmpentry, &IRQFifo.entry[IRQFifo.stackpos], sizeof(IRQFifoEntry)); + --IRQFifo.stackpos; + if(IRQFifo.stackpos >= 0) { + myGUS.irq.WaveTable = IRQFifo.entry[IRQFifo.stackpos].WaveIRQ; + myGUS.irq.VolRamp = IRQFifo.entry[IRQFifo.stackpos].RampIRQ; + } else { + myGUS.irq.WaveTable = false; + myGUS.irq.VolRamp = false; + } +} + + +// Returns a single 16-bit sample from the Gravis's RAM +INLINE Bit16s GetSample(Bit32u Delta, Bit32u CurAddr, bool eightbit) { + Bit32u useAddr; + Bit32u holdAddr; + useAddr = CurAddr >> 9; + if(eightbit) { + if(Delta >= 1024) { + Bit8s tmpsmall = (Bit8s)GUSRam[useAddr]; + return (Bit16s)(tmpsmall << 7); + } else { + + // Interpolate + Bit8s b1 = (Bit8s)GUSRam[useAddr]; + Bit8s b2 = (Bit8s)GUSRam[useAddr+1]; + Bit16s w1 = b1 << 7; + Bit16s w2 = b2 << 7; + Bit16s diff = w2 - w1; + return (Bit16s)(w1 + (((Bit32s)diff * (Bit32s)(CurAddr & 0x3fe)) >> 10)); + + } + } else { + + // Formula used to convert addresses for use with 16-bit samples + holdAddr = useAddr & 0xc0000L; + useAddr = useAddr & 0x1ffffL; + useAddr = useAddr << 1; + useAddr = (holdAddr | useAddr); + + if(Delta >= 1024) { + + return (Bit16s)((Bit16u)GUSRam[useAddr] | ((Bit16u)GUSRam[useAddr+1] << 8)) >> 2 + ; + + } else { + + // Interpolate + Bit16s w1 = (Bit16s)((Bit16u)GUSRam[useAddr] | ((Bit16u)GUSRam[useAddr+1] << 8)); + Bit16s w2 = (Bit16s)((Bit16u)GUSRam[useAddr+2] | ((Bit16u)GUSRam[useAddr+3] << 8)); + Bit16s diff = w2 - w1; + return (Bit16s)(w1 + (((Bit32s)diff * (Bit32s)((CurAddr) & 0x3fe)) >> 10)) >> 2; + + } + } +} + +class GUSChannels { +public: + Bit8u voiceCont; + Bit16u FreqCont; + Bit32u RealDelta; + Bit32u StartAddr; + Bit32u EndAddr; + Bit8s VolRampRate; + Bit16s VolRampStart; + Bit16s VolRampEnd; + Bit8u VolRampStartOrg; + Bit8u VolRampEndOrg; + Bit32s CurVolume; + Bit32u CurAddr; + Bit8u PanPot; + Bit8u VolControl; + Bit8u channum; + + bool moving; + bool playing; + bool ramping; + bool dir; + bool voldir; + +public: + bool notifyonce; + Bit32s leftvol; + Bit32s rightvol; + Bit32s nextramp; + + GUSChannels(Bit8u num) { + channum = num; + playing = true; + ramping = false; + moving = false; + dir = false; + voldir = false; + StartAddr = 0; + EndAddr = 0; + CurAddr = 0; + VolRampRate = 0; + VolRampStart = 0; + VolRampEnd = 0; + leftvol = 255; + rightvol = 255; + nextramp = 0; + + }; + + // Voice control register + void WriteVoiceCtrl(Bit8u val) { + voiceCont = val; + if (val & 0x3) moving = false; + if ((val & 0x3) == 0) { + //playing = true; + moving = true; + } + dir = false; + if((val & 0x40) !=0) dir = true; + + } + Bit8u ReadVoiceCtrl(void) { + Bit8u tmpval = voiceCont & 0xfe; + if(!playing) tmpval++; + return tmpval; + } + + // Frequency control register + void WriteFreqCtrl(Bit16u val) { + FreqCont = val; + int fc; + fc = val; + fc = fc >> 1; + fc = fc * myGUS.basefreq; + fc = fc - (myGUS.basefreq >> 1); + fc = fc / 512; + float simple; + + simple = ((float)fc / (float)GUS_RATE) * 512; + RealDelta = (Bit32u)simple; + } + Bit16u ReadFreqCtrl(void) { + return FreqCont; + } + + // Used when GUS changes channel numbers during playback + void UpdateFreqCtrl() { WriteFreqCtrl(FreqCont); } + + // Pan position register + void WritePanPot(Bit8u val) { + if(val<8) { + leftvol = 255; + rightvol = val << 5; + } else { + rightvol = 255; + leftvol = (8-(val-8)) << 5; + } + PanPot = val; + } + Bit8u ReadPanPot(void) { + return PanPot; + } + + // Volume ramping control register + void WriteVolControl(Bit8u val) { + VolControl = val; + if (val & 0x3) ramping = false; + if ((val & 0x3) == 0) ramping = true; + voldir = false; + if((val & 0x40) !=0) voldir = true; + + } + Bit8u ReadVolControl(void) { + Bit8u tmpval = VolControl & 0xfe; + if(!ramping) tmpval++; + return tmpval; + } + + + // Methods to queue IRQ on ramp or sample end + void NotifyEndSamp(void) { + if(!notifyonce) { + if((voiceCont & 0x20) != 0) { + pushIRQ(channum,true,false); + notifyonce = true; + } + } + } + void NotifyEndRamp(void) { + if(!notifyonce) { + if((VolControl & 0x20) != 0) { + pushIRQ(channum,false,true); + notifyonce = true; + } + } + } + + // Debug routine to show current channel position + void ShowAddr(void) { + LOG_GUS("Chan %d Start %d End %d Current %d", channum, StartAddr>>9, EndAddr>>9, CurAddr>>9); + } + + + // Generate the samples required by the callback routine + // It should be noted that unless a channel is stopped, it will + // continue to return the sample it is pointing to, regardless + // of whether or not the channel is moving or ramping. + void generateSamples(Bit16s * stream,Bit32u len) { + int i; + Bit16s tmpsamp; + bool eightbit; + eightbit = ((voiceCont & 0x4) == 0); + + notifyonce = false; + + for(i=0;i<(int)len;i++) { + // Get sample + tmpsamp = GetSample(RealDelta, CurAddr, eightbit); + + // Clip and convert log scale to PCM scale + if(CurVolume>4095) CurVolume = 4095; + if(CurVolume<0) CurVolume = 0; + tmpsamp = (tmpsamp * vol16bit[CurVolume]) >> 12; + + // Output stereo sample + stream[i<<1] = (Bit16s)(((Bit32s)tmpsamp * (Bit32s)leftvol)>>8) ; + stream[(i<<1)+1] = (Bit16s)(((Bit32s)tmpsamp * rightvol)>>8); + + + if(dir) { + // Increment backwards + if (moving) CurAddr -= RealDelta; + + //Thought 16-bit needed this + //if ((!eightbit) && (moving)) CurAddr -= RealDelta; + + if(CurAddr <= StartAddr) { + if((VolControl & 0x4) == 0) { + if((voiceCont & 0x8) != 0) { + if((voiceCont & 0x10) != 0) { + dir = !dir; + } else { + CurAddr = EndAddr; + } + + } else { + moving = false; + } + NotifyEndSamp(); + } else { + NotifyEndSamp(); + + } + + } + + } else { + + // Increment forwards + if (moving) CurAddr += RealDelta; + + //Thought 16-bit needed this + //if ((!eightbit) && (moving)) CurAddr += RealDelta; + if(CurAddr >= EndAddr) { + if((VolControl & 0x4) == 0) { + if((voiceCont & 0x8) != 0) { + if((voiceCont & 0x10) != 0) { + dir = !dir; + } else { + CurAddr = StartAddr; + } + + } else { + moving = false; + } + NotifyEndSamp(); + } else { + NotifyEndSamp(); + } + } + } + + // Update volume + if(ramping) { + + // Subtract ramp counter by elapsed microseconds + nextramp -= myGUS.mupersamp; + bool flagged; + flagged = false; + + // Ramp volume until nextramp is a positive integer + while(nextramp <= 0) { + if(voldir) { + CurVolume -= (VolRampRate & 0x3f); + if (CurVolume <= 0) { + CurVolume = 0; + flagged = true; + } + + if((vol16bit[CurVolume]<=VolRampStart) || (flagged)){ + if((VolControl & 0x8) != 0) { + if((VolControl & 0x10) != 0) { + voldir = !voldir; + } else { + CurVolume = VolRampEndOrg; + } + } else { + ramping = false; + } + NotifyEndRamp(); + } + + } else { + CurVolume += (VolRampRate & 0x3f); + if (CurVolume >= 4095) { + CurVolume = 4095; + flagged = true; + } + + if((vol16bit[CurVolume]>=VolRampEnd) || (flagged)){ + if((VolControl & 0x8) != 0) { + if((VolControl & 0x10) != 0) { + voldir = !voldir; + } else { + CurVolume = VolRampStartOrg; + } + } else { + ramping = false; + } + NotifyEndRamp(); + } + + } + + + switch(VolRampRate >> 6) { + case 0: + nextramp += myGUS.muperchan; + break; + case 1: + nextramp += myGUS.muperchan* 8; + break; + case 2: + nextramp += myGUS.muperchan * 64; + break; + case 3: + nextramp += myGUS.muperchan * 512; + break; + default: + nextramp += myGUS.muperchan * 512; + break; + + } + + } + + } + + + } + + + } + + +}; + + +GUSChannels *guschan[33]; + +GUSChannels *curchan; + + +static void GUSReset(void) +{ + if((myGUS.gRegData & 0x1) == 0x1) { + // Reset + myGUS.timerReg = 85; + memset(&myGUS.irq, 0, sizeof(myGUS.irq)); + } + if((myGUS.gRegData & 0x4) != 0) { + myGUS.irqenabled = true; + } else { + myGUS.irqenabled = false; + } + + myGUS.timers[0].active = false; + myGUS.timers[1].active = false; + myGUS.timers[0].bytetimer = 0x0; + myGUS.timers[1].bytetimer = 0x0; + + // Stop all channels + int i; + for(i=0;i<32;i++) { + guschan[i]->WriteVoiceCtrl(0x3); + + } + IRQFifo.stackpos = -1; + +} -void GUS_Init(Section* sec) { - MSG_Add("GUS_CONFIGFILE_HELP","Nothing to setup yet!\n"); +static Bit16u ExecuteReadRegister(void) { + Bit8u tmpreg; + switch (myGUS.gRegSelect) { + case 0x41: // Dma control register - read acknowledges DMA IRQ + tmpreg = myGUS.DMAControl & 0xbf; + if(myGUS.irq.DMATC) tmpreg |= 0x40; + + myGUS.irq.DMATC = false; + PIC_DeActivateIRQ(myGUS.irq1); + + return (Bit16u)(tmpreg << 8); + case 0x42: // Dma address register + return myGUS.dmaAddr; + case 0x45: // Timer control register. Identical in operation to Adlib's timer + return (Bit16u)(myGUS.TimerControl << 8); + break; + case 0x49: // Dma sample register + tmpreg = myGUS.DMAControl & 0xbf; + if(myGUS.irq.DMATC) tmpreg |= 0x40; + + myGUS.irq.DMATC = false; + PIC_DeActivateIRQ(myGUS.irq1); + //LOG_MSG("Read sampling status, returned 0x%x", tmpreg); + + return (Bit16u)(tmpreg << 8); + case 0x80: // Channel voice control read register + if(curchan != NULL) { + Bit8u sndout; + sndout = curchan->voiceCont & 0xFC; + if(!curchan->moving) sndout |= 0x3; + + return (Bit16u)(sndout<< 8); + } else return 0x0300; + + case 0x82: // Channel MSB address register + if(curchan != NULL) { + return (curchan->StartAddr >> 16); + } else return 0x0000; + case 0x83: // Channel LSW address register + if(curchan != NULL) { + return (curchan->StartAddr & 0xffff); + } else return 0x0000; + case 0x89: // Channel volume register + if(curchan != NULL) { + return (curchan->CurVolume << 4); + } else return 0x0000; + case 0x8a: // Channel MSB current address register + if(curchan != NULL) { + return (curchan->CurAddr >> 16); + } else return 0x0000; + + case 0x8b: // Channel LSW current address register + if(curchan != NULL) { + return (curchan->CurAddr & 0xFFFF); + } else return 0x0000; + case 0x8d: // Channel volume control register + if(curchan != NULL) { + Bit8u volout; + volout = curchan->VolControl & 0xFC; + if(!curchan->ramping) volout |= 0x3; + return (volout << 8); + } else return 0x0300; + + case 0x8f: // General channel IRQ status register + Bit8u temp; + temp = 0x20; + IRQFifoEntry tmpentry; + PIC_DeActivateIRQ(myGUS.irq1); + popIRQ(&tmpentry); + if(!tmpentry.WaveIRQ) temp |= 0x80; + if(!tmpentry.RampIRQ) temp |= 0x40; + temp |= tmpentry.channum; + + return (Bit16u)(temp << 8); + default: + LOG_GUS("Read Register num 0x%x", myGUS.gRegSelect); + return myGUS.gRegData; + } +} + + +static void ExecuteGlobRegister(void) { + int i; + //LOG_MSG("Access global register %x with %x", myGUS.gRegSelect, myGUS.gRegData); + switch(myGUS.gRegSelect) { + case 0x0: // Channel voice control register + if(curchan != NULL) { + curchan->WriteVoiceCtrl((Bit8u)myGUS.gRegData); + } + break; + case 0x1: // Channel frequency control register + if(curchan != NULL) { + curchan->WriteFreqCtrl(myGUS.gRegData); + } + break; + case 0x2: // Channel MSB start address register + if(curchan != NULL) { + Bit32u tmpaddr = myGUS.gRegData << 16; + curchan->StartAddr = (curchan->StartAddr & 0xFFFF) | tmpaddr; + } + break; + case 0x3: // Channel LSB start address register + if(curchan != NULL) { + Bit32u tmpaddr = (Bit32u)(myGUS.gRegData); + curchan->StartAddr = (curchan->StartAddr & 0x1FFF0000) | tmpaddr; + } + break; + case 0x4: // Channel MSB end address register + if(curchan != NULL) { + Bit32u tmpaddr = (Bit32u)myGUS.gRegData << 16; + curchan->EndAddr = (curchan->EndAddr & 0xFFFF) | tmpaddr; + } + break; + case 0x5: // Channel MSB end address register + if(curchan != NULL) { + Bit32u tmpaddr = (Bit32u)(myGUS.gRegData); + curchan->EndAddr = (curchan->EndAddr & 0x1FFF0000) | tmpaddr; + } + break; + case 0x6: // Channel volume ramp rate register + if(curchan != NULL) { + Bit8u tmpdata = (Bit8u)myGUS.gRegData; + curchan->VolRampRate = tmpdata; + } + break; + case 0x7: // Channel volume ramp start register EEEEMMMM + if(curchan != NULL) { + Bit8u tmpdata = (Bit8u)myGUS.gRegData; + curchan->VolRampStart = vol8bit[tmpdata]; + curchan->VolRampStartOrg = tmpdata << 4; + } + break; + case 0x8: // Channel volume ramp end register EEEEMMMM + if(curchan != NULL) { + Bit8u tmpdata = (Bit8u)myGUS.gRegData; + curchan->VolRampEnd = vol8bit[tmpdata]; + curchan->VolRampEndOrg = tmpdata << 4; + } + break; + case 0x9: // Channel current volume register + if(curchan != NULL) { + Bit16u tmpdata = (Bit16u)myGUS.gRegData >> 4; + curchan->CurVolume = tmpdata; + } + break; + case 0xA: // Channel MSB current address register + if(curchan != NULL) { + curchan->CurAddr = (curchan->CurAddr & 0xFFFF) | ((Bit32u)myGUS.gRegData << 16); + } + break; + case 0xB: // Channel LSW current address register + if(curchan != NULL) { + curchan->CurAddr = (curchan->CurAddr & 0xFFFF0000) | ((Bit32u)myGUS.gRegData); + } + break; + case 0xC: // Channel pan pot register + if(curchan != NULL) { + curchan->WritePanPot((Bit8u)myGUS.gRegData); + } + break; + case 0xD: // Channel volume control register + if(curchan != NULL) { + curchan->WriteVolControl((Bit8u)myGUS.gRegData); + } + break; + case 0xE: // Set active channel register + myGUS.activechan = (myGUS.gRegData & 31) +1; + if(myGUS.activechan < 14) myGUS.activechan = 14; + if(myGUS.activechan > 32) myGUS.activechan = 32; + MIXER_Enable(gus_chan,true); + myGUS.basefreq = (Bit32u)((float)1000000/(1.619695497*(float)myGUS.activechan)); + + float simple; + simple = (1.0 / (float)GUS_RATE) / 0.000001; + myGUS.mupersamp = (Bit32s)simple*1024; + myGUS.muperchan = (Bit32s)((float)1.6 * (float)myGUS.activechan * 1024); + LOG_GUS("GUS set to %d channels", myGUS.activechan); + + for(i=0;iUpdateFreqCtrl(); } + + break; + case 0x10: // Undocumented register used in Fast Tracker 2 + break; + case 0x41: // Dma control register + myGUS.DMAControl = (Bit8u)myGUS.gRegData; + if ((myGUS.DMAControl & 0x1) != 0) { + //LOG_MSG("GUS request DMA transfer"); + if(DmaChannels[myGUS.dma1]->enabled) UseDMA(DmaChannels[myGUS.dma1]); + } + break; + case 0x42: // Gravis DRAM DMA address register + myGUS.dmaAddr = myGUS.gRegData; + break; + case 0x43: // MSB Peek/poke DRAM position + + myGUS.gDramAddr = (0xff0000 & myGUS.gDramAddr) | ((Bit32u)myGUS.gRegData); + break; + case 0x44: // LSW Peek/poke DRAM position + myGUS.gDramAddr = (0xffff & myGUS.gDramAddr) | ((Bit32u)myGUS.gRegData) << 16; + break; + case 0x45: // Timer control register. Identical in operation to Adlib's timer + myGUS.TimerControl = (Bit8u)myGUS.gRegData; + if((myGUS.TimerControl & 0x08) !=0) myGUS.timers[1].countdown = myGUS.timers[1].setting; + if((myGUS.TimerControl & 0x04) !=0) myGUS.timers[0].countdown = myGUS.timers[0].setting; + myGUS.irq.T1 = false; + myGUS.irq.T2 = false; + PIC_DeActivateIRQ(myGUS.irq1); + break; + + case 0x46: // Timer 1 control + myGUS.timers[0].bytetimer = (Bit8u)myGUS.gRegData; + myGUS.timers[0].setting = ((Bit32s)0xff - (Bit32s)myGUS.timers[0].bytetimer) * ((Bit32s)80 << 10); + myGUS.timers[0].countdown = myGUS.timers[0].setting; + break; + case 0x47: // Timer 2 control + myGUS.timers[1].bytetimer = (Bit8u)myGUS.gRegData; + myGUS.timers[1].setting = ((Bit32s)0xff - (Bit32s)myGUS.timers[1].bytetimer) * ((Bit32s)360 << 10); + myGUS.timers[1].countdown = myGUS.timers[1].setting; + break; + case 0x49: // DMA sampling control register + myGUS.SampControl = (Bit8u)myGUS.gRegData; + if ((myGUS.SampControl & 0x1) != 0) { + if(DmaChannels[myGUS.dma1]->enabled) UseDMA(DmaChannels[myGUS.dma1]); + } + break; + case 0x4c: // GUS reset register + GUSReset(); + break; + default: + LOG_GUS("Unimplemented global register %x -- %x", myGUS.gRegSelect, myGUS.gRegData); + } + return; +} + + +static Bit16u read_gus16(Bit32u port) { + + return ExecuteReadRegister(); +} + +static void write_gus16(Bit32u port,Bit16u val) { + myGUS.gRegData = val; + ExecuteGlobRegister(); +} + + +static Bit8u read_gus(Bit32u port) { + + switch(port - GUS_BASE) { + case 0x206: + Bit8u temp; + temp = 0; + if(myGUS.irq.MIDITx) temp |= 1; + if(myGUS.irq.MIDIRx) temp |= 2; + if(myGUS.irq.T1) temp |= 4; + if(myGUS.irq.T2) temp |= 8; + if(myGUS.irq.Resv) temp |= 16; + if(myGUS.irq.WaveTable) temp |= 32; + if(myGUS.irq.VolRamp) temp |= 64; + if(myGUS.irq.DMATC) temp |= 128; + PIC_DeActivateIRQ(myGUS.irq1); + return temp; + case 0x208: + Bit8u tmptime; + tmptime = 0; + + if(myGUS.irq.T1) tmptime |= (1 << 6); + if(myGUS.irq.T2) tmptime |= (1 << 5); + if((myGUS.irq.T1) || (myGUS.irq.T2)) tmptime |= (1 << 7); + return tmptime; + case 0x20a: + return myGUS.timerReg; + case 0x302: + return (Bit8u)myGUS.gCurChannel; + case 0x303: + return myGUS.gRegSelect; + case 0x304: + return ExecuteReadRegister() & 0xff; + case 0x305: + return ExecuteReadRegister() >> 8; + case 0x307: + if(myGUS.gDramAddr < sizeof(GUSRam)) { + return GUSRam[myGUS.gDramAddr]; + } else { + return 0; + } + default: + LOG_GUS("Read GUS at port 0x%x", port); + break; + } + + return 0xff; +} + + +static void write_gus(Bit32u port,Bit8u val) { + + switch(port - GUS_BASE) { + case 0x200: + myGUS.mixControl = val; + break; + case 0x208: + myGUS.timerReg = val; + break; + case 0x209: + myGUS.timers[0].active = ((val & 0x1) > 0); + myGUS.timers[1].active = ((val & 0x2) > 0); + + break; + case 0x20b: + if((myGUS.mixControl & 0x40) != 0) { + // IRQ configuration + Bit8u temp = val & 0x7; // Select GF1 irq + if(myGUS.irq1 == irqtable[temp]) { + } else { + LOG_GUS("Attempt to assign GUS to wrong IRQ - at %x set to %x", myGUS.irq1, irqtable[temp]); + } + } else { + // DMA configuration + Bit8u temp = val & 0x7; // Select playback IRQ + if(myGUS.dma1 == dmatable[temp]) { + } else { + LOG_GUS("Attempt to assign GUS to wrong DMA - at %x, assigned %x", myGUS.dma1, dmatable[temp]); + } + } + + break; + case 0x302: + myGUS.gCurChannel = val ; + if (myGUS.gCurChannel > 32) myGUS.gCurChannel = 32; + curchan = guschan[val]; + break; + case 0x303: + myGUS.gRegSelect = val; + myGUS.gRegData = 0; + break; + case 0x304: + myGUS.gRegData = (0x00ff & myGUS.gRegData) | val << 8; + ExecuteGlobRegister(); + break; + case 0x305: + myGUS.gRegData = (0xff00 & myGUS.gRegData) | val; + ExecuteGlobRegister(); + break; + + case 0x307: + if(myGUS.gDramAddr < sizeof(GUSRam)) GUSRam[myGUS.gDramAddr] = val; + break; + default: + LOG_GUS("Write GUS at port 0x%x with %x", port, val); + break; + } + + +} + +static void UseDMA(DmaChannel *useDMA) { + Bit32s dmaaddr = myGUS.dmaAddr << 4; + if((myGUS.DMAControl & 0x2) == 0) { + //Write data into UltraSound + Bit32s comsize = useDMA->currcnt; + + useDMA->Read(useDMA->currcnt,&GUSRam[dmaaddr]); + if((myGUS.DMAControl & 0x80) != 0) { + //Invert the MSB to convert twos compliment form + + int i; + if((myGUS.DMAControl & 0x40) == 0) { + // 8-bit data + for(i=dmaaddr;i<(dmaaddr+comsize);i++) GUSRam[i] ^= 0x80; + } else { + // 16-bit data + for(i=dmaaddr+1;i<(dmaaddr+comsize-1);i+=2) GUSRam[i] ^= 0x80; + } + } + } else { + //Read data out of UltraSound + useDMA->Write(useDMA->currcnt,&GUSRam[dmaaddr]); + + } +} + +static void GUS_DMA_Callback(void *useChannel, bool tc) { + DmaChannel *myDMA; + myDMA = (DmaChannel *)useChannel; + + if(tc) { + if((myGUS.DMAControl & 0x20) != 0) { + myGUS.irq.DMATC = true; + PIC_ActivateIRQ(myGUS.irq2); + } + } else { + if ((myGUS.DMAControl & 0x1) != 0) UseDMA(myDMA); + } + + +} + +static void GUS_CallBack(Bit8u * stream,Bit32u len) { + + Bit16s *bufptr; + Bit16s buffer[4096]; + Bit32s tmpbuf[4096]; + + memset(&buffer[0],0,len*4); + memset(&tmpbuf[0],0,len*8); + + int i,t; + for(i=0;iplaying) { + guschan[i]->generateSamples(&buffer[0],len); + + for(t=0;t= 0) { + PIC_ActivateIRQ(myGUS.irq1); + } + } + + if(myGUS.timers[0].active) { + myGUS.timers[0].countdown-=(len * (Bit32u)myGUS.mupersamp); + if(!myGUS.irq.T1) { + // Expire Timer 1 + if(myGUS.timers[0].countdown < 0) { + if((myGUS.TimerControl & 0x04) !=0) { + PIC_ActivateIRQ(myGUS.irq1); + } + myGUS.irq.T1 = true; + //LOG_MSG("T1 timer expire"); + //myGUS.timers[0].countdown = myGUS.timers[0].setting; + } + } + } + if(myGUS.timers[1].active) { + if(!myGUS.irq.T2) { + myGUS.timers[1].countdown-=(len * (Bit32u)myGUS.mupersamp); + // Expire Timer 2 + if(myGUS.timers[1].countdown < 0) { + if((myGUS.TimerControl & 0x08) !=0) { + PIC_ActivateIRQ(myGUS.irq1); + } + myGUS.irq.T2 = true; + } + } + } + + + bufptr = (Bit16s *)stream; + for(i=0;i> 4)); + b = 1.0+((float)(i & 0xf))/(float)16; + a *= b; + a /= 16; + vol8bit[i] = (Bit16u)a; + } + for(i=0;i<4096;i++) { + float a,b; + a = pow(2.0f,(float)(i >> 8)); + b = 1.0+((float)(i & 0xff))/(float)256; + a *= b; + a /= 16; + vol16bit[i] = (Bit16u)a; + } } +void GUS_Init(Section* sec) { + + + memset(&myGUS,0,sizeof(myGUS)); + memset(GUSRam,0,1024*1024); + + Section_prop * section=static_cast(sec); + if(!section->Get_bool("gus")) return; + myGUS.rate=section->Get_int("rate"); + + myGUS.portbase = section->Get_hex("base") - 0x200; + myGUS.dma1 = section->Get_int("dma1"); + myGUS.dma2 = section->Get_int("dma2"); + myGUS.irq1 = section->Get_int("irq1"); + myGUS.irq2 = section->Get_int("irq2"); + strcpy(&myGUS.ultradir[0], section->Get_string("ultradir")); + + myGUS.timerReg = 85; + myGUS.timers[0].active = false; + myGUS.timers[1].active = false; + + + memset(&myGUS.irq, 0, sizeof(myGUS.irq)); + IRQFifo.stackpos = -1; + myGUS.irqenabled = false; + + // We'll leave the MIDI interface to the MPU-401 + + // Ditto for the Joystick + + // GF1 Synthesizer + + IO_RegisterWriteHandler(0x302 + GUS_BASE,write_gus,"GF1 Page Register"); + IO_RegisterReadHandler(0x302 + GUS_BASE,read_gus,"GF1 Page Register"); + + IO_RegisterWriteHandler(0x303 + GUS_BASE,write_gus,"GF1 Global Register Select"); + IO_RegisterReadHandler(0x303 + GUS_BASE,read_gus,"GF1 Global Register Select"); + + IO_RegisterWriteHandler(0x304 + GUS_BASE,write_gus,"GF1 Global Data Low Byte"); + IO_RegisterReadHandler(0x304 + GUS_BASE,read_gus,"GF1 Global Data Low Byte"); + + IO_RegisterWriteWHandler(0x304 + GUS_BASE,write_gus16); + IO_RegisterReadWHandler(0x304 + GUS_BASE,read_gus16); + + IO_RegisterWriteHandler(0x305 + GUS_BASE,write_gus,"GF1 Global Data High Byte"); + IO_RegisterReadHandler(0x305 + GUS_BASE,read_gus,"GF1 Global Data High Byte"); + + IO_RegisterReadHandler(0x206 + GUS_BASE,read_gus,"GF1 IRQ Status Register"); + + IO_RegisterWriteHandler(0x208 + GUS_BASE,write_gus,"Timer Control Reg"); + IO_RegisterReadHandler(0x208 + GUS_BASE,read_gus,"Timer Control Reg"); + + IO_RegisterWriteHandler(0x209 + GUS_BASE,write_gus,"Timer Data IO"); + + IO_RegisterWriteHandler(0x307 + GUS_BASE,write_gus,"DRAM IO"); + IO_RegisterReadHandler(0x307 + GUS_BASE,read_gus,"DRAM IO"); + + // Board Only + + IO_RegisterWriteHandler(0x200 + GUS_BASE,write_gus,"Mix Control Register"); + IO_RegisterReadHandler(0x20A + GUS_BASE,read_gus,"GUS Undocumented"); + IO_RegisterWriteHandler(0x20B + GUS_BASE,write_gus,"IRQ/DMA Control Register"); + + PIC_RegisterIRQ(myGUS.irq1,0,"GUS"); + PIC_RegisterIRQ(myGUS.irq2,0,"GUS"); + + DmaChannels[myGUS.dma1]->RegisterCallback(GUS_DMA_Callback); + + MakeTables(); + + int i; + for(i=0;i<=32;i++) { + guschan[i] = new GUSChannels(i); + } + + // Register the Mixer CallBack + + gus_chan=MIXER_AddChannel(GUS_CallBack,GUS_RATE,"GUS"); + MIXER_SetMode(gus_chan,MIXER_16STEREO); + MIXER_Enable(gus_chan,false); + + int portat = 0x200+GUS_BASE; + // ULTRASND=Port,DMA1,DMA2,IRQ1,IRQ2 + SHELL_AddAutoexec("SET ULTRASND=%3X,%d,%d,%d,%d",portat,myGUS.dma1,myGUS.dma2,myGUS.irq1,myGUS.irq2); + SHELL_AddAutoexec("SET ULTRADIR=%s", myGUS.ultradir); + + +} + + + diff --git a/src/hardware/hardware.cpp b/src/hardware/hardware.cpp index 49cf722..017ecc4 100644 --- a/src/hardware/hardware.cpp +++ b/src/hardware/hardware.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/iohandler.cpp b/src/hardware/iohandler.cpp index 6e2429e..32e6e95 100644 --- a/src/hardware/iohandler.cpp +++ b/src/hardware/iohandler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,71 +19,128 @@ #include "dosbox.h" #include "inout.h" -IO_ReadBlock IO_ReadTable[IO_MAX]; -IO_WriteBlock IO_WriteTable[IO_MAX]; +#define IO_MAX 1024 -void IO_Write(Bitu num,Bit8u val) { - if (num(val),port); - IO_RegisterWriteHandler(port,&IO_WriteBlocked,"Blocked Write"); + io.write_b[port]=IO_WriteBBlocked; +} +void IO_WriteDefaultW(Bit32u port,Bit16u val) { + io.write_b[port](port,(Bit8u)val); + io.write_b[port+1](port+1,(Bit8u)(val>>8)); +} +void IO_WriteDefaultD(Bit32u port,Bit32u val) { + io.write_b[port](port,(Bit8u)val); + io.write_b[port+1](port+1,(Bit8u)(val>>8)); + io.write_b[port+2](port+2,(Bit8u)(val>>16)); + io.write_b[port+3](port+3,(Bit8u)(val>>24)); +} + +void IO_RegisterReadBHandler(Bitu port,IO_ReadBHandler * handler) { + if (port>=IO_MAX) return; + io.read_b[port]=handler; +} +void IO_RegisterReadWHandler(Bitu port,IO_ReadWHandler * handler) { + if (port>=IO_MAX) return; + io.read_w[port]=handler; +} +void IO_RegisterReadDHandler(Bitu port,IO_ReadDHandler * handler) { + if (port>=IO_MAX) return; + io.read_d[port]=handler; +} +void IO_RegisterWriteBHandler(Bitu port,IO_WriteBHandler * handler) { + if (port>=IO_MAX) return; + io.write_b[port]=handler; +} +void IO_RegisterWriteWHandler(Bitu port,IO_WriteWHandler * handler) { + if (port>=IO_MAX) return; + io.write_w[port]=handler; +} +void IO_RegisterWriteDHandler(Bitu port,IO_WriteDHandler * handler) { + if (port>=IO_MAX) return; + io.write_d[port]=handler; } -void IO_RegisterReadHandler(Bit32u port,IO_ReadHandler * handler,char * name) { - if (port=IO_MAX) return; + io.read_b[port]=IO_ReadDefaultB; + io.read_w[port]=IO_ReadDefaultW; + io.read_d[port]=IO_ReadDefaultD; } - -void IO_RegisterWriteHandler(Bit32u port,IO_WriteHandler * handler,char * name) { - if (port=IO_MAX) return; + io.write_b[port]=IO_WriteDefaultB; + io.write_w[port]=IO_WriteDefaultW; + io.write_d[port]=IO_WriteDefaultD; } - -void IO_FreeReadHandler(Bit32u port) { - if (port #include "dosbox.h" #include "keyboard.h" @@ -66,6 +68,7 @@ struct KeyBlock { bool enabled; bool active; bool scheduled; + bool key_on_60; }; static KeyBlock keyb; @@ -79,6 +82,7 @@ void KEYBOARD_ClrBuffer(void) { keyb.buf.pos=0; keyb.scheduled=false; PIC_DeActivateIRQ(1); + keyb.key_on_60=false; } /* Read an entry from the keycode buffer */ @@ -97,6 +101,7 @@ void KEYBOARD_GetCode(void) { keyb.buf.state=STATE_NORMAL; break; } + keyb.key_on_60=true; if (keyb.enabled) PIC_ActivateIRQ(1); } @@ -112,13 +117,14 @@ void KEYBOARD_AddCode(Bit8u scancode,Bit8u ascii,Bitu mod,KeyStates state) { keyb.buf.code[start].mod=mod; } /* Start up an event to start the first IRQ */ - if (!keyb.scheduled) { + if (!keyb.scheduled && !keyb.key_on_60) { keyb.scheduled=true; PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); } } void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod) { + keyb.key_on_60=false; //else no new keys get scheduled :) switch (keyb.buf.state) { case STATE_NORMAL: if (keyb.buf.used && !keyb.scheduled) { @@ -142,18 +148,21 @@ void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod) { } static Bit8u read_p60(Bit32u port) { + keyb.key_on_60 = false; switch (keyb.buf.state) { case STATE_NORMAL: - if (keyb.buf.used && !keyb.scheduled) { + if (keyb.buf.used && !keyb.scheduled) { //key60 is false keyb.scheduled=true; PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); } + return keyb.buf.code[keyb.buf.pos].scancode; case STATE_EXTEND: - if (!keyb.scheduled) { + if (!keyb.scheduled) { keyb.scheduled=true; PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); } + return 224; } return 0; @@ -179,8 +188,21 @@ static void write_p60(Bit32u port,Bit8u val) { keyb.command=CMD_SETTYPERATE; KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ break; + case 0xf4: /* Enable keyboard,clear buffer, start scanning */ + keyb.active=true; + KEYBOARD_ClrBuffer(); + LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated port 60"); + KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + break; + case 0xf5: /* Reset keyboard and disable scanning */ + case 0xf6: /* Reset keyboard and enable scanning */ + LOG(LOG_KEYBOARD,LOG_NORMAL)("Reset"); + KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ + break; default: + /* Just always acknowledge strange commands */ LOG(LOG_KEYBOARD,LOG_ERROR)("60:Unhandled command %X",val); + KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ } return; case CMD_SETOUTPORT: @@ -197,6 +219,7 @@ static void write_p60(Bit32u port,Bit8u val) { static Bit8u read_p61(Bit32u port) { port_61_data^=0x20; + port_61_data^=0x10; return port_61_data; } @@ -214,11 +237,11 @@ static void write_p64(Bit32u port,Bit8u val) { switch (val) { case 0xae: /* Activate keyboard */ keyb.active=true; - if (keyb.buf.used && !keyb.scheduled) { + if (keyb.buf.used && !keyb.scheduled && !keyb.key_on_60) { keyb.scheduled=true; PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); } - LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated"); + LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated port 64"); break; case 0xad: /* Deactivate keyboard */ keyb.active=false; @@ -239,7 +262,11 @@ static void write_p64(Bit32u port,Bit8u val) { } static Bit8u read_p64(Bit32u port) { - return 0x1c | (keyb.buf.used ? 0x1 : 0x0); +// Bit8u status= 0x1c | ((keyb.buf.used ||keyb.key_on_60)? 0x1 : 0x0); +// Old one. Digitracker 2 doesn't like this. key_on_60 is much more advanged. + Bit8u status= 0x1c | (keyb.key_on_60? 0x1 : 0x0); + keyb.key_on_60=false; + return status; } void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler) { @@ -407,5 +434,6 @@ void KEYBOARD_Init(Section* sec) { keyb.enabled=true; keyb.command=CMD_NONE; keyb.last_index=0; + keyb.key_on_60=false; KEYBOARD_ClrBuffer(); } diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index e91b9d5..dddeb8c 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,20 +30,26 @@ #define PAGES_IN_BLOCK ((1024*1024)/MEM_PAGE_SIZE) #define MAX_MEMORY 64 +#define MAX_PAGE_ENTRIES (MAX_MEMORY*1024*1024/4096) #define LFB_PAGES 512 - -static Bit8u controlport_data; -static bool a20_enabled; +#define MAX_LINKS ((MAX_MEMORY*1024/4)+4096) //Hopefully enough struct AllocBlock { Bit8u data[PAGES_IN_BLOCK*4096]; AllocBlock * next; }; +struct LinkBlock { + Bitu used; + Bit32u pages[MAX_LINKS]; +}; + static struct MemoryBlock { - Bitu pages; - Bitu free_pages; - PageEntry * entries; + Bitu pages; + PageHandler * * phandlers; + HostPt * hostpts; + MemHandle * mhandles; + LinkBlock links; struct { Bitu pages; HostPt cur_page; @@ -54,172 +60,90 @@ static struct MemoryBlock { Bitu end_page; Bitu pages; HostPt address; - PageEntry entries[LFB_PAGES]; } lfb; struct { - HostPt ram_bases[128/4]; - HostPt map_base; - VGA_RANGES range; - } vga; - PageDirectory dir; + bool enabled; + Bit8u controlport; + } a20; } memory; -Bit8u ENTRY_readb(PageEntry * pentry,PhysPt address) { - switch(pentry->type) { - case ENTRY_VGA: - return (*vga.config.readhandler)(pentry->data.vga_base+(address & 4095)); - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) return mem_readb(address); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) return mem_readb(address); - break; - - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry read from %X with illegal type %d",address,pentry->type); +class IllegalPageHandler : public PageHandler { +public: + IllegalPageHandler() { + flags=PFLAG_INIT|PFLAG_NOCODE; } - return 0; + Bitu readb(PhysPt addr) { + LOG_MSG("Illegal read from %x",addr); + return 0; + } + void writeb(PhysPt addr,Bitu val) { + LOG_MSG("Illegal write to %x",addr); + } + HostPt GetHostPt(Bitu phys_page) { + return 0; + } +}; + +class RAMPageHandler : public PageHandler { +public: + RAMPageHandler() { + flags=PFLAG_READABLE|PFLAG_WRITEABLE; + } + HostPt GetHostPt(Bitu phys_page) { + if (!memory.hostpts[phys_page]) { + memory.hostpts[phys_page]=MEM_GetBlockPage(); + } + return memory.hostpts[phys_page]; + } +}; + +class ROMPageHandler : public RAMPageHandler { +public: + ROMPageHandler() { + flags=PFLAG_READABLE|PFLAG_HASROM; + } +}; + +class LFBPageHandler : public RAMPageHandler { +public: + LFBPageHandler() { + flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; + } + HostPt GetHostPt(Bitu phys_page) { + return memory.lfb.address+(phys_page-memory.lfb.start_page)*4096; + } +}; + + +static IllegalPageHandler illegal_page_handler; +static RAMPageHandler ram_page_handler; +static ROMPageHandler rom_page_handler; +static LFBPageHandler lfb_page_handler; + +void MEM_SetLFB(Bitu page,Bitu pages,HostPt pt) { + memory.lfb.address=pt; + memory.lfb.start_page=page; + memory.lfb.end_page=page+pages; + memory.lfb.pages=pages; + PAGING_ClearTLB(); } -Bit16u ENTRY_readw(PageEntry * pentry,PhysPt address) { - switch(pentry->type) { - case ENTRY_VGA: - { - VGA_ReadHandler * handler=vga.config.readhandler; - address=pentry->data.vga_base + (address & 4095); - return (*handler)(address) | - ((*handler)(address+1) << 8); - } - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) return mem_readw(address); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) return mem_readw(address); - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry read from %X with illegal type %d",address,pentry->type); +PageHandler * MEM_GetPageHandler(Bitu phys_page) { + if (phys_page=memory.lfb.start_page) && (phys_pagetype) { - case ENTRY_VGA: - { - VGA_ReadHandler * handler=vga.config.readhandler; - address=pentry->data.vga_base + (address & 4095); - return (*handler)(address) | - ((*handler)(address+1) << 8) | - ((*handler)(address+2) << 16) | - ((*handler)(address+3) << 24); - } - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) return mem_readd(address); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) return mem_readd(address); - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry read from %X with illegal type %d",address,pentry->type); - } - return 0; -} - -void ENTRY_writeb(PageEntry * pentry,PhysPt address,Bit8u val) { - switch(pentry->type) { - case ENTRY_VGA: - (*vga.config.writehandler)(pentry->data.vga_base+(address&4095),val); - break; - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) mem_writeb(address,val); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) mem_writeb(address,val); - break; - case ENTRY_ROM: - LOG(LOG_PAGING,LOG_WARN)("Write %X to ROM at %X",val,address); - break; - case ENTRY_CHANGES: - writeb(pentry->data.mem+(address&4095),val); - { - Bitu start=address&4095;Bitu end=start; - for (PageLink * link=pentry->links;link;link=link->next) - if (link->change) link->change->Changed(link,start,end); - } - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry write %X to %X with illegal type %d",val,address,pentry->type); +void MEM_SetPageHandler(Bitu phys_page,Bitu pages,PageHandler * handler) { + for (;pages>0;pages--) { + memory.phandlers[phys_page]=handler; + phys_page++; } } -void ENTRY_writew(PageEntry * pentry,PhysPt address,Bit16u val) { - switch(pentry->type) { - case ENTRY_VGA: - { - VGA_WriteHandler * handler=vga.config.writehandler; - address=pentry->data.vga_base+(address&4095); - (*handler)(address,(Bit8u)val); - (*handler)(address+1,(Bit8u)(val>>8)); - } - break; - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) mem_writew(address,val); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) mem_writew(address,val); - break; - case ENTRY_ROM: - LOG(LOG_PAGING,LOG_WARN)("Write %X to ROM at %X",val,address); - break; - case ENTRY_CHANGES: - writew(pentry->data.mem+(address&4095),val); - { - Bitu start=address&4095;Bitu end=start+1; - for (PageLink * link=pentry->links;link;link=link->next) - if (link->change) link->change->Changed(link,start,end); - } - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry write %X to %X with illegal type %d",val,address,pentry->type); - } -} - - -void ENTRY_writed(PageEntry * pentry,PhysPt address,Bit32u val) { - switch(pentry->type) { - case ENTRY_VGA: - { - VGA_WriteHandler * handler=vga.config.writehandler; - address=pentry->data.vga_base+(address&4095); - (*handler)(address,(Bit8u)val); - (*handler)(address+1,(Bit8u)(val>>8)); - (*handler)(address+2,(Bit8u)(val>>16)); - (*handler)(address+3,(Bit8u)(val>>24)); - } - break; - case ENTRY_NA: - if (pentry->data.dir->InitPageLinear(address)) mem_writed(address,val); - break; - case ENTRY_INIT: - if (pentry->data.dir->InitPage(address)) mem_writed(address,val); - break; - case ENTRY_ROM: - LOG(LOG_PAGING,LOG_WARN)("Write %X to ROM at %X",val,address); - break; - case ENTRY_CHANGES: - writed(pentry->data.mem+(address&4095),val); - { - Bitu start=address&4095;Bitu end=start+3; - for (PageLink * link=pentry->links;link;link=link->next) - if (link->change) link->change->Changed(link,start,end); - } - break; - default: - LOG(LOG_PAGING,LOG_ERROR)("Entry write %X to %X with illegal type %d",val,address,pentry->type); - } -} - - Bitu mem_strlen(PhysPt pt) { Bitu x=0; while (x<1024) { @@ -270,193 +194,11 @@ Bitu MEM_TotalPages(void) { return memory.pages; } -void MEM_UnlinkPage(PageLink * plink) { - PageLink * checker=plink->entry->links; - PageLink * * last=&plink->entry->links; - while (checker) { - if (checker == plink) { - *last=plink->next; - PAGING_AddFreePageLink(plink); - return; - } - last=&checker->next; - checker=checker->next; - } - E_Exit("Unlinking unlinked link"); - -} - -PageLink * MEM_LinkPage(Bitu phys_page,PhysPt lin_base) { - PageEntry * entry; - /* Check if it's in a valid memory range */ - if (phys_page=memory.lfb.start_page && phys_pagelin_base=lin_base; - link->change=0; - /* Check what kind of handler we need to give the page */ - switch (entry->type) { - case ENTRY_RAM: - link->read=entry->data.mem - lin_base; - link->write=link->read; - break; - case ENTRY_ROM: - link->read=entry->data.mem - lin_base; - link->write=0; - break; - case ENTRY_VGA: - link->read=0; - link->write=0; - break; - case ENTRY_LFB: - link->read=entry->data.mem - lin_base; - link->write=link->read; - break; - case ENTRY_ALLOC: - entry->type=ENTRY_RAM; - entry->data.mem=MEM_GetBlockPage(); - link->read=entry->data.mem - lin_base; - link->write=link->read; - break; - case ENTRY_CHANGES: - link->read=entry->data.mem - lin_base; - link->write=0; - break; - default: - E_Exit("LinkPage:Illegal type %d",entry->type); - } - /* Place the entry in the link */ - link->entry=entry; - link->next=entry->links; - entry->links=link; - return link; -} - - -void MEM_CheckLinks(PageEntry * theentry) { - if (theentry->type!=ENTRY_RAM && theentry->type!=ENTRY_CHANGES) { - LOG(LOG_PAGING,LOG_NORMAL)("Checking links on type %d",theentry->type); - return; - } - bool haschange=false;PageLink * link; - for (link=theentry->links;link;link=link->next) { - if (link->change) { - haschange=true;break; - } - } - if (haschange) { - theentry->type=ENTRY_CHANGES; - for (link=theentry->links;link;link=link->next) { - link->read=theentry->data.mem - link->lin_base; - link->write=0; - } - } else { - theentry->type=ENTRY_RAM; - for (link=theentry->links;link;link=link->next) { - link->read=theentry->data.mem - link->lin_base; - link->write=link->read; - } - } -} - -void MEM_AllocLinkMemory(PageEntry * theentry) { - //TODO Maybe check if this is a LINK_ALLOC type - HostPt themem=MEM_GetBlockPage(); - theentry->data.mem=themem; - theentry->type=ENTRY_RAM; - theentry->links=0; -} - -void MEM_SetLFB(Bitu page,Bitu pages,HostPt pt) { - if (pages>LFB_PAGES) E_Exit("MEM:LFB to large"); - LOG(LOG_PAGING,LOG_NORMAL)("LFB Base at address %X,page %X",page*4096,page); - memory.lfb.pages=pages; - memory.lfb.start_page=page; - memory.lfb.end_page=page+pages; - memory.lfb.address=pt; - for (Bitu i=0;idata.mem=themem; - theentry->type=ENTRY_LFB; - PageLink * link=theentry->links; - while (link) { - link->read=themem - link->lin_base; - link->write=link->read; - link=link->next; - } - } - memory.vga.range=range; - } - /* Setup the new range, check if it's gonna handler based */ - Bitu start,end; - switch (range) { - case VGA_RANGE_A000:start=0;end=16;break; - case VGA_RANGE_B000:start=16;end=24;break; - case VGA_RANGE_B800:start=24;end=32;break; - } - if (base) { - /* If it has an address it's a mapping */ - for (i=start;itype=ENTRY_LFB; - theentry->data.mem=themem; - PageLink * link=theentry->links; - while (link) { - link->read=themem - link->lin_base; - link->write=link->read; - link=link->next; - } - } - } else { - /* No address, so it'll be a handler */ - for (i=start;itype=ENTRY_VGA; - PhysPt thebase=(i-start)*4096; - PageLink * link=theentry->links; - theentry->data.vga_base=thebase; - while (link) { - link->read=0; - link->write=0; - link=link->next; - } - } - } -} - Bitu MEM_FreeLargest(void) { Bitu size=0;Bitu largest=0; Bitu index=XMS_START; while (indexlargest) largest=size; @@ -472,7 +214,7 @@ Bitu MEM_FreeTotal(void) { Bitu free=0; Bitu index=XMS_START; while (index0) { pages++; - handle=memory.entries[handle].next_handle; + handle=memory.mhandles[handle]; } return pages; } @@ -499,12 +241,12 @@ INLINE Bitu BestMatch(Bitu size) { /* Check if we are searching for first free page */ if (!first) { /* Check if this is a free page */ - if (!memory.entries[index].next_handle) { + if (!memory.mhandles[index]) { first=index; } } else { /* Check if this still is used page */ - if (memory.entries[index].next_handle) { + if (memory.mhandles[index]) { Bitu pages=index-first; if (pages==size) { return first; @@ -535,7 +277,7 @@ MemHandle MEM_AllocatePages(Bitu pages,bool sequence) { MemHandle * next=&ret; while (pages) { *next=index; - next=&memory.entries[index].next_handle; + next=&memory.mhandles[index]; index++;pages--; } *next=-1; @@ -545,9 +287,9 @@ MemHandle MEM_AllocatePages(Bitu pages,bool sequence) { while (pages) { Bitu index=BestMatch(1); if (!index) E_Exit("MEM:corruption during allocate"); - while (pages && (!memory.entries[index].next_handle)) { + while (pages && (!memory.mhandles[index])) { *next=index; - next=&memory.entries[index].next_handle; + next=&memory.mhandles[index]; index++;pages--; } *next=-1; //Invalidate it in case we need another match @@ -558,8 +300,8 @@ MemHandle MEM_AllocatePages(Bitu pages,bool sequence) { void MEM_ReleasePages(MemHandle handle) { while (handle>0) { - MemHandle next=memory.entries[handle].next_handle; - memory.entries[handle].next_handle=0; + MemHandle next=memory.mhandles[handle]; + memory.mhandles[handle]=0; handle=next; } } @@ -580,22 +322,22 @@ bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) { while (index>0) { old_pages++; last=index; - index=memory.entries[index].next_handle; + index=memory.mhandles[index]; } if (old_pages == pages) return true; if (old_pages > pages) { /* Decrease size */ pages--;index=handle;old_pages--; while (pages) { - index=memory.entries[index].next_handle; + index=memory.mhandles[index]; pages--;old_pages--; } - MemHandle next=memory.entries[index].next_handle; - memory.entries[index].next_handle=-1; + MemHandle next=memory.mhandles[index]; + memory.mhandles[index]=-1; index=next; while (old_pages) { - next=memory.entries[index].next_handle; - memory.entries[index].next_handle=0; + next=memory.mhandles[index]; + memory.mhandles[index]=0; index=next; old_pages--; } @@ -606,17 +348,17 @@ bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) { if (sequence) { index=last+1; Bitu free=0; - while ((index=need) { /* Enough space allocate more pages */ index=last; while (need) { - memory.entries[index].next_handle=index+1; + memory.mhandles[index]=index+1; need--;index++; } - memory.entries[index].next_handle=-1; + memory.mhandles[index]=-1; return true; } else { /* Not Enough space allocate new block and copy */ @@ -630,63 +372,38 @@ bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) { } else { MemHandle rem=MEM_AllocatePages(need,false); if (!rem) return false; - memory.entries[last].next_handle=rem; + memory.mhandles[last]=rem; return true; } } return 0; } - -void MEM_UnmapPages(Bitu phys_page,Bitu pages) { - for (;pages;pages--) { - memory.dir.LinkPage(phys_page,phys_page); - phys_page++; - } -} - -void MEM_MapPagesHandle(Bitu lin_page,MemHandle mem,Bitu mem_page,Bitu pages) { - for (;mem_page;mem_page--) { - if (mem<=0) E_Exit("MEM:MapPages:Fault in memory tables"); - mem=memory.entries[mem].next_handle; - } - for (;pages;pages--) { - if (mem<=0) E_Exit("MEM:MapPages:Fault in memory tables"); - memory.dir.LinkPage(lin_page++,mem); - mem=memory.entries[mem].next_handle; - } -} - -void MEM_MapPagesDirect(Bitu lin_page,Bitu phys_page,Bitu pages) { - for (;pages;pages--) { - memory.dir.LinkPage(lin_page++,phys_page++); - } -} - MemHandle MEM_NextHandle(MemHandle handle) { - return memory.entries[handle].next_handle; + return memory.mhandles[handle]; } +MemHandle MEM_NextHandleAt(MemHandle handle,Bitu where) { + while (where) { + where--; + handle=memory.mhandles[handle]; + } + return handle; +} + + /* A20 line handling, Basically maps the 4 pages at the 1mb to 0mb in the default page directory */ bool MEM_A20_Enabled(void) { - return a20_enabled; + return memory.a20.enabled; } void MEM_A20_Enable(bool enabled) { - a20_enabled=enabled; - Bitu i; - if (!enabled) { - for (i=0x0;i<0x10;i++) { - memory.dir.LinkPage(0x100+i,i); - } - } else { - for (i=0x0;i<0x10;i++) { - memory.dir.LinkPage(0x100+i,0x100+i); - } - } + Bitu phys_base=enabled ? (1024/4) : 0; + for (Bitu i=0;i<16;i++) PAGING_MapPage((1024/4)+i,phys_base+i); + memory.a20.enabled=enabled; } @@ -742,20 +459,11 @@ void mem_writed(PhysPt address,Bit32u val) { } void phys_writeb(PhysPt addr,Bit8u val) { - Bitu page=addr>>12; - if (page>=memory.pages) E_Exit("physwrite:outside of physical range"); - PageEntry * theentry=&memory.entries[page]; - switch (theentry->type) { - case ENTRY_ALLOC: - MEM_AllocLinkMemory(theentry); - break; - case ENTRY_RAM: - case ENTRY_ROM: - break; - default: - E_Exit("physwrite:illegal type %d",theentry->type); + HostPt block=memory.hostpts[addr >> 12]; + if (!block) { + block=memory.hostpts[addr >> 12]=MEM_GetBlockPage(); } - writeb(theentry->data.mem+(addr & 4095),val); + host_writeb(block+(addr & 4095),val); } void phys_writew(PhysPt addr,Bit16u val) { @@ -770,38 +478,43 @@ void phys_writed(PhysPt addr,Bit32u val) { phys_writeb(addr+3,(Bit8u)(val >> 24)); } -Bit32u phys_page_readd(Bitu page,Bitu index) { - if (page>=memory.pages) E_Exit("physwrite:outside of physical range"); - PageEntry * theentry=&memory.entries[page]; - switch (theentry->type) { - case ENTRY_CHANGES: - case ENTRY_RAM: - case ENTRY_ROM: - return readd(memory.entries[page].data.mem+index*4); - break; - default: - E_Exit("pageread:illegal type %d",theentry->type); +Bit32u MEM_PhysReadD(Bitu addr) { + Bitu page=addr >> 12; + Bitu index=(addr & 4095); + if (page>memory.pages) + E_Exit("Reading from illegal page"); + HostPt block=memory.hostpts[page]; + if (!block) { + E_Exit("Reading from empty page"); } - return 0; + return host_readd(block+index); +} + +void MEM_PhysWriteD(Bitu addr,Bit32u val) { + Bitu page=addr >> 12; + Bitu index=(addr & 4095); + if (page>memory.pages) + E_Exit("Writing from illegal page"); + HostPt block=memory.hostpts[page]; + if (!block) { + E_Exit("Writing to empty page"); + } + host_writed(block+index,val); } static void write_p92(Bit32u port,Bit8u val) { // Bit 0 = system reset (switch back to real mode) if (val&1) E_Exit("XMS: CPU reset via port 0x92 not supported."); - controlport_data = val & ~2; + memory.a20.controlport = val & ~2; MEM_A20_Enable((val & 2)>0); } static Bit8u read_p92(Bit32u port) { - return controlport_data | (a20_enabled ? 0x02 : 0); + return memory.a20.controlport | (memory.a20.enabled ? 0x02 : 0); } -PageDirectory * MEM_DefaultDirectory(void) { - return &memory.dir; -} - HostPt MEM_GetBlockPage(void) { HostPt ret; if (memory.block.pages) { @@ -847,36 +560,17 @@ void MEM_Init(Section * sec) { memsize=MAX_MEMORY; } memory.pages=(memsize*1024*1024)/4096; - if (memory.pages>0x110) memory.free_pages=memory.pages-0x110; - else memory.free_pages=0; - - memory.entries= new PageEntry[memory.pages]; + /* Allocate the data for the different page information blocks */ + memory.hostpts=new HostPt[memory.pages]; + memory.phandlers=new PageHandler * [memory.pages]; + memory.mhandles=new MemHandle [memory.pages]; for (i=0;i #include "dosbox.h" @@ -55,14 +57,7 @@ Bitu PIC_IRQActive; static IRQ_Block irqs[16]; static PIC_Controller pics[2]; - -enum QUEUE_TYPE { - IRQ,EVENT -}; - struct PICEntry { - QUEUE_TYPE type; - Bitu irq; Bitu index; PIC_EventHandler event; PICEntry * next; @@ -77,6 +72,9 @@ static struct { static void write_command(Bit32u port,Bit8u val) { PIC_Controller * pic=&pics[port==0x20 ? 0 : 1]; Bitu irq_base=port==0x20 ? 0 : 8; + Bitu i; + Bit16u IRQ_priority_table[16] = + { 0,1,8,9,10,11,12,13,14,15,2,3,4,5,6,7 }; switch (val) { case 0x0A: /* select read interrupt request register */ pic->request_issr=false; @@ -97,7 +95,13 @@ static void write_command(Bit32u port,Bit8u val) { irqs[PIC_IRQActive].inservice=false; if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler(); PIC_IRQActive=PIC_NOIRQ; - }//TODO Warnings? + for (i=0; i<=15; i++){ + if(irqs[IRQ_priority_table[i]].inservice) { + PIC_IRQActive=IRQ_priority_table[i]; + break; + } + } + } //TODO Warnings? break; case 0x60:case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:case 0x67: /* Spefific EOI 0-7 */ @@ -105,6 +109,12 @@ static void write_command(Bit32u port,Bit8u val) { irqs[PIC_IRQActive].inservice=false; if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler(); PIC_IRQActive=PIC_NOIRQ; + for (i=0; i<=15; i++) { + if (irqs[IRQ_priority_table[i]].inservice) { + PIC_IRQActive=IRQ_priority_table[i]; + break; + } + } }//TODO Warnings? break; case 0xC0:case 0xC1:case 0xC2:case 0xC3:case 0xC4:case 0xC5:case 0xC6:case 0xC7: @@ -121,21 +131,28 @@ static void write_data(Bit32u port,Bit8u val) { Bitu i; switch(pic->icw_index) { case 0: /* mask register */ + LOG(LOG_PIC,LOG_NORMAL)("%d mask %X",port==0x21 ? 0 : 1,val); for (i=0;i<=7;i++) { irqs[i+irq_base].masked=(val&(1<0; if (irqs[i+irq_base].active && !irqs[i+irq_base].masked) PIC_IRQCheck|=(1 << (i+irq_base)); else PIC_IRQCheck&=~(1 << (i+irq_base)); }; +#if 0 + if (PIC_IRQCheck) { + CPU_CycleLeft+=CPU_Cycles; + CPU_Cycles=0; + } +#endif break; case 1: /* icw2 */ - LOG(LOG_PIC,LOG_NORMAL)("%d:Base vector %X",static_cast(port==0x21 ? 0 : 1),static_cast(val)); + LOG(LOG_PIC,LOG_NORMAL)("%d:Base vector %X",port==0x21 ? 0 : 1,val); for (i=0;i<=7;i++) { irqs[i+irq_base].vector=(val&0xf8)+i; }; if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; break; case 2: /* icw 3 */ - LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 3 %X",static_cast(port==0x21 ? 0 : 1),static_cast(val)); + LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 3 %X",port==0x21 ? 0 : 1,val); if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; break; case 3: /* icw 4 */ @@ -149,7 +166,7 @@ static void write_data(Bit32u port,Bit8u val) { */ pic->auto_eoi=(val & 0x2)>0; - LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 4 %X",static_cast(port==0x21 ? 0 : 1),static_cast(val)); + LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 4 %X",port==0x21 ? 0 : 1,val); if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; break; default: /* icw 3, and 4*/ @@ -187,13 +204,13 @@ static Bit8u read_data(Bit32u port) { return ret; } -void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name) { +void PIC_RegisterIRQ(Bitu irq,PIC_EOIHandler handler,char * name) { if (irq>15) E_Exit("PIC:Illegal IRQ"); irqs[irq].name=name; irqs[irq].handler=handler; } -void PIC_FreeIRQ(Bit32u irq) { +void PIC_FreeIRQ(Bitu irq) { if (irq>15) E_Exit("PIC:Illegal IRQ"); irqs[irq].name=0; irqs[irq].handler=0; @@ -202,7 +219,7 @@ void PIC_FreeIRQ(Bit32u irq) { PIC_IRQCheck&=~(1 << irq); } -void PIC_ActivateIRQ(Bit32u irq) { +void PIC_ActivateIRQ(Bitu irq) { if (irq<16) { irqs[irq].active=true; if (!irqs[irq].masked) { @@ -211,7 +228,7 @@ void PIC_ActivateIRQ(Bit32u irq) { } } -void PIC_DeActivateIRQ(Bit32u irq) { +void PIC_DeActivateIRQ(Bitu irq) { if (irq<16) { irqs[irq].active=false; PIC_IRQCheck&=~(1 << irq); @@ -221,24 +238,42 @@ void PIC_DeActivateIRQ(Bit32u irq) { void PIC_runIRQs(void) { Bitu i; if (!GETFLAG(IF)) return; - if (PIC_IRQActive!=PIC_NOIRQ) return; if (!PIC_IRQCheck) return; + Bit16u IRQ_priority_lookup[17] = + { 0,1,10,11,12,13,14,15,2,3,4,5,6,7,8,9,16 }; + Bit16u activeIRQ = PIC_IRQActive; + if (activeIRQ==PIC_NOIRQ) activeIRQ = 16; for (i=0;i<=15;i++) { - if (i!=2) { - if (!irqs[i].masked && irqs[i].active) { - irqs[i].active=false; - PIC_IRQCheck&=~(1 << i); - Interrupt(irqs[i].vector); - if (!pics[0].auto_eoi) { - PIC_IRQActive=i; - irqs[i].inservice=true; + if (IRQ_priority_lookup[i]index=index; entry->event=handler; - entry->type=EVENT; - pic.free_entry=pic.free_entry->next; - AddEntry(entry); -} - -void PIC_AddIRQ(Bitu irq,Bitu delay) { - if (irq>15) E_Exit("PIC:Illegal IRQ"); - if (!pic.free_entry) { - LOG(LOG_PIC,LOG_ERROR)("Event queue full"); - return; - } - PICEntry * entry=pic.free_entry; - Bitu index=delay+PIC_Index(); - entry->index=index; - entry->irq=irq; - entry->type=IRQ; pic.free_entry=pic.free_entry->next; AddEntry(entry); } @@ -305,30 +324,27 @@ void PIC_RemoveEvents(PIC_EventHandler handler) { PICEntry * prev_entry; prev_entry=0; while (entry) { - switch (entry->type) { - case EVENT: - if (entry->event==handler) { - if (prev_entry) { - prev_entry->next=entry->next; - entry->next=pic.free_entry; - pic.free_entry=entry; - entry=prev_entry->next; - continue; - } else { - pic.next_entry=entry->next; - entry->next=pic.free_entry; - pic.free_entry=entry; - entry=pic.next_entry; - continue; - } + if (entry->event==handler) { + if (prev_entry) { + prev_entry->next=entry->next; + entry->next=pic.free_entry; + pic.free_entry=entry; + entry=prev_entry->next; + continue; + } else { + pic.next_entry=entry->next; + entry->next=pic.free_entry; + pic.free_entry=entry; + entry=pic.next_entry; + continue; } - break; } prev_entry=entry; entry=entry->next; - } + } } + bool PIC_RunQueue(void) { /* Check to see if a new milisecond needs to be started */ CPU_CycleLeft+=CPU_Cycles; @@ -341,14 +357,7 @@ bool PIC_RunQueue(void) { while (pic.next_entry && pic.next_entry->index<=index) { PICEntry * entry=pic.next_entry; pic.next_entry=entry->next; - switch (entry->type) { - case EVENT: - (entry->event)(); - break; - case IRQ: - PIC_ActivateIRQ(entry->irq); - break; - } + (entry->event)(); /* Put the entry in the free list */ entry->next=pic.free_entry; pic.free_entry=entry; @@ -487,7 +496,7 @@ void PIC_Init(Section* sec) { irqs[0].masked=false; /* Enable system timer */ irqs[1].masked=false; /* Enable Keyboard IRQ */ irqs[8].masked=false; /* Enable RTC IRQ */ - irqs[12].masked=false; /* Enable Mouse IRQ */ +/* irqs[12].masked=false; moved to mouse.cpp */ /* Enable Mouse IRQ */ IO_RegisterReadHandler(0x20,read_command,"Master PIC Command"); IO_RegisterReadHandler(0x21,read_data,"Master PIC Data"); IO_RegisterWriteHandler(0x20,write_command,"Master PIC Command"); diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index fc8f6a4..93430fe 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -65,6 +65,8 @@ enum DSP_MODES { enum DMA_MODES { DMA_NONE, DMA_8_SILENCE, + DMA_2_SINGLE, + DMA_3_SINGLE, DMA_4_SINGLE, DMA_8_SINGLE,DMA_8_AUTO, DMA_16_SINGLE,DMA_16_AUTO, @@ -202,7 +204,7 @@ static void DSP_SetSpeaker(bool how) { static INLINE void SB_RaiseIRQ(SB_IRQS type) { LOG(LOG_SB,LOG_NORMAL)("Raising IRQ"); - PIC_AddIRQ(sb.hw.irq,0); + PIC_ActivateIRQ(sb.hw.irq); switch (type) { case SB_IRQ_8: sb.irq.pending_8bit=true; @@ -285,6 +287,34 @@ INLINE Bit16s decode_ADPCM_4_sample(Bit8u sample,Bits& reference,Bits& scale) { #endif +INLINE Bit16s decode_ADPCM_2_sample(Bit8u sample,Bits& reference,Bits& scale) { + static Bits scaleMap[8] = { -2, -1, 0, 0, 1, 1, 1, 1 }; + + if (sample & 0x02) { + reference = max(0x00, reference - ((sample & 0x01) << (scale+2))); + } else { + reference = min(0xff, reference + ((sample & 0x01) << (scale+2))); + } + scale = max(2, min(6, scaleMap[sample & 0x07])); + return (((Bit8s)reference)^0x80)<<8; +} + +INLINE Bit16s decode_ADPCM_3_sample(Bit8u sample,Bits& reference,Bits& scale) { + static Bits scaleMap[8] = { -2, -1, 0, 0, 1, 1, 1, 1 }; + + if (sample & 0x04) { + reference = max(0x00, reference - ((sample & 0x03) << (scale+1))); + } else { + reference = min(0xff, reference + ((sample & 0x03) << (scale+1))); + } + scale = max(2, min(6, scaleMap[sample & 0x07])); + return (((Bit8s)reference)^0x80)<<8; +} + + + + + static void GenerateDMASound(Bitu size) { /* Check some variables */ if (!size) return; @@ -296,8 +326,72 @@ static void GenerateDMASound(Bitu size) { #else if (index<2000) size=sb.dma.left; #endif - Bitu read,i; + Bitu read,i,ad; switch (sb.dma.mode) { + case DMA_2_SINGLE: + if (sb.adpcm.reference==0x1000000 && sb.dma.left) { + Bit8u ref; + read=DMA_8_Read(sb.hw.dma8,&ref,1); + if (!read) { sb.mode=MODE_NONE;return; } + sb.dma.left--; + sb.adpcm.reference=0; + sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE; + } + if (sb.dma.left> 6,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*4+1]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >>4) & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*4+2]=decode_ADPCM_2_sample((sb.dma.buf.b8[i] >>2)& 0x3,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*4+3]=decode_ADPCM_2_sample(sb.dma.buf.b8[i] & 0x3,sb.adpcm.reference,sb.adpcm.stepsize); + } + read*=4; + break; + case DMA_3_SINGLE: + if (sb.adpcm.reference==0x1000000 && sb.dma.left) { + Bit8u ref; + read=DMA_8_Read(sb.hw.dma8,&ref,1); + if (!read) { sb.mode=MODE_NONE;return;} + sb.dma.left--; + sb.adpcm.reference=0; + sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE; + } + if (sb.dma.left>3)&7, sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*8+2]=decode_ADPCM_3_sample(((sb.dma.buf.b8[i*3] >>6)&3)&((sb.dma.buf.b8[i*3+1]&1)<<2),sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*8+3]=decode_ADPCM_3_sample((sb.dma.buf.b8[i*3+1]>>1)&7,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*8+4]=decode_ADPCM_3_sample((sb.dma.buf.b8[i*3+1]>>4)&7,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*8+5]=decode_ADPCM_3_sample(((sb.dma.buf.b8[i*3+1]>>7)&1)&((sb.dma.buf.b8[i*3+2]&3)<<1),sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*8+6]=decode_ADPCM_3_sample((sb.dma.buf.b8[i*3+2]>>2)&7,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*8+7]=decode_ADPCM_3_sample((sb.dma.buf.b8[i*3+2]>>5)&7,sb.adpcm.reference,sb.adpcm.stepsize); + } + read*=8; + if (ad) { + sb.tmp.buf.m[read]=decode_ADPCM_3_sample((sb.dma.buf.b8[read*3/8])&7,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[read+1]=decode_ADPCM_3_sample((sb.dma.buf.b8[read*3/8]>>3)&7,sb.adpcm.reference,sb.adpcm.stepsize); + read+=2; + if (ad==2) { + sb.tmp.buf.m[read]=decode_ADPCM_3_sample(((sb.dma.buf.b8[(read-2)*3/8-1]>>6)&3)&(sb.dma.buf.b8[read*3/8]&1), sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[read+1]=decode_ADPCM_3_sample((sb.dma.buf.b8[(read-2)*3/8]>>1)&7,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[read+2]=decode_ADPCM_3_sample((sb.dma.buf.b8[(read-2)*3/8]>>4)&7,sb.adpcm.reference,sb.adpcm.stepsize); + read+=3; + } + } + break; case DMA_4_SINGLE: if (sb.adpcm.reference==0x1000000 && sb.dma.left) { //TODO Check this @@ -457,6 +551,10 @@ static void DSP_ChangeMode(DSP_MODES mode) { sb.mode=mode; } +static void DSP_RaiseIRQEvent(void) { + SB_RaiseIRQ(SB_IRQ_8); +} + static void DSP_StartDMATranfser(DMA_MODES mode) { char * type; /* First fill with current whatever is playing */ @@ -470,7 +568,7 @@ static void DSP_StartDMATranfser(DMA_MODES mode) { sb.tmp.index=0; switch (mode) { case DMA_8_SILENCE: - PIC_AddIRQ(sb.hw.irq,((1000000*sb.dma.left)/sb.dma.rate)); + PIC_AddEvent(&DSP_RaiseIRQEvent,((1000000*sb.dma.left)/sb.dma.rate)); sb.dma.mode=DMA_NONE; return; case DMA_8_SINGLE: @@ -485,6 +583,14 @@ static void DSP_StartDMATranfser(DMA_MODES mode) { type="4-Bit ADPCM Single Cycle"; sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; break; + case DMA_3_SINGLE: + type="3-Bit ADPCM Single Cycle"; + sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + break; + case DMA_2_SINGLE: + type="2-Bit ADPCM Single Cycle"; + sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + break; default: LOG(LOG_SB,LOG_ERROR)("DSP:Illegal transfer mode %d",mode); return; @@ -510,6 +616,8 @@ static void DSP_AddData(Bit8u val) { static void DSP_Reset(void) { + LOG(LOG_SB,LOG_ERROR)("DSP:Reset"); + PIC_DeActivateIRQ(sb.hw.irq); DSP_ChangeMode(MODE_NONE); sb.dsp.cmd_len=0; sb.dsp.in.pos=0; @@ -588,6 +696,18 @@ static void DSP_DoCommand(void) { sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); DSP_StartDMATranfser(DMA_4_SINGLE); break; + case 0x77: /* 074h : Single Cycle 3-bit(2.6bit) ADPCM Reference*/ + sb.adpcm.reference=0x1000000; + case 0x76: /* 074h : Single Cycle 3-bit(2.6bit) ADPCM */ + sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); + DSP_StartDMATranfser(DMA_3_SINGLE); + break; + case 0x17: /* 074h : Single Cycle 2-bit ADPCM Reference*/ + sb.adpcm.reference=0x1000000; + case 0x16: /* 074h : Single Cycle 2-bit ADPCM */ + sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); + DSP_StartDMATranfser(DMA_2_SINGLE); + break; case 0x80: /* Silence DAC */ sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); DSP_StartDMATranfser(DMA_8_SILENCE); diff --git a/src/hardware/serialport.cpp b/src/hardware/serialport.cpp index c2ba4a9..a5ba389 100644 --- a/src/hardware/serialport.cpp +++ b/src/hardware/serialport.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/softmodem.cpp b/src/hardware/softmodem.cpp index 38e568e..29ab9bf 100644 --- a/src/hardware/softmodem.cpp +++ b/src/hardware/softmodem.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -590,7 +590,7 @@ void MODEM_Init(Section* sec) { unsigned long args = 1; Section_prop * section=static_cast(sec); - if(!section->Get_bool("enabled")) return; + if(!section->Get_bool("modem")) return; if(SDLNet_Init()==-1) { LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError()); diff --git a/src/hardware/tandy_sound.cpp b/src/hardware/tandy_sound.cpp index d7d55fa..4078540 100644 --- a/src/hardware/tandy_sound.cpp +++ b/src/hardware/tandy_sound.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/timer.cpp b/src/hardware/timer.cpp index b071dc0..b8a9fe8 100644 --- a/src/hardware/timer.cpp +++ b/src/hardware/timer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: timer.cpp,v 1.19 2003/10/14 08:38:36 qbix79 Exp $ */ +/* $Id: timer.cpp,v 1.20 2004/01/10 11:43:41 qbix79 Exp $ */ #include "dosbox.h" #include "inout.h" @@ -209,6 +209,8 @@ void TIMER_Init(Section* sect) { pit[0].micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)pit[0].cntr)); pit[2].micro=100; pit[2].read_latch=-1; /* MadTv1 */ + pit[2].write_state = 3; /* Chuck Yeager */ + pit[2].mode=3; PIC_AddEvent(PIT0_Event,pit[0].micro); } diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index 17a0373..3b9c325 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,14 +28,21 @@ VGA_Type vga; +Bit32u CGA_2_Table[16]; Bit32u CGA_4_Table[256]; +Bit32u CGA_16_Table[256]; +Bit32u TXT_Font_Table[16]; +Bit32u TXT_FG_Table[16]; +Bit32u TXT_BG_Table[16]; Bit32u ExpandTable[256]; Bit32u Expand16Table[4][16]; -Bit32u Expand16BigTable[0x10000]; Bit32u FillTable[16]; +Bit32u ColorTable[16]; + void VGA_SetMode(VGAModes mode) { + if (vga.mode == mode) return; vga.mode=mode; VGA_SetupHandlers(); VGA_StartResize(); @@ -99,19 +106,39 @@ void VGA_Init(Section* sec) { CGA_4_Table[i]=((i>>0)&3) | (((i>>2)&3) << 8)| (((i>>4)&3) <<16) | (((i>>6)&3) << 24); #else CGA_4_Table[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24); + + #endif } for (i=0;i<16;i++) { + TXT_FG_Table[i]=i | (i << 8)| (i <<16) | (i << 24); + TXT_BG_Table[i]=i | (i << 8)| (i <<16) | (i << 24); + #ifdef WORDS_BIGENDIAN - FillTable[i]= ((i & 1) ? 0xff000000 : 0) | - ((i & 2) ? 0x00ff0000 : 0) | - ((i & 4) ? 0x0000ff00 : 0) | - ((i & 8) ? 0x000000ff : 0) ; + CGA_2_Table[i]=((i>>0)&1) | (((i>>1)&1) << 8)| (((i>>1)&1) <<16) | (((i>>3)&1) << 24); + FillTable[i]= + ((i & 1) ? 0xff000000 : 0) | + ((i & 2) ? 0x00ff0000 : 0) | + ((i & 4) ? 0x0000ff00 : 0) | + ((i & 8) ? 0x000000ff : 0) ; + TXT_Font_Table[i]= + ((i & 1) ? 0x000000ff : 0) | + ((i & 2) ? 0x0000ff00 : 0) | + ((i & 4) ? 0x00ff0000 : 0) | + ((i & 8) ? 0xff000000 : 0) ; #else - FillTable[i]= ((i & 1) ? 0x000000ff : 0) | - ((i & 2) ? 0x0000ff00 : 0) | - ((i & 4) ? 0x00ff0000 : 0) | - ((i & 8) ? 0xff000000 : 0) ; + CGA_2_Table[i]=((i>>3)&1) | (((i>>2)&1) << 8)| (((i>>1)&1) <<16) | (((i>>0)&1) << 24); + FillTable[i]= + ((i & 1) ? 0x000000ff : 0) | + ((i & 2) ? 0x0000ff00 : 0) | + ((i & 4) ? 0x00ff0000 : 0) | + ((i & 8) ? 0xff000000 : 0) ; + TXT_Font_Table[i]= + ((i & 1) ? 0xff000000 : 0) | + ((i & 2) ? 0x00ff0000 : 0) | + ((i & 4) ? 0x0000ff00 : 0) | + ((i & 8) ? 0x000000ff : 0) ; + #endif } for (j=0;j<4;j++) { @@ -131,28 +158,5 @@ void VGA_Init(Section* sec) { #endif } } - for (i=0;i<0x10000;i++) { - Bit32u val=0; - if (i & 0x1) val|=0x1 << 24; - if (i & 0x2) val|=0x1 << 16; - if (i & 0x4) val|=0x1 << 8; - if (i & 0x8) val|=0x1 << 0; - - if (i & 0x10) val|=0x4 << 24; - if (i & 0x20) val|=0x4 << 16; - if (i & 0x40) val|=0x4 << 8; - if (i & 0x80) val|=0x4 << 0; - - if (i & 0x100) val|=0x2 << 24; - if (i & 0x200) val|=0x2 << 16; - if (i & 0x400) val|=0x2 << 8; - if (i & 0x800) val|=0x2 << 0; - - if (i & 0x1000) val|=0x8 << 24; - if (i & 0x2000) val|=0x8 << 16; - if (i & 0x4000) val|=0x8 << 8; - if (i & 0x8000) val|=0x8 << 0; - Expand16BigTable[i]=val; - } } diff --git a/src/hardware/vga_attr.cpp b/src/hardware/vga_attr.cpp index e94936c..a486344 100644 --- a/src/hardware/vga_attr.cpp +++ b/src/hardware/vga_attr.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,6 @@ #define attr(blah) vga.attr.blah - void VGA_ATTR_SetPalette(Bit8u index,Bit8u val) { vga.attr.palette[index]=val; if (vga.attr.mode_control & 0x80) val=(val&0xf) | (vga.attr.color_select << 4); @@ -57,12 +56,14 @@ void write_p3c0(Bit32u port,Bit8u val) { break; case 0x10: /* Mode Control Register */ if ((attr(mode_control) ^ val) & 0x80) { - attr(mode_control)=val; + attr(mode_control)^=0x80; for (Bitu i=0;i<0x10;i++) { VGA_ATTR_SetPalette(i,vga.attr.palette[i]); } } - attr(mode_control)=val; + if ((attr(mode_control) ^ val) & 0x08) { + VGA_SetBlinking(val & 0x8); + } /* Special hacks for games programming registers themselves, Doesn't work if they program EGA16 themselves, @@ -73,6 +74,7 @@ void write_p3c0(Bit32u port,Bit8u val) { } else { if (vga.mode==M_VGA) VGA_SetMode(M_EGA16); } + attr(mode_control)=val; //TODO Monochrome mode //TODO 9 bit characters //TODO line wrapping split screen shit see bit 5 @@ -114,6 +116,7 @@ void write_p3c0(Bit32u port,Bit8u val) { case 0x13: /* Horizontal PEL Panning Register */ attr(horizontal_pel_panning)=val & 0xF; switch (vga.mode) { + case M_TEXT2: case M_TEXT16: if (val==0x7) vga.config.pel_panning=7; if (val>0x7) vga.config.pel_panning=0; diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index ad7becd..e957f8e 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -127,8 +127,6 @@ void write_p3d5(Bit32u port,Bit8u val) { */ break; case 0x09: /* Maximum Scan Line Register */ - vga.config.vline_double=(val & 128)>1; - vga.config.vline_height=(val & 0xf); vga.config.line_compare=(vga.config.line_compare & 0x5ff)|(val&0x40)<<3; if ((vga.crtc.maximum_scan_line ^ val) & 0xbf) { crtc(maximum_scan_line)=val; diff --git a/src/hardware/vga_dac.cpp b/src/hardware/vga_dac.cpp index b387d91..4fcb0f8 100644 --- a/src/hardware/vga_dac.cpp +++ b/src/hardware/vga_dac.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,8 +22,6 @@ #include "vga.h" /* -//TODO PEL Mask Maybe -//TODO Find some way to get palette lookups in groups 3C6h (R/W): PEL Mask bit 0-7 This register is anded with the palette index sent for each dot. Should be set to FFh. diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index cbdb01c..103b821 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,390 +17,358 @@ */ #include +#include #include "dosbox.h" #include "video.h" #include "render.h" #include "vga.h" #include "pic.h" -//TODO Make the full draw like the vga really does from video memory. +#define VGA_PARTS 4 -static void VGA_CGA2_Draw(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=&vga.mem.linear[0]; - Bit8u * flip=&vga.mem.linear[8*1024]; - Bit8u * draw; - for (Bitu y=0;y>3;x>0;x--) { - Bit8u val=*(tempread++); - *(draw+0)=(val>>7)&1; - *(draw+1)=(val>>6)&1; - *(draw+2)=(val>>5)&1; - *(draw+3)=(val>>4)&1; - *(draw+4)=(val>>3)&1; - *(draw+5)=(val>>2)&1; - *(draw+6)=(val>>1)&1; - *(draw+7)=(val>>0)&1; - draw+=8; - } - bitdata+=pitch; +typedef Bit8u * (* VGA_Line_Handler)(Bitu vidstart,Bitu panning,Bitu line); + +static VGA_Line_Handler VGA_DrawLine; + +static Bit8u * VGA_HERC_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * reader=&vga.mem.linear[vidstart+(line * 8 * 1024)]; + Bit32u * draw=(Bit32u *)RENDER_TempLine; + for (Bitu x=vga.draw.blocks;x>0;x--) { + Bitu val=*reader++; + *draw++=CGA_2_Table[val >> 4]; + *draw++=CGA_2_Table[val & 0xf]; } + return RENDER_TempLine; } -static void VGA_CGA4_Draw(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=&vga.mem.linear[0]; - Bit8u * flip=&vga.mem.linear[8*1024]; - Bit8u * draw; - for (Bitu y=0;y=flip) reader-=8*1024; - } - draw=bitdata; - for (Bitu x=0;x>2;x++) { - Bit8u val=*(tempread++); - *(Bit32u *)draw=CGA_4_Table[val]; - draw+=4; - } - bitdata+=pitch; +static Bit8u * VGA_CGA2_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + line*=8*1024;Bit32u * draw=(Bit32u *)RENDER_TempLine; + for (Bitu x=vga.draw.blocks;x>0;x--) { + Bitu val=vga.mem.linear[vidstart+line];vidstart=(vidstart+1)&0x1fff; + *draw++=CGA_2_Table[val >> 4]; + *draw++=CGA_2_Table[val & 0xf]; } + return RENDER_TempLine; } -static void VGA_TANDY16_Draw(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=&vga.mem.linear[(vga.tandy.disp_bank << 14) + vga.config.display_start*2]; - - for (Bitu y=0;y>2;x++) { - Bit8u val1=*(tempread++); - Bit8u val2=*(tempread++); - Bit32u full=(val1 & 0x0f) << 8 | - (val1 & 0xf0) >> 4 | - (val2 & 0x0f) << 24 | - (val2 & 0xf0) << 12; - *(Bit32u *)draw=full; - draw+=4; - } - bitdata+=pitch; - if ((y & 3)==3)reader+=160; +static Bit8u * VGA_CGA4_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + line*=8*1024;Bit32u * draw=(Bit32u *)RENDER_TempLine; + for (Bitu x=0;x0;cy--) { - Bit8u * draw_char=draw_start; - /* Do first character keeping track of panning */ - { - Bit8u c=*(reader++); - Bit8u * findex=&vga.draw.font[c*32]; - Bit8u col=*(reader++); - Bit8u fg=col & 0xF; - Bit8u bg=(col>> 4); - Bit8u * draw_line=draw_char; - Bit8u bit_index=1 << (7-panning); - for (Bitu y=vga.draw.font_height;y>0;y--) { - Bit8u * draw=draw_line; - draw_line+=next_line; - Bit8u bit=bit_index; - Bit8u bit_mask=*findex++; - while (bit) { - if (bit_mask & bit) *draw=fg; - else *draw=bg; - draw++;bit>>=1; - } - } - draw_char+=8-panning; - } - for (Bitu cx=vga.draw.cols-1;cx>0;cx--) { - Bit8u c=*(reader++); - Bit8u * findex=&vga.draw.font[c*32]; - Bit8u col=*(reader++); - Bit8u fg=col & 0xF; - Bit8u bg=(col>> 4); - Bit8u * draw=draw_char; - for (Bitu y=vga.draw.font_height;y>0;y--) { - Bit8u bit_mask=*findex++; - #include "font-switch.h" - draw+=next_line; - } - draw_char+=8; - } - /* Do last character if needed */ - if (panning) { - Bit8u c=*(reader); - Bit8u * findex=&vga.draw.font[c*32]; - Bit8u col=*(reader+1); - Bit8u fg=col & 0xF; - Bit8u bg=(col>> 4); - Bit8u * draw_line=draw_char; - Bit8u bit_index=1 << panning; - for (Bitu y=vga.draw.font_height;y>0;y--) { - Bit8u * draw=draw_line; - draw_line+=next_line; - Bit8u bit=bit_index; - Bit8u bit_mask=*findex++; - while (bit) { - if (bit_mask & bit) *draw=fg; - else *draw=bg; - draw++;bit>>=1; - } - } - } - draw_start+=next_charline; - reader+=next_start; +static Bit8u convert16[16]={ + 0x0,0x2,0x1,0x3,0x5,0x7,0x4,0x9, + 0x6,0xa,0x8,0xb,0xd,0xe,0xc,0xf +}; + +static Bit8u * VGA_CGA16_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + line*=8*1024;Bit32u * draw=(Bit32u *)RENDER_TempLine; + for (Bitu x=0;x> 4] | convert16[val & 0xf] << 16; + *draw++=full|=full<<8; } -/* Cursor handling */ - vga.draw.cursor.count++; - if (vga.draw.cursor.count>16) vga.draw.cursor.count=0; - - if(vga.draw.cursor.enabled && (vga.draw.cursor.count>8)) { /* Draw a cursor if enabled */ - Bits cur_start=vga.config.cursor_start-start; - if (cur_start<0) return; - - Bitu row=cur_start / (vga.config.scan_len*2); - Bitu col=cur_start % (vga.config.scan_len*2); - Bit32u att=vga.mem.linear[vga.config.cursor_start*2+1]&0xf; - att=(att << 8) | att; - att=(att << 16) | att; - - if ((col*8)>=vga.draw.width) return; - if ((row*vga.draw.font_height)>=vga.draw.height) return; - if (vga.draw.cursor.sline>=vga.draw.font_height) return; - if (vga.draw.cursor.sline>vga.draw.cursor.eline) return; - Bit8u * cursor_draw=bitdata+(row*vga.draw.font_height+vga.draw.cursor.sline)*vga.draw.width+col*8; - - for (Bits loop=vga.draw.cursor.eline-vga.draw.cursor.sline;loop>=0;loop--) { - *((Bit32u *)cursor_draw)=att; - *((Bit32u *)(cursor_draw+4))=att; - cursor_draw+=vga.draw.width; - } - } + return RENDER_TempLine; } -static void EndRetrace(void) { - /* start the actual display update now */ - RENDER_DoUpdate(); - vga.config.retrace=false; +static Bit8u * VGA_TANDY16_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit8u * reader=&vga.mem.linear[(vga.tandy.disp_bank << 14) + vidstart + (line * 8 * 1024)]; + Bit32u * draw=(Bit32u *)RENDER_TempLine; + for (Bitu x=0;x> 4 | + (val2 & 0x0f) << 24 | + (val2 & 0xf0) << 12; + } + return RENDER_TempLine; } -static void VGA_BlankTimer() { - PIC_AddEvent(VGA_BlankTimer,vga.draw.blank); - PIC_AddEvent(EndRetrace,667); - /* Setup a timer to destroy the vertical retrace bit in a few microseconds */ - vga.config.real_start=vga.config.display_start; +static Bit8u * VGA_EGA_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + return &vga.mem.linear[512*1024+vidstart*8+panning]; +} +static Bit8u * VGA_VGA_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + return &vga.mem.linear[vidstart*4+panning]; +} + + +static Bit32u FontMask[2]={0xffffffff,0x0}; +static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart,Bitu panning,Bitu line) { + Bit32u * draw=(Bit32u *)RENDER_TempLine; + Bit8u * vidmem=&vga.mem.linear[vidstart]; + for (Bitu cx=0;cx>4]; + Bit32u mask2=TXT_Font_Table[font&0xf]; + Bitu col=vidmem[cx*2+1]; + Bit32u fg=TXT_FG_Table[col&0xf]; + Bit32u bg=TXT_BG_Table[col>>4]; + mask1&=FontMask[col >> 7];mask2&=FontMask[col >> 7]; + *draw++=fg&mask1 | bg&~mask1; + *draw++=fg&mask2 | bg&~mask2; + } + Bits font_addr=(vga.config.cursor_start*2-vidstart)/2; + if (!vga.draw.cursor.enabled || !(vga.draw.cursor.count&0x8)) goto skip_cursor; + if (font_addr>=0 && font_addrvga.draw.cursor.eline) goto skip_cursor; + draw=(Bit32u *)&RENDER_TempLine[font_addr*8]; + Bit32u att=TXT_FG_Table[vga.mem.linear[vga.config.cursor_start*2+1]&0xf]; + *draw++=att;*draw++=att; + } +skip_cursor: + return RENDER_TempLine; +} + +static void VGA_VerticalDisplayEnd(void) { vga.config.retrace=true; + vga.config.real_start=vga.config.display_start; } +static void VGA_HorizontalTimer(void) { -void VGA_DrawHandler(RENDER_Part_Handler part_handler) { - Bit8u * buf,* bufsplit; - /* Draw the current frame */ - if (!vga.draw.resizing) { - if (vga.config.line_compare=vga.draw.height){ - LOG(LOG_VGAGFX,LOG_NORMAL)("Split at %d",stop); - goto drawnormal; - } - switch (vga.mode) { - case M_EGA16: - buf=&vga.mem.linear[512*1024+vga.config.real_start*8+vga.config.pel_panning]; - bufsplit=&vga.mem.linear[512*1024]; - break; - case M_VGA: - case M_LIN8: - buf=&vga.mem.linear[vga.config.real_start*4+vga.config.pel_panning]; - bufsplit=vga.mem.linear; - break; - case M_TEXT16: - { - Bitu first_rows=stop/vga.draw.font_height; - if (vga.config.hlines_skip) first_rows++; - if (stop%vga.draw.font_height) first_rows++; - Bitu next_rows=(vga.draw.height-stop)/vga.draw.font_height; - if ((vga.draw.height-stop)%vga.draw.font_height) next_rows++; - VGA_TEXT_Draw(&vga.mem.linear[512*1024],vga.config.real_start,vga.config.pel_panning,first_rows); - VGA_TEXT_Draw(&vga.mem.linear[1024*1024],0,0,next_rows); - buf=&vga.mem.linear[512*1024+vga.config.hlines_skip*vga.draw.width]; - bufsplit=&vga.mem.linear[1024*1024]; - } - break; - default: - LOG(LOG_VGAGFX,LOG_NORMAL)("VGA:Unhandled split screen mode %d",vga.mode); - goto norender; - } - if (stop) part_handler(buf,0,0,vga.draw.width,stop); - if (vga.draw.height-stop) part_handler(bufsplit,0,stop,vga.draw.width,vga.draw.height-stop); - } else { -drawnormal: - switch (vga.mode) { - case M_CGA2: - VGA_CGA2_Draw(&vga.mem.linear[512*1024],vga.draw.width); - buf=&vga.mem.linear[512*1024]; - break; - case M_CGA4: - VGA_CGA4_Draw(&vga.mem.linear[512*1024],vga.draw.width); - buf=&vga.mem.linear[512*1024]; - break; - case M_TANDY16: - VGA_TANDY16_Draw(&vga.mem.linear[512*1024],vga.draw.width); - buf=&vga.mem.linear[512*1024]; - break; - case M_EGA16: - buf=&vga.mem.linear[512*1024+vga.config.real_start*8+vga.config.pel_panning]; - break; - case M_VGA: - case M_LIN8: - buf=&vga.mem.linear[vga.config.real_start*4+vga.config.pel_panning]; - break; - case M_TEXT16: - { - Bitu rows=vga.draw.rows; - if (vga.config.hlines_skip) rows++; - VGA_TEXT_Draw(&vga.mem.linear[512*1024],vga.config.real_start,vga.config.pel_panning,rows); - buf=&vga.mem.linear[512*1024+vga.config.hlines_skip*vga.draw.width]; - } - break; - default: - return; - } - part_handler(buf,0,0,vga.draw.width,vga.draw.height); +} + +static void VGA_DrawPart(void) { + Bitu subline=0;Bitu vidofs=vga.config.real_start; + Bit8u * draw=0; + while (vga.draw.lines_left) { + vga.draw.lines_left--; + Bit8u * data=VGA_DrawLine(vga.draw.address,vga.draw.panning,vga.draw.address_line); + RENDER_DrawLine(data); + vga.draw.address_line++; + if (vga.draw.address_line>=vga.draw.address_line_total) { + vga.draw.address_line=0; + vga.draw.address+=vga.draw.address_add; + } + if (vga.draw.split_line==vga.draw.lines_left) { + vga.draw.address=0;vga.draw.panning=0; + vga.draw.address_line=0; } -norender:; } - + RENDER_EndUpdate(); +// vga.draw.parts_left--; +// if (vga.draw.parts_left) PIC_AddEvent(VGA_DrawPart,vga.draw.micro.parts); } +void VGA_SetBlinking(Bitu enabled) { + Bitu b; + LOG(LOG_VGA,LOG_NORMAL)("Blinking %d",enabled); + if (enabled) { + b=0;vga.draw.blinking=1; //used to -1 but blinking is unsigned + vga.attr.mode_control|=0x08; + vga.cga.mode_control&=~0x20; + } else { + b=8;vga.draw.blinking=0; + vga.attr.mode_control&=~0x08; + vga.cga.mode_control|=0x20; + } + for (Bitu i=0;i<8;i++) TXT_BG_Table[i+8]=(b+i) | ((b+i) << 8)| ((b+i) <<16) | ((b+i) << 24); +} + +static void VGA_VerticalTimer(void) { + vga.config.retrace=false; + PIC_AddEvent(VGA_VerticalTimer,vga.draw.micro.vtotal); + PIC_AddEvent(VGA_VerticalDisplayEnd,vga.draw.micro.vend); + vga.draw.parts_left=4; + vga.draw.lines_left=vga.draw.lines_total; + vga.draw.address=vga.config.real_start; + vga.draw.address_line=vga.config.hlines_skip; + vga.draw.split_line=vga.draw.lines_total-(vga.config.line_compare/vga.draw.lines_scaled); + vga.draw.panning=vga.config.pel_panning; + switch (vga.mode) { + case M_TEXT2:case M_TEXT16: + vga.draw.cursor.count++; + /* check for blinking and blinking change delay */ + FontMask[1]=(vga.attr.mode_control & (vga.draw.cursor.count >> 1) & 0x8) ? + 0 : 0xffffffff; + vga.draw.address=(vga.draw.address*2); + break; + case M_CGA4:case M_CGA2:case M_CGA16: + vga.draw.address=(vga.draw.address*2)&0x1fff; + break; + } + if (RENDER_StartUpdate()) { + VGA_DrawPart(); + } +} void VGA_SetupDrawing(void) { /* Calculate the FPS for this screen */ double fps; - Bitu vtotal=2 + (vga.crtc.vertical_total | ((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4) ); + Bitu vtotal=2 + vga.crtc.vertical_total | + ((vga.crtc.overflow & 1) << 8) | ((vga.crtc.overflow & 0x20) << 4); Bitu htotal=5 + vga.crtc.horizontal_total; - Bitu vdispend = 1 + (vga.crtc.vertical_display_end | ((vga.crtc.overflow & 2)<<7) | ((vga.crtc.overflow & 0x40) << 3) ); + Bitu vdispend = 1 + (vga.crtc.vertical_display_end | + ((vga.crtc.overflow & 2)<<7) | ((vga.crtc.overflow & 0x40) << 3) | + ((vga.s3.ex_ver_overflow & 0x2) << 9)); Bitu hdispend = 1 + (vga.crtc.horizontal_display_end); Bitu hbstart = vga.crtc.start_horizontal_blanking; - Bitu vbstart = vga.crtc.start_vertical_blanking | ((vga.crtc.overflow & 0x08) << 5) | ((vga.crtc.maximum_scan_line & 0x20) << 4) ; - - if (hbstart> 2) & 3; clock=1000*S3_CLOCK(vga.s3.clk[clock].m,vga.s3.clk[clock].n,vga.s3.clk[clock].r); /* Check for 8 for 9 character clock mode */ if (vga.seq.clocking_mode & 1 ) clock/=8; else clock/=9; /* Check for pixel doubling, master clock/2 */ - if (vga.seq.clocking_mode & 0x8) clock/=2; + if (vga.seq.clocking_mode & 0x8) { + htotal*=2; + } /* Check for dual transfer whatever thing,master clock/2 */ if (vga.s3.pll.cmd & 0x10) clock/=2; - - + LOG(LOG_VGA,LOG_NORMAL)("H total %d, V Total %d",htotal,vtotal); LOG(LOG_VGA,LOG_NORMAL)("H D End %d, V D End %d",hdispend,vdispend); fps=clock/(vtotal*htotal); + double linemicro=(1000000/fps); + vga.draw.parts_total=VGA_PARTS; + vga.draw.micro.vtotal=(Bitu)(linemicro); + linemicro/=vtotal; //Really make it the line_micro + vga.draw.micro.vend=(Bitu)(linemicro*vrstart); + vga.draw.micro.parts=(Bitu)((linemicro*vdispend)/vga.draw.parts_total); + vga.draw.micro.htotal=(Bitu)(linemicro); + vga.draw.micro.hend=(Bitu)((linemicro/htotal)*hrstart); + + double correct_ratio=(100.0/525.0); + double aspect_ratio=((double)htotal/((double)vtotal)/correct_ratio); + vga.draw.resizing=false; - Bitu width,height,pitch,flags; + Bitu width,height,pitch; + Bitu scalew=1; + Bitu scaleh=1; - flags=0; - vga.draw.lines=height=vdispend; width=hdispend; - vga.draw.double_height=vga.config.vline_double; - vga.draw.double_width=(vga.seq.clocking_mode & 0x8)>0; - vga.draw.font_height=vga.config.vline_height+1; + height=vdispend; + vga.draw.double_scan=false; + vga.draw.font_height=(vga.crtc.maximum_scan_line&0xf)+1; switch (vga.mode) { case M_VGA: - vga.draw.double_width=true; //Hack since 256 color modes use 2 clocks for a pixel - /* Don't know might do this different sometime, will have to do for now */ - if (!vga.draw.double_height) { - if (vga.config.vline_height&1) { - vga.draw.double_height=true; - vga.draw.font_height/=2; - } - } + scalew=2; + scaleh*=vga.draw.font_height; + if (vga.crtc.maximum_scan_line&0x80) scaleh*=2; + vga.draw.lines_scaled=scaleh; + height/=scaleh; width<<=2; pitch=vga.config.scan_len*8; + vga.draw.address_add=vga.config.scan_len*2; + vga.draw.address_line_total=1; + VGA_DrawLine=VGA_VGA_Draw_Line; break; case M_LIN8: width<<=3; - if (vga.draw.double_width) width>>=1; - if (!vga.draw.double_height) { - if (vga.config.vline_height&1) { - vga.draw.double_height=true; - vga.draw.font_height/=2; - } - } - pitch=vga.config.scan_len*8; + scaleh*=vga.draw.font_height; + pitch=vga.config.scan_len*4; + vga.draw.address_add=vga.config.scan_len*2; + vga.draw.lines_scaled=scaleh; + vga.draw.address_line_total=1; + VGA_DrawLine=VGA_VGA_Draw_Line; break; case M_EGA16: width<<=3; pitch=vga.config.scan_len*16; + scaleh*=vga.draw.font_height; + if (vga.crtc.maximum_scan_line&0x80) scaleh*=2; + vga.draw.lines_scaled=scaleh; + height/=scaleh; + if (vga.seq.clocking_mode & 0x8) scalew*=2; + vga.draw.address_add=vga.config.scan_len*2; + vga.draw.address_line_total=1; + VGA_DrawLine=VGA_EGA_Draw_Line; break; case M_CGA4: - width<<=3; + case M_CGA16: //Let is use 320x200 res and double pixels myself + scaleh=2;scalew=2; + vga.draw.blocks=width; + width<<=2; + height/=2; pitch=width; + vga.draw.lines_scaled=1; + vga.draw.address_line_total=2; + vga.draw.address_add=80; //CGA doesn't have an offset reg + VGA_DrawLine=(vga.mode == M_CGA4) ? VGA_CGA4_Draw_Line : VGA_CGA16_Draw_Line; break; case M_CGA2: + scaleh=2;height/=2; + vga.draw.address_line_total=2; + vga.draw.blocks=width; width<<=3; pitch=width; + vga.draw.address_line_total=2; + vga.draw.address_add=80; //CGA doesn't have an offset reg + vga.draw.lines_scaled=1; + VGA_DrawLine=VGA_CGA2_Draw_Line; + break; + case M_HERC: + vga.draw.address_line_total=4; + width*=9; + vga.draw.blocks=width/8; + vga.draw.address_add=width/8; + vga.draw.lines_scaled=1; + height=348; + pitch=width; + aspect_ratio=1.5; + VGA_DrawLine=VGA_HERC_Draw_Line; break; case M_TANDY16: - width<<=3; + scaleh=2;scalew=2; + vga.draw.blocks=width*2; + vga.draw.address_add=160; + vga.draw.address_line_total=4; + vga.draw.lines_scaled=1; + width<<=2;height/=2; pitch=width; + VGA_DrawLine=VGA_TANDY16_Draw_Line; break; + case M_TEXT2: case M_TEXT16: - /* probably a 16-color text mode, got to detect mono mode somehow */ - vga.draw.font_height=vga.config.vline_height+1; - vga.draw.cols=width; - vga.draw.rows=(height/vga.draw.font_height); - if (height % vga.draw.font_height) vga.draw.rows++; + aspect_ratio=1.0; + if (vga.draw.font_height<4 && (machine640) width=640; if (height>480) height=480; pitch=width; + VGA_DrawLine=VGA_TEXT_Draw_Line; break; default: LOG(LOG_VGA,LOG_ERROR)("Unhandled VGA type %d while checking for resolution"); }; - if (vga.draw.double_height) { - flags|=DoubleHeight; - height/=2; - } - if (vga.draw.double_width) { - flags|=DoubleWidth; - /* Double width is dividing main clock, the width should be correct already for this */ - } + vga.draw.lines_total=height; if (( width != vga.draw.width) || (height != vga.draw.height) || (pitch != vga.draw.pitch)) { - PIC_RemoveEvents(VGA_BlankTimer); + PIC_RemoveEvents(VGA_VerticalTimer); + PIC_RemoveEvents(VGA_VerticalDisplayEnd); vga.draw.width=width; vga.draw.height=height; vga.draw.pitch=pitch; + vga.draw.scaleh=scaleh; - LOG(LOG_VGA,LOG_NORMAL)("Width %d, Height %d, Pitch %d",width,height,pitch); - LOG(LOG_VGA,LOG_NORMAL)("Flags %X, fps %f",flags,fps); - RENDER_SetSize(width,height,8,pitch,((float)width/(float)height),flags,&VGA_DrawHandler); - vga.draw.blank=(Bitu)(1000000/fps); - PIC_AddEvent(VGA_BlankTimer,vga.draw.blank); + LOG(LOG_VGA,LOG_NORMAL)("Width %d, Height %d, fps %f",width,height,fps); + LOG(LOG_VGA,LOG_NORMAL)("Scalew %d, Scaleh %d aspect %f",scalew,scaleh,aspect_ratio); + RENDER_SetSize(width,height,8,pitch,aspect_ratio,scalew,scaleh); + PIC_AddEvent(VGA_VerticalTimer,vga.draw.micro.vtotal); } }; diff --git a/src/hardware/vga_gfx.cpp b/src/hardware/vga_gfx.cpp index 8304651..2498c26 100644 --- a/src/hardware/vga_gfx.cpp +++ b/src/hardware/vga_gfx.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 23e43b4..0842dd1 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,15 +27,15 @@ #include "paging.h" #include "pic.h" -static Bit8u VGA_NormalReadHandler(PhysPt start) { +static Bitu VGA_NormalReadHandler(PhysPt start) { vga.latch.d=vga.mem.latched[start].d; switch (vga.config.read_mode) { case 0: - return(vga.latch.b[vga.config.read_map_select]); + return (vga.latch.b[vga.config.read_map_select]); case 1: VGA_Latch templatch; templatch.d=(vga.latch.d & FillTable[vga.config.color_dont_care]) ^ FillTable[vga.config.color_compare & vga.config.color_dont_care]; - return ~(templatch.b[0] | templatch.b[1] | templatch.b[2] | templatch.b[3]); + return (Bit8u)~(templatch.b[0] | templatch.b[1] | templatch.b[2] | templatch.b[3]); } return 0; } @@ -84,7 +84,7 @@ INLINE static Bit32u ModeOperation(Bit8u val) { } static void VGA_GFX_16_WriteHandler(PhysPt start,Bit8u val) { - val=(val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate)); + val=((val >> vga.config.data_rotate) | (val << (8-vga.config.data_rotate))); Bit32u data=ModeOperation(val); /* Update video memory and the pixel buffer */ VGA_Latch pixels; @@ -116,7 +116,6 @@ static void VGA_GFX_16_WriteHandler(PhysPt start,Bit8u val) { static void VGA_GFX_256U_WriteHandler(PhysPt start,Bit8u val) { Bit32u data=ModeOperation(val); -// Bit32u data=ExpandTable[val]; VGA_Latch pixels; pixels.d=vga.mem.latched[start].d; pixels.d&=vga.config.full_not_map_mask; @@ -125,72 +124,214 @@ static void VGA_GFX_256U_WriteHandler(PhysPt start,Bit8u val) { vga.mem.latched[start+64*1024].d=pixels.d; } -static void VGA_TEXT16_Write(PhysPt start,Bit8u val) { - /* Check for page 2 being enabled for writing */ - if (vga.seq.map_mask & 0x4) { - vga.draw.font[start]=val; - } - //TODO Check for writes to other pages with normal text characters/attributes -} +/* Gonna assume that whoever maps vga memory, maps it on 32/64kb boundary */ + +#define VGA_PAGES (128/4) +#define VGA_PAGE_A0 (0xA0000/4096) +#define VGA_PAGE_B0 (0xB0000/4096) +#define VGA_PAGE_B8 (0xB8000/4096) + +static struct { + Bit8u ram_area[VGA_PAGES*4096]; + Bitu map_base; +} vgapages; + +class VGARead_PageHandler : public PageHandler { +public: + Bitu readb(PhysPt addr) { + addr&=0xffff; + return VGA_NormalReadHandler(addr); + } + Bitu readw(PhysPt addr) { + addr&=0xffff; + return + (VGA_NormalReadHandler(addr+0) << 0) | + (VGA_NormalReadHandler(addr+1) << 8); + } + Bitu readd(PhysPt addr) { + addr&=0xffff; + return + (VGA_NormalReadHandler(addr+0) << 0) | + (VGA_NormalReadHandler(addr+1) << 8) | + (VGA_NormalReadHandler(addr+2) << 16) | + (VGA_NormalReadHandler(addr+3) << 24); + } +}; + +class VGA_16_PageHandler : public VGARead_PageHandler { +public: + VGA_16_PageHandler() { + flags=PFLAG_NOCODE; + } + void writeb(PhysPt addr,Bitu val) { + addr&=0xffff; + VGA_GFX_16_WriteHandler(addr+0,(Bit8u)(val >> 0)); + } + void writew(PhysPt addr,Bitu val) { + addr&=0xffff; + VGA_GFX_16_WriteHandler(addr+0,(Bit8u)(val >> 0)); + VGA_GFX_16_WriteHandler(addr+1,(Bit8u)(val >> 8)); + } + void writed(PhysPt addr,Bitu val) { + addr&=0xffff; + VGA_GFX_16_WriteHandler(addr+0,(Bit8u)(val >> 0)); + VGA_GFX_16_WriteHandler(addr+1,(Bit8u)(val >> 8)); + VGA_GFX_16_WriteHandler(addr+2,(Bit8u)(val >> 16)); + VGA_GFX_16_WriteHandler(addr+3,(Bit8u)(val >> 24)); + } +}; + +class VGA_256_PageHandler : public VGARead_PageHandler { +public: + VGA_256_PageHandler() { + flags=PFLAG_NOCODE; + } + void writeb(PhysPt addr,Bitu val) { + addr&=0xffff; + VGA_GFX_256U_WriteHandler(addr+0,(Bit8u)(val >> 0)); + } + void writew(PhysPt addr,Bitu val) { + addr&=0xffff; + VGA_GFX_256U_WriteHandler(addr+0,(Bit8u)(val >> 0)); + VGA_GFX_256U_WriteHandler(addr+1,(Bit8u)(val >> 8)); + } + void writed(PhysPt addr,Bitu val) { + addr&=0xffff; + VGA_GFX_256U_WriteHandler(addr+0,(Bit8u)(val >> 0)); + VGA_GFX_256U_WriteHandler(addr+1,(Bit8u)(val >> 8)); + VGA_GFX_256U_WriteHandler(addr+2,(Bit8u)(val >> 16)); + VGA_GFX_256U_WriteHandler(addr+3,(Bit8u)(val >> 24)); + } +}; + +class VGA_TEXT_PageHandler : public PageHandler { +public: + VGA_TEXT_PageHandler() { + flags=PFLAG_NOCODE; + } + Bitu readb(PhysPt addr) { + addr&=0x7fff; + return vga.draw.font[addr]; + } + void writeb(PhysPt addr,Bitu val){ + addr&=0x7fff; + if (vga.seq.map_mask & 0x4) { + vga.draw.font[addr]=(Bit8u)val; + } + } +}; + + +class VGA_RAM_PageHandler : public PageHandler { +public: + VGA_RAM_PageHandler() { + flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; + } + HostPt GetHostPt(Bitu phys_page) { + phys_page-=VGA_PAGE_A0; + return &vgapages.ram_area[phys_page*4096]; + } +}; + +class VGA_MAP_PageHandler : public PageHandler { +public: + VGA_MAP_PageHandler() { + flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; + } + HostPt GetHostPt(Bitu phys_page) { + phys_page-=vgapages.map_base; + return &vga.mem.linear[vga.s3.bank*64*1024+phys_page*4096]; + } +}; + +class VGA_TANDY_PageHandler : public PageHandler { +public: + VGA_TANDY_PageHandler() { + flags=PFLAG_READABLE|PFLAG_WRITEABLE|PFLAG_NOCODE; + } + HostPt GetHostPt(Bitu phys_page) { + phys_page-=vgapages.map_base; + return &vga.mem.linear[(vga.tandy.mem_bank << 14)+(phys_page * 4096)]; + } +}; + + +static struct { + VGA_RAM_PageHandler hram; + VGA_MAP_PageHandler hmap; + VGA_TEXT_PageHandler htext; + VGA_TANDY_PageHandler htandy; + VGA_256_PageHandler h256; + VGA_16_PageHandler h16; +} vgaph; -static Bit8u VGA_TEXT16_Read(PhysPt start) { - return vga.draw.font[start]; -} void VGA_SetupHandlers(void) { - HostPt where; + PageHandler * range_handler; switch (vga.mode) { case M_LIN8: - where=&vga.mem.linear[vga.s3.bank*64*1024]; + range_handler=&vgaph.hmap; break; case M_VGA: if (vga.config.chained) { - where=&vga.mem.linear[vga.s3.bank*64*1024]; + range_handler=&vgaph.hmap; } else { - vga.config.readhandler=&VGA_NormalReadHandler, - vga.config.writehandler=&VGA_GFX_256U_WriteHandler; - where=0; + range_handler=&vgaph.h256; } break; case M_EGA16: - vga.config.readhandler=&VGA_NormalReadHandler, - vga.config.writehandler=&VGA_GFX_16_WriteHandler; - where=0; + range_handler=&vgaph.h16; break; + case M_TEXT2: case M_TEXT16: /* Check if we're not in odd/even mode */ if (vga.gfx.miscellaneous & 0x2) { - where=&vga.mem.linear[0]; + range_handler=&vgaph.hmap; } else { - vga.config.readhandler=&VGA_TEXT16_Read; - vga.config.writehandler=&VGA_TEXT16_Write; - where=0; + range_handler=&vgaph.htext; } break; case M_TANDY16: - where=&vga.mem.linear[vga.tandy.mem_bank << 14]; + range_handler=&vgaph.htandy; break; + case M_CGA16: case M_CGA4: case M_CGA2: - where=&vga.mem.linear[0]; + range_handler=&vgaph.hmap; break; + case M_HERC: + range_handler=&vgaph.hmap; + if (vga.herc.mode_control&0x80) goto range_b800; + else goto range_b000; default: LOG_MSG("Unhandled vga mode %X",vga.mode); } - VGA_RANGES range; switch ((vga.gfx.miscellaneous >> 2) & 3) { case 0: + vgapages.map_base=VGA_PAGE_A0; + MEM_SetPageHandler(VGA_PAGE_A0,32,range_handler); + break; case 1: - range=VGA_RANGE_A000; + vgapages.map_base=VGA_PAGE_A0; + MEM_SetPageHandler(VGA_PAGE_A0,16,range_handler); + MEM_SetPageHandler(VGA_PAGE_B0,16,&vgaph.hram); break; case 2: - range=VGA_RANGE_B000; +range_b000: + vgapages.map_base=VGA_PAGE_B0; + MEM_SetPageHandler(VGA_PAGE_B0,8,range_handler); + MEM_SetPageHandler(VGA_PAGE_A0,16,&vgaph.hram); + MEM_SetPageHandler(VGA_PAGE_B8,8,&vgaph.hram); break; case 3: - range=VGA_RANGE_B800; +range_b800: + vgapages.map_base=VGA_PAGE_B8; + MEM_SetPageHandler(VGA_PAGE_B8,8,range_handler); + MEM_SetPageHandler(VGA_PAGE_A0,16,&vgaph.hram); + MEM_SetPageHandler(VGA_PAGE_B0,8,&vgaph.hram); break; } - MEM_SetupVGA(range,where); + PAGING_ClearTLB(); } bool lfb_update; @@ -209,7 +350,4 @@ void VGA_StartUpdateLFB(void) { void VGA_SetupMemory() { memset((void *)&vga.mem,0,512*1024*4); - /* Setup linear window to some initial value */ - vga.s3.la_window=0xc000; - VGA_DoUpdateLFB(); } diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index 6bb0188..650d56a 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include "inout.h" #include "pic.h" #include "vga.h" +#include "../ints/int10.h" static Bit8u flip=0; @@ -28,14 +29,24 @@ Bit8u read_p3d4(Bit32u port); void write_p3d5(Bit32u port,Bit8u val); Bit8u read_p3d5(Bit32u port); +static void write_p3d9(Bit32u port,Bit8u val); + static Bit8u read_p3da(Bit32u port) { vga.internal.attrindex=false; if (vga.config.retrace) { - return 9; + switch (vga.mode) { + case M_HERC: + return 0x81; + case M_TEXT2: + if (machine==MCH_HERC) return 0x81; + if (machine==MCH_AUTO) return 0x89; + default: + return 9; + } } flip++; - if (flip>10) flip=0; - if (flip>5) return 1; + if (flip>20) flip=0; + if (flip>10) return 1; return 0; /* 0 Either Vertical or Horizontal Retrace active if set @@ -43,16 +54,38 @@ static Bit8u read_p3da(Bit32u port) { */ } - static void write_p3d8(Bit32u port,Bit8u val) { - switch (vga.mode) { - case M_CGA4: - + /* Check if someone changes the blinking/hi intensity bit */ + switch (machine) { + case MCH_AUTO: + VGA_SetBlinking((val & 0x20)); + switch (vga.mode) { + case M_CGA2: + case M_CGA4: + case M_CGA16: + goto m_cga; + } + break; + case MCH_CGA: + VGA_SetBlinking((val & 0x20)); +m_cga: + if (val & 0x2) { + if (val & 0x10) { + if (val & 0x8) { + VGA_SetMode(M_CGA16); //Video burst 16 160x200 color mode + } else { + VGA_SetMode(M_CGA2); + } + } else VGA_SetMode(M_CGA4); + write_p3d9(0x3d9,vga.cga.color_select); //Setup the correct palette + } else { + VGA_SetMode(M_TEXT16); + } + vga.cga.mode_control=val; break; default: - break; + LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to 3d8 in mode %d",val,vga.mode); } - LOG(LOG_VGAMISC,LOG_NORMAL)("Write %2X to 3d8",val); /* 3 Vertical Sync Select. If set Vertical Sync to the monitor is the logical OR of the vertical sync and the vertical display enable. @@ -60,50 +93,91 @@ static void write_p3d8(Bit32u port,Bit8u val) { } static void write_p3d9(Bit32u port,Bit8u val) { + Bitu i; + vga.cga.color_select=val; switch (vga.mode) { case M_CGA2: - vga.cga.color_select=val; /* changes attribute 1 */ - vga.attr.palette[1]=(val & 7) + ((val & 8) ? 0x38 : 0); - VGA_DAC_CombineColor(1,vga.attr.palette[0]); + VGA_ATTR_SetPalette(0,0); + VGA_ATTR_SetPalette(1,val & 0xf); break; case M_CGA4: - vga.cga.color_select=val; - /* changes attribute 0 */ - VGA_ATTR_SetPalette(0,(val & 7) + ((val & 8) ? 0x38 : 0)); - if (val & 0x020) { - VGA_ATTR_SetPalette(1,0x13); - VGA_ATTR_SetPalette(2,0x15); - VGA_ATTR_SetPalette(3,0x17); - } else { - VGA_ATTR_SetPalette(1,0x02); - VGA_ATTR_SetPalette(2,0x04); - VGA_ATTR_SetPalette(3,0x06); + /* changes attribute 0 */ + { + VGA_ATTR_SetPalette(0,(val & 0xf)); + Bit8u pal_base=(val & 0x10) ? 0x08 : 0; + if (val & 0x020) { + VGA_ATTR_SetPalette(1,0x03+pal_base); + VGA_ATTR_SetPalette(2,0x05+pal_base); + VGA_ATTR_SetPalette(3,0x07+pal_base); + } else { + VGA_ATTR_SetPalette(1,0x02+pal_base); + VGA_ATTR_SetPalette(2,0x04+pal_base); + VGA_ATTR_SetPalette(3,0x06+pal_base); + } } break; - /* Color Select register - Text modes: 320x200 modes: 640x200 mode: - 0 Blue border Blue background Blue ForeGround - 1 Green border Green background Green ForeGround - 2 Red border Red background Red ForeGround - 3 Bright border Bright background Bright ForeGround - 4 Backgr. color Alt. intens. colors Alt. intens colors - 5 No func. Selects palette - Palette 0 is Green, red and brown, - Palette 1 is Cyan, magenta and white. - */ + case M_CGA16: + for(i=0;i<0x10;i++) VGA_ATTR_SetPalette(i,i); + break; + case M_TEXT16: + /* Assume a normal text palette has been set */ +// VGA_ATTR_SetPalette(0,(val & 0x8) ? ((val & 7)+32) : (val &7)); + break; default: LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode); } } -static void write_p3df(Bit32u port,Bit8u val) { +static void write_p3da(Bit32u port,Bit8u val) { + if (machine==MCH_TANDY) goto tandy_3da; switch (vga.mode) { case M_TANDY16: +tandy_3da: + vga.tandy.reg_index=val; + break; + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode); + break; + + } +} + + +static void write_p3de(Bit32u port,Bit8u val) { + if (machine==MCH_TANDY) goto tandy_3de; + switch (vga.mode) { + case M_TANDY16: +tandy_3de: + switch (vga.tandy.reg_index) { + case 0x2: /* Border color */ + vga.tandy.border_color=val; + break; + /* palette colors */ + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + VGA_ATTR_SetPalette(vga.tandy.reg_index-0x10,val & 0xf); + break; + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to tandy reg %X",val,vga.tandy.reg_index); + } + break; + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode); + break; + } +} + +static void write_p3df(Bit32u port,Bit8u val) { + if (machine==MCH_TANDY) goto tandy_3df; + switch (vga.mode) { + case M_TANDY16: +tandy_3df: vga.tandy.disp_bank=val & ((val & 0x80) ? 0x6 : 0x7); vga.tandy.mem_bank=(val >> 3) & ((val & 0x80) ? 0x6 : 0x7); VGA_SetupHandlers(); - break; /* 0-2 Identifies the page of main memory being displayed in units of 16K. @@ -122,36 +196,44 @@ static void write_p3df(Bit32u port,Bit8u val) { } static Bit8u read_p3d9(Bit32u port) { - switch (vga.mode) { - case M_CGA2: - case M_CGA4: + switch (machine) { + case MCH_AUTO: + case MCH_CGA: + case MCH_TANDY: return vga.cga.color_select; default: return 0xff; - } + }; } static void write_p3c2(Bit32u port,Bit8u val) { vga.misc_output=val; + if (val & 0x1) { IO_RegisterWriteHandler(0x3d4,write_p3d4,"VGA:CRTC Index Select"); IO_RegisterReadHandler(0x3d4,read_p3d4,"VGA:CRTC Index Select"); IO_RegisterWriteHandler(0x3d5,write_p3d5,"VGA:CRTC Data Register"); IO_RegisterReadHandler(0x3d5,read_p3d5,"VGA:CRTC Data Register"); + IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1"); + IO_FreeWriteHandler(0x3b4); IO_FreeReadHandler(0x3b4); IO_FreeWriteHandler(0x3b5); IO_FreeReadHandler(0x3b5); + IO_FreeReadHandler(0x3ba); } else { IO_RegisterWriteHandler(0x3b4,write_p3d4,"VGA:CRTC Index Select"); IO_RegisterReadHandler(0x3b4,read_p3d4,"VGA:CRTC Index Select"); IO_RegisterWriteHandler(0x3b5,write_p3d5,"VGA:CRTC Data Register"); IO_RegisterReadHandler(0x3b5,read_p3d5,"VGA:CRTC Data Register"); + IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1"); + IO_FreeWriteHandler(0x3d4); IO_FreeReadHandler(0x3d4); IO_FreeWriteHandler(0x3d5); IO_FreeReadHandler(0x3d5); + IO_FreeReadHandler(0x3da); } /* 0 If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base Address=3Bxh. @@ -171,21 +253,68 @@ static Bit8u read_p3cc(Bit32u port) { return vga.misc_output; } + +static void write_hercules(Bit32u port,Bit8u val) { + switch (port) { + case 0x3b8: + vga.herc.mode_control=(vga.herc.mode_control & ~0x7d) | (val&0x7d); + if ((vga.herc.enable_bits & 1) && ((vga.herc.mode_control ^ val)&0x2)) { + vga.herc.mode_control^=0x2; + if (vga.mode != M_HERC || vga.mode != M_TEXT2) { + VGA_ATTR_SetPalette(0,0x00); + VGA_ATTR_SetPalette(1,0x07); + + /* Force 0x3b4/5 registers */ + if (vga.misc_output & 1) write_p3c2(0,vga.misc_output & ~1); + } + if (val & 0x2) { + if (vga.mode != M_HERC) VGA_SetMode(M_HERC); + } else { + if (vga.mode != M_TEXT2) VGA_SetMode(M_TEXT2); + } + } + if ((vga.herc.enable_bits & 0x2) && ((vga.herc.mode_control ^ val)&0x80)) { + vga.herc.mode_control^=0x80; + VGA_SetupHandlers(); + } + break; + case 0x3bf: + vga.herc.enable_bits=val; + break; + default: + LOG_MSG("write %x to Herc port %x",val,port); + } +} + +static Bit8u read_hercules(Bit32u port) { + switch (port) { + case 0x3b8: + default: + LOG_MSG("read from Herc port %x",port); + } + return 0; +} + + + + void VGA_SetupMisc(void) { - IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1"); - IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1"); - + vga.herc.enable_bits=0; IO_RegisterWriteHandler(0x3d8,write_p3d8,"VGA Feature Control Register"); - - IO_RegisterWriteHandler(0x3d9,write_p3d9,"CGA Color Select Register"); IO_RegisterReadHandler(0x3d9,read_p3d9,"CGA Color Select Register"); - - - IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output"); + IO_RegisterWriteHandler(0x3c2,write_p3c2,"VGA Misc Output"); IO_RegisterReadHandler(0x3cc,read_p3cc,"VGA Misc Output"); - IO_RegisterWriteHandler(0x3df,write_p3df,"PCJR Setting"); + + if (machine==MCH_HERC || machine==MCH_AUTO) { + vga.herc.mode_control=0x8; + IO_RegisterWriteHandler(0x3b8,write_hercules,"Hercules"); + IO_RegisterWriteHandler(0x3bf,write_hercules,"Hercules"); + } + IO_RegisterWriteHandler(0x3de,write_p3de,"PCJR Reg Write"); + IO_RegisterWriteHandler(0x3df,write_p3df,"PCJR Bank Select"); + IO_RegisterWriteHandler(0x3da,write_p3da,"PCJR Reg Select"); } diff --git a/src/hardware/vga_seq.cpp b/src/hardware/vga_seq.cpp index 4433f76..1ab8cc1 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/ints/Makefile.in b/src/ints/Makefile.in index 6e1fd36..a532973 100644 --- a/src/ints/Makefile.in +++ b/src/ints/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -345,7 +345,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -365,7 +365,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -390,7 +389,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index b1e4fef..76c68ee 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,27 +16,30 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: bios.cpp,v 1.22 2003/09/30 13:49:34 finsterr Exp $ */ +/* $Id: bios.cpp,v 1.28 2004/01/26 14:08:16 qbix79 Exp $ */ #include #include "dosbox.h" #include "bios.h" #include "regs.h" +#include "cpu.h" #include "callback.h" #include "inout.h" #include "mem.h" #include "pic.h" #include "joystick.h" +#include "dos_inc.h" static Bitu call_int1a,call_int11,call_int8,call_int17,call_int12,call_int15,call_int1c; static Bitu call_int1,call_int70; +static Bit16u size_extended; static Bitu INT70_Handler(void) { /* Acknowledge irq with cmos */ IO_Write(0x70,0xc); IO_Read(0x71); if (mem_readb(BIOS_WAIT_FLAG_ACTIVE)) { - Bits count=mem_readd(BIOS_WAIT_FLAG_COUNT); + Bit32u count=mem_readd(BIOS_WAIT_FLAG_COUNT); if (count>997) { mem_writed(BIOS_WAIT_FLAG_COUNT,count-997); } else { @@ -78,10 +81,15 @@ static Bitu INT1A_Handler(void) { CALLBACK_SCF(false); break; case 0x04: /* GET REAL-TIME ClOCK DATA (AT,XT286,PS) */ - reg_dx=reg_cx=0; - CALLBACK_SCF(false); - LOG(LOG_BIOS,LOG_ERROR)("INT1A:04:Faked RTC get date call"); - break; + reg_dx=0; + reg_cx=0x2003; + CALLBACK_SCF(false); + LOG(LOG_BIOS,LOG_ERROR)("INT1A:04:Faked RTC get date call"); + break; +// reg_dx=reg_cx=0; +// CALLBACK_SCF(false); +// LOG(LOG_BIOS,LOG_ERROR)("INT1A:04:Faked RTC get date call"); +// break; case 0x80: /* Pcjr Setup Sound Multiplexer */ LOG(LOG_BIOS,LOG_ERROR)("INT1A:80:Setup tandy sound multiplexer to %d",reg_al); break; @@ -166,20 +174,37 @@ static Bitu INT17_Handler(void) { static Bitu INT15_Handler(void) { + static Bitu biosConfigSeg=0; + switch (reg_ah) { case 0x06: LOG(LOG_BIOS,LOG_NORMAL)("INT15 Unkown Function 6"); break; case 0xC0: /* Get Configuration*/ - LOG(LOG_BIOS,LOG_ERROR)("Request BIOS Configuration INT 15 C0"); - CALLBACK_SCF(true); - break; + { + if (biosConfigSeg==0) biosConfigSeg = DOS_GetMemory(1); //We have 16 bytes + PhysPt data = PhysMake(biosConfigSeg,0); + mem_writew(data,8); // 3 Bytes following + mem_writeb(data+2,0xFC); // Model ID + mem_writeb(data+3,0x00); // Submodel ID + mem_writeb(data+4,0x01); // Bios Revision + mem_writeb(data+5,(1<<6)|(1<<5)|(1<<4));// Feature Byte 1 + mem_writeb(data+6,(1<<6)); // Feature Byte 2 + mem_writeb(data+7,0); // Feature Byte 3 + mem_writeb(data+8,0); // Feature Byte 4 + mem_writeb(data+9,0); // Feature Byte 4 + CPU_SetSegGeneral(es,biosConfigSeg); + reg_bx = 0; + reg_ah = 0; + CALLBACK_SCF(false); + }; break; case 0x4f: /* BIOS - Keyboard intercept */ /* Carry should be set but let's just set it just in case */ CALLBACK_SCF(true); break; case 0x83: /* BIOS - SET EVENT WAIT INTERVAL */ { + if(reg_al == 0x01) LOG(LOG_BIOS,LOG_WARN)("Bios set event interval cancelled: not handled"); if (mem_readb(BIOS_WAIT_FLAG_ACTIVE)) { reg_ah=0x80; CALLBACK_SCF(true); @@ -243,13 +268,28 @@ static Bitu INT15_Handler(void) { break; } case 0x88: /* SYSTEM - GET EXTENDED MEMORY SIZE (286+) */ - IO_Write(0x70,0x30); - reg_al=IO_Read(0x71); - IO_Write(0x70,0x31); - reg_ah=IO_Read(0x71); + reg_ax=size_extended; LOG(LOG_BIOS,LOG_NORMAL)("INT15:Function 0x88 Remaining %04X kb",reg_ax); CALLBACK_SCF(false); break; + case 0x89: /* SYSTEM - SWITCH TO PROTECTED MODE */ + { + IO_Write(0x20,0x10);IO_Write(0x21,reg_bh);IO_Write(0x21,0); + IO_Write(0xA0,0x10);IO_Write(0xA1,reg_bl);IO_Write(0xA1,0); + MEM_A20_Enable(true); + PhysPt table=SegPhys(es)+reg_si; + CPU_LGDT(mem_readw(table+0x8),mem_readd(table+0x8+0x2) & 0xFFFFFF); + CPU_LIDT(mem_readw(table+0x10),mem_readd(table+0x10+0x2) & 0xFFFFFF); + CPU_SET_CRX(0,CPU_GET_CRX(0)|1); + CPU_SetSegGeneral(ds,0x18); + CPU_SetSegGeneral(es,0x20); + CPU_SetSegGeneral(ss,0x28); + reg_sp+=6; //Clear stack of interrupt frame + CPU_SetFlags(0,FMASK_ALL); + reg_ax=0; + CPU_JMP(false,0x30,reg_cx); + } + break; case 0x90: /* OS HOOK - DEVICE BUSY */ CALLBACK_SCF(false); reg_ah=0; @@ -258,6 +298,10 @@ static Bitu INT15_Handler(void) { CALLBACK_SCF(false); reg_ah=0; break; + case 0xc3: /* set carry flag so BorlandRTM doesn't assume a VECTRA/PS2 */ + reg_ah=0x86; + CALLBACK_SCF(true); + break; case 0xc2: /* BIOS PS2 Pointing Device Support */ case 0xc4: /* BIOS POS Programma option Select */ /* @@ -284,6 +328,10 @@ static Bitu INT1_Single_Step(void) { return CBRET_NONE; } +void BIOS_ZeroExtendedSize(void) { + size_extended=0; +} + void BIOS_SetupKeyboard(void); void BIOS_SetupDisks(void); @@ -353,6 +401,12 @@ void BIOS_Init(Section* sec) { #else mem_writew(BIOS_CONFIGURATION,0xc821); //1 Floppy,FPU,2 serial, 1 parallel #endif + /* Setup extended memory size */ + IO_Write(0x70,0x30); + size_extended=IO_Read(0x71); + IO_Write(0x70,0x31); + size_extended|=(IO_Read(0x71) << 8); + } diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index afbe92c..3e7a38f 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/ints/bios_keyboard.cpp b/src/ints/bios_keyboard.cpp index 80de081..09aa5cd 100644 --- a/src/ints/bios_keyboard.cpp +++ b/src/ints/bios_keyboard.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -207,11 +207,17 @@ static Bitu IRQ1_Handler(void) { KEYBOARD_ReadKey(scancode,ascii,mod); // LOG(0,"Got code %X ascii %C mod %X",scancode,ascii,mod); #endif + Bit16u old_ax=reg_ax; + reg_flags|=1; + reg_ah=0x4f;reg_al=scancode; + CALLBACK_RunRealInt(0x15); + reg_ax=old_ax;Bit8u flags1,flags2,flags3; + if (!(reg_flags&1)) goto irq1_return; //TODO maybe implement the int 0x15 ah=4f scancode lookup hook - Bit8u flags1=mem_readb(BIOS_KEYBOARD_FLAGS1); - Bit8u flags2=mem_readb(BIOS_KEYBOARD_FLAGS2); - Bit8u flags3=mem_readb(BIOS_KEYBOARD_FLAGS3); + flags1=mem_readb(BIOS_KEYBOARD_FLAGS1); + flags2=mem_readb(BIOS_KEYBOARD_FLAGS2); + flags3=mem_readb(BIOS_KEYBOARD_FLAGS3); switch (scancode) { /* First the hard ones */ case 0xe0: /* Extended key */ @@ -284,6 +290,7 @@ irq1_end: mem_writeb(BIOS_KEYBOARD_FLAGS1,flags1); mem_writeb(BIOS_KEYBOARD_FLAGS2,flags2); mem_writeb(BIOS_KEYBOARD_FLAGS3,flags3); +irq1_return: IO_Write(0x20,0x20); #if 0 /* Signal the keyboard for next code */ diff --git a/src/ints/dpmi.cpp b/src/ints/dpmi.cpp index 1f6f869..dbbe45f 100644 --- a/src/ints/dpmi.cpp +++ b/src/ints/dpmi.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,8 @@ #include "setup.h" #include "inout.h" #include "cpu.h" +#include "bios.h" +#include "paging.h" #include "debug.h" @@ -203,12 +205,14 @@ public: Bitu CreateAlias (Bitu selector, Bit16u& alias); void ReloadSegments (Bitu selector); bool SetAccessRights (Bitu selector, SetDescriptor& desc, Bitu rights); + bool SetProtInterrupt (Bitu num, Bitu selector, Bitu offset); // Special Interrupt handlers Bitu Int2fHandler (void); Bitu Int31Handler (void); // Exceptions + Bitu CreateException (void); void CreateException (Bitu num, Bitu errorCode); Bitu ExceptionReturn (void); @@ -219,7 +223,7 @@ public: // Real mode reflection callbacks void PrepareReflectToReal (Bitu num); - Bitu CallRealIRETFrame (void); + Bitu CallRealIRETFrame (bool callAsInt); Bitu CallRealIRETFrameReturn (void); Bitu SimulateInt (void); Bitu SimulateIntReturn (void); @@ -293,7 +297,8 @@ private: bool bit32; Bitu psp; } client; - Bit16u mem_handle; /* Handle for GDT/IDT */ + Bit32s mem_handle; /* Handle for GDT/IDT */ + Bitu idtBase,idtLimit; struct { PhysPt base; Bitu limit; @@ -372,6 +377,14 @@ struct { // DPMI static functions // ************************************************ +#define SWITCH_TO_REALMODE CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); \ + CPU_SIDT(dpmi.idtLimit,dpmi.idtBase); \ + CPU_LIDT(256*4,0); + +#define SWITCH_TO_PROTMODE CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); \ + CPU_LIDT(dpmi.idtLimit,dpmi.idtBase); + + static DPMI* activeDPMI = 0; static Bit32u originalIntTable[256]; @@ -548,7 +561,7 @@ void DPMI::CopyRegistersToBuffer(PhysPt data) mem_writed(data+0x14, reg_edx); mem_writed(data+0x18, reg_ecx); mem_writed(data+0x1C, reg_eax); - mem_writew(data+0x20, flags.word); + mem_writew(data+0x20, reg_flags); mem_writew(data+0x22, SegValue(es)); mem_writew(data+0x24, SegValue(ds)); mem_writew(data+0x26, SegValue(fs)); @@ -696,23 +709,42 @@ void DPMI::ReloadSegments(Bitu selector) if (SegValue(ss)==selector) CPU_SetSegGeneral(ss,selector); }; +Bitu DPMI::CreateException(void) +{ + // Division by Zero + CreateException(0,0); + return CBRET_NONE; +}; + void DPMI::CreateException(Bitu num, Bitu errorCode) { + // Assuming Stack looks like a int has occured + Bitu stack_eip,stack_cs,stack_flags; if (dpmi.client.bit32) { + // Clean up stack + stack_eip = CPU_Pop32(); + stack_cs = CPU_Pop32(); + stack_flags = CPU_Pop32(); + // Push values for exception handler CPU_Push32(SegValue(ss)); CPU_Push32(reg_esp); - CPU_Push32(flags.word); - CPU_Push32(SegValue(cs)); - CPU_Push32(reg_eip-2); // FIXME: Fake ! + CPU_Push32(stack_flags); + CPU_Push32(stack_cs); + CPU_Push32(stack_eip); CPU_Push32(errorCode); CPU_Push32(GDT_PROTCODE); // return cs CPU_Push32(DPMI_CB_EXCEPTIONRETURN_OFFSET); // return eip } else { + // Clean up stack + stack_eip = CPU_Pop16(); + stack_cs = CPU_Pop16(); + stack_flags = CPU_Pop16(); + // Push values for exception handler CPU_Push16(SegValue(ss)); CPU_Push16(reg_sp); - CPU_Push16(flags.word); - CPU_Push16(SegValue(cs)); - CPU_Push16(reg_ip-2); // FIXME: Fake ! + CPU_Push16(stack_flags); + CPU_Push16(stack_cs); + CPU_Push16(stack_eip); CPU_Push16(errorCode); CPU_Push16(GDT_PROTCODE); // return cs CPU_Push16(DPMI_CB_EXCEPTIONRETURN_OFFSET); // return eip @@ -812,7 +844,7 @@ Bitu DPMI::RealModeCallback(void) desc.Save (dpmi.ldt.base+(dpmi.realStackSelector[dpmi.protStackCurrent] & ~7)); } else E_Exit("DPMI: RealmodeCB: Could not provide real mode stack descriptor."); /* Switch to protected mode */ - CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + SWITCH_TO_PROTMODE // Setup dataSelector Descriptor data; Bitu dataSelector; @@ -833,7 +865,7 @@ Bitu DPMI::RealModeCallback(void) CPU_SetSegGeneral(ss,dpmi.protStackSelector[dpmi.protStackCurrent++]); reg_esp = DPMI_PROTMODE_STACKSIZE; // prepare stack for iret - if (dpmi.client.bit32) CPU_Push32(flags.word); else CPU_Push16(flags.word); + if (dpmi.client.bit32) CPU_Push32(reg_flags); else CPU_Push16(reg_flags); // Setup cs:ip to return to DPMI_ReturnFromRealModeCallback CPU_SetSegGeneral(cs,GDT_CODE); reg_eip = RealOff(CALLBACK_RealPointer(callback.rmCallbackReturn)); @@ -841,7 +873,7 @@ Bitu DPMI::RealModeCallback(void) SetVirtualIntFlag(false); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); - CPU_Push32(flags.word); + CPU_Push32(reg_flags); CPU_CALL(dpmi.client.bit32,dpmi.rmCallback[num].codeSelector,dpmi.rmCallback[num].codeOffset); return 0; }; @@ -858,7 +890,7 @@ Bitu DPMI::RealModeCallbackReturn(void) PhysPt data = PhysPt(SegPhys(es)+reg_edi); DPMI_LOG("DPMI: CB: Reading RegData at = %04X:%04X",SegValue(es),reg_edi); /* Swtich to real mode */ - CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + SWITCH_TO_REALMODE dpmi.protStackCurrent--; // Restore Registers LoadRegistersFromBuffer(data); @@ -873,7 +905,7 @@ Bitu DPMI::RealModeCallbackReturn(void) static Bitu count = 0; -Bitu DPMI::CallRealIRETFrame(void) +Bitu DPMI::CallRealIRETFrame(bool callAsInt) { Bitu calledIP = mem_readd(SegPhys(ss)+reg_esp); Bitu calledCS = mem_readd(SegPhys(ss)+reg_esp+4); @@ -888,11 +920,11 @@ Bitu DPMI::CallRealIRETFrame(void) LoadRegistersFromBuffer(data); PushStack(data); /* Switch to real mode */ - CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + SWITCH_TO_REALMODE // Provide Stack ProvideRealModeStack(prStack,toCopy); // Push flags - CPU_Push16(flags.word); + if (callAsInt) CPU_Push16(reg_flags); // Setup IP Bitu newCS = mem_readw(data+0x2C); Bitu newIP = mem_readw(data+0x2A); @@ -912,7 +944,7 @@ Bitu DPMI::CallRealIRETFrameReturn(void) // returning from realmode func DPMI_LOG("DPMI: LEAVE REAL PROC IRETF %d",count); /* Switch to protected mode */ - CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + SWITCH_TO_PROTMODE // Save registers into real mode structure CopyRegistersToBuffer(PopStack()); // Restore changed Resgisters @@ -940,7 +972,7 @@ Bitu DPMI::SimulateInt(void) LoadRegistersFromBuffer(data); PushStack(data); /* Switch to real mode */ - CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + SWITCH_TO_REALMODE // Provide Stack ProvideRealModeStack(prStack,toCopy); // prepare for return @@ -948,8 +980,8 @@ Bitu DPMI::SimulateInt(void) reg_ip = RealOff(CALLBACK_RealPointer(callback.simintReturn)); // Push flags from structure on stack DPMI_LOG("DPMI: SimInt1: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); - flags.word = mem_readw(data+0x20); - Interrupt(num); + reg_flags = mem_readw(data+0x20); + CPU_SW_Interrupt(num,0); DPMI_LOG("DPMI: SimInt2: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); return 0; }; @@ -962,7 +994,7 @@ Bitu DPMI::SimulateIntReturn(void) UpdateRealModeStack(); /* Switch to protected mode */ - CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + SWITCH_TO_PROTMODE // Save registers into real mode structure CopyRegistersToBuffer(PopStack()); // Restore changed Resgisters @@ -986,7 +1018,7 @@ void DPMI::PrepareReflectToReal(Bitu num) PushStack(reg_eip); PushStack(SegValue(cs)); /* Swtich to real mode */ - CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + SWITCH_TO_REALMODE // Setup cs:ip to return to intreturn Bitu retcs = RealSeg(CALLBACK_RealPointer(callback.ptorintReturn)); Bitu retip = RealOff(CALLBACK_RealPointer(callback.ptorintReturn)); @@ -1010,8 +1042,8 @@ Bitu DPMI::ptorHandler(void) // if (num==0x0F) DPMI_LOG("DPMI: INT %02X %04X called.",num,reg_ax); // Prepare flags for real int - // CPU_SetFlagsw(flags.word & 0x3ED5); // 0011111011010101b - Interrupt(num); + // CPU_SetFlagsw(reg_flags & 0x3ED5); // 0011111011010101b + CPU_SW_Interrupt(num,0); return 0; } @@ -1020,7 +1052,7 @@ Bitu DPMI::ptorHandlerReturn(void) { UpdateRealModeStack(); /* Switch to protected mode */ - CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + SWITCH_TO_PROTMODE // Restore Registers Bitu newcs = PopStack(); reg_eip = PopStack(); @@ -1037,12 +1069,12 @@ Bitu DPMI::ptorHandlerReturn(void) } // Change flags on stack to reflect possible results from ints if (dpmi.client.bit32) { - Bit32u oldFlags = mem_readd(SegPhys(ss)+reg_esp+8) & ~FLAG_MASK;// leave only flags that cannot be changed by int - Bit32u userFlags = flags.word & FLAG_MASK; // Mask out illegal flags not to change by int (0011111011010101b) + Bit32u oldFlags = mem_readd(SegPhys(ss)+reg_esp+8) & ~FMASK_TEST; // leave only flags that cannot be changed by int + Bit32u userFlags = reg_flags & FMASK_NORMAL; // Mask out illegal flags not to change by int (0011111011010101b) mem_writed(SegPhys(ss)+reg_esp+8,oldFlags|userFlags); } else { - Bit16u oldFlags = mem_readw(SegPhys(ss)+reg_sp+4) & ~FLAG_MASK; // leave only flags that cannot be changed by int - Bit16u userFlags = flags.word & FLAG_MASK; // Mask out illegal flags not to change by int (0011111011010101b) + Bit16u oldFlags = mem_readw(SegPhys(ss)+reg_sp+4) & ~FMASK_TEST; // leave only flags that cannot be changed by int + Bit16u userFlags = reg_flags & FMASK_NORMAL; // Mask out illegal flags not to change by int (0011111011010101b) mem_writew(SegPhys(ss)+reg_sp+4,oldFlags|userFlags); }; SetVirtualIntFlag(true); @@ -1065,7 +1097,7 @@ Bitu DPMI::Int21Handler(void) PushStack(SegValue(cs)); /* Swtich to real mode */ - CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + SWITCH_TO_REALMODE // Setup cs:ip to return to intreturn SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.int21Return))); reg_ip = RealOff(CALLBACK_RealPointer(callback.int21Return)); @@ -1074,7 +1106,7 @@ Bitu DPMI::Int21Handler(void) reg_esp = rm_sp; // Call realmode interrupt DPMI_LOG("DPMI: INT 21 %04X called.",reg_ax); - Interrupt(0x21); + CPU_SW_Interrupt(0x21,0); if (reg_ah==0x4C) { // Shut doen dpmi and restore previous one delete this; @@ -1087,7 +1119,7 @@ Bitu DPMI::Int21HandlerReturn(void) { UpdateRealModeStack(); /* Switch to protected mode */ - CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + SWITCH_TO_PROTMODE // Restore Registers Bitu newcs = PopStack(); CPU_SetSegGeneral(es,PopStack()); @@ -1095,7 +1127,7 @@ Bitu DPMI::Int21HandlerReturn(void) reg_esp = PopStack(); CPU_SetSegGeneral(ss,PopStack()); // Set carry flag - DPMI_CALLBACK_SCF(flags.word & 1); + DPMI_CALLBACK_SCF(reg_flags & 1); DPMI_LOG("DPMI: INT 21 RETURN"); SetVirtualIntFlag(true); CPU_JMP(dpmi.client.bit32,newcs,reg_eip); @@ -1120,7 +1152,7 @@ Bitu DPMI::HWIntDefaultHandler() // originalroutine aufrufen dpmi.rmCallback[index].stop = false; PrepareReflectToReal(num); - CPU_Push16(flags.word); + CPU_Push16(reg_flags); SetVirtualIntFlag(false); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); @@ -1145,7 +1177,7 @@ Bitu DPMI::HWIntDefaultHandler() SetVirtualIntFlag(false); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); - CPU_Push16(flags.word); + CPU_Push16(reg_flags); CPU_CALL(false,RealSeg(vec),RealOff(vec)); } } else { @@ -1155,7 +1187,7 @@ Bitu DPMI::HWIntDefaultHandler() if (dpmi.rmCallback[index].stop) { dpmi.rmCallback[index].stop = false; PrepareReflectToReal(num); - CPU_Push16(flags.word); + CPU_Push16(reg_flags); SetVirtualIntFlag(false); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); @@ -1172,7 +1204,7 @@ Bitu DPMI::HWIntDefaultHandler() } else { // kein spezieller Protmode handler - Rufe originalroutine auf PrepareReflectToReal(num); - CPU_Push16(flags.word); + CPU_Push16(reg_flags); SetVirtualIntFlag(false); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); @@ -1202,7 +1234,7 @@ void DPMI::SaveRegisterState(Bitu num) save_edi[num] = reg_edi; save_ebp[num] = reg_ebp; save_esp[num] = reg_esp; - save_fl [num] = flags.word; + save_fl [num] = reg_flags; }; void DPMI::LoadRegisterState(Bitu num) @@ -1217,7 +1249,7 @@ void DPMI::LoadRegisterState(Bitu num) reg_edx = save_edx[num]; reg_esi = save_esi[num]; reg_edi = save_edi[num]; - flags.word = save_fl [num]; + reg_flags = save_fl [num]; }; Bitu DPMI::EnterProtMode(void) { @@ -1226,7 +1258,7 @@ Bitu DPMI::EnterProtMode(void) { SaveRegisterState(0); /* Switch to protected mode */ - CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + SWITCH_TO_PROTMODE CPU_SetSegGeneral(ds,reg_ax); CPU_SetSegGeneral(es,reg_cx); @@ -1254,7 +1286,7 @@ Bitu DPMI::EnterRealMode(void) { SaveRegisterState(1); /* Swtich to real mode */ - CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + SWITCH_TO_REALMODE // (E)BP will be preserved across the mode switch call so it can be used as a pointer. // TODO: If interrupts are disabled when the mode switch procedure is invoked, // they will not be re-enabled by the DPMI host (even temporarily). @@ -1485,8 +1517,8 @@ Bitu DPMI::Int31Handler(void) SetDescriptor desc; if (cpu.gdt.GetDescriptor(reg_bx,desc)) { DPMI_LOG("DPMI: 0006: Get Base %04X : B:%08X",reg_bx,desc.GetBase()); - reg_cx = desc.GetBase()>>16; - reg_dx = desc.GetBase()&0xFFFF; + reg_cx = (Bit16u)(desc.GetBase()>>16); + reg_dx = (Bit16u)(desc.GetBase()&0xFFFF); DPMI_CALLBACK_SCF(false); } else { DPMI_LOG_ERROR("DPMI: 0006: Invalid Selector: %04X",reg_bx); @@ -1516,7 +1548,7 @@ Bitu DPMI::Int31Handler(void) if ((!dpmi.client.bit32) && (reg_cx!=0)) { // 16-bit DPMI implementations can not set segment limits greater // than 0FFFFh (64K) so CX must be zero when calling - DPMI_LOG_ERROR("DPMI: 0008: Set Segment Limit invalid: %04X ",reg_bx); + DPMI_LOG_ERROR("DPMI: 0008: Set Segment Limit invalid: %04X (%04X%04X)",reg_bx,reg_cx,reg_dx); reg_ax = DPMI_ERROR_INVALID_VALUE; DPMI_CALLBACK_SCF(true); } else if (cpu.gdt.GetDescriptor(reg_bx,desc)) { @@ -1584,6 +1616,17 @@ Bitu DPMI::Int31Handler(void) DPMI_CALLBACK_SCF(true); break; }; + // TEMP : Test +/* if (!dpmi.client.bit32) { + if (desc.GetLimit()>0xFFFF) { + DPMI_LOG_ERROR("DPMI: 000C: Set Limit %04X : failure (%08X)",reg_bx,desc.GetLimit()); + desc.SetLimit(0xFFFF); + } + if (desc.GetBase ()>0xFFFFFF) { + DPMI_LOG_ERROR("DPMI: 000C: Set Base %04X : failure (%08X)",reg_bx,desc.GetBase()); + desc.SetBase(desc.GetBase() % 0xFFFFFF); + } + }*/ desc.Save(dpmi.ldt.base+(reg_bx & ~7)); ReloadSegments(reg_bx); DPMI_LOG("DPMI: 000B: Set Descriptor %04X : B:%08X L:%08X : P %01X",reg_bx,desc.GetBase(),desc.GetLimit(),desc.saved.seg.p); @@ -1719,8 +1762,6 @@ Bitu DPMI::Int31Handler(void) DPMI_CALLBACK_SCF(true); }; break; - DPMI_CALLBACK_SCF(false); - break; case 0x0204:{// Get Protected Mode Interrupt Vector SetDescriptor gate; if (dpmi.pharlap) { @@ -1738,27 +1779,19 @@ Bitu DPMI::Int31Handler(void) DPMI_LOG("DPMI: 0204: Get Prot Int Vector %02X (%04X:%08X)",reg_bl,reg_cx,reg_edx); DPMI_CALLBACK_SCF(false); }; break; - case 0x0205:{// Set Protected Mode Interrupt Vector - SetDescriptor gate; - gate.Clear(); - gate.saved.seg.p=1; - gate.SetSelector(reg_cx); - gate.SetOffset(Mask(reg_edx)); - gate.SetType(dpmi.client.bit32?DESC_386_INT_GATE:DESC_286_INT_GATE); - gate.saved.seg.dpl = DPMI_DPL; - gate.Save(dpmi.idt.base+reg_bl*8); - if (dpmi.pharlap) { - gate.Save(cpu.idt.GetBase()+reg_bl*8); - DPMI_LOG("DPMI: 0205: Pharlap: Set Prot Int Vector %02X (%04X:%08X)",reg_bl,reg_cx,reg_edx); - } else - DPMI_LOG("DPMI: 0205: Set Prot Int Vector %02X (%04X:%08X)",reg_bl,reg_cx,reg_edx); + case 0x0205:{// Set Protected Mode Interrupt Vector + DPMI_LOG("DPMI: 0205: Set Prot Int Vector %02X (%04X:%08X)",reg_bl,reg_cx,reg_edx); + SetProtInterrupt(reg_bl,reg_cx,reg_edx); DPMI_CALLBACK_SCF(false); }; break; case 0x0300:// Simulate Real Mode Interrupt SimulateInt(); break; + case 0x0301:// Call Real Mode Procedure With RET Frame + CallRealIRETFrame(false); + break; case 0x0302:// Call Real Mode Procedure With IRET Frame - CallRealIRETFrame(); + CallRealIRETFrame(true); break; case 0x0303:{//Allocate Real Mode Callback Address Bitu num = 0; @@ -1886,18 +1919,18 @@ Bitu DPMI::Int31Handler(void) DPMI_LOG("DPMI: 0503: Resize Memory: H:%08X (%d KB)",handle,newSize*4); if (MEM_ReAllocatePages(handle,newSize,true)) { linear = handle * DPMI_PAGE_SIZE; - reg_si = handle>>16; - reg_di = handle&0xFFFF; - reg_bx = linear>>16; - reg_cx = linear&0xFFFF; + reg_si = (Bit16u)(handle>>16); + reg_di = (Bit16u)(handle&0xFFFF); + reg_bx = (Bit16u)(linear>>16); + reg_cx = (Bit16u)(linear&0xFFFF); DPMI_CALLBACK_SCF(false); } else if (AllocateMem(newByte,newHandle,linear)) { // Not possible, try to allocate DPMI_LOG("DPMI: 0503: Reallocated Memory: %d KB",newSize*4); - reg_si = newHandle>>16; - reg_di = newHandle&0xFFFF; - reg_bx = linear>>16; - reg_cx = linear&0xFFFF; + reg_si = (Bit16u)(newHandle>>16); + reg_di = (Bit16u)(newHandle&0xFFFF); + reg_bx = (Bit16u)(linear>>16); + reg_cx = (Bit16u)(linear&0xFFFF); // copy contents Bitu size = MEM_AllocatedPages(handle); if (newSize>16; reg_cx = linear & 0xFFFF; @@ -2127,10 +2162,11 @@ Bitu DPMI::Int2fHandler(void) // Callbacks and Callback-Returns // ********************************************************************* +static Bitu DPMI_Exception(void) { if (activeDPMI) return activeDPMI->CreateException(); return 0;}; static Bitu DPMI_ExceptionReturn(void) { if (activeDPMI) return activeDPMI->ExceptionReturn(); return 0;}; static Bitu DPMI_RealModeCallback(void) { if (activeDPMI) return activeDPMI->RealModeCallback(); return 0;}; static Bitu DPMI_RealModeCallbackReturn(void) { if (activeDPMI) return activeDPMI->RealModeCallbackReturn(); return 0;}; -static Bitu DPMI_CallRealIRETFrame(void) { if (activeDPMI) return activeDPMI->CallRealIRETFrame(); return 0;}; +static Bitu DPMI_CallRealIRETFrame(void) { if (activeDPMI) return activeDPMI->CallRealIRETFrame(true); return 0;}; static Bitu DPMI_CallRealIRETFrameReturn(void) { if (activeDPMI) return activeDPMI->CallRealIRETFrameReturn(); return 0;}; static Bitu DPMI_SimulateInt(void) { if (activeDPMI) return activeDPMI->SimulateInt(); return 0;}; static Bitu DPMI_SimulateIntReturn(void) { if (activeDPMI) return activeDPMI->SimulateIntReturn(); return 0;}; @@ -2153,6 +2189,27 @@ static Bitu DPMI_API_Entry_MSDOS(void) { if (activeDPMI) return activeDPMI->AP // Setup stuff // **************************************************************** +bool DPMI::SetProtInterrupt(Bitu num, Bitu selector, Bitu offset) +{ + // Nobody messes with the div0 vector + if (num==0) return true; + + SetDescriptor gate; + gate.Clear(); + gate.saved.seg.p=1; + gate.SetSelector(selector); + gate.SetOffset (Mask(offset)); + gate.SetType (dpmi.client.bit32?DESC_386_INT_GATE:DESC_286_INT_GATE); + gate.saved.seg.dpl = DPMI_DPL; + gate.Save(dpmi.idt.base+num*8); + // Special Pharlap stuff + if (dpmi.pharlap) { + gate.Save(cpu.idt.GetBase()+num*8); + DPMI_LOG("DPMI: 0205: Pharlap: Set Prot Int Vector %02X (%04X:%08X)",reg_bl,reg_cx,reg_edx); + } + return true; +}; + RealPt DPMI::HookInterrupt(Bitu num, Bitu intHandler) { // Setup realmode hook @@ -2166,11 +2223,7 @@ RealPt DPMI::HookInterrupt(Bitu num, Bitu intHandler) } else E_Exit("DPMI: Couldnt allocate Realmode-Callback for INT %04X",num); // Setup protmode hook func = CALLBACK_RealPointer(intHandler); - SetDescriptor gate; - gate.Load (dpmi.idt.base+num*8); - gate.SetSelector(GDT_CODE); - gate.SetOffset (RealOff(func)); - gate.Save (dpmi.idt.base+num*8); + SetProtInterrupt(num,GDT_CODE,RealOff(func)); return oldVec; } @@ -2488,33 +2541,34 @@ void DPMI_Init(Section* sec) Section_prop * section=static_cast(sec); if (!section->Get_bool("dpmi")) return; + BIOS_ZeroExtendedSize(); memset(&callback,0,sizeof(callback)); /* setup Real mode Callbacks */ callback.entry=CALLBACK_Allocate(); - CALLBACK_Setup(callback.entry,DPMI_EntryPoint,CB_RETF); + CALLBACK_Setup(callback.entry,DPMI_EntryPoint,CB_RETF,"Entrypoint"); callback.enterpmode=CALLBACK_Allocate(); - CALLBACK_Setup(callback.enterpmode,DPMI_EnterProtMode,CB_RETF); + CALLBACK_Setup(callback.enterpmode,DPMI_EnterProtMode,CB_RETF,"Enter PMode"); callback.realsavestate=CALLBACK_Allocate(); - CALLBACK_Setup(callback.realsavestate,DPMI_RealSaveState,CB_RETF); + CALLBACK_Setup(callback.realsavestate,DPMI_RealSaveState,CB_RETF,"Save RealState"); callback.simint=CALLBACK_Allocate(); - CALLBACK_Setup(callback.simint,DPMI_SimulateInt,CB_IRET); + CALLBACK_Setup(callback.simint,DPMI_SimulateInt,CB_IRET,"Sim INT"); callback.simintReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.simintReturn,DPMI_SimulateIntReturn,CB_IRET); + CALLBACK_Setup(callback.simintReturn,DPMI_SimulateIntReturn,CB_IRET,"Sim INT RET"); callback.rmIntFrame=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmIntFrame,DPMI_CallRealIRETFrame,CB_IRET); + CALLBACK_Setup(callback.rmIntFrame,DPMI_CallRealIRETFrame,CB_IRET,"Call REAL IRET"); callback.rmIntFrameReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmIntFrameReturn,DPMI_CallRealIRETFrameReturn,CB_IRET); + CALLBACK_Setup(callback.rmIntFrameReturn,DPMI_CallRealIRETFrameReturn,CB_IRET,"Call REAL IRET RET"); callback.ptorint=CALLBACK_Allocate(); - CALLBACK_Setup(callback.ptorint,DPMI_ptorHandler,CB_IRET); + CALLBACK_Setup(callback.ptorint,DPMI_ptorHandler,CB_IRET,"INT Handler"); callback.ptorintReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.ptorintReturn,DPMI_ptorHandlerReturn,CB_IRET); + CALLBACK_Setup(callback.ptorintReturn,DPMI_ptorHandlerReturn,CB_IRET,"INT Handler RET"); callback.int21Return=CALLBACK_Allocate(); - CALLBACK_Setup(callback.int21Return,DPMI_Int21HandlerReturn,CB_IRET); + CALLBACK_Setup(callback.int21Return,DPMI_Int21HandlerReturn,CB_IRET,"INT 21 RET"); callback.rmCallbackReturn=CALLBACK_Allocate(); - CALLBACK_Setup(callback.rmCallbackReturn,DPMI_RealModeCallbackReturn,CB_IRET); + CALLBACK_Setup(callback.rmCallbackReturn,DPMI_RealModeCallbackReturn,CB_IRET,"RMCB RET"); callback.int21msdos=CALLBACK_Allocate(); - CALLBACK_Setup(callback.int21msdos,DPMI_API_Int21_MSDOS,CB_IRET); + CALLBACK_Setup(callback.int21msdos,DPMI_API_Int21_MSDOS,CB_IRET,"MSDOS INT 21 API"); /* Setup multiplex */ DOS_AddMultiplexHandler(DPMI_Multiplex); @@ -2633,46 +2687,52 @@ void DPMI::Setup() // Setup Hardware Interrupt handler for (i=0; i #include @@ -92,7 +93,7 @@ struct EMM_Handle { static EMM_Handle emm_handles[EMM_MAX_HANDLES]; static EMM_Mapping emm_mappings[EMM_MAX_PHYS]; -static Bitu call_int67; +static Bitu call_int67,call_vdma; struct MoveRegion { Bit32u bytes; @@ -156,13 +157,21 @@ static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) { /* Mapping it is */ emm_mappings[phys_page].handle=handle; emm_mappings[phys_page].page=log_page; - MEM_MapPagesHandle(EMM_PAGEFRAME4K+phys_page*4,emm_handles[handle].mem,log_page*4,4); + + MemHandle memh=MEM_NextHandleAt(emm_handles[handle].mem,log_page*4);; + for (Bitu i=0;i<4;i++) { + PAGING_MapPage(EMM_PAGEFRAME4K+phys_page*4+i,memh); + memh=MEM_NextHandle(memh); + } + PAGING_ClearTLB(); return EMM_NO_ERROR; } else if (log_page==NULL_PAGE) { /* Unmapping it is */ emm_mappings[phys_page].handle=NULL_HANDLE; emm_mappings[phys_page].page=NULL_PAGE; - MEM_UnmapPages(EMM_PAGEFRAME4K+phys_page*4,4); + for (Bitu i=0;i<4;i++) + PAGING_MapPage(EMM_PAGEFRAME4K+phys_page*4+i,EMM_PAGEFRAME4K+phys_page*4+i); + PAGING_ClearTLB(); return EMM_NO_ERROR; } else { /* Illegal logical page it is */ @@ -436,6 +445,7 @@ static Bit8u MemoryRegion(void) { return EMM_NO_ERROR; } + static Bitu INT67_Handler(void) { Bitu i; switch (reg_ah) { @@ -573,10 +583,28 @@ static Bitu INT67_Handler(void) { return CBRET_NONE; } +static Bitu INT4B_Handler() { + switch (reg_ah) { + case 0x81: + CALLBACK_SCF(true); + reg_ax=0x1; + break; + default: + LOG(LOG_MISC,LOG_WARN)("Unhandled interrupt 4B function %x",reg_ah); + break; + } + return CBRET_NONE; +} void EMS_Init(Section* sec) { + /* Virtual DMA interrupt callback */ + call_vdma=CALLBACK_Allocate(); + CALLBACK_Setup(call_vdma,&INT4B_Handler,CB_IRET); + RealSetVec(0x4b,CALLBACK_RealPointer(call_vdma)); + Section_prop * section=static_cast(sec); if (!section->Get_bool("ems")) return; + BIOS_ZeroExtendedSize(); call_int67=CALLBACK_Allocate(); CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET); /* Register the ems device */ diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp index 4a7d2db..6bcc230 100644 --- a/src/ints/int10.cpp +++ b/src/ints/int10.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,9 @@ #include "video.h" #include "inout.h" #include "int10.h" -#include "../hardware/vga.h" /* Maybe move this thing */ +#include "setup.h" +#include "support.h" +#include "vga.h" Int10Data int10; static Bitu call_10; @@ -70,7 +72,7 @@ static Bitu INT10_Handler(void) { reg_ah=0; break; case 0x05: /* Set Active Page */ - if (reg_al & 0x80) LOG(LOG_INT10,LOG_NORMAL)("Func %x",reg_al); + if (reg_al & 0x80) LOG(LOG_INT10,LOG_NORMAL)("Tandy set CRT/CPU Page Func %x",reg_al); else INT10_SetActivePage(reg_al); break; case 0x06: /* Scroll Up */ @@ -105,7 +107,7 @@ static Bitu INT10_Handler(void) { INT10_GetPixel(reg_cx,reg_dx,reg_bh,®_al); break; case 0x0E: /* Teletype OutPut */ - INT10_TeletypeOutput(reg_al,reg_bl,false); + INT10_TeletypeOutput(reg_al,reg_bl); break; case 0x0F: /* Get videomode */ reg_bh=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); @@ -255,6 +257,7 @@ graphics_chars: } break; case 0x12: /* alternate function select */ + if (machinetwidth*rnew)*(cheight/2)+cleft); + PhysPt src=base+((CurMode->twidth*rold)*(cheight/2)+cleft); + Bitu copy=(cright-cleft); + Bitu nextline=CurMode->twidth; + for (Bitu i=0;itwidth*rnew)*(cheight/2)+cleft)*2; PhysPt src=base+((CurMode->twidth*rold)*(cheight/2)+cleft)*2; Bitu copy=(cright-cleft)*2;Bitu nextline=CurMode->twidth*2; - for (Bitu i=0;itwidth*rnew)*(cheight/4)+cleft)*4; + PhysPt src=base+((CurMode->twidth*rold)*(cheight/4)+cleft)*4; + Bitu copy=(cright-cleft)*4;Bitu nextline=CurMode->twidth*4; + for (Bitu i=0;itwidth*row)*(cheight/2)+cleft); + Bitu copy=(cright-cleft); + Bitu nextline=CurMode->twidth; + attr=(attr & 0x3) | ((attr & 0x3) << 2) | ((attr & 0x3) << 4) | ((attr & 0x3) << 6); + for (Bitu i=0;itwidth*row)*(cheight/2)+cleft)*2; Bitu copy=(cright-cleft)*2;Bitu nextline=CurMode->twidth*2; - for (Bitu i=0;itwidth*row)*cheight+cleft)*4; + Bitu copy=(cright-cleft)*4;Bitu nextline=CurMode->twidth*4; + attr=(attr & 0xf) | (attr & 0xf) << 4; + for (Bitu i=0;itype!=M_TEXT16) page=0xff; + if (CurMode->type>M_TEXT16) page=0xff; BIOS_NCOLS;BIOS_NROWS; if(rul>rlr) return; if(cul>clr) return; @@ -142,11 +204,15 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit while (start!=end) { start+=next; switch (CurMode->type) { + case M_TEXT2: case M_TEXT16: TEXT_CopyRow(cul,clr,start,start+nlines,base);break; case M_CGA2: + CGA2_CopyRow(cul,clr,start,start+nlines,base);break; case M_CGA4: - CGA_CopyRow(cul,clr,start,start+nlines,base);break; + CGA4_CopyRow(cul,clr,start,start+nlines,base);break; + case M_TANDY16: + TANDY16_CopyRow(cul,clr,start,start+nlines,base);break; case M_EGA16: EGA16_CopyRow(cul,clr,start,start+nlines,base);break; default: @@ -163,11 +229,15 @@ filling: } for (;nlines>0;nlines--) { switch (CurMode->type) { + case M_TEXT2: case M_TEXT16: TEXT_FillRow(cul,clr,start,base,attr);break; case M_CGA2: + CGA2_FillRow(cul,clr,start,base,attr);break; case M_CGA4: - CGA_FillRow(cul,clr,start,base,attr);break; + CGA4_FillRow(cul,clr,start,base,attr);break; + case M_TANDY16: + TANDY16_FillRow(cul,clr,start,base,attr);break; case M_EGA16: EGA16_FillRow(cul,clr,start,base,attr);break; default: @@ -187,10 +257,11 @@ void INT10_SetActivePage(Bit8u page) { real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address); if (CurMode->mode<0x8) mem_address>>=1; /* Write the new start address in vgahardware */ - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0c); - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(Bit8u)(mem_address>>8)); - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0d); - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(Bit8u)mem_address); + Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); + IO_Write(base,0x0c); + IO_Write(base+1,(Bit8u)(mem_address>>8)); + IO_Write(base,0x0d); + IO_Write(base+1,(Bit8u)mem_address); // And change the BIOS page real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page); @@ -243,8 +314,9 @@ void INT10_SetCursorShape(Bit8u first,Bit8u last) { } } dowrite: - IO_Write(0x3d4,0xa);IO_Write(0x3d5,first); - IO_Write(0x3d4,0xb);IO_Write(0x3d5,last); + Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); + IO_Write(base,0xa);IO_Write(base+1,first); + IO_Write(base,0xb);IO_Write(base+1,last); } @@ -263,10 +335,11 @@ void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) { // Calculate the address knowing nbcols nbrows and page num address=(ncols*row)+col+real_readw(BIOSMEM_SEG,BIOSMEM_CURRENT_START); // CRTC regs 0x0e and 0x0f - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0e); - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(Bit8u)(address>>8)); - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS),0x0f); - IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(Bit8u)address); + Bit16u base=real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); + IO_Write(base,0x0e); + IO_Write(base+1,(Bit8u)(address>>8)); + IO_Write(base,0x0f); + IO_Write(base+1,(Bit8u)address); } } @@ -290,6 +363,7 @@ static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool Bitu x,y; Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); switch (CurMode->type) { + case M_TEXT2: case M_TEXT16: { // Compute the address @@ -305,6 +379,7 @@ static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool return; case M_CGA4: case M_CGA2: + case M_TANDY16: if (chr<128) fontdata=Real2Phys(RealGetVec(0x43))+chr*cheight; //was plain 8 else { chr-=128; @@ -335,7 +410,7 @@ static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) { //TODO Check if this page thing is correct - if (CurMode->type!=M_TEXT16) page=0xff; + if (CurMode->type>M_TEXT16) page=0xff; if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); Bit8u cur_row=CURSOR_POS_ROW(page); Bit8u cur_col=CURSOR_POS_COL(page); @@ -351,8 +426,7 @@ void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) } } - -void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr) { +void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr) { //TODO Check if this page thing is correct Bit8u page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); BIOS_NCOLS;BIOS_NROWS; @@ -375,14 +449,14 @@ void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr) { break; case '\t': do { - INT10_TeletypeOutput(' ',attr,showattr); + INT10_TeletypeOutputAttr(' ',attr,useattr); cur_row=CURSOR_POS_ROW(page); cur_col=CURSOR_POS_COL(page); } while(cur_col%8); break; default: /* Draw the actual Character */ - WriteChar(cur_col,cur_row,page,chr,attr,showattr); + WriteChar(cur_col,cur_row,page,chr,attr,useattr); cur_col++; } if(cur_col==ncols) { @@ -398,9 +472,14 @@ void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr) { INT10_SetCursorPos(cur_row,cur_col,page); } + +void INT10_TeletypeOutput(Bit8u chr,Bit8u attr) { + INT10_TeletypeOutputAttr(chr,attr,CurMode->type>M_TEXT16); +} + void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page) { //TODO Check if this page thing is correct - if (CurMode->type!=M_TEXT16) page=0xff; + if (CurMode->type>M_TEXT16) page=0xff; if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); BIOS_NCOLS;BIOS_NROWS; @@ -420,8 +499,8 @@ void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,B if (flag&2) { attr=mem_readb(string); string++; - } - INT10_TeletypeOutput(chr,attr,true); + } else attr=7; + INT10_TeletypeOutputAttr(chr,attr,flag & 2); count--; } if (flag & 1) { diff --git a/src/ints/int10_memory.cpp b/src/ints/int10_memory.cpp index af827ce..ceb725f 100644 --- a/src/ints/int10_memory.cpp +++ b/src/ints/int10_memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,20 +47,23 @@ static Bit16u map_offset[8]={ void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height) { PhysPt where=PhysMake(0xa000,map_offset[map & 0x7]+offset*32); IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x4); //Enable plane 2 - IO_Write(0x3ce,0x6);IO_Write(0x3cf,0x0); //Disable odd/even and a0000 adressing + IO_Write(0x3ce,0x6);Bitu old_6=IO_Read(0x3cf); + IO_Write(0x3cf,0x0); //Disable odd/even and a0000 adressing for (Bitu i=0;isheight/height)-1); @@ -76,8 +79,9 @@ void INT10_SetupRomMemory(void) { /* This should fill up certain structures inside the Video Bios Rom Area */ PhysPt rom_base=PhysMake(0xc000,0); Bitu i; - int10.rom.used=2; + int10.rom.used=3; // int10.rom.used=2; Size of ROM added phys_writew(rom_base+0,0xaa55); + phys_writeb(rom_base+2,0x40); // Size of ROM: 64 512-blocks = 32KB int10.rom.font_8_first=RealMake(0xC000,int10.rom.used); for (i=0;i<128*8;i++) { phys_writeb(rom_base+int10.rom.used++,int10_font_08[i]); diff --git a/src/ints/int10_misc.cpp b/src/ints/int10_misc.cpp index 40a8a91..3afefc0 100644 --- a/src/ints/int10_misc.cpp +++ b/src/ints/int10_misc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -93,6 +93,8 @@ void INT10_GetFuncStateInformation(PhysPt save) { switch (CurMode->type) { case M_TEXT16: col_count=16;break; + case M_TEXT2: + col_count=2;break; // ?? case M_CGA2: col_count=2;break; case M_CGA4: diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index 9cf4e1f..0f17c4e 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -6,40 +6,45 @@ #include "int10.h" #include "mouse.h" -#define _HALF_CLOCK 0x0001 -#define _LINE_DOUBLE 0x0002 -#define _VGA_LINE_DOUBLE 0x0004 -#define _VGA_PIXEL_DOUBLE 0x0008 +#define _EGA_HALF_CLOCK 0x0001 +#define _EGA_LINE_DOUBLE 0x0002 #define SEQ_REGS 0x05 #define GFX_REGS 0x09 #define ATT_REGS 0x15 VideoModeBlock ModeList[]={ -/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,special flags */ -{ 0x000 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_HALF_CLOCK }, -{ 0x001 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_HALF_CLOCK }, -{ 0x002 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x003 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_HALF_CLOCK |_LINE_DOUBLE }, -{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_HALF_CLOCK |_LINE_DOUBLE }, -{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,_LINE_DOUBLE }, -{ 0x007 ,M_TEXT16 ,720 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 }, +/* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,rate,special flags */ +{ 0x000 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK }, +{ 0x001 ,M_TEXT16 ,320 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK }, +{ 0x002 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 }, +{ 0x003 ,M_TEXT16 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 }, +{ 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0 }, +{ 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0}, +{ 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x0800 ,100 ,449 ,80 ,400 ,60 ,0 }, +{ 0x007 ,M_TEXT2 ,640 ,400 ,80 ,25 ,9 ,16 ,4 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,70 ,0 }, /* 8,9,0xa are tandy modes */ -{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_HALF_CLOCK |_LINE_DOUBLE }, +{ 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,100 ,449 ,80 ,400 ,60 ,0}, -{ 0x00D ,M_EGA16 ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_HALF_CLOCK |_LINE_DOUBLE }, -{ 0x00E ,M_EGA16 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_LINE_DOUBLE }, -{ 0x00F ,M_EGA2 ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,400 ,0 }, -{ 0x010 ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 }, -{ 0x011 ,M_EGA2 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,449 ,80 ,480 ,0 }, -{ 0x012 ,M_EGA16 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 }, -{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x0000 ,100 ,449 ,80 ,400 ,_VGA_LINE_DOUBLE }, +{ 0x00D ,M_EGA16 ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,70 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE }, +{ 0x00E ,M_EGA16 ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,70 ,_EGA_LINE_DOUBLE }, +{ 0x00F ,M_EGA2 ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,400 ,70 ,0 }, +{ 0x010 ,M_EGA16 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,70 ,0 }, +{ 0x011 ,M_EGA2 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,449 ,80 ,480 ,70 ,0 }, +{ 0x012 ,M_EGA16 ,640 ,480 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,70 ,0 }, +{ 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x0000 ,100 ,449 ,80 ,400 ,70 ,0 }, -{ 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 }, -{ 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 }, +{ 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 ,0 }, +{ 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 ,0 }, +{ 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,70 ,0 }, -{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, + +{ 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 , 0}, +{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 , 0}, +{ 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,70 , 0 }, +{ 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,70 , 0 }, + +{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 ,0 }, }; @@ -67,6 +72,18 @@ static Bit8u ega_palette[64][3]= {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f} }; +#if 0 +static Bit8u cga_palette[64][3]= { + {0x00,0x00,0x00}, {0x00,0x00,0x1f}, {0x00,0x1f,0x00}, {0x00,0x1f,0x1f}, {0x1f,0x00,0x00}, {0x1f,0x00,0x1f}, {0x1f,0x1f,0x00}, {0x1f,0x1f,0x1f}, + {0x0f,0x0f,0x0f}, {0x00,0x00,0x3f}, {0x00,0x3f,0x00}, {0x00,0x3f,0x3f}, {0x3f,0x00,0x00}, {0x3f,0x00,0x3f}, {0x3f,0x3f,0x00}, {0x3f,0x3f,0x3f}, +}; +#else +static Bit8u cga_palette[16][3]= { + {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, + {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, +}; +#endif + static Bit8u vga_palette[256][3]= { @@ -114,7 +131,6 @@ bool INT10_SetVideoMode(Bitu mode) { bool clearmem=true; Bit8u modeset_ctl,video_ctl,vga_switches; - Bit16u crtc_addr; if (mode<256) { if (mode & 128) { @@ -143,17 +159,26 @@ foundmode: /* Setup the VGA to the correct mode */ VGA_SetMode(CurMode->type); - + + Bit16u crtc_base; + bool mono_mode=CurMode->type == M_TEXT2; + if (mono_mode) { + crtc_base=0x3b4; + } else { + crtc_base=0x3d4; + } /* Setup MISC Output Register */ - Bit8u misc_output=0x3; //Color and cpu memory access + Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1); + IO_Write(0x3c2,misc_output); //Setup for 3b4 or 3d4 /* Program Sequencer */ Bit8u seq_data[SEQ_REGS]; memset(seq_data,0,SEQ_REGS); seq_data[1]|=1; //8 dot fonts by default seq_data[1]|= //Check for half clock - (CurMode->special & _HALF_CLOCK) ? 0x08 : 0x00; + (CurMode->special & _EGA_HALF_CLOCK) ? 0x08 : 0x00; seq_data[4]|=0x02; //More than 64kb switch (CurMode->type) { + case M_TEXT2: case M_TEXT16: seq_data[2]|=0x3; //Enable plane 0 and 1 seq_data[4]|=0x05; //Alpanumeric and odd/even enabled @@ -173,55 +198,55 @@ foundmode: } /* Program CRTC */ /* First disable write protection */ - IO_Write(0x3d4,0x11); - IO_Write(0x3d5,IO_Read(0x3d5)&0x7f); + IO_Write(crtc_base,0x11); + IO_Write(crtc_base+1,IO_Read(crtc_base+1)&0x7f); /* Clear all the regs */ for (i=0x0;i<=0x18;i++) { - IO_Write(0x3d4,i);IO_Write(0x3d5,0); + IO_Write(crtc_base,i);IO_Write(crtc_base+1,0); } Bit8u overflow=0;Bit8u max_scanline=0; Bit8u ver_overflow=0;Bit8u hor_overflow=0; /* Horizontal Total */ - IO_Write(0x3d4,0x00);IO_Write(0x3d5,CurMode->htotal-5); + IO_Write(crtc_base,0x00);IO_Write(crtc_base+1,CurMode->htotal-5); hor_overflow|=((CurMode->htotal-5) & 0x100) >> 8; /* Horizontal Display End */ - IO_Write(0x3d4,0x01);IO_Write(0x3d5,CurMode->hdispend-1); + IO_Write(crtc_base,0x01);IO_Write(crtc_base+1,CurMode->hdispend-1); hor_overflow|=((CurMode->hdispend-1) & 0x100) >> 7; /* Start horizontal Blanking */ - IO_Write(0x3d4,0x02);IO_Write(0x3d5,CurMode->hdispend); + IO_Write(crtc_base,0x02);IO_Write(crtc_base+1,CurMode->hdispend); hor_overflow|=((CurMode->hdispend) & 0x100) >> 6; /* End horizontal Blanking */ Bitu blank_end; - if (CurMode->special & _HALF_CLOCK) { + if (CurMode->special & _EGA_HALF_CLOCK) { blank_end = (CurMode->htotal-1) & 0x7f; } else { blank_end = (CurMode->htotal-2) & 0x7f; } - IO_Write(0x3d4,0x03);IO_Write(0x3d5,0x80|(blank_end & 0x1f)); + IO_Write(crtc_base,0x03);IO_Write(crtc_base+1,0x80|(blank_end & 0x1f)); // hor_overflow|=(blank_end & 0x40) >> 3; /* Start Horizontal Retrace */ Bitu ret_start; - if (CurMode->special & _HALF_CLOCK) { + if (CurMode->special & _EGA_HALF_CLOCK) { ret_start = (CurMode->hdispend+2); } else { ret_start = (CurMode->hdispend+4); } - IO_Write(0x3d4,0x04);IO_Write(0x3d5,ret_start); + IO_Write(crtc_base,0x04);IO_Write(crtc_base+1,ret_start); hor_overflow|=(ret_start & 0x100) >> 4; /* End Horizontal Retrace */ Bitu ret_end; - if (CurMode->special & _HALF_CLOCK) { + if (CurMode->special & _EGA_HALF_CLOCK) { ret_end = (CurMode->htotal-2) & 0x3f; } else { ret_end = (CurMode->htotal-4) & 0x3f; } - IO_Write(0x3d4,0x05);IO_Write(0x3d5,(ret_end & 0x1f) | (blank_end & 0x20) << 2); + IO_Write(crtc_base,0x05);IO_Write(crtc_base+1,(ret_end & 0x1f) | (blank_end & 0x20) << 2); // hor_overflow|=(ret_end & 0x20); //TODO Be sure about these ending values in extended overflow of s3 /* Vertical Total */ - IO_Write(0x3d4,0x06);IO_Write(0x3d5,(CurMode->vtotal-2)); + IO_Write(crtc_base,0x06);IO_Write(crtc_base+1,(CurMode->vtotal-2)); overflow|=((CurMode->vtotal-2) & 0x100) >> 8; overflow|=((CurMode->vtotal-2) & 0x200) >> 4; ver_overflow|=((CurMode->vtotal-2) & 0x400) >> 10; @@ -231,67 +256,67 @@ foundmode: So you get same sized borders, but okay :) */ /* Vertical Retrace Start */ - IO_Write(0x3d4,0x10);IO_Write(0x3d5,(CurMode->vdispend+12)); + IO_Write(crtc_base,0x10);IO_Write(crtc_base+1,(CurMode->vdispend+12)); overflow|=((CurMode->vdispend+12) & 0x100) >> 6; overflow|=((CurMode->vdispend+12) & 0x200) >> 2; ver_overflow|=((CurMode->vdispend+12) & 0x400) >> 6; /* Vertical Retrace End */ - IO_Write(0x3d4,0x11);IO_Write(0x3d5,(CurMode->vdispend+14) & 0xF); + IO_Write(crtc_base,0x11);IO_Write(crtc_base+1,(CurMode->vdispend+14) & 0xF); /* Vertical Display End */ - IO_Write(0x3d4,0x12);IO_Write(0x3d5,(CurMode->vdispend-1)); + IO_Write(crtc_base,0x12);IO_Write(crtc_base+1,(CurMode->vdispend-1)); overflow|=((CurMode->vdispend-1) & 0x100) >> 7; overflow|=((CurMode->vdispend-1) & 0x200) >> 3; ver_overflow|=((CurMode->vdispend-1) & 0x400) >> 9; /* Vertical Blank Start */ - IO_Write(0x3d4,0x15);IO_Write(0x3d5,(CurMode->vdispend+8)); + IO_Write(crtc_base,0x15);IO_Write(crtc_base+1,(CurMode->vdispend+8)); overflow|=((CurMode->vdispend+8) & 0x100) >> 5; - max_scanline|=((CurMode->vdispend+8) & 0x200) >> 3; + max_scanline|=((CurMode->vdispend+8) & 0x200) >> 4; ver_overflow|=((CurMode->vdispend+8) & 0x400) >> 8; /* Vertical Retrace End */ - IO_Write(0x3d4,0x16);IO_Write(0x3d5,(CurMode->vtotal-8)); + IO_Write(crtc_base,0x16);IO_Write(crtc_base+1,(CurMode->vtotal-8)); /* Line Compare */ - Bitu line_compare=CurMode->vtotal+1; //Out of range - IO_Write(0x3d4,0x18);IO_Write(0x3d5,line_compare&0xff); + Bitu line_compare=(mode>=256) ? 2047 : 1023; + IO_Write(crtc_base,0x18);IO_Write(crtc_base+1,line_compare&0xff); overflow|=(line_compare & 0x100) >> 4; max_scanline|=(line_compare & 0x200) >> 3; ver_overflow|=(line_compare & 0x400) >> 4; Bit8u underline=0; /* Maximum scanline / Underline Location */ - if (CurMode->special & _LINE_DOUBLE) max_scanline|=0x80; + if (CurMode->special & _EGA_LINE_DOUBLE) max_scanline|=0x80; switch (CurMode->type) { + case M_TEXT2: case M_TEXT16: - max_scanline|=CurMode->theight-1; + max_scanline|=CurMode->cheight-1; underline=0x1f; break; case M_VGA: underline=0x40; - if (CurMode->special & _VGA_LINE_DOUBLE) max_scanline|=1; max_scanline|=1; //Vga doesn't use double line but this break; case M_LIN8: underline=0x60; //Seems to enable the every 4th clock on my s3 - if (CurMode->special & _VGA_LINE_DOUBLE) max_scanline|=1; +// if (CurMode->special & _VGA_LINE_DOUBLE) max_scanline|=1; break; } - IO_Write(0x3d4,0x09);IO_Write(0x3d5,max_scanline); - IO_Write(0x3d4,0x14);IO_Write(0x3d5,underline); + IO_Write(crtc_base,0x09);IO_Write(crtc_base+1,max_scanline); + IO_Write(crtc_base,0x14);IO_Write(crtc_base+1,underline); /* OverFlow */ - IO_Write(0x3d4,0x07);IO_Write(0x3d5,overflow); + IO_Write(crtc_base,0x07);IO_Write(crtc_base+1,overflow); /* Extended Horizontal Overflow */ - IO_Write(0x3d4,0x5d);IO_Write(0x3d5,hor_overflow); + IO_Write(crtc_base,0x5d);IO_Write(crtc_base+1,hor_overflow); /* Extended Vertical Overflow */ - IO_Write(0x3d4,0x5e);IO_Write(0x3d5,ver_overflow); + IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow); /* Offset Register */ - IO_Write(0x3d4,0x13); + IO_Write(crtc_base,0x13); switch (CurMode->type) { case M_LIN8: - IO_Write(0x3d5,CurMode->swidth/8); + IO_Write(crtc_base+1,CurMode->swidth/8); break; default: - IO_Write(0x3d5,CurMode->hdispend/2); + IO_Write(crtc_base+1,CurMode->hdispend/2); } /* Mode Control */ Bit8u mode_control=0; @@ -303,6 +328,7 @@ foundmode: case M_EGA16: mode_control=0xe3; break; + case M_TEXT2: case M_TEXT16: case M_VGA: mode_control=0xa3; @@ -310,18 +336,22 @@ foundmode: case M_LIN8: mode_control=0xab; break; - } - IO_Write(0x3d4,0x17);IO_Write(0x3d5,mode_control); + IO_Write(crtc_base,0x17);IO_Write(crtc_base+1,mode_control); /* Renable write protection */ - IO_Write(0x3d4,0x11); - IO_Write(0x3d5,IO_Read(0x3d5)|0x80); + IO_Write(crtc_base,0x11); + IO_Write(crtc_base+1,IO_Read(crtc_base+1)|0x80); /* Setup the correct clock */ - if (CurMode->mode<0x100) { + switch (CurMode->type) { + case M_VGA: + case M_TEXT2: + case M_TEXT16: + case M_EGA16: //Stick to 25mhz clock for now - } else { + break; + default: misc_output|=0xef; //Select clock 3 - Bitu clock=CurMode->vtotal*8*CurMode->htotal*70; + Bitu clock=CurMode->vtotal*8*CurMode->htotal*CurMode->rate; VGA_SetClock(3,clock/1000); } /* Write Misc Output */ @@ -333,6 +363,10 @@ foundmode: gfx_data[0x7]=0xf; /* Color don't care */ gfx_data[0x8]=0xff; /* BitMask */ switch (CurMode->type) { + case M_TEXT2: + gfx_data[0x5]|=0x10; //Odd-Even Mode + gfx_data[0x6]|=0x0a; //alphanumeric mode at 0xb000=0x7fff + break; case M_TEXT16: gfx_data[0x5]|=0x10; //Odd-Even Mode gfx_data[0x6]|=0x0e; //alphanumeric mode at 0xb800=0xbfff @@ -363,13 +397,18 @@ foundmode: switch (CurMode->type) { case M_EGA16: if (CurMode->mode>0xe) goto att_text16; - case M_TANDY16: - att_data[0x10]=0x01; //Color Graphics - for (i=0;i<8;i++) { + for (i=0;i<8;i++) { att_data[i]=i; att_data[i+8]=i+0x10; } break; + case M_TANDY16: + att_data[0x10]=0x01; //Color Graphics + for (i=0;i<16;i++) { + att_data[i]=i; + } + break; + case M_TEXT2: case M_TEXT16: att_data[0x13]=0x08; //Pel panning on 8, although we don't have 9 dot text mode att_data[0x10]=0x0C; //Color Text with blinking @@ -380,8 +419,12 @@ att_text16: } break; case M_CGA2: + IO_Write(0x3d9,0x7); //Setup using CGA color select register + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x7); + goto skipatt; case M_CGA4: - IO_Write(0x3d9,0x20); //Setup using CGA color select register + IO_Write(0x3d9,0x30); //Setup using CGA color select register + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30); goto skipatt; case M_VGA: case M_LIN8: @@ -392,7 +435,7 @@ att_text16: break; } - IO_Read(0x3da); + IO_Read(mono_mode ? 0x3ba : 0x3da); for (i=0;itype) { case M_EGA16: if (CurMode->mode>0xe) goto dac_text16; - case M_CGA2: - case M_CGA4: - case M_TANDY16: for (i=0;i<64;i++) { IO_Write(0x3c9,ega_palette[i][0]); IO_Write(0x3c9,ega_palette[i][1]); IO_Write(0x3c9,ega_palette[i][2]); } break; + case M_CGA2: + case M_CGA4: + case M_TANDY16: + for (i=0;i<16;i++) { + IO_Write(0x3c9,cga_palette[i][0]); + IO_Write(0x3c9,cga_palette[i][1]); + IO_Write(0x3c9,cga_palette[i][2]); + } + break; + case M_TEXT2: case M_TEXT16: dac_text16: for (i=0;i<64;i++) { @@ -429,29 +479,53 @@ dac_text16: } break; } - /* Setup registers for special video modes */ + /* Setup some special stuff for different modes */ + Bit8u feature=real_readb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE); switch (CurMode->type) { + case M_CGA2: + feature=(feature&~0x30)|0x20; + IO_Write(0x3d8,0x12); //Setup using CGA color select register + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x12); + break; + case M_CGA4: + feature=(feature&~0x30)|0x20; + IO_Write(0x3d8,0x2); //Setup using CGA color select register + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2); + break; case M_TANDY16: + feature=(feature&~0x30)|0x20; IO_Write(0x3df,0x80); //Enter 32k mode and banks on 0 break; + case M_TEXT2: + feature=(feature&~0x30)|0x30; + break; + case M_TEXT16: + feature=(feature&~0x30)|0x20; + break; + case M_EGA16: + case M_VGA: + feature=(feature&~0x30); + break; + } + real_writeb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,feature); /* Setup the CPU Window */ - IO_Write(0x3d4,0x6a); - IO_Write(0x3d5,0); + IO_Write(crtc_base,0x6a); + IO_Write(crtc_base+1,0); /* Setup the linear frame buffer */ - IO_Write(0x3d4,0x59); - IO_Write(0x3d5,(Bit8u)(S3_LFB_BASE >> 24)); - IO_Write(0x3d4,0x5a); - IO_Write(0x3d5,(Bit8u)(S3_LFB_BASE >> 16)); + IO_Write(crtc_base,0x59); + IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 24)); + IO_Write(crtc_base,0x5a); + IO_Write(crtc_base+1,(Bit8u)(S3_LFB_BASE >> 16)); /* Setup some remaining S3 registers */ - IO_Write(0x3d4,0x31);IO_Write(0x3d5,0x9); //Enable banked memory and 256k+ access - IO_Write(0x3d4,0x58);IO_Write(0x3d5,0x3); //Enable 8 mb of linear addressing - IO_Write(0x3d4,0x38);IO_Write(0x3d5,0x48); //Register lock 1 - IO_Write(0x3d4,0x39);IO_Write(0x3d5,0xa5); //Register lock 2 + IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,0x9); //Enable banked memory and 256k+ access + IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing + IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1 + IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2 /* Load text mode font */ - if (CurMode->type==M_TEXT16) { + if (CurMode->type<=M_TEXT16) { INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16); } /* Clear video memory if needs be */ @@ -463,9 +537,14 @@ dac_text16: real_writew(0xb800,i*2,0x0000); } break; + case M_TEXT2: + for (i=0;i<16*1024;i++) { + real_writew(0xb000,i*2,0x0120); + } + break; case M_TEXT16: for (i=0;i<16*1024;i++) { - real_writew(0xb800,i*2,0x0700); + real_writew(0xb800,i*2,0x0720); } break; case M_EGA16: @@ -477,16 +556,12 @@ dac_text16: } } } - /* Setup the CRTC Address */ - - crtc_addr=0x3d4; - /* Setup the BIOS */ if (mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode); else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode-0x98); //Looks like the s3 bios real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,CurMode->twidth); real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,CurMode->plength); - real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr); + real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_base); real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,CurMode->theight-1); real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,CurMode->cheight); real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem << 7))); @@ -498,12 +573,8 @@ dac_text16: real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER,0x00); real_writew(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2,0x00); - // FIXME - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but... - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but... - // Set cursor shape - if(CurMode->type==M_TEXT16) { + if(CurMode->type<=M_TEXT16) { INT10_SetCursorShape(0x06,07); } // Set cursor pos for page 0..7 diff --git a/src/ints/int10_pal.cpp b/src/ints/int10_pal.cpp index 2563e30..f39c793 100644 --- a/src/ints/int10_pal.cpp +++ b/src/ints/int10_pal.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -155,18 +155,17 @@ void INT10_GetPelMask(Bit8u & mask) { mask=IO_Read(VGAREG_PEL_MASK); } - void INT10_SetBackgroundBorder(Bit8u val) { -//TODO Detect if we're CGA? - Bit8u old=IO_Read(0x3d9) & 0xf0; - old|=val & 0xf; - IO_Write(0x3d9,old); + Bitu temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); + temp=(temp & 0xe0) | (val & 0x1f); + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp); + IO_Write(0x3d9,temp); } void INT10_SetColorSelect(Bit8u val) { -//TODO Detect if we're CGA? - Bit8u old=IO_Read(0x3d9) & ~0x20; - old|=(val & 1) << 5; - IO_Write(0x3d9,old); + Bitu temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); + temp=(temp & 0xdf) | ((val & 1) ? 0x20 : 0x0); + real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp); + IO_Write(0x3d9,temp); } diff --git a/src/ints/int10_put_pixel.cpp b/src/ints/int10_put_pixel.cpp index efa0a33..b44e359 100644 --- a/src/ints/int10_put_pixel.cpp +++ b/src/ints/int10_put_pixel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,6 +54,25 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { real_writeb(0xb800,off,old); } break; + case M_TANDY16: + { + Bit16u off=(y>>2)*160+(x>>1); + off+=(8*1024) * (y & 3); + Bit8u old=real_readb(0xb800,off); + Bit8u p[2]; + p[1] = (old >> 4) & 0xf; + p[0] = old & 0xf; + Bitu ind = 1-(x & 0x1); + + if (color & 0x80) { + p[ind]^=color; + } else { + p[ind]=color; + } + old = (p[1] << 4) | p[0]; + real_writeb(0xb800,off,old); + } + break; case M_EGA16: { /* Set the correct bitmask for the pixel position */ @@ -77,8 +96,9 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); } break; } + case M_VGA: - mem_writeb(Real2Phys(RealMake(0xa000,y*320+x)),color); + mem_writeb(PhysMake(0xa000,y*320+x),color); break; default: LOG(LOG_INT10,LOG_ERROR)("PutPixel unhandled mode type %d",CurMode->type); diff --git a/src/ints/int10_vesa.cpp b/src/ints/int10_vesa.cpp index 644c45a..8159f02 100644 --- a/src/ints/int10_vesa.cpp +++ b/src/ints/int10_vesa.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: int10_vesa.cpp,v 1.7 2004/01/11 09:27:52 harekiet Exp $ */ + #include #include @@ -168,7 +170,7 @@ Bit8u VESA_GetSVGAMode(Bit16u & mode) { return 0x00; } -Bit8u VESA_SetCPUWindow(Bit8u window,Bit16u address) { +Bit8u VESA_SetCPUWindow(Bit8u window,Bit8u address) { if (window) return 0x1; if ((address<32)) { IO_Write(0x3d4,0x6a); @@ -293,12 +295,8 @@ Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y) { return 0x1; } return 0x00; - - } - - static Bitu SetWindowPositionHandler(void) { if (reg_bh) reg_ah=VESA_GetCPUWindow(reg_bl,reg_dx); else reg_ah=VESA_SetCPUWindow(reg_bl,reg_dx); @@ -306,7 +304,6 @@ static Bitu SetWindowPositionHandler(void) { return 0; } - void INT10_SetupVESA(void) { /* Put the mode list somewhere in memory */ Bitu i; @@ -325,7 +322,7 @@ void INT10_SetupVESA(void) { int10.rom.oemstring=RealMake(0xc000,int10.rom.used); Bitu len=strlen(string_oem)+1; for (i=0;i #include "dosbox.h" @@ -100,7 +100,14 @@ static struct { float mickeysPerPixel_y; float pixelPerMickey_x; float pixelPerMickey_y; - + Bit16u updateRegion_x[2]; + Bit16u updateRegion_y[2]; + Bit16u page; + Bit16u doubleSpeedThreshold; + Bit16u language; + Bit16u cursorType; + bool enabled; + Bit16s oldshown; } mouse; #define X_MICKEY 8 @@ -116,11 +123,16 @@ static struct { INLINE void Mouse_AddEvent(Bit16u type) { if (mouse.events= mouse.updateRegion_x[0]) && (POS_X <= mouse.updateRegion_x[1]) && + (POS_Y >= mouse.updateRegion_y[0]) && (POS_Y <= mouse.updateRegion_y[1])) { + if (CurMode->type==M_TEXT16) + RestoreCursorBackgroundText(); + else + RestoreCursorBackground(); + mouse.shown--; + return; + } + */ /*Not sure yet what to do update region should be set to ??? */ + // Get Clipping ranges // In Textmode ? - if (CurMode->type==M_TEXT16) { + if (CurMode->type<=M_TEXT16) { DrawCursorText(); return; } @@ -392,15 +418,20 @@ static void SetMickeyPixelRate(Bit16s px, Bit16s py) }; static void mouse_reset_hardware(void){ - mouse.sub_mask=0; - mouse.sub_seg=0; - mouse.sub_ofs=0; + PIC_SetIRQMask(MOUSE_IRQ,false); }; -static void mouse_reset(void) -{ +void Mouse_NewVideoMode(void) +{ //Does way to much. Many of this stuff should be moved to mouse_reset one day WriteMouseIntVector(); - real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); + +// real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); + if(MOUSE_IRQ > 7) { + real_writed(0,((0x70+MOUSE_IRQ-8)<<2),CALLBACK_RealPointer(call_int74)); + } else { + real_writed(0,((0x8+MOUSE_IRQ)<<2),CALLBACK_RealPointer(call_int74)); + } + mouse.shown=-1; /* Get the correct resolution from the current video mode */ Bitu mode=mem_readb(BIOS_VIDEO_MODE); @@ -448,14 +479,30 @@ static void mouse_reset(void) mouse.cursorMask = defaultCursorMask; mouse.textAndMask= defaultTextAndMask; mouse.textXorMask= defaultTextXorMask; + mouse.language = 0; + mouse.page = 0; + mouse.doubleSpeedThreshold = 64; + mouse.updateRegion_x[0] = 1; + mouse.updateRegion_y[0] = 1; + mouse.updateRegion_x[1] = 1; + mouse.updateRegion_y[1] = 1; + mouse.cursorType = 0; + mouse.enabled=true; + mouse.oldshown=-1; SetMickeyPixelRate(8,16); } -void Mouse_NewVideoMode(void) -{ - //mouse.shown = -1; - mouse_reset(); + + +static void mouse_reset(void) { +//Much to empty Mouse_NewVideoMode contains stuff that should be in here + Mouse_NewVideoMode(); + + mouse.sub_mask=0; + mouse.sub_seg=0; + mouse.sub_ofs=0; + //Added this for cd-v19 } @@ -479,7 +526,7 @@ static Bitu INT33_Handler(void) { break; case 0x02: /* Hide Mouse */ { - if (CurMode->type!=M_TEXT16) RestoreCursorBackground(); + if (CurMode->type>M_TEXT16) RestoreCursorBackground(); else RestoreCursorBackgroundText(); mouse.shown--; } @@ -549,10 +596,12 @@ static Bitu INT33_Handler(void) { mouse.cursorMask = userdefCursorMask; mouse.hotx = reg_bx; mouse.hoty = reg_cx; + mouse.cursorType = 2; DrawCursor(); } break; case 0x0a: /* Define Text Cursor */ + mouse.cursorType = reg_bx; mouse.textAndMask = reg_cx; mouse.textXorMask = reg_dx; break; @@ -570,6 +619,19 @@ static Bitu INT33_Handler(void) { mouse.mickey_x=0; mouse.mickey_y=0; break; + case 0x10: /* Define screen region for updating */ + mouse.updateRegion_x[0]=reg_cx; + mouse.updateRegion_y[0]=reg_dx; + mouse.updateRegion_x[1]=reg_si; + mouse.updateRegion_y[1]=reg_di; + break; + case 0x11: /* Get number of buttons */ + reg_ax=0xffff; + reg_bx=MOUSE_BUTTONS; + break; + case 0x13: /* Set double-speed threshold */ + mouse.doubleSpeedThreshold=(reg_bx ? reg_bx : 64); + break; case 0x14: /* Exchange event-handler */ { Bit16u oldSeg = mouse.sub_seg; @@ -585,6 +647,23 @@ static Bitu INT33_Handler(void) { SegSet16(es,oldSeg); } break; + case 0x15: /* Get Driver storage space requirements */ + reg_bx = sizeof(mouse); + break; + case 0x16: /* Save driver state */ + { + LOG(LOG_MOUSE,LOG_WARN)("Saving driver state..."); + PhysPt dest = SegPhys(es)+reg_dx; + MEM_BlockWrite(dest, &mouse, sizeof(mouse)); + } + break; + case 0x17: /* load driver state */ + { + LOG(LOG_MOUSE,LOG_WARN)("Loading driver state..."); + PhysPt src = SegPhys(es)+reg_dx; + MEM_BlockRead(src, &mouse, sizeof(mouse)); + } + break; case 0x1a: /* Set mouse sensitivity */ SetMickeyPixelRate(reg_bx,reg_cx); // ToDo : double mouse speed value @@ -598,13 +677,56 @@ static Bitu INT33_Handler(void) { case 0x1c: /* Set interrupt rate */ /* Can't really set a rate this is host determined */ break; + case 0x1d: /* Set display page number */ + mouse.page=reg_bx; + break; + case 0x1e: /* Get display page number */ + reg_bx=mouse.page; + break; + case 0x1f: /* Disable Mousedriver */ + /* ES:BX old mouse driver Zero at the moment TODO */ + reg_bx=0; + SegSet16(es,0); + mouse.enabled=false; /* Just for reporting not doing a thing with it */ + mouse.oldshown=mouse.shown; + mouse.shown=-1; + break; + case 0x20: /* Enable Mousedriver */ + mouse.enabled=true; + mouse.shown=mouse.oldshown; + break; + case 0x22: /* Set language for messages */ + /* + * Values for mouse driver language: + * + * 00h English + * 01h French + * 02h Dutch + * 03h German + * 04h Swedish + * 05h Finnish + * 06h Spanish + * 07h Portugese + * 08h Italian + * + */ + mouse.language=reg_bx; + break; + case 0x23: /* Get language for messages */ + reg_bx=mouse.language; + break; case 0x24: /* Get Software version and mouse type */ reg_bx=0x805; //Version 8.05 woohoo - reg_ch=0xff; /* Unkown type */ - reg_cl=0; /* Hmm ps2 irq dunno */ + reg_ch=0x04; /* PS/2 type */ + reg_cl=0;//MOUSE_IRQ; /* Hmm ps2 irq 0!!!! */ + break; + case 0x26: /* Get Maximum virtual coordinates */ + reg_bx=(mouse.enabled ? 0x0000 : 0xffff); + reg_cx=mouse.max_x; + reg_dx=mouse.max_y; break; default: - LOG(LOG_MOUSE,LOG_ERROR)("Mouse Function %2X",reg_ax); + LOG(LOG_MOUSE,LOG_ERROR)("Mouse Function %04X not implemented!",reg_ax); } return CBRET_NONE; } @@ -642,7 +764,7 @@ static Bitu INT74_Handler(void) { IO_Write(0x20,0x20); /* Check for more Events if so reactivate IRQ */ if (mouse.events) { - PIC_ActivateIRQ(12); + PIC_ActivateIRQ(MOUSE_IRQ); } return CBRET_NONE; } @@ -678,7 +800,11 @@ void MOUSE_Init(Section* sec) { call_int74=CALLBACK_Allocate(); CALLBACK_Setup(call_int74,&INT74_Handler,CB_IRET); - real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); + if(MOUSE_IRQ > 7) { + real_writed(0,((0x70+MOUSE_IRQ-8)<<2),CALLBACK_RealPointer(call_int74)); + } else { + real_writed(0,((0x8+MOUSE_IRQ)<<2),CALLBACK_RealPointer(call_int74)); + } memset(&mouse,0,sizeof(mouse)); mouse_reset_hardware(); diff --git a/src/ints/xms.cpp b/src/ints/xms.cpp index f610ef9..7d43450 100644 --- a/src/ints/xms.cpp +++ b/src/ints/xms.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: xms.cpp,v 1.31 2004/01/14 20:54:41 finsterr Exp $ */ + #include #include #include "dosbox.h" @@ -26,6 +28,7 @@ #include "setup.h" #include "inout.h" #include "xms.h" +#include "bios.h" #define XMS_HANDLES 50 /* 50 XMS Memory Blocks */ #define XMS_VERSION 0x0300 /* version 3.00 */ @@ -49,6 +52,8 @@ #define XMS_RESIZE_EXTENDED_MEMORY_BLOCK 0x0f #define XMS_ALLOCATE_UMB 0x10 #define XMS_DEALLOCATE_UMB 0x11 +#define XMS_QUERY_ANY_FREE_MEMORY 0x88 +#define XMS_ALLOCATE_ANY_MEMORY 0x89 #define HIGH_MEMORY_NOT_EXIST 0x90 #define HIGH_MEMORY_IN_USE 0x91 @@ -119,7 +124,7 @@ Bitu XMS_AllocateMemory(Bitu size, Bit16u& handle) /* Find free handle */ Bit16u index=1; while (!xms_handles[index].free) { - if (++index>XMS_HANDLES) return XMS_OUT_OF_HANDLES; + if (++index>=XMS_HANDLES) return XMS_OUT_OF_HANDLES; } Bitu pages=(size/4) + ((size & 3) ? 1 : 0); MemHandle mem=MEM_AllocatePages(pages,true); @@ -279,6 +284,9 @@ Bitu XMS_Handler(void) { case XMS_QUERY_FREE_EXTENDED_MEMORY: /* 08 */ reg_bl = XMS_QueryFreeMemory(reg_ax,reg_dx); break; + case XMS_ALLOCATE_ANY_MEMORY: /* 89 */ + reg_edx &= 0xffff; + // fall through case XMS_ALLOCATE_EXTENDED_MEMORY: /* 09 */ { Bit16u handle = 0; @@ -323,7 +331,12 @@ Bitu XMS_Handler(void) { case XMS_DEALLOCATE_UMB: /* 11 */ LOG(LOG_MISC,LOG_ERROR)("XMS:Unhandled call %2X",reg_ah); break; - + case XMS_QUERY_ANY_FREE_MEMORY: /* 88 */ + reg_bl = XMS_QueryFreeMemory(reg_ax,reg_dx); + reg_eax &= 0xffff; + reg_edx &= 0xffff; + reg_ecx = (MEM_TotalPages()*MEM_PAGESIZE)-1; // highest known physical memory address + break; } // LOG(LOG_MISC,LOG_ERROR)("XMS: CALL Result: %02X",reg_bl); return CBRET_NONE; @@ -334,7 +347,7 @@ void XMS_Init(Section* sec) { Section_prop * section=static_cast(sec); if (!section->Get_bool("xms")) return; Bitu i; - + BIOS_ZeroExtendedSize(); DOS_AddMultiplexHandler(multiplex_xms); call_xms=CALLBACK_Allocate(); CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF); diff --git a/src/ints/xms.h b/src/ints/xms.h index e217060..56489dc 100644 --- a/src/ints/xms.h +++ b/src/ints/xms.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/misc/Makefile.in b/src/misc/Makefile.in index 759945d..2f9e02a 100644 --- a/src/misc/Makefile.in +++ b/src/misc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -314,7 +314,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -334,7 +334,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -359,7 +358,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/misc/messages.cpp b/src/misc/messages.cpp index 073f2ef..fc9d6ba 100644 --- a/src/misc/messages.cpp +++ b/src/misc/messages.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/misc/programs.cpp b/src/misc/programs.cpp index 111699d..99fa6ea 100644 --- a/src/misc/programs.cpp +++ b/src/misc/programs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: programs.cpp,v 1.12 2004/01/09 12:34:53 qbix79 Exp $ */ + +#include #include #include #include @@ -164,7 +167,10 @@ bool Program::SetEnv(const char * entry,const char * new_string) { /* TODO Maybe save the program name sometime. not really needed though */ /* Save the new entry */ if (new_string[0]) { - sprintf(env_string,"%s=%s",entry,new_string); + std::string bigentry(entry); + for (std::string::iterator it = bigentry.begin(); it != bigentry.end(); ++it) *it = toupper(*it); + sprintf(env_string,"%s=%s",bigentry.c_str(),new_string); +// sprintf(env_string,"%s=%s",entry,new_string); //oldcode MEM_BlockWrite(env_write,env_string,strlen(env_string)+1); env_write+=strlen(env_string)+1; } diff --git a/src/misc/setup.cpp b/src/misc/setup.cpp index 39785d0..45b81f7 100644 --- a/src/misc/setup.cpp +++ b/src/misc/setup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: setup.cpp,v 1.19 2004/01/29 09:26:52 qbix79 Exp $ */ + #include "dosbox.h" #include "cross.h" #include "setup.h" @@ -28,6 +30,10 @@ using namespace std; +void Prop_float::SetValue(char* input){ + input=trim(input); + __value._float= atof(input); +} void Prop_int::SetValue(char* input){ input=trim(input); @@ -64,10 +70,20 @@ void Prop_bool::GetValuestring(char* str){ sprintf(str,"%s",__value._bool?"true":"false"); } +void Prop_float::GetValuestring(char* str){ + sprintf(str,"%1.2f",__value._float); +} + void Prop_hex::GetValuestring(char* str){ sprintf(str,"%X",__value._hex); } +void Section_prop::Add_float(const char* _propname, float _value) { + Property* test=new Prop_float(_propname,_value); + properties.push_back(test); +} + + void Section_prop::Add_int(const char* _propname, int _value) { Property* test=new Prop_int(_propname,_value); properties.push_back(test); @@ -103,7 +119,14 @@ bool Section_prop::Get_bool(const char* _propname){ } return false; } - +float Section_prop::Get_float(const char* _propname){ + for(it tel=properties.begin();tel!=properties.end();tel++){ + if((*tel)->propname==_propname){ + return ((*tel)->GetValue())._float; + } + } + return false; +} const char* Section_prop::Get_string(const char* _propname){ for(it tel=properties.begin();tel!=properties.end();tel++){ @@ -226,36 +249,48 @@ Section* Config::GetSection(const char* _sectionname){ return NULL; } -void Config::ParseConfigFile(const char* configfilename){ +bool Config::ParseConfigFile(const char* configfilename){ ifstream in(configfilename); - if (!in) { - LOG_MSG("CONFIG:Can't find config file %s, using default settings",configfilename); - return; - } - char gegevens[150]; + if (!in) return false; + LOG_MSG("CONFIG:Loading settings from config file %s", configfilename); + char gegevens[1024]; Section* currentsection = NULL; Section* testsec = NULL; while (in) { - in.getline(gegevens,150); + in.getline(gegevens,1024); char* temp; - switch(gegevens[0]){ + char* s; + int len; + s = gegevens; + + /* strip trailing whitespace */ + for (len = strlen(s); len > 0 && isspace(s[len - 1]); len--) { + /* nothing */ + } + s[len] = 0; + + /* strip leading whitespace */ + while (isspace(s[0])) { + s++; + } + switch(s[0]){ case '%': case '\0': - case '\n': - case '#': + case '#': case ' ': + case '\n': continue; break; case '[': - temp = strrchr(gegevens,']'); + temp = strrchr(s,']'); *temp=0; - testsec = GetSection(&gegevens[1]); + testsec = GetSection(&s[1]); if(testsec != NULL ) currentsection = testsec; testsec = NULL; break; default: try{ - currentsection->HandleInputline(gegevens); + currentsection->HandleInputline(s); }catch(const char* message){ message=0; //EXIT with message @@ -263,6 +298,7 @@ void Config::ParseConfigFile(const char* configfilename){ break; } } + return true; } void Config::ParseEnv(char ** envp) { diff --git a/src/misc/support.cpp b/src/misc/support.cpp index ca70674..7be9568 100644 --- a/src/misc/support.cpp +++ b/src/misc/support.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: support.cpp,v 1.20 2003/10/14 20:39:02 harekiet Exp $ */ +/* $Id: support.cpp,v 1.21 2004/01/10 14:03:35 qbix79 Exp $ */ #include #include diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in index 65973d2..0f95ad4 100644 --- a/src/platform/Makefile.in +++ b/src/platform/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -339,7 +339,7 @@ install-am: all-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: diff --git a/src/platform/visualc/Makefile.am b/src/platform/visualc/Makefile.am index 605cef9..1c4a870 100644 --- a/src/platform/visualc/Makefile.am +++ b/src/platform/visualc/Makefile.am @@ -1 +1 @@ -EXTRA_DIST = dirent.c dirent.h unistd.h config.h +EXTRA_DIST = dirent.c dirent.h unistd.h config.h ntddscsi.h ntddcdrm.h diff --git a/src/platform/visualc/Makefile.in b/src/platform/visualc/Makefile.in index ca8ad37..f30f43a 100644 --- a/src/platform/visualc/Makefile.in +++ b/src/platform/visualc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -129,7 +129,7 @@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ -EXTRA_DIST = dirent.c dirent.h unistd.h config.h +EXTRA_DIST = dirent.c dirent.h unistd.h config.h ntddscsi.h ntddcdrm.h subdir = src/platform/visualc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -200,7 +200,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -219,7 +219,6 @@ clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile - distclean-am: clean-am distclean-generic dvi: dvi-am @@ -242,7 +241,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/platform/visualc/config.h b/src/platform/visualc/config.h index f05615f..42aeeeb 100644 --- a/src/platform/visualc/config.h +++ b/src/platform/visualc/config.h @@ -3,17 +3,26 @@ #define VERSION "0.60" /* Define to 1 to enable internal debugger, requires libcurses */ -#define C_DEBUG 0 +#define C_DEBUG 1 /* Define to 1 to enable screenshots, requires libpng */ #define C_SSHOT 1 +/* Define to 1 to use opengl display output support */ +#define C_OPENGL 1 + /* Define to 1 to enable internal modem support, requires SDL_net */ #define C_MODEM 1 /* Enable some heavy debugging options */ #define C_HEAVY_DEBUG 0 +/* The type of cpu this host has */ +#define C_HOSTCPU X86 + +/* Define to 1 to use x86 dynamic cpu core */ +#define C_DYNAMIC_X86 1 + /* Enable memory function inlining in */ #define C_CORE_INLINE 0 diff --git a/src/platform/visualc/ntddcdrm.h b/src/platform/visualc/ntddcdrm.h new file mode 100644 index 0000000..c1ee8c2 --- /dev/null +++ b/src/platform/visualc/ntddcdrm.h @@ -0,0 +1,320 @@ +/* + * ntddcdrm.h + * + * CDROM IOCTL interface. + * + * This file is part of the w32api package. + * + * Contributors: + * Created by Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __NTDDCDRM_H +#define __NTDDCDRM_H + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(push,4) + +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM + +#define IOCTL_CDROM_CHECK_VERIFY \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_FIND_NEW_DEVICES \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_GET_CONTROL \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_GET_LAST_SESSION \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_GET_VOLUME \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_PAUSE_AUDIO \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_PLAY_AUDIO_MSF \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_RAW_READ \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) + +#define IOCTL_CDROM_READ_Q_CHANNEL \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_READ_TOC \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_READ_TOC_EX \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_RESUME_AUDIO \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_SEEK_AUDIO_MSF \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_SET_VOLUME \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_SIMBAD \ + CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_STOP_AUDIO \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS) + + +#define MAXIMUM_NUMBER_TRACKS 100 +#define MAXIMUM_CDROM_SIZE 804 +#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2 + +typedef struct _TRACK_DATA { + UCHAR Reserved; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR TrackNumber; + UCHAR Reserved1; + UCHAR Address[4]; +} TRACK_DATA, *PTRACK_DATA; + +/* CDROM_DISK_DATA.DiskData flags */ +#define CDROM_DISK_AUDIO_TRACK 0x00000001 +#define CDROM_DISK_DATA_TRACK 0x00000002 + +typedef struct _CDROM_DISK_DATA { + ULONG DiskData; +} CDROM_DISK_DATA, *PCDROM_DISK_DATA; + +typedef struct _CDROM_PLAY_AUDIO_MSF { + UCHAR StartingM; + UCHAR StartingS; + UCHAR StartingF; + UCHAR EndingM; + UCHAR EndingS; + UCHAR EndingF; +} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF; + +/* CDROM_READ_TOC_EX.Format constants */ +#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00 +#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01 +#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02 +#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03 +#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04 +#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05 + +typedef struct _CDROM_READ_TOC_EX { + UCHAR Format : 4; + UCHAR Reserved1 : 3; + UCHAR Msf : 1; + UCHAR SessionTrack; + UCHAR Reserved2; + UCHAR Reserved3; +} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX; + +typedef struct _CDROM_SEEK_AUDIO_MSF { + UCHAR M; + UCHAR S; + UCHAR F; +} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; + +/* CDROM_SUB_Q_DATA_FORMAT.Format constants */ +#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 +#define IOCTL_CDROM_CURRENT_POSITION 0x01 +#define IOCTL_CDROM_MEDIA_CATALOG 0x02 +#define IOCTL_CDROM_TRACK_ISRC 0x03 + +typedef struct _CDROM_SUB_Q_DATA_FORMAT { + UCHAR Format; + UCHAR Track; +} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; + +typedef struct _CDROM_TOC { + UCHAR Length[2]; + UCHAR FirstTrack; + UCHAR LastTrack; + TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; +} CDROM_TOC, *PCDROM_TOC; + +#define CDROM_TOC_SIZE sizeof(CDROM_TOC) + +typedef struct _CDROM_TOC_ATIP_DATA_BLOCK { + UCHAR CdrwReferenceSpeed : 3; + UCHAR Reserved3 : 1; + UCHAR WritePower : 3; + UCHAR True1 : 1; + UCHAR Reserved4 : 6; + UCHAR UnrestrictedUse : 1; + UCHAR Reserved5 : 1; + UCHAR A3Valid : 1; + UCHAR A2Valid : 1; + UCHAR A1Valid : 1; + UCHAR Reserved6 : 3; + UCHAR IsCdrw : 1; + UCHAR True2 : 1; + UCHAR Reserved7; + UCHAR LeadInMsf[3]; + UCHAR Reserved8; + UCHAR LeadOutMsf[3]; + UCHAR Reserved9; + UCHAR A1Values[3]; + UCHAR Reserved10; + UCHAR A2Values[3]; + UCHAR Reserved11; + UCHAR A3Values[3]; + UCHAR Reserved12; +} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK; + +/* CDROM_TOC_CD_TEXT_DATA_BLOCK.PackType constants */ +#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80 +#define CDROM_CD_TEXT_PACK_PERFORMER 0x81 +#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82 +#define CDROM_CD_TEXT_PACK_COMPOSER 0x83 +#define CDROM_CD_TEXT_PACK_ARRANGER 0x84 +#define CDROM_CD_TEXT_PACK_MESSAGES 0x85 +#define CDROM_CD_TEXT_PACK_DISC_ID 0x86 +#define CDROM_CD_TEXT_PACK_GENRE 0x87 +#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88 +#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89 +#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e +#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f + +typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK { + UCHAR PackType; + UCHAR TrackNumber : 7; + UCHAR ExtensionFlag : 1; + UCHAR SequenceNumber; + UCHAR CharacterPosition : 4; + UCHAR BlockNumber : 3; + UCHAR Unicode : 1; + union { + UCHAR Text[12]; + WCHAR WText[6]; + }; + UCHAR CRC[2]; +} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK; + +/* CDROM_TOC_FULL_TOC_DATA_BLOCK.Adr constants */ +#define ADR_NO_MODE_INFORMATION 0x0 +#define ADR_ENCODES_CURRENT_POSITION 0x1 +#define ADR_ENCODES_MEDIA_CATALOG 0x2 +#define ADR_ENCODES_ISRC 0x3 + +typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK { + UCHAR SessionNumber; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR Reserved1; + UCHAR Point; + UCHAR MsfExtra[3]; + UCHAR Zero; + UCHAR Msf[3]; +} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK; + +/* SUB_Q_HEADER.AudioStatus constants */ +#define AUDIO_STATUS_NOT_SUPPORTED 0x00 +#define AUDIO_STATUS_IN_PROGRESS 0x11 +#define AUDIO_STATUS_PAUSED 0x12 +#define AUDIO_STATUS_PLAY_COMPLETE 0x13 +#define AUDIO_STATUS_PLAY_ERROR 0x14 +#define AUDIO_STATUS_NO_STATUS 0x15 + +typedef struct _SUB_Q_HEADER { + UCHAR Reserved; + UCHAR AudioStatus; + UCHAR DataLength[2]; +} SUB_Q_HEADER, *PSUB_Q_HEADER; + +typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved[3]; + UCHAR Reserved1 : 7; + UCHAR Mcval :1; + UCHAR MediaCatalog[15]; +} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; + +typedef struct _SUB_Q_TRACK_ISRC { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved0; + UCHAR Track; + UCHAR Reserved1; + UCHAR Reserved2 : 7; + UCHAR Tcval : 1; + UCHAR TrackIsrc[15]; +} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; + +typedef struct _SUB_Q_CURRENT_POSITION { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Control : 4; + UCHAR ADR : 4; + UCHAR TrackNumber; + UCHAR IndexNumber; + UCHAR AbsoluteAddress[4]; + UCHAR TrackRelativeAddress[4]; +} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; + +typedef union _SUB_Q_CHANNEL_DATA { + SUB_Q_CURRENT_POSITION CurrentPosition; + SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; + SUB_Q_TRACK_ISRC TrackIsrc; +} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; + +/* CDROM_AUDIO_CONTROL.LbaFormat constants */ +#define AUDIO_WITH_PREEMPHASIS 0x1 +#define DIGITAL_COPY_PERMITTED 0x2 +#define AUDIO_DATA_TRACK 0x4 +#define TWO_FOUR_CHANNEL_AUDIO 0x8 + +typedef struct _CDROM_AUDIO_CONTROL { + UCHAR LbaFormat; + USHORT LogicalBlocksPerSecond; +} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL; + +typedef struct _VOLUME_CONTROL { + UCHAR PortVolume[4]; +} VOLUME_CONTROL, *PVOLUME_CONTROL; + +typedef enum _TRACK_MODE_TYPE { + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +typedef struct __RAW_READ_INFO { + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + +#endif /* __NTDDCDRM_H */ diff --git a/src/platform/visualc/ntddscsi.h b/src/platform/visualc/ntddscsi.h new file mode 100644 index 0000000..8342c23 --- /dev/null +++ b/src/platform/visualc/ntddscsi.h @@ -0,0 +1,176 @@ +/* + * ntddscsi.h + * + * SCSI port IOCTL interface. + * + * This file is part of the w32api package. + * + * Contributors: + * Created by Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __NTDDSCSI_H +#define __NTDDSCSI_H + +#if __GNUC__ >=3 +#pragma GCC system_header +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#pragma pack(push,4) + +//#include "ntddk.h" + +#define DD_SCSI_DEVICE_NAME "\\Device\\ScsiPort" +#define DD_SCSI_DEVICE_NAME_U L"\\Device\\ScsiPort" + +#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER + +#define IOCTL_SCSI_GET_INQUIRY_DATA \ + CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_SCSI_GET_CAPABILITIES \ + CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_SCSI_GET_ADDRESS \ + CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_SCSI_MINIPORT \ + CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +#define IOCTL_SCSI_PASS_THROUGH \ + CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +#define IOCTL_SCSI_PASS_THROUGH_DIRECT \ + CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +#define IOCTL_SCSI_RESCAN_BUS \ + CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +DEFINE_GUID(ScsiRawInterfaceGuid, \ + 0x53f56309L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); + +DEFINE_GUID(WmiScsiAddressGuid, \ + 0x53f5630fL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); + +typedef struct _SCSI_PASS_THROUGH { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG_PTR DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; + +typedef struct _SCSI_PASS_THROUGH_DIRECT { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + PVOID DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; + +typedef struct _SRB_IO_CONTROL { + ULONG HeaderLength; + UCHAR Signature[8]; + ULONG Timeout; + ULONG ControlCode; + ULONG ReturnCode; + ULONG Length; +} SRB_IO_CONTROL, *PSRB_IO_CONTROL; + +typedef struct _SCSI_ADDRESS { + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +} SCSI_ADDRESS, *PSCSI_ADDRESS; + +typedef struct _SCSI_BUS_DATA { + UCHAR NumberOfLogicalUnits; + UCHAR InitiatorBusId; + ULONG InquiryDataOffset; +}SCSI_BUS_DATA, *PSCSI_BUS_DATA; + +typedef struct _SCSI_ADAPTER_BUS_INFO { + UCHAR NumberOfBuses; + SCSI_BUS_DATA BusData[1]; +} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; + +typedef struct _IO_SCSI_CAPABILITIES { + ULONG Length; + ULONG MaximumTransferLength; + ULONG MaximumPhysicalPages; + ULONG SupportedAsynchronousEvents; + ULONG AlignmentMask; + BOOLEAN TaggedQueuing; + BOOLEAN AdapterScansDown; + BOOLEAN AdapterUsesPio; +} IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES; + +typedef struct _SCSI_INQUIRY_DATA { + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + BOOLEAN DeviceClaimed; + ULONG InquiryDataLength; + ULONG NextInquiryDataOffset; + UCHAR InquiryData[1]; +} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; + +#define SCSI_IOCTL_DATA_OUT 0 +#define SCSI_IOCTL_DATA_IN 1 +#define SCSI_IOCTL_DATA_UNSPECIFIED 2 + +/* +typedef struct _DUMP_POINTERS { + PADAPTER_OBJECT AdapterObject; + PVOID MappedRegisterBase; + PVOID DumpData; + PVOID CommonBufferVa; + LARGE_INTEGER CommonBufferPa; + ULONG CommonBufferSize; + BOOLEAN AllocateCommonBuffers; + BOOLEAN UseDiskDump; + UCHAR Spare1[2]; + PVOID DeviceObject; +} DUMP_POINTERS, *PDUMP_POINTERS; +*/ +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + +#endif /* __NTDDSCSI_H */ diff --git a/src/shell/Makefile.am b/src/shell/Makefile.am index a9476e9..06f8c5f 100644 --- a/src/shell/Makefile.am +++ b/src/shell/Makefile.am @@ -1,4 +1,4 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libshell.a -libshell_a_SOURCES = shell.cpp shell_batch.cpp shell_cmds.cpp shell_inc.h shell_misc.cpp +libshell_a_SOURCES = shell.cpp shell_batch.cpp shell_cmds.cpp shell_misc.cpp diff --git a/src/shell/Makefile.in b/src/shell/Makefile.in index b005121..7513fe6 100644 --- a/src/shell/Makefile.in +++ b/src/shell/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -132,7 +132,7 @@ target_vendor = @target_vendor@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libshell.a -libshell_a_SOURCES = shell.cpp shell_batch.cpp shell_cmds.cpp shell_inc.h shell_misc.cpp +libshell_a_SOURCES = shell.cpp shell_batch.cpp shell_cmds.cpp shell_misc.cpp subdir = src/shell ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -156,10 +156,6 @@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ DIST_SOURCES = $(libshell_a_SOURCES) DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libshell_a_SOURCES) @@ -318,7 +314,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -338,7 +334,6 @@ clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -363,7 +358,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index 9610fd1..24dfbf6 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,13 +16,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell.cpp,v 1.36 2003/10/14 23:34:28 harekiet Exp $ */ +/* $Id: shell.cpp,v 1.39 2004/02/03 08:35:29 qbix79 Exp $ */ #include #include #include #include "setup.h" -#include "shell_inc.h" +#include "shell.h" Bitu call_shellstop; @@ -71,7 +71,7 @@ Bitu DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn,bool * append) { char ch; Bitu num=0; - while (ch=*lr++) { + while ( (ch=*lr++) ) { switch (ch) { case '>': *append=((*lr)=='>'); @@ -283,15 +283,18 @@ void SHELL_Init() { MSG_Add("SHELL_CMD_DIR_BYTES_FREE","%5d Dir(s) %17s Bytes free\n"); MSG_Add("SHELL_EXECUTE_DRIVE_NOT_FOUND","Drive %c does not exist!\n"); MSG_Add("SHELL_EXECUTE_ILLEGAL_COMMAND","Illegal command: %s.\n"); - MSG_Add("SHELL_CMD_PAUSE","Press any key to continue.\n"); + MSG_Add("SHELL_CMD_PAUSE","Press any key to continue.\n"); MSG_Add("SHELL_CMD_PAUSE_HELP","Waits for 1 keystroke to continue.\n"); MSG_Add("SHELL_CMD_COPY_FAILURE","Copy failure : %s.\n"); MSG_Add("SHELL_CMD_COPY_SUCCESS"," %d File(s) copied.\n"); + MSG_Add("SHELL_CMD_SUBST_NO_REMOVE","Removing drive not supported. Doing nothing.\n"); + MSG_Add("SHELL_CMD_SUBST_FAILURE","SUBST failed. You either made an error in your commandline or the target drive is already used.\nIt's only possible to use SUBST on Local drives"); MSG_Add("SHELL_STARTUP","DOSBox Shell v" VERSION "\n" "This version runs some protected mode games!\n" "For supported shell commands type: HELP\n" "For a short introduction type: INTRO\n\n" + "If you want more speed, try ctrl-F8 and ctrl-F12.\n" "For more information read the README file in DOSBox directory.\n" "\nHAVE FUN!\nThe DOSBox Team\n\n" ); @@ -311,10 +314,13 @@ void SHELL_Init() { MSG_Add("SHELL_CMD_REM_HELP","Add comments in a batch file.\n"); MSG_Add("SHELL_CMD_NO_WILD","This is a simple version of the command, no wildcards allowed!\n"); MSG_Add("SHELL_CMD_RENAME_HELP","Renames files.\n"); - MSG_Add("SHELL_CMD_DELETE_HELP","Removes files.\n"); + MSG_Add("SHELL_CMD_DELETE_HELP","Removes files.\n"); MSG_Add("SHELL_CMD_COPY_HELP","Copy files.\n"); MSG_Add("SHELL_CMD_CALL_HELP","Start a batch file from within another batch file.\n"); - /* Regular startup */ + MSG_Add("SHELL_CMD_SUBST_HELP","Assign an internal directory to a drive\n"); + MSG_Add("SHELL_CMD_LOADHIGH_HELP","Run a program. For batch file compatibility only.\n"); + + /* Regular startup */ call_shellstop=CALLBACK_Allocate(); /* Setup the startup CS:IP to kill the last running machine when exitted */ RealPt newcsip=CALLBACK_RealPointer(call_shellstop); diff --git a/src/shell/shell_batch.cpp b/src/shell/shell_batch.cpp index c927e88..4642a2b 100644 --- a/src/shell/shell_batch.cpp +++ b/src/shell/shell_batch.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ #include #include -#include "shell_inc.h" +#include "shell.h" BatchFile::BatchFile(DOS_Shell * host,char * name, char * cmd_line) { @@ -89,7 +89,7 @@ emptyline: if (!first) continue; *first++=0; std::string temp; if (shell->GetEnvStr(cmd_read,temp)) { - char * equals=strchr(temp.c_str(),'='); + const char * equals=strchr(temp.c_str(),'='); if (!equals) continue; equals++; strcpy(cmd_write,equals); @@ -125,7 +125,8 @@ again: } while (c!='\n' && n); *cmd_write++=0; if (cmd[0]==':') { - if (strcasecmp(cmd+1,where)==0) return true; + char *nospace = trim(cmd+1); + if (strcasecmp(nospace,where)==0) return true; } if (!n) { delete this; diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index 2bb7113..2de9dfc 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,13 +16,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell_cmds.cpp,v 1.33 2003/10/14 23:34:23 harekiet Exp $ */ +/* $Id: shell_cmds.cpp,v 1.37 2004/01/10 14:03:36 qbix79 Exp $ */ #include -#include "shell_inc.h" +#include "shell.h" #include "callback.h" #include "regs.h" +#include "../dos/drives.h" static SHELL_Cmd cmd_list[]={ { "CHDIR", 0, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP"}, @@ -49,7 +50,10 @@ static SHELL_Cmd cmd_list[]={ { "REN", 1, &DOS_Shell::CMD_RENAME, "SHELL_CMD_RENAME_HELP"}, { "PAUSE", 0, &DOS_Shell::CMD_PAUSE, "SHELL_CMD_PAUSE_HELP"}, { "CALL", 0, &DOS_Shell::CMD_CALL, "SHELL_CMD_CALL_HELP"}, -{ 0,0,0,0} +{ "SUBST", 0, &DOS_Shell::CMD_SUBST, "SHELL_CMD_SUBST_HELP"}, +{ "LOADHIGH", 0, &DOS_Shell::CMD_LOADHIGH, "SHELL_CMD_LOADHIGH_HELP"}, +{ "LH", 1, &DOS_Shell::CMD_LOADHIGH, "SHELL_CMD_LOADHIGH_HELP"}, +{0,0,0,0} }; void DOS_Shell::DoCommand(char * line) { @@ -251,10 +255,32 @@ void DOS_Shell::CMD_DIR(char * args) { byte_count=file_count=dir_count=0; char buffer[CROSS_LEN]; - if (strlen(args)==0) args="*.*"; //no arguments. - if ((strlen(args)==1) && (args[0]==' ')) args="*.*"; //stuff like dir /p + args = trim(args); + Bit32u argLen = strlen(args); + if (argLen == 0) { + strcpy(args,"*.*"); //no arguments. + } else { + switch (args[argLen-1]) + { + case '\\': // handle \, C:\, etc. + case ':' : // handle C:, etc. + strcat(args,"*.*"); + break; + default: + break; + } + } args = ExpandDot(args,buffer); - StripSpaces(args); + + if (!strrchr(args,'*') && !strrchr(args,'?')) { + Bit16u attribute=0; + if(DOS_GetFileAttr(args,&attribute) && (attribute&DOS_ATTR_DIRECTORY) ) { + strcat(args,"\\*.*"); // if no wildcard and a directory, get its files + } + } + if (!strrchr(args,'.')) { + strcat(args,".*"); // if no extension, get them all + } /* Make a full path in the args */ if (!DOS_Canonicalize(args,path)) { @@ -564,3 +590,55 @@ void DOS_Shell::CMD_CALL(char * args){ this->call=false; } +void DOS_Shell::CMD_SUBST (char * args) { +/* If more that one type can be substed think of something else + * E.g. make basedir member dos_drive instead of localdrive + */ + localDrive* ldp=0; + char mountstring[DOS_PATHLENGTH+CROSS_LEN+20]; + char temp_str[2] = { 0,0 }; + try { + strcpy(mountstring,"MOUNT "); + StripSpaces(args); + std::string arg; + CommandLine command(0,args); + + if (command.GetCount() != 2) throw 0 ; + command.FindCommand(2,arg); + if((arg=="/D" ) || (arg=="/d")) throw 1; //No removal (one day) + + command.FindCommand(1,arg); + if(arg[1] !=':') throw(0); + temp_str[0]=toupper(args[0]); + if(Drives[temp_str[0]-'A'] ) throw 0; //targetdrive in use + strcat(mountstring,temp_str); + strcat(mountstring," "); + + command.FindCommand(2,arg); + Bit8u drive;char fulldir[DOS_PATHLENGTH]; + if (!DOS_MakeName(const_cast(arg.c_str()),fulldir,&drive)) throw 0; + + if( ( ldp=dynamic_cast(Drives[drive])) == 0 ) throw 0; + char newname[CROSS_LEN]; + strcpy(newname, ldp->basedir); + strcat(newname,fulldir); + CROSS_FILENAME(newname); + ldp->dirCache.ExpandName(newname); + strcat(mountstring, newname); + this->ParseLine(mountstring); + } + catch(int a){ + if(a == 0) { + WriteOut(MSG_Get("SHELL_CMD_SUBST_FAILURE")); + } else { + WriteOut(MSG_Get("SHELL_CMD_SUBST_NO_REMOVE")); + } + return; + } + + return; +} + +void DOS_Shell::CMD_LOADHIGH(char *args){ + this->ParseLine(args); +} diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index 3b94cc2..7490986 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2003 The DOSBox Team + * Copyright (C) 2002-2004 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,11 +16,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell_misc.cpp,v 1.26 2003/10/10 09:21:35 qbix79 Exp $ */ +/* $Id: shell_misc.cpp,v 1.28 2004/01/10 14:03:36 qbix79 Exp $ */ #include #include -#include "shell_inc.h" +#include "shell.h" #include "regs.h" diff --git a/visualc/Makefile.in b/visualc/Makefile.in index 84c777b..108a50f 100644 --- a/visualc/Makefile.in +++ b/visualc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.7.7 from Makefile.am. +# Makefile.in generated by automake 1.7.9 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 @@ -200,7 +200,7 @@ install-am: all-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - INSTALL_STRIP_FLAG=-s \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: @@ -219,7 +219,6 @@ clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile - distclean-am: clean-am distclean-generic dvi: dvi-am @@ -242,7 +241,6 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile - maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am diff --git a/visualc/dosbox.dsp b/visualc/dosbox.dsp index 6328322..a01dc42 100644 --- a/visualc/dosbox.dsp +++ b/visualc/dosbox.dsp @@ -89,46 +89,6 @@ LINK32=link.exe # Begin Group "cpu" # PROP Default_Filter "" -# Begin Group "core_16" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\src\cpu\core_16\helpers.h -# End Source File -# Begin Source File - -SOURCE=..\src\cpu\core_16\main.h -# End Source File -# Begin Source File - -SOURCE=..\src\cpu\core_16\prefix_66.h -# End Source File -# Begin Source File - -SOURCE=..\src\cpu\core_16\prefix_66_of.h -# End Source File -# Begin Source File - -SOURCE=..\src\cpu\core_16\prefix_of.h -# End Source File -# Begin Source File - -SOURCE=..\src\cpu\core_16\start.h -# End Source File -# Begin Source File - -SOURCE=..\src\cpu\core_16\stop.h -# End Source File -# Begin Source File - -SOURCE=..\src\cpu\core_16\support.h -# End Source File -# Begin Source File - -SOURCE=..\src\cpu\core_16\table_ea.h -# End Source File -# End Group # Begin Group "core_full" # PROP Default_Filter "" diff --git a/visualc_net/Makefile.am b/visualc_net/Makefile.am new file mode 100644 index 0000000..6d1c6dd --- /dev/null +++ b/visualc_net/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = dosbox.sln dosbox.vcproj \ No newline at end of file diff --git a/visualc_net/Makefile.in b/visualc_net/Makefile.in new file mode 100644 index 0000000..9a25c1b --- /dev/null +++ b/visualc_net/Makefile.in @@ -0,0 +1,271 @@ +# 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@ +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@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +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@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +EXTRA_DIST = dosbox.sln dosbox.vcproj +subdir = visualc_net +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits visualc_net/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + +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 + +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 + +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: all all-am check check-am clean clean-generic distclean \ + distclean-generic 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 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: diff --git a/visualc_net/dosbox.sln b/visualc_net/dosbox.sln new file mode 100644 index 0000000..5f2be4c --- /dev/null +++ b/visualc_net/dosbox.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dosbox", "dosbox.vcproj", "{7FCFFB9B-8629-4D51-849C-8490CECF8AB7}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Debug.ActiveCfg = Debug|Win32 + {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Debug.Build.0 = Debug|Win32 + {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Release.ActiveCfg = Release|Win32 + {7FCFFB9B-8629-4D51-849C-8490CECF8AB7}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/visualc_net/dosbox.vcproj b/visualc_net/dosbox.vcproj new file mode 100644 index 0000000..5d30ae3 --- /dev/null +++ b/visualc_net/dosbox.vcproj @@ -0,0 +1,739 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +