diff --git a/AUTHORS b/AUTHORS index e5076c3..7d2b32a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -5,3 +5,5 @@ Sjoerd v.d. Berg Peter Veenstra Felix Jakschitsch Ulf Wohlers +Tommy Frössman + diff --git a/ChangeLog b/ChangeLog index 3745cf8..90cdcdb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +0.60 + - rewrote memory system for future paging support + - fixed several EMS and XMS bugs and rewrite for new memory system + - added some support for tandy video modes + - added MAME Tandy 3 voice emulation + - added MAME CMS/GameBlaster emulation + - added serial port emulation with virtual tcp/ip modem (somewhat buggy) + - sound blaster emulation is now sb pro 2.0 compatible + - added basic support for 32-bit protected mode + - VGA now tries to emulate an S3 Trio 64 card with 2 MB + - VESA 2.0 support for some 256 color modes + - rewrote large piece of video bios code for better compatibility + - added support for the not inheritance flags. + - created functions for creating child psp. + - updated errorcodes of findfirst (thanks Mirek!) + - rewrote loggingsystem to generate less warnings + - added dos protected mode interface (dpmi) + - added cdrom label support + - improved cdrom audio playing + - fixed and improved directory cache + - debugger shows selector- and cpu mode info + - added SELINFO (selector information) command to debugger + - added reference counting for dos files + - added tab-completion + - added basic fpu support. + - fixed several bugs with case sensitive filesystems. + - added more shell commands and improved their behaviour. + - mouse improvements. + - real time clock improvements. + - DMA fixes. + - Improved .BAT file support. + 0.58 - fixed date and time issues with fcbs - added more commands to the internal Shell diff --git a/INSTALL b/INSTALL index fae0057..12c4bd9 100644 --- a/INSTALL +++ b/INSTALL @@ -1,21 +1,28 @@ Things needed for compilation. SDL - The Simple DirectMedia Library available at http://www.libsdl.org + The Simple DirectMedia Library available at http://www.libsdl.org Curses - If you want to enable the debugger you need a curses library. - ncurses should be installed on just about every unix distro. - For win32 get pdcurses at http://pdcurses.sourceforge.net + (optional) + If you want to enable the debugger you need a curses library. + ncurses should be installed on just about every unix distro. + For win32 get pdcurses at http://pdcurses.sourceforge.net Libpng - Needed for the screenshots. (--enable-shots when configuring dosbox) + Needed for the screenshots. (optional) For win32 get libpng from http://www.sourceforge.net/projects/gnuwin32 Zlib - Needed by libpng. + Needed by libpng. (optional) For win32 get libz (rename to zlib) from http://www.sourceforge.net/projects/gnuwin32 +SDL_Net + For modem support(optional). Get it from http://www.libsdl.org + +ALSA_Headers + (optional) + ???????? for Alsa support under linux If you want compile from the CVS under a unix system, you'll also need automake (>=1.6), autoconf(>=2.50). Should be available at http://www.gnu.org @@ -26,19 +33,28 @@ If you are building from the cvs run ./autogen.sh first before doing the followi 1. ./configure 2. make -In step 1 you could add the following switches --enable-shots this will -enable the screenshot facility, also --enable-debug is a valid switch. This -will enable the internal debugger. (It can be started by pressing - on the -numeric keyboard) +In step 1 you could add the following switches: +--enable-debug + enables the internal debugger. --enable-debug=heavy enables even more + debug options. Dosbox should then be run from a xterm and when the sdl- + window is active press - on numeric keyboard to enter the debugger. + +--disable-fpu + Will disable the emulated fpu. Although the fpu emulation hasn't finished and isn't + entirely accurate it's advised to leave it on. + +--enable-core-inline + enables some memory increasing inlines. This greatly increases compiletime for maybe a increase + in speed. Check the src subdir for the binary. + + Compiling on FreeBSD might be a problem since SDL has no joystick support there. To get around this edit sdlmain.cpp to enable some #define. Let's hope someday the sdl people will just report 0 joysticks in freebsd or get it working some other way :) Build instructions for VC++6 - -Open the workspace in the visualc subdir and build from there. - +Don't use VC++ 6:it creates faulty code in core_normal.cpp diff --git a/Makefile.in b/Makefile.in index c769f67..a72024c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -15,77 +15,122 @@ @SET_MAKE@ # Main Makefile for DOSBox -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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 = autogen.sh SUBDIRS = src include visualc docs @@ -96,14 +141,15 @@ CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = DIST_SOURCES = -RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ - uninstall-info-recursive all-recursive install-data-recursive \ - install-exec-recursive installdirs-recursive install-recursive \ - uninstall-recursive check-recursive installcheck-recursive -DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ - Makefile.in NEWS THANKS acinclude.m4 aclocal.m4 config.guess \ - config.h.in config.sub configure configure.in depcomp \ - install-sh missing mkinstalldirs +RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ + ps-recursive install-info-recursive uninstall-info-recursive \ + all-recursive install-data-recursive install-exec-recursive \ + installdirs-recursive install-recursive uninstall-recursive \ + check-recursive installcheck-recursive +DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/configure AUTHORS \ + COPYING ChangeLog INSTALL Makefile.am NEWS THANKS acinclude.m4 \ + aclocal.m4 config.guess config.h.in config.sub configure.in \ + depcomp install-sh missing mkinstalldirs DIST_SUBDIRS = $(SUBDIRS) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -198,10 +244,17 @@ tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -217,9 +270,15 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ + if (etags --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + else \ + include_option=--include; \ + fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + test -f $$subdir/TAGS && \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ @@ -232,13 +291,28 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = . @@ -250,17 +324,25 @@ am__remove_distdir = \ && rm -fr $(distdir); }; } GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print distdir: $(DISTFILES) - @if sed 15q $(srcdir)/NEWS | fgrep -e "$(VERSION)" >/dev/null; \ - then :; else \ + @case `sed 15q $(srcdir)/NEWS` in \ + *"$(VERSION)"*) : ;; \ + *) \ echo "NEWS not updated; not releasing" 1>&2; \ - exit 1; \ - fi + exit 1;; \ + esac $(am__remove_distdir) mkdir $(distdir) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -313,12 +395,13 @@ distcheck: dist $(am__remove_distdir) GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - chmod -R a-w $(distdir); chmod a+w $(distdir) - mkdir $(distdir)/=build - mkdir $(distdir)/=inst + mkdir $(distdir)/_build + mkdir $(distdir)/_inst chmod a-w $(distdir) - dc_install_base=`$(am__cd) $(distdir)/=inst && pwd` \ - && cd $(distdir)/=build \ - && ../configure --srcdir=.. --prefix=$$dc_install_base \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && cd $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ @@ -326,23 +409,39 @@ distcheck: dist && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ - && (test `find $$dc_install_base -type f -print | wc -l` -le 1 \ - || { echo "ERROR: files left after uninstall:" ; \ - find $$dc_install_base -type f -print ; \ - exit 1; } >&2 ) \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && $(mkinstalldirs) "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist-gzip \ && rm -f $(distdir).tar.gz \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @echo "$(distdir).tar.gz is ready for distribution" | \ sed 'h;s/./=/g;p;x;p;x' +distuninstallcheck: + @cd $(distuninstallcheck_dir) \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 distcleancheck: distclean - if test '$(srcdir)' = . ; then \ + @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi - test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left after distclean:" ; \ + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am @@ -370,7 +469,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -381,6 +480,8 @@ 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 dvi: dvi-recursive @@ -403,22 +504,33 @@ installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf autom4te.cache + -rm -rf $(top_srcdir)/autom4te.cache + + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive -.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ - clean-generic clean-recursive dist dist-all dist-gzip distcheck \ - distclean distclean-generic distclean-hdr distclean-recursive \ - distclean-tags distcleancheck distdir dvi dvi-am dvi-recursive \ - info info-am info-recursive install install-am install-data \ +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ + clean-generic clean-recursive ctags ctags-recursive dist \ + dist-all dist-gzip distcheck distclean distclean-generic \ + distclean-hdr distclean-recursive distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am dvi-recursive info \ + info-am info-recursive install install-am install-data \ install-data-am install-data-recursive install-exec \ install-exec-am install-exec-recursive install-info \ install-info-am install-info-recursive install-man \ @@ -426,9 +538,9 @@ uninstall-info: uninstall-info-recursive installdirs installdirs-am installdirs-recursive \ maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-generic \ - mostlyclean-recursive tags tags-recursive uninstall \ - uninstall-am uninstall-info-am uninstall-info-recursive \ - uninstall-recursive + mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \ + ps-recursive tags tags-recursive uninstall uninstall-am \ + uninstall-info-am uninstall-info-recursive uninstall-recursive # 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. diff --git a/NEWS b/NEWS index 6afcd45..7e7c1e5 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,35 @@ +0.60 + - rewrote memory system for future paging support + - fixed several EMS and XMS bugs and rewrite for new memory system + - added some support for tandy video modes + - added MAME Tandy 3 voice emulation + - added MAME CMS/GameBlaster emulation + - added serial port emulation with virtual tcp/ip modem (somewhat buggy) + - sound blaster emulation is now sb pro 2.0 compatible + - added basic support for 32-bit protected mode + - VGA now tries to emulate an S3 Trio 64 card with 2 MB + - VESA 2.0 support for some 256 color modes + - rewrote large piece of video bios code for better compatibility + - added support for the not inheritance flags. + - created functions for creating child psp. + - updated errorcodes of findfirst (thanks Mirek!) + - rewrote loggingsystem to generate less warnings + - added dos protected mode interface (dpmi) + - added cdrom label support + - improved cdrom audio playing + - fixed and improved directory cache + - debugger shows selector- and cpu mode info + - added SELINFO (selector information) command to debugger + - added reference counting for dos files + - added tab-completion + - added basic fpu support. + - fixed several bugs with case sensitive filesystems. + - added more shell commands and improved their behaviour. + - mouse improvements. + - real time clock improvements. + - DMA fixes. + - Improved .BAT file support. + 0.58 - fixed date and time issues with fcbs - added more commands to the internal Shell diff --git a/README b/README index 1369451..4a7d377 100644 --- a/README +++ b/README @@ -1,97 +1,173 @@ -DOSBox v0.58 +DOSBox v0.60 +===== +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 +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. + +====== Usage: ====== -With the new internal shell,we've changed the command line a bit, -so let's just give some examples of what you can do now. +dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] + [-lang languagefile] -dosbox - With nothing on the command line you'll end up on the internal drive and - from there you can mount directories as drives. -dosbox [filename/directory] - If dosbox detects a directory it'll mount that as the C: drive - and then start the shell from c:\. - If dosbox doesn't detect a directory it'll assume you mean an executable. - This can be .bat .com .exe. Doesn't need to have extension included. - It will mount the directory the file is in as the C: drive. - Then start up the shell which will start the file. + name + If "name" is a directory it'll mount that as the C: drive. + If "name" is an executable it'll mount the directory of "name" + as the C: drive and execute "name". + + -exit + dosbox will exit after the "name" has been executed. -There also are a couple of command line switches. + -c command + Runs the specified command before running "name". Multiple commands + can be specified. Each command should start with -c though. -dosbox -fullscreen - starts dosbox in fullscreen mode. -dosbox -conf file - loads file as a configfile. -dosbox -lang file - loads file as a languagefile. + -fullscreen + Starts dosbox in fullscreen mode. -You can also add commands to be executed before the main program starts. -Or you can use them to start the program. -To add commands use the -c command line switch. + -conf configfile + Start dosbox with the options specified in "configfile". + + -lang languagefile + Start dosbox using the language string specified in "languagefile". + + -noconsole (Windows Only) + Start dosbox without showing the console window, output will + be redirected to stdout.txt and stderr.txt + +Note: If a name/command/configfile/languagefile contains a space in it, put + the whole name/command/configfile/languagefile between quotes("example"). For example: dosbox c:\atlantis\atlantis.exe -c "MOUNT D C:\SAVES" - This would mount c:\atlanis as c:\ and run atlantis.exe. + This would mount c:\atlantis as c:\ and run atlantis.exe. Before it does that it would first mount C:\SAVES as the D drive. -In Windows you can also drag directories/files on the dosbox executable. +In Windows you can also drag directories/files onto the dosbox executable. + + +================== Internal Programs: ================== -MOUNT -Program to mount local directories as drives inside DOSBox. -The option -t specifies the media: Where can be. - dir = harddisk - floppy = floppy drive - cdrom = cdrom drive +dosbox supports most of the DOS commands found in command.com. +In addition, the following commands are available: -The option -cd lists all found cdrom drives and their id. -The option -usecd [x] forces to use the cdrom number x (id as shown in list -cd) +MOUNT "Emulated Drive letter" "Real Drive or Directory" + [-t type] [-aspi] [-ioctl] [-usecd number] [-size drivesize] + [-label drivelabel] +MOUNT -cd + + Program to mount local directories as drives inside DOSBox. -The option -aspi forces to use aspi driver - (only valid if mounting a cdrom and on Windows systems with ASPI-Layer). -The option -ioctl forces to use ioctl functions - (only valid if mounting a cdrom and on Win2000/XP/NT systems). + "Emulated Drive letter" + The driveletter inside dosbox (eg. C). -For example to mount c:\floppy as a floppy : mount a c:\floppy -t floppy -For example to mount system cdrom drive e as cdrom drive d in dosbox - mount d e:\ -t cdrom -For example to mount system cdrom drive at mountpoint /media/cdrom as cdrom -drive d in dosbox - mount d /media/cdrom -t cdrom -usecd 0 + "Real Drive letter or Directory" + The local directory you want to have inside dosbox. + (Under Win32 usually the same as "Emulated Drive letter". + For Example: mount c c:\ ) -It is also possible to mount a directory as cdrom, but it's limited. + -t type + Type of the mounted directory. Supported are: dir (standard), + floppy, cdrom. + + -size drivesize + Sets the size of the drive. + + -label drivelabel + Sets the name of the drive to "drivelabel". Needed on some + systems if the cd label isn't read correctly. Useful when a + program can't find its cdrom. + + -aspi + Forces to use the aspi layer. Only valid if mounting a cdrom under + Windows systems with an ASPI-Layer. + + -ioctl + Forces to use ioctl commands. Only valid if mounting a cdrom under + windows which support them (Win2000/XP/NT). + + -usecd number + Forces to use SDL cdrom support for drive number. + Number can be found by -cd. Valid on all systems. + + -cd + Displays all detected cdrom drives and their numbers. Use with -usecd. + + 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 + 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 + 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. + + + General MOUNT Examples: + 1. To mount c:\floppy as a floppy : + mount a c:\floppy -t floppy + 2. To mount system cdrom drive E as cdrom drive D in dosbox: + mount d e:\ -t cdrom + 3. To mount system cdrom drive at mountpoint /media/cdrom as cdrom drive D + in dosbox: + mount d /media/cdrom -t cdrom -usecd 0 + 4. To mount a drive with 870 mb free diskspace (rarely needed! experts only): + mount c d:\ -size 4025,127,16513,1700 + 5. to mount /home/dos/dosgames as drive C in dosbox: + mount c /home/dos/dosgames MEM -Program to display the amount of free memory + Program to display the amount of free memory. -CONFIG -Utility for generating a config file and language file. -The option -writeconf filename is used to write the current config settings. -The option -writelang filename is used to write the current language strings. +CONFIG [-writeconf] [-writelang] localfile + Write the current configuration or language settings to file. + "localfile" is located on the local drive !!! -For more information use the the /? command line switch with the programs. +LOADFIX [-size] [program] [program-parameters] +LOADFIX -f + Program to "eat up" memory. Useful for old programs which don't expect much + memory to be free. -The Config File: -=============== -A config file can be generated by CONFIG.COM, edit it to customize DOSBox. -The file is divided in several sections (the names got [] around it). -Some sections have options which you can set. -# and % indicate commentlines. -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. + -size + number of kb to "eat up", default = 64kb + + -f + frees all previously allocated memory + -The Language File: -================= -A language file can be generated by CONFIG.COM. -Read it and you will hopefuly understand how to change it. -Start Dosbox with -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. +Examples: + 1. To start mm2.exe and allocate 64kb memory : + loadfix mm2 + 2. To start mm2.exe and allocate 32kb memory : + loadfix -32 mm2 + 3. To free previous allocated memory : + loadfix -f +For more information use the /? command line switch with the programs. + + + +============= Special Keys: ============= @@ -102,41 +178,27 @@ CTRL-F7 Decrease frameskip. CTRL-F8 Increase frameskip. CTRL-F9 Kill dosbox. CTRL-F10 Capture/Release the mouse. -CTRL-F11 Slowdown emulation. -CTRL-F12 Speedup emulation. +CTRL-F11 Slow down emulation (Decrease DOSBox Cycles). +CTRL-F12 Speed up emulation (Increase DOSox Cycles). +NOTE: Once you increase your DOSBox cycles beyond your computer's maximum +capacity, it will produce the same effect as slowing down the emulation. +This maximum will vary from computer to computer, there is no standard. + +==================== System requirements: ==================== -Fast machine my guess would be pentium-2 400+ to get decent emulation +Fast machine. My guess would be pentium-2 400+ to get decent emulation of games written for an 286 machine. - -FAQ: -==== - -Q: I've got a Z instead of a C at the prompt. -A: In DOSBox you can mount directories as drives - in win32: mount c D:\ would give you an C in DOSBox which points - at D:\ in win32 - in linux: mount c /home/username would give you and C in DOSBox - which points at /home/username in Linux - -Q: The mouse doesn't work. -A: Normally dosbox detects the mouse being used by a game, if you click on - the screen then it should get locked and work. - Sometimes the dosbox mouse detection doesn't work with certain games, you - might have to force to lock the mouse then with ctrl-f10. - -Q: The sound stutters. -A: Your 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. - - -For more questions check the site/forum. +For protected mode games a 1 Ghz machine is recommended and don't expect +them to run fast though!! Be sure to read the next section on how to speed +it up somewhat. +================================ To run resource-demanding games: -=============================== +================================ DOSBox emulates the CPU, the sound and graphic cards, and some other stuff, all at the same time. You can overclock DOSBox by using CTRL+F12, but @@ -164,12 +226,62 @@ You can also try to disable the sound through the setup utility of the game to further reduce load on your CPU. -Building your own Version DOSBox: -================================= +==== +FAQ: +==== -Dowload the source. +Q: I've got a Z instead of a C at the prompt. +A: In DOSBox you can mount directories as drives. + In win32: mount c D:\ would give you a C in DOSBox which points + at D:\ in win32. + In linux: mount c /home/username would give you a C in DOSBox + which points at /home/username in Linux. + +Q: The mouse doesn't work. +A: Normally dosbox detects the mouse being used by a game. If you click on + the screen then it should get locked and work. + Sometimes the dosbox mouse detection doesn't work with certain games. You + might have to force to lock the mouse then with ctrl-F10. + +Q: The sound stutters. +A: You're using too much cpu power to keep dosbox running at the current speed. + You can either lower the cycles or skip frames or get a faster machine. + + +For more questions check the site/forum: +http://dosbox.sourceforge.net + + +================ +The Config File: +================ + +A config file can be generated by CONFIG.COM. Edit it 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. +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. + +================== +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 +or you can setup the filename in the config file in the [dosbox] section. +There's a language= entry that can be changed with the filename. + + +==================================== +Building your own version of DOSBox: +==================================== + +Download the source. Check the INSTALL in the source distribution. +=============== Special Thanks: =============== @@ -179,8 +291,9 @@ The Bochs and DOSemu projects which I used for information. Freedos for ideas in making my shell. The Beta Testers. +======== Contact: ======== Harekiet harekiet@zophar.net -http://dosbox.zophar.net +http://dosbox.sourceforge.net diff --git a/acinclude.m4 b/acinclude.m4 index bdf2763..f0a8266 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -303,9 +303,6 @@ AC_SUBST(ALSA_CFLAGS) AC_SUBST(ALSA_LIBS) ]) - - - AH_TOP([ /* * Copyright (C) 2002-2003 The DOSBox Team @@ -326,8 +323,6 @@ AH_TOP([ */ ]) -AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures.]) - AH_BOTTOM([#define INLINE inline]) AH_BOTTOM([#if C_HAS_ATTRIBUTE @@ -336,18 +331,4 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE #define GCC_ATTRIBUTE(x) /* attribute not supported */ #endif]) -AH_BOTTOM([ -/* Enable some heavy debugging options */ -#define C_HEAVY_DEBUG 0 - -/* Enable some big compile-time increasing inlines */ -#define C_EXTRAINLINE 0 - -/* Enable the FPU module, still only for beta testing */ -#define C_FPU 0 - -/* Maximum memory address range in megabytes */ -#define C_MEM_MAX_SIZE 12 -]) - diff --git a/aclocal.m4 b/aclocal.m4 index 29c8c7b..47566a4 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# aclocal.m4 generated automatically by aclocal 1.6.3 -*- Autoconf -*- +# generated automatically by aclocal 1.7.7 -*- Autoconf -*- -# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -316,9 +316,6 @@ AC_SUBST(ALSA_CFLAGS) AC_SUBST(ALSA_LIBS) ]) - - - AH_TOP([ /* * Copyright (C) 2002-2003 The DOSBox Team @@ -339,8 +336,6 @@ AH_TOP([ */ ]) -AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures.]) - AH_BOTTOM([#define INLINE inline]) AH_BOTTOM([#if C_HAS_ATTRIBUTE @@ -349,20 +344,6 @@ AH_BOTTOM([#if C_HAS_ATTRIBUTE #define GCC_ATTRIBUTE(x) /* attribute not supported */ #endif]) -AH_BOTTOM([ -/* Enable some heavy debugging options */ -#define C_HEAVY_DEBUG 0 - -/* Enable some big compile-time increasing inlines */ -#define C_EXTRAINLINE 0 - -/* Enable the FPU module, still only for beta testing */ -#define C_FPU 0 - -/* Maximum memory address range in megabytes */ -#define C_MEM_MAX_SIZE 12 -]) - # Do all the work for Automake. -*- Autoconf -*- @@ -370,7 +351,7 @@ AH_BOTTOM([ # This macro actually does too much some checks are only needed if # your package does certain things. But this isn't really a big deal. -# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 # Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify @@ -388,16 +369,9 @@ AH_BOTTOM([ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. -# serial 8 +# serial 10 -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - -AC_PREREQ([2.52]) +AC_PREREQ([2.54]) # Autoconf 2.50 wants to disallow AM_ names. We explicitly allow # the ones we care about. @@ -423,6 +397,16 @@ if test "`cd $srcdir && pwd`" != "`pwd`" && AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], @@ -430,8 +414,8 @@ m4_ifval([$2], AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl - AC_SUBST([PACKAGE], [AC_PACKAGE_TARNAME])dnl - AC_SUBST([VERSION], [AC_PACKAGE_VERSION])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) @@ -452,19 +436,41 @@ AM_PROG_INSTALL_STRIP # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_][CC], +[AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_][CC], - defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_][CXX], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_][CXX], - defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl ]) ]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $1 | $1:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) + # Copyright 2002 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify @@ -485,14 +491,14 @@ AC_PROVIDE_IFELSE([AC_PROG_][CXX], # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. -AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.6"]) +AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.7"]) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # 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.6.3])]) + [AM_AUTOMAKE_VERSION([1.7.7])]) # Helper functions for option handling. -*- Autoconf -*- @@ -778,9 +784,42 @@ fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# serial 4 -*- Autoconf -*- +# -*- Autoconf -*- +# Copyright (C) 2003 Free Software Foundation, Inc. -# Copyright 1999, 2000, 2001 Free Software Foundation, Inc. +# 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, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 1 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# serial 5 -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. # 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 @@ -841,18 +880,32 @@ AC_CACHE_CHECK([dependency style of $depcc], # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. - echo '#include "conftest.h"' > conftest.c - echo 'int i;' > conftest.h - echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + : > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) @@ -870,13 +923,20 @@ AC_CACHE_CHECK([dependency style of $depcc], # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=conftest.c object=conftest.o \ - depfile=conftest.Po tmpdepfile=conftest.TPo \ - $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && - grep conftest.h conftest.Po > /dev/null 2>&1 && + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - am_cv_$1_dependencies_compiler_type=$depmode - break + # icc doesn't choke on unknown options, it will just issue warnings + # (even with -Werror). So we grep stderr for any message + # that says an option was ignored. + if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi fi done @@ -887,6 +947,9 @@ else fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) @@ -895,16 +958,8 @@ AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], -[rm -f .deps 2>/dev/null -mkdir .deps 2>/dev/null -if test -d .deps; then - DEPDIR=.deps -else - # MS-DOS does not allow filenames that begin with a dot. - DEPDIR=_deps -fi -rmdir .deps 2>/dev/null -AC_SUBST([DEPDIR]) +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) @@ -1006,7 +1061,9 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) -# Copyright 2001 Free Software Foundation, Inc. -*- Autoconf -*- +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. # 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 @@ -1031,8 +1088,9 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' -doit: +am__doit: @echo done +.PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) @@ -1046,7 +1104,7 @@ echo "include confinc" > confmf # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU @@ -1060,9 +1118,9 @@ if test "$am__include" = "#"; then _am_result=BSD fi fi -AC_SUBST(am__include) -AC_SUBST(am__quote) -AC_MSG_RESULT($_am_result) +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) @@ -1106,7 +1164,7 @@ else fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([conditional \"$1\" was never defined. + AC_MSG_ERROR([conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]) fi])]) @@ -1133,58 +1191,6 @@ AC_PREREQ([2.52]) # serial 6 -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. We must strip everything past the first ":", -# and everything past the last "/". - -# _AM_DIRNAME(PATH) -# ----------------- -# Like AS_DIRNAME, only do it during macro expansion -AC_DEFUN([_AM_DIRNAME], - [m4_if(regexp([$1], [^.*[^/]//*[^/][^/]*/*$]), -1, - m4_if(regexp([$1], [^//\([^/]\|$\)]), -1, - m4_if(regexp([$1], [^/.*]), -1, - [.], - patsubst([$1], [^\(/\).*], [\1])), - patsubst([$1], [^\(//\)\([^/].*\|$\)], [\1])), - patsubst([$1], [^\(.*[^/]\)//*[^/][^/]*/*$], [\1]))[]dnl -])# _AM_DIRNAME - - -# The stamp files are numbered to have different names. -# We could number them on a directory basis, but that's additional -# complications, let's have a unique counter. -m4_define([_AM_STAMP_Count], [0]) - - -# _AM_STAMP(HEADER) -# ----------------- -# The name of the stamp file for HEADER. -AC_DEFUN([_AM_STAMP], -[m4_define([_AM_STAMP_Count], m4_incr(_AM_STAMP_Count))dnl -AS_ESCAPE(_AM_DIRNAME(patsubst([$1], - [:.*])))/stamp-h[]_AM_STAMP_Count]) - - -# _AM_CONFIG_HEADER(HEADER[:SOURCES], COMMANDS, INIT-COMMANDS) -# ------------------------------------------------------------ -# We used to try to get a real timestamp in stamp-h. But the fear is that -# that will cause unnecessary cvs conflicts. -AC_DEFUN([_AM_CONFIG_HEADER], -[# Add the stamp file to the list of files AC keeps track of, -# along with our hook. -AC_CONFIG_HEADERS([$1], - [# update the timestamp -echo 'timestamp for $1' >"_AM_STAMP([$1])" -$2], - [$3]) -])# _AM_CONFIG_HEADER - - -# AM_CONFIG_HEADER(HEADER[:SOURCES]..., COMMANDS, INIT-COMMANDS) -# -------------------------------------------------------------- -AC_DEFUN([AM_CONFIG_HEADER], -[AC_FOREACH([_AM_File], [$1], [_AM_CONFIG_HEADER(_AM_File, [$2], [$3])]) -])# AM_CONFIG_HEADER +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) diff --git a/config.h.in b/config.h.in index 52bd4e0..c616d0d 100644 --- a/config.h.in +++ b/config.h.in @@ -20,15 +20,33 @@ */ +/* Define to 1 to use inlined memory functions in cpu core */ +#undef C_CORE_INLINE + /* Define to 1 to enable internal debugger, requires libcurses */ #undef C_DEBUG +/* Define to 1 to enable floating point emulation */ +#undef C_FPU + /* Determines if the compilers supports attributes for structures. */ #undef C_HAS_ATTRIBUTE +/* Define to 1 to enable heavy debugging, also have to enable C_DEBUG */ +#undef C_HEAVY_DEBUG + +/* Define to 1 to enable internal modem support, requires SDL_net */ +#undef C_MODEM + /* Define to 1 to enable screenshots, requires libpng */ #undef C_SSHOT +/* environ can be included */ +#undef ENVIRON_INCLUDED + +/* environ can be linked */ +#undef ENVIRON_LINKED + /* Define to 1 to use ALSA for MIDI */ #undef HAVE_ALSA @@ -113,17 +131,3 @@ #else #define GCC_ATTRIBUTE(x) /* attribute not supported */ #endif - - -/* Enable some heavy debugging options */ -#define C_HEAVY_DEBUG 0 - -/* Enable some big compile-time increasing inlines */ -#define C_EXTRAINLINE 0 - -/* Enable the FPU module, still only for beta testing */ -#define C_FPU 0 - -/* Maximum memory address range in megabytes */ -#define C_MEM_MAX_SIZE 12 - diff --git a/config.sub b/config.sub index 04baf3d..79657cd 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-01-03' +timestamp='2003-10-07' # 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,7 @@ 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* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -228,13 +228,14 @@ case $basic_machine in | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | clipper \ + | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ - | ip2k \ + | ip2k | iq2000 \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ @@ -247,6 +248,7 @@ case $basic_machine in | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ @@ -257,11 +259,11 @@ case $basic_machine in | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ - | tahoe | thumb | tic80 | tron \ + | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ @@ -296,7 +298,7 @@ case $basic_machine in | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ @@ -304,7 +306,7 @@ case $basic_machine in | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* \ + | ip2k-* | iq2000-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ @@ -319,6 +321,7 @@ case $basic_machine in | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ @@ -329,11 +332,13 @@ case $basic_machine in | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ + | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ @@ -371,6 +376,9 @@ case $basic_machine in basic_machine=a29k-none os=-bsd ;; + amd64) + basic_machine=x86_64-pc + ;; amdahl) basic_machine=580-amdahl os=-sysv @@ -766,18 +774,24 @@ case $basic_machine in pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; - pentiumii | pentium2) + pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; + pentium4) + basic_machine=i786-pc + ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - pentiumii-* | pentium2-*) + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; pn) basic_machine=pn-gould ;; @@ -836,6 +850,10 @@ case $basic_machine in sb1el) basic_machine=mipsisa64sb1el-unknown ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; sequent) basic_machine=i386-sequent ;; @@ -843,6 +861,9 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; + sh64) + basic_machine=sh64-unknown + ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks @@ -917,14 +938,18 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic4x | c4x*) - basic_machine=tic4x-unknown - os=-coff - ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; tx39) basic_machine=mipstx39-unknown ;; @@ -1027,7 +1052,7 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) + sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) @@ -1106,7 +1131,7 @@ case $os in | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -hiux* | -386bsd* | -knetbsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ @@ -1118,7 +1143,7 @@ case $os in | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -microbsd*) + | -powermax* | -dnix* | -nx6 | -nx7 | -sei*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1142,6 +1167,9 @@ case $os in -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; @@ -1227,6 +1255,12 @@ case $os in -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; -none) ;; *) @@ -1258,6 +1292,9 @@ case $basic_machine in arm*-semi) os=-aout ;; + c4x-* | tic4x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 diff --git a/configure b/configure index b38d92a..7311667 100644 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.57 for dosbox 0.58. +# Generated by GNU Autoconf 2.57 for dosbox 0.60. # # Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. @@ -266,8 +266,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='dosbox' PACKAGE_TARNAME='dosbox' -PACKAGE_VERSION='0.58' -PACKAGE_STRING='dosbox 0.58' +PACKAGE_VERSION='0.60' +PACKAGE_STRING='dosbox 0.60' PACKAGE_BUGREPORT='' ac_unique_file="README" @@ -308,7 +308,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE RANLIB ac_ct_RANLIB SDL_CONFIG SDL_CFLAGS SDL_LIBS EGREP ALSA_CFLAGS ALSA_LIBS LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE am__leading_dot CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE RANLIB ac_ct_RANLIB SDL_CONFIG SDL_CFLAGS SDL_LIBS EGREP ALSA_CFLAGS ALSA_LIBS LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -785,7 +785,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.58 to adapt to many kinds of systems. +\`configure' configures dosbox 0.60 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -852,7 +852,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of dosbox 0.58:";; + short | recursive ) echo "Configuration of dosbox 0.60:";; esac cat <<\_ACEOF @@ -864,7 +864,8 @@ Optional Features: --disable-sdltest Do not try to compile and run a test SDL program --disable-alsatest Do not try to compile and run a test Alsa program --enable-debug Enable debug mode - --enable-shots Enable screenshot support + --enable-core-inline Enable inlined memory handling in CPU Core + --disable-fpu Disable FPU support Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -943,14 +944,14 @@ ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi - cd $ac_popdir + cd "$ac_popdir" done fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -dosbox configure 0.58 +dosbox configure 0.60 generated by GNU Autoconf 2.57 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 @@ -965,7 +966,7 @@ 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.58, which was +It was created by dosbox $as_me 0.60, which was generated by GNU Autoconf 2.57. Invocation command line was $ $0 $@ @@ -1142,7 +1143,7 @@ _ASBOX echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 - rm -f core core.* *.core && + rm -f core *.core && rm -rf conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 @@ -1412,7 +1413,7 @@ test -n "$target_alias" && NONENONEs,x,x, && program_prefix=${target_alias}- -am__api_version="1.6" +am__api_version="1.7" # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -1631,6 +1632,15 @@ echo "${ECHO_T}no" >&6 SET_MAKE="MAKE=${MAKE-make}" fi +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then @@ -1639,9 +1649,19 @@ echo "$as_me: error: source directory already configured; run \"make distclean\" { (exit 1); exit 1; }; } fi +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + # Define the identity of the package. - PACKAGE=dosbox - VERSION=0.58 + PACKAGE='dosbox' + VERSION='0.60' cat >>confdefs.h <<_ACEOF @@ -1767,13 +1787,9 @@ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" -# Add the stamp file to the list of files AC keeps track of, -# along with our hook. ac_config_headers="$ac_config_headers config.h" - - 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_,'` @@ -2571,8 +2587,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then for ac_declaration in \ - ''\ - '#include ' \ + '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ @@ -2586,8 +2601,8 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include $ac_declaration +#include int main () { @@ -2670,24 +2685,16 @@ ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -rm -f .deps 2>/dev/null -mkdir .deps 2>/dev/null -if test -d .deps; then - DEPDIR=.deps -else - # MS-DOS does not allow filenames that begin with a dot. - DEPDIR=_deps -fi -rmdir .deps 2>/dev/null - +DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' -doit: +am__doit: @echo done +.PHONY: am__doit END # If we don't find an include directive, just comment out the code. echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 @@ -2702,7 +2709,7 @@ echo "include confinc" > confmf # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then +if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU @@ -2762,18 +2769,32 @@ else # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. - echo '#include "conftest.h"' > conftest.c - echo 'int i;' > conftest.h - echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + : > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) @@ -2791,13 +2812,20 @@ else # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=conftest.c object=conftest.o \ - depfile=conftest.Po tmpdepfile=conftest.TPo \ - $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && - grep conftest.h conftest.Po > /dev/null 2>&1 && + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - am_cv_CC_dependencies_compiler_type=$depmode - break + # icc doesn't choke on unknown options, it will just issue warnings + # (even with -Werror). So we grep stderr for any message + # that says an option was ignored. + if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi fi done @@ -2813,6 +2841,18 @@ echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -3273,8 +3313,7 @@ else fi fi for ac_declaration in \ - ''\ - '#include ' \ + '' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ @@ -3288,8 +3327,8 @@ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include $ac_declaration +#include int main () { @@ -3385,18 +3424,32 @@ else # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. - echo '#include "conftest.h"' > conftest.c - echo 'int i;' > conftest.h - echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + : > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) @@ -3414,13 +3467,20 @@ else # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ - source=conftest.c object=conftest.o \ - depfile=conftest.Po tmpdepfile=conftest.TPo \ - $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && - grep conftest.h conftest.Po > /dev/null 2>&1 && + source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - am_cv_CXX_dependencies_compiler_type=$depmode - break + # icc doesn't choke on unknown options, it will just issue warnings + # (even with -Werror). So we grep stderr for any message + # that says an option was ignored. + if grep 'ignoring option' conftest.err >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi fi done @@ -3436,6 +3496,18 @@ echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + +if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -3784,7 +3856,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) no_sdl=yes fi -rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" @@ -4196,7 +4268,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi -rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi @@ -4386,7 +4458,100 @@ 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 +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +int +main () +{ +*environ; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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 + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; +cat >>confdefs.h <<\_ACEOF +#define ENVIRON_INCLUDED 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +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 +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 +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +extern char ** environ; +int +main () +{ +*environ; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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 + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; +cat >>confdefs.h <<\_ACEOF +#define ENVIRON_LINKED 1 +_ACEOF + +else + echo "$as_me: failed program was:" >&5 +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 + + #Check if the compiler support attributes + + 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 @@ -4861,7 +5026,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_c_bigendian=yes fi -rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +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 @@ -4889,6 +5054,8 @@ esac #Features to enable/disable + + # Check whether --enable-debug or --disable-debug was given. if test "${enable_debug+set}" = set; then enableval="$enable_debug" @@ -5085,27 +5252,139 @@ if test $ac_cv_lib_curses_initscr = yes; then have_curses_lib=yes fi + echo "$as_me:$LINENO: checking for initscr in -lpdcurses" >&5 +echo $ECHO_N "checking for initscr in -lpdcurses... $ECHO_C" >&6 +if test "${ac_cv_lib_pdcurses_initscr+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char initscr (); +int +main () +{ +initscr (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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_pdcurses_initscr=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_pdcurses_initscr=no +fi +rm -f 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 +echo "${ECHO_T}$ac_cv_lib_pdcurses_initscr" >&6 +if test $ac_cv_lib_pdcurses_initscr = yes; then + have_pdcurses_lib=yes +fi + if test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then - LIBS="$LIBS -lcurses" + LIBS="$LIBS -lcurses" cat >>confdefs.h <<\_ACEOF #define C_DEBUG 1 _ACEOF + if test x$enable_debug = xheavy ; then + cat >>confdefs.h <<\_ACEOF +#define C_HEAVY_DEBUG 1 +_ACEOF + + fi + elif test x$have_pdcurses_lib = xyes -a x$have_curses_h = xyes ; then + LIBS="$LIBS -lpdcurses" + cat >>confdefs.h <<\_ACEOF +#define C_DEBUG 1 +_ACEOF + + if test x$enable_debug = xheavy ; then + cat >>confdefs.h <<\_ACEOF +#define C_HEAVY_DEBUG 1 +_ACEOF + + fi else - { echo "$as_me:$LINENO: WARNING: Can't enable debug mode without libcurses" >&5 -echo "$as_me: WARNING: Can't enable debug mode without libcurses" >&2;} + { echo "$as_me:$LINENO: WARNING: Can't find curses, debug mode disabled" >&5 +echo "$as_me: WARNING: Can't find curses, debug mode disabled" >&2;} fi fi; -# Check whether --enable-shots or --disable-shots was given. -if test "${enable_shots+set}" = set; then - enableval="$enable_shots" +# Check whether --enable-core-inline or --disable-core-inline was given. +if test "${enable_core_inline+set}" = set; then + enableval="$enable_core_inline" - if test "${ac_cv_header_png_h+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, + cat >>confdefs.h <<\_ACEOF +#define C_CORE_INLINE 1 +_ACEOF + + 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 + cat >>confdefs.h <<\_ACEOF +#define C_FPU 1 +_ACEOF + +fi; + + + +if test "${ac_cv_header_png_h+set}" = set; then echo "$as_me:$LINENO: checking for png.h" >&5 echo $ECHO_N "checking for png.h... $ECHO_C" >&6 if test "${ac_cv_header_png_h+set}" = set; then @@ -5239,7 +5518,7 @@ if test $ac_cv_header_png_h = yes; then fi - echo "$as_me:$LINENO: checking for png_check_sig in -lpng" >&5 +echo "$as_me:$LINENO: checking for png_check_sig in -lpng" >&5 echo $ECHO_N "checking for png_check_sig in -lpng... $ECHO_C" >&6 if test "${ac_cv_lib_png_png_check_sig+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -5297,18 +5576,222 @@ if test $ac_cv_lib_png_png_check_sig = yes; then have_png_lib=yes fi - if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then - LIBS="$LIBS -lpng -lz" - cat >>confdefs.h <<\_ACEOF +if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then + LIBS="$LIBS -lpng -lz" + cat >>confdefs.h <<\_ACEOF #define C_SSHOT 1 _ACEOF - else - { echo "$as_me:$LINENO: WARNING: Can't enable screenshots without libpng" >&5 -echo "$as_me: WARNING: Can't enable screenshots without libpng" >&2;} - fi +else + { echo "$as_me:$LINENO: WARNING: Can't find libpng, screenshot support disabled" >&5 +echo "$as_me: WARNING: Can't find libpng, screenshot support disabled" >&2;} +fi + + + +if test "${ac_cv_header_SDL_SDL_net_h+set}" = set; then + echo "$as_me:$LINENO: checking for SDL/SDL_net.h" >&5 +echo $ECHO_N "checking for SDL/SDL_net.h... $ECHO_C" >&6 +if test "${ac_cv_header_SDL_SDL_net_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_net_h" >&5 +echo "${ECHO_T}$ac_cv_header_SDL_SDL_net_h" >&6 +else + # Is the header compilable? +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 +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>&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.$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 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 +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 + 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 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 + ;; + 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: 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 + ;; +esac +echo "$as_me:$LINENO: checking for SDL/SDL_net.h" >&5 +echo $ECHO_N "checking for SDL/SDL_net.h... $ECHO_C" >&6 +if test "${ac_cv_header_SDL_SDL_net_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_SDL_SDL_net_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_SDL_SDL_net_h" >&5 +echo "${ECHO_T}$ac_cv_header_SDL_SDL_net_h" >&6 + +fi +if test $ac_cv_header_SDL_SDL_net_h = yes; then + have_sdl_net_h=yes +fi + + +echo "$as_me:$LINENO: checking for SDLNet_Init in -lSDL_net" >&5 +echo $ECHO_N "checking for SDLNet_Init in -lSDL_net... $ECHO_C" >&6 +if test "${ac_cv_lib_SDL_net_SDLNet_Init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&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 +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char SDLNet_Init (); +int +main () +{ +SDLNet_Init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 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_SDL_net_SDLNet_Init=yes +else + echo "$as_me: failed program was:" >&5 +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 +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_net_SDLNet_Init" >&5 +echo "${ECHO_T}$ac_cv_lib_SDL_net_SDLNet_Init" >&6 +if test $ac_cv_lib_SDL_net_SDLNet_Init = yes; then + have_sdl_net_lib=yes +fi + +if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then + LIBS="$LIBS -lSDL_net" + cat >>confdefs.h <<\_ACEOF +#define C_MODEM 1 +_ACEOF + +else + { echo "$as_me:$LINENO: WARNING: Can't find SDL_net, internal modem disabled" >&5 +echo "$as_me: WARNING: Can't find SDL_net, internal modem disabled" >&2;} +fi -fi; case "$target" in *-*-cygwin* | *-*-mingw32*) @@ -5325,7 +5808,7 @@ _ACEOF esac - ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_16/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_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" 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 @@ -5424,6 +5907,20 @@ echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files @@ -5693,7 +6190,7 @@ _ASBOX } >&5 cat >&5 <<_CSEOF -This file was extended by dosbox $as_me 0.58, which was +This file was extended by dosbox $as_me 0.60, which was generated by GNU Autoconf 2.57. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5756,7 +6253,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -dosbox config.status 0.58 +dosbox config.status 0.60 configured by $0, generated by GNU Autoconf 2.57, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" @@ -5871,6 +6368,8 @@ do "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/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" ;; @@ -5986,6 +6485,7 @@ s,@target_os@,$target_os,;t t s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@CYGPATH_W@,$CYGPATH_W,;t t s,@PACKAGE@,$PACKAGE,;t t s,@VERSION@,$VERSION,;t t s,@ACLOCAL@,$ACLOCAL,;t t @@ -6000,6 +6500,7 @@ s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t s,@AWK@,$AWK,;t t s,@SET_MAKE@,$SET_MAKE,;t t +s,@am__leading_dot@,$am__leading_dot,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t s,@LDFLAGS@,$LDFLAGS,;t t @@ -6014,11 +6515,15 @@ s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t s,@CCDEPMODE@,$CCDEPMODE,;t t +s,@am__fastdepCC_TRUE@,$am__fastdepCC_TRUE,;t t +s,@am__fastdepCC_FALSE@,$am__fastdepCC_FALSE,;t t s,@CPP@,$CPP,;t t s,@CXX@,$CXX,;t t s,@CXXFLAGS@,$CXXFLAGS,;t t s,@ac_ct_CXX@,$ac_ct_CXX,;t t s,@CXXDEPMODE@,$CXXDEPMODE,;t t +s,@am__fastdepCXX_TRUE@,$am__fastdepCXX_TRUE,;t t +s,@am__fastdepCXX_FALSE@,$am__fastdepCXX_FALSE,;t t s,@RANLIB@,$RANLIB,;t t s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@SDL_CONFIG@,$SDL_CONFIG,;t t @@ -6454,13 +6959,29 @@ echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} cat $tmp/config.h rm -f $tmp/config.h fi - # Run the commands associated with the file. - case $ac_file in - config.h ) # update the timestamp -echo 'timestamp for config.h' >"./stamp-h1" - ;; +# Compute $ac_file's index in $config_headers. +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $ac_file | $ac_file:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac 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 || +echo X$ac_file | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'`/stamp-h$_am_stamp_count +done _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF diff --git a/configure.in b/configure.in index adb4ad8..305dc4c 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Init. -AC_INIT(dosbox,0.58) +AC_INIT(dosbox,0.60) AC_PREREQ(2.50) AC_CONFIG_SRCDIR(README) @@ -36,9 +36,19 @@ AC_C_INLINE AC_TYPE_SIZE_T AC_STRUCT_TM + +AC_MSG_CHECKING(if environ can be included) +AC_TRY_LINK([#include +#include ],[*environ;], +[AC_MSG_RESULT(yes);AC_DEFINE(ENVIRON_INCLUDED,1,[environ can be included])],AC_MSG_RESULT(no)) +AC_MSG_CHECKING(if environ can be linked) +AC_TRY_LINK([extern char ** environ;],[*environ;], +[AC_MSG_RESULT(yes);AC_DEFINE(ENVIRON_LINKED,1,[environ can be linked])],AC_MSG_RESULT(no)) + dnl Checks for libraries. #Check if the compiler support attributes +AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures.]) AC_MSG_CHECKING(if compiler allows __attribute__) AC_TRY_COMPILE([], [typedef struct { } __attribute__ ((packed)) junk;], [ AC_MSG_RESULT(yes);AC_DEFINE(C_HAS_ATTRIBUTE)],AC_MSG_RESULT(no)) @@ -50,30 +60,67 @@ AC_C_BIGENDIAN #Features to enable/disable AH_TEMPLATE(C_DEBUG,[Define to 1 to enable internal debugger, requires libcurses]) -AC_ARG_ENABLE(debug,[ --enable-debug Enable debug mode],[ +AH_TEMPLATE(C_HEAVY_DEBUG,[Define to 1 to enable heavy debugging, also have to enable C_DEBUG]) +AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],[Enable debug mode]),[ AC_CHECK_HEADER(curses.h,have_curses_h=yes,) AC_CHECK_LIB(curses, initscr, have_curses_lib=yes, , ) + AC_CHECK_LIB(pdcurses, initscr, have_pdcurses_lib=yes, , ) if test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then - LIBS="$LIBS -lcurses" + LIBS="$LIBS -lcurses" AC_DEFINE(C_DEBUG,1) + if test x$enable_debug = xheavy ; then + AC_DEFINE(C_HEAVY_DEBUG,1) + fi + elif test x$have_pdcurses_lib = xyes -a x$have_curses_h = xyes ; then + LIBS="$LIBS -lpdcurses" + AC_DEFINE(C_DEBUG,1) + if test x$enable_debug = xheavy ; then + AC_DEFINE(C_HEAVY_DEBUG,1) + fi else - AC_MSG_WARN([Can't enable debug mode without libcurses]) + AC_MSG_WARN([Can't find curses, debug mode disabled]) fi ],) -AH_TEMPLATE(C_SSHOT,[Define to 1 to enable screenshots, requires libpng]) -AC_ARG_ENABLE(shots,[ --enable-shots Enable screenshot support],[ - AC_CHECK_HEADER(png.h,have_png_h=yes,) - AC_CHECK_LIB(png, png_check_sig, have_png_lib=yes, ,-lz) - if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then - LIBS="$LIBS -lpng -lz" - AC_DEFINE(C_SSHOT,1) - else - AC_MSG_WARN([Can't enable screenshots without libpng]) +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_DEFINE(C_CORE_INLINE,1) 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)) + +AH_TEMPLATE(C_SSHOT,[Define to 1 to enable screenshots, requires libpng]) +AC_CHECK_HEADER(png.h,have_png_h=yes,) +AC_CHECK_LIB(png, png_check_sig, have_png_lib=yes, ,-lz) +if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then + LIBS="$LIBS -lpng -lz" + AC_DEFINE(C_SSHOT,1) +else + AC_MSG_WARN([Can't find libpng, screenshot support disabled]) +fi + +AH_TEMPLATE(C_MODEM,[Define to 1 to enable internal modem support, requires SDL_net]) +AC_CHECK_HEADER(SDL/SDL_net.h,have_sdl_net_h=yes,) +AC_CHECK_LIB(SDL_net, SDLNet_Init, have_sdl_net_lib=yes, , ) +if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then + LIBS="$LIBS -lSDL_net" + AC_DEFINE(C_MODEM,1) +else + AC_MSG_WARN([Can't find SDL_net, internal modem disabled]) +fi + + dnl Some host detection and actions for them case "$target" in *-*-cygwin* | *-*-mingw32*) @@ -95,6 +142,8 @@ 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 diff --git a/depcomp b/depcomp index 807b991..edb5d38 100644 --- a/depcomp +++ b/depcomp @@ -1,7 +1,7 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -# Copyright 1999, 2000 Free Software Foundation, Inc. +# Copyright 1999, 2000, 2003 Free Software Foundation, Inc. # 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 @@ -172,19 +172,25 @@ sgi) aix) # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. This file always lives in the current directory. - # Also, the AIX compiler puts `$object:' at the start of each line; - # $object doesn't have directory information. - stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" - outname="$stripped.o" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi - stat=$? + + if test -f "$tmpdepfile"; then : + else + stripped=`echo "$stripped" | sed 's,^.*/,,'` + tmpdepfile="$stripped.u" + fi + if test $stat -eq 0; then : else rm -f "$tmpdepfile" @@ -192,6 +198,7 @@ aix) fi if test -f "$tmpdepfile"; then + outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. @@ -206,6 +213,44 @@ aix) rm -f "$tmpdepfile" ;; +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. @@ -240,8 +285,8 @@ tru64) fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a space and a tab in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi @@ -254,7 +299,7 @@ tru64) dashmstdout) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o. + # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. @@ -265,9 +310,7 @@ dashmstdout) shift fi - # Remove `-o $object'. We will use -o /dev/null later, - # however we can't do the remplacement now because - # `-o $object' might simply not be used + # Remove `-o $object'. IFS=" " for arg do @@ -287,7 +330,11 @@ dashmstdout) done test -z "$dashmflag" && dashmflag=-M - "$@" -o /dev/null $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' @@ -306,6 +353,13 @@ dashXmstdout) makedepend) "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi # X makedepend shift cleared=no @@ -318,7 +372,9 @@ makedepend) case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; - -*) + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; @@ -339,7 +395,7 @@ makedepend) cpp) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout. + # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. @@ -381,7 +437,7 @@ cpp) msvisualcpp) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, + # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " diff --git a/docs/Makefile.in b/docs/Makefile.in index d81d2dc..ca0b56c 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -15,81 +15,127 @@ @SET_MAKE@ # Main Makefile for DOSBox -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ man_MANS = dosbox.1 EXTRA_DIST = $(man_MANS) subdir = docs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -97,7 +143,7 @@ DIST_SOURCES = NROFF = nroff MANS = $(man_MANS) -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am all: all-am .SUFFIXES: @@ -144,6 +190,10 @@ uninstall-man1: done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 1*) ;; \ + *) ext='1' ;; \ + esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ @@ -153,13 +203,22 @@ uninstall-man1: tags: TAGS TAGS: +ctags: CTAGS +CTAGS: + DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -185,7 +244,6 @@ all-am: Makefile $(MANS) installdirs: $(mkinstalldirs) $(DESTDIR)$(man1dir) - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -205,7 +263,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -215,6 +273,7 @@ clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am + -rm -f Makefile distclean-am: clean-am distclean-generic @@ -237,6 +296,7 @@ install-man: install-man1 installcheck-am: maintainer-clean: maintainer-clean-am + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -244,6 +304,14 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am uninstall-man uninstall-man: uninstall-man1 @@ -254,8 +322,8 @@ uninstall-man: uninstall-man1 install-exec-am install-info install-info-am install-man \ install-man1 install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic uninstall uninstall-am \ - uninstall-info-am uninstall-man uninstall-man1 + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ + uninstall-am uninstall-info-am uninstall-man uninstall-man1 # 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. diff --git a/docs/dosbox.1 b/docs/dosbox.1 index 805b853..a140290 100644 --- a/docs/dosbox.1 +++ b/docs/dosbox.1 @@ -1,59 +1,193 @@ .\" Hey, EMACS: -*- nroff -*- -.TH DOSBOX 1 "March 31, 2003" +.TH DOSBOX 1 "October 5, 2003" .\" Please adjust this date whenever revising the manpage. .SH NAME -dosbox \- an x86/DOS emulator with sound/graphics primarily for games +dosbox \- an x86/DOS emulator with sound/graphics .SH SYNOPSIS .B dosbox -[\fB-fullscreen\fR] -[\fB-conf\fR \fIconfigfile\fR] -[\fB-lang\fR \fIlangfile\fR] -[\fBfile\fR] -[\fB-c\fR \fIcommand1\fR <\fIcommand2\fR>...] -.br +.B [\-fullscreen] +.BI "[\-conf " configfile ] +.BI "[\-lang " langfile ] +.B [file] +.BI "[\-c " command ] +.B [\-exit] .SH DESCRIPTION This manual page briefly documents -\fBdosbox\fR, an x86/DOS emulator capable of running many games. +.BR "dosbox" ", an x86/DOS emulator." .TP -The optional \fBfile\fR argument should be a DOS executable or a directory. If it is a dos executable (.com .exe .bat) the program will run automatically. If it is a directory, a DOS session will run with the directory mounted as C:. +.RB "The optional " file " argument should be a DOS executable or a directory. If it is a dos executable (.com .exe .bat) the program will run automatically. If it is a directory, a DOS session will run with the directory mounted as C:." .SH OPTIONS A summary of options is included below. .TP -\fB-fullscreen\fR -Start DOSBox in fullscreen mode +.B \-fullscreen +.RB "Start " dosbox " in fullscreen mode." .TP -\fB-c\fR \fIcommand 1\fR [\fIcommand 2\fR] ... -Run one or more DOS commands after starting \fBdosbox\fR. If an executable is -also specified, these commands will be executed before running the program. +.BI \-c " command" +.RI "Runs the specified " command " before running " +.BR file . +.RI "Multiple commands can be specified. Each " command " should start with " +.BR \-c " though." .TP -\fB-conf\fR \fIconfigfile\fR -Start \fBdosbox\fR with the options specified in \fIconfigfile\fR +.BI \-conf " configfile +.RB "Start " dosbox " with the options specified in " +.IR configfile . .TP -\fB-lang\fR \fIlangfile\fR -Start \fBdosbox\fR with the language specified in \fIlangfile\fR -.SH INTERNAL COMMANDS +.BI \-lang " langfile +.RB "Start " dosbox " with the language specified in " +.IR langfile . +.TP +.B \-exit +.BR dosbox " will exit after running the program specified by " file . +.SH "INTERNAL COMMANDS" .B dosbox supports most of the DOS commands found in command.com. In addition, the following extra commands are available: +.HP +.BI "MOUNT [\-t " type "] [\-size " size ] +.I driveletter sourcedirectory +.B [\-aspi] [\-ioctl] +.BI "[\-usecd " number "] [\-label " drivelabel ] +.LP +.B MOUNT \-cd +.LP +.RB "Program to mount local directories as drives inside " dosbox . +.RS .TP -\fBMOUNT\fR [\fB-t\fR \fItype\fR] [\fB-size\fR \fIsize\fR] \fBdriveletter\fR \fBsourcedirectory\fR [\fB-aspi\fR] -Map \fBsourcedirectory\fR to \fBdriveletter\fR. -\fItype\fR may be \fIdir\fR for a hard drive, \fIfloppy\fR for a floppy -drive or \fIcdrom\fR for a cdrom. \fIsize\fR specifies the size of the volume. -You can force ASPI mode for a cdrom with \fB-aspi\fR. +.I driveletter +The driveletter inside dosbox (eg. C). .TP -\fBMEM\fR +.I sourcedirectory +The local directory you want to have inside dosbox. +.TP +.BI \-t " type" +Type of the mounted directory. Supported are: dir (standard), floppy, cdrom. +.TP +.BI \-size " drivesize" +Sets the size of the drive. +.TP +.BI \-label " drivelabel" +.RI "Sets the name of the drive to " drivelabel ". Needed on some" +systems if the cd label isn't read correctly. Useful when a +program can't find its cdrom. +.TP +.B \-aspi +Forces to use the aspi layer. Only valid if mounting a cdrom under +Windows systems with an ASPI-Layer. +.TP +.B \-ioctl +Forces to use ioctl commands. Only valid if mounting a cdrom under +windows which support them (Win2000/XP/NT). +.TP +.BI \-usecd " number" +Forces to use SDL cdrom support for drive number. +.IR Number " can be found by " +.BR \-cd ". Valid on all systems." +.TP +.B \-cd +.RB "Displays all detected cdrom drives and their numbers. Use with " \-usecd "." +.RE +.PP +.B "Example:" +.TP +.RB "To mount your /home/dos/dosgames directory as C drive in " dosbox : +.RS +mount c /home/dos/dosgames +.RE +.TP +.B MEM +.LP Display the amount of free memory .TP -\fBCONFIG\fR [\fB-writeconf\fR] [\fB-writelang\fR] \fBfile\fR -Write the current configuration or language settings to \fBfile\fR +.B CONFIG [\-writeconf] [\-writelang] file +.LP +.RB "Write the current configuration or language settings to " file , +which is located on the local filesystem. Not a mounted drive in +.BR dosbox . +.TP +.B LOADFIX [\-size] [programname] [parameters] +.LP +.B LOADFIX \-f +.LP +Program to eat up memory, Useful for old programs which don't expect much memory to be free. +.RS +.TP +.B [programname] +The name of the program which is executed after loadfix eats up its memory. +.TP +.B [parameters] +.RB "Parameters given to the " programname " executable." +.TP +.B \-size +The amount of memory to eat up (in kb). Example -32, -64 or -128 +.TP +.B \-f +Frees all memory eaten up by loadfix. +.RE .SH FILES Configuration and language files use a format similar to Windows .ini files. If a file named -\fBdosbox.conf\fR is found in the current directory, it will be automatically loaded. +.BR dosbox.conf " is found in the current directory, it will be automatically loaded." +.SH "SPECIAL KEYS" +.TP 12m +.IP ALT\-ENTER +Go full screen and back. +.IP CTRL\-F5 +Save a screenshot. +.IP CTRL\-F6 +Start/Stop recording sound output to a wave file. +.IP CTRL\-F7 +Decrease frameskip. +.IP CTRL\-F8 +Increase frameskip. +.IP CTRL\-F9 +Kill dosbox. +.IP CTRL\-F10 +Capture/Release the mouse. +.IP CTRL\-F11 +Slow down emulation (Increase DOSBox Cycles). +.IP CTRL\-F12 +Speed up emulation (Decrease DOSBox Cycles). +.PP +.B "Note: " +Once you increase your DOSBox cycles beyond your computer's maximum +capacity, it will produce the same effect as slowing down the emulation. +This maximum will vary from computer to computer, there is no standard. +.SH "SYSTEM REQUIREMENTS" +Fast machine. My guess would be pentium\-2 400+ to get decent emulation +of games written for an 286 machine. +For protected mode games a 1 Ghz machine is recommended and don't expect +them to run fast though!! Be sure to read the next section on how to speed +it up somewhat. +.SS "To run resource\-demanding games" +.BR dosbox " emulates the CPU, the sound and graphic cards, and some other" +.RB " stuff, all at the same time. You can overclock " dosbox " by using CTRL\-F12, but" +you'll be limited by the power of your actual CPU. You can see how much free +time your true CPU has by various utils (top). Once 100% of your real CPU time is +.RB "used there is no further way to speed up " dosbox " unless you reduce the load" +.RB "generated by the non\-CPU parts of " dosbox . +.PP +So: +.PP +.RB "Close every program but " dosbox . +.PP +.RB "Overclock " dosbox " until 100% of your CPU is used.(CTR\-+F12)" +.PP +.RB "Since VGA emulation is the most demanding part of " dosbox " in terms of actual" +CPU usage, we'll start here. Increase the number of frames skipped (in +increments of one) by pressing CRTL\-F8. Your CPU usage should decrease. +Go back one step and repeat this until the game runs fast enough for you. +Please note that this is a trade off: you lose in fluidity of video what you +gain in speed. +.SH NOTES +.RB "While we hope that, one day, " dosbox " will run virtually all programs ever made for the PC..." +.RB "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 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 +.RB "require a much faster processor for you to run it properly in " dosbox . .SH BUGS -Not all DOS programs work properly. Notably, any program that uses protected mode will not work at all. -DOSBox will exit without warning if an error occured. -.SH SEE ALSO +Not all DOS programs work properly. +.BR dosbox " will exit without warning if an error occured." +.SH "SEE ALSO" The README in /usr/share/doc/dosbox .SH AUTHOR This manual page was written by Peter Veenstra and James Oakley , diff --git a/include/Makefile.am b/include/Makefile.am index 4425e6e..d910b84 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -13,15 +13,18 @@ hardware.h \ inout.h \ joystick.h \ keyboard.h \ +logging.h \ mem.h \ mixer.h \ modules.h \ mouse.h \ +paging.h \ pic.h \ programs.h \ render.h \ regs.h \ render.h \ +serialport.h \ setup.h \ support.h \ timer.h \ diff --git a/include/Makefile.in b/include/Makefile.in index 23b4139..112a016 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,77 +13,122 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ noinst_HEADERS = \ bios.h \ callback.h \ @@ -99,28 +144,32 @@ hardware.h \ inout.h \ joystick.h \ keyboard.h \ +logging.h \ mem.h \ mixer.h \ modules.h \ mouse.h \ +paging.h \ pic.h \ programs.h \ render.h \ regs.h \ render.h \ +serialport.h \ setup.h \ support.h \ timer.h \ video.h subdir = include +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = HEADERS = $(noinst_HEADERS) -DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.in Makefile.am all: all-am .SUFFIXES: @@ -134,6 +183,9 @@ uninstall-info-am: ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -159,20 +211,41 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -197,7 +270,6 @@ check: check-am all-am: Makefile $(HEADERS) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -217,7 +289,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -227,6 +299,7 @@ clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am + -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags @@ -249,6 +322,7 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -256,16 +330,24 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am -.PHONY: GTAGS all all-am check check-am clean clean-generic distclean \ - distclean-generic distclean-tags distdir dvi dvi-am info \ - info-am install install-am install-data install-data-am \ +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic ctags \ + distclean distclean-generic distclean-tags distdir dvi dvi-am \ + info info-am install install-am install-data install-data-am \ install-exec install-exec-am install-info install-info-am \ install-man install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/include/callback.h b/include/callback.h index 065dd9b..9b083be 100644 --- a/include/callback.h +++ b/include/callback.h @@ -28,6 +28,7 @@ enum { CB_RETF,CB_IRET,CB_IRET_STI }; #define CB_MAX 1024 #define CB_SEG 0xC800 +#define CB_BASE (CB_SEG << 4) enum { CBRET_NONE=0,CBRET_STOP=1 @@ -47,6 +48,7 @@ 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_Free(Bitu callback); diff --git a/include/cpu.h b/include/cpu.h index f6f2281..40ea13f 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -23,64 +23,353 @@ #include "regs.h" #include "mem.h" -/* Some common Defines */ -/* A CPU Handler */ -typedef Bitu (CPU_Decoder)(void); -extern CPU_Decoder * cpudecoder; - /* CPU Cycle Timing */ extern Bits CPU_Cycles; extern Bits CPU_CycleLeft; extern Bits CPU_CycleMax; +/* Some common Defines */ +/* A CPU Handler */ +typedef Bits (CPU_Decoder)(void); +extern CPU_Decoder * cpudecoder; + + //CPU Stuff -void SetCPU16bit(); +void SetCPU16bit( ); -//Types of Flag changing instructions -enum { - t_ADDb=0,t_ADDw,t_ADDd, - t_ORb,t_ORw,t_ORd, - t_ADCb,t_ADCw,t_ADCd, - t_SBBb,t_SBBw,t_SBBd, - t_ANDb,t_ANDw,t_ANDd, - t_SUBb,t_SUBw,t_SUBd, - t_XORb,t_XORw,t_XORd, - t_CMPb,t_CMPw,t_CMPd, - t_INCb,t_INCw,t_INCd, - t_DECb,t_DECw,t_DECd, - t_TESTb,t_TESTw,t_TESTd, - t_SHLb,t_SHLw,t_SHLd, - t_SHRb,t_SHRw,t_SHRd, - t_SARb,t_SARw,t_SARd, - t_ROLb,t_ROLw,t_ROLd, - t_RORb,t_RORw,t_RORd, - 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, - t_UNKNOWN, - t_NOTDONE, +enum CODE_TYPE { + CODE_REAL, + CODE_PMODE16, + CODE_PMODE32, + CODE_INIT, }; -void Interrupt(Bit8u num); +extern bool parity_lookup[256]; -//Flag Handling -bool get_CF(void); -bool get_AF(void); -bool get_ZF(void); -bool get_SF(void); -bool get_OF(void); -bool get_PF(void); +void CPU_LLDT(Bitu selector); +void CPU_LTR(Bitu selector); +void CPU_LIDT(Bitu limit,Bitu base); +void CPU_LGDT(Bitu limit,Bitu base); -#define LoadCF flags.cf=get_CF(); -#define LoadZF flags.zf=get_ZF(); -#define LoadSF flags.sf=get_SF(); -#define LoadOF flags.of=get_OF(); +void CPU_STR(Bitu & selector); +void CPU_SLDT(Bitu & selector); +void CPU_SIDT(Bitu & limit,Bitu & base); +void CPU_SGDT(Bitu & limit,Bitu & base); +void CPU_ARPL(Bitu & dest_sel,Bitu src_sel); +void CPU_LAR(Bitu selector,Bitu & ar); +void CPU_LSL(Bitu selector,Bitu & limit); + +bool CPU_SET_CRX(Bitu cr,Bitu value); +Bitu CPU_GET_CRX(Bitu cr); + +void CPU_SMSW(Bitu & word); +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); + +bool Interrupt(Bitu num); +bool CPU_IRET(bool use32); +void CPU_SetSegGeneral(SegNames seg,Bitu value); + +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); +}; + + + +// ********************************************************************* +// Descriptor +// ********************************************************************* + +#define CR0_PROTECTION 0x00000001 +#define CR0_FPUENABLED 0x00000002 +#define CR0_FPUMONITOR 0x00000004 +#define CR0_TASKSWITCH 0x00000008 +#define CR0_FPUPRESENT 0x00000010 +#define CR0_PAGING 0x80000000 + + +#define DESC_INVALID 0x00 +#define DESC_286_TSS_A 0x01 +#define DESC_LDT 0x02 +#define DESC_286_TSS_B 0x03 +#define DESC_286_CALL_GATE 0x04 +#define DESC_TASK_GATE 0x05 +#define DESC_286_INT_GATE 0x06 +#define DESC_286_TRAP_GATE 0x07 + +#define DESC_386_TSS_A 0x09 +#define DESC_386_TSS_B 0x0b +#define DESC_386_CALL_GATE 0x0c +#define DESC_386_INT_GATE 0x0e +#define DESC_386_TRAP_GATE 0x0f + +/* EU/ED Expand UP/DOWN RO/RW Read Only/Read Write NA/A Accessed */ +#define DESC_DATA_EU_RO_NA 0x10 +#define DESC_DATA_EU_RO_A 0x11 +#define DESC_DATA_EU_RW_NA 0x12 +#define DESC_DATA_EU_RW_A 0x13 +#define DESC_DATA_ED_RO_NA 0x14 +#define DESC_DATA_ED_RO_A 0x15 +#define DESC_DATA_ED_RW_NA 0x16 +#define DESC_DATA_ED_RW_A 0x17 + +/* N/R Readable NC/C Confirming A/NA Accessed */ +#define DESC_CODE_N_NC_A 0x18 +#define DESC_CODE_N_NC_NA 0x19 +#define DESC_CODE_R_NC_A 0x1a +#define DESC_CODE_R_NC_NA 0x1b +#define DESC_CODE_N_C_A 0x1c +#define DESC_CODE_N_C_NA 0x1d +#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);; + +struct S_Descriptor { + Bit32u limit_0_15 :16; + Bit32u base_0_15 :16; + Bit32u base_16_23 :8; + Bit32u type :5; + Bit32u dpl :2; + Bit32u p :1; + Bit32u limit_16_19 :4; + Bit32u avl :1; + Bit32u r :1; + Bit32u big :1; + Bit32u g :1; + Bit32u base_24_31 :8; +}GCC_ATTRIBUTE(packed); + +struct G_Descriptor { + Bit32u offset_0_15 :16; + Bit32u selector :16; + Bit32u paramcount :5; + Bit32u reserved :3; + Bit32u type :5; + Bit32u dpl :2; + Bit32u p :1; + Bit32u offset_16_31 :16; +} 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 */ + Bit16u ss0; /* The CK stack selector */ + Bit16u ss1; /* The parent KL stack selector */ + Bit16u ss2; /* Unused */ + 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 */ +}; + +void CPU_ReadTaskSeg32(PhysPt base,TaskSegment_32 * seg); + +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; +}; + +class Descriptor +{ +public: + Descriptor() { saved.fill[0]=saved.fill[1]=0; } + + void Load(PhysPt address) { + Bit32u* data = (Bit32u*)&saved; + *data = mem_readd(address); + *(data+1) = mem_readd(address+4); + } + void Save(PhysPt address) { + Bit32u* data = (Bit32u*)&saved; + mem_writed(address,*data); + mem_writed(address+4,*(data+1)); + } + PhysPt GetBase (void) { + return (saved.seg.base_24_31<<24) | (saved.seg.base_16_23<<16) | saved.seg.base_0_15; + } + Bitu GetLimit (void) { + Bitu limit = (saved.seg.limit_16_19<<16) | saved.seg.limit_0_15; + if (saved.seg.g) return (limit<<12) | 0xFFF; + return limit; + } + Bitu GetOffset(void) { + return (saved.gate.offset_16_31 << 16) | saved.gate.offset_0_15; + } + Bitu GetSelector(void) { + return saved.gate.selector; + } + Bitu Type(void) { + return saved.seg.type; + } + Bitu Conforming(void) { + return saved.seg.type & 8; + } + Bitu DPL(void) { + return saved.seg.dpl; + } + Bitu Big(void) { + return saved.seg.big; + } +public: + union { + S_Descriptor seg; + G_Descriptor gate; + Bit32u fill[2]; + } saved; +}; + +class DescriptorTable { +public: + PhysPt GetBase (void) { return table_base; } + Bitu GetLimit (void) { return table_limit; } + void SetBase (PhysPt _base) { table_base = _base; } + void SetLimit (Bitu _limit) { table_limit= _limit; } + + bool GetDescriptor (Bitu selector, Descriptor& desc) { + selector&=~7; + if (selector>=table_limit) return false; + desc.Load(table_base+(selector)); + return true; + } +protected: + PhysPt table_base; + Bitu table_limit; +}; + +class GDTDescriptorTable : public DescriptorTable { +public: + bool GetDescriptor (Bitu selector, Descriptor& desc) { + Bitu address=selector & ~7; + if (selector & 4) { + if (address>=ldt_limit) return false; + desc.Load(ldt_base+address); + return true; + } else { + if (address>=table_limit) return false; + desc.Load(table_base+address); + return true; + } + } + + Bitu SLDT(void) { + return ldt_value; + } + bool LLDT(Bitu value) { +//TODO checking + Descriptor desc; + GetDescriptor(value,desc); + ldt_base=desc.GetBase(); + ldt_limit=desc.GetLimit(); + ldt_value=value; + return true; + } +private: + PhysPt ldt_base; + Bitu ldt_limit; + Bitu ldt_value; +}; + +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; +}; + +extern CPUBlock cpu; + #endif diff --git a/include/cross.h b/include/cross.h index 813ff25..730bdc8 100644 --- a/include/cross.h +++ b/include/cross.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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,9 +26,11 @@ #if defined (_MSC_VER) /* MS Visual C++ */ #include #include -#else /* LINUX */ +#define LONGTYPE(a) a##i64 +#else /* LINUX / GCC */ #include #include +#define LONGTYPE(a) a##LL #endif #define CROSS_LEN 512 /* Maximum filename size */ diff --git a/include/debug.h b/include/debug.h index de1d460..28f0297 100644 --- a/include/debug.h +++ b/include/debug.h @@ -25,6 +25,7 @@ void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off); bool DEBUG_ExitLoop(void); extern Bitu cycle_count; +extern Bitu debugCallback; #ifdef C_HEAVY_DEBUG bool DEBUG_HeavyIsBreakpoint(void); diff --git a/include/dos_inc.h b/include/dos_inc.h index 1c4036b..43ba1d1 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -22,14 +22,16 @@ #include #include +#ifdef _MSC_VER #pragma pack (1) +#endif struct CommandTail{ Bit8u count; /* number of bytes returned */ char buffer[127]; /* the buffer itself */ } GCC_ATTRIBUTE(packed); - - +#ifdef _MSC_VER #pragma pack () +#endif struct DOS_Date { Bit16u year; @@ -95,6 +97,7 @@ bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate); /* Routines for Drive Class */ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry); +bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status); bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry); bool DOS_UnlinkFile(char * name); bool DOS_FindFirst(char *search,Bit16u attr); @@ -123,6 +126,7 @@ void DOS_SetupDevices(void); /* Execute and new process creation */ bool DOS_NewPSP(Bit16u pspseg,Bit16u size); +bool DOS_ChildPSP(Bit16u pspseg,Bit16u size); bool DOS_Execute(char * name,PhysPt block,Bit8u flags); bool DOS_Terminate(bool tsr); @@ -199,29 +203,31 @@ INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) { #define DOSERR_NOT_SAME_DEVICE 17 #define DOSERR_NO_MORE_FILES 18 + /* Remains some classes used to access certain things */ -#define sGet(s,m) GetIt(((s *)Phys2Host(pt))->m,(PhysPt)&(((s *)0)->m)) -#define sSave(s,m,val) SaveIt(((s *)Phys2Host(pt))->m,(PhysPt)&(((s *)0)->m),val) +#define sGet(s,m) GetIt(((s *)0)->m,(PhysPt)&(((s *)0)->m)) +#define sSave(s,m,val) SaveIt(((s *)0)->m,(PhysPt)&(((s *)0)->m),val) + class MemStruct { public: - INLINE Bit8u GetIt(Bit8u,PhysPt addr) { + INLINE Bit8u GetIt(Bit8u&,PhysPt addr) { return mem_readb(pt+addr); } - INLINE Bit16u GetIt(Bit16u,PhysPt addr) { + INLINE Bit16u GetIt(Bit16u&,PhysPt addr) { return mem_readw(pt+addr); } - INLINE Bit32u GetIt(Bit32u,PhysPt addr) { + INLINE Bit32u GetIt(Bit32u&,PhysPt addr) { return mem_readd(pt+addr); } - INLINE void SaveIt(Bit8u,PhysPt addr,Bit8u val) { + INLINE void SaveIt(Bit8u&,PhysPt addr,Bit8u val) { mem_writeb(pt+addr,val); } - INLINE void SaveIt(Bit16u,PhysPt addr,Bit16u val) { + INLINE void SaveIt(Bit16u&,PhysPt addr,Bit16u val) { mem_writew(pt+addr,val); } - INLINE void SaveIt(Bit32u,PhysPt addr,Bit32u val) { + INLINE void SaveIt(Bit32u&,PhysPt addr,Bit32u val) { mem_writed(pt+addr,val); } INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);} @@ -233,16 +239,16 @@ protected: class DOS_PSP :public MemStruct { public: - DOS_PSP (Bit16u segment) { SetPt(segment);seg=segment;psp=(sPSP *)HostMake(segment,0);}; + DOS_PSP (Bit16u segment) { SetPt(segment);seg=segment;}; void MakeNew (Bit16u memSize); - void CopyFileTable (DOS_PSP* srcpsp); + void CopyFileTable (DOS_PSP* srcpsp,bool createchildpsp); Bit16u FindFreeFileEntry (void); void CloseFiles (void); void SaveVectors (void); void RestoreVectors (void); void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); }; - Bit16u GetSize () { return sGet(sPSP,next_seg); }; + Bit16u GetSize (void) { return sGet(sPSP,next_seg); }; void SetDTA (RealPt ptdta) { sSave(sPSP,dta,ptdta); }; RealPt GetDTA (void) { return sGet(sPSP,dta); }; void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); }; @@ -261,9 +267,11 @@ public: void SetCommandTail (RealPt src); bool SetNumFiles (Bit16u fileNum); Bit16u FindEntryByHandle (Bit8u handle); - + private: + #ifdef _MSC_VER #pragma pack(1) + #endif struct sPSP { Bit8u exit[2]; /* CP/M-like exit poimt */ Bit16u next_seg; /* Segment of first byte beyond memory allocated or program */ @@ -289,9 +297,10 @@ private: Bit8u fill_4[4]; /* unused */ CommandTail cmdtail; } GCC_ATTRIBUTE(packed); - #pragma pack() + #ifdef _MSC_VER + #pragma pack() + #endif Bit16u seg; - sPSP* psp; public: static Bit16u rootpsp; }; @@ -302,7 +311,9 @@ public: void Clear(void); void LoadData(void); void SaveData(void); /* Save it as an exec block */ + #ifdef _MSC_VER #pragma pack (1) + #endif struct sOverlay { Bit16u loadseg; Bit16u relocation; @@ -315,7 +326,9 @@ public: RealPt initsssp; RealPt initcsip; }GCC_ATTRIBUTE(packed); + #ifdef _MSC_VER #pragma pack() + #endif sExec exec; sOverlay overlay; }; @@ -326,23 +339,31 @@ public: void SetLocation(Bit16u seg); void SetFirstMCB(Bit16u _first_mcb); void SetfirstFileTable(RealPt _first_table); + void SetBuffers(Bit16u x,Bit16u y); RealPt GetPointer (void); -private: + + #ifdef _MSC_VER #pragma pack(1) + #endif struct sDIB { - Bit8u stuff1[22]; // some stuff, hopefully never used.... - Bit16u firstMCB; // first memory control block - RealPt firstDPB; // first drive parameter block - RealPt firstFileTable; // first system file table - RealPt activeClock; // active clock device header - RealPt activeCon; // active console device header - Bit16u maxSectorLength; // maximum bytes per sector of any block device; - RealPt discInfoBuffer; // pointer to disc info buffer - RealPt curDirStructure; // pointer to current array of directory structure - RealPt fcbTable; // pointer to system FCB table + Bit8u stuff1[22]; // -0x18 some stuff, hopefully never used.... + Bit16u firstMCB; // -0x2 first memory control block + RealPt firstDPB; // 0x00 first drive parameter block + RealPt firstFileTable; // 0x04 first system file table + RealPt activeClock; // 0x08 active clock device header + RealPt activeCon; // 0x0c active console device header + Bit16u maxSectorLength; // 0x10 maximum bytes per sector of any block device; + RealPt discInfoBuffer; // 0x12 pointer to disc info buffer + RealPt curDirStructure; // 0x16 pointer to current array of directory structure + RealPt fcbTable; // 0x1a pointer to system FCB table + Bit8u stuff2[0x21]; // 0x1e more stuff + Bit16u buffers_x; // x in BUFFERS x,y + Bit16u buffers_y; // y in BUFFERS x,y // some more stuff, hopefully never used. } GCC_ATTRIBUTE(packed); + #ifdef _MSC_VER #pragma pack () + #endif Bit16u seg; }; @@ -360,7 +381,9 @@ public: void SetDirID(Bit16u entry) { sSave(sDTA,dirID,entry); }; Bit16u GetDirID(void) { return sGet(sDTA,dirID); }; private: + #ifdef _MSC_VER #pragma pack(1) + #endif struct sDTA { Bit8u sdrive; /* The Drive the search is taking place */ Bit8u sattr; /* The Attributes that need to be found */ @@ -374,7 +397,9 @@ private: Bit32u size; char name[DOS_NAMELENGTH_ASCII]; } GCC_ATTRIBUTE(packed); + #ifdef _MSC_VER #pragma pack() + #endif }; class DOS_FCB: public MemStruct { @@ -397,7 +422,9 @@ public: private: bool extended; PhysPt real_pt; + #ifdef _MSC_VER #pragma pack (1) + #endif struct sFCB { Bit8u drive; /* Drive number 0=default, 1=A, etc */ Bit8u filename[8]; /* Space padded name */ @@ -414,7 +441,9 @@ private: Bit8u cur_rec; /* Current record in current block */ Bit32u rndm; /* Current relative record number */ } GCC_ATTRIBUTE(packed); + #ifdef _MSC_VER #pragma pack () + #endif }; class DOS_MCB : public MemStruct{ @@ -429,7 +458,9 @@ public: Bit16u GetSize(void) { return sGet(sMCB,size);} Bit16u GetPSPSeg(void) { return sGet(sMCB,psp_segment);} private: + #ifdef _MSC_VER #pragma pack (1) + #endif struct sMCB { Bit8u type; Bit16u psp_segment; @@ -437,7 +468,9 @@ private: Bit8u unused[3]; Bit8u filename[8]; } GCC_ATTRIBUTE(packed); + #ifdef _MSC_VER #pragma pack () + #endif }; extern DOS_InfoBlock dos_infoblock;; diff --git a/include/dos_system.h b/include/dos_system.h index 0ea54ef..6407218 100644 --- a/include/dos_system.h +++ b/include/dos_system.h @@ -16,6 +16,8 @@ * 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 $ */ + #ifndef DOSSYSTEM_H_ #define DOSSYSTEM_H_ @@ -51,7 +53,7 @@ class DOS_DTA; class DOS_File { public: - DOS_File() { name=0; }; + DOS_File():flags(0) { name=0; refCtr = 0; }; virtual ~DOS_File(){}; virtual bool Read(Bit8u * data,Bit16u * size)=0; virtual bool Write(Bit8u * data,Bit16u * size)=0; @@ -62,12 +64,15 @@ public: virtual char* GetName(void) { return name; }; virtual bool IsOpen() { return open; }; virtual bool IsName(const char* _name) { if (!name) return false; return strcmp(name,_name)==0; }; + virtual void AddRef() { refCtr++; }; + virtual Bits RemoveRef() { return --refCtr; }; Bit8u type; Bit32u flags; Bit16u time; Bit16u date; Bit16u attr; Bit32u size; + Bits refCtr; bool open; char* name; /* Some Device Specific Stuff */ @@ -99,11 +104,16 @@ public: char* GetExpandName (const char* path); bool GetShortName (const char* fullname, char* shortname); + bool FindFirst (char* path, Bitu dtaAddress, Bitu& id); + bool FindNext (Bitu id, char* &result); + void CacheOut (const char* path, bool ignoreLastDir = false); void AddEntry (const char* path, bool checkExist = false); void DeleteEntry (const char* path, bool ignoreLastDir = false); void EmptyCache (void); + void SetLabel (const char* name); + char* GetLabel (void) { return label; }; class CFileInfo { public: @@ -111,7 +121,7 @@ public: for (Bit32u i=0; i fileList; std::vector longNameList; - std::vector outputList; }; private: bool RemoveTrailingDot (char* shortname); - Bit16s GetLongName (CFileInfo* info, char* shortname); + Bits GetLongName (CFileInfo* info, char* shortname); void CreateShortName (CFileInfo* dir, CFileInfo* info); Bit16u CreateShortNameID (CFileInfo* dir, const char* name); bool SetResult (CFileInfo* dir, char * &result, Bit16u entryNr); bool IsCachedIn (CFileInfo* dir); CFileInfo* FindDirInfo (const char* path, char* expandedPath); bool RemoveSpaces (char* str); - bool OpenDir (CFileInfo* dir, char* path, Bit16u& id); + bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id); void CreateEntry (CFileInfo* dir, const char* name); Bit16u GetFreeID (CFileInfo* dir); void Clear (void); - CFileInfo* dirBase; char dirPath [CROSS_LEN]; char basePath [CROSS_LEN]; @@ -154,7 +162,9 @@ private: CFileInfo* dirSearch [MAX_OPENDIRS]; char dirSearchName [MAX_OPENDIRS]; bool free [MAX_OPENDIRS]; + CFileInfo* dirFindFirst [MAX_OPENDIRS]; + char label [CROSS_LEN]; }; class DOS_No_Drive_Cache { @@ -182,6 +192,9 @@ public: Bit16u GetCurrentEntry (void) { return 0; }; void EmptyCache (void) {}; + + void SetLabel (const char* name) {}; + char* GetLabel (void) {return "";}; public: char basePath [CROSS_LEN]; @@ -215,7 +228,7 @@ public: DOS_Drive_Cache dirCache; }; -enum { OPEN_READ=0,OPEN_WRITE=1,OPEN_READWRITE=2 }; +enum { OPEN_READ=0,OPEN_WRITE=1,OPEN_READWRITE=2, DOS_NOT_INHERIT=128}; enum { DOS_SEEK_SET=0,DOS_SEEK_CUR=1,DOS_SEEK_END=2}; diff --git a/include/dosbox.h b/include/dosbox.h index 03205ec..4d7507f 100644 --- a/include/dosbox.h +++ b/include/dosbox.h @@ -22,8 +22,6 @@ void E_Exit(char * message,...); -void S_Warn(char * message,...); - void MSG_Add(const char*,const char*); //add messages to the internal langaugefile const char* MSG_Get(char const *); //get messages from the internal langaugafile @@ -61,27 +59,10 @@ void DOSBOX_Init(void); class Config; extern Config * control; -extern Bitu errorlevel; -#define LOG_MSG S_Warn - -enum LOG_TYPES { - LOG_ALL, - LOG_VGA, LOG_VGAGFX,LOG_VGAMISC,LOG_INT10, - LOG_SB,LOG_DMA, - LOG_FPU,LOG_CPU, - LOG_FCB,LOG_FILES,LOG_IOCTL,LOG_EXEC,LOG_DOSMISC, - LOG_PIT,LOG_KEYBOARD,LOG_PIC, - LOG_MOUSE,LOG_BIOS,LOG_GUI,LOG_MISC, - LOG_MAX,LOG_ERROR=0x80 -}; - -#if C_DEBUG -extern void DEBUG_ShowMsg(Bit32u msgmask, char * msg,...); -#define LOG DEBUG_ShowMsg -#else -#define LOG -#endif /* C_DEBUG */ +#ifndef __LOGGING_H_ +#include "logging.h" +#endif // the logging system. #endif /* __DOSBOX_H */ diff --git a/include/fpu.h b/include/fpu.h index d181a2a..a1bfb2e 100644 --- a/include/fpu.h +++ b/include/fpu.h @@ -38,13 +38,4 @@ void FPU_ESC6_EA(Bitu func,PhysPt ea); void FPU_ESC7_Normal(Bitu rm); void FPU_ESC7_EA(Bitu func,PhysPt ea); -#define FPU_ESC(code) { \ - Bit8u rm=Fetchb(); \ - if (rm>=0xc0) { \ - FPU_ESC ## code ## _Normal(rm); \ - } else { \ - GetEAa;FPU_ESC ## code ## _EA(rm,eaa); \ - } \ -} - #endif diff --git a/include/logging.h b/include/logging.h new file mode 100644 index 0000000..570bc7f --- /dev/null +++ b/include/logging.h @@ -0,0 +1,65 @@ +#ifndef __LOGGING_H_ +#define __LOGGING_H_ +enum LOG_TYPES { + LOG_ALL, + LOG_VGA, LOG_VGAGFX,LOG_VGAMISC,LOG_INT10, + LOG_SB,LOG_DMA, + LOG_FPU,LOG_CPU,LOG_PAGING, + LOG_FCB,LOG_FILES,LOG_IOCTL,LOG_EXEC,LOG_DOSMISC, + LOG_PIT,LOG_KEYBOARD,LOG_PIC, + LOG_MOUSE,LOG_BIOS,LOG_GUI,LOG_MISC, + LOG_IO, + LOG_MAX, +}; + +enum LOG_SEVERITIES { + LOG_NORMAL, + LOG_WARN, + LOG_ERROR, +}; + +#if C_DEBUG +class LOG +{ + LOG_TYPES d_type; + LOG_SEVERITIES d_severity; +public: + + LOG (LOG_TYPES type , LOG_SEVERITIES severity): + d_type(type), + d_severity(severity) + {} + void operator() (char* buf, ...); //../src/debug/debug_gui.cpp + +}; + +void DEBUG_ShowMsg(char * format,...); +#define LOG_MSG DEBUG_ShowMsg + +#else //C_DEBUG + +struct LOG +{ + LOG(LOG_TYPES type, LOG_SEVERITIES severity) { return;} + void operator()(char const* buf) { return;} + void operator()(char const* buf, double f1) { return;} + void operator()(char const* buf, double f1, double f2) { return;} + void operator()(char const* buf, double f1, double f2, double f3) { return;} + + void operator()(char const* buf, char const* s1) { return;} + void operator()(char const* buf, char const* s1, double f1) { return;} + void operator()(char const* buf, char const* s1, double f1,double f2) { return;} + void operator()(char const* buf, double f1, char const* s1) { return;} + + + +}; //add missing operators to here + //try to avoid anything smaller than bit32... +void GFX_ShowMsg(char * format,...); +#define LOG_MSG GFX_ShowMsg + +#endif //C_DEBUG + + +#endif //__LOGGING_H_ + diff --git a/include/mem.h b/include/mem.h index 19e3d30..509a441 100644 --- a/include/mem.h +++ b/include/mem.h @@ -26,34 +26,29 @@ typedef Bit32u PhysPt; typedef Bit8u * HostPt; typedef Bit32u RealPt; -typedef Bit8u (*MEMORY_ReadHandler)(PhysPt pt); -typedef void (*MEMORY_WriteHandler)(PhysPt pt,Bit8u val); +typedef Bits MemHandle; -#define PAGE_KB 16 -#define PAGE_SIZE (PAGE_KB*1024) -#define PAGE_SHIFT 14 -#define PAGE_COUNT(A) (A & ((1 << PAGE_SHIFT)-1) ? 1+(A >> PAGE_SHIFT) : (A >> PAGE_SHIFT) ) -#define MAX_PAGES PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024) +#define MEM_PAGESIZE 4096 -extern HostPt ReadHostTable[MAX_PAGES]; -extern HostPt WriteHostTable[MAX_PAGES]; -extern MEMORY_ReadHandler ReadHandlerTable[MAX_PAGES]; -extern MEMORY_WriteHandler WriteHandlerTable[MAX_PAGES]; +bool MEM_A20_Enabled(void); +void MEM_A20_Enable(bool enable); + +/* Memory management / EMS mapping */ +HostPt MEM_GetBlockPage(void); +Bitu MEM_FreeTotal(void); //Free 4 kb pages +Bitu MEM_FreeLargest(void); //Largest free 4 kb pages block +Bitu MEM_TotalPages(void); //Total amount of 4 kb pages +Bitu MEM_AllocatedPages(MemHandle handle); // amount of allocated pages of handle +MemHandle MEM_AllocatePages(Bitu pages,bool sequence); +PhysPt MEM_AllocatePage(void); +void MEM_ReleasePages(MemHandle handle); +bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence); +void MEM_MapPagesHandle(Bitu lin_page,MemHandle mem,Bitu mem_page,Bitu pages); +void MEM_MapPagesDirect(Bitu lin_page,Bitu phys_page,Bitu pages); +void MEM_UnmapPages(Bitu phys_page,Bitu pages); -INLINE Bit16u PAGES(Bit32u bytes) { - if ((bytes & 4095) == 0) return (Bit16u)(bytes>>12); - return (Bit16u)(1+(bytes>>12)); -} - - -void MEM_SetupPageHandlers(Bitu startpage,Bitu pages,MEMORY_ReadHandler read,MEMORY_WriteHandler write); -void MEM_ClearPageHandlers(Bitu startpage,Bitu pages); - -void MEM_SetupMapping(Bitu startpage,Bitu pages,void * data); -void MEM_ClearMapping(Bitu startpage,Bitu pages); - -extern HostPt memory; +MemHandle MEM_NextHandle(MemHandle handle); /* The folowing six functions are used everywhere in the end so these should be changed for @@ -75,16 +70,20 @@ INLINE void writeb(HostPt off,Bit8u val) { off[0]=val; }; INLINE void writew(HostPt off,Bit16u val) { - off[0]=(Bit8u)((val & 0x00ff)); - off[1]=(Bit8u)((val & 0xff00) >> 8); + off[0]=(Bit8u)(val); + off[1]=(Bit8u)(val >> 8); }; INLINE void writed(HostPt off,Bit32u val) { - off[0]=(Bit8u)((val & 0x000000ff)); - off[1]=(Bit8u)((val & 0x0000ff00) >> 8); - off[2]=(Bit8u)((val & 0x00ff0000) >> 16); - off[3]=(Bit8u)((val & 0xff000000) >> 24); + off[0]=(Bit8u)(val); + off[1]=(Bit8u)(val >> 8); + off[2]=(Bit8u)(val >> 16); + off[3]=(Bit8u)(val >> 24); }; +#define MLEB(_MLE_VAL_) (_MLE_VAL_) +#define MLEW(_MLE_VAL_) ((_MLE_VAL_ >> 8) | (_MLE_VAL_ << 8)) +#define MLED(_MLE_VAL_) ((_MLE_VAL_ >> 24)|((_MLE_VAL_ >> 8)&0xFF00)|((_MLE_VAL_ << 8)&0xFF0000)|((_MLE_VAL_ << 24)&0xFF000000)) + #else INLINE Bit8u readb(HostPt off) { @@ -106,12 +105,19 @@ INLINE void writed(HostPt off,Bit32u val) { *(Bit32u *)(off)=val; }; +#define MLEB(_MLE_VAL_) (_MLE_VAL_) +#define MLEW(_MLE_VAL_) (_MLE_VAL_) +#define MLED(_MLE_VAL_) (_MLE_VAL_) + #endif -/* The Folowing six functions are slower but they recognize the paged memory system */ -//TODO maybe make em inline to go a bit faster +#define WLE(VAR_,VAL_) \ + if (sizeof(VAR_)==1) VAR_=MLEB(VAL_); \ + if (sizeof(VAR_)==2) VAR_=MLEW(VAL_); \ + if (sizeof(VAR_)==4) VAR_=MLED(VAL_); + +/* The Folowing six functions are slower but they recognize the paged memory system */ -#if (!C_EXTRAINLINE) Bit8u mem_readb(PhysPt pt); Bit16u mem_readw(PhysPt pt); Bit32u mem_readd(PhysPt pt); @@ -120,68 +126,22 @@ void mem_writeb(PhysPt pt,Bit8u val); void mem_writew(PhysPt pt,Bit16u val); void mem_writed(PhysPt pt,Bit32u val); -#else +void phys_writeb(PhysPt addr,Bit8u val); +void phys_writew(PhysPt addr,Bit16u val); +void phys_writed(PhysPt addr,Bit32u val); -INLINE void mem_writeb(PhysPt pt,Bit8u val) { - if (WriteHostTable[pt >> PAGE_SHIFT]) writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); - else { - WriteHandlerTable[pt >> PAGE_SHIFT](pt,val); - } -} - -INLINE void mem_writew(PhysPt pt,Bit16u val) { - if (WriteHostTable[pt >> PAGE_SHIFT]) writew(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); - else { - WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff)); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) ); - } -} - -INLINE void mem_writed(PhysPt pt,Bit32u val) { - if (WriteHostTable[pt >> PAGE_SHIFT]) writed(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); - else { - WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff)); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) ); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+2,(Bit8u)((val >> 16) & 0xff) ); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+3,(Bit8u)((val >> 24) & 0xff) ); - } -} - -INLINE Bit8u mem_readb(PhysPt pt) { - if (ReadHostTable[pt >> PAGE_SHIFT]) return readb(ReadHostTable[pt >> PAGE_SHIFT]+pt); - else { - return ReadHandlerTable[pt >> PAGE_SHIFT](pt); - } -} - -INLINE Bit16u mem_readw(PhysPt pt) { - if (ReadHostTable[pt >> PAGE_SHIFT]) return readw(ReadHostTable[pt >> PAGE_SHIFT]+pt); - else { - return - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) | - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8; - } - -} - -INLINE Bit32u mem_readd(PhysPt pt){ - if (ReadHostTable[pt >> PAGE_SHIFT]) return readd(ReadHostTable[pt >> PAGE_SHIFT]+pt); - else { - return - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) | - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8 | - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+2)) << 16 | - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+3)) << 24; - } -} - -#endif +/* 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); void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size); void MEM_StrCopy(PhysPt pt,char * data,Bitu size); +void mem_memcpy(PhysPt dest,PhysPt src,Bitu size); +Bitu mem_strlen(PhysPt pt); +void mem_strcpy(PhysPt dest,PhysPt src); + /* The folowing functions are all shortcuts to the above functions using physical addressing */ INLINE Bit8u real_readb(Bit16u seg,Bit16u off) { @@ -204,13 +164,6 @@ INLINE void real_writed(Bit16u seg,Bit16u off,Bit32u val) { mem_writed(((seg<<4)+off),val); } -INLINE HostPt HostMake(Bit16u seg,Bit16u off) { - return memory+(seg<<4)+off; -} - -INLINE HostPt Phys2Host(PhysPt pt) { - return memory+pt; -} INLINE Bit16u RealSeg(RealPt pt) { return (Bit16u)(pt>>16); @@ -228,10 +181,6 @@ INLINE PhysPt PhysMake(Bit16u seg,Bit16u off) { return (seg<<4)+off; } -INLINE HostPt Real2Host(RealPt pt) { - return memory+(RealSeg(pt)<<4) +RealOff(pt); -} - INLINE RealPt RealMake(Bit16u seg,Bit16u off) { return (seg<<16)+off; } diff --git a/include/mouse.h b/include/mouse.h index 0123ecb..07fce5a 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -26,5 +26,5 @@ void Mouse_ButtonPressed(Bit8u button); void Mouse_ButtonReleased(Bit8u button); void Mouse_AutoLock(bool enable); -void Mouse_SetResolution(Bit16u width, Bit16u height); +void Mouse_NewVideoMode(void); diff --git a/include/paging.h b/include/paging.h new file mode 100644 index 0000000..73169bc --- /dev/null +++ b/include/paging.h @@ -0,0 +1,224 @@ +/* + * 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. + */ + +#ifndef _PAGING_H_ +#define _PAGING_H_ + +#include "mem.h" + +class PageDirectory; +struct PageEntry; +struct PageLink; + +#define MEM_PAGE_SIZE (4096) +#define XMS_START (0x110) + +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, +}; + +enum VGA_RANGES { + VGA_RANGE_A000, + VGA_RANGE_B000, + VGA_RANGE_B800, +}; + + +class PageChange { +public: + virtual void Changed(PageLink * link,Bitu start,Bitu end)=0; +}; + +/* 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); + +PageLink * MEM_LinkPage(Bitu phys_page,PhysPt lin_base); + +void MEM_UnlinkPage(PageLink * link); +void MEM_SetLFB(Bitu _page,Bitu _pages,HostPt _pt); + +#pragma pack(1) +typedef struct { + Bit32u p:1; + Bit32u wr:1; + Bit32u us:1; + Bit32u pwt:1; + Bit32u pcd:1; + Bit32u a:1; + Bit32u d:1; + Bit32u pat:1; + Bit32u g:1; + Bit32u avl:3; + Bit32u base:20; +} X86_PageEntryBlock GCC_ATTRIBUTE(packed); +#pragma pack() + +union X86PageEntry { + Bit32u load; + 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; + bool enabled; +}; + +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); + +/* Unaligned address handlers */ +Bit16u mem_unalignedreadw(PhysPt address); +Bit32u mem_unalignedreadd(PhysPt address); +void mem_unalignedwritew(PhysPt address,Bit16u val); +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); +} + +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); +} + + +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); +} + +INLINE void mem_writeb_inline(PhysPt address,Bit8u val) { + PageLink * plink=GetPageLink(address); + + if (plink->write) writeb(plink->write+address,val); + else ENTRY_writeb(plink->entry,address,val); +} + +INLINE void mem_writew_inline(PhysPt address,Bit16u val) { + if (address & 1) {mem_unalignedwritew(address,val);return;} + + PageLink * plink=GetPageLink(address); + + if (plink->write) writew(plink->write+address,val); + else ENTRY_writew(plink->entry,address,val); +} + +INLINE void mem_writed_inline(PhysPt address,Bit32u val) { + if (address & 3) {mem_unalignedwrited(address,val);return;} + + PageLink * plink=GetPageLink(address); + + 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 947166b..d40a5f9 100644 --- a/include/pic.h +++ b/include/pic.h @@ -20,7 +20,10 @@ #define __PIC_H -#include "cpu.h" +/* CPU Cycle Timing */ +extern Bits CPU_Cycles; +extern Bits CPU_CycleLeft; +extern Bits CPU_CycleMax; typedef void (PIC_EOIHandler) (void); typedef void (* PIC_EventHandler)(void); @@ -32,7 +35,6 @@ typedef void (* PIC_EventHandler)(void); extern Bitu PIC_IRQCheck; extern Bitu PIC_IRQActive; - extern Bitu PIC_Ticks; INLINE Bitu PIC_Index(void) { @@ -55,7 +57,7 @@ void PIC_runIRQs(void); void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name); void PIC_FreeIRQ(Bit32u irq); -Bitu PIC_RunQueue(void); +bool PIC_RunQueue(void); void PIC_AddIRQ(Bitu irq,Bitu delay); void PIC_AddEvent(PIC_EventHandler handler,Bitu delay); diff --git a/include/regs.h b/include/regs.h index 2c3954f..a3a266f 100644 --- a/include/regs.h +++ b/include/regs.h @@ -29,19 +29,44 @@ struct Flag_Info { } var1,var2,result; Bitu type; Bitu prev_type; - bool cf,sf,pf,af,zf,of,df,tf,intf; - bool nt; - Bit8u io; - bool oldcf; + 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_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 SETFLAGBIT(TYPE,TEST) if (TEST) flags.word|=FLAG_ ## TYPE; else flags.word&=~FLAG_ ## TYPE + +#define GETFLAG(TYPE) (flags.word & FLAG_ ## TYPE) +#define GETFLAGBOOL(TYPE) ((flags.word & FLAG_ ## TYPE) ? true : false ) + struct Segment { Bit16u val; PhysPt phys; /* The phyiscal address start in emulated machine */ }; +enum SegNames { es=0,cs,ss,ds,fs,gs}; -enum SegNames { cs=0,ds,es,fs,gs,ss}; +struct Segments { + Bitu val[8]; + PhysPt phys[8]; +}; union GenReg32 { Bit32u dword[1]; @@ -69,7 +94,7 @@ struct CPU_Regs { GenReg32 regs[8],ip; }; -extern Segment Segs[6]; +extern Segments Segs; extern Flag_Info flags; extern CPU_Regs cpu_regs; @@ -78,11 +103,11 @@ extern CPU_Regs cpu_regs; //#define SegValue(index) Segs[index].val INLINE PhysPt SegPhys(SegNames index) { - return Segs[index].phys; + return Segs.phys[index]; } INLINE Bit16u SegValue(SegNames index) { - return Segs[index].val; + return Segs.val[index]; } @@ -92,16 +117,22 @@ INLINE RealPt RealMakeSeg(SegNames index,Bit16u off) { INLINE void SegSet16(Bitu index,Bit16u val) { - Segs[index].val=val; - Segs[index].phys=val << 4; + Segs.val[index]=val; + Segs.phys[index]=val << 4; } -enum REG_NUM { - REG_NUM_AX, REG_NUM_CX, REG_NUM_DX, REG_NUM_BX, - REG_NUM_SP, REG_NUM_BP, REG_NUM_SI, REG_NUM_DI +enum { + REGI_AX, REGI_CX, REGI_DX, REGI_BX, + REGI_SP, REGI_BP, REGI_SI, REGI_DI }; +enum { + REGI_AL, REGI_CL, REGI_DL, REGI_BL, + REGI_AH, REGI_CH, REGI_DH, REGI_BH, +}; + + //macros to convert a 3-bit register index to the correct register #define reg_8l(reg) (cpu_regs.regs[(reg)].byte[BL_INDEX]) #define reg_8h(reg) (cpu_regs.regs[(reg)].byte[BH_INDEX]) @@ -110,37 +141,37 @@ enum REG_NUM { #define reg_32(reg) (cpu_regs.regs[(reg)].dword[DW_INDEX]) -#define reg_al cpu_regs.regs[REG_NUM_AX].byte[BL_INDEX] -#define reg_ah cpu_regs.regs[REG_NUM_AX].byte[BH_INDEX] -#define reg_ax cpu_regs.regs[REG_NUM_AX].word[W_INDEX] -#define reg_eax cpu_regs.regs[REG_NUM_AX].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] +#define reg_eax cpu_regs.regs[REGI_AX].dword[DW_INDEX] -#define reg_bl cpu_regs.regs[REG_NUM_BX].byte[BL_INDEX] -#define reg_bh cpu_regs.regs[REG_NUM_BX].byte[BH_INDEX] -#define reg_bx cpu_regs.regs[REG_NUM_BX].word[W_INDEX] -#define reg_ebx cpu_regs.regs[REG_NUM_BX].dword[DW_INDEX] +#define reg_bl cpu_regs.regs[REGI_BX].byte[BL_INDEX] +#define reg_bh cpu_regs.regs[REGI_BX].byte[BH_INDEX] +#define reg_bx cpu_regs.regs[REGI_BX].word[W_INDEX] +#define reg_ebx cpu_regs.regs[REGI_BX].dword[DW_INDEX] -#define reg_cl cpu_regs.regs[REG_NUM_CX].byte[BL_INDEX] -#define reg_ch cpu_regs.regs[REG_NUM_CX].byte[BH_INDEX] -#define reg_cx cpu_regs.regs[REG_NUM_CX].word[W_INDEX] -#define reg_ecx cpu_regs.regs[REG_NUM_CX].dword[DW_INDEX] +#define reg_cl cpu_regs.regs[REGI_CX].byte[BL_INDEX] +#define reg_ch cpu_regs.regs[REGI_CX].byte[BH_INDEX] +#define reg_cx cpu_regs.regs[REGI_CX].word[W_INDEX] +#define reg_ecx cpu_regs.regs[REGI_CX].dword[DW_INDEX] -#define reg_dl cpu_regs.regs[REG_NUM_DX].byte[BL_INDEX] -#define reg_dh cpu_regs.regs[REG_NUM_DX].byte[BH_INDEX] -#define reg_dx cpu_regs.regs[REG_NUM_DX].word[W_INDEX] -#define reg_edx cpu_regs.regs[REG_NUM_DX].dword[DW_INDEX] +#define reg_dl cpu_regs.regs[REGI_DX].byte[BL_INDEX] +#define reg_dh cpu_regs.regs[REGI_DX].byte[BH_INDEX] +#define reg_dx cpu_regs.regs[REGI_DX].word[W_INDEX] +#define reg_edx cpu_regs.regs[REGI_DX].dword[DW_INDEX] -#define reg_si cpu_regs.regs[REG_NUM_SI].word[W_INDEX] -#define reg_esi cpu_regs.regs[REG_NUM_SI].dword[DW_INDEX] +#define reg_si cpu_regs.regs[REGI_SI].word[W_INDEX] +#define reg_esi cpu_regs.regs[REGI_SI].dword[DW_INDEX] -#define reg_di cpu_regs.regs[REG_NUM_DI].word[W_INDEX] -#define reg_edi cpu_regs.regs[REG_NUM_DI].dword[DW_INDEX] +#define reg_di cpu_regs.regs[REGI_DI].word[W_INDEX] +#define reg_edi cpu_regs.regs[REGI_DI].dword[DW_INDEX] -#define reg_sp cpu_regs.regs[REG_NUM_SP].word[W_INDEX] -#define reg_esp cpu_regs.regs[REG_NUM_SP].dword[DW_INDEX] +#define reg_sp cpu_regs.regs[REGI_SP].word[W_INDEX] +#define reg_esp cpu_regs.regs[REGI_SP].dword[DW_INDEX] -#define reg_bp cpu_regs.regs[REG_NUM_BP].word[W_INDEX] -#define reg_ebp cpu_regs.regs[REG_NUM_BP].dword[DW_INDEX] +#define reg_bp cpu_regs.regs[REGI_BP].word[W_INDEX] +#define reg_ebp cpu_regs.regs[REGI_BP].dword[DW_INDEX] #define reg_ip cpu_regs.ip.word[W_INDEX] #define reg_eip cpu_regs.ip.dword[DW_INDEX] diff --git a/include/render.h b/include/render.h index 054941c..2f63708 100644 --- a/include/render.h +++ b/include/render.h @@ -19,8 +19,11 @@ enum RENDER_Operation { - OP_None,OP_Shot, - OP_2xSai,OP_Scale2x, + OP_None, + OP_Shot, + OP_Normal2x, + OP_AdvMame2x, + OP_Blit, }; enum { diff --git a/include/serialport.h b/include/serialport.h new file mode 100644 index 0000000..1347ac6 --- /dev/null +++ b/include/serialport.h @@ -0,0 +1,136 @@ +/* + * 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. + */ + +#if !defined __SERIALPORT_H +#define __SERIALPORT_H + +#include + +//If it's too high you overflow terminal clients buffers i think +#define FIFO_SIZE (1024) + +// Serial port interface // + +#define M_CTS 0x01 +#define M_DSR 0x02 +#define M_RI 0x04 +#define M_DCD 0x08 + +enum INT_TYPES { + INT_MS, + INT_TX, + INT_RX, + INT_RX_FIFO, + INT_LS, + INT_NONE, +}; + +typedef void MControl_Handler(Bitu mc); + +class CSerial { +public: + + // Constructor takes base port (0x3f0, 0x2f0, 0x2e0, etc.), IRQ, and initial bps // + CSerial (Bit16u initbase, Bit8u initirq, Bit32u initbps); + virtual ~CSerial(); + + // External port functions for IOHandlers // + void write_port(Bit32u port, Bit8u val); + Bit8u read_port(Bit32u port); + + static void write_serial(Bit32u port,Bit8u val); + static Bit8u read_serial(Bit32u port); + + void SetMCHandler(MControl_Handler * mcontrol); + + /* Allow the modem to change the modem status bits */ + void setmodemstatus(Bit8u status); + Bit8u getmodemstatus(void); + Bit8u getlinestatus(void); + + void checkint(void); + void raiseint(INT_TYPES type); + void lowerint(INT_TYPES type); + + /* Access to the receive fifo */ + Bitu rx_free(); + void rx_addb(Bit8u byte); + void rx_adds(Bit8u * data,Bitu size); + Bitu rx_size(); + Bit8u rx_readb(void); + + /* Access to the transmit fifo */ + Bitu tx_free(); + void tx_addb(Bit8u byte); + Bitu tx_size(); + Bit8u tx_readb(void); + + + // These variables maintain the status of the serial port + Bit16u base; + Bit16u irq; + Bit32u bps; + + bool FIFOenabled; + Bit16u FIFOsize; + +private: + + void setdivisor(Bit8u dmsb, Bit8u dlsb); + void checkforirq(void); + struct { + Bitu used; + Bitu pos; + Bit8u data[FIFO_SIZE]; + } rx_fifo,tx_fifo; + struct { + Bitu requested; + Bitu enabled; + INT_TYPES active; + } ints; + + Bitu rx_lastread; + Bit8u irq_pending; + + Bit8u scratch; + Bit8u dlab; + Bit8u divisor_lsb; + Bit8u divisor_msb; + Bit8u wordlen; + Bit8u dtr; + Bit8u rts; + Bit8u out1; + Bit8u out2; + Bit8u local_loopback; + Bit8u linectrl; + Bit8u intid; + Bit8u ierval; + Bit8u mstatus; + + Bit8u txval; + Bit8u timeout; + + MControl_Handler * mc_handler; + char remotestr[4096]; +}; + +// This function returns the CSerial objects for ports 1-4 // +CSerial *getComport(Bitu portnum); + +#endif + diff --git a/include/setup.h b/include/setup.h index 21ea765..f66b619 100644 --- a/include/setup.h +++ b/include/setup.h @@ -19,9 +19,11 @@ #ifndef _SETUP_H_ #define _SETUP_H_ +#ifdef _MSC_VER #pragma warning ( disable : 4786 ) +#endif -#include +#include "cross.h" #include #include @@ -35,10 +37,10 @@ public: bool FindHex(char * name,int & value,bool remove=false); bool FindInt(char * name,int & value,bool remove=false); bool FindString(char * name,std::string & value,bool remove=false); - bool FindCommand(int which,std::string & value); + bool FindCommand(unsigned int which,std::string & value); bool FindStringBegin(char * begin,std::string & value, bool remove=false); bool FindStringRemain(char * name,std::string & value); - int GetCount(void); + unsigned int GetCount(void); private: typedef std::list::iterator cmd_it; std::list cmds; diff --git a/include/video.h b/include/video.h index a7304ff..33997cc 100644 --- a/include/video.h +++ b/include/video.h @@ -34,6 +34,8 @@ struct GFX_PalEntry { #define GFX_FIXED_BPP 0x01 #define GFX_RESIZEABLE 0x02 #define GFX_SHADOW 0x04 +#define GFX_BLITTING 0x08 + #define MODE_SET 0x01 @@ -50,6 +52,8 @@ 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); #endif diff --git a/install-sh b/install-sh index 11870f1..6ce63b9 100644 --- a/install-sh +++ b/install-sh @@ -1,19 +1,37 @@ #!/bin/sh # # install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). # -# Copyright 1991 by the Massachusetts Institute of Technology +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. # -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it @@ -56,7 +74,7 @@ dir_arg="" while [ x"$1" != x ]; do case $1 in - -c) instcmd="$cpprog" + -c) instcmd=$cpprog shift continue;; @@ -79,7 +97,7 @@ while [ x"$1" != x ]; do shift continue;; - -s) stripcmd="$stripprog" + -s) stripcmd=$stripprog shift continue;; @@ -106,7 +124,7 @@ done if [ x"$src" = x ] then - echo "install: no input file specified" + echo "$0: no input file specified" >&2 exit 1 else : @@ -115,8 +133,8 @@ fi if [ x"$dir_arg" != x ]; then dst=$src src="" - - if [ -d $dst ]; then + + if [ -d "$dst" ]; then instcmd=: chmodcmd="" else @@ -125,20 +143,20 @@ if [ x"$dir_arg" != x ]; then else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad +# might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f "$src" ] || [ -d "$src" ] then : else - echo "install: $src does not exist" + echo "$0: $src does not exist" >&2 exit 1 fi - + if [ x"$dst" = x ] then - echo "install: no destination specified" + echo "$0: no destination specified" >&2 exit 1 else : @@ -147,16 +165,16 @@ else # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic - if [ -d $dst ] + if [ -d "$dst" ] then - dst="$dst"/`basename $src` + dst=$dst/`basename "$src"` else : fi fi ## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` +dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script @@ -165,69 +183,73 @@ dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` if [ ! -d "$dstdir" ]; then defaultIFS=' ' -IFS="${IFS-${defaultIFS}}" +IFS="${IFS-$defaultIFS}" -oIFS="${IFS}" +oIFS=$IFS # Some sh's can't handle IFS=/ for some reason. IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" +set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS=$oIFS pathcomp='' while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" + pathcomp=$pathcomp$1 shift - if [ ! -d "${pathcomp}" ] ; + if [ ! -d "$pathcomp" ] ; then - $mkdirprog "${pathcomp}" + $mkdirprog "$pathcomp" else : fi - pathcomp="${pathcomp}/" + pathcomp=$pathcomp/ done fi if [ x"$dir_arg" != x ] then - $doit $instcmd $dst && + $doit $instcmd "$dst" && - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi else # If we're going to rename the final executable, determine the name now. - if [ x"$transformarg" = x ] + if [ x"$transformarg" = x ] then - dstfile=`basename $dst` + dstfile=`basename "$dst"` else - dstfile=`basename $dst $transformbasename | + dstfile=`basename "$dst" $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename - if [ x"$dstfile" = x ] + if [ x"$dstfile" = x ] then - dstfile=`basename $dst` + dstfile=`basename "$dst"` else : fi -# Make a temp file name in the proper directory. +# Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/#inst.$$# + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + +# Trap to clean up temp files at exit. + + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 # Move or copy the file name to the temp name - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && + $doit $instcmd "$src" "$dsttmp" && # and set any options; do chmod last to preserve setuid bits @@ -235,17 +257,38 @@ else # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && + +# Now remove or move aside any old file at destination location. We try this +# two ways since rm can't unlink itself on some systems and the destination +# file might be busy for other reasons. In this case, the final cleanup +# might fail but the new file should still install successfully. + +{ + if [ -f "$dstdir/$dstfile" ] + then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || + $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || + { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi +} && # Now rename the file to the real destination. - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" fi && +# The final little trick to "correctly" pass the exit status to the exit trap. -exit 0 +{ + (exit 0); exit +} diff --git a/missing b/missing index 6a37006..fc54c64 100644 --- a/missing +++ b/missing @@ -1,6 +1,6 @@ #! /bin/sh # Common stub for a few missing GNU programs while installing. -# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -165,7 +165,7 @@ WARNING: \`$1' is missing on your system. You should only need it if WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. - You can get \`$1Help2man' as part of \`Autoconf' from any GNU + You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` @@ -326,7 +326,7 @@ WARNING: I can't seem to be able to run \`tar' with the given arguments. WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequirements for installing + it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 diff --git a/mkinstalldirs b/mkinstalldirs index 8ab885e..d2d5f21 100644 --- a/mkinstalldirs +++ b/mkinstalldirs @@ -12,18 +12,29 @@ Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." # process command line arguments while test $# -gt 0 ; do - case "${1}" in - -h | --help | --h* ) # -h for help - echo "${usage}" 1>&2; exit 0 ;; - -m ) # -m PERM arg - shift - test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } - dirmode="${1}" - shift ;; - -- ) shift; break ;; # stop option processing - -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option - * ) break ;; # first non-opt arg - esac + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" 1>&2 + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac done for file @@ -36,64 +47,65 @@ do done case $# in -0) exit 0 ;; + 0) exit 0 ;; esac case $dirmode in -'') - if mkdir -p -- . 2>/dev/null; then - echo "mkdir -p -- $*" - exec mkdir -p -- "$@" - fi ;; -*) - if mkdir -m "$dirmode" -p -- . 2>/dev/null; then - echo "mkdir -m $dirmode -p -- $*" - exec mkdir -m "$dirmode" -p -- "$@" - fi ;; + '') + if mkdir -p -- . 2>/dev/null; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + fi + ;; + *) + if mkdir -m "$dirmode" -p -- . 2>/dev/null; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + fi + ;; esac for file do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" - mkdir "$pathcomp" || lasterr=$? + mkdir "$pathcomp" || lasterr=$? - if test ! -d "$pathcomp"; then - errstatus=$lasterr - else - if test ! -z "$dirmode"; then - echo "chmod $dirmode $pathcomp" + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? - lasterr="" - chmod "$dirmode" "$pathcomp" || lasterr=$? + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi - if test ! -z "$lasterr"; then - errstatus=$lasterr - fi - fi - fi - fi - - pathcomp="$pathcomp/" - done + pathcomp="$pathcomp/" + done done exit $errstatus # Local Variables: # mode: shell-script -# sh-indentation: 3 +# sh-indentation: 2 # End: # mkinstalldirs ends here diff --git a/src/Makefile.in b/src/Makefile.in index cfd9289..5ff859c 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,77 +13,122 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ AM_CPPFLAGS = -I$(top_srcdir)/include SUBDIRS = cpu debug dos fpu gui hardware ints misc shell platform @@ -95,6 +140,7 @@ dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware ints/libints.a misc/libmisc.a shell/libshell.a subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -108,11 +154,7 @@ dosbox_DEPENDENCIES = cpu/libcpu.a debug/libdebug.a dos/libdos.a \ misc/libmisc.a shell/libshell.a dosbox_LDFLAGS = -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dosbox.Po @@ -121,14 +163,14 @@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ DIST_SOURCES = $(dosbox_SOURCES) -RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ - uninstall-info-recursive all-recursive install-data-recursive \ - install-exec-recursive installdirs-recursive install-recursive \ - uninstall-recursive check-recursive installcheck-recursive -DIST_COMMON = Makefile.am Makefile.in +RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ + ps-recursive install-info-recursive uninstall-info-recursive \ + all-recursive install-data-recursive install-exec-recursive \ + installdirs-recursive install-recursive uninstall-recursive \ + check-recursive installcheck-recursive +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am DIST_SUBDIRS = $(SUBDIRS) SOURCES = $(dosbox_SOURCES) @@ -151,7 +193,7 @@ install-binPROGRAMS: $(bin_PROGRAMS) ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \ - $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f || exit 1; \ else :; fi; \ done @@ -165,6 +207,21 @@ uninstall-binPROGRAMS: clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +installcheck-binPROGRAMS: $(bin_PROGRAMS) + bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \ + case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ + *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ + esac; \ + f=`echo "$$p" | \ + sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + for opt in --help --version; do \ + if $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \ + && test -n "`cat c$${pid}_.out`" \ + && test -z "`cat c$${pid}_.err`"; then :; \ + else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \ + done; \ + done; rm -f c$${pid}_.???; exit $$bad dosbox$(EXEEXT): $(dosbox_OBJECTS) $(dosbox_DEPENDENCIES) @rm -f dosbox$(EXEEXT) $(CXXLINK) $(dosbox_LDFLAGS) $(dosbox_OBJECTS) $(dosbox_LDADD) $(LIBS) @@ -177,21 +234,27 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dosbox.Po@am__quote@ -distclean-depend: - -rm -rf ./$(DEPDIR) - .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd @@ -248,10 +311,17 @@ tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -267,9 +337,15 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ + if (etags --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + else \ + include_option=--include; \ + fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + test -f $$subdir/TAGS && \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -282,20 +358,41 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -354,7 +451,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -364,9 +461,11 @@ clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-recursive + -rm -rf ./$(DEPDIR) -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-recursive @@ -384,35 +483,46 @@ install-info: install-info-recursive install-man: -installcheck-am: +installcheck-am: installcheck-binPROGRAMS maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-info: uninstall-info-recursive -.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ - clean-binPROGRAMS clean-generic clean-recursive distclean \ - distclean-compile distclean-depend distclean-generic \ +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-recursive ctags \ + ctags-recursive distclean distclean-compile distclean-generic \ distclean-recursive distclean-tags distdir dvi dvi-am \ dvi-recursive info info-am info-recursive install install-am \ install-binPROGRAMS install-data install-data-am \ install-data-recursive install-exec install-exec-am \ install-exec-recursive install-info install-info-am \ install-info-recursive install-man install-recursive \ - install-strip installcheck installcheck-am installdirs \ - installdirs-am installdirs-recursive maintainer-clean \ - maintainer-clean-generic maintainer-clean-recursive mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-recursive \ - tags tags-recursive uninstall uninstall-am \ - uninstall-binPROGRAMS uninstall-info-am \ + install-strip installcheck installcheck-am \ + installcheck-binPROGRAMS installdirs installdirs-am \ + installdirs-recursive maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-recursive pdf pdf-am \ + pdf-recursive ps ps-am ps-recursive tags tags-recursive \ + uninstall uninstall-am uninstall-binPROGRAMS uninstall-info-am \ uninstall-info-recursive uninstall-recursive # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/src/cpu/Makefile.am b/src/cpu/Makefile.am index 97ef51e..6eee892 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -1,5 +1,6 @@ -SUBDIRS = core_16 +SUBDIRS = core_16 core_full core_normal 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 instructions.h \ No newline at end of file +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 diff --git a/src/cpu/Makefile.in b/src/cpu/Makefile.in index 0a41ab0..54f19d8 100644 --- a/src/cpu/Makefile.in +++ b/src/cpu/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,83 +13,131 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ -SUBDIRS = core_16 +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@ +SUBDIRS = core_16 core_full core_normal 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 instructions.h +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 + subdir = src/cpu +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -98,37 +146,34 @@ 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) + modrm.$(OBJEXT) slow_16.$(OBJEXT) core_full.$(OBJEXT) \ + paging.$(OBJEXT) core_normal.$(OBJEXT) libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS) -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/callback.Po ./$(DEPDIR)/cpu.Po \ +@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)/slow_16.Po +@AMDEP_TRUE@ ./$(DEPDIR)/paging.Po ./$(DEPDIR)/slow_16.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ -CFLAGS = @CFLAGS@ 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 = $(libcpu_a_SOURCES) -RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ - uninstall-info-recursive all-recursive install-data-recursive \ - install-exec-recursive installdirs-recursive install-recursive \ - uninstall-recursive check-recursive installcheck-recursive -DIST_COMMON = Makefile.am Makefile.in +RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ + ps-recursive install-info-recursive uninstall-info-recursive \ + all-recursive install-data-recursive install-exec-recursive \ + installdirs-recursive install-recursive uninstall-recursive \ + check-recursive installcheck-recursive +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am DIST_SUBDIRS = $(SUBDIRS) SOURCES = $(libcpu_a_SOURCES) @@ -158,26 +203,35 @@ 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_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@ -distclean-depend: - -rm -rf ./$(DEPDIR) - .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd @@ -234,10 +288,17 @@ tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -253,9 +314,15 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ + if (etags --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + else \ + include_option=--include; \ + fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + test -f $$subdir/TAGS && \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -268,20 +335,41 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -339,7 +427,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -349,9 +437,11 @@ clean: clean-recursive clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-recursive + -rm -rf ./$(DEPDIR) -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-recursive @@ -372,20 +462,30 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive -.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ - clean-generic clean-noinstLIBRARIES clean-recursive distclean \ - distclean-compile distclean-depend distclean-generic \ +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ + clean-generic clean-noinstLIBRARIES clean-recursive ctags \ + ctags-recursive distclean distclean-compile distclean-generic \ distclean-recursive distclean-tags distdir dvi dvi-am \ dvi-recursive info info-am info-recursive install install-am \ install-data install-data-am install-data-recursive \ @@ -395,7 +495,8 @@ uninstall-info: uninstall-info-recursive installdirs installdirs-am installdirs-recursive \ maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-recursive tags tags-recursive \ + mostlyclean-generic mostlyclean-recursive pdf pdf-am \ + pdf-recursive ps ps-am ps-recursive tags tags-recursive \ uninstall uninstall-am uninstall-info-am \ uninstall-info-recursive uninstall-recursive diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index ce79268..81ec286 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -16,6 +16,8 @@ * 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 $ */ + #include #include @@ -40,7 +42,7 @@ static Bitu illegal_handler(void) { } Bitu CALLBACK_Allocate(void) { - for (Bitu i=0;(i=CB_MAX) return false; switch (type) { case CB_RETF: - real_writeb((Bit16u)CB_SEG,(callback<<4)+0,(Bit8u)0xFE); //GRP 4 - real_writeb((Bit16u)CB_SEG,(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction - real_writew((Bit16u)CB_SEG,(callback<<4)+2,callback); //The immediate word - real_writeb((Bit16u)CB_SEG,(callback<<4)+4,(Bit8u)0xCB); //A RETF Instruction + phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFE); //GRP 4 + phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction + phys_writew(CB_BASE+(callback<<4)+2,callback); //The immediate word + phys_writeb(CB_BASE+(callback<<4)+4,(Bit8u)0xCB); //A RETF Instruction break; case CB_IRET: - real_writeb((Bit16u)CB_SEG,(callback<<4)+0,(Bit8u)0xFE); //GRP 4 - real_writeb((Bit16u)CB_SEG,(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction - real_writew((Bit16u)CB_SEG,(callback<<4)+2,callback); //The immediate word - real_writeb((Bit16u)CB_SEG,(callback<<4)+4,(Bit8u)0xCF); //An IRET Instruction + phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFE); //GRP 4 + phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0x38); //Extra Callback instruction + phys_writew(CB_BASE+(callback<<4)+2,callback); //The immediate word + phys_writeb(CB_BASE+(callback<<4)+4,(Bit8u)0xCF); //An IRET Instruction break; case CB_IRET_STI: - real_writeb((Bit16u)CB_SEG,(callback<<4)+0,(Bit8u)0xFB); //STI - real_writeb((Bit16u)CB_SEG,(callback<<4)+1,(Bit8u)0xFE); //GRP 4 - real_writeb((Bit16u)CB_SEG,(callback<<4)+2,(Bit8u)0x38); //Extra Callback instruction - real_writew((Bit16u)CB_SEG,(callback<<4)+3,callback); //The immediate word - real_writeb((Bit16u)CB_SEG,(callback<<4)+5,(Bit8u)0xCF); //An IRET Instruction + phys_writeb(CB_BASE+(callback<<4)+0,(Bit8u)0xFB); //STI + phys_writeb(CB_BASE+(callback<<4)+1,(Bit8u)0xFE); //GRP 4 + phys_writeb(CB_BASE+(callback<<4)+2,(Bit8u)0x38); //Extra Callback instruction + phys_writew(CB_BASE+(callback<<4)+3,callback); //The immediate word + phys_writeb(CB_BASE+(callback<<4)+5,(Bit8u)0xCF); //An IRET Instruction break; default: @@ -148,6 +150,35 @@ bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type) { return true; } +bool CALLBACK_SetupAt(Bitu callback,CallBack_Handler handler,Bitu type,Bitu linearAddress) { + if (callback>=CB_MAX) return false; + switch (type) { + case CB_RETF: + mem_writeb(linearAddress+0,(Bit8u)0xFE); //GRP 4 + mem_writeb(linearAddress+1,(Bit8u)0x38); //Extra Callback instruction + mem_writew(linearAddress+2, callback); //The immediate word + mem_writeb(linearAddress+4,(Bit8u)0xCB); //A RETF Instruction + break; + case CB_IRET: + mem_writeb(linearAddress+0,(Bit8u)0xFE); //GRP 4 + mem_writeb(linearAddress+1,(Bit8u)0x38); //Extra Callback instruction + mem_writew(linearAddress+2,callback); //The immediate word + mem_writeb(linearAddress+4,(Bit8u)0xCF); //An IRET Instruction + break; + case CB_IRET_STI: + mem_writeb(linearAddress+0,(Bit8u)0xFB); //STI + mem_writeb(linearAddress+1,(Bit8u)0xFE); //GRP 4 + mem_writeb(linearAddress+2,(Bit8u)0x38); //Extra Callback instruction + mem_writew(linearAddress+3, callback); //The immediate word + mem_writeb(linearAddress+5,(Bit8u)0xCF); //An IRET Instruction + break; + default: + E_Exit("CALLBACK:Setup:Illegal type %d",type); + } + CallBack_Handlers[callback]=handler; + return true; +} + void CALLBACK_Init(Section* sec) { Bitu i; for (i=0;i= 0xc0 ) {GetEArb;inst(*earb,LoadRb,SaveRb);} \ + else {GetEAa;inst(eaa,LoadMb,SaveMb);} \ + } + #define RMEwGw(inst) \ { \ GetRMrw; \ @@ -45,6 +52,13 @@ 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; \ @@ -52,6 +66,19 @@ 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; \ @@ -59,6 +86,14 @@ 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; \ @@ -66,6 +101,28 @@ 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)} @@ -74,3 +131,13 @@ #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 index 5bfe47c..1bda624 100644 --- a/src/cpu/core_16/main.h +++ b/src/cpu/core_16/main.h @@ -67,7 +67,8 @@ restart: Push_16(SegValue(ss));break; case 0x17: /* POP SS */ SegSet16(ss,Pop_16()); - goto restart; + CPU_Cycles++;//Be sure we run another instruction + break; case 0x18: /* SBB Eb,Gb */ RMEbGb(SBBB);break; case 0x19: /* SBB Ew,Gw */ @@ -82,7 +83,7 @@ restart: AXIw(SBBW);break; case 0x1e: /* PUSH DS */ Push_16(SegValue(ds));break; - case 0x1f: /* POP DS */ + case 0x1f: /* POP DS */ SegSet16(ds,Pop_16());break; case 0x20: /* AND Eb,Gb */ RMEbGb(ANDB);break; @@ -99,23 +100,7 @@ restart: case 0x26: /* SEG ES: */ SegPrefix(es);break; case 0x27: /* DAA */ - if (((reg_al & 0x0F)>0x09) || get_AF()) { - reg_al+=0x06; - flags.af=true; - } else { - flags.af=false; - } - flags.cf=get_CF(); - if ((reg_al > 0x9F) || flags.cf) { - reg_al+=0x60; - flags.cf=true; - } else { - flags.cf=false; - } - flags.sf=(reg_al>>7)>0; - flags.zf=(reg_al==0); - //TODO Maybe parity - flags.type=t_UNKNOWN; + DAA(); break; case 0x28: /* SUB Eb,Gb */ RMEbGb(SUBB);break; @@ -132,19 +117,7 @@ restart: case 0x2e: /* SEG CS: */ SegPrefix(cs);break; case 0x2f: /* DAS */ - if (((reg_al & 0x0f) > 9) || get_AF()) { - reg_al-=6; - flags.af=true; - } else { - flags.af=false; - } - if ((reg_al>0x9f) || get_CF()) { - reg_al-=0x60; - flags.cf=true; - } else { - flags.cf=false; - } - flags.type=t_UNKNOWN; + DAS(); break; case 0x30: /* XOR Eb,Gb */ RMEbGb(XORB);break; @@ -161,18 +134,7 @@ restart: case 0x36: /* SEG SS: */ SegPrefix(ss);break; case 0x37: /* AAA */ - if (get_AF() || ((reg_al & 0xf) > 9)) - { - reg_al += 6; - reg_ah += 1; - flags.af=true; - flags.cf=true; - } else { - flags.af=false; - flags.cf=false; - } - reg_al &= 0x0F; - flags.type=t_UNKNOWN; + AAA(); break; case 0x38: /* CMP Eb,Gb */ RMEbGb(CMPB);break; @@ -189,14 +151,7 @@ restart: case 0x3e: /* SEG DS: */ SegPrefix(ds);break; case 0x3f: /* AAS */ - if (((reg_al & 0x0f)>9) || get_AF()) { - reg_al=(reg_al-6) & 0xF; - reg_ah--; - flags.af=flags.cf=true; - } else { - flags.af=flags.cf=false; - } - flags.type=t_UNKNOWN; + AAS(); break; case 0x40: /* INC AX */ INCW(reg_ax,LoadRw,SaveRw);break; @@ -240,7 +195,7 @@ restart: 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; + Push_16(reg_sp);break; case 0x55: /* PUSH BP */ Push_16(reg_bp);break; case 0x56: /* PUSH SI */ @@ -255,8 +210,8 @@ restart: reg_dx=Pop_16();break; case 0x5b: /* POP BX */ reg_bx=Pop_16();break; - case 0x5c: /* POP SP */ - reg_sp=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 */ @@ -264,8 +219,11 @@ restart: case 0x5f: /* POP DI */ reg_di=Pop_16();break; case 0x60: /* PUSHA */ - Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx); - Push_16(reg_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di); + { + 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 @@ -278,7 +236,7 @@ restart: bound_min=LoadMw(eaa); bound_max=LoadMw(eaa+2); if ( (((Bit16s)*rmrw) < bound_min) || (((Bit16s)*rmrw) > bound_max) ) { - INTERRUPT(5); + EXCEPTION(5); } } break; @@ -294,11 +252,8 @@ restart: break; case 0x67: /* Address Size Prefix */ #ifdef CPU_PREFIX_67 - prefix.mark|=PREFIX_ADDR; -#ifdef CPU_PREFIX_COUNT - prefix.count++; -#endif - lookupEATable=EAPrefixTable[prefix.mark]; + core_16.prefixes^=PREFIX_ADDR; + lookupEATable=EAPrefixTable[core_16.prefixes]; goto restart; #else NOTDONE; @@ -308,35 +263,19 @@ restart: case 0x68: /* PUSH Iw */ Push_16(Fetchw());break; case 0x69: /* IMUL Gw,Ew,Iw */ - { - GetRMrw; - Bit32s res; - if (rm >= 0xc0 ) {GetEArw;res=(Bit32s)(*earws) * (Bit32s)Fetchws();} - else {GetEAa;res=(Bit32s)LoadMws(eaa) * (Bit32s)Fetchws();} - *rmrw=res & 0xFFFF; - flags.type=t_MUL; - if ((res> -32768) && (res<32767)) {flags.cf=false;flags.of=false;} - else {flags.cf=true;flags.of=true;} - break; - }; + RMGwEwOp3(DIMULW,Fetchws()); + break; case 0x6a: /* PUSH Ib */ - Push_16(Fetchbs());break; + Push_16(Fetchbs()); + break; case 0x6b: /* IMUL Gw,Ew,Ib */ - { - GetRMrw;Bit32s res; - if (rm >= 0xc0 ) {GetEArw;res=(Bit32s)(*earws) * (Bit32s)Fetchbs();} - else {GetEAa;res=(Bit32s)LoadMws(eaa) * (Bit32s)Fetchbs();} - *rmrw=res & 0xFFFF; - flags.type=t_MUL; - if ((res> -32768) && (res<32767)) {flags.cf=false;flags.of=false;} - else {flags.cf=true;flags.of=true;} - break; - } + RMGwEwOp3(DIMULW,Fetchbs()); + break; case 0x6c: /* INSB */ { stringDI; SaveMb(to,IO_Read(reg_dx)); - if (flags.df) reg_di--; else reg_di++; + if (GETFLAG(DF)) reg_di--; else reg_di++; break; } case 0x6d: /* INSW */ @@ -344,14 +283,14 @@ restart: stringDI; SaveMb(to,IO_Read(reg_dx)); SaveMb((to+1),IO_Read(reg_dx+1)); - if (flags.df) reg_di-=2; else reg_di+=2; + if (GETFLAG(DF)) reg_di-=2; else reg_di+=2; break; } case 0x6e: /* OUTSB */ { stringSI; IO_Write(reg_dx,LoadMb(from)); - if (flags.df) reg_si--; else reg_si++; + if (GETFLAG(DF)) reg_si--; else reg_si++; break; } case 0x6f: /* OUTSW */ @@ -359,7 +298,7 @@ restart: stringSI; IO_Write(reg_dx,LoadMb(from)); IO_Write(reg_dx+1,LoadMb(from+1)); - if (flags.df) reg_si-=2; else reg_si+=2; + if (GETFLAG(DF)) reg_si-=2; else reg_si+=2; break; } case 0x70: /* JO */ @@ -486,9 +425,11 @@ restart: break; } case 0x84: /* TEST Eb,Gb */ - RMEbGb(TESTB);break; + RMEbGb(TESTB); + break; case 0x85: /* TEST Ew,Gw */ - RMEwGw(TESTW);break; + RMEwGw(TESTW); + break; case 0x86: /* XCHG Eb,Gb */ { GetRMrb;Bit8u oldrmrb=*rmrb; @@ -557,9 +498,9 @@ restart: } case 0x8d: /* LEA */ { - prefix.segbase=0; - prefix.mark|=PREFIX_SEG; - lookupEATable=EAPrefixTable[prefix.mark]; + core_16.segbase=0; + core_16.prefixes|=PREFIX_SEG; + lookupEATable=EAPrefixTable[core_16.prefixes]; GetRMrw;GetEAa; *rmrw=(Bit16u)eaa; break; @@ -577,7 +518,7 @@ restart: break; case 0x10: /* MOV SS,Ew */ SegSet16(ss,val); - goto restart; + CPU_Cycles++;//Be sure we run another instruction break; case 0x18: /* MOV DS,Ew */ SegSet16(ds,val);break; @@ -636,59 +577,50 @@ restart: case 0x9b: /* WAIT */ break; /* No waiting here */ case 0x9c: /* PUSHF */ - { - Bit16u pflags= - (get_CF() << 0) | (get_PF() << 2) | (get_AF() << 4) | - (get_ZF() << 6) | (get_SF() << 7) | (flags.tf << 8) | - (flags.intf << 9) |(flags.df << 10) | (get_OF() << 11) | - (flags.io << 12) | (flags.nt <<14); - Push_16(pflags); - break; - } + FillFlags(); + Push_16(flags.word); + break; case 0x9d: /* POPF */ - { - Bit16u bits=Pop_16(); - Save_Flagsw(bits); - break; - } + SETFLAGSw(Pop_16()); + CheckTF(); +#ifdef CPU_PIC_CHECK + if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; +#endif + break; case 0x9e: /* SAHF */ - flags.of =get_OF(); - flags.type=t_UNKNOWN; - flags.cf =(reg_ah & 0x001)!=0;flags.pf =(reg_ah & 0x004)!=0; - flags.af =(reg_ah & 0x010)!=0;flags.zf =(reg_ah & 0x040)!=0; - flags.sf =(reg_ah & 0x080)!=0; + SETFLAGSb(reg_ah); break; case 0x9f: /* LAHF */ { - reg_ah=(get_CF() << 0) | (get_PF() << 2) | (get_AF() << 4) | - (get_ZF() << 6) | (get_SF() << 7); + FillFlags(); + reg_ah=(Bit8u)flags.word; break; } case 0xa0: /* MOV AL,Ob */ { - reg_al=LoadMb(GetEADirect[prefix.mark]()); + reg_al=LoadMb(GetEADirect[core_16.prefixes]()); } break; case 0xa1: /* MOV AX,Ow */ { - reg_ax=LoadMw(GetEADirect[prefix.mark]()); + reg_ax=LoadMw(GetEADirect[core_16.prefixes]()); } break; case 0xa2: /* MOV Ob,AL */ { - SaveMb(GetEADirect[prefix.mark](),reg_al); + SaveMb(GetEADirect[core_16.prefixes](),reg_al); } break; case 0xa3: /* MOV Ow,AX */ { - SaveMw(GetEADirect[prefix.mark](),reg_ax); + SaveMw(GetEADirect[core_16.prefixes](),reg_ax); } break; case 0xa4: /* MOVSB */ { stringSI;stringDI; SaveMb(to,LoadMb(from));; - if (flags.df) { reg_si--;reg_di--; } + if (GETFLAG(DF)) { reg_si--;reg_di--; } else {reg_si++;reg_di++;} break; } @@ -696,7 +628,7 @@ restart: { stringSI;stringDI; SaveMw(to,LoadMw(from)); - if (flags.df) { reg_si-=2;reg_di-=2; } + if (GETFLAG(DF)) { reg_si-=2;reg_di-=2; } else {reg_si+=2;reg_di+=2;} break; } @@ -704,7 +636,7 @@ restart: { stringSI;stringDI; CMPB(from,LoadMb(to),LoadMb,0); - if (flags.df) { reg_si--;reg_di--; } + if (GETFLAG(DF)) { reg_si--;reg_di--; } else {reg_si++;reg_di++;} break; } @@ -712,7 +644,7 @@ restart: { stringSI;stringDI; CMPW(from,LoadMw(to),LoadMw,0); - if (flags.df) { reg_si-=2;reg_di-=2; } + if (GETFLAG(DF)) { reg_si-=2;reg_di-=2; } else {reg_si+=2;reg_di+=2;} break; } @@ -724,7 +656,7 @@ restart: { stringDI; SaveMb(to,reg_al); - if (flags.df) { reg_di--; } + if (GETFLAG(DF)) { reg_di--; } else {reg_di++;} break; } @@ -732,7 +664,7 @@ restart: { stringDI; SaveMw(to,reg_ax); - if (flags.df) { reg_di-=2; } + if (GETFLAG(DF)) { reg_di-=2; } else {reg_di+=2;} break; } @@ -740,7 +672,7 @@ restart: { stringSI; reg_al=LoadMb(from); - if (flags.df) { reg_si--; } + if (GETFLAG(DF)) { reg_si--; } else {reg_si++;} break; } @@ -748,7 +680,7 @@ restart: { stringSI; reg_ax=LoadMw(from); - if (flags.df) { reg_si-=2;} + if (GETFLAG(DF)) { reg_si-=2;} else {reg_si+=2;} break; } @@ -756,7 +688,7 @@ restart: { stringDI; CMPB(reg_al,LoadMb(to),LoadRb,0); - if (flags.df) { reg_di--; } + if (GETFLAG(DF)) { reg_di--; } else {reg_di++;} break; } @@ -764,7 +696,7 @@ restart: { stringDI; CMPW(reg_ax,LoadMw(to),LoadRw,0); - if (flags.df) { reg_di-=2; } + if (GETFLAG(DF)) { reg_di-=2; } else {reg_di+=2;} break; } @@ -843,7 +775,7 @@ restart: { Bit16u bytes=Fetchw();Bit8u level=Fetchb(); Push_16(reg_bp);reg_bp=reg_sp;reg_sp-=bytes; - EAPoint reader=SegBase(ss)+reg_bp; + PhysPt reader=SegBase(ss)+reg_bp; for (Bit8u i=1;i 0; - flags.zf=(reg_ax == 0); - //TODO PF - flags.pf=0; - } + AAM(Fetchb()); break; case 0xd5: /* AAD Ib */ - reg_al=reg_ah*Fetchb()+reg_al; - reg_ah=0; - flags.cf=(reg_al>=0x80); - flags.zf=(reg_al==0); - //TODO PF - flags.type=t_UNKNOWN; + AAD(Fetchb()); break; + case 0xd6: /* SALC */ reg_al = get_CF() ? 0xFF : 0; break; case 0xd7: /* XLAT */ - if (prefix.mark & PREFIX_SEG) { - reg_al=LoadMb(prefix.segbase+(Bit16u)(reg_bx+reg_al)); - PrefixReset; + if (core_16.prefixes & PREFIX_SEG) { + reg_al=LoadMb(core_16.segbase+(Bit16u)(reg_bx+reg_al)); } else { reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al)); } @@ -961,7 +896,7 @@ restart: case 0xde: /* FPU ESC 6 */ case 0xdf: /* FPU ESC 7 */ { - LOG(LOG_CPU,"FPU used"); + LOG(LOG_CPU,LOG_NORMAL)("FPU used"); Bit8u rm=Fetchb(); if (rm<0xc0) GetEAa; } @@ -982,8 +917,8 @@ restart: case 0xe3: /* JCXZ */ { Bitu test; - if (prefix.mark & PREFIX_ADDR) { - test=reg_ecx;PrefixReset; + if (core_16.prefixes & PREFIX_ADDR) { + test=reg_ecx; } else test=reg_cx; if (!test) ADDIPFAST(Fetchbs()); else ADDIPFAST(1); @@ -1027,7 +962,7 @@ restart: break; case 0xed: /* IN AX,DX */ reg_al=IO_Read(reg_dx); - reg_ah=IO_Read(reg_dx+1); + reg_ah=IO_Read(reg_dx+1); break; case 0xee: /* OUT DX,AL */ IO_Write(reg_dx,reg_al); @@ -1037,7 +972,7 @@ restart: IO_Write(reg_dx+1,reg_ah); break; case 0xf0: /* LOCK */ - LOG(LOG_CPU,"CPU:LOCK"); +// LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK"); break; case 0xf1: /* Weird call undocumented */ // INTERRUPT(1); @@ -1050,30 +985,32 @@ restart: Repeat_Normal(true,false); continue; case 0xf4: /* HLT */ - break; + LEAVECORE; + CPU_HLT(); + return 0x0; case 0xf5: /* CMC */ - flags.cf=!get_CF(); + SETFLAGBIT(CF,!get_CF()); if (flags.type!=t_CF) flags.prev_type=flags.type; flags.type=t_CF; break; case 0xf6: /* GRP3 Eb(,Ib) */ - { + { GetRM; - switch (rm & 0x38) { + switch ((rm & 0x38)>>3) { case 0x00: /* TEST Eb,Ib */ - case 0x08: /* TEST Eb,Ib Undocumented*/ + case 0x01: /* TEST Eb,Ib Undocumented*/ { if (rm >= 0xc0 ) {GetEArb;TESTB(*earb,Fetchb(),LoadRb,0)} else {GetEAa;TESTB(eaa,Fetchb(),LoadMb,0);} break; } - case 0x10: /* NOT Eb */ + case 0x02: /* NOT Eb */ { if (rm >= 0xc0 ) {GetEArb;*earb=~*earb;} else {GetEAa;SaveMb(eaa,~LoadMb(eaa));} break; } - case 0x18: /* NEG Eb */ + case 0x03: /* NEG Eb */ { flags.type=t_NEGb; if (rm >= 0xc0 ) { @@ -1085,69 +1022,38 @@ restart: } break; } - case 0x20: /* MUL AL,Eb */ - { - flags.type=t_MUL; - if (rm >= 0xc0 ) {GetEArb;reg_ax=reg_al * (*earb);} - else {GetEAa;reg_ax=reg_al * LoadMb(eaa);} - flags.cf=flags.of=((reg_ax & 0xff00) !=0); - break; - } - case 0x28: /* IMUL AL,Eb */ - { - flags.type=t_MUL; - if (rm >= 0xc0 ) {GetEArb;reg_ax=(Bit8s)reg_al * (*earbs);} - else {GetEAa;reg_ax=((Bit8s)reg_al) * LoadMbs(eaa);} - flags.cf=flags.of=!((reg_ax & 0xff80)==0xff80 || (reg_ax & 0xff80)==0x0000); - break; - } - case 0x30: /* DIV Eb */ - { -// flags.type=t_DIV; - Bit8u val; - if (rm >= 0xc0 ) {GetEArb;val=*earb;} - else {GetEAa;val=LoadMb(eaa);} - if (val==0) {INTERRUPT(0);break;} - Bit16u quotientu=reg_ax / val; - reg_ah=(Bit8u)(reg_ax % val); - reg_al=quotientu & 0xff; - if (quotientu!=reg_al) - INTERRUPT(0); - break; - } - case 0x38: /* IDIV Eb */ - { -// flags.type=t_DIV; - Bit8s val; - if (rm >= 0xc0 ) {GetEArb;val=*earbs;} - else {GetEAa;val=LoadMbs(eaa);} - if (val==0) {INTERRUPT(0);break;} - Bit16s quotients=((Bit16s)reg_ax) / val; - reg_ah=(Bit8s)(((Bit16s)reg_ax) % val); - reg_al=quotients & 0xff; - if (quotients!=(Bit8s)reg_al) - INTERRUPT(0); - 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;} + break; + } case 0xf7: /* GRP3 Ew(,Iw) */ { GetRM; - switch (rm & 0x38) { + switch ((rm & 0x38)>>3) { case 0x00: /* TEST Ew,Iw */ - case 0x08: /* TEST Ew,Iw Undocumented*/ + case 0x01: /* TEST Ew,Iw Undocumented*/ { if (rm >= 0xc0 ) {GetEArw;TESTW(*earw,Fetchw(),LoadRw,SaveRw);} else {GetEAa;TESTW(eaa,Fetchw(),LoadMw,SaveMw);} break; } - case 0x10: /* NOT Ew */ + case 0x02: /* NOT Ew */ { if (rm >= 0xc0 ) {GetEArw;*earw=~*earw;} else {GetEAa;SaveMw(eaa,~LoadMw(eaa));} break; } - case 0x18: /* NEG Ew */ + case 0x03: /* NEG Ew */ { flags.type=t_NEGw; if (rm >= 0xc0 ) { @@ -1159,125 +1065,63 @@ restart: } break; } - case 0x20: /* MUL AX,Ew */ - { - flags.type=t_MUL;Bit32u tempu; - if (rm >= 0xc0 ) {GetEArw;tempu=reg_ax * (*earw);} - else {GetEAa;tempu=reg_ax * LoadMw(eaa);} - reg_ax=(Bit16u)(tempu & 0xffff);reg_dx=(Bit16u)(tempu >> 16); - flags.cf=flags.of=(reg_dx !=0); - break; - } - case 0x28: /* IMUL AX,Ew */ - { - flags.type=t_MUL;Bit32s temps; - if (rm >= 0xc0 ) {GetEArw;temps=((Bit16s)reg_ax) * (*earws);} - else {GetEAa;temps=((Bit16s)reg_ax) * LoadMws(eaa);} - reg_ax=Bit16u(temps & 0xffff);reg_dx=(Bit16u)(temps >> 16); - if ( (reg_dx==0xffff) && (reg_ax & 0x8000) ) { - flags.cf=flags.of=false; - } else if ( (reg_dx==0x0000) && (reg_ax<0x8000) ) { - flags.cf=flags.of=false; - } else { - flags.cf=flags.of=true; - } - break; - } - case 0x30: /* DIV Ew */ - { -// flags.type=t_DIV; - Bit16u val; - if (rm >= 0xc0 ) {GetEArw;val=*earw;} - else {GetEAa;val=LoadMw(eaa);} - if (val==0) {INTERRUPT(0);break;} - Bit32u tempu=(reg_dx<<16)|reg_ax; - Bit32u quotientu=tempu/val; - reg_dx=(Bit16u)(tempu % val); - reg_ax=(Bit16u)(quotientu & 0xffff); - if (quotientu>0xffff) - INTERRUPT(0); - break; - } - case 0x38: /* IDIV Ew */ - { -// flags.type=t_DIV; - Bit16s val; - if (rm >= 0xc0 ) {GetEArw;val=*earws;} - else {GetEAa;val=LoadMws(eaa);} - if (val==0) {INTERRUPT(0);break;} - Bit32s temps=(reg_dx<<16)|reg_ax; - Bit32s quotients=temps/val; - reg_dx=(Bit16s)(temps % val); - reg_ax=(Bit16s)quotients; - if (quotients!=(Bit16s)reg_ax) - INTERRUPT(0); - 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 */ - flags.cf=false; + SETFLAGBIT(CF,false); if (flags.type!=t_CF) flags.prev_type=flags.type; flags.type=t_CF; break; case 0xf9: /* STC */ - flags.cf=true; + SETFLAGBIT(CF,true); if (flags.type!=t_CF) flags.prev_type=flags.type; flags.type=t_CF; break; case 0xfa: /* CLI */ - flags.intf=false; + SETFLAGBIT(IF,false); break; case 0xfb: /* STI */ - flags.intf=true; - if (flags.intf && PIC_IRQCheck) { - SAVEIP; - PIC_runIRQs(); - LOADIP; - }; + SETFLAGBIT(IF,true); +#ifdef CPU_PIC_CHECK + if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; +#endif break; case 0xfc: /* CLD */ - flags.df=false; + SETFLAGBIT(DF,false); break; case 0xfd: /* STD */ - flags.df=true; + SETFLAGBIT(DF,true); break; case 0xfe: /* GRP4 Eb */ { GetRM; switch (rm & 0x38) { case 0x00: /* INC Eb */ - flags.cf=get_CF();flags.type=t_INCb; - if (rm >= 0xc0 ) {GetEArb;flags.result.b=*earb+=1;} - else {GetEAa;flags.result.b=LoadMb(eaa)+1;SaveMb(eaa,flags.result.b);} + RMEb(INCB); break; case 0x08: /* DEC Eb */ - flags.cf=get_CF();flags.type=t_DECb; - if (rm >= 0xc0 ) {GetEArb;flags.result.b=*earb-=1;} - else {GetEAa;flags.result.b=LoadMb(eaa)-1;SaveMb(eaa,flags.result.b);} + RMEb(DECB); break; case 0x38: /* CallBack */ { - Bit32u ret; - Bit16u call=Fetchw(); - SAVEIP; - if (call>3) & 7); break; @@ -1289,15 +1133,11 @@ restart: GetRM; switch (rm & 0x38) { case 0x00: /* INC Ew */ - flags.cf=get_CF();flags.type=t_INCw; - if (rm >= 0xc0 ) {GetEArw;flags.result.w=*earw+=1;} - else {GetEAa;flags.result.w=LoadMw(eaa)+1;SaveMw(eaa,flags.result.w);} + RMEw(INCW); break; case 0x08: /* DEC Ew */ - flags.cf=get_CF();flags.type=t_DECw; - if (rm >= 0xc0 ) {GetEArw;flags.result.w=*earw-=1;} - else {GetEAa;flags.result.w=LoadMw(eaa)-1;SaveMw(eaa,flags.result.w);} - break; + RMEw(DECW); + break; case 0x10: /* CALL Ev */ if (rm >= 0xc0 ) {GetEArw;Push_16(GETIP);SETIP(*earw);} else {GetEAa;Push_16(GETIP);SETIP(LoadMw(eaa));} diff --git a/src/cpu/core_16/prefix_66.h b/src/cpu/core_16/prefix_66.h index 60cb966..47ee3d6 100644 --- a/src/cpu/core_16/prefix_66.h +++ b/src/cpu/core_16/prefix_66.h @@ -155,11 +155,8 @@ switch(Fetchb()) { SegPrefix_66(gs);break; case 0x67: /* Address Size Prefix */ #ifdef CPU_PREFIX_67 - prefix.mark|=PREFIX_ADDR; -#ifdef CPU_PREFIX_COUNT - prefix.count++; -#endif - lookupEATable=EAPrefixTable[prefix.mark]; + core_16.prefixes^=PREFIX_ADDR; + lookupEATable=EAPrefixTable[core_16.prefixes]; goto restart_66; #else NOTDONE; @@ -167,31 +164,13 @@ switch(Fetchb()) { case 0x68: /* PUSH Id */ Push_32(Fetchd());break; case 0x69: /* IMUL Gd,Ed,Id */ - { - GetRMrd; - Bit64s res; - if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*eards) * (Bit64s)Fetchds();} - else {GetEAa;res=(Bit64s)LoadMds(eaa) * (Bit64s)Fetchds();} - *rmrd=(Bit32s)(res); - flags.type=t_MUL; - if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;} - else {flags.cf=true;flags.of=true;} - break; - } + RMGdEdOp3(DIMULD,Fetchds()); + break; case 0x6a: /* PUSH Ib */ Push_32(Fetchbs());break; case 0x6b: /* IMUL Gd,Ed,Ib */ - { - GetRMrd; - Bit64s res; - if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*eards) * (Bit64s)Fetchbs();} - else {GetEAa;res=(Bit64s)LoadMds(eaa) * (Bit64s)Fetchbs();} - *rmrd=(Bit32s)(res); - flags.type=t_MUL; - if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;} - else {flags.cf=true;flags.of=true;} - break; - } + RMGdEdOp3(DIMULD,Fetchbs()); + break; case 0x81: /* Grpl Ed,Id */ { GetRM; @@ -276,13 +255,13 @@ switch(Fetchb()) { break; } case 0x8c: - LOG(LOG_CPU,"CPU:66:8c looped back"); + LOG(LOG_CPU,LOG_NORMAL)("CPU:66:8c looped back"); break; case 0x8d: /* LEA */ { - prefix.segbase=0; - prefix.mark|=PREFIX_SEG; - lookupEATable=EAPrefixTable[prefix.mark]; + core_16.segbase=0; + core_16.prefixes|=PREFIX_SEG; + lookupEATable=EAPrefixTable[core_16.prefixes]; GetRMrd;GetEAa; *rmrd=(Bit32u)eaa; break; @@ -324,35 +303,33 @@ switch(Fetchb()) { else reg_edx=0; break; case 0x9c: /* PUSHFD */ - { - Bit32u pflags= - (get_CF() << 0) | (get_PF() << 2) | (get_AF() << 4) | - (get_ZF() << 6) | (get_SF() << 7) | (flags.tf << 8) | - (flags.intf << 9) |(flags.df << 10) | (get_OF() << 11) | - (flags.io << 12) | (flags.nt <<14); - Push_32(pflags); - break; - } + FillFlags(); + Push_32(flags.word); + break; case 0x9d: /* POPFD */ - { - Bit16u val=(Bit16u)(Pop_32()&0xffff); - Save_Flagsw(val); - break; - } + 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[prefix.mark]()); - } + reg_eax=LoadMd(GetEADirect[core_16.prefixes]()); break; case 0xa3: /* MOV Ow,EAX */ - { - SaveMd(GetEADirect[prefix.mark](),reg_eax); - } + SaveMd(GetEADirect[core_16.prefixes](),reg_eax); break; case 0xa5: /* MOVSD */ { stringSI;stringDI;SaveMd(to,LoadMd(from)); - if (flags.df) { reg_si-=4;reg_di-=4; } + 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; @@ -363,7 +340,7 @@ switch(Fetchb()) { { stringDI; SaveMd(to,reg_eax); - if (flags.df) { reg_di-=4; } + if (GETFLAG(DF)) { reg_di-=4; } else {reg_di+=4;} break; } @@ -371,7 +348,7 @@ switch(Fetchb()) { { stringSI; reg_eax=LoadMd(from); - if (flags.df) { reg_si-=4;} + if (GETFLAG(DF)) { reg_si-=4;} else {reg_si+=4;} break; } @@ -379,7 +356,7 @@ switch(Fetchb()) { { stringDI; CMPD(reg_eax,LoadMd(to),LoadRd,0); - if (flags.df) { reg_di-=4; } + if (GETFLAG(DF)) { reg_di-=4; } else {reg_di+=4;} break; } @@ -424,34 +401,42 @@ switch(Fetchb()) { 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 */ - prefix.count++; Repeat_Normal(false,true); continue; case 0xf3: /* REPZ */ - prefix.count++; Repeat_Normal(true,true); continue; case 0xf7: /* GRP3 Ed(,Id) */ { - union { Bit64u u;Bit64s s;} temp; - union {Bit64u u;Bit64s s;} quotient; GetRM; - switch (rm & 0x38) { + switch ((rm & 0x38)>>3) { case 0x00: /* TEST Ed,Id */ - case 0x08: /* TEST Ed,Id Undocumented*/ + case 0x01: /* TEST Ed,Id Undocumented*/ { if (rm >= 0xc0 ) {GetEArd;TESTD(*eard,Fetchd(),LoadRd,SaveRd);} else {GetEAa;TESTD(eaa,Fetchd(),LoadMd,SaveMd);} break; } - case 0x10: /* NOT Ed */ + case 0x02: /* NOT Ed */ { if (rm >= 0xc0 ) {GetEArd;*eard=~*eard;} else {GetEAa;SaveMd(eaa,~LoadMd(eaa));} break; } - case 0x18: /* NEG Ed */ + case 0x03: /* NEG Ed */ { flags.type=t_NEGd; if (rm >= 0xc0 ) { @@ -463,60 +448,18 @@ switch(Fetchb()) { } break; } - case 0x20: /* MUL EAX,Ed */ - { - flags.type=t_MUL; - if (rm >= 0xc0 ) {GetEArd;temp.u=(Bit64u)reg_eax * (Bit64u)(*eard);} - else {GetEAa;temp.u=(Bit64u)reg_eax * (Bit64u)LoadMd(eaa);} - reg_eax=(Bit32u)(temp.u & 0xffffffff);reg_edx=(Bit32u)(temp.u >> 32); - flags.cf=flags.of=(reg_edx !=0); - break; - } - case 0x28: /* IMUL EAX,Ed */ - { - flags.type=t_MUL; - if (rm >= 0xc0 ) {GetEArd;temp.s=((Bit64s)((Bit32s)reg_eax) * (Bit64s)(*eards));} - else {GetEAa;temp.s=((Bit64s)((Bit32s)reg_eax) * (Bit64s)(LoadMds(eaa)));} - reg_eax=Bit32u(temp.s & 0xffffffff);reg_edx=(Bit32u)(temp.s >> 32); - if ( (reg_edx==0xffffffff) && (reg_eax & 0x80000000) ) { - flags.cf=flags.of=false; - } else if ( (reg_edx==0x00000000) && (reg_eax<0x80000000) ) { - flags.cf=flags.of=false; - } else { - flags.cf=flags.of=true; - } - break; - } - case 0x30: /* DIV Ed */ - { -// flags.type=t_DIV; - Bit32u val; - if (rm >= 0xc0 ) {GetEArd;val=*eard;} - else {GetEAa;val=LoadMd(eaa);} - if (val==0) {INTERRUPT(0);break;} - temp.u=(((Bit64u)reg_edx)<<32)|reg_eax; - quotient.u=temp.u/val; - reg_edx=(Bit32u)(temp.u % val); - reg_eax=(Bit32u)(quotient.u & 0xffffffff); - if (quotient.u>0xffffffff) - INTERRUPT(0); - break; - } - case 0x38: /* IDIV Ed */ - { -// flags.type=t_DIV; - Bit32s val; - if (rm >= 0xc0 ) {GetEArd;val=*eards;} - else {GetEAa;val=LoadMds(eaa);} - if (val==0) {INTERRUPT(0);break;} - temp.s=(((Bit64u)reg_edx)<<32)|reg_eax; - quotient.s=(temp.s/val); - reg_edx=(Bit32s)(temp.s % val); - reg_eax=(Bit32s)(quotient.s); - if (quotient.s!=(Bit32s)reg_eax) - INTERRUPT(0); - 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; } @@ -525,14 +468,10 @@ switch(Fetchb()) { GetRM; switch (rm & 0x38) { case 0x00: /* INC Ed */ - flags.cf=get_CF();flags.type=t_INCd; - if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard+=1;} - else {GetEAa;flags.result.d=LoadMd(eaa)+1;SaveMd(eaa,flags.result.d);} + RMEd(INCD); break; case 0x08: /* DEC Ed */ - flags.cf=get_CF();flags.type=t_DECd; - if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard-=1;} - else {GetEAa;flags.result.d=LoadMd(eaa)-1;SaveMd(eaa,flags.result.d);} + RMEd(DECD); break; case 0x30: /* Push Ed */ if (rm >= 0xc0 ) {GetEArd;Push_32(*eard);} diff --git a/src/cpu/core_16/prefix_66_of.h b/src/cpu/core_16/prefix_66_of.h index fa972dc..0738eda 100644 --- a/src/cpu/core_16/prefix_66_of.h +++ b/src/cpu/core_16/prefix_66_of.h @@ -17,8 +17,55 @@ */ 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; @@ -41,26 +88,19 @@ switch (Fetchb()) { break; } - case 0xb6: /* MOVZX Gd,Eb */ + case 0xb6: /* MOVZX Gd,Eb */ { GetRMrd; if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;} else {GetEAa;*rmrd=LoadMb(eaa);} break; } - case 0xaf: /* IMUL Gd,Ed */ + case 0xaf: /* IMUL Gd,Ed */ { - GetRMrd; - Bit64s res; - if (rm >= 0xc0 ) {GetEArd;res=((Bit64s)((Bit32s)*rmrd) * (Bit64s)((Bit32s)*eards));} - else {GetEAa;res=((Bit64s)((Bit32s)*rmrd) * (Bit64s)LoadMds(eaa));} - *rmrd=(Bit32s)(res); - flags.type=t_MUL; - if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;} - else {flags.cf=true;flags.of=true;} + RMGdEdOp3(DIMULD,*rmrd); break; }; - case 0xb7: /* MOVXZ Gd,Ew */ + case 0xb7: /* MOVXZ Gd,Ew */ { GetRMrd; if (rm >= 0xc0 ) {GetEArw;*rmrd=*earw;} @@ -73,7 +113,7 @@ switch (Fetchb()) { if (rm >= 0xc0 ) { GetEArd; Bit32u mask=1 << (Fetchb() & 31); - flags.cf=(*eard & mask)>0; + SETFLAGBIT(CF,(*eard & mask)); switch (rm & 0x38) { case 0x20: /* BT */ break; @@ -84,7 +124,7 @@ switch (Fetchb()) { *eard&=~mask; break; case 0x38: /* BTC */ - if (flags.cf) *eard&=~mask; + if (GETFLAG(CF)) *eard&=~mask; else *eard|=mask; break; default: @@ -93,7 +133,7 @@ switch (Fetchb()) { } else { GetEAa;Bit32u old=LoadMd(eaa); Bit32u mask=1 << (Fetchb() & 31); - flags.cf=(old & mask)>0; + SETFLAGBIT(CF,(old & mask)); switch (rm & 0x38) { case 0x20: /* BT */ break; @@ -104,7 +144,7 @@ switch (Fetchb()) { SaveMd(eaa,old & ~mask); break; case 0x38: /* BTC */ - if (flags.cf) old&=~mask; + if (GETFLAG(CF)) old&=~mask; else old|=mask; SaveMd(eaa,old); break; @@ -122,11 +162,11 @@ switch (Fetchb()) { Bit32u mask=1 << (*rmrd & 31); if (rm >= 0xc0 ) { GetEArd; - flags.cf=(*eard & mask)>0; + SETFLAGBIT(CF,(*eard & mask)); *eard^=mask; } else { GetEAa;Bit32u old=LoadMd(eaa); - flags.cf=(old & mask)>0; + SETFLAGBIT(CF,(old & mask)); SaveMd(eaa,old ^ mask); } if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } @@ -139,11 +179,11 @@ switch (Fetchb()) { if (rm >= 0xc0) { GetEArd; value=*eard; } else { GetEAa; value=LoadMd(eaa); } if (value==0) { - flags.zf = true; + SETFLAGBIT(ZF,true); } else { result = 0; while ((value & 0x01)==0) { result++; value>>=1; } - flags.zf = false; + SETFLAGBIT(ZF,false); *rmrd = result; } flags.type=t_UNKNOWN; @@ -156,11 +196,11 @@ switch (Fetchb()) { if (rm >= 0xc0) { GetEArd; value=*eard; } else { GetEAa; value=LoadMd(eaa); } if (value==0) { - flags.zf = true; + SETFLAGBIT(ZF,true); } else { result = 35; // Operandsize-1 while ((value & 0x80000000)==0) { result--; value<<=1; } - flags.zf = false; + SETFLAGBIT(ZF,false); *rmrd = result; } flags.type=t_UNKNOWN; @@ -169,14 +209,14 @@ switch (Fetchb()) { case 0xbe: /* MOVSX Gd,Eb */ { GetRMrd; - if (rm >= 0xc0 ) {GetEArb;*rmrd=*earbs;} + if (rm >= 0xc0 ) {GetEArb;*rmrd=*(Bit8s *)earb;} else {GetEAa;*rmrd=LoadMbs(eaa);} break; } case 0xbf: /* MOVSX Gd,Ew */ { GetRMrd; - if (rm >= 0xc0 ) {GetEArw;*rmrd=*earws;} + if (rm >= 0xc0 ) {GetEArw;*rmrd=*(Bit16s *)earw;} else {GetEAa;*rmrd=LoadMws(eaa);} break; } diff --git a/src/cpu/core_16/prefix_of.h b/src/cpu/core_16/prefix_of.h index 039f660..f28113c 100644 --- a/src/cpu/core_16/prefix_of.h +++ b/src/cpu/core_16/prefix_of.h @@ -19,94 +19,122 @@ switch(Fetchb()) { case 0x00: /* GRP 6 */ { - INTERRUPT(6); - break; - GetRM; - switch (rm & 0x38) { - case 0x00: + 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: - E_Exit("CPU:GRP6:Illegal call %2X",(rm>>3) &3); + LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which); } } break; - - case 0x01: /* GRP 7 */ + 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; - switch (rm & 0x38) { - case 0x20: /* SMSW */ - /* Let's seriously fake this call */ - if (rm>0xc0) {GetEArw;*earw=0;} - else {GetEAa;SaveMw(eaa,0);} - break; - default: - E_Exit("CPU:GRP7:Illegal call %2X",(rm>>3) &3); + 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; - /* 0x02 LAR Gw,Ew (286) */ - /* 0x03 LSL Gw,Ew (286) */ - /* 0x05 LOADALL (286 only?) */ - /* 0x06 CLTS (286) */ - /* 0x07 LOADALL (386 only?) */ - /* 0x08 INVD (486) */ - /* 0x02 WBINVD (486) */ - /* 0x10 UMOV Eb,Gb (386) */ - /* 0x11 UMOV Ew,Gw (386) */ - /* 0x12 UMOV Gb,Eb (386) */ - /* 0x13 UMOV Gw,Ew (386) */ - /* 0x20 MOV Rd,CRx (386) */ - /* 0x21 MOV Rd,DRx (386) */ - /* 0x22 MOV CRx,Rd (386) */ - /* 0x23 MOV DRx,Rd (386) */ case 0x23: /* MOV DRx,Rd */ { GetRM; - LOG(LOG_CPU,"CPU:0F:23 does nothing"); + Bitu which=(rm >> 3) & 7; + if (rm >= 0xc0 ) { + GetEArd; + } else { + GetEAa; + LOG(LOG_CPU,LOG_ERROR)("MOV DR%,XXX with non-register",which); + } } break; - /* 0x24 MOV Rd,TRx (386) */ - /* 0x26 MOV TRx,Rd (386) */ - /* 0x30 WRMSR (P5) */ - /* 0x31 RDTSC (P5) */ - /* 0x32 RDMSR (P5) */ - /* 0x33 RDPMC (P6) */ - /* 0x40-4F CMOVcc Gw,Ew (P6) */ - /* 0x50 PAVEB Rq,Eq (CYRIX MMX) */ - /* 0x51 PADDSIW Rq,Eq (CYRIX MMX) */ - /* 0x52 PMAGW Rq,Eq (CYRIX MMX) */ - /* 0x54 PDISTIB Rq,Eq (CYRIX MMX) */ - /* 0x55 PSUBSIW Rq,Eq (CYRIX MMX) */ - /* 0x58 PMVZB Rq,Eq (CYRIX MMX) */ - /* 0x59 PMULHRW Rq,Eq (CYRIX MMX) */ - /* 0x5A PMVNZB Rq,Eq (CYRIX MMX) */ - /* 0x5B PMVLZB Rq,Eq (CYRIX MMX) */ - /* 0x5C PMVGEZB Rq,Eq (CYRIX MMX) */ - /* 0x5D PMULHRIW Rq,Eq (CYRIX MMX) */ - /* 0x5E PMACHRIW Rq,Eq (CYRIX MMX) */ - /* 0x60 PUNPCKLBW Rq,Eq (MMX) */ - /* 0x61 PUNPCKLWD Rq,Eq (MMX) */ - /* 0x62 PUNPCKLDQ Rq,Eq (MMX) */ - /* 0x63 PACKSSWB Rq,Eq (MMX) */ - /* 0x64 PCMPGTB Rq,Eq (MMX) */ - /* 0x65 PCMPGTW Rq,Eq (MMX) */ - /* 0x66 PCMPGTD Rq,Eq (MMX) */ - /* 0x67 PACKUSWB Rq,Eq (MMX) */ - /* 0x68 PUNPCKHBW Rq,Eq (MMX) */ - /* 0x69 PUNPCKHWD Rq,Eq (MMX) */ - /* 0x6A PUNPCKHDQ Rq,Eq (MMX) */ - /* 0x6B PACKSSDW Rq,Eq (MMX) */ - /* 0x6E MOVD Rq,Ed (MMX) */ - /* 0x6F MOVQ Rq,Eq (MMX) */ - /* 0x71 PSLLW/PSRAW/PSRLW Rq,Ib (MMX) */ - /* 0x72 PSLLD/PSRAD/PSRLD Rq,Ib (MMX) */ - /* 0x73 PSLLQ/PSRLQ Rq,Ib (MMX) */ - /* 0x74 PCMPEQB Rq,Eq (MMX) */ - /* 0x75 PCMPEQW Rq,Eq (MMX) */ - /* 0x76 PCMPEQD Rq,Eq (MMX) */ - /* 0x77 EMMS (MMX) */ - /* 0x7E MOVD Ed,Rq (MMX) */ - /* 0x7F MOVQ Ed,Rq (MMX) */ case 0x80: /* JO */ JumpSIw(get_OF());break; case 0x81: /* JNO */ @@ -177,90 +205,64 @@ switch(Fetchb()) { Push_16(SegValue(fs));break; case 0xa1: /* POP FS */ SegSet16(fs,Pop_16());break; - /* 0xa2 CPUID */ + case 0xa2: + CPU_CPUID(); + break; case 0xa3: /* BT Ew,Gw */ { GetRMrw; Bit16u mask=1 << (*rmrw & 15); if (rm >= 0xc0 ) { GetEArw; - flags.cf=(*earw & mask)>0; + SETFLAGBIT(CF,(*earw & mask)); } else { GetEAa;Bit16u old=LoadMw(eaa); - flags.cf=(old & mask)>0; + 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 */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;DSHLW(*earw,*rmrw,Fetchb(),LoadRw,SaveRw);} - else {GetEAa;DSHLW(eaa,*rmrw,Fetchb(),LoadMw,SaveMw);} - break; - } + RMEwGwOp3(DSHLW,Fetchb()); + break; case 0xa5: /* SHLD Ew,Gw,CL */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;DSHLW(*earw,*rmrw,reg_cl,LoadRw,SaveRw);} - else {GetEAa;DSHLW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);} - break; - } - /* 0xa6 XBTS (early 386 only) CMPXCHG (early 486 only) */ - /* 0xa7 IBTS (early 386 only) CMPXCHG (early 486 only) */ + RMEwGwOp3(DSHLW,reg_cl); + break; case 0xa8: /* PUSH GS */ Push_16(SegValue(gs));break; case 0xa9: /* POP GS */ SegSet16(gs,Pop_16());break; - /* 0xaa RSM */ case 0xab: /* BTS Ew,Gw */ { GetRMrw; Bit16u mask=1 << (*rmrw & 15); if (rm >= 0xc0 ) { GetEArw; - flags.cf=(*earw & mask)>0; + SETFLAGBIT(CF,(*earw & mask)); *earw|=mask; } else { GetEAa;Bit16u old=LoadMw(eaa); - flags.cf=(old & mask)>0; + 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 */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;DSHRW(*earw,*rmrw,Fetchb(),LoadRw,SaveRw);} - else {GetEAa;DSHRW(eaa,*rmrw,Fetchb(),LoadMw,SaveMw);} - break; - } + RMEwGwOp3(DSHRW,Fetchb()); + break; case 0xad: /* SHRD Ew,Gw,CL */ - { - GetRMrw; - if (rm >= 0xc0 ) {GetEArw;DSHRW(*earw,*rmrw,reg_cl,LoadRw,SaveRw);} - else {GetEAa;DSHRW(eaa,*rmrw,reg_cl,LoadMw,SaveMw);} - break; - } + RMEwGwOp3(DSHRW,reg_cl); + break; case 0xaf: /* IMUL Gw,Ew */ - { - GetRMrw; - Bit32s res; - if (rm >= 0xc0 ) {GetEArw;res=(Bit32s)(*rmrw) * (Bit32s)(*earws);} - else {GetEAa;res=(Bit32s)(*rmrw) *(Bit32s)LoadMws(eaa);} - *rmrw=res & 0xFFFF; - flags.type=t_MUL; - if ((res> -32768) && (res<32767)) {flags.cf=false;flags.of=false;} - else {flags.cf=true;flags.of=true;} - break; - } - /* 0xb0 CMPXCHG Eb,Gb */ - /* 0xb1 CMPXCHG Ew,Gw */ + 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 */ @@ -269,11 +271,11 @@ switch(Fetchb()) { Bit16u mask=1 << (*rmrw & 15); if (rm >= 0xc0 ) { GetEArw; - flags.cf=(*earw & mask)>0; + SETFLAGBIT(CF,(*earw & mask)); *earw&= ~mask; } else { GetEAa;Bit16u old=LoadMw(eaa); - flags.cf=(old & mask)>0; + SETFLAGBIT(CF,(old & mask)); SaveMw(eaa,old & ~mask); } if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } @@ -309,10 +311,10 @@ switch(Fetchb()) { case 0xba: /* GRP8 Ew,Ib */ { GetRM; - Bit16u mask=1 << (Fetchb() & 15); if (rm >= 0xc0 ) { GetEArw; - flags.cf=(*earw & mask)>0; + Bit16u mask=1 << (Fetchb() & 15); + SETFLAGBIT(CF,(*earw & mask)); switch (rm & 0x38) { case 0x20: /* BT */ break; @@ -330,7 +332,8 @@ switch(Fetchb()) { } } else { GetEAa;Bit16u old=LoadMw(eaa); - flags.cf=(old & mask)>0; + Bit16u mask=1 << (Fetchb() & 15); + SETFLAGBIT(CF,(old & mask)); switch (rm & 0x38) { case 0x20: /* BT */ break; @@ -356,11 +359,11 @@ switch(Fetchb()) { Bit16u mask=1 << (*rmrw & 15); if (rm >= 0xc0 ) { GetEArw; - flags.cf=(*earw & mask)>0; + SETFLAGBIT(CF,(*earw & mask)); *earw^=mask; } else { GetEAa;Bit16u old=LoadMw(eaa); - flags.cf=(old & mask)>0; + SETFLAGBIT(CF,(old & mask)); SaveMw(eaa,old ^ mask); } if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } @@ -373,11 +376,11 @@ switch(Fetchb()) { if (rm >= 0xc0) { GetEArw; value=*earw; } else { GetEAa; value=LoadMw(eaa); } if (value==0) { - flags.zf = true; + SETFLAGBIT(ZF,true); } else { result = 0; while ((value & 0x01)==0) { result++; value>>=1; } - flags.zf = false; + SETFLAGBIT(ZF,false); *rmrw = result; } flags.type=t_UNKNOWN; @@ -390,11 +393,11 @@ switch(Fetchb()) { if (rm >= 0xc0) { GetEArw; value=*earw; } else { GetEAa; value=LoadMw(eaa); } if (value==0) { - flags.zf = true; + SETFLAGBIT(ZF,true); } else { result = 15; // Operandsize-1 while ((value & 0x8000)==0) { result--; value<<=1; } - flags.zf = false; + SETFLAGBIT(ZF,false); *rmrw = result; } flags.type=t_UNKNOWN; @@ -403,14 +406,10 @@ switch(Fetchb()) { case 0xbe: /* MOVSX Gw,Eb */ { GetRMrw; - if (rm >= 0xc0 ) {GetEArb;*rmrw=*earbs;} + if (rm >= 0xc0 ) {GetEArb;*rmrw=*(Bit8s *)earb;} else {GetEAa;*rmrw=LoadMbs(eaa);} break; } - /* 0xc0 XADD Eb,Gb (486) */ - /* 0xc1 XADD Ew,Gw (486) */ - /* 0xc7 CMPXCHG8B Mq (P5) */ - /* 0xc8-cf BSWAP Rw (odd behavior,486) */ case 0xc8: BSWAP(reg_eax); break; case 0xc9: BSWAP(reg_ecx); break; case 0xca: BSWAP(reg_edx); break; @@ -420,35 +419,6 @@ switch(Fetchb()) { case 0xce: BSWAP(reg_esi); break; case 0xcf: BSWAP(reg_edi); break; - /* 0xd1 PSRLW Rq,Eq (MMX) */ - /* 0xd2 PSRLD Rq,Eq (MMX) */ - /* 0xd3 PSRLQ Rq,Eq (MMX) */ - /* 0xd5 PMULLW Rq,Eq (MMX) */ - /* 0xd8 PSUBUSB Rq,Eq (MMX) */ - /* 0xd9 PSUBUSW Rq,Eq (MMX) */ - /* 0xdb PAND Rq,Eq (MMX) */ - /* 0xdc PADDUSB Rq,Eq (MMX) */ - /* 0xdd PADDUSW Rq,Eq (MMX) */ - /* 0xdf PANDN Rq,Eq (MMX) */ - /* 0xe1 PSRAW Rq,Eq (MMX) */ - /* 0xe2 PSRAD Rq,Eq (MMX) */ - /* 0xe5 PMULHW Rq,Eq (MMX) */ - /* 0xe8 PSUBSB Rq,Eq (MMX) */ - /* 0xe9 PSUBSW Rq,Eq (MMX) */ - /* 0xeb POR Rq,Eq (MMX) */ - /* 0xec PADDSB Rq,Eq (MMX) */ - /* 0xed PADDSW Rq,Eq (MMX) */ - /* 0xef PXOR Rq,Eq (MMX) */ - /* 0xf1 PSLLW Rq,Eq (MMX) */ - /* 0xf2 PSLLD Rq,Eq (MMX) */ - /* 0xf3 PSLLQ Rq,Eq (MMX) */ - /* 0xf5 PMADDWD Rq,Eq (MMX) */ - /* 0xf8 PSUBB Rq,Eq (MMX) */ - /* 0xf9 PSUBW Rq,Eq (MMX) */ - /* 0xfa PSUBD Rq,Eq (MMX) */ - /* 0xfc PADDB Rq,Eq (MMX) */ - /* 0xfd PADDW Rq,Eq (MMX) */ - /* 0xfe PADDD Rq,Eq (MMX) */ default: SUBIP(1); E_Exit("CPU:Opcode 0F:%2X Unhandled",Fetchb()); diff --git a/src/cpu/core_16/start.h b/src/cpu/core_16/start.h deleted file mode 100644 index f54a1e2..0000000 --- a/src/cpu/core_16/start.h +++ /dev/null @@ -1,20 +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. - */ - -/* Setup the CS:IP and SS:SP Pointers */ -LOADIP; diff --git a/src/cpu/core_16/support.h b/src/cpu/core_16/support.h index 93d48c6..8770a7d 100644 --- a/src/cpu/core_16/support.h +++ b/src/cpu/core_16/support.h @@ -16,36 +16,60 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -EAPoint IPPoint; -#define SUBIP(a) IPPoint-=a -#define SETIP(a) IPPoint=SegBase(cs)+a -#define GETIP (Bit16u)(IPPoint-SegBase(cs)) +#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 IPPoint=SegBase(cs)+reg_ip +#define LOADIP core_16.ip_lookup=SegBase(cs)+reg_ip + +#define LEAVECORE \ + SAVEIP; \ + FillFlags(); static INLINE void ADDIP(Bit16u add) { - IPPoint=SegBase(cs)+((Bit16u)(((Bit16u)(IPPoint-SegBase(cs)))+(Bit16u)add)); + core_16.ip_lookup=SegBase(cs)+((Bit16u)(((Bit16u)(core_16.ip_lookup-SegBase(cs)))+(Bit16u)add)); } static INLINE void ADDIPFAST(Bit16s blah) { - IPPoint+=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(IPPoint); - IPPoint+=1; + Bit8u temp=LoadMb(core_16.ip_lookup); + core_16.ip_lookup+=1; return temp; } static INLINE Bit16u Fetchw() { - Bit16u temp=LoadMw(IPPoint); - IPPoint+=2; + Bit16u temp=LoadMw(core_16.ip_lookup); + core_16.ip_lookup+=2; return temp; } static INLINE Bit32u Fetchd() { - Bit32u temp=LoadMd(IPPoint); - IPPoint+=4; + Bit32u temp=LoadMd(core_16.ip_lookup); + core_16.ip_lookup+=4; return temp; } @@ -82,15 +106,42 @@ static INLINE Bit32u Pop_32() { 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 \ - EAPoint to; \ + PhysPt to; \ to=SegBase(es)+reg_di #define stringSI \ - EAPoint from; \ - if (prefix.mark & PREFIX_SEG) { \ - from=(prefix.segbase+reg_si); \ - PrefixReset; \ + PhysPt from; \ + if (core_16.prefixes & PREFIX_SEG) { \ + from=(core_16.segbase+reg_si); \ } else { \ from=SegBase(ds)+reg_si; \ } @@ -99,60 +150,47 @@ static INLINE Bit32u Pop_32() { #include "table_ea.h" #include "../modrm.h" - -static Bit8s table_df_8[2]={1,-1}; -static Bit16s table_df_16[2]={2,-2}; -static Bit32s table_df_32[2]={4,-4}; - - static void Repeat_Normal(bool testz,bool prefix_66) { PhysPt base_si,base_di; Bit16s direct; - if (flags.df) direct=-1; + if (GETFLAG(DF)) direct=-1; else direct=1; base_di=SegBase(es); - if (prefix.mark & PREFIX_ADDR) E_Exit("Unhandled 0x67 prefixed string op"); + if (core_16.prefixes & PREFIX_ADDR) E_Exit("Unhandled 0x67 prefixed string op"); rep_again: - if (prefix.mark & PREFIX_SEG) { - base_si=(prefix.segbase); + if (core_16.prefixes & PREFIX_SEG) { + base_si=(core_16.segbase); } else { base_si=SegBase(ds); } switch (Fetchb()) { case 0x26: /* ES Prefix */ - prefix.segbase=SegBase(es); - prefix.mark|=PREFIX_SEG; - prefix.count++; + core_16.segbase=SegBase(es); + core_16.prefixes|=PREFIX_SEG; goto rep_again; case 0x2e: /* CS Prefix */ - prefix.segbase=SegBase(cs); - prefix.mark|=PREFIX_SEG; - prefix.count++; + core_16.segbase=SegBase(cs); + core_16.prefixes|=PREFIX_SEG; goto rep_again; case 0x36: /* SS Prefix */ - prefix.segbase=SegBase(ss); - prefix.mark|=PREFIX_SEG; - prefix.count++; + core_16.segbase=SegBase(ss); + core_16.prefixes|=PREFIX_SEG; goto rep_again; case 0x3e: /* DS Prefix */ - prefix.segbase=SegBase(ds); - prefix.mark|=PREFIX_SEG; - prefix.count++; + core_16.segbase=SegBase(ds); + core_16.prefixes|=PREFIX_SEG; goto rep_again; case 0x64: /* FS Prefix */ - prefix.segbase=SegBase(fs); - prefix.mark|=PREFIX_SEG; - prefix.count++; + core_16.segbase=SegBase(fs); + core_16.prefixes|=PREFIX_SEG; goto rep_again; case 0x65: /* GS Prefix */ - prefix.segbase=SegBase(gs); - prefix.mark|=PREFIX_SEG; - prefix.count++; + core_16.segbase=SegBase(gs); + core_16.prefixes|=PREFIX_SEG; goto rep_again; case 0x66: /* Size Prefix */ - prefix.count++; prefix_66=!prefix_66; goto rep_again; case 0x6c: /* REP INSB */ @@ -352,58 +390,12 @@ rep_again: } break; default: - IPPoint--; - LOG(LOG_CPU|LOG_ERROR,"Unhandled REP Prefix %X",Fetchb()); + 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 */ - IPPoint-=(prefix.count+2); /* Rep instruction and whatever string instruction */ -normalexit: - PrefixReset; + core_16.ip_lookup=core_16.ip_start; +normalexit:; } -//flags.io and nt shouldn't be compiled for 386 -#ifdef CPU_386 -#define Save_Flagsw(FLAGW) \ -{ \ - flags.type=t_UNKNOWN; \ - flags.cf =(FLAGW & 0x001)>0;flags.pf =(FLAGW & 0x004)>0; \ - flags.af =(FLAGW & 0x010)>0;flags.zf =(FLAGW & 0x040)>0; \ - flags.sf =(FLAGW & 0x080)>0;flags.tf =(FLAGW & 0x100)>0; \ - flags.intf =(FLAGW & 0x200)>0; \ - flags.df =(FLAGW & 0x400)>0;flags.of =(FLAGW & 0x800)>0; \ - flags.io =(FLAGW >> 12) & 0x03; \ - flags.nt =(FLAGW & 0x4000)>0; \ - if (flags.intf && PIC_IRQCheck) { \ - SAVEIP; \ - PIC_runIRQs(); \ - LOADIP; \ - } \ - if (flags.tf) { \ - cpudecoder=&CPU_Real_16_Slow_Decode_Trap; \ - goto decode_end; \ - } \ -} - -#else - -#define Save_Flagsw(FLAGW) \ -{ \ - flags.type=t_UNKNOWN; \ - flags.cf =(FLAGW & 0x001)>0;flags.pf =(FLAGW & 0x004)>0; \ - flags.af =(FLAGW & 0x010)>0;flags.zf =(FLAGW & 0x040)>0; \ - flags.sf =(FLAGW & 0x080)>0;flags.tf =(FLAGW & 0x100)>0; \ - flags.intf =(FLAGW & 0x200)>0; \ - flags.df =(FLAGW & 0x400)>0;flags.of =(FLAGW & 0x800)>0; \ - if (flags.intf && PIC_IRQCheck) { \ - SAVEIP; \ - PIC_runIRQs(); \ - LOADIP; \ - } \ - if (flags.tf) { \ - cpudecoder=&CPU_Real_16_Slow_Decode_Trap; \ - goto decode_end; \ - } \ -} - -#endif diff --git a/src/cpu/core_16/table_ea.h b/src/cpu/core_16/table_ea.h index 9393a25..cf7131f 100644 --- a/src/cpu/core_16/table_ea.h +++ b/src/cpu/core_16/table_ea.h @@ -18,8 +18,8 @@ /* Some variables for EA Loolkup */ -typedef EAPoint (*GetEATable[256])(void); -typedef EAPoint (*EA_LookupHandler)(void); +typedef PhysPt (*GetEATable[256])(void); +typedef PhysPt (*EA_LookupHandler)(void); static GetEATable * lookupEATable; @@ -28,64 +28,51 @@ static GetEATable * lookupEATable; #define PREFIX_ADDR 0x2 #define PREFIX_SEG_ADDR 0x3 -static struct { - Bitu mark; - Bitu count; - EAPoint segbase; -} prefix; /* Gets initialized at the bottem, can't seem to declare forward references */ static GetEATable * EAPrefixTable[4]; #define SegPrefix(blah) \ - prefix.segbase=SegBase(blah); \ - prefix.mark|=PREFIX_SEG; \ - prefix.count++; \ - lookupEATable=EAPrefixTable[prefix.mark]; \ + core_16.segbase=SegBase(blah); \ + core_16.prefixes|=PREFIX_SEG; \ + lookupEATable=EAPrefixTable[core_16.prefixes]; \ goto restart; #define SegPrefix_66(blah) \ - prefix.segbase=SegBase(blah); \ - prefix.mark|=PREFIX_SEG; \ - prefix.count++; \ - lookupEATable=EAPrefixTable[prefix.mark]; \ + core_16.segbase=SegBase(blah); \ + core_16.prefixes|=PREFIX_SEG; \ + lookupEATable=EAPrefixTable[core_16.prefixes]; \ goto restart_66; -#define PrefixReset \ - prefix.mark=PREFIX_NONE; \ - prefix.count=0; \ - lookupEATable=EAPrefixTable[PREFIX_NONE]; - - /* The MOD/RM Decoder for EA for this decoder's addressing modes */ -static EAPoint EA_16_00_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); } -static EAPoint EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); } -static EAPoint EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); } -static EAPoint EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); } -static EAPoint EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); } -static EAPoint EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); } -static EAPoint EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());} -static EAPoint EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); } +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 EAPoint EA_16_40_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); } -static EAPoint EA_16_41_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); } -static EAPoint EA_16_42_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); } -static EAPoint EA_16_43_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); } -static EAPoint EA_16_44_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchbs()); } -static EAPoint EA_16_45_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchbs()); } -static EAPoint EA_16_46_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchbs()); } -static EAPoint EA_16_47_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchbs()); } +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 EAPoint EA_16_80_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); } -static EAPoint EA_16_81_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); } -static EAPoint EA_16_82_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); } -static EAPoint EA_16_83_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); } -static EAPoint EA_16_84_n(void) { return SegBase(ds)+(Bit16u)(reg_si+Fetchws()); } -static EAPoint EA_16_85_n(void) { return SegBase(ds)+(Bit16u)(reg_di+Fetchws()); } -static EAPoint EA_16_86_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+Fetchws()); } -static EAPoint EA_16_87_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+Fetchws()); } +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 */ @@ -123,34 +110,33 @@ static GetEATable GetEA_16_n={ }; -#define segprefixed(val) EAPoint ret=prefix.segbase+val;PrefixReset;return ret; -static EAPoint EA_16_00_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) } -static EAPoint EA_16_01_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) } -static EAPoint EA_16_02_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si)) } -static EAPoint EA_16_03_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di)) } -static EAPoint EA_16_04_s(void) { segprefixed((Bit16u)(reg_si)) } -static EAPoint EA_16_05_s(void) { segprefixed((Bit16u)(reg_di)) } -static EAPoint EA_16_06_s(void) { segprefixed((Bit16u)(Fetchw())) } -static EAPoint EA_16_07_s(void) { segprefixed((Bit16u)(reg_bx)) } +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 EAPoint EA_16_40_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs())) } -static EAPoint EA_16_41_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs())) } -static EAPoint EA_16_42_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs())) } -static EAPoint EA_16_43_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs())) } -static EAPoint EA_16_44_s(void) { segprefixed((Bit16u)(reg_si+Fetchbs())) } -static EAPoint EA_16_45_s(void) { segprefixed((Bit16u)(reg_di+Fetchbs())) } -static EAPoint EA_16_46_s(void) { segprefixed((Bit16u)(reg_bp+Fetchbs())) } -static EAPoint EA_16_47_s(void) { segprefixed((Bit16u)(reg_bx+Fetchbs())) } +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 EAPoint EA_16_80_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws())) } -static EAPoint EA_16_81_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws())) } -static EAPoint EA_16_82_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws())) } -static EAPoint EA_16_83_s(void) { segprefixed((Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws())) } -static EAPoint EA_16_84_s(void) { segprefixed((Bit16u)(reg_si+Fetchws())) } -static EAPoint EA_16_85_s(void) { segprefixed((Bit16u)(reg_di+Fetchws())) } -static EAPoint EA_16_86_s(void) { segprefixed((Bit16u)(reg_bp+Fetchws())) } -static EAPoint EA_16_87_s(void) { segprefixed((Bit16u)(reg_bx+Fetchws())) } +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 */ @@ -190,9 +176,9 @@ static GetEATable GetEA_16_s={ static Bit32u SIBZero=0; static Bit32u * SIBIndex[8]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_edi }; -INLINE EAPoint Sib(Bitu mode) { +INLINE PhysPt Sib(Bitu mode) { Bit8u sib=Fetchb(); - EAPoint base; + PhysPt base; switch (sib&7) { case 0: /* EAX Base */ base=SegBase(ds)+reg_eax;break; @@ -220,32 +206,32 @@ INLINE EAPoint Sib(Bitu mode) { }; -static EAPoint EA_32_00_n(void) { PrefixReset;return SegBase(ds)+reg_eax; } -static EAPoint EA_32_01_n(void) { PrefixReset;return SegBase(ds)+reg_ecx; } -static EAPoint EA_32_02_n(void) { PrefixReset;return SegBase(ds)+reg_edx; } -static EAPoint EA_32_03_n(void) { PrefixReset;return SegBase(ds)+reg_ebx; } -static EAPoint EA_32_04_n(void) { PrefixReset;return Sib(0);} -static EAPoint EA_32_05_n(void) { PrefixReset;return SegBase(ds)+Fetchd(); } -static EAPoint EA_32_06_n(void) { PrefixReset;return SegBase(ds)+reg_esi; } -static EAPoint EA_32_07_n(void) { PrefixReset;return SegBase(ds)+reg_edi; } +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 EAPoint EA_32_40_n(void) { PrefixReset;return SegBase(ds)+reg_eax+Fetchbs(); } -static EAPoint EA_32_41_n(void) { PrefixReset;return SegBase(ds)+reg_ecx+Fetchbs(); } -static EAPoint EA_32_42_n(void) { PrefixReset;return SegBase(ds)+reg_edx+Fetchbs(); } -static EAPoint EA_32_43_n(void) { PrefixReset;return SegBase(ds)+reg_ebx+Fetchbs(); } -static EAPoint EA_32_44_n(void) { PrefixReset;EAPoint temp=Sib(1);return temp+Fetchbs();} -static EAPoint EA_32_45_n(void) { PrefixReset;return SegBase(ss)+reg_ebp+Fetchbs(); } -static EAPoint EA_32_46_n(void) { PrefixReset;return SegBase(ds)+reg_esi+Fetchbs(); } -static EAPoint EA_32_47_n(void) { PrefixReset;return SegBase(ds)+reg_edi+Fetchbs(); } +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 EAPoint EA_32_80_n(void) { PrefixReset;return SegBase(ds)+reg_eax+Fetchds(); } -static EAPoint EA_32_81_n(void) { PrefixReset;return SegBase(ds)+reg_ecx+Fetchds(); } -static EAPoint EA_32_82_n(void) { PrefixReset;return SegBase(ds)+reg_edx+Fetchds(); } -static EAPoint EA_32_83_n(void) { PrefixReset;return SegBase(ds)+reg_ebx+Fetchds(); } -static EAPoint EA_32_84_n(void) { PrefixReset;EAPoint temp=Sib(2);return temp+Fetchbs();} -static EAPoint EA_32_85_n(void) { PrefixReset;return SegBase(ss)+reg_ebp+Fetchds(); } -static EAPoint EA_32_86_n(void) { PrefixReset;return SegBase(ds)+reg_esi+Fetchds(); } -static EAPoint EA_32_87_n(void) { PrefixReset;return SegBase(ds)+reg_edi+Fetchds(); } +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 */ @@ -282,64 +268,62 @@ static GetEATable GetEA_32_n={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -INLINE EAPoint Sib_s(Bitu mode) { +INLINE PhysPt Sib_s(Bitu mode) { Bit8u sib=Fetchb(); - EAPoint base; + PhysPt base; switch (sib&7) { case 0: /* EAX Base */ - base=prefix.segbase+reg_eax;break; + base=reg_eax;break; case 1: /* ECX Base */ - base=prefix.segbase+reg_ecx;break; + base=reg_ecx;break; case 2: /* EDX Base */ - base=prefix.segbase+reg_edx;break; + base=reg_edx;break; case 3: /* EBX Base */ - base=prefix.segbase+reg_ebx;break; + base=reg_ebx;break; case 4: /* ESP Base */ - base=prefix.segbase+reg_esp;break; + base=reg_esp;break; case 5: /* #1 Base */ if (!mode) { - base=prefix.segbase+Fetchd();break; + base=Fetchd();break; } else { - base=prefix.segbase+reg_ebp;break; + base=reg_ebp;break; } case 6: /* ESI Base */ - base=prefix.segbase+reg_esi;break; + base=reg_esi;break; case 7: /* EDI Base */ - base=prefix.segbase+reg_edi;break; + base=reg_edi;break; } base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); - PrefixReset; return base; }; -#define segprefixed_32(val) EAPoint ret=prefix.segbase+(Bit32u)(val);PrefixReset;return ret; -static EAPoint EA_32_00_s(void) { segprefixed_32(reg_eax); } -static EAPoint EA_32_01_s(void) { segprefixed_32(reg_ecx); } -static EAPoint EA_32_02_s(void) { segprefixed_32(reg_edx); } -static EAPoint EA_32_03_s(void) { segprefixed_32(reg_ebx); } -static EAPoint EA_32_04_s(void) { return Sib_s(0);} -static EAPoint EA_32_05_s(void) { segprefixed_32(Fetchd()); } -static EAPoint EA_32_06_s(void) { segprefixed_32(reg_esi); } -static EAPoint EA_32_07_s(void) { segprefixed_32(reg_edi); } +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 EAPoint EA_32_40_s(void) { segprefixed_32(reg_eax+Fetchbs()); } -static EAPoint EA_32_41_s(void) { segprefixed_32(reg_ecx+Fetchbs()); } -static EAPoint EA_32_42_s(void) { segprefixed_32(reg_edx+Fetchbs()); } -static EAPoint EA_32_43_s(void) { segprefixed_32(reg_ebx+Fetchbs()); } -static EAPoint EA_32_44_s(void) { return Sib_s(1)+Fetchbs();} -static EAPoint EA_32_45_s(void) { segprefixed_32(reg_ebp+Fetchbs()); } -static EAPoint EA_32_46_s(void) { segprefixed_32(reg_esi+Fetchbs()); } -static EAPoint EA_32_47_s(void) { segprefixed_32(reg_edi+Fetchbs()); } +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 EAPoint EA_32_80_s(void) { segprefixed_32(reg_eax+Fetchds()); } -static EAPoint EA_32_81_s(void) { segprefixed_32(reg_ecx+Fetchds()); } -static EAPoint EA_32_82_s(void) { segprefixed_32(reg_edx+Fetchds()); } -static EAPoint EA_32_83_s(void) { segprefixed_32(reg_ebx+Fetchds()); } -static EAPoint EA_32_84_s(void) { return Sib_s(2)+Fetchds();} -static EAPoint EA_32_85_s(void) { segprefixed_32(reg_ebp+Fetchds()); } -static EAPoint EA_32_86_s(void) { segprefixed_32(reg_esi+Fetchds()); } -static EAPoint EA_32_87_s(void) { segprefixed_32(reg_edi+Fetchds()); } +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={ @@ -377,20 +361,20 @@ static GetEATable GetEA_32_s={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static EAPoint GetEADirect_NONE(void) { - EAPoint result=SegBase(ds)+Fetchw(); +static PhysPt GetEADirect_NONE(void) { + PhysPt result=SegBase(ds)+Fetchw(); return result; } -static EAPoint GetEADirect_SEG(void) { - EAPoint result=prefix.segbase+Fetchw();PrefixReset; +static PhysPt GetEADirect_SEG(void) { + PhysPt result=core_16.segbase+Fetchw(); return result; } -static EAPoint GetEADirect_ADDR(void) { - EAPoint result=SegBase(ds)+Fetchd();PrefixReset; +static PhysPt GetEADirect_ADDR(void) { + PhysPt result=SegBase(ds)+Fetchd(); return result; } -static EAPoint GetEADirect_SEG_ADDR(void) { - EAPoint result=prefix.segbase+Fetchd();PrefixReset; +static PhysPt GetEADirect_SEG_ADDR(void) { + PhysPt result=core_16.segbase+Fetchd(); return result; } diff --git a/src/cpu/core_full.cpp b/src/cpu/core_full.cpp new file mode 100644 index 0000000..dcaf00d --- /dev/null +++ b/src/cpu/core_full.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2002-2003 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" + +#include "pic.h" +#include "regs.h" +#include "cpu.h" +#include "lazyflags.h" +#include "paging.h" +#include "fpu.h" +#include "debug.h" +#include "inout.h" +#include "callback.h" + + +typedef PhysPt EAPoint; +#define SegBase(c) SegPhys(c) + +#define LoadMb(off) mem_readb_inline(off) +#define LoadMw(off) mem_readw_inline(off) +#define LoadMd(off) mem_readd_inline(off) + +#define LoadMbs(off) (Bit8s)(LoadMb(off)) +#define LoadMws(off) (Bit16s)(LoadMw(off)) +#define LoadMds(off) (Bit32s)(LoadMd(off)) + +#define SaveMb(off,val) mem_writeb_inline(off,val) +#define SaveMw(off,val) mem_writew_inline(off,val) +#define SaveMd(off,val) mem_writed_inline(off,val) + +#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" +#include "instructions.h" + +#define LEAVECORE \ + SaveIP(); \ + FillFlags(); + +#define EXCEPTION(blah) \ + { \ + Bit8u new_num=blah; \ + IPPoint=inst.start_entry; \ + LEAVECORE; \ + Interrupt(new_num); \ + LoadIP(); \ + goto nextopcode; \ + } + +Bits Full_DeCode(void) { + FullData inst; + if (!cpu.code.big) { + inst.start_prefix=0x0;; + inst.start_entry=0x0; + } else { + inst.start_prefix=PREFIX_ADDR; + inst.start_entry=0x200; + } + EAPoint IPPoint; + LoadIP(); + flags.type=t_UNKNOWN; + while (CPU_Cycles>0) { +#if C_DEBUG + cycle_count++; +#if C_HEAVY_DEBUG + SaveIP(); + if (DEBUG_HeavyIsBreakpoint()) { + LEAVECORE; + return debugCallback; + }; +#endif +#endif + inst.start=IPPoint; + inst.entry=inst.start_entry; + inst.prefix=inst.start_prefix; +restartopcode: + inst.entry=(inst.entry & 0xffffff00) | Fetchb(); + inst.code=OpCodeTable[inst.entry]; + #include "core_full/load.h" + #include "core_full/op.h" + #include "core_full/save.h" +nextopcode:; + CPU_Cycles--; + } + LEAVECORE; + return CBRET_NONE; +} + + +void CPU_Core_Full_Start(bool big) { + cpudecoder=&Full_DeCode; +} diff --git a/src/cpu/core_full/Makefile.am b/src/cpu/core_full/Makefile.am new file mode 100644 index 0000000..41fbe6a --- /dev/null +++ b/src/cpu/core_full/Makefile.am @@ -0,0 +1,3 @@ + +noinst_HEADERS = ea_lookup.h load.h loadwrite.h op.h optable.h save.h \ + string.h support.h diff --git a/src/cpu/core_full/Makefile.in b/src/cpu/core_full/Makefile.in new file mode 100644 index 0000000..c2c48a7 --- /dev/null +++ b/src/cpu/core_full/Makefile.in @@ -0,0 +1,326 @@ +# Makefile.in generated by automake 1.7.7 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@ + +noinst_HEADERS = ea_lookup.h load.h loadwrite.h op.h optable.h save.h \ + string.h support.h + +subdir = src/cpu/core_full +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.in Makefile.am +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/cpu/core_full/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) + +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic ctags \ + distclean distclean-generic distclean-tags distdir dvi dvi-am \ + info info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/cpu/core_full/ea_lookup.h b/src/cpu/core_full/ea_lookup.h new file mode 100644 index 0000000..cd8834e --- /dev/null +++ b/src/cpu/core_full/ea_lookup.h @@ -0,0 +1,237 @@ +{ + EAPoint seg_base; + Bit16u off; + switch ((inst.rm_mod<<3)|inst.rm_eai) { + case 0x00: + off=reg_bx+reg_si; + seg_base=SegBase(ds); + break; + case 0x01: + off=reg_bx+reg_di; + seg_base=SegBase(ds); + break; + case 0x02: + off=reg_bp+reg_si; + seg_base=SegBase(ss); + break; + case 0x03: + off=reg_bp+reg_di; + seg_base=SegBase(ss); + break; + case 0x04: + off=reg_si; + seg_base=SegBase(ds); + break; + case 0x05: + off=reg_di; + seg_base=SegBase(ds); + break; + case 0x06: + off=Fetchw(); + seg_base=SegBase(ds); + break; + case 0x07: + off=reg_bx; + seg_base=SegBase(ds); + break; + + case 0x08: + off=reg_bx+reg_si+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x09: + off=reg_bx+reg_di+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x0a: + off=reg_bp+reg_si+Fetchbs(); + seg_base=SegBase(ss); + break; + case 0x0b: + off=reg_bp+reg_di+Fetchbs(); + seg_base=SegBase(ss); + break; + case 0x0c: + off=reg_si+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x0d: + off=reg_di+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x0e: + off=reg_bp+Fetchbs(); + seg_base=SegBase(ss); + break; + case 0x0f: + off=reg_bx+Fetchbs(); + seg_base=SegBase(ds); + break; + + case 0x10: + off=reg_bx+reg_si+Fetchws(); + seg_base=SegBase(ds); + break; + case 0x11: + off=reg_bx+reg_di+Fetchws(); + seg_base=SegBase(ds); + break; + case 0x12: + off=reg_bp+reg_si+Fetchws(); + seg_base=SegBase(ss); + break; + case 0x13: + off=reg_bp+reg_di+Fetchws(); + seg_base=SegBase(ss); + break; + case 0x14: + off=reg_si+Fetchws(); + seg_base=SegBase(ds); + break; + case 0x15: + off=reg_di+Fetchws(); + seg_base=SegBase(ds); + break; + case 0x16: + off=reg_bp+Fetchws(); + seg_base=SegBase(ss); + break; + case 0x17: + off=reg_bx+Fetchws(); + seg_base=SegBase(ds); + break; + } + inst.rm_off=off; + if (inst.prefix & PREFIX_SEG) { + inst.rm_eaa=inst.seg.base+off; + } else { + inst.rm_eaa=seg_base+off; + } +} else { + + +#define SIB(MODE) { \ + Bitu sib=Fetchb(); \ + switch (sib&7) { \ + case 0:seg_base=SegBase(ds);off=reg_eax;break; \ + case 1:seg_base=SegBase(ds);off=reg_ecx;break; \ + case 2:seg_base=SegBase(ds);off=reg_edx;break; \ + case 3:seg_base=SegBase(ds);off=reg_ebx;break; \ + case 4:seg_base=SegBase(ss);off=reg_esp;break; \ + case 5:if (!MODE) { seg_base=SegBase(ds);off=Fetchd();break; \ + } else { seg_base=SegBase(ss);off=reg_ebp;break;} \ + case 6:seg_base=SegBase(ds);off=reg_esi;break; \ + case 7:seg_base=SegBase(ds);off=reg_edi;break; \ + } \ + off+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); \ +}; + static Bit32u SIBZero=0; + static Bit32u * SIBIndex[8]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_edi }; + EAPoint seg_base; + Bit32u off; + switch ((inst.rm_mod<<3)|inst.rm_eai) { + case 0x00: + off=reg_eax; + seg_base=SegBase(ds); + break; + case 0x01: + off=reg_ecx; + seg_base=SegBase(ds); + break; + case 0x02: + off=reg_edx; + seg_base=SegBase(ds); + break; + case 0x03: + off=reg_ebx; + seg_base=SegBase(ds); + break; + case 0x04: + SIB(0); + break; + case 0x05: + off=Fetchd(); + seg_base=SegBase(ds); + break; + case 0x06: + off=reg_esi; + seg_base=SegBase(ds); + break; + case 0x07: + off=reg_edi; + seg_base=SegBase(ds); + break; + + case 0x08: + off=reg_eax+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x09: + off=reg_ecx+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x0a: + off=reg_edx+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x0b: + off=reg_ebx+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x0c: + SIB(1); + off+=Fetchbs(); + break; + case 0x0d: + off=reg_ebp+Fetchbs(); + seg_base=SegBase(ss); + break; + case 0x0e: + off=reg_esi+Fetchbs(); + seg_base=SegBase(ds); + break; + case 0x0f: + off=reg_edi+Fetchbs(); + seg_base=SegBase(ds); + break; + + case 0x10: + off=reg_eax+Fetchds(); + seg_base=SegBase(ds); + break; + case 0x11: + off=reg_ecx+Fetchds(); + seg_base=SegBase(ds); + break; + case 0x12: + off=reg_edx+Fetchds(); + seg_base=SegBase(ds); + break; + case 0x13: + off=reg_ebx+Fetchds(); + seg_base=SegBase(ds); + break; + case 0x14: + SIB(1); + off+=Fetchds(); + break; + case 0x15: + off=reg_ebp+Fetchds(); + seg_base=SegBase(ss); + break; + case 0x16: + off=reg_esi+Fetchds(); + seg_base=SegBase(ds); + break; + case 0x17: + off=reg_edi+Fetchds(); + seg_base=SegBase(ds); + break; + } + inst.rm_off=off; + if (inst.prefix & PREFIX_SEG) { + inst.rm_eaa=inst.seg.base+off; + } else { + inst.rm_eaa=seg_base+off; + } +} diff --git a/src/cpu/core_full/load.h b/src/cpu/core_full/load.h new file mode 100644 index 0000000..b0adcce --- /dev/null +++ b/src/cpu/core_full/load.h @@ -0,0 +1,501 @@ +switch (inst.code.load) { +/* General loading */ + case L_MODRM: + inst.rm=Fetchb(); + inst.rm_index=(inst.rm >> 3) & 7; + inst.rm_eai=inst.rm&07; + inst.rm_mod=inst.rm>>6; + /* Decode address of mod/rm if needed */ + if (inst.rm<0xc0) { + if (!(inst.prefix & PREFIX_ADDR)) + #include "ea_lookup.h" + } +l_MODRMswitch: + switch (inst.code.extra) { +/* Byte */ + case M_Ib: + inst.op1.d=Fetchb(); + break; + case M_Ebx: + if (inst.rm<0xc0) inst.op1.ds=(Bit8s)LoadMb(inst.rm_eaa); + else inst.op1.ds=(Bit8s)reg_8(inst.rm_eai); + break; + case M_EbIb: + inst.op2.d=Fetchb(); + case M_Eb: + if (inst.rm<0xc0) inst.op1.d=LoadMb(inst.rm_eaa); + else inst.op1.d=reg_8(inst.rm_eai); + break; + case M_EbGb: + if (inst.rm<0xc0) inst.op1.d=LoadMb(inst.rm_eaa); + else inst.op1.d=reg_8(inst.rm_eai); + inst.op2.d=reg_8(inst.rm_index); + break; + case M_GbEb: + if (inst.rm<0xc0) inst.op2.d=LoadMb(inst.rm_eaa); + else inst.op2.d=reg_8(inst.rm_eai); + case M_Gb: + inst.op1.d=reg_8(inst.rm_index);; + break; +/* Word */ + case M_Iw: + inst.op1.d=Fetchw(); + break; + case M_EwxGwx: + inst.op2.ds=(Bit16s)reg_16(inst.rm_index); + goto l_M_Ewx; + case M_EwxIbx: + inst.op2.ds=Fetchbs(); + goto l_M_Ewx; + case M_EwxIwx: + inst.op2.ds=Fetchws(); +l_M_Ewx: + case 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_EwIbx: + inst.op2.ds=Fetchbs(); + goto l_M_Ew; + case M_EwIw: + inst.op2.d=Fetchw(); + goto l_M_Ew; + case M_EwGwCL: + inst.imm.d=reg_cl; + goto l_M_EwGw; + case M_EwGwIb: + inst.imm.d=Fetchb(); +l_M_EwGw: + case M_EwGw: + inst.op2.d=reg_16(inst.rm_index); +l_M_Ew: + case M_Ew: + if (inst.rm<0xc0) inst.op1.d=LoadMw(inst.rm_eaa); + else inst.op1.d=reg_16(inst.rm_eai); + break; + case M_GwEw: + if (inst.rm<0xc0) inst.op2.d=LoadMw(inst.rm_eaa); + else inst.op2.d=reg_16(inst.rm_eai); + case M_Gw: + inst.op1.d=reg_16(inst.rm_index);; + break; +/* DWord */ + case M_Id: + inst.op1.d=Fetchd(); + break; + case M_EdxGdx: + inst.op2.ds=(Bit32s)reg_32(inst.rm_index); + case M_Edx: + 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_EdIbx: + inst.op2.ds=Fetchbs(); + goto l_M_Ed; + case M_EdId: + inst.op2.d=Fetchd(); + goto l_M_Ed; + case M_EdGdCL: + inst.imm.d=reg_cl; + goto l_M_EdGd; + case M_EdGdIb: + inst.imm.d=Fetchb(); +l_M_EdGd: + case M_EdGd: + inst.op2.d=reg_32(inst.rm_index); +l_M_Ed: + case M_Ed: + if (inst.rm<0xc0) inst.op1.d=LoadMd(inst.rm_eaa); + else inst.op1.d=reg_32(inst.rm_eai); + break; + case M_GdEd: + if (inst.rm<0xc0) inst.op2.d=LoadMd(inst.rm_eaa); + else inst.op2.d=reg_32(inst.rm_eai); + case M_Gd: + inst.op1.d=reg_32(inst.rm_index); + break; +/* Others */ + + case M_SEG: + //TODO Check for limit + inst.op1.d=SegValue((SegNames)inst.rm_index); + break; + case M_Efw: + if (inst.rm>=0xC0) { + LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw "); + goto nextopcode; + } + inst.op1.d=LoadMw(inst.rm_eaa); + inst.op2.d=LoadMw(inst.rm_eaa+2); + break; + case M_Efd: + if (inst.rm>=0xc0) { + LOG(LOG_CPU,LOG_ERROR)("MODRM:Illegal M_Efw "); + goto nextopcode; + } + inst.op1.d=LoadMd(inst.rm_eaa); + inst.op2.d=LoadMw(inst.rm_eaa+4); + break; + case M_EA: + inst.op1.d=inst.rm_off; + break; + case M_POPw: + inst.op1.d = Pop_16(); + break; + case M_POPd: + inst.op1.d = Pop_32(); + break; + case M_GRP: + inst.code=Groups[inst.code.op][inst.rm_index]; + goto l_MODRMswitch; + case M_GRP_Ib: + inst.op2.d=Fetchb(); + inst.code=Groups[inst.code.op][inst.rm_index]; + goto l_MODRMswitch; + case M_GRP_CL: + inst.op2.d=reg_cl; + inst.code=Groups[inst.code.op][inst.rm_index]; + goto l_MODRMswitch; + case M_GRP_1: + inst.op2.d=1; + inst.code=Groups[inst.code.op][inst.rm_index]; + goto l_MODRMswitch; + + /* Should continue with normal handler afterwards */ + case 0: + break; + default: + LOG(LOG_CPU,LOG_ERROR)("MODRM:Unhandled load %d entry %x",inst.code.extra,inst.entry); + break; + } + break; + case L_POPw: + inst.op1.d = Pop_16(); + break; + case L_POPd: + inst.op1.d = Pop_32(); + break; + case L_POPfw: + inst.op1.d = Pop_16(); + inst.op2.d = Pop_16(); + break; + case L_POPfd: + inst.op1.d = Pop_32(); + inst.op2.d = Pop_16(); + break; + case L_Ib: + inst.op1.d=Fetchb(); + break; + case L_Ibx: + inst.op1.ds=Fetchbs(); + break; + case L_Iw: + inst.op1.d=Fetchw(); + break; + case L_Iwx: + inst.op1.ds=Fetchws(); + break; + case L_Idx: + case L_Id: + inst.op1.d=Fetchd(); + break; + case L_Ifw: + inst.op1.d=Fetchw(); + inst.op2.d=Fetchw(); + break; + case L_Ifd: + inst.op1.d=Fetchd(); + inst.op2.d=Fetchw(); + break; +/* Direct load of registers */ + case L_REGbIb: + inst.op2.d=Fetchb(); + case L_REGb: + inst.op1.d=reg_8(inst.code.extra); + break; + case L_REGwIw: + inst.op2.d=Fetchw(); + case L_REGw: + inst.op1.d=reg_16(inst.code.extra); + break; + case L_REGdId: + inst.op2.d=Fetchd(); + case L_REGd: + inst.op1.d=reg_32(inst.code.extra); + break; + case L_FLG: + FillFlags(); + inst.op1.d = flags.word; + break; + case L_SEG: + inst.op1.d=SegValue((SegNames)inst.code.extra); + break; +/* Depending on addressize */ + case L_OP: + if (inst.prefix & PREFIX_ADDR) { + inst.rm_eaa=Fetchd(); + } else { + inst.rm_eaa=Fetchw(); + } + if (inst.prefix & PREFIX_SEG) { + inst.rm_eaa+=inst.seg.base; + } else { + inst.rm_eaa+=SegBase(ds); + } + break; + /* Special cases */ + case L_DOUBLE: + inst.entry|=0x100; + goto restartopcode; + case L_PRESEG: + inst.prefix|=PREFIX_SEG; + inst.seg.base=SegBase((SegNames)inst.code.extra); + goto restartopcode; + case L_PREREPNE: + inst.prefix|=PREFIX_REP; + inst.repz=false; + goto restartopcode; + case L_PREREP: + inst.prefix|=PREFIX_REP; + inst.repz=true; + goto restartopcode; + case L_PREOP: + inst.entry^=0x200; + goto restartopcode; + case L_PREADD: + inst.prefix^=PREFIX_ADDR; + goto restartopcode; + case L_VAL: + inst.op1.d=inst.code.extra; + break; + case L_INTO: + if (!get_OF()) goto nextopcode; + inst.op1.d=4; + break; + case D_IRETw: + flags.type=t_UNKNOWN; + if (!CPU_IRET(false)) return CBRET_NONE; + if (GETFLAG(IF) && PIC_IRQCheck) { + return CBRET_NONE; + } + LoadIP(); + goto nextopcode; + case D_IRETd: + flags.type=t_UNKNOWN; + if (!CPU_IRET(true)) return CBRET_NONE; + if (GETFLAG(IF) && PIC_IRQCheck) { + return CBRET_NONE; + } + LoadIP(); + goto nextopcode; + case D_RETFwIw: + if (!CPU_RET(false,Fetchw())) { + FillFlags(); + return CBRET_NONE; + } + LoadIP(); + goto nextopcode; + case D_RETFw: + if (!CPU_RET(false,0)) { + FillFlags(); + return CBRET_NONE; + } + LoadIP(); + goto nextopcode; + case D_RETFdIw: + if (!CPU_RET(true,Fetchw())) { + FillFlags(); + return CBRET_NONE; + } + LoadIP(); + goto nextopcode; + case D_RETFd: + if (!CPU_RET(true,0)) { + FillFlags(); + return CBRET_NONE; + } + LoadIP(); + goto nextopcode; +/* Direct operations */ + case L_STRING: + #include "string.h" + goto nextopcode; + case D_PUSHAw: + { + 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); + } + goto nextopcode; + case D_PUSHAd: + { + Bit32u old_esp=reg_esp; + Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx); + Push_32(old_esp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi); + } + goto nextopcode; + case D_POPAw: + 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(); + goto nextopcode; + case D_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(); + 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); + goto nextopcode; + case D_CBW: + reg_ax=(Bit8s)reg_al; + goto nextopcode; + case D_CWDE: + reg_eax=(Bit16s)reg_ax; + goto nextopcode; + case D_CWD: + if (reg_ax & 0x8000) reg_dx=0xffff; + else reg_dx=0; + goto nextopcode; + case D_CDQ: + if (reg_eax & 0x80000000) reg_edx=0xffffffff; + else reg_edx=0; + goto nextopcode; + case D_CLI: + SETFLAGBIT(IF,false); + goto nextopcode; + case D_STI: + SETFLAGBIT(IF,true); + if (GETFLAG(IF) && PIC_IRQCheck) { + LEAVECORE; + return CBRET_NONE; + } + goto nextopcode; + case D_STC: + SETFLAGBIT(CF,true); + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + goto nextopcode; + case D_CLC: + SETFLAGBIT(CF,false); + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + goto nextopcode; + case D_CMC: + SETFLAGBIT(CF,!get_CF()); + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + goto nextopcode; + case D_CLD: + SETFLAGBIT(DF,false); + goto nextopcode; + case D_STD: + SETFLAGBIT(DF,true); + goto nextopcode; + case D_WAIT: + case D_NOP: + goto nextopcode; + case D_ENTERw: + { + Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; + Bitu frame_ptr=reg_esp-2; + if (cpu.stack.big) { + reg_esp-=2; + mem_writew(SegBase(ss)+reg_esp,reg_bp); + for (Bitu i=1;i> 8)); + 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)); + goto nextopcode; + case O_CBACK: + LEAVECORE; + return inst.op1.d; + case O_GRP6w: + case O_GRP6d: + switch (inst.rm_index) { + case 0x00: /* SLDT */ + { + Bitu selector; + CPU_SLDT(selector); + inst.op1.d=(Bit32u)selector; + } + break; + case 0x01: /* STR */ + { + Bitu selector; + CPU_STR(selector); + inst.op1.d=(Bit32u)selector; + } + break; + case 0x02: /* LLDT */ + CPU_LLDT(inst.op1.d); + goto nextopcode; /* Else value will saved */ + case 0x03: /* LTR */ + CPU_LTR(inst.op1.d); + goto nextopcode; /* Else value will saved */ + case 0x04: /* VERR */ + FillFlags(); + CPU_VERR(inst.op1.d); + goto nextopcode; /* Else value will saved */ + case 0x05: /* VERW */ + FillFlags(); + CPU_VERW(inst.op1.d); + goto nextopcode; /* Else value will saved */ + default: + LOG(LOG_CPU,LOG_ERROR)("Group 6 Illegal subfunction %X",inst.rm_index); + } + break; + case O_GRP7w: + case O_GRP7d: + switch (inst.rm_index) { + case 0: /* SGDT */ + { + Bitu limit,base; + CPU_SGDT(limit,base); + SaveMw(inst.rm_eaa,limit); + SaveMd(inst.rm_eaa+2,base); + goto nextopcode; + } + case 1: /* SIDT */ + { + Bitu limit,base; + CPU_SIDT(limit,base); + SaveMw(inst.rm_eaa,limit); + SaveMd(inst.rm_eaa+2,base); + goto nextopcode; + } + case 2: /* LGDT */ + CPU_LGDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF)); + goto nextopcode; + case 3: /* LIDT */ + CPU_LIDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF)); + goto nextopcode; + case 4: /* SMSW */ + { + Bitu word;CPU_SMSW(word); + inst.op1.d=word; + break; + } + case 6: /* LMSW */ + FillFlags(); + CPU_LMSW(inst.op1.w); + goto nextopcode; + default: + LOG(LOG_CPU,LOG_ERROR)("Group 7 Illegal subfunction %X",inst.rm_index); + } + break; + case O_M_Cd_Rd: + CPU_SET_CRX(inst.rm_index,inst.op1.d); + break; + case O_M_Rd_Cd: + inst.op1.d=CPU_GET_CRX(inst.rm_index); + break; + case O_LAR: + { + FillFlags(); + Bitu ar;CPU_LAR(inst.op1.d,ar); + inst.op1.d=(Bit32u)ar; + } + break; + case O_LSL: + { + FillFlags(); + Bitu limit;CPU_LSL(inst.op1.d,limit); + inst.op1.d=(Bit32u)limit; + } + break; + case O_ARPL: + { + FillFlags(); + Bitu new_sel=inst.op1.d; + CPU_ARPL(new_sel,inst.op2.d); + inst.op1.d=(Bit32u)new_sel; + } + break; + case O_BSFw: + { + FillFlags(); + if (!inst.op1.w) { + SETFLAGBIT(ZF,true); + } else { + Bitu count=0; + while (count<16) { + if ((inst.op1.w>>count) & 1) break; + count++; + } + inst.op1.d=count; + SETFLAGBIT(ZF,false); + } + } + break; + case O_BSFd: + { + FillFlags(); + if (!inst.op1.d) { + SETFLAGBIT(ZF,true); + } else { + Bitu count=0; + while (count<32) { + if ((inst.op1.d>>count) & 1) break; + count++; + } + inst.op1.d=count; + SETFLAGBIT(ZF,false); + } + } + break; + case O_BSRw: + { + FillFlags(); + if (!inst.op1.w) { + SETFLAGBIT(ZF,true); + } else { + Bits count=15; + while (count>0) { + if ((inst.op1.w>>count) & 1) break; + count--; + } + inst.op1.d=count; + SETFLAGBIT(ZF,false); + } + } + break; + case O_BSRd: + { + FillFlags(); + if (!inst.op1.d) { + SETFLAGBIT(ZF,true); + } else { + Bits count=31; + while (count>0) { + if ((inst.op1.d>>count) & 1) break; + count--; + } + inst.op1.d=count; + SETFLAGBIT(ZF,false); + } + } + break; + case O_BTw: + case O_BTSw: + case O_BTCw: + 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; + } + } + break; + case O_BTd: + case O_BTSd: + case O_BTCd: + 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; + } + } + break; + case O_BSWAP: + BSWAP(inst.op1.d); + break; + case O_FPU: +#if C_FPU + switch (((inst.rm>=0xc0) << 3) | inst.code.save) { + case 0x00: FPU_ESC0_EA(inst.rm,inst.rm_eaa);break; + case 0x01: FPU_ESC1_EA(inst.rm,inst.rm_eaa);break; + case 0x02: FPU_ESC2_EA(inst.rm,inst.rm_eaa);break; + case 0x03: FPU_ESC3_EA(inst.rm,inst.rm_eaa);break; + case 0x04: FPU_ESC4_EA(inst.rm,inst.rm_eaa);break; + case 0x05: FPU_ESC5_EA(inst.rm,inst.rm_eaa);break; + case 0x06: FPU_ESC6_EA(inst.rm,inst.rm_eaa);break; + case 0x07: FPU_ESC7_EA(inst.rm,inst.rm_eaa);break; + + case 0x08: FPU_ESC0_Normal(inst.rm);break; + case 0x09: FPU_ESC1_Normal(inst.rm);break; + case 0x0a: FPU_ESC2_Normal(inst.rm);break; + case 0x0b: FPU_ESC3_Normal(inst.rm);break; + case 0x0c: FPU_ESC4_Normal(inst.rm);break; + case 0x0d: FPU_ESC5_Normal(inst.rm);break; + case 0x0e: FPU_ESC6_Normal(inst.rm);break; + case 0x0f: FPU_ESC7_Normal(inst.rm);break; + } + goto nextopcode; +#else + LOG(LOG_CPU,LOG_ERROR)("Unhandled FPU ESCAPE %d",inst.code.save); + goto nextopcode; +#endif + case O_BOUNDw: + { + Bit16s bound_min, bound_max; + bound_min=LoadMw(inst.rm_eaa); + bound_max=LoadMw(inst.rm_eaa+2); + if ( (((Bit16s)inst.op1.w) < bound_min) || (((Bit16s)inst.op1.w) > bound_max) ) { + EXCEPTION(5); + } + } + break; + case 0: + break; + default: + LOG(LOG_CPU,LOG_ERROR)("OP:Unhandled code %d entry %X",inst.code.op,inst.entry); + +} diff --git a/src/cpu/core_full/optable.h b/src/cpu/core_full/optable.h new file mode 100644 index 0000000..aaee0ed --- /dev/null +++ b/src/cpu/core_full/optable.h @@ -0,0 +1,813 @@ +/* Big ass opcode table normal,double, 66 normal, 66 double */ +static OpCode OpCodeTable[1024]={ +/* 0x00 - 0x07 */ +{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 }, +/* 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 }, +{L_REGbIb ,t_ORb ,S_REGb ,REGI_AL },{L_REGwIw ,t_ORw ,S_REGw ,REGI_AX }, +{L_SEG ,0 ,S_PUSHw,cs },{L_DOUBLE ,0 ,0 ,0 }, + +/* 0x10 - 0x17 */ +{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 }, +/* 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 }, + +/* 0x20 - 0x27 */ +{L_MODRM ,t_ANDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ANDw ,S_Ew ,M_EwGw }, +{L_MODRM ,t_ANDb ,S_Gb ,M_GbEb },{L_MODRM ,t_ANDw ,S_Gw ,M_GwEw }, +{L_REGbIb ,t_ANDb ,S_REGb ,REGI_AL },{L_REGwIw ,t_ANDw ,S_REGw ,REGI_AX }, +{L_PRESEG ,0 ,0 ,es },{D_DAA ,0 ,0 ,0 }, +/* 0x28 - 0x2f */ +{L_MODRM ,t_SUBb ,S_Eb ,M_EbGb },{L_MODRM ,t_SUBw ,S_Ew ,M_EwGw }, +{L_MODRM ,t_SUBb ,S_Gb ,M_GbEb },{L_MODRM ,t_SUBw ,S_Gw ,M_GwEw }, +{L_REGbIb ,t_SUBb ,S_REGb ,REGI_AL },{L_REGwIw ,t_SUBw ,S_REGw ,REGI_AX }, +{L_PRESEG ,0 ,0 ,cs },{D_DAS ,0 ,0 ,0 }, + +/* 0x30 - 0x37 */ +{L_MODRM ,t_XORb ,S_Eb ,M_EbGb },{L_MODRM ,t_XORw ,S_Ew ,M_EwGw }, +{L_MODRM ,t_XORb ,S_Gb ,M_GbEb },{L_MODRM ,t_XORw ,S_Gw ,M_GwEw }, +{L_REGbIb ,t_XORb ,S_REGb ,REGI_AL },{L_REGwIw ,t_XORw ,S_REGw ,REGI_AX }, +{L_PRESEG ,0 ,0 ,ss },{D_AAA ,0 ,0 ,0 }, +/* 0x38 - 0x3f */ +{L_MODRM ,t_CMPb ,0 ,M_EbGb },{L_MODRM ,t_CMPw ,0 ,M_EwGw }, +{L_MODRM ,t_CMPb ,0 ,M_GbEb },{L_MODRM ,t_CMPw ,0 ,M_GwEw }, +{L_REGbIb ,t_CMPb ,0 ,REGI_AL },{L_REGwIw ,t_CMPw ,0 ,REGI_AX }, +{L_PRESEG ,0 ,0 ,ds },{D_AAS ,0 ,0 ,0 }, + +/* 0x40 - 0x47 */ +{L_REGw ,t_INCw ,S_REGw ,REGI_AX},{L_REGw ,t_INCw ,S_REGw ,REGI_CX}, +{L_REGw ,t_INCw ,S_REGw ,REGI_DX},{L_REGw ,t_INCw ,S_REGw ,REGI_BX}, +{L_REGw ,t_INCw ,S_REGw ,REGI_SP},{L_REGw ,t_INCw ,S_REGw ,REGI_BP}, +{L_REGw ,t_INCw ,S_REGw ,REGI_SI},{L_REGw ,t_INCw ,S_REGw ,REGI_DI}, +/* 0x48 - 0x4f */ +{L_REGw ,t_DECw ,S_REGw ,REGI_AX},{L_REGw ,t_DECw ,S_REGw ,REGI_CX}, +{L_REGw ,t_DECw ,S_REGw ,REGI_DX},{L_REGw ,t_DECw ,S_REGw ,REGI_BX}, +{L_REGw ,t_DECw ,S_REGw ,REGI_SP},{L_REGw ,t_DECw ,S_REGw ,REGI_BP}, +{L_REGw ,t_DECw ,S_REGw ,REGI_SI},{L_REGw ,t_DECw ,S_REGw ,REGI_DI}, + +/* 0x50 - 0x57 */ +{L_REGw ,0 ,S_PUSHw,REGI_AX},{L_REGw ,0 ,S_PUSHw,REGI_CX}, +{L_REGw ,0 ,S_PUSHw,REGI_DX},{L_REGw ,0 ,S_PUSHw,REGI_BX}, +{L_REGw ,0 ,S_PUSHw,REGI_SP},{L_REGw ,0 ,S_PUSHw,REGI_BP}, +{L_REGw ,0 ,S_PUSHw,REGI_SI},{L_REGw ,0 ,S_PUSHw,REGI_DI}, +/* 0x58 - 0x5f */ +{L_POPw ,0 ,S_REGw ,REGI_AX},{L_POPw ,0 ,S_REGw ,REGI_CX}, +{L_POPw ,0 ,S_REGw ,REGI_DX},{L_POPw ,0 ,S_REGw ,REGI_BX}, +{L_POPw ,0 ,S_REGw ,REGI_SP},{L_POPw ,0 ,S_REGw ,REGI_BP}, +{L_POPw ,0 ,S_REGw ,REGI_SI},{L_POPw ,0 ,S_REGw ,REGI_DI}, + + +/* 0x60 - 0x67 */ +{D_PUSHAw ,0 ,0 ,0 },{D_POPAw ,0 ,0 ,0 }, +{L_MODRM ,O_BOUNDw ,0 ,M_Gw },{L_MODRM ,O_ARPL ,S_Ew ,M_EwGw }, +{L_PRESEG ,0 ,0 ,fs },{L_PRESEG ,0 ,0 ,gs }, +{L_PREOP ,0 ,0 ,0 },{L_PREADD ,0 ,0 ,0 }, +/* 0x68 - 0x6f */ +{L_Iw ,0 ,S_PUSHw,0 },{L_MODRM ,O_IMULRw ,S_Gw ,M_EwxIwx}, +{L_Ibx ,0 ,S_PUSHw,0 },{L_MODRM ,O_IMULRw ,S_Gw ,M_EwxIbx}, +{L_STRING ,R_INSB ,0 ,0 },{L_STRING ,R_INSW ,0 ,0 }, +{L_STRING ,R_OUTSB ,0 ,0 },{L_STRING ,R_OUTSW ,0 ,0 }, + + +/* 0x70 - 0x77 */ +{L_Ibx ,O_C_O ,S_C_AIPw,0 },{L_Ibx ,O_C_NO ,S_C_AIPw,0 }, +{L_Ibx ,O_C_B ,S_C_AIPw,0 },{L_Ibx ,O_C_NB ,S_C_AIPw,0 }, +{L_Ibx ,O_C_Z ,S_C_AIPw,0 },{L_Ibx ,O_C_NZ ,S_C_AIPw,0 }, +{L_Ibx ,O_C_BE ,S_C_AIPw,0 },{L_Ibx ,O_C_NBE ,S_C_AIPw,0 }, +/* 0x78 - 0x7f */ +{L_Ibx ,O_C_S ,S_C_AIPw,0 },{L_Ibx ,O_C_NS ,S_C_AIPw,0 }, +{L_Ibx ,O_C_P ,S_C_AIPw,0 },{L_Ibx ,O_C_NP ,S_C_AIPw,0 }, +{L_Ibx ,O_C_L ,S_C_AIPw,0 },{L_Ibx ,O_C_NL ,S_C_AIPw,0 }, +{L_Ibx ,O_C_LE ,S_C_AIPw,0 },{L_Ibx ,O_C_NLE ,S_C_AIPw,0 }, + + +/* 0x80 - 0x87 */ +{L_MODRM ,0 ,0 ,M_GRP },{L_MODRM ,1 ,0 ,M_GRP }, +{L_MODRM ,0 ,0 ,M_GRP },{L_MODRM ,3 ,0 ,M_GRP }, +{L_MODRM ,t_TESTb ,0 ,M_EbGb },{L_MODRM ,t_TESTw ,0 ,M_EwGw }, +{L_MODRM ,0 ,S_EbGb ,M_GbEb },{L_MODRM ,0 ,S_EwGw ,M_GwEw }, +/* 0x88 - 0x8f */ +{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 }, + +/* 0x90 - 0x97 */ +{D_NOP ,0 ,0 ,0 },{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_CX}, +{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_DX},{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_BX}, +{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_SP},{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_BP}, +{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_SI},{L_REGw ,O_XCHG_AX ,S_REGw ,REGI_DI}, +/* 0x98 - 0x9f */ +{D_CBW ,0 ,0 ,0 },{D_CWD ,0 ,0 ,0 }, +{L_Ifw ,O_CALLFw ,0 ,0 },{D_WAIT ,0 ,0 ,0 }, +{L_FLG ,0 ,S_PUSHw,0 },{L_POPw ,0 ,S_FLGw ,0 }, +{L_REGb ,0 ,S_FLGb ,REGI_AH},{L_FLG ,0 ,S_REGb ,REGI_AH}, + +/* 0xa0 - 0xa7 */ +{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_AXOP ,0 ,0 }, +{L_OP ,O_OPAL ,0 ,0 },{L_OP ,O_OPAX ,0 ,0 }, +{L_STRING ,R_MOVSB ,0 ,0 },{L_STRING ,R_MOVSW ,0 ,0 }, +{L_STRING ,R_CMPSB ,0 ,0 },{L_STRING ,R_CMPSW ,0 ,0 }, +/* 0xa8 - 0xaf */ +{L_REGbIb ,t_TESTb ,0 ,REGI_AL},{L_REGwIw ,t_TESTw ,0 ,REGI_AX}, +{L_STRING ,R_STOSB ,0 ,0 },{L_STRING ,R_STOSW ,0 ,0 }, +{L_STRING ,R_LODSB ,0 ,0 },{L_STRING ,R_LODSW ,0 ,0 }, +{L_STRING ,R_SCASB ,0 ,0 },{L_STRING ,R_SCASW ,0 ,0 }, + +/* 0xb0 - 0xb7 */ +{L_Ib ,0 ,S_REGb ,REGI_AL},{L_Ib ,0 ,S_REGb ,REGI_CL}, +{L_Ib ,0 ,S_REGb ,REGI_DL},{L_Ib ,0 ,S_REGb ,REGI_BL}, +{L_Ib ,0 ,S_REGb ,REGI_AH},{L_Ib ,0 ,S_REGb ,REGI_CH}, +{L_Ib ,0 ,S_REGb ,REGI_DH},{L_Ib ,0 ,S_REGb ,REGI_BH}, +/* 0xb8 - 0xbf */ +{L_Iw ,0 ,S_REGw ,REGI_AX},{L_Iw ,0 ,S_REGw ,REGI_CX}, +{L_Iw ,0 ,S_REGw ,REGI_DX},{L_Iw ,0 ,S_REGw ,REGI_BX}, +{L_Iw ,0 ,S_REGw ,REGI_SP},{L_Iw ,0 ,S_REGw ,REGI_BP}, +{L_Iw ,0 ,S_REGw ,REGI_SI},{L_Iw ,0 ,S_REGw ,REGI_DI}, + +/* 0xc0 - 0xc7 */ +{L_MODRM ,5 ,0 ,M_GRP_Ib },{L_MODRM ,6 ,0 ,M_GRP_Ib }, +{L_POPw ,0 ,S_IPIw ,0 },{L_POPw ,0 ,S_IP ,0 }, +{L_MODRM ,O_SEGES ,S_SEGGw,M_Efw },{L_MODRM ,O_SEGDS ,S_SEGGw,M_Efw }, +{L_MODRM ,0 ,S_Eb ,M_Ib },{L_MODRM ,0 ,S_Ew ,M_Iw }, +/* 0xc8 - 0xcf */ +{D_ENTERw ,0 ,0 ,0 },{D_LEAVEw ,0 ,0 ,0 }, +{D_RETFwIw ,0 ,0 ,0 },{D_RETFw ,0 ,0 ,0 }, +{L_VAL ,O_INT ,0 ,3 },{L_Ib ,O_INT ,0 ,0 }, +{L_INTO ,O_INT ,0 ,0 },{D_IRETw ,0 ,0 ,0 }, + +/* 0xd0 - 0xd7 */ +{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 }, +//TODO FPU +/* 0xd8 - 0xdf */ +{L_MODRM ,O_FPU ,0 ,0 },{L_MODRM ,O_FPU ,1 ,0 }, +{L_MODRM ,O_FPU ,2 ,0 },{L_MODRM ,O_FPU ,3 ,0 }, +{L_MODRM ,O_FPU ,4 ,0 },{L_MODRM ,O_FPU ,5 ,0 }, +{L_MODRM ,O_FPU ,6 ,0 },{L_MODRM ,O_FPU ,7 ,0 }, + +/* 0xe0 - 0xe7 */ +{L_Ibx ,O_LOOPNZ ,S_AIPw ,0 },{L_Ibx ,O_LOOPZ ,S_AIPw ,0 }, +{L_Ibx ,O_LOOP ,S_AIPw ,0 },{L_Ibx ,O_JCXZ ,S_AIPw ,0 }, +{L_Ib ,O_INb ,0 ,0 },{L_Ib ,O_INw ,0 ,0 }, +{L_Ib ,O_OUTb ,0 ,0 },{L_Ib ,O_OUTw ,0 ,0 }, +/* 0xe8 - 0xef */ +{L_Iw ,O_CALLNw ,S_AIPw ,0 },{L_Iwx ,0 ,S_AIPw ,0 }, +{L_Ifw ,O_JMPFw ,0 ,0 },{L_Ibx ,0 ,S_AIPw ,0 }, +{L_REGw ,O_INb ,0 ,REGI_DX},{L_REGw ,O_INw ,0 ,REGI_DX}, +{L_REGw ,O_OUTb ,0 ,REGI_DX},{L_REGw ,O_OUTw ,0 ,REGI_DX}, + +/* 0xf0 - 0xf7 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{L_PREREPNE ,0 ,0 ,0 },{L_PREREP ,0 ,0 ,0 }, +{D_HLT ,0 ,0 ,0 },{D_CMC ,0 ,0 ,0 }, +{L_MODRM ,8 ,0 ,M_GRP },{L_MODRM ,9 ,0 ,M_GRP }, +/* 0xf8 - 0xff */ +{D_CLC ,0 ,0 ,0 },{D_STC ,0 ,0 ,0 }, +{D_CLI ,0 ,0 ,0 },{D_STI ,0 ,0 ,0 }, +{D_CLD ,0 ,0 ,0 },{D_STD ,0 ,0 ,0 }, +{L_MODRM ,0xb ,0 ,M_GRP },{L_MODRM ,0xc ,0 ,M_GRP }, + +/* 0x100 - 0x107 */ +{L_MODRM ,O_GRP6w ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7w ,S_Ew ,M_Ew }, +{L_MODRM ,O_LAR ,S_Gw ,M_Ew },{L_MODRM ,O_LSL ,S_Gw ,M_Ew }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,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 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x110 - 0x117 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x118 - 0x11f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{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 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x128 - 0x12f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x130 - 0x137 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x138 - 0x13f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x140 - 0x147 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x148 - 0x14f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x150 - 0x157 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x158 - 0x15f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x160 - 0x167 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x168 - 0x16f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + + +/* 0x170 - 0x177 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x178 - 0x17f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x180 - 0x187 */ +{L_Iwx ,O_C_O ,S_C_AIPw,0 },{L_Iwx ,O_C_NO ,S_C_AIPw,0 }, +{L_Iwx ,O_C_B ,S_C_AIPw,0 },{L_Iwx ,O_C_NB ,S_C_AIPw,0 }, +{L_Iwx ,O_C_Z ,S_C_AIPw,0 },{L_Iwx ,O_C_NZ ,S_C_AIPw,0 }, +{L_Iwx ,O_C_BE ,S_C_AIPw,0 },{L_Iwx ,O_C_NBE ,S_C_AIPw,0 }, +/* 0x188 - 0x18f */ +{L_Iwx ,O_C_S ,S_C_AIPw,0 },{L_Iwx ,O_C_NS ,S_C_AIPw,0 }, +{L_Iwx ,O_C_P ,S_C_AIPw,0 },{L_Iwx ,O_C_NP ,S_C_AIPw,0 }, +{L_Iwx ,O_C_L ,S_C_AIPw,0 },{L_Iwx ,O_C_NL ,S_C_AIPw,0 }, +{L_Iwx ,O_C_LE ,S_C_AIPw,0 },{L_Iwx ,O_C_NLE ,S_C_AIPw,0 }, + +/* 0x190 - 0x197 */ +{L_MODRM ,O_C_O ,S_C_Eb,0 },{L_MODRM ,O_C_NO ,S_C_Eb,0 }, +{L_MODRM ,O_C_B ,S_C_Eb,0 },{L_MODRM ,O_C_NB ,S_C_Eb,0 }, +{L_MODRM ,O_C_Z ,S_C_Eb,0 },{L_MODRM ,O_C_NZ ,S_C_Eb,0 }, +{L_MODRM ,O_C_BE ,S_C_Eb,0 },{L_MODRM ,O_C_NBE ,S_C_Eb,0 }, +/* 0x198 - 0x19f */ +{L_MODRM ,O_C_S ,S_C_Eb,0 },{L_MODRM ,O_C_NS ,S_C_Eb,0 }, +{L_MODRM ,O_C_P ,S_C_Eb,0 },{L_MODRM ,O_C_NP ,S_C_Eb,0 }, +{L_MODRM ,O_C_L ,S_C_Eb,0 },{L_MODRM ,O_C_NL ,S_C_Eb,0 }, +{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_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_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_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 ,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 }, + +/* 0x1c0 - 0x1cc */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x1c8 - 0x1cf */ +{L_REGd ,O_BSWAP ,S_REGd ,REGI_AX},{L_REGd ,O_BSWAP ,S_REGd ,REGI_CX}, +{L_REGd ,O_BSWAP ,S_REGd ,REGI_DX},{L_REGd ,O_BSWAP ,S_REGd ,REGI_BX}, +{L_REGd ,O_BSWAP ,S_REGd ,REGI_SP},{L_REGd ,O_BSWAP ,S_REGd ,REGI_BP}, +{L_REGd ,O_BSWAP ,S_REGd ,REGI_SI},{L_REGd ,O_BSWAP ,S_REGd ,REGI_DI}, + +/* 0x1d0 - 0x1d7 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x1d8 - 0x1df */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x1e0 - 0x1ee */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x1e8 - 0x1ef */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x1f0 - 0x1fc */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x1f8 - 0x1ff */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + + +/* 0x200 - 0x207 */ +{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 }, +/* 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 }, +{L_REGbIb ,t_ORb ,S_REGb ,REGI_AL },{L_REGdId ,t_ORd ,S_REGd ,REGI_AX }, +{L_SEG ,0 ,S_PUSHd,cs },{L_DOUBLE ,0 ,0 ,0 }, + +/* 0x210 - 0x217 */ +{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 }, +/* 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 }, + +/* 0x220 - 0x227 */ +{L_MODRM ,t_ANDb ,S_Eb ,M_EbGb },{L_MODRM ,t_ANDd ,S_Ed ,M_EdGd }, +{L_MODRM ,t_ANDb ,S_Gb ,M_GbEb },{L_MODRM ,t_ANDd ,S_Gd ,M_GdEd }, +{L_REGbIb ,t_ANDb ,S_REGb ,REGI_AL },{L_REGdId ,t_ANDd ,S_REGd ,REGI_AX }, +{L_PRESEG ,0 ,0 ,es },{D_DAA ,0 ,0 ,0 }, +/* 0x228 - 0x22f */ +{L_MODRM ,t_SUBb ,S_Eb ,M_EbGb },{L_MODRM ,t_SUBd ,S_Ed ,M_EdGd }, +{L_MODRM ,t_SUBb ,S_Gb ,M_GbEb },{L_MODRM ,t_SUBd ,S_Gd ,M_GdEd }, +{L_REGbIb ,t_SUBb ,S_REGb ,REGI_AL },{L_REGdId ,t_SUBd ,S_REGd ,REGI_AX }, +{L_PRESEG ,0 ,0 ,cs },{D_DAS ,0 ,0 ,0 }, + +/* 0x230 - 0x237 */ +{L_MODRM ,t_XORb ,S_Eb ,M_EbGb },{L_MODRM ,t_XORd ,S_Ed ,M_EdGd }, +{L_MODRM ,t_XORb ,S_Gb ,M_GbEb },{L_MODRM ,t_XORd ,S_Gd ,M_GdEd }, +{L_REGbIb ,t_XORb ,S_REGb ,REGI_AL },{L_REGdId ,t_XORd ,S_REGd ,REGI_AX }, +{L_PRESEG ,0 ,0 ,ss },{D_AAA ,0 ,0 ,0 }, +/* 0x238 - 0x23f */ +{L_MODRM ,t_CMPb ,0 ,M_EbGb },{L_MODRM ,t_CMPd ,0 ,M_EdGd }, +{L_MODRM ,t_CMPb ,0 ,M_GbEb },{L_MODRM ,t_CMPd ,0 ,M_GdEd }, +{L_REGbIb ,t_CMPb ,0 ,REGI_AL },{L_REGdId ,t_CMPd ,0 ,REGI_AX }, +{L_PRESEG ,0 ,0 ,ds },{D_AAS ,0 ,0 ,0 }, + +/* 0x240 - 0x247 */ +{L_REGd ,t_INCd ,S_REGd ,REGI_AX},{L_REGd ,t_INCd ,S_REGd ,REGI_CX}, +{L_REGd ,t_INCd ,S_REGd ,REGI_DX},{L_REGd ,t_INCd ,S_REGd ,REGI_BX}, +{L_REGd ,t_INCd ,S_REGd ,REGI_SP},{L_REGd ,t_INCd ,S_REGd ,REGI_BP}, +{L_REGd ,t_INCd ,S_REGd ,REGI_SI},{L_REGd ,t_INCd ,S_REGd ,REGI_DI}, +/* 0x248 - 0x24f */ +{L_REGd ,t_DECd ,S_REGd ,REGI_AX},{L_REGd ,t_DECd ,S_REGd ,REGI_CX}, +{L_REGd ,t_DECd ,S_REGd ,REGI_DX},{L_REGd ,t_DECd ,S_REGd ,REGI_BX}, +{L_REGd ,t_DECd ,S_REGd ,REGI_SP},{L_REGd ,t_DECd ,S_REGd ,REGI_BP}, +{L_REGd ,t_DECd ,S_REGd ,REGI_SI},{L_REGd ,t_DECd ,S_REGd ,REGI_DI}, + +/* 0x250 - 0x257 */ +{L_REGd ,0 ,S_PUSHd,REGI_AX},{L_REGd ,0 ,S_PUSHd,REGI_CX}, +{L_REGd ,0 ,S_PUSHd,REGI_DX},{L_REGd ,0 ,S_PUSHd,REGI_BX}, +{L_REGd ,0 ,S_PUSHd,REGI_SP},{L_REGd ,0 ,S_PUSHd,REGI_BP}, +{L_REGd ,0 ,S_PUSHd,REGI_SI},{L_REGd ,0 ,S_PUSHd,REGI_DI}, +/* 0x258 - 0x25f */ +{L_POPd ,0 ,S_REGd ,REGI_AX},{L_POPd ,0 ,S_REGd ,REGI_CX}, +{L_POPd ,0 ,S_REGd ,REGI_DX},{L_POPd ,0 ,S_REGd ,REGI_BX}, +{L_POPd ,0 ,S_REGd ,REGI_SP},{L_POPd ,0 ,S_REGd ,REGI_BP}, +{L_POPd ,0 ,S_REGd ,REGI_SI},{L_POPd ,0 ,S_REGd ,REGI_DI}, + +/* 0x260 - 0x267 */ +{D_PUSHAd ,0 ,0 ,0 },{D_POPAd ,0 ,0 ,0 }, +{L_MODRM ,O_BOUNDd ,0 ,0 },{0 ,0 ,0 ,0 }, +{L_PRESEG ,0 ,0 ,fs },{L_PRESEG ,0 ,0 ,gs }, +{L_PREOP ,0 ,0 ,0 },{L_PREADD ,0 ,0 ,0 }, +/* 0x268 - 0x26f */ +{L_Id ,0 ,S_PUSHd,0 },{L_MODRM ,O_IMULRd ,S_Gd ,M_EdId}, +{L_Ibx ,0 ,S_PUSHd,0 },{L_MODRM ,O_IMULRd ,S_Gd ,M_EdIbx}, +{L_STRING ,R_INSB ,0 ,0 },{L_STRING ,R_INSD ,0 ,0 }, +{L_STRING ,R_OUTSB ,0 ,0 },{L_STRING ,R_OUTSD ,0 ,0 }, + +/* 0x270 - 0x277 */ +{L_Ibx ,O_C_O ,S_C_AIPd,0 },{L_Ibx ,O_C_NO ,S_C_AIPd,0 }, +{L_Ibx ,O_C_B ,S_C_AIPd,0 },{L_Ibx ,O_C_NB ,S_C_AIPd,0 }, +{L_Ibx ,O_C_Z ,S_C_AIPd,0 },{L_Ibx ,O_C_NZ ,S_C_AIPd,0 }, +{L_Ibx ,O_C_BE ,S_C_AIPd,0 },{L_Ibx ,O_C_NBE ,S_C_AIPd,0 }, +/* 0x278 - 0x27f */ +{L_Ibx ,O_C_S ,S_C_AIPd,0 },{L_Ibx ,O_C_NS ,S_C_AIPd,0 }, +{L_Ibx ,O_C_P ,S_C_AIPd,0 },{L_Ibx ,O_C_NP ,S_C_AIPd,0 }, +{L_Ibx ,O_C_L ,S_C_AIPd,0 },{L_Ibx ,O_C_NL ,S_C_AIPd,0 }, +{L_Ibx ,O_C_LE ,S_C_AIPd,0 },{L_Ibx ,O_C_NLE ,S_C_AIPd,0 }, + +/* 0x280 - 0x287 */ +{L_MODRM ,0 ,0 ,M_GRP },{L_MODRM ,2 ,0 ,M_GRP }, +{L_MODRM ,0 ,0 ,M_GRP },{L_MODRM ,4 ,0 ,M_GRP }, +{L_MODRM ,t_TESTb ,0 ,M_EbGb },{L_MODRM ,t_TESTd ,0 ,M_EdGd }, +{L_MODRM ,0 ,S_EbGb ,M_GbEb },{L_MODRM ,0 ,S_EdGd ,M_GdEd }, +/* 0x288 - 0x28f */ +{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 }, + +/* 0x290 - 0x297 */ +{D_NOP ,0 ,0 ,0 },{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_CX}, +{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_DX},{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_BX}, +{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_SP},{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_BP}, +{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_SI},{L_REGd ,O_XCHG_EAX ,S_REGd ,REGI_DI}, +/* 0x298 - 0x29f */ +{D_CWDE ,0 ,0 ,0 },{D_CDQ ,0 ,0 ,0 }, +{L_Ifd ,O_CALLFd ,0 ,0 },{D_WAIT ,0 ,0 ,0 }, +{L_FLG ,0 ,S_PUSHd,0 },{L_POPd ,0 ,S_FLGd ,0 }, +{L_REGb ,0 ,S_FLGb ,REGI_AH},{L_FLG ,0 ,S_REGb ,REGI_AH}, + +/* 0x2a0 - 0x2a7 */ +{L_OP ,O_ALOP ,0 ,0 },{L_OP ,O_EAXOP ,0 ,0 }, +{L_OP ,O_OPAL ,0 ,0 },{L_OP ,O_OPEAX ,0 ,0 }, +{L_STRING ,R_MOVSB ,0 ,0 },{L_STRING ,R_MOVSD ,0 ,0 }, +{L_STRING ,R_CMPSB ,0 ,0 },{L_STRING ,R_CMPSD ,0 ,0 }, +/* 0x2a8 - 0x2af */ +{L_REGbIb ,t_TESTb ,0 ,REGI_AL},{L_REGdId ,t_TESTd ,0 ,REGI_AX}, +{L_STRING ,R_STOSB ,0 ,0 },{L_STRING ,R_STOSD ,0 ,0 }, +{L_STRING ,R_LODSB ,0 ,0 },{L_STRING ,R_LODSD ,0 ,0 }, +{L_STRING ,R_SCASB ,0 ,0 },{L_STRING ,R_SCASD ,0 ,0 }, + +/* 0x2b0 - 0x2b7 */ +{L_Ib ,0 ,S_REGb ,REGI_AL},{L_Ib ,0 ,S_REGb ,REGI_CL}, +{L_Ib ,0 ,S_REGb ,REGI_DL},{L_Ib ,0 ,S_REGb ,REGI_BL}, +{L_Ib ,0 ,S_REGb ,REGI_AH},{L_Ib ,0 ,S_REGb ,REGI_CH}, +{L_Ib ,0 ,S_REGb ,REGI_DH},{L_Ib ,0 ,S_REGb ,REGI_BH}, +/* 0x2b8 - 0x2bf */ +{L_Id ,0 ,S_REGd ,REGI_AX},{L_Id ,0 ,S_REGd ,REGI_CX}, +{L_Id ,0 ,S_REGd ,REGI_DX},{L_Id ,0 ,S_REGd ,REGI_BX}, +{L_Id ,0 ,S_REGd ,REGI_SP},{L_Id ,0 ,S_REGd ,REGI_BP}, +{L_Id ,0 ,S_REGd ,REGI_SI},{L_Id ,0 ,S_REGd ,REGI_DI}, + +/* 0x2c0 - 0x2c7 */ +{L_MODRM ,5 ,0 ,M_GRP_Ib },{L_MODRM ,7 ,0 ,M_GRP_Ib }, +{L_POPd ,0 ,S_IPIw ,0 },{L_POPd ,0 ,S_IP ,0 }, +{L_MODRM ,O_SEGES ,S_SEGGd,M_Efd },{L_MODRM ,O_SEGDS ,S_SEGGd,M_Efd }, +{L_MODRM ,0 ,S_Eb ,M_Ib },{L_MODRM ,0 ,S_Ed ,M_Id }, +/* 0x2c8 - 0x2cf */ +{D_ENTERd ,0 ,0 ,0 },{D_LEAVEd ,0 ,0 ,0 }, +{D_RETFdIw ,0 ,0 ,0 },{D_RETFd ,0 ,0 ,0 }, +{L_VAL ,O_INT ,0 ,3 },{L_Ib ,O_INT ,0 ,0 }, +{L_INTO ,O_INT ,0 ,0 },{D_IRETd ,0 ,0 ,0 }, + +/* 0x2d0 - 0x2d7 */ +{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 }, +/* 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 }, +{L_MODRM ,O_FPU ,4 ,0 },{L_MODRM ,O_FPU ,5 ,0 }, +{L_MODRM ,O_FPU ,6 ,0 },{L_MODRM ,O_FPU ,7 ,0 }, + +/* 0x2e0 - 0x2e7 */ +{L_Ibx ,O_LOOPNZ ,S_AIPd ,0 },{L_Ibx ,O_LOOPZ ,S_AIPd ,0 }, +{L_Ibx ,O_LOOP ,S_AIPd ,0 },{L_Ibx ,O_JCXZ ,S_AIPd ,0 }, +{L_Ib ,O_INb ,0 ,0 },{L_Ib ,O_INd ,0 ,0 }, +{L_Ib ,O_OUTb ,0 ,0 },{L_Ib ,O_OUTd ,0 ,0 }, +/* 0x2e8 - 0x2ef */ +{L_Id ,O_CALLNd ,S_AIPd ,0 },{L_Idx ,0 ,S_AIPd ,0 }, +{L_Ifd ,O_JMPFd ,0 ,0 },{L_Ibx ,0 ,S_AIPd ,0 }, +{L_REGw ,O_INb ,0 ,REGI_DX},{L_REGw ,O_INd ,0 ,REGI_DX}, +{L_REGw ,O_OUTb ,0 ,REGI_DX},{L_REGw ,O_OUTd ,0 ,REGI_DX}, + +/* 0x2f0 - 0x2f7 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{L_PREREPNE ,0 ,0 ,0 },{L_PREREP ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{D_CMC ,0 ,0 ,0 }, +{L_MODRM ,8 ,0 ,M_GRP },{L_MODRM ,0xa ,0 ,M_GRP }, +/* 0x2f8 - 0x2ff */ +{D_CLC ,0 ,0 ,0 },{D_STC ,0 ,0 ,0 }, +{D_CLI ,0 ,0 ,0 },{D_STI ,0 ,0 ,0 }, +{D_CLD ,0 ,0 ,0 },{D_STD ,0 ,0 ,0 }, +{L_MODRM ,0xb ,0 ,M_GRP },{L_MODRM ,0xd ,0 ,M_GRP }, + + +/* 0x300 - 0x307 */ +{L_MODRM ,O_GRP6d ,S_Ew ,M_Ew },{L_MODRM ,O_GRP7d ,S_Ew ,M_Ew }, +{L_MODRM ,O_LAR ,S_Gd ,M_Ew },{L_MODRM ,O_LSL ,S_Gd ,M_Ew }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,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 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x310 - 0x317 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x318 - 0x31f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{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 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x328 - 0x32f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x330 - 0x337 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x338 - 0x33f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x340 - 0x347 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x348 - 0x34f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x350 - 0x357 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x358 - 0x35f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x360 - 0x367 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x368 - 0x36f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + + +/* 0x370 - 0x377 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x378 - 0x37f */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x380 - 0x387 */ +{L_Idx ,O_C_O ,S_C_AIPd,0 },{L_Idx ,O_C_NO ,S_C_AIPd,0 }, +{L_Idx ,O_C_B ,S_C_AIPd,0 },{L_Idx ,O_C_NB ,S_C_AIPd,0 }, +{L_Idx ,O_C_Z ,S_C_AIPd,0 },{L_Idx ,O_C_NZ ,S_C_AIPd,0 }, +{L_Idx ,O_C_BE ,S_C_AIPd,0 },{L_Idx ,O_C_NBE ,S_C_AIPd,0 }, +/* 0x388 - 0x38f */ +{L_Idx ,O_C_S ,S_C_AIPd,0 },{L_Idx ,O_C_NS ,S_C_AIPd,0 }, +{L_Idx ,O_C_P ,S_C_AIPd,0 },{L_Idx ,O_C_NP ,S_C_AIPd,0 }, +{L_Idx ,O_C_L ,S_C_AIPd,0 },{L_Idx ,O_C_NL ,S_C_AIPd,0 }, +{L_Idx ,O_C_LE ,S_C_AIPd,0 },{L_Idx ,O_C_NLE ,S_C_AIPd,0 }, + +/* 0x390 - 0x397 */ +{L_MODRM ,O_C_O ,S_C_Eb,0 },{L_MODRM ,O_C_NO ,S_C_Eb,0 }, +{L_MODRM ,O_C_B ,S_C_Eb,0 },{L_MODRM ,O_C_NB ,S_C_Eb,0 }, +{L_MODRM ,O_C_Z ,S_C_Eb,0 },{L_MODRM ,O_C_NZ ,S_C_Eb,0 }, +{L_MODRM ,O_C_BE ,S_C_Eb,0 },{L_MODRM ,O_C_NBE ,S_C_Eb,0 }, +/* 0x398 - 0x39f */ +{L_MODRM ,O_C_S ,S_C_Eb,0 },{L_MODRM ,O_C_NS ,S_C_Eb,0 }, +{L_MODRM ,O_C_P ,S_C_Eb,0 },{L_MODRM ,O_C_NP ,S_C_Eb,0 }, +{L_MODRM ,O_C_L ,S_C_Eb,0 },{L_MODRM ,O_C_NL ,S_C_Eb,0 }, +{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_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_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_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 ,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 }, + +/* 0x3c0 - 0x3cc */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x3c8 - 0x3cf */ +{L_REGd ,O_BSWAP ,S_REGd ,REGI_AX},{L_REGd ,O_BSWAP ,S_REGd ,REGI_CX}, +{L_REGd ,O_BSWAP ,S_REGd ,REGI_DX},{L_REGd ,O_BSWAP ,S_REGd ,REGI_BX}, +{L_REGd ,O_BSWAP ,S_REGd ,REGI_SP},{L_REGd ,O_BSWAP ,S_REGd ,REGI_BP}, +{L_REGd ,O_BSWAP ,S_REGd ,REGI_SI},{L_REGd ,O_BSWAP ,S_REGd ,REGI_DI}, + +/* 0x3d0 - 0x3d7 */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x3d8 - 0x3df */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x3e0 - 0x3ee */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x3e8 - 0x3ef */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, + +/* 0x3f0 - 0x3fc */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +/* 0x3f8 - 0x3ff */ +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{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 OpCode Groups[16][8]={ +{ /* 0x00 Group 1 Eb,Ib */ +{0 ,t_ADDb ,S_Eb ,M_EbIb },{0 ,t_ORb ,S_Eb ,M_EbIb }, +{0 ,t_ADCb ,S_Eb ,M_EbIb },{0 ,t_SBBb ,S_Eb ,M_EbIb }, +{0 ,t_ANDb ,S_Eb ,M_EbIb },{0 ,t_SUBb ,S_Eb ,M_EbIb }, +{0 ,t_XORb ,S_Eb ,M_EbIb },{0 ,t_CMPb ,0 ,M_EbIb }, +},{ /* 0x01 Group 1 Ew,Iw */ +{0 ,t_ADDw ,S_Ew ,M_EwIw },{0 ,t_ORw ,S_Ew ,M_EwIw }, +{0 ,t_ADCw ,S_Ew ,M_EwIw },{0 ,t_SBBw ,S_Ew ,M_EwIw }, +{0 ,t_ANDw ,S_Ew ,M_EwIw },{0 ,t_SUBw ,S_Ew ,M_EwIw }, +{0 ,t_XORw ,S_Ew ,M_EwIw },{0 ,t_CMPw ,0 ,M_EwIw }, +},{ /* 0x02 Group 1 Ed,Id */ +{0 ,t_ADDd ,S_Ed ,M_EdId },{0 ,t_ORd ,S_Ed ,M_EdId }, +{0 ,t_ADCd ,S_Ed ,M_EdId },{0 ,t_SBBd ,S_Ed ,M_EdId }, +{0 ,t_ANDd ,S_Ed ,M_EdId },{0 ,t_SUBd ,S_Ed ,M_EdId }, +{0 ,t_XORd ,S_Ed ,M_EdId },{0 ,t_CMPd ,0 ,M_EdId }, +},{ /* 0x03 Group 1 Ew,Ibx */ +{0 ,t_ADDw ,S_Ew ,M_EwIbx },{0 ,t_ORw ,S_Ew ,M_EwIbx }, +{0 ,t_ADCw ,S_Ew ,M_EwIbx },{0 ,t_SBBw ,S_Ew ,M_EwIbx }, +{0 ,t_ANDw ,S_Ew ,M_EwIbx },{0 ,t_SUBw ,S_Ew ,M_EwIbx }, +{0 ,t_XORw ,S_Ew ,M_EwIbx },{0 ,t_CMPw ,0 ,M_EwIbx }, +},{ /* 0x04 Group 1 Ed,Ibx */ +{0 ,t_ADDd ,S_Ed ,M_EdIbx },{0 ,t_ORd ,S_Ed ,M_EdIbx }, +{0 ,t_ADCd ,S_Ed ,M_EdIbx },{0 ,t_SBBd ,S_Ed ,M_EdIbx }, +{0 ,t_ANDd ,S_Ed ,M_EdIbx },{0 ,t_SUBd ,S_Ed ,M_EdIbx }, +{0 ,t_XORd ,S_Ed ,M_EdIbx },{0 ,t_CMPd ,0 ,M_EdIbx }, + +},{ /* 0x05 Group 2 Eb,XXX */ +{0 ,t_ROLb ,S_Eb ,M_Eb },{0 ,t_RORb ,S_Eb ,M_Eb }, +{0 ,t_RCLb ,S_Eb ,M_Eb },{0 ,t_RCRb ,S_Eb ,M_Eb }, +{0 ,t_SHLb ,S_Eb ,M_Eb },{0 ,t_SHRb ,S_Eb ,M_Eb }, +{0 ,t_SHLb ,S_Eb ,M_Eb },{0 ,t_SARb ,S_Eb ,M_Eb }, +},{ /* 0x06 Group 2 Ew,XXX */ +{0 ,t_ROLw ,S_Ew ,M_Ew },{0 ,t_RORw ,S_Ew ,M_Ew }, +{0 ,t_RCLw ,S_Ew ,M_Ew },{0 ,t_RCRw ,S_Ew ,M_Ew }, +{0 ,t_SHLw ,S_Ew ,M_Ew },{0 ,t_SHRw ,S_Ew ,M_Ew }, +{0 ,t_SHLw ,S_Ew ,M_Ew },{0 ,t_SARw ,S_Ew ,M_Ew }, +},{ /* 0x07 Group 2 Ed,XXX */ +{0 ,t_ROLd ,S_Ed ,M_Ed },{0 ,t_RORd ,S_Ed ,M_Ed }, +{0 ,t_RCLd ,S_Ed ,M_Ed },{0 ,t_RCRd ,S_Ed ,M_Ed }, +{0 ,t_SHLd ,S_Ed ,M_Ed },{0 ,t_SHRd ,S_Ed ,M_Ed }, +{0 ,t_SHLd ,S_Ed ,M_Ed },{0 ,t_SARd ,S_Ed ,M_Ed }, + + +},{ /* 0x08 Group 3 Eb */ +{0 ,t_TESTb ,0 ,M_EbIb },{0 ,t_TESTb ,0 ,M_EbIb }, +{0 ,O_NOT ,S_Eb ,M_Eb },{0 ,t_NEGb ,S_Eb ,M_Eb }, +{0 ,O_MULb ,0 ,M_Eb },{0 ,O_IMULb ,0 ,M_Eb }, +{0 ,O_DIVb ,0 ,M_Eb },{0 ,O_IDIVb ,0 ,M_Eb }, +},{ /* 0x09 Group 3 Ew */ +{0 ,t_TESTw ,0 ,M_EwIw },{0 ,t_TESTw ,0 ,M_EwIw }, +{0 ,O_NOT ,S_Ew ,M_Ew },{0 ,t_NEGw ,S_Ew ,M_Ew }, +{0 ,O_MULw ,0 ,M_Ew },{0 ,O_IMULw ,0 ,M_Ew }, +{0 ,O_DIVw ,0 ,M_Ew },{0 ,O_IDIVw ,0 ,M_Ew }, +},{ /* 0x0a Group 3 Ed */ +{0 ,t_TESTd ,0 ,M_EdId },{0 ,t_TESTd ,0 ,M_EdId }, +{0 ,O_NOT ,S_Ed ,M_Ed },{0 ,t_NEGd ,S_Ed ,M_Ed }, +{0 ,O_MULd ,0 ,M_Ed },{0 ,O_IMULd ,0 ,M_Ed }, +{0 ,O_DIVd ,0 ,M_Ed },{0 ,O_IDIVd ,0 ,M_Ed }, + +},{ /* 0x0b Group 4 Eb */ +{0 ,t_INCb ,S_Eb ,M_Eb },{0 ,t_DECb ,S_Eb ,M_Eb }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,0 ,0 ,0 }, +{0 ,0 ,0 ,0 },{0 ,O_CBACK ,0 ,M_Iw }, +},{ /* 0x0c Group 5 Ew */ +{0 ,t_INCw ,S_Ew ,M_Ew },{0 ,t_DECw ,S_Ew ,M_Ew }, +{0 ,O_CALLNw ,S_IP ,M_Ew },{0 ,O_CALLFw ,0 ,M_Efw }, +{0 ,0 ,S_IP ,M_Ew },{0 ,O_JMPFw ,0 ,M_Efw }, +{0 ,0 ,S_PUSHw,M_Ew },{0 ,0 ,0 ,0 }, +},{ /* 0x0d Group 5 Ed */ +{0 ,t_INCd ,S_Ed ,M_Ed },{0 ,t_DECd ,S_Ed ,M_Ed }, +{0 ,O_CALLNd ,S_IP ,M_Ed },{0 ,O_CALLFd ,0 ,M_Efd }, +{0 ,0 ,S_IP ,M_Ed },{0 ,O_JMPFd ,0 ,M_Efd }, +{0 ,0 ,S_PUSHd,M_Ed },{0 ,0 ,0 ,0 }, + + +},{ /* 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 }, +},{ /* 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 }, + + + +} +}; + + + diff --git a/src/cpu/core_full/save.h b/src/cpu/core_full/save.h new file mode 100644 index 0000000..a5e97eb --- /dev/null +++ b/src/cpu/core_full/save.h @@ -0,0 +1,122 @@ +/* Write the data from the opcode */ +switch (inst.code.save) { +/* Byte */ + case S_C_Eb: + inst.op1.b=inst.cond ? 1 : 0; + case S_Eb: + if (inst.rm<0xc0) SaveMb(inst.rm_eaa,inst.op1.b); + else reg_8(inst.rm_eai)=inst.op1.b; + break; + case S_Gb: + reg_8(inst.rm_index)=inst.op1.b; + break; + case S_EbGb: + if (inst.rm<0xc0) SaveMb(inst.rm_eaa,inst.op1.b); + else reg_8(inst.rm_eai)=inst.op1.b; + reg_8(inst.rm_index)=inst.op2.b; + break; +/* Word */ + case S_Ew: + if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst.op1.w); + else reg_16(inst.rm_eai)=inst.op1.w; + break; + case S_Gw: + reg_16(inst.rm_index)=inst.op1.w; + break; + case S_EwGw: + if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst.op1.w); + else reg_16(inst.rm_eai)=inst.op1.w; + reg_16(inst.rm_index)=inst.op2.w; + break; +/* Dword */ + case S_Ed: + if (inst.rm<0xc0) SaveMd(inst.rm_eaa,inst.op1.d); + else reg_32(inst.rm_eai)=inst.op1.d; + break; + case S_EdMw: /* Special one 16 to memory, 32 zero extend to reg */ + if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst.op1.w); + else reg_32(inst.rm_eai)=inst.op1.d; + break; + case S_Gd: + reg_32(inst.rm_index)=inst.op1.d; + break; + case S_EdGd: + if (inst.rm<0xc0) SaveMd(inst.rm_eaa,inst.op1.d); + else reg_32(inst.rm_eai)=inst.op1.d; + reg_32(inst.rm_index)=inst.op2.d; + break; + + case S_REGb: + reg_8(inst.code.extra)=inst.op1.b; + break; + case S_REGw: + reg_16(inst.code.extra)=inst.op1.w; + break; + 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); + break; + case S_SEGGw: + reg_16(inst.rm_index)=inst.op1.w; + CPU_SetSegGeneral((SegNames)inst.code.extra,inst.op2.w); + break; + case S_SEGGd: + 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); + break; + case S_PUSHd: + Push_32(inst.op1.d); + break; + + case S_C_AIPw: + if (!inst.cond) goto nextopcode; + case S_AIPw: + SaveIP(); + reg_eip+=inst.op1.d; + reg_eip&=0xffff; + LoadIP(); + break; + case S_C_AIPd: + if (!inst.cond) goto nextopcode; + case S_AIPd: + SaveIP(); + reg_eip+=inst.op1.d; + LoadIP(); + break; + case S_IPIw: + reg_esp+=Fetchw(); + case S_IP: + SaveIP(); + reg_eip=inst.op1.d; + LoadIP(); + break; + case S_FLGb: + SETFLAGSb(inst.op1.b); + break; + case S_FLGw: + SETFLAGSw(inst.op1.w); + if (GETFLAG(IF) && PIC_IRQCheck) { + SaveIP(); + return CBRET_NONE; + } + break; + case S_FLGd: + SETFLAGSd(inst.op1.d); + if (GETFLAG(IF) && PIC_IRQCheck) { + SaveIP(); + return CBRET_NONE; + } + break; + case 0: + break; + default: + LOG(LOG_CPU,LOG_ERROR)("SAVE:Unhandled code %d entry %X",inst.code.save,inst.entry); +} diff --git a/src/cpu/core_full/string.h b/src/cpu/core_full/string.h new file mode 100644 index 0000000..183c2d9 --- /dev/null +++ b/src/cpu/core_full/string.h @@ -0,0 +1,230 @@ +{ + EAPoint si_base,di_base; + Bitu si_index,di_index; + Bitu add_mask; + Bitu count,count_left; + Bits add_index; + + if (inst.prefix & PREFIX_SEG) si_base=inst.seg.base; + else si_base=SegBase(ds); + di_base=SegBase(es); + if (inst.prefix & PREFIX_ADDR) { + add_mask=0xFFFFFFFF; + si_index=reg_esi; + di_index=reg_edi; + count=reg_ecx; + } else { + add_mask=0xFFFF; + si_index=reg_si; + di_index=reg_di; + count=reg_cx; + } + if (!(inst.prefix & PREFIX_REP)) { + count=1; + } else { + /* Calculate amount of ops to do before cycles run out */ + if ((count>(Bitu)CPU_Cycles) && (inst.code.op0;count--) { + IO_Write(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)); + 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)); + 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)); + 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)); + di_index=(di_index+add_index) & add_mask; + } + break; + case R_STOSB: + for (;count>0;count--) { + SaveMb(di_base+di_index,reg_al); + di_index=(di_index+add_index) & add_mask; + } + break; + case R_STOSW: + add_index<<=1; + for (;count>0;count--) { + SaveMw(di_base+di_index,reg_ax); + di_index=(di_index+add_index) & add_mask; + } + break; + case R_STOSD: + add_index<<=2; + for (;count>0;count--) { + SaveMd(di_base+di_index,reg_eax); + di_index=(di_index+add_index) & add_mask; + } + break; + case R_MOVSB: + for (;count>0;count--) { + SaveMb(di_base+di_index,LoadMb(si_base+si_index)); + di_index=(di_index+add_index) & add_mask; + si_index=(si_index+add_index) & add_mask; + } + break; + case R_MOVSW: + add_index<<=1; + for (;count>0;count--) { + SaveMw(di_base+di_index,LoadMw(si_base+si_index)); + di_index=(di_index+add_index) & add_mask; + si_index=(si_index+add_index) & add_mask; + } + break; + case R_MOVSD: + add_index<<=2; + for (;count>0;count--) { + SaveMd(di_base+di_index,LoadMd(si_base+si_index)); + di_index=(di_index+add_index) & add_mask; + si_index=(si_index+add_index) & add_mask; + } + break; + case R_LODSB: + for (;count>0;count--) { + reg_al=LoadMb(si_base+si_index); + si_index=(si_index+add_index) & add_mask; + } + break; + case R_LODSW: + add_index<<=1; + for (;count>0;count--) { + reg_ax=LoadMw(si_base+si_index); + si_index=(si_index+add_index) & add_mask; + } + break; + case R_LODSD: + add_index<<=2; + for (;count>0;count--) { + reg_eax=LoadMd(si_base+si_index); + si_index=(si_index+add_index) & add_mask; + } + break; + case R_SCASB: + { + Bit8u val2; + for (;count>0;) { + count--;CPU_Cycles--; + val2=LoadMb(di_base+di_index); + di_index=(di_index+add_index) & add_mask; + if ((reg_al==val2)!=inst.repz) break; + } + CMPB(reg_al,val2,LoadD,0); + } + break; + case R_SCASW: + { + add_index<<=1;Bit16u val2; + for (;count>0;) { + count--;CPU_Cycles--; + val2=LoadMw(di_base+di_index); + di_index=(di_index+add_index) & add_mask; + if ((reg_ax==val2)!=inst.repz) break; + } + CMPW(reg_ax,val2,LoadD,0); + } + break; + case R_SCASD: + { + add_index<<=2;Bit32u val2; + for (;count>0;) { + count--;CPU_Cycles--; + val2=LoadMd(di_base+di_index); + di_index=(di_index+add_index) & add_mask; + if ((reg_eax==val2)!=inst.repz) break; + } + CMPD(reg_eax,val2,LoadD,0); + } + break; + case R_CMPSB: + { + Bit8u val1,val2; + for (;count>0;) { + count--;CPU_Cycles--; + val1=LoadMb(si_base+si_index); + val2=LoadMb(di_base+di_index); + si_index=(si_index+add_index) & add_mask; + di_index=(di_index+add_index) & add_mask; + if ((val1==val2)!=inst.repz) break; + } + CMPB(val1,val2,LoadD,0); + } + break; + case R_CMPSW: + { + add_index<<=1;Bit16u val1,val2; + for (;count>0;) { + count--;CPU_Cycles--; + val1=LoadMw(si_base+si_index); + val2=LoadMw(di_base+di_index); + si_index=(si_index+add_index) & add_mask; + di_index=(di_index+add_index) & add_mask; + if ((val1==val2)!=inst.repz) break; + } + CMPW(val1,val2,LoadD,0); + } + break; + case R_CMPSD: + { + add_index<<=2;Bit32u val1,val2; + for (;count>0;) { + count--;CPU_Cycles--; + val1=LoadMd(si_base+si_index); + val2=LoadMd(di_base+di_index); + si_index=(si_index+add_index) & add_mask; + di_index=(di_index+add_index) & add_mask; + if ((val1==val2)!=inst.repz) break; + } + CMPD(val1,val2,LoadD,0); + } + break; + default: + LOG(LOG_CPU,LOG_ERROR)("Unhandled string %d entry %X",inst.code.op,inst.entry); + } + /* Clean up after certain amount of instructions */ + reg_esi&=(~add_mask); + reg_esi|=(si_index & add_mask); + reg_edi&=(~add_mask); + reg_edi|=(di_index & add_mask); + if (inst.prefix & PREFIX_REP) { + count+=count_left; + reg_ecx&=(~add_mask); + reg_ecx|=(count & add_mask); + } +} diff --git a/src/cpu/core_full/support.h b/src/cpu/core_full/support.h new file mode 100644 index 0000000..fd50313 --- /dev/null +++ b/src/cpu/core_full/support.h @@ -0,0 +1,188 @@ +enum { + L_N=0, + L_SKIP, + /* Grouped ones using MOD/RM */ + L_MODRM, + + L_Ib,L_Iw,L_Id, + L_Ibx,L_Iwx,L_Idx, //Sign extend + L_Ifw,L_Ifd, + L_OP, + + L_REGb,L_REGw,L_REGd, + L_REGbIb,L_REGwIw,L_REGdId, + L_POPw,L_POPd, + L_POPfw,L_POPfd, + L_SEG, + + + + L_FLG,L_INTO, + + L_VAL, + L_PRESEG, + L_DOUBLE, + L_PREOP,L_PREADD,L_PREREP,L_PREREPNE, + L_STRING, + +/* Direct ones */ + D_IRETw,D_IRETd, + D_PUSHAw,D_PUSHAd, + D_POPAw,D_POPAd, + D_DAA,D_DAS, + D_AAA,D_AAS, + D_CBW,D_CWDE, + D_CWD,D_CDQ, + D_SETALC, + D_XLATw,D_XLATd, + 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, +}; + + +enum { + O_N=t_LASTFLAG, + O_COND, + O_XCHG_AX,O_XCHG_EAX, + O_IMULRw,O_IMULRd, + O_BOUNDw,O_BOUNDd, + O_CALLNw,O_CALLNd, + O_CALLFw,O_CALLFd, + O_JMPFw,O_JMPFd, + + O_OPAL,O_ALOP, + O_OPAX,O_AXOP, + O_OPEAX,O_EAXOP, + O_INT, + O_SEGDS,O_SEGES,O_SEGFS,O_SEGGS,O_SEGSS, + O_LOOP,O_LOOPZ,O_LOOPNZ,O_JCXZ, + O_INb,O_INw,O_INd, + O_OUTb,O_OUTw,O_OUTd, + + O_NOT,O_AAM,O_AAD, + O_MULb,O_MULw,O_MULd, + O_IMULb,O_IMULw,O_IMULd, + O_DIVb,O_DIVw,O_DIVd, + O_IDIVb,O_IDIVw,O_IDIVd, + O_CBACK, + + + O_DSHLw,O_DSHLd, + O_DSHRw,O_DSHRd, + O_C_O ,O_C_NO ,O_C_B ,O_C_NB ,O_C_Z ,O_C_NZ ,O_C_BE ,O_C_NBE, + O_C_S ,O_C_NS ,O_C_P ,O_C_NP ,O_C_L ,O_C_NL ,O_C_LE ,O_C_NLE, + + O_GRP6w,O_GRP6d, + O_GRP7w,O_GRP7d, + O_M_Cd_Rd,O_M_Rd_Cd, + O_LAR,O_LSL, + O_ARPL, + + O_BTw,O_BTSw,O_BTRw,O_BTCw, + O_BTd,O_BTSd,O_BTRd,O_BTCd, + O_BSFw,O_BSRw,O_BSFd,O_BSRd, + + O_BSWAP, + O_FPU, + + +}; + +enum { + S_N=0, + S_C_Eb, + S_Eb,S_Gb,S_EbGb, + S_Ew,S_Gw,S_EwGw, + S_Ed,S_Gd,S_EdGd,S_EdMw, + + + S_REGb,S_REGw,S_REGd, + S_PUSHw,S_PUSHd, + S_SEGI, + S_SEGm, + S_SEGGw,S_SEGGd, + + + S_AIPw,S_C_AIPw, + S_AIPd,S_C_AIPd, + + S_FLGb,S_FLGw,S_FLGd, + S_IP,S_IPIw, +}; + +enum { + R_OUTSB,R_OUTSW,R_OUTSD, + R_INSB,R_INSW,R_INSD, + R_MOVSB,R_MOVSW,R_MOVSD, + R_LODSB,R_LODSW,R_LODSD, + R_STOSB,R_STOSW,R_STOSD, + R_SCASB,R_SCASW,R_SCASD, + R_CMPSB,R_CMPSW,R_CMPSD, +}; + +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_EbIb, + M_EwIw,M_EwIbx,M_EwxIbx,M_EwxIwx,M_EwGwIb,M_EwGwCL, + M_EdId,M_EdIbx,M_EdGdIb,M_EdGdCL, + + M_Efw,M_Efd, + + M_Ib,M_Iw,M_Id, + + + M_SEG,M_EA, + M_GRP, + M_GRP_Ib,M_GRP_CL,M_GRP_1, + + M_POPw,M_POPd, +}; + +struct OpCode { + Bit8u load,op,save,extra; +}; + +struct FullData { + Bitu entry; + EAPoint start; + Bitu rm; + EAPoint rm_eaa; + Bitu rm_off; + Bitu rm_eai; + Bitu rm_index; + Bitu rm_mod; + OpCode code; + union { + Bit8u b;Bit8s bs; + Bit16u w;Bit16s ws; + Bit32u d;Bit32s ds; + } op1,op2,imm; + Bitu new_flags; + struct { + EAPoint base; + } seg; + Bitu cond; + bool repz; + Bitu prefix; + Bitu start_prefix; + Bitu start_entry; +}; + + +#define PREFIX_NONE 0x0 +#define PREFIX_SEG 0x1 +#define PREFIX_ADDR 0x2 +#define PREFIX_REP 0x4 + diff --git a/src/cpu/core_normal.cpp b/src/cpu/core_normal.cpp new file mode 100644 index 0000000..c7c77f7 --- /dev/null +++ b/src/cpu/core_normal.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2002-2003 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" +#include "mem.h" +#include "cpu.h" +#include "lazyflags.h" +#include "inout.h" +#include "callback.h" +#include "pic.h" +#include "fpu.h" + +#if C_DEBUG +#include "debug.h" +#endif + + +#define SegBase(c) SegPhys(c) +#if (!C_CORE_INLINE) + +#define LoadMb(off) mem_readb(off) +#define LoadMw(off) mem_readw(off) +#define LoadMd(off) mem_readd(off) + +#define SaveMb(off,val) mem_writeb(off,val) +#define SaveMw(off,val) mem_writew(off,val) +#define SaveMd(off,val) mem_writed(off,val) + +#else + +#include "paging.h" +#define LoadMb(off) mem_readb_inline(off) +#define LoadMw(off) mem_readw_inline(off) +#define LoadMd(off) mem_readd_inline(off) + +#define SaveMb(off,val) mem_writeb_inline(off,val) +#define SaveMw(off,val) mem_writew_inline(off,val) +#define SaveMd(off,val) mem_writed_inline(off,val) + +#endif + +#define LoadMbs(off) (Bit8s)(LoadMb(off)) +#define LoadMws(off) (Bit16s)(LoadMw(off)) +#define LoadMds(off) (Bit32s)(LoadMd(off)) + +#define LoadRb(reg) reg +#define LoadRw(reg) reg +#define LoadRd(reg) reg + +#define SaveRb(reg,val) reg=val +#define SaveRw(reg,val) reg=val +#define SaveRd(reg,val) reg=val + +extern Bitu cycle_count; + +#if C_FPU +#define CPU_FPU 1 //Enable FPU escape instructions +#endif + +#define CPU_PIC_CHECK 1 +#define CPU_TRAP_CHECK 1 + +#define OPCODE_NONE 0x000 +#define OPCODE_0F 0x100 +#define OPCODE_SIZE 0x200 + +#define PREFIX_SEG 0x1 +#define PREFIX_ADDR 0x2 +#define PREFIX_SEG_ADDR (PREFIX_SEG|PREFIX_ADDR) +#define PREFIX_REP 0x4 + +#define TEST_PREFIX_SEG (core.prefixes & PREFIX_SEG) +#define TEST_PREFIX_ADDR (core.prefixes & PREFIX_ADDR) +#define TEST_PREFIX_REP (core.prefixes & PREFIX_REP) + +#define DO_PREFIX_SEG(_SEG) \ + core.prefixes|=PREFIX_SEG; \ + core.seg_prefix_base=SegBase(_SEG); \ + goto restart_prefix; + +#define DO_PREFIX_ADDR() \ + core.prefixes^=PREFIX_ADDR; \ + goto restart_prefix; + +#define DO_PREFIX_REP(_ZERO) \ + core.prefixes|=PREFIX_REP; \ + core.rep_zero=_ZERO; \ + goto restart_prefix; + +typedef PhysPt (*GetEATable[256])(void); + +static struct { + Bitu opcode_index; + Bitu prefixes; + Bitu index_default; + Bitu prefix_default; + PhysPt op_start; + PhysPt ip_lookup; + PhysPt seg_prefix_base; + bool rep_zero; + GetEATable * ea_table; +} core; + +#include "instructions.h" +#include "core_normal/support.h" +#include "core_normal/string.h" + +static GetEATable * EAPrefixTable[8] = { + &GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR, + &GetEA_NONE,&GetEA_SEG,&GetEA_ADDR,&GetEA_SEG_ADDR, +}; + +#define CASE_W(_WHICH) \ + case (OPCODE_NONE+_WHICH): + +#define CASE_D(_WHICH) \ + case (OPCODE_SIZE+_WHICH): + +#define CASE_B(_WHICH) \ + CASE_W(_WHICH) \ + CASE_D(_WHICH) + +#define CASE_0F_W(_WHICH) \ + case ((OPCODE_0F|OPCODE_NONE)+_WHICH): + +#define CASE_0F_D(_WHICH) \ + case ((OPCODE_0F|OPCODE_SIZE)+_WHICH): + +#define CASE_0F_B(_WHICH) \ + CASE_0F_W(_WHICH) \ + CASE_0F_D(_WHICH) + +#define EALookupTable (*(core.ea_table)) + + +static Bits CPU_Core_Normal_Decode_Trap(void); + +static Bits CPU_Core_Normal_Decode(void) { +decode_start: + LOADIP; + flags.type=t_UNKNOWN; + while (CPU_Cycles>0) { + core.op_start=core.ip_lookup; + core.opcode_index=core.index_default; + core.prefixes=core.prefix_default; +#if C_DEBUG + cycle_count++; +#if C_HEAVY_DEBUG + SAVEIP; + if (DEBUG_HeavyIsBreakpoint()) { + LEAVECORE; + return debugCallback; + }; +#endif +#endif + CPU_Cycles--; +restart_prefix: + core.ea_table=EAPrefixTable[core.prefixes]; +restart_opcode: + switch (core.opcode_index+Fetchb()) { + + #include "core_normal/prefix_none.h" + #include "core_normal/prefix_0f.h" + #include "core_normal/prefix_66.h" + #include "core_normal/prefix_66_0f.h" + default: + ADDIPFAST(-1); +#if C_DEBUG + LOG_MSG("Unhandled code %X",core.opcode_index+Fetchb()); +#else + E_Exit("Unhandled CPU opcode"); +#endif + } + } + decode_end: + LEAVECORE; + return CBRET_NONE; +} + +static Bits CPU_Core_Normal_Decode_Trap(void) { + + Bits oldCycles = CPU_Cycles; + CPU_Cycles = 1; + Bits ret=CPU_Core_Normal_Decode(); + + Interrupt(1); + + CPU_Cycles = oldCycles-1; + cpudecoder = &CPU_Core_Normal_Decode; + + return ret; +} + + + +void CPU_Core_Normal_Start(bool big) { + + if (GETFLAG(TF)) cpudecoder=CPU_Core_Normal_Decode_Trap; + else cpudecoder=CPU_Core_Normal_Decode; + + 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.am b/src/cpu/core_normal/Makefile.am new file mode 100644 index 0000000..99f76f3 --- /dev/null +++ b/src/cpu/core_normal/Makefile.am @@ -0,0 +1,3 @@ + +noinst_HEADERS = helpers.h prefix_none.h prefix_66.h prefix_0f.h support.h table_ea.h \ + prefix_66_0f.h string.h diff --git a/src/cpu/core_normal/Makefile.in b/src/cpu/core_normal/Makefile.in new file mode 100644 index 0000000..5557fef --- /dev/null +++ b/src/cpu/core_normal/Makefile.in @@ -0,0 +1,326 @@ +# Makefile.in generated by automake 1.7.7 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@ + +noinst_HEADERS = helpers.h prefix_none.h prefix_66.h prefix_0f.h support.h table_ea.h \ + prefix_66_0f.h string.h + +subdir = src/cpu/core_normal +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.in Makefile.am +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits src/cpu/core_normal/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) + +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic ctags \ + distclean distclean-generic distclean-tags distdir dvi dvi-am \ + info info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/cpu/core_normal/helpers.h b/src/cpu/core_normal/helpers.h new file mode 100644 index 0000000..6a30e05 --- /dev/null +++ b/src/cpu/core_normal/helpers.h @@ -0,0 +1,143 @@ +/* + * 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=EALookupTable[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_normal/prefix_0f.h b/src/cpu/core_normal/prefix_0f.h new file mode 100644 index 0000000..0871fab --- /dev/null +++ b/src/cpu/core_normal/prefix_0f.h @@ -0,0 +1,449 @@ +/* + * 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. + */ + + CASE_0F_W(0x00) /* GRP 6 Exxx */ + { + 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: + { + FillFlags(); + 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_0F_W(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_0F_W(0x02) /* LAR Gw,Ew */ + { + FillFlags(); + GetRMrw;Bitu ar; + if (rm >= 0xc0) { + GetEArw;CPU_LAR(*earw,ar); + } else { + GetEAa;CPU_LAR(LoadMw(eaa),ar); + } + *rmrw=(Bit16u)ar; + } + break; + CASE_0F_W(0x03) /* LSL Gw,Ew */ + { + FillFlags(); + GetRMrw;Bitu limit; + if (rm >= 0xc0) { + GetEArw;CPU_LSL(*earw,limit); + } else { + GetEAa;CPU_LSL(LoadMw(eaa),limit); + } + *rmrw=(Bit16u)limit; + } + break; + CASE_0F_B(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_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; + } else { + GetEAa; + LOG(LOG_CPU,LOG_ERROR)("MOV CR%,XXX with non-register",which); + } + } + break; + CASE_0F_B(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_0F_W(0x80) /* JO */ + JumpSIw(get_OF());break; + CASE_0F_W(0x81) /* JNO */ + JumpSIw(!get_OF());break; + CASE_0F_W(0x82) /* JB */ + JumpSIw(get_CF());break; + CASE_0F_W(0x83) /* JNB */ + JumpSIw(!get_CF());break; + CASE_0F_W(0x84) /* JZ */ + JumpSIw(get_ZF());break; + CASE_0F_W(0x85) /* JNZ */ + JumpSIw(!get_ZF());break; + CASE_0F_W(0x86) /* JBE */ + JumpSIw(get_CF() || get_ZF());break; + CASE_0F_W(0x87) /* JNBE */ + JumpSIw(!get_CF() && !get_ZF());break; + CASE_0F_W(0x88) /* JS */ + JumpSIw(get_SF());break; + CASE_0F_W(0x89) /* JNS */ + JumpSIw(!get_SF());break; + CASE_0F_W(0x8a) /* JP */ + JumpSIw(get_PF());break; + CASE_0F_W(0x8b) /* JNP */ + JumpSIw(!get_PF());break; + CASE_0F_W(0x8c) /* JL */ + JumpSIw(get_SF() != get_OF());break; + CASE_0F_W(0x8d) /* JNL */ + JumpSIw(get_SF() == get_OF());break; + CASE_0F_W(0x8e) /* JLE */ + JumpSIw(get_ZF() || (get_SF() != get_OF()));break; + CASE_0F_W(0x8f) /* JNLE */ + JumpSIw((get_SF() == get_OF()) && !get_ZF());break; + CASE_0F_B(0x90) /* SETO */ + SETcc(get_OF());break; + CASE_0F_B(0x91) /* SETNO */ + SETcc(!get_OF());break; + CASE_0F_B(0x92) /* SETB */ + SETcc(get_CF());break; + CASE_0F_B(0x93) /* SETNB */ + SETcc(!get_CF());break; + CASE_0F_B(0x94) /* SETZ */ + SETcc(get_ZF());break; + CASE_0F_B(0x95) /* SETNZ */ + SETcc(!get_ZF()); break; + CASE_0F_B(0x96) /* SETBE */ + SETcc(get_CF() || get_ZF());break; + CASE_0F_B(0x97) /* SETNBE */ + SETcc(!get_CF() && !get_ZF());break; + CASE_0F_B(0x98) /* SETS */ + SETcc(get_SF());break; + CASE_0F_B(0x99) /* SETNS */ + SETcc(!get_SF());break; + CASE_0F_B(0x9a) /* SETP */ + SETcc(get_PF());break; + CASE_0F_B(0x9b) /* SETNP */ + SETcc(!get_PF());break; + CASE_0F_B(0x9c) /* SETL */ + SETcc(get_SF() != get_OF());break; + CASE_0F_B(0x9d) /* SETNL */ + SETcc(get_SF() == get_OF());break; + CASE_0F_B(0x9e) /* SETLE */ + SETcc(get_ZF() || (get_SF() != get_OF()));break; + CASE_0F_B(0x9f) /* SETNLE */ + SETcc((get_SF() == get_OF()) && !get_ZF());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_B(0xa2) /* CPUID */ + CPU_CPUID();break; + CASE_0F_W(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_0F_W(0xa4) /* SHLD Ew,Gw,Ib */ + RMEwGwOp3(DSHLW,Fetchb()); + break; + CASE_0F_W(0xa5) /* SHLD Ew,Gw,CL */ + RMEwGwOp3(DSHLW,reg_cl); + break; + CASE_0F_W(0xa8) /* PUSH GS */ + Push_16(SegValue(gs));break; + CASE_0F_W(0xa9) /* POP GS */ + CPU_SetSegGeneral(gs,Pop_16());break; + CASE_0F_W(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_0F_W(0xac) /* SHRD Ew,Gw,Ib */ + RMEwGwOp3(DSHRW,Fetchb()); + break; + CASE_0F_W(0xad) /* SHRD Ew,Gw,CL */ + RMEwGwOp3(DSHRW,reg_cl); + break; + CASE_0F_W(0xaf) /* IMUL Gw,Ew */ + RMGwEwOp3(DIMULW,*rmrw); + break; + CASE_0F_W(0xb2) /* LSS Ew */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);CPU_SetSegGeneral(ss,LoadMw(eaa+2)); + break; + } + CASE_0F_W(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_0F_W(0xb4) /* LFS Ew */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);CPU_SetSegGeneral(fs,LoadMw(eaa+2)); + break; + } + CASE_0F_W(0xb5) /* LGS Ew */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);CPU_SetSegGeneral(gs,LoadMw(eaa+2)); + break; + } + CASE_0F_W(0xb6) /* MOVZX Gw,Eb */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArb;*rmrw=*earb;} + else {GetEAa;*rmrw=LoadMb(eaa);} + break; + } + CASE_0F_W(0xb7) /* MOVZX Gw,Ew */ + CASE_0F_W(0xbf) /* MOVSX Gw,Ew */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} + else {GetEAa;*rmrw=LoadMw(eaa);} + break; + } + CASE_0F_W(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_0F_W(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_0F_W(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_0F_W(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_0F_W(0xbe) /* MOVSX Gw,Eb */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArb;*rmrw=*(Bit8s *)earb;} + else {GetEAa;*rmrw=LoadMbs(eaa);} + break; + } + CASE_0F_B(0xc8) /* BSWAP EAX */ + BSWAP(reg_eax);break; + CASE_0F_B(0xc9) /* BSWAP ECX */ + BSWAP(reg_ecx);break; + CASE_0F_B(0xca) /* BSWAP EDX */ + BSWAP(reg_edx);break; + CASE_0F_B(0xcb) /* BSWAP EBX */ + BSWAP(reg_ebx);break; + CASE_0F_B(0xcc) /* BSWAP ESP */ + BSWAP(reg_esp);break; + CASE_0F_B(0xcd) /* BSWAP EBP */ + BSWAP(reg_ebp);break; + CASE_0F_B(0xce) /* BSWAP ESI */ + BSWAP(reg_esi);break; + CASE_0F_B(0xcf) /* BSWAP EDI */ + BSWAP(reg_edi);break; + diff --git a/src/cpu/core_normal/prefix_66.h b/src/cpu/core_normal/prefix_66.h new file mode 100644 index 0000000..1530db9 --- /dev/null +++ b/src/cpu/core_normal/prefix_66.h @@ -0,0 +1,666 @@ +/* + * 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. + */ + + CASE_D(0x01) /* ADD Ed,Gd */ + RMEdGd(ADDD);break; + CASE_D(0x03) /* ADD Gd,Ed */ + RMGdEd(ADDD);break; + CASE_D(0x05) /* ADD EAX,Id */ + 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(0x09) /* OR Ed,Gd */ + RMEdGd(ORD);break; + CASE_D(0x0b) /* OR Gd,Ed */ + RMGdEd(ORD);break; + CASE_D(0x0d) /* OR EAX,Id */ + EAXId(ORD);break; + CASE_D(0x0e) /* PUSH CS */ + Push_32(SegValue(cs));break; + CASE_D(0x11) /* ADC Ed,Gd */ + RMEdGd(ADCD);break; + CASE_D(0x13) /* ADC Gd,Ed */ + RMGdEd(ADCD);break; + CASE_D(0x15) /* ADC EAX,Id */ + EAXId(ADCD);break; + CASE_D(0x16) /* PUSH SS */ + Push_32(SegValue(ss));break; + CASE_D(0x17) /* POP SS */ + CPU_SetSegGeneral(ss,(Bit16u)Pop_32());break; + CASE_D(0x19) /* SBB Ed,Gd */ + RMEdGd(SBBD);break; + CASE_D(0x1b) /* SBB Gd,Ed */ + RMGdEd(SBBD);break; + CASE_D(0x1d) /* SBB EAX,Id */ + EAXId(SBBD);break; + CASE_D(0x1e) /* PUSH DS */ + Push_32(SegValue(ds));break; + CASE_D(0x1f) /* POP DS */ + CPU_SetSegGeneral(ds,(Bit16u)Pop_32());break; + CASE_D(0x21) /* AND Ed,Gd */ + RMEdGd(ANDD);break; + CASE_D(0x23) /* AND Gd,Ed */ + RMGdEd(ANDD);break; + CASE_D(0x25) /* AND EAX,Id */ + EAXId(ANDD);break; + CASE_D(0x29) /* SUB Ed,Gd */ + RMEdGd(SUBD);break; + CASE_D(0x2b) /* SUB Gd,Ed */ + RMGdEd(SUBD);break; + CASE_D(0x2d) /* SUB EAX,Id */ + EAXId(SUBD);break; + CASE_D(0x31) /* XOR Ed,Gd */ + RMEdGd(XORD);break; + CASE_D(0x33) /* XOR Gd,Ed */ + RMGdEd(XORD);break; + CASE_D(0x35) /* XOR EAX,Id */ + EAXId(XORD);break; + CASE_D(0x39) /* CMP Ed,Gd */ + RMEdGd(CMPD);break; + CASE_D(0x3b) /* CMP Gd,Ed */ + RMGdEd(CMPD);break; + CASE_D(0x3d) /* CMP EAX,Id */ + EAXId(CMPD);break; + CASE_D(0x40) /* INC EAX */ + INCD(reg_eax,LoadRd,SaveRd);break; + CASE_D(0x41) /* INC ECX */ + INCD(reg_ecx,LoadRd,SaveRd);break; + CASE_D(0x42) /* INC EDX */ + INCD(reg_edx,LoadRd,SaveRd);break; + CASE_D(0x43) /* INC EBX */ + INCD(reg_ebx,LoadRd,SaveRd);break; + CASE_D(0x44) /* INC ESP */ + INCD(reg_esp,LoadRd,SaveRd);break; + CASE_D(0x45) /* INC EBP */ + INCD(reg_ebp,LoadRd,SaveRd);break; + CASE_D(0x46) /* INC ESI */ + INCD(reg_esi,LoadRd,SaveRd);break; + CASE_D(0x47) /* INC EDI */ + INCD(reg_edi,LoadRd,SaveRd);break; + CASE_D(0x48) /* DEC EAX */ + DECD(reg_eax,LoadRd,SaveRd);break; + CASE_D(0x49) /* DEC ECX */ + DECD(reg_ecx,LoadRd,SaveRd);break; + CASE_D(0x4a) /* DEC EDX */ + DECD(reg_edx,LoadRd,SaveRd);break; + CASE_D(0x4b) /* DEC EBX */ + DECD(reg_ebx,LoadRd,SaveRd);break; + CASE_D(0x4c) /* DEC ESP */ + DECD(reg_esp,LoadRd,SaveRd);break; + CASE_D(0x4d) /* DEC EBP */ + DECD(reg_ebp,LoadRd,SaveRd);break; + CASE_D(0x4e) /* DEC ESI */ + DECD(reg_esi,LoadRd,SaveRd);break; + CASE_D(0x4f) /* DEC EDI */ + DECD(reg_edi,LoadRd,SaveRd);break; + CASE_D(0x50) /* PUSH EAX */ + Push_32(reg_eax);break; + CASE_D(0x51) /* PUSH ECX */ + Push_32(reg_ecx);break; + CASE_D(0x52) /* PUSH EDX */ + Push_32(reg_edx);break; + CASE_D(0x53) /* PUSH EBX */ + Push_32(reg_ebx);break; + CASE_D(0x54) /* PUSH ESP */ + Push_32(reg_esp);break; + CASE_D(0x55) /* PUSH EBP */ + Push_32(reg_ebp);break; + CASE_D(0x56) /* PUSH ESI */ + Push_32(reg_esi);break; + CASE_D(0x57) /* PUSH EDI */ + Push_32(reg_edi);break; + CASE_D(0x58) /* POP EAX */ + reg_eax=Pop_32();break; + CASE_D(0x59) /* POP ECX */ + reg_ecx=Pop_32();break; + CASE_D(0x5a) /* POP EDX */ + reg_edx=Pop_32();break; + CASE_D(0x5b) /* POP EBX */ + reg_ebx=Pop_32();break; + CASE_D(0x5c) /* POP ESP */ + reg_esp=Pop_32();break; + CASE_D(0x5d) /* POP EBP */ + reg_ebp=Pop_32();break; + CASE_D(0x5e) /* POP ESI */ + reg_esi=Pop_32();break; + CASE_D(0x5f) /* POP EDI */ + reg_edi=Pop_32();break; + CASE_D(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_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(); + break; + CASE_D(0x62) /* BOUND Ed */ + { + Bit32s bound_min, bound_max; + GetRMrd;GetEAa; + bound_min=LoadMd(eaa); + bound_max=LoadMd(eaa+4); + if ( (((Bit32s)*rmrd) < bound_min) || (((Bit32s)*rmrd) > bound_max) ) { + EXCEPTION(5); + } + } + break; + CASE_D(0x63) /* ARPL Ed,Rd */ + { + FillFlags(); + GetRMrw; + if (rm >= 0xc0 ) { + GetEArd;Bitu new_sel=(Bit16u)*eard; + CPU_ARPL(new_sel,*rmrw); + *eard=(Bit32u)new_sel; + } else { + GetEAa;Bitu new_sel=LoadMw(eaa); + CPU_ARPL(new_sel,*rmrw); + SaveMd(eaa,(Bit32u)new_sel); + } + } + break; + CASE_D(0x68) /* PUSH Id */ + Push_32(Fetchd());break; + CASE_D(0x69) /* IMUL Gd,Ed,Id */ + RMGdEdOp3(DIMULD,Fetchds()); + break; + CASE_D(0x6a) /* PUSH Ib */ + Push_32(Fetchbs());break; + CASE_D(0x6b) /* IMUL Gd,Ed,Ib */ + RMGdEdOp3(DIMULD,Fetchbs()); + break; + CASE_D(0x81) /* Grpl Ed,Id */ + { + GetRM;Bitu which=(rm>>3)&7; + if (rm >= 0xc0) { + GetEArd;Bit32u id=Fetchd(); + switch (which) { + case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; + case 0x01: ORD(*eard,id,LoadRd,SaveRd);break; + case 0x02:ADCD(*eard,id,LoadRd,SaveRd);break; + case 0x03:SBBD(*eard,id,LoadRd,SaveRd);break; + case 0x04:ANDD(*eard,id,LoadRd,SaveRd);break; + case 0x05:SUBD(*eard,id,LoadRd,SaveRd);break; + case 0x06:XORD(*eard,id,LoadRd,SaveRd);break; + case 0x07:CMPD(*eard,id,LoadRd,SaveRd);break; + } + } else { + GetEAa;Bit32u id=Fetchd(); + switch (which) { + case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; + case 0x01: ORD(eaa,id,LoadMd,SaveMd);break; + case 0x02:ADCD(eaa,id,LoadMd,SaveMd);break; + case 0x03:SBBD(eaa,id,LoadMd,SaveMd);break; + case 0x04:ANDD(eaa,id,LoadMd,SaveMd);break; + case 0x05:SUBD(eaa,id,LoadMd,SaveMd);break; + case 0x06:XORD(eaa,id,LoadMd,SaveMd);break; + case 0x07:CMPD(eaa,id,LoadMd,SaveMd);break; + } + } + } + break; + CASE_D(0x83) /* Grpl Ed,Ix */ + { + GetRM;Bitu which=(rm>>3)&7; + if (rm >= 0xc0) { + GetEArd;Bit32u id=(Bit32s)Fetchbs(); + switch (which) { + case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break; + case 0x01: ORD(*eard,id,LoadRd,SaveRd);break; + case 0x02:ADCD(*eard,id,LoadRd,SaveRd);break; + case 0x03:SBBD(*eard,id,LoadRd,SaveRd);break; + case 0x04:ANDD(*eard,id,LoadRd,SaveRd);break; + case 0x05:SUBD(*eard,id,LoadRd,SaveRd);break; + case 0x06:XORD(*eard,id,LoadRd,SaveRd);break; + case 0x07:CMPD(*eard,id,LoadRd,SaveRd);break; + } + } else { + GetEAa;Bit32u id=(Bit32s)Fetchbs(); + switch (which) { + case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; + case 0x01: ORD(eaa,id,LoadMd,SaveMd);break; + case 0x02:ADCD(eaa,id,LoadMd,SaveMd);break; + case 0x03:SBBD(eaa,id,LoadMd,SaveMd);break; + case 0x04:ANDD(eaa,id,LoadMd,SaveMd);break; + case 0x05:SUBD(eaa,id,LoadMd,SaveMd);break; + case 0x06:XORD(eaa,id,LoadMd,SaveMd);break; + case 0x07:CMPD(eaa,id,LoadMd,SaveMd);break; + } + } + } + break; + CASE_D(0x85) /* TEST Ed,Gd */ + RMEdGd(TESTD);break; + CASE_D(0x87) /* XCHG Ed,Gd */ + { + GetRMrd;Bit32u oldrmrd=*rmrd; + if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard=oldrmrd;} + else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,oldrmrd);} + break; + } + CASE_D(0x89) /* MOV Ed,Gd */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArd;*eard=*rmrd;} + else {GetEAa;SaveMd(eaa,*rmrd);} + break; + } + CASE_D(0x8b) /* MOV Gd,Ed */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;} + else {GetEAa;*rmrd=LoadMd(eaa);} + break; + } + CASE_D(0x8c) /* Mov Ew,Sw */ + { + GetRM;Bit16u val;Bitu which=(rm>>3)&7; + switch (which) { + case 0x00: /* MOV Ew,ES */ + val=SegValue(es);break; + case 0x01: /* MOV Ew,CS */ + val=SegValue(cs);break; + case 0x02: /* MOV Ew,SS */ + val=SegValue(ss);break; + case 0x03: /* MOV Ew,DS */ + val=SegValue(ds);break; + case 0x04: /* MOV Ew,FS */ + val=SegValue(fs);break; + case 0x05: /* MOV Ew,GS */ + val=SegValue(gs);break; + default: + val=0; + E_Exit("CPU:8c:Illegal RM Byte"); + } + if (rm >= 0xc0 ) {GetEArd;*eard=val;} + else {GetEAa;SaveMw(eaa,val);} + break; + } + CASE_D(0x8d) /* LEA Gd */ + { + //Little hack to always use segprefixed version + core.seg_prefix_base=0; + GetRMrd; + if (TEST_PREFIX_ADDR) { + *rmrd=(Bit32u)(*GetEA_SEG_ADDR[rm])(); + } else { + *rmrd=(Bit32u)(*GetEA_SEG[rm])(); + } + break; + } + CASE_D(0x8f) /* POP Ed */ + { + GetRM; + if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();} + else {GetEAa;SaveMd(eaa,Pop_32());} + break; + } + CASE_D(0x91) /* XCHG ECX,EAX */ + { Bit32u temp=reg_eax;reg_eax=reg_ecx;reg_ecx=temp;break;} + CASE_D(0x92) /* XCHG EDX,EAX */ + { Bit32u temp=reg_eax;reg_eax=reg_edx;reg_edx=temp;break;} + break; + CASE_D(0x93) /* XCHG EBX,EAX */ + { Bit32u temp=reg_eax;reg_eax=reg_ebx;reg_ebx=temp;break;} + break; + CASE_D(0x94) /* XCHG ESP,EAX */ + { Bit32u temp=reg_eax;reg_eax=reg_esp;reg_esp=temp;break;} + break; + CASE_D(0x95) /* XCHG EBP,EAX */ + { Bit32u temp=reg_eax;reg_eax=reg_ebp;reg_ebp=temp;break;} + break; + CASE_D(0x96) /* XCHG ESI,EAX */ + { Bit32u temp=reg_eax;reg_eax=reg_esi;reg_esi=temp;break;} + break; + CASE_D(0x97) /* XCHG EDI,EAX */ + { Bit32u temp=reg_eax;reg_eax=reg_edi;reg_edi=temp;break;} + break; + CASE_D(0x98) /* CWDE */ + reg_eax=(Bit16s)reg_ax;break; + CASE_D(0x99) /* CDQ */ + if (reg_eax & 0x80000000) reg_edx=0xffffffff; + else reg_edx=0; + break; + 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; + } + CASE_D(0x9c) /* PUSHFD */ + FillFlags(); + Push_32(flags.word); + break; + CASE_D(0x9d) /* POPFD */ + SETFLAGSd(Pop_32()) +#if CPU_TRAP_CHECK + if (GETFLAG(TF)) { + cpudecoder=CPU_Core_Normal_Decode_Trap; + goto decode_end; + } +#endif +#ifdef CPU_PIC_CHECK + if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; +#endif + + break; + CASE_D(0xa1) /* MOV EAX,Od */ + { + GetEADirect; + reg_eax=LoadMd(eaa); + } + break; + CASE_D(0xa3) /* MOV Od,EAX */ + { + GetEADirect; + SaveMd(eaa,reg_eax); + } + break; + CASE_D(0xa5) /* MOVSD */ + DoString(R_MOVSD);break; + CASE_D(0xa7) /* CMPSD */ + DoString(R_CMPSD);break; + CASE_D(0xa9) /* TEST EAX,Id */ + EAXId(TESTD);break; + CASE_D(0xab) /* STOSD */ + DoString(R_STOSD);break; + CASE_D(0xad) /* LODSD */ + DoString(R_LODSD);break; + CASE_D(0xaf) /* SCASD */ + DoString(R_SCASD);break; + CASE_D(0xb8) /* MOV EAX,Id */ + reg_eax=Fetchd();break; + CASE_D(0xb9) /* MOV ECX,Id */ + reg_ecx=Fetchd();break; + CASE_D(0xba) /* MOV EDX,Iw */ + reg_edx=Fetchd();break; + CASE_D(0xbb) /* MOV EBX,Id */ + reg_ebx=Fetchd();break; + CASE_D(0xbc) /* MOV ESP,Id */ + reg_esp=Fetchd();break; + CASE_D(0xbd) /* MOV EBP.Id */ + reg_ebp=Fetchd();break; + CASE_D(0xbe) /* MOV ESI,Id */ + reg_esi=Fetchd();break; + CASE_D(0xbf) /* MOV EDI,Id */ + reg_edi=Fetchd();break; + CASE_D(0xc1) /* GRP2 Ed,Ib */ + GRP2D(Fetchb());break; + CASE_D(0xc2) /* RETN Iw */ + { + Bit16u addsp=Fetchw(); + SETIP(Pop_32());reg_esp+=addsp; + break; + } + CASE_D(0xc3) /* RETN */ + SETIP(Pop_32()); + break; + CASE_D(0xc4) /* LES */ + { + GetRMrd;GetEAa; + *rmrd=LoadMd(eaa);CPU_SetSegGeneral(es,LoadMw(eaa+4)); + break; + } + CASE_D(0xc5) /* LDS */ + { + GetRMrd;GetEAa; + *rmrd=LoadMd(eaa);CPU_SetSegGeneral(ds,LoadMw(eaa+4)); + break; + } + CASE_D(0xc7) /* MOV Ed,Id */ + { + GetRM; + if (rm >= 0xc0) {GetEArd;*eard=Fetchd();} + else {GetEAa;SaveMd(eaa,Fetchd());} + break; + } + CASE_D(0xc8) /* ENTER Iw,Ib */ + { + Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; + Bitu frame_ptr=reg_esp-4; + if (cpu.stack.big) { + reg_esp-=4; + mem_writed(SegBase(ss)+reg_esp,reg_ebp); + for (Bitu i=1;i> 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; + } + CASE_D(0xe8) /* CALL Jd */ + { + Bit32s newip=Fetchds(); + Push_32((Bit32u)GETIP); + ADDIPd(newip); + break; + } + CASE_D(0xe9) /* JMP Jd */ + ADDIPd(Fetchds()); + break; + CASE_D(0xea) /* JMP Ad */ + { + Bit32u newip=Fetchd(); + Bit16u newcs=Fetchw(); + SAVEIP; + if (CPU_JMP(true,newcs,newip)) { + LOADIP; + } else { + FillFlags();return CBRET_NONE; + } + break; + } + 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); + 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)); + break; + CASE_D(0xf7) /* GRP3 Ed(,Id) */ + { + GetRM;Bitu which=(rm>>3)&7; + switch (which) { + 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_D(0xff) /* GRP 5 Ed */ + { + GetRM;Bitu which=(rm>>3)&7; + switch (which) { + case 0x00: /* INC Ed */ + RMEd(INCD); + break; + case 0x01: /* DEC Ed */ + RMEd(DECD); + break; + case 0x02: /* CALL NEAR Ed */ + if (rm >= 0xc0 ) {GetEArd;Push_32(GETIP);SETIP(*eard);} + else {GetEAa;Push_32(GETIP);SETIP(LoadMd(eaa));} + break; + case 0x03: /* CALL FAR Ed */ + { + GetEAa; + Bit32u newip=LoadMd(eaa); + Bit16u newcs=LoadMw(eaa+4); + SAVEIP; + if (CPU_CALL(true,newcs,newip)) { + LOADIP; + } else { + FillFlags();return CBRET_NONE; + } + } + break; + case 0x04: /* JMP NEAR Ed */ + if (rm >= 0xc0 ) {GetEArd;SETIP(*eard);} + else {GetEAa;SETIP(LoadMd(eaa));} + break; + case 0x05: /* JMP FAR Ed */ + { + GetEAa; + Bit32u newip=LoadMd(eaa); + Bit16u newcs=LoadMw(eaa+4); + SAVEIP; + if (CPU_JMP(true,newcs,newip)) { + LOADIP; + } else { + FillFlags();return CBRET_NONE; + } + } + break; + case 0x06: /* 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",which); + break; + } + break; + } + + diff --git a/src/cpu/core_normal/prefix_66_0f.h b/src/cpu/core_normal/prefix_66_0f.h new file mode 100644 index 0000000..7496d84 --- /dev/null +++ b/src/cpu/core_normal/prefix_66_0f.h @@ -0,0 +1,360 @@ +/* + * 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. + */ + CASE_0F_D(0x00) /* GRP 6 Exxx */ + { + 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=(Bit16u)saveval;} + else {GetEAa;SaveMw(eaa,saveval);} + } + break; + case 0x02:case 0x03:case 0x04:case 0x05: + { + /* Just use 16-bit loads since were only using selectors */ + FillFlags(); + Bitu loadval; + if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} + else {GetEAa;loadval=LoadMw(eaa);} + 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_0F_D(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,(Bit16u)limit); + SaveMd(eaa+2,(Bit32u)base); + break; + case 0x01: /* SIDT */ + CPU_SIDT(limit,base); + SaveMw(eaa,(Bit16u)limit); + SaveMd(eaa+2,(Bit32u)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,(Bit16u)limit); + break; + case 0x06: /* LMSW */ + limit=LoadMw(eaa); + if (!CPU_LMSW((Bit16u)limit)) goto decode_end; + break; + } + } else { + GetEArd;Bitu limit; + switch (which) { + case 0x04: /* SMSW */ + CPU_SMSW(limit); + *eard=(Bit32u)limit; + break; + case 0x06: /* LMSW */ + if (!CPU_LMSW(*eard)) goto decode_end; + break; + default: + LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which); + break; + } + + } + } + break; + CASE_0F_D(0x02) /* LAR Gd,Ed */ + { + FillFlags(); + GetRMrd;Bitu ar; + if (rm >= 0xc0) { + GetEArw;CPU_LAR(*earw,ar); + } else { + GetEAa;CPU_LAR(LoadMw(eaa),ar); + } + *rmrd=(Bit32u)ar; + } + break; + CASE_0F_D(0x03) /* LSL Gd,Ew */ + { + FillFlags(); + GetRMrd;Bitu limit; + /* Just load 16-bit values for selectors */ + if (rm >= 0xc0) { + GetEArw;CPU_LSL(*earw,limit); + } else { + GetEAa;CPU_LSL(LoadMw(eaa),limit); + } + *rmrd=(Bit16u)limit; + } + break; + CASE_0F_D(0x80) /* JO */ + JumpSId(get_OF());break; + CASE_0F_D(0x81) /* JNO */ + JumpSId(!get_OF());break; + CASE_0F_D(0x82) /* JB */ + JumpSId(get_CF());break; + CASE_0F_D(0x83) /* JNB */ + JumpSId(!get_CF());break; + CASE_0F_D(0x84) /* JZ */ + JumpSId(get_ZF());break; + CASE_0F_D(0x85) /* JNZ */ + JumpSId(!get_ZF());break; + CASE_0F_D(0x86) /* JBE */ + JumpSId(get_CF() || get_ZF());break; + CASE_0F_D(0x87) /* JNBE */ + JumpSId(!get_CF() && !get_ZF());break; + CASE_0F_D(0x88) /* JS */ + JumpSId(get_SF());break; + CASE_0F_D(0x89) /* JNS */ + JumpSId(!get_SF());break; + CASE_0F_D(0x8a) /* JP */ + JumpSId(get_PF());break; + CASE_0F_D(0x8b) /* JNP */ + JumpSId(!get_PF());break; + CASE_0F_D(0x8c) /* JL */ + JumpSId(get_SF() != get_OF());break; + CASE_0F_D(0x8d) /* JNL */ + JumpSId(get_SF() == get_OF());break; + CASE_0F_D(0x8e) /* JLE */ + JumpSId(get_ZF() || (get_SF() != get_OF()));break; + CASE_0F_D(0x8f) /* JNLE */ + JumpSId((get_SF() == get_OF()) && !get_ZF());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; + + CASE_0F_D(0xa3) /* BT Ed,Gd */ + { + GetRMrd; + Bit32u mask=1 << (*rmrd & 31); + if (rm >= 0xc0 ) { + GetEArd; + SETFLAGBIT(CF,(*eard & mask)); + } else { + GetEAa;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 */ + RMEdGdOp3(DSHLD,Fetchb()); + break; + CASE_0F_D(0xa5) /* SHLD Ed,Gd,CL */ + RMEdGdOp3(DSHLD,reg_cl); + break; + CASE_0F_D(0xa8) /* PUSH GS */ + Push_32(SegValue(gs));break; + CASE_0F_D(0xa9) /* POP GS */ + CPU_SetSegGeneral(gs,(Bit16u)Pop_32());break; + CASE_0F_D(0xab) /* BTS 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_0F_D(0xac) /* SHRD Ed,Gd,Ib */ + RMEdGdOp3(DSHRD,Fetchb()); + break; + 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); + break; + } + CASE_0F_D(0xb2) /* LSS Ed */ + { + GetRMrd;GetEAa; + *rmrd=LoadMd(eaa);CPU_SetSegGeneral(ss,LoadMw(eaa+4)); + break; + } + CASE_0F_D(0xb7) /* MOVXZ Gd,Ew */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArw;*rmrd=*earw;} + else {GetEAa;*rmrd=LoadMw(eaa);} + break; + } + CASE_0F_D(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_0F_D(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_0F_D(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_0F_D(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 = 31; // Operandsize-1 + while ((value & 0x80000000)==0) { result--; value<<=1; } + SETFLAGBIT(ZF,false); + *rmrd = result; + } + flags.type=t_UNKNOWN; + break; + } + CASE_0F_D(0xbe) /* MOVSX Gd,Eb */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArb;*rmrd=*(Bit8s *)earb;} + else {GetEAa;*rmrd=LoadMbs(eaa);} + break; + } + CASE_0F_D(0xbf) /* MOVSX Gd,Ew */ + { + GetRMrd; + if (rm >= 0xc0 ) {GetEArw;*rmrd=*(Bit16s *)earw;} + else {GetEAa;*rmrd=LoadMws(eaa);} + break; + } diff --git a/src/cpu/core_normal/prefix_none.h b/src/cpu/core_normal/prefix_none.h new file mode 100644 index 0000000..040e178 --- /dev/null +++ b/src/cpu/core_normal/prefix_none.h @@ -0,0 +1,1171 @@ +/* + * 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. + */ + + CASE_B(0x00) /* ADD Eb,Gb */ + RMEbGb(ADDB);break; + CASE_W(0x01) /* ADD Ew,Gw */ + RMEwGw(ADDW);break; + CASE_B(0x02) /* ADD Gb,Eb */ + RMGbEb(ADDB);break; + CASE_W(0x03) /* ADD Gw,Ew */ + RMGwEw(ADDW);break; + CASE_B(0x04) /* ADD AL,Ib */ + ALIb(ADDB);break; + CASE_W(0x05) /* ADD AX,Iw */ + 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_B(0x08) /* OR Eb,Gb */ + RMEbGb(ORB);break; + CASE_W(0x09) /* OR Ew,Gw */ + RMEwGw(ORW);break; + CASE_B(0x0a) /* OR Gb,Eb */ + RMGbEb(ORB);break; + CASE_W(0x0b) /* OR Gw,Ew */ + RMGwEw(ORW);break; + CASE_B(0x0c) /* OR AL,Ib */ + ALIb(ORB);break; + CASE_W(0x0d) /* OR AX,Iw */ + AXIw(ORW);break; + CASE_W(0x0e) /* PUSH CS */ + Push_16(SegValue(cs));break; + CASE_B(0x0f) /* 2 byte opcodes*/ + core.opcode_index|=OPCODE_0F; + goto restart_opcode; + break; + CASE_B(0x10) /* ADC Eb,Gb */ + RMEbGb(ADCB);break; + CASE_W(0x11) /* ADC Ew,Gw */ + RMEwGw(ADCW);break; + CASE_B(0x12) /* ADC Gb,Eb */ + RMGbEb(ADCB);break; + CASE_W(0x13) /* ADC Gw,Ew */ + RMGwEw(ADCW);break; + CASE_B(0x14) /* ADC AL,Ib */ + ALIb(ADCB);break; + CASE_W(0x15) /* ADC AX,Iw */ + AXIw(ADCW);break; + CASE_W(0x16) /* PUSH SS */ + Push_16(SegValue(ss));break; + CASE_W(0x17) /* POP SS */ + CPU_SetSegGeneral(ss,Pop_16());break; + CASE_B(0x18) /* SBB Eb,Gb */ + RMEbGb(SBBB);break; + CASE_W(0x19) /* SBB Ew,Gw */ + RMEwGw(SBBW);break; + CASE_B(0x1a) /* SBB Gb,Eb */ + RMGbEb(SBBB);break; + CASE_W(0x1b) /* SBB Gw,Ew */ + RMGwEw(SBBW);break; + CASE_B(0x1c) /* SBB AL,Ib */ + ALIb(SBBB);break; + CASE_W(0x1d) /* SBB AX,Iw */ + AXIw(SBBW);break; + CASE_W(0x1e) /* PUSH DS */ + Push_16(SegValue(ds));break; + CASE_W(0x1f) /* POP DS */ + CPU_SetSegGeneral(ds,Pop_16());break; + CASE_B(0x20) /* AND Eb,Gb */ + RMEbGb(ANDB);break; + CASE_W(0x21) /* AND Ew,Gw */ + RMEwGw(ANDW);break; + CASE_B(0x22) /* AND Gb,Eb */ + RMGbEb(ANDB);break; + CASE_W(0x23) /* AND Gw,Ew */ + RMGwEw(ANDW);break; + CASE_B(0x24) /* AND AL,Ib */ + ALIb(ANDB);break; + CASE_W(0x25) /* AND AX,Iw */ + AXIw(ANDW);break; + CASE_B(0x26) /* SEG ES: */ + DO_PREFIX_SEG(es);break; + CASE_B(0x27) /* DAA */ + DAA();break; + CASE_B(0x28) /* SUB Eb,Gb */ + RMEbGb(SUBB);break; + CASE_W(0x29) /* SUB Ew,Gw */ + RMEwGw(SUBW);break; + CASE_B(0x2a) /* SUB Gb,Eb */ + RMGbEb(SUBB);break; + CASE_W(0x2b) /* SUB Gw,Ew */ + RMGwEw(SUBW);break; + CASE_B(0x2c) /* SUB AL,Ib */ + ALIb(SUBB);break; + CASE_W(0x2d) /* SUB AX,Iw */ + AXIw(SUBW);break; + CASE_B(0x2e) /* SEG CS: */ + DO_PREFIX_SEG(cs);break; + CASE_B(0x2f) /* DAS */ + DAS();break; + CASE_B(0x30) /* XOR Eb,Gb */ + RMEbGb(XORB);break; + CASE_W(0x31) /* XOR Ew,Gw */ + RMEwGw(XORW);break; + CASE_B(0x32) /* XOR Gb,Eb */ + RMGbEb(XORB);break; + CASE_W(0x33) /* XOR Gw,Ew */ + RMGwEw(XORW);break; + CASE_B(0x34) /* XOR AL,Ib */ + ALIb(XORB);break; + CASE_W(0x35) /* XOR AX,Iw */ + AXIw(XORW);break; + CASE_B(0x36) /* SEG SS: */ + DO_PREFIX_SEG(ss);break; + CASE_B(0x37) /* AAA */ + AAA();break; + CASE_B(0x38) /* CMP Eb,Gb */ + RMEbGb(CMPB);break; + CASE_W(0x39) /* CMP Ew,Gw */ + RMEwGw(CMPW);break; + CASE_B(0x3a) /* CMP Gb,Eb */ + RMGbEb(CMPB);break; + CASE_W(0x3b) /* CMP Gw,Ew */ + RMGwEw(CMPW);break; + CASE_B(0x3c) /* CMP AL,Ib */ + ALIb(CMPB);break; + CASE_W(0x3d) /* CMP AX,Iw */ + AXIw(CMPW);break; + CASE_B(0x3e) /* SEG DS: */ + DO_PREFIX_SEG(ds);break; + CASE_B(0x3f) /* AAS */ + AAS();break; + CASE_W(0x40) /* INC AX */ + INCW(reg_ax,LoadRw,SaveRw);break; + CASE_W(0x41) /* INC CX */ + INCW(reg_cx,LoadRw,SaveRw);break; + CASE_W(0x42) /* INC DX */ + INCW(reg_dx,LoadRw,SaveRw);break; + CASE_W(0x43) /* INC BX */ + INCW(reg_bx,LoadRw,SaveRw);break; + CASE_W(0x44) /* INC SP */ + INCW(reg_sp,LoadRw,SaveRw);break; + CASE_W(0x45) /* INC BP */ + INCW(reg_bp,LoadRw,SaveRw);break; + CASE_W(0x46) /* INC SI */ + INCW(reg_si,LoadRw,SaveRw);break; + CASE_W(0x47) /* INC DI */ + INCW(reg_di,LoadRw,SaveRw);break; + CASE_W(0x48) /* DEC AX */ + DECW(reg_ax,LoadRw,SaveRw);break; + CASE_W(0x49) /* DEC CX */ + DECW(reg_cx,LoadRw,SaveRw);break; + CASE_W(0x4a) /* DEC DX */ + DECW(reg_dx,LoadRw,SaveRw);break; + CASE_W(0x4b) /* DEC BX */ + DECW(reg_bx,LoadRw,SaveRw);break; + CASE_W(0x4c) /* DEC SP */ + DECW(reg_sp,LoadRw,SaveRw);break; + CASE_W(0x4d) /* DEC BP */ + DECW(reg_bp,LoadRw,SaveRw);break; + CASE_W(0x4e) /* DEC SI */ + DECW(reg_si,LoadRw,SaveRw);break; + CASE_W(0x4f) /* DEC DI */ + DECW(reg_di,LoadRw,SaveRw);break; + CASE_W(0x50) /* PUSH AX */ + Push_16(reg_ax);break; + CASE_W(0x51) /* PUSH CX */ + Push_16(reg_cx);break; + CASE_W(0x52) /* PUSH DX */ + Push_16(reg_dx);break; + 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; + CASE_W(0x56) /* PUSH SI */ + Push_16(reg_si);break; + CASE_W(0x57) /* PUSH DI */ + Push_16(reg_di);break; + CASE_W(0x58) /* POP AX */ + reg_ax=Pop_16();break; + CASE_W(0x59) /* POP CX */ + reg_cx=Pop_16();break; + CASE_W(0x5a) /* POP DX */ + reg_dx=Pop_16();break; + CASE_W(0x5b) /* POP BX */ + reg_bx=Pop_16();break; + CASE_W(0x5c) /* POP SP */ + reg_sp=Pop_16();break; + CASE_W(0x5d) /* POP BP */ + reg_bp=Pop_16();break; + CASE_W(0x5e) /* POP SI */ + reg_si=Pop_16();break; + CASE_W(0x5f) /* POP DI */ + reg_di=Pop_16();break; + CASE_W(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_W(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_W(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_W(0x63) /* ARPL Ew,Rw */ + { + FillFlags(); + GetRMrw; + if (rm >= 0xc0 ) { + GetEArw;Bitu new_sel=*earw; + CPU_ARPL(new_sel,*rmrw); + *earw=(Bit16u)new_sel; + } else { + GetEAa;Bitu new_sel=LoadMw(eaa); + CPU_ARPL(new_sel,*rmrw); + SaveMw(eaa,(Bit16u)new_sel); + } + } + break; + CASE_B(0x64) /* SEG FS: */ + DO_PREFIX_SEG(fs);break; + CASE_B(0x65) /* SEG GS: */ + DO_PREFIX_SEG(gs);break; + CASE_B(0x66) /* Operand Size Prefix */ + core.opcode_index^=OPCODE_SIZE; + goto restart_opcode; + CASE_B(0x67) /* Address Size Prefix */ + DO_PREFIX_ADDR(); + CASE_W(0x68) /* PUSH Iw */ + Push_16(Fetchw());break; + CASE_W(0x69) /* IMUL Gw,Ew,Iw */ + RMGwEwOp3(DIMULW,Fetchws()); + break; + CASE_W(0x6a) /* PUSH Ib */ + Push_16(Fetchbs()); + break; + CASE_W(0x6b) /* IMUL Gw,Ew,Ib */ + RMGwEwOp3(DIMULW,Fetchbs()); + break; + CASE_B(0x6c) /* INSB */ + DoString(R_INSB);break; + CASE_W(0x6d) /* INSW */ + DoString(R_INSW);break; + CASE_B(0x6e) /* OUTSB */ + 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_B(0x80) /* Grpl Eb,Ib */ + CASE_B(0x82) /* Grpl Eb,Ib Mirror instruction*/ + { + GetRM;Bitu which=(rm>>3)&7; + if (rm>= 0xc0) { + GetEArb;Bit8u ib=Fetchb(); + switch (which) { + case 0x00:ADDB(*earb,ib,LoadRb,SaveRb);break; + case 0x01: ORB(*earb,ib,LoadRb,SaveRb);break; + case 0x02:ADCB(*earb,ib,LoadRb,SaveRb);break; + case 0x03:SBBB(*earb,ib,LoadRb,SaveRb);break; + case 0x04:ANDB(*earb,ib,LoadRb,SaveRb);break; + case 0x05:SUBB(*earb,ib,LoadRb,SaveRb);break; + case 0x06:XORB(*earb,ib,LoadRb,SaveRb);break; + case 0x07:CMPB(*earb,ib,LoadRb,SaveRb);break; + } + } else { + GetEAa;Bit8u ib=Fetchb(); + switch (which) { + case 0x00:ADDB(eaa,ib,LoadMb,SaveMb);break; + case 0x01: ORB(eaa,ib,LoadMb,SaveMb);break; + case 0x02:ADCB(eaa,ib,LoadMb,SaveMb);break; + case 0x03:SBBB(eaa,ib,LoadMb,SaveMb);break; + case 0x04:ANDB(eaa,ib,LoadMb,SaveMb);break; + case 0x05:SUBB(eaa,ib,LoadMb,SaveMb);break; + case 0x06:XORB(eaa,ib,LoadMb,SaveMb);break; + case 0x07:CMPB(eaa,ib,LoadMb,SaveMb);break; + } + } + break; + } + CASE_W(0x81) /* Grpl Ew,Iw */ + { + GetRM;Bitu which=(rm>>3)&7; + if (rm>= 0xc0) { + GetEArw;Bit16u iw=Fetchw(); + switch (which) { + case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; + case 0x01: ORW(*earw,iw,LoadRw,SaveRw);break; + case 0x02:ADCW(*earw,iw,LoadRw,SaveRw);break; + case 0x03:SBBW(*earw,iw,LoadRw,SaveRw);break; + case 0x04:ANDW(*earw,iw,LoadRw,SaveRw);break; + case 0x05:SUBW(*earw,iw,LoadRw,SaveRw);break; + case 0x06:XORW(*earw,iw,LoadRw,SaveRw);break; + case 0x07:CMPW(*earw,iw,LoadRw,SaveRw);break; + } + } else { + GetEAa;Bit16u iw=Fetchw(); + switch (which) { + case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; + case 0x01: ORW(eaa,iw,LoadMw,SaveMw);break; + case 0x02:ADCW(eaa,iw,LoadMw,SaveMw);break; + case 0x03:SBBW(eaa,iw,LoadMw,SaveMw);break; + case 0x04:ANDW(eaa,iw,LoadMw,SaveMw);break; + case 0x05:SUBW(eaa,iw,LoadMw,SaveMw);break; + case 0x06:XORW(eaa,iw,LoadMw,SaveMw);break; + case 0x07:CMPW(eaa,iw,LoadMw,SaveMw);break; + } + } + break; + } + CASE_W(0x83) /* Grpl Ew,Ix */ + { + GetRM;Bitu which=(rm>>3)&7; + if (rm>= 0xc0) { + GetEArw;Bit16u iw=(Bit16s)Fetchbs(); + switch (which) { + case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break; + case 0x01: ORW(*earw,iw,LoadRw,SaveRw);break; + case 0x02:ADCW(*earw,iw,LoadRw,SaveRw);break; + case 0x03:SBBW(*earw,iw,LoadRw,SaveRw);break; + case 0x04:ANDW(*earw,iw,LoadRw,SaveRw);break; + case 0x05:SUBW(*earw,iw,LoadRw,SaveRw);break; + case 0x06:XORW(*earw,iw,LoadRw,SaveRw);break; + case 0x07:CMPW(*earw,iw,LoadRw,SaveRw);break; + } + } else { + GetEAa;Bit16u iw=(Bit16s)Fetchbs(); + switch (which) { + case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break; + case 0x01: ORW(eaa,iw,LoadMw,SaveMw);break; + case 0x02:ADCW(eaa,iw,LoadMw,SaveMw);break; + case 0x03:SBBW(eaa,iw,LoadMw,SaveMw);break; + case 0x04:ANDW(eaa,iw,LoadMw,SaveMw);break; + case 0x05:SUBW(eaa,iw,LoadMw,SaveMw);break; + case 0x06:XORW(eaa,iw,LoadMw,SaveMw);break; + case 0x07:CMPW(eaa,iw,LoadMw,SaveMw);break; + } + } + break; + } + CASE_B(0x84) /* TEST Eb,Gb */ + RMEbGb(TESTB); + break; + CASE_W(0x85) /* TEST Ew,Gw */ + RMEwGw(TESTW); + break; + CASE_B(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_W(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_B(0x88) /* MOV Eb,Gb */ + { + GetRMrb; + if (rm >= 0xc0 ) {GetEArb;*earb=*rmrb;} + else {GetEAa;SaveMb(eaa,*rmrb);} + break; + } + CASE_W(0x89) /* MOV Ew,Gw */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;*earw=*rmrw;} + else {GetEAa;SaveMw(eaa,*rmrw);} + break; + } + CASE_B(0x8a) /* MOV Gb,Eb */ + { + GetRMrb; + if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;} + else {GetEAa;*rmrb=LoadMb(eaa);} + break; + } + CASE_W(0x8b) /* MOV Gw,Ew */ + { + GetRMrw; + if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;} + else {GetEAa;*rmrw=LoadMw(eaa);} + break; + } + CASE_W(0x8c) /* Mov Ew,Sw */ + { + GetRM;Bit16u val;Bitu which=(rm>>3)&7; + switch (which) { + case 0x00: /* MOV Ew,ES */ + val=SegValue(es);break; + case 0x01: /* MOV Ew,CS */ + val=SegValue(cs);break; + case 0x02: /* MOV Ew,SS */ + val=SegValue(ss);break; + case 0x03: /* MOV Ew,DS */ + val=SegValue(ds);break; + case 0x04: /* MOV Ew,FS */ + val=SegValue(fs);break; + case 0x05: /* 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_W(0x8d) /* LEA Gw */ + { + //Little hack to always use segprefixed version + core.seg_prefix_base=0; + GetRMrw; + if (TEST_PREFIX_ADDR) { + *rmrw=(Bit16u)(*GetEA_SEG_ADDR[rm])(); + } else { + *rmrw=(Bit16u)(*GetEA_SEG[rm])(); + } + break; + } + CASE_B(0x8e) /* MOV Sw,Ew */ + { + GetRM;Bit16u val;Bitu which=(rm>>3)&7; + if (rm >= 0xc0 ) {GetEArw;val=*earw;} + else {GetEAa;val=LoadMw(eaa);} + switch (which) { + case 0x00: /* MOV ES,Ew */ + CPU_SetSegGeneral(es,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"); + } + break; + } + CASE_W(0x8f) /* POP Ew */ + { + GetRM; + if (rm >= 0xc0 ) {GetEArw;*earw=Pop_16();} + else {GetEAa;SaveMw(eaa,Pop_16());} + break; + } + CASE_B(0x90) /* NOP */ + break; + CASE_W(0x91) /* XCHG CX,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_cx;reg_cx=temp; } + break; + CASE_W(0x92) /* XCHG DX,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_dx;reg_dx=temp; } + break; + CASE_W(0x93) /* XCHG BX,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_bx;reg_bx=temp; } + break; + CASE_W(0x94) /* XCHG SP,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_sp;reg_sp=temp; } + break; + CASE_W(0x95) /* XCHG BP,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_bp;reg_bp=temp; } + break; + CASE_W(0x96) /* XCHG SI,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_si;reg_si=temp; } + break; + CASE_W(0x97) /* XCHG DI,AX */ + { Bit16u temp=reg_ax;reg_ax=reg_di;reg_di=temp; } + break; + CASE_W(0x98) /* CBW */ + reg_ax=(Bit8s)reg_al;break; + CASE_W(0x99) /* CWD */ + if (reg_ax & 0x8000) reg_dx=0xffff;else reg_dx=0; + break; + 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; + } + CASE_B(0x9b) /* WAIT */ + break; /* No waiting here */ + CASE_W(0x9c) /* PUSHF */ + FillFlags(); + Push_16(flags.word); + break; + CASE_W(0x9d) /* POPF */ + SETFLAGSw(Pop_16()); +#if CPU_TRAP_CHECK + if (GETFLAG(TF)) { + cpudecoder=CPU_Core_Normal_Decode_Trap; + goto decode_end; + } +#endif +#ifdef CPU_PIC_CHECK + if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; +#endif + break; + CASE_B(0x9e) /* SAHF */ + SETFLAGSb(reg_ah); + break; + CASE_B(0x9f) /* LAHF */ + FillFlags(); + reg_ah=flags.word&0xff; + break; + CASE_B(0xa0) /* MOV AL,Ob */ + { + GetEADirect; + reg_al=LoadMb(eaa); + } + break; + CASE_W(0xa1) /* MOV AX,Ow */ + { + GetEADirect; + reg_ax=LoadMw(eaa); + } + break; + CASE_B(0xa2) /* MOV Ob,AL */ + { + GetEADirect; + SaveMb(eaa,reg_al); + } + break; + CASE_W(0xa3) /* MOV Ow,AX */ + { + GetEADirect; + SaveMw(eaa,reg_ax); + } + break; + CASE_B(0xa4) /* MOVSB */ + DoString(R_MOVSB);break; + CASE_W(0xa5) /* MOVSW */ + DoString(R_MOVSW);break; + CASE_B(0xa6) /* CMPSB */ + DoString(R_CMPSB);break; + CASE_W(0xa7) /* CMPSW */ + DoString(R_CMPSW);break; + CASE_B(0xa8) /* TEST AL,Ib */ + ALIb(TESTB);break; + CASE_W(0xa9) /* TEST AX,Iw */ + AXIw(TESTW);break; + CASE_B(0xaa) /* STOSB */ + DoString(R_STOSB);break; + CASE_W(0xab) /* STOSW */ + DoString(R_STOSW);break; + CASE_B(0xac) /* LODSB */ + DoString(R_LODSB);break; + CASE_W(0xad) /* LODSW */ + DoString(R_LODSW);break; + CASE_B(0xae) /* SCASB */ + DoString(R_SCASB);break; + CASE_W(0xaf) /* SCASW */ + DoString(R_SCASW);break; + CASE_B(0xb0) /* MOV AL,Ib */ + reg_al=Fetchb();break; + CASE_B(0xb1) /* MOV CL,Ib */ + reg_cl=Fetchb();break; + CASE_B(0xb2) /* MOV DL,Ib */ + reg_dl=Fetchb();break; + CASE_B(0xb3) /* MOV BL,Ib */ + reg_bl=Fetchb();break; + CASE_B(0xb4) /* MOV AH,Ib */ + reg_ah=Fetchb();break; + CASE_B(0xb5) /* MOV CH,Ib */ + reg_ch=Fetchb();break; + CASE_B(0xb6) /* MOV DH,Ib */ + reg_dh=Fetchb();break; + CASE_B(0xb7) /* MOV BH,Ib */ + reg_bh=Fetchb();break; + CASE_W(0xb8) /* MOV AX,Iw */ + reg_ax=Fetchw();break; + CASE_W(0xb9) /* MOV CX,Iw */ + reg_cx=Fetchw();break; + CASE_W(0xba) /* MOV DX,Iw */ + reg_dx=Fetchw();break; + CASE_W(0xbb) /* MOV BX,Iw */ + reg_bx=Fetchw();break; + CASE_W(0xbc) /* MOV SP,Iw */ + reg_sp=Fetchw();break; + CASE_W(0xbd) /* MOV BP.Iw */ + reg_bp=Fetchw();break; + CASE_W(0xbe) /* MOV SI,Iw */ + reg_si=Fetchw();break; + CASE_W(0xbf) /* MOV DI,Iw */ + reg_di=Fetchw();break; + CASE_B(0xc0) /* GRP2 Eb,Ib */ + GRP2B(Fetchb());break; + CASE_W(0xc1) /* GRP2 Ew,Ib */ + GRP2W(Fetchb());break; + CASE_W(0xc2) /* RETN Iw */ + { + Bit16u addsp=Fetchw(); + SETIP(Pop_16());reg_esp+=addsp; + break; + } + CASE_W(0xc3) /* RETN */ + SETIP(Pop_16()); + break; + CASE_W(0xc4) /* LES */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);CPU_SetSegGeneral(es,LoadMw(eaa+2)); + break; + } + CASE_W(0xc5) /* LDS */ + { + GetRMrw;GetEAa; + *rmrw=LoadMw(eaa);CPU_SetSegGeneral(ds,LoadMw(eaa+2)); + break; + } + CASE_B(0xc6) /* MOV Eb,Ib */ + { + GetRM; + if (rm >= 0xc0) {GetEArb;*earb=Fetchb();} + else {GetEAa;SaveMb(eaa,Fetchb());} + break; + } + CASE_W(0xc7) /* MOV EW,Iw */ + { + GetRM; + if (rm >= 0xc0) {GetEArw;*earw=Fetchw();} + else {GetEAa;SaveMw(eaa,Fetchw());} + break; + } + CASE_W(0xc8) /* ENTER Iw,Ib */ + { + Bitu bytes=Fetchw();Bitu level=Fetchb() & 0x1f; + Bitu frame_ptr=reg_esp-2; + if (cpu.stack.big) { + reg_esp-=2; + mem_writew(SegBase(ss)+reg_esp,reg_bp); + for (Bitu i=1;i>3)&7; + switch (which) { + 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_W(0xf7) /* GRP3 Ew(,Iw) */ + { + GetRM;Bitu which=(rm>>3)&7; + switch (which) { + 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_B(0xf8) /* CLC */ + SETFLAGBIT(CF,false); + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + CASE_B(0xf9) /* STC */ + SETFLAGBIT(CF,true); + if (flags.type!=t_CF) flags.prev_type=flags.type; + flags.type=t_CF; + break; + CASE_B(0xfa) /* CLI */ + SETFLAGBIT(IF,false); + break; + CASE_B(0xfb) /* STI */ + SETFLAGBIT(IF,true); +#ifdef CPU_PIC_CHECK + if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end; +#endif + break; + CASE_B(0xfc) /* CLD */ + SETFLAGBIT(DF,false); + break; + CASE_B(0xfd) /* STD */ + SETFLAGBIT(DF,true); + break; + CASE_B(0xfe) /* GRP4 Eb */ + { + GetRM;Bitu which=(rm>>3)&7; + switch (which) { + case 0x00: /* INC Eb */ + RMEb(INCB); + break; + case 0x01: /* DEC Eb */ + RMEb(DECB); + break; + case 0x07: /* CallBack */ + { + Bitu cb=Fetchw(); + LEAVECORE; + return cb; + } + default: + E_Exit("Illegal GRP4 Call %d",(rm>>3) & 7); + break; + } + break; + } + CASE_W(0xff) /* GRP5 Ew */ + { + GetRM;Bitu which=(rm>>3)&7; + switch (which) { + case 0x00: /* INC Ew */ + RMEw(INCW); + break; + case 0x01: /* DEC Ew */ + RMEw(DECW); + break; + case 0x02: /* CALL Ev */ + if (rm >= 0xc0 ) {GetEArw;Push_16((Bit16u)GETIP);SETIP(*earw);} + else {GetEAa;Push_16((Bit16u)GETIP);SETIP(LoadMw(eaa));} + break; + case 0x03: /* CALL Ep */ + { + GetEAa; + Bit16u newip=LoadMw(eaa); + Bit16u newcs=LoadMw(eaa+2); + SAVEIP; + if (CPU_CALL(false,newcs,newip)) { + LOADIP; + } else { + FillFlags();return CBRET_NONE; + } + } + break; + case 0x04: /* JMP Ev */ + if (rm >= 0xc0 ) {GetEArw;SETIP(*earw);} + else {GetEAa;SETIP(LoadMw(eaa));} + break; + case 0x05: /* JMP Ep */ + { + GetEAa; + Bit16u newip=LoadMw(eaa); + Bit16u newcs=LoadMw(eaa+2); + SAVEIP; + if (CPU_JMP(false,newcs,newip)) { + LOADIP; + } else { + FillFlags();return CBRET_NONE; + } } + break; + case 0x06: /* PUSH Ev */ + if (rm >= 0xc0 ) {GetEArw;Push_16(*earw);} + else {GetEAa;Push_16(LoadMw(eaa));} + break; + default: + E_Exit("CPU:GRP5:Illegal Call %2X",which); + break; + } + break; + } + + + + diff --git a/src/cpu/core_normal/string.h b/src/cpu/core_normal/string.h new file mode 100644 index 0000000..4fce863 --- /dev/null +++ b/src/cpu/core_normal/string.h @@ -0,0 +1,243 @@ +enum STRING_OP { + R_OUTSB,R_OUTSW,R_OUTSD, + R_INSB,R_INSW,R_INSD, + R_MOVSB,R_MOVSW,R_MOVSD, + R_LODSB,R_LODSW,R_LODSD, + R_STOSB,R_STOSW,R_STOSD, + R_SCASB,R_SCASW,R_SCASD, + R_CMPSB,R_CMPSW,R_CMPSD, +}; + +#define LoadD(_BLAH) _BLAH + +static void DoString(STRING_OP type) { + PhysPt si_base,di_base; + Bitu si_index,di_index; + Bitu add_mask; + Bitu count,count_left; + Bits add_index; + + if (TEST_PREFIX_SEG) si_base=core.seg_prefix_base; + else si_base=SegBase(ds); + di_base=SegBase(es); + if (TEST_PREFIX_ADDR) { + add_mask=0xFFFFFFFF; + si_index=reg_esi; + di_index=reg_edi; + count=reg_ecx; + } else { + add_mask=0xFFFF; + si_index=reg_si; + di_index=reg_di; + count=reg_cx; + } + if (!(TEST_PREFIX_REP)) { + count=1; + } else { + CPU_Cycles++; + /* Calculate amount of ops to do before cycles run out */ + if ((count>(Bitu)CPU_Cycles) && (type0;count--) { + IO_Write(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)); + 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)); + 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)); + 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)); + di_index=(di_index+add_index) & add_mask; + } + break; + case R_STOSB: + for (;count>0;count--) { + SaveMb(di_base+di_index,reg_al); + di_index=(di_index+add_index) & add_mask; + } + break; + case R_STOSW: + add_index<<=1; + for (;count>0;count--) { + SaveMw(di_base+di_index,reg_ax); + di_index=(di_index+add_index) & add_mask; + } + break; + case R_STOSD: + add_index<<=2; + for (;count>0;count--) { + SaveMd(di_base+di_index,reg_eax); + di_index=(di_index+add_index) & add_mask; + } + break; + case R_MOVSB: + for (;count>0;count--) { + SaveMb(di_base+di_index,LoadMb(si_base+si_index)); + di_index=(di_index+add_index) & add_mask; + si_index=(si_index+add_index) & add_mask; + } + break; + case R_MOVSW: + add_index<<=1; + for (;count>0;count--) { + SaveMw(di_base+di_index,LoadMw(si_base+si_index)); + di_index=(di_index+add_index) & add_mask; + si_index=(si_index+add_index) & add_mask; + } + break; + case R_MOVSD: + add_index<<=2; + for (;count>0;count--) { + SaveMd(di_base+di_index,LoadMd(si_base+si_index)); + di_index=(di_index+add_index) & add_mask; + si_index=(si_index+add_index) & add_mask; + } + break; + case R_LODSB: + for (;count>0;count--) { + reg_al=LoadMb(si_base+si_index); + si_index=(si_index+add_index) & add_mask; + } + break; + case R_LODSW: + add_index<<=1; + for (;count>0;count--) { + reg_ax=LoadMw(si_base+si_index); + si_index=(si_index+add_index) & add_mask; + } + break; + case R_LODSD: + add_index<<=2; + for (;count>0;count--) { + reg_eax=LoadMd(si_base+si_index); + si_index=(si_index+add_index) & add_mask; + } + break; + case R_SCASB: + { + Bit8u val2; + for (;count>0;) { + count--;CPU_Cycles--; + val2=LoadMb(di_base+di_index); + di_index=(di_index+add_index) & add_mask; + if ((reg_al==val2)!=core.rep_zero) break; + } + CMPB(reg_al,val2,LoadD,0); + } + break; + case R_SCASW: + { + add_index<<=1;Bit16u val2; + for (;count>0;) { + count--;CPU_Cycles--; + val2=LoadMw(di_base+di_index); + di_index=(di_index+add_index) & add_mask; + if ((reg_ax==val2)!=core.rep_zero) break; + } + CMPW(reg_ax,val2,LoadD,0); + } + break; + case R_SCASD: + { + add_index<<=2;Bit32u val2; + for (;count>0;) { + count--;CPU_Cycles--; + val2=LoadMd(di_base+di_index); + di_index=(di_index+add_index) & add_mask; + if ((reg_eax==val2)!=core.rep_zero) break; + } + CMPD(reg_eax,val2,LoadD,0); + } + break; + case R_CMPSB: + { + Bit8u val1,val2; + for (;count>0;) { + count--;CPU_Cycles--; + val1=LoadMb(si_base+si_index); + val2=LoadMb(di_base+di_index); + si_index=(si_index+add_index) & add_mask; + di_index=(di_index+add_index) & add_mask; + if ((val1==val2)!=core.rep_zero) break; + } + CMPB(val1,val2,LoadD,0); + } + break; + case R_CMPSW: + { + add_index<<=1;Bit16u val1,val2; + for (;count>0;) { + count--;CPU_Cycles--; + val1=LoadMw(si_base+si_index); + val2=LoadMw(di_base+di_index); + si_index=(si_index+add_index) & add_mask; + di_index=(di_index+add_index) & add_mask; + if ((val1==val2)!=core.rep_zero) break; + } + CMPW(val1,val2,LoadD,0); + } + break; + case R_CMPSD: + { + add_index<<=2;Bit32u val1,val2; + for (;count>0;) { + count--;CPU_Cycles--; + val1=LoadMd(si_base+si_index); + val2=LoadMd(di_base+di_index); + si_index=(si_index+add_index) & add_mask; + di_index=(di_index+add_index) & add_mask; + if ((val1==val2)!=core.rep_zero) break; + } + CMPD(val1,val2,LoadD,0); + } + break; + default: + LOG(LOG_CPU,LOG_ERROR)("Unhandled string op %d",type); + } + /* Clean up after certain amount of instructions */ + reg_esi&=(~add_mask); + reg_esi|=(si_index & add_mask); + reg_edi&=(~add_mask); + reg_edi|=(di_index & add_mask); + if (TEST_PREFIX_REP) { + count+=count_left; + reg_ecx&=(~add_mask); + reg_ecx|=(count & add_mask); + } +} diff --git a/src/cpu/core_normal/support.h b/src/cpu/core_normal/support.h new file mode 100644 index 0000000..d0e4d2a --- /dev/null +++ b/src/cpu/core_normal/support.h @@ -0,0 +1,138 @@ +/* + * 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 SETIP(_a_) (core.ip_lookup=SegBase(cs)+_a_) +#define GETIP (Bit32u)(core.ip_lookup-SegBase(cs)) +#define SAVEIP {reg_eip=GETIP;} +#define LOADIP {core.ip_lookup=(SegBase(cs)+reg_eip);} + +#define LEAVECORE \ + SAVEIP; \ + FillFlags(); + +static INLINE void ADDIPw(Bits add) { + SAVEIP; + reg_eip=(Bit16u)(reg_eip+add); + LOADIP; +} + +static INLINE void ADDIPd(Bits add) { + SAVEIP; + reg_eip=(reg_eip+add); + LOADIP; +} + + +static INLINE void ADDIPFAST(Bits blah) { + core.ip_lookup+=blah; +} + +#define EXCEPTION(blah) \ + { \ + Bit8u new_num=blah; \ + core.ip_lookup=core.op_start; \ + LEAVECORE; \ + if (Interrupt(new_num)) { \ + goto decode_start; \ + } else return CBRET_NONE; \ + } + +static INLINE Bit8u Fetchb() { + Bit8u temp=LoadMb(core.ip_lookup); + core.ip_lookup+=1; + return temp; +} + +static INLINE Bit16u Fetchw() { + Bit16u temp=LoadMw(core.ip_lookup); + core.ip_lookup+=2; + return temp; +} +static INLINE Bit32u Fetchd() { + Bit32u temp=LoadMd(core.ip_lookup); + core.ip_lookup+=4; + return temp; +} + +static INLINE Bit8s Fetchbs() { + return Fetchb(); +} +static INLINE Bit16s Fetchws() { + return Fetchw(); +} + +static INLINE Bit32s Fetchds() { + return Fetchd(); +} + +static INLINE void Push_16(Bit16u blah) { + reg_esp-=2; + SaveMw(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); +}; + +static INLINE void Push_32(Bit32u blah) { + reg_esp-=4; + SaveMd(SegBase(ss)+(reg_esp & cpu.stack.mask),blah); +}; + +static INLINE Bit16u Pop_16() { + Bit16u temp=LoadMw(SegBase(ss)+(reg_esp & cpu.stack.mask)); + reg_esp+=2; + return temp; +}; + +static INLINE Bit32u Pop_32() { + Bit32u temp=LoadMd(SegBase(ss)+(reg_esp & cpu.stack.mask)); + reg_esp+=4; + return temp; +}; + +#define JumpSIb(blah) \ + if (blah) { \ + ADDIPFAST(Fetchbs()); \ + } else { \ + ADDIPFAST(1); \ + } + +#define JumpSIw(blah) \ + if (blah) { \ + ADDIPw(Fetchws()); \ + } else { \ + ADDIPFAST(2); \ + } + + +#define JumpSId(blah) \ + if (blah) { \ + ADDIPd(Fetchds()); \ + } else { \ + ADDIPFAST(4); \ + } + +#define SETcc(cc) \ + { \ + GetRM; \ + if (rm >= 0xc0 ) {GetEArb;*earb=(cc) ? 1 : 0;} \ + else {GetEAa;SaveMb(eaa,(cc) ? 1 : 0);} \ + } + +#include "helpers.h" +#include "table_ea.h" +#include "../modrm.h" + + diff --git a/src/cpu/core_normal/table_ea.h b/src/cpu/core_normal/table_ea.h new file mode 100644 index 0000000..a93182e --- /dev/null +++ b/src/cpu/core_normal/table_ea.h @@ -0,0 +1,356 @@ +/* + * 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. + */ + +typedef PhysPt (*GetEATable[256])(void); +typedef PhysPt (*EA_LookupHandler)(void); + + +/* The MOD/RM Decoder for EA for this decoder's addressing modes */ +static PhysPt EA_16_00_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_si); } +static PhysPt EA_16_01_n(void) { return SegBase(ds)+(Bit16u)(reg_bx+(Bit16s)reg_di); } +static PhysPt EA_16_02_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_si); } +static PhysPt EA_16_03_n(void) { return SegBase(ss)+(Bit16u)(reg_bp+(Bit16s)reg_di); } +static PhysPt EA_16_04_n(void) { return SegBase(ds)+(Bit16u)(reg_si); } +static PhysPt EA_16_05_n(void) { return SegBase(ds)+(Bit16u)(reg_di); } +static PhysPt EA_16_06_n(void) { return SegBase(ds)+(Bit16u)(Fetchw());} +static PhysPt EA_16_07_n(void) { return SegBase(ds)+(Bit16u)(reg_bx); } + +static PhysPt EA_16_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_NONE={ +/* 00 */ + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, + EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n, +/* 01 */ + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, + EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n, +/* 10 */ + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, + EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n, +/* 11 These are illegal so make em 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + + +static PhysPt EA_16_00_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si); } +static PhysPt EA_16_01_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di); } +static PhysPt EA_16_02_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si); } +static PhysPt EA_16_03_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di); } +static PhysPt EA_16_04_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si); } +static PhysPt EA_16_05_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di); } +static PhysPt EA_16_06_s(void) { return core.seg_prefix_base+(Bit16u)(Fetchw()); } +static PhysPt EA_16_07_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx); } + +static PhysPt EA_16_40_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); } +static PhysPt EA_16_41_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); } +static PhysPt EA_16_42_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); } +static PhysPt EA_16_43_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); } +static PhysPt EA_16_44_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchbs()); } +static PhysPt EA_16_45_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchbs()); } +static PhysPt EA_16_46_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchbs()); } +static PhysPt EA_16_47_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchbs()); } + +static PhysPt EA_16_80_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); } +static PhysPt EA_16_81_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); } +static PhysPt EA_16_82_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); } +static PhysPt EA_16_83_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); } +static PhysPt EA_16_84_s(void) { return core.seg_prefix_base+(Bit16u)(reg_si+Fetchws()); } +static PhysPt EA_16_85_s(void) { return core.seg_prefix_base+(Bit16u)(reg_di+Fetchws()); } +static PhysPt EA_16_86_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bp+Fetchws()); } +static PhysPt EA_16_87_s(void) { return core.seg_prefix_base+(Bit16u)(reg_bx+Fetchws()); } + +static GetEATable GetEA_SEG={ +/* 00 */ + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, + EA_16_00_s,EA_16_01_s,EA_16_02_s,EA_16_03_s,EA_16_04_s,EA_16_05_s,EA_16_06_s,EA_16_07_s, +/* 01 */ + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, + EA_16_40_s,EA_16_41_s,EA_16_42_s,EA_16_43_s,EA_16_44_s,EA_16_45_s,EA_16_46_s,EA_16_47_s, +/* 10 */ + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, + EA_16_80_s,EA_16_81_s,EA_16_82_s,EA_16_83_s,EA_16_84_s,EA_16_85_s,EA_16_86_s,EA_16_87_s, +/* 11 These are illegal so make em 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static Bit32u SIBZero=0; +static Bit32u * 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_44_n(void) { return Sib(1)+Fetchbs();} +static PhysPt EA_32_45_n(void) { return SegBase(ss)+reg_ebp+Fetchbs(); } +static PhysPt EA_32_46_n(void) { return SegBase(ds)+reg_esi+Fetchbs(); } +static PhysPt EA_32_47_n(void) { return SegBase(ds)+reg_edi+Fetchbs(); } + +static PhysPt EA_32_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_84_n(void) { return Sib(2)+Fetchds();} +static PhysPt EA_32_85_n(void) { return SegBase(ss)+reg_ebp+Fetchds(); } +static PhysPt EA_32_86_n(void) { return SegBase(ds)+reg_esi+Fetchds(); } +static PhysPt EA_32_87_n(void) { return SegBase(ds)+reg_edi+Fetchds(); } + +static GetEATable GetEA_ADDR={ +/* 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.seg_prefix_base+(Bit32u)(reg_eax); } +static PhysPt EA_32_01_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx); } +static PhysPt EA_32_02_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx); } +static PhysPt EA_32_03_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx); } +static PhysPt EA_32_04_s(void) { return core.seg_prefix_base+(Bit32u)(Sib_s(0));} +static PhysPt EA_32_05_s(void) { return core.seg_prefix_base+(Bit32u)(Fetchd()); } +static PhysPt EA_32_06_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi); } +static PhysPt EA_32_07_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi); } + +static PhysPt EA_32_40_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchbs()); } +static PhysPt EA_32_41_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchbs()); } +static PhysPt EA_32_42_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchbs()); } +static PhysPt EA_32_43_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchbs()); } +static PhysPt EA_32_44_s(void) { PhysPt temp=Sib_s(1);return core.seg_prefix_base+(Bit32u)(temp+Fetchbs());} +static PhysPt EA_32_45_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchbs()); } +static PhysPt EA_32_46_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchbs()); } +static PhysPt EA_32_47_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchbs()); } + +static PhysPt EA_32_80_s(void) { return core.seg_prefix_base+(Bit32u)(reg_eax+Fetchds()); } +static PhysPt EA_32_81_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ecx+Fetchds()); } +static PhysPt EA_32_82_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edx+Fetchds()); } +static PhysPt EA_32_83_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebx+Fetchds()); } +static PhysPt EA_32_84_s(void) { PhysPt temp=Sib_s(2);return core.seg_prefix_base+(Bit32u)(temp+Fetchds());} +static PhysPt EA_32_85_s(void) { return core.seg_prefix_base+(Bit32u)(reg_ebp+Fetchds()); } +static PhysPt EA_32_86_s(void) { return core.seg_prefix_base+(Bit32u)(reg_esi+Fetchds()); } +static PhysPt EA_32_87_s(void) { return core.seg_prefix_base+(Bit32u)(reg_edi+Fetchds()); } + + +static GetEATable GetEA_SEG_ADDR={ +/* 00 */ + EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, + EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, + EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, + EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, + EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, + EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, + EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, + EA_32_00_s,EA_32_01_s,EA_32_02_s,EA_32_03_s,EA_32_04_s,EA_32_05_s,EA_32_06_s,EA_32_07_s, +/* 01 */ + EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, + EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, + EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, + EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, + EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, + EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, + EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, + EA_32_40_s,EA_32_41_s,EA_32_42_s,EA_32_43_s,EA_32_44_s,EA_32_45_s,EA_32_46_s,EA_32_47_s, +/* 10 */ + EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, + EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, + EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, + EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, + EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, + EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, + EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, + EA_32_80_s,EA_32_81_s,EA_32_82_s,EA_32_83_s,EA_32_84_s,EA_32_85_s,EA_32_86_s,EA_32_87_s, +/* 11 These are illegal so make em 0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +#define GetEADirect \ + PhysPt eaa; \ + if (TEST_PREFIX_SEG) { \ + if (TEST_PREFIX_ADDR) { \ + eaa=core.seg_prefix_base+Fetchd(); \ + } else { \ + eaa=core.seg_prefix_base+Fetchw(); \ + } \ + } else { \ + if (TEST_PREFIX_ADDR) { \ + eaa=SegBase(ds)+Fetchd(); \ + } else { \ + eaa=SegBase(ds)+Fetchw(); \ + } \ + } + + diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 854d383..31ced96 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -16,20 +16,26 @@ * 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 $ */ + +#include #include "dosbox.h" #include "cpu.h" #include "memory.h" #include "debug.h" #include "keyboard.h" #include "setup.h" +#include "paging.h" -//Regs regs; +#if 1 +#undef LOG +#define LOG(X,Y) +#endif Flag_Info flags; - CPU_Regs cpu_regs; - -Segment Segs[6]; +CPUBlock cpu; +Segments Segs; Bits CPU_Cycles=0; Bits CPU_CycleLeft=0; @@ -37,108 +43,884 @@ Bits CPU_CycleMax=1500; CPU_Decoder * cpudecoder; -static void CPU_CycleIncrease(void) { - Bitu old_cycles=CPU_CycleMax; - CPU_CycleMax=(Bitu)(CPU_CycleMax*1.2); - CPU_CycleLeft=0;CPU_Cycles=0; - if (CPU_CycleMax==old_cycles) CPU_CycleMax++; - LOG_MSG("CPU:%d cycles",CPU_CycleMax); +void CPU_Real_16_Slow_Start(bool big); +void CPU_Core_Full_Start(bool big); +void CPU_Core_Normal_Start(bool big); + +#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_Push16(Bitu value) { + reg_esp-=2; + mem_writew(SegPhys(ss) + (reg_esp & cpu.stack.mask) ,value); } -static void CPU_CycleDecrease(void) { - CPU_CycleMax=(Bitu)(CPU_CycleMax/1.2); - CPU_CycleLeft=0;CPU_Cycles=0; - if (!CPU_CycleMax) CPU_CycleMax=1; - LOG_MSG("CPU:%d cycles",CPU_CycleMax); +void CPU_Push32(Bitu value) { + reg_esp-=4; + 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; + return val; +} + +Bitu CPU_Pop32(void) { + Bitu val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); + reg_esp+=4; + return val; +} + +PhysPt SelBase(Bitu sel) { + if (cpu.cr0 & CR0_PROTECTION) { + Descriptor desc; + cpu.gdt.GetDescriptor(sel,desc); + return desc.GetBase(); + } else { + return sel<<4; + } +} + +void CPU_SetFlags(Bitu word) { + flags.word=(word|2)&~0x28; +} + +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; + } + return false; } Bit8u lastint; -void Interrupt(Bit8u num) { +bool Interrupt(Bitu num) { lastint=num; -//DEBUG THINGIE to check fucked ints - +#if C_DEBUG switch (num) { - case 0x00: - LOG(LOG_CPU,"Divide Error"); - break; - case 0x06: - break; - case 0x07: - LOG(LOG_FPU,"Co Processor Exception"); - break; - case 0x08: - case 0x09: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x15: - case 0x16: - case 0x17: - case 0x1A: - case 0x1C: - case 0x21: - case 0x2a: - case 0x2f: - case 0x33: - case 0x67: - case 0x74: - break; case 0xcd: #if C_HEAVY_DEBUG - LOG(LOG_CPU|LOG_ERROR,"Call to interrupt 0xCD this is BAD"); + LOG(LOG_CPU,LOG_ERROR)("Call to interrupt 0xCD this is BAD"); DEBUG_HeavyWriteLogInstruction(); #endif E_Exit("Call to interrupt 0xCD this is BAD"); case 0x03: -#if C_DEBUG - if (DEBUG_Breakpoint()) return; -#endif - break; - case 0x05: - LOG(LOG_CPU,"CPU:Out Of Bounds interrupt"); - break; - default: -// LOG_WARN("Call to unsupported INT %02X call %02X",num,reg_ah); - - break; + if (DEBUG_Breakpoint()) return true; }; -/* Check for 16-bit or 32-bit and then setup everything for the interrupt to start */ - Bit16u pflags; - pflags= - (get_CF() << 0) | - (get_PF() << 2) | - (get_AF() << 4) | - (get_ZF() << 6) | - (get_SF() << 7) | - (flags.tf << 8) | - (flags.intf << 9) | - (flags.df << 10) | - (get_OF() << 11) | - (flags.io << 12) | - (flags.nt <<14); - - flags.intf=false; - flags.tf=false; -/* Save everything on a 16-bit stack */ - reg_sp-=2; - mem_writew(SegPhys(ss)+reg_sp,pflags); - reg_sp-=2; - mem_writew(SegPhys(ss)+reg_sp,SegValue(cs)); - reg_sp-=2; - mem_writew(SegPhys(ss)+reg_sp,reg_ip); -/* Get the new CS:IP from vector table */ - Bit16u newip=mem_readw(num << 2); - Bit16u newcs=mem_readw((num <<2)+2); - SegSet16(cs,newcs); - reg_ip=newip; +#endif + + if (!cpu.pmode) { + /* 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(num << 2); + Segs.val[cs]=mem_readw((num << 2)+2); + Segs.phys[cs]=Segs.val[cs]<<4; + cpu.code.big=false; + return CPU_CheckCodeType(CODE_REAL); + } else { + /* Protected Mode Interrupt */ + Descriptor gate; +//TODO Check for software interrupt and check gate's dplcpu.cpl) E_Exit("Interrupt to higher privilege"); + 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: + 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); + } + default: + E_Exit("Illegal descriptor type %X for int %X",gate.Type(),num); + } + } + assert(1); + return false; } -void CPU_Real_16_Slow_Start(void); -void SetCPU16bit() -{ - CPU_Real_16_Slow_Start(); +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 */ + if (use32) { + reg_eip=CPU_Pop32(); + SegSet16(cs,CPU_Pop32()); + CPU_SetFlags(CPU_Pop32()); + } else { + reg_eip=CPU_Pop16(); + SegSet16(cs,CPU_Pop16()); + CPU_SetFlagsw(CPU_Pop16()); + } + cpu.code.big=false; + return CPU_CheckCodeType(CODE_REAL); + } else { /* Protected mode IRET */ + /* Check if this is task IRET */ + if (GETFLAG(NT)) { + if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set"); + E_Exit("Task IRET"); + + + } + Bitu selector,offset,old_flags; + if (use32) { + offset=CPU_Pop32(); + selector=CPU_Pop32() & 0xffff; + old_flags=CPU_Pop32(); + if (old_flags & FLAG_VM) E_Exit("No vm86 support"); + } else { + offset=CPU_Pop16(); + selector=CPU_Pop16(); + old_flags=(flags.word & 0xffff0000) | CPU_Pop16(); + } + Bitu rpl=selector & 3; + Descriptor desc; + cpu.gdt.GetDescriptor(selector,desc); + if (rpl=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); + } else { + /* Return to higher privilege */ + 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: + if (!(cpu.cpl==rpl)) E_Exit("IRET:Outer level:NC:RPL != 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"); + break; + default: + E_Exit("IRET from illegal descriptor type %X",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; + if (use32) { + new_esp=CPU_Pop32(); + new_ss=CPU_Pop32() & 0xffff; + } else { + new_esp=CPU_Pop16(); + new_ss=CPU_Pop16(); + } + 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); + } + return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + } + return false; +} + +bool CPU_JMP(bool use32,Bitu selector,Bitu offset) { + if (!cpu.pmode || cpu.v86) { + if (!use32) { + reg_eip=offset&0xffff; + } else { + reg_eip=offset; + } + SegSet16(cs,selector); + cpu.code.big=false; + return CPU_CheckCodeType(CODE_REAL); + } else { + Bitu rpl=selector & 3; + Descriptor desc; + cpu.gdt.GetDescriptor(selector,desc); + 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: + if (rpl>cpu.cpl) E_Exit("JMP:NC:RPL>CPL"); + if (rpl!=desc.DPL()) E_Exit("JMP:NC:RPL != DPL"); + cpu.cpl=desc.DPL(); + LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:NC to %X:%X big %d",selector,offset,desc.Big()); + goto CODE_jmp; + case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: + case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: + LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:C to %X:%X big %d",selector,offset,desc.Big()); +CODE_jmp: + /* Normal jump to another selector:offset */ + Segs.phys[cs]=desc.GetBase(); + 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); + default: + E_Exit("JMP Illegal descriptor type %X",desc.Type()); + } + } + assert(1); + return false; +} + + + +bool CPU_CALL(bool use32,Bitu selector,Bitu offset) { + if (!cpu.pmode || cpu.v86) { + if (!use32) { + CPU_Push16(SegValue(cs)); + CPU_Push16(reg_ip); + reg_eip=offset&0xffff; + } else { + CPU_Push32(SegValue(cs)); + CPU_Push32(reg_eip); + reg_eip=offset; + } + cpu.code.big=false; + SegSet16(cs,selector); + return CPU_CheckCodeType(CODE_REAL); + } else { + Descriptor call; + Bitu rpl=selector & 3; + cpu.gdt.GetDescriptor(selector,call); + /* Check for type of far call */ + switch (call.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 (rpl>cpu.cpl) E_Exit("CALL:CODE:NC:RPL>CPL"); + if (call.DPL()!=cpu.cpl) E_Exit("CALL:CODE:NC:DPL!=CPL"); + LOG(LOG_CPU,LOG_NORMAL)("CALL:CODE:NC to %X:%X",selector,offset); + goto call_code; + 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 (call.DPL()>cpu.cpl) E_Exit("CALL:CODE:C:DPL>CPL"); + LOG(LOG_CPU,LOG_NORMAL)("CALL:CODE:C to %X:%X",selector,offset); +call_code: + if (!use32) { + CPU_Push16(SegValue(cs)); + CPU_Push16(reg_ip); + reg_eip=offset&0xffff; + } else { + CPU_Push32(SegValue(cs)); + CPU_Push32(reg_eip); + reg_eip=offset; + } + Segs.phys[cs]=call.GetBase(); + cpu.code.big=call.Big()>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--; + } + // Push return address onto new stack + CPU_Push16(oldcs); + CPU_Push16(oldip); +// LOG(LOG_MISC,LOG_ERROR)("CPU: Callgate (Higher) %04X:%04X",newcs,neweip); + return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + } else { + // same privilidge level + Bitu oldcs = SegValue(cs); + Bitu oldip = reg_ip; + Bitu newcs = call.GetSelector() | 3; + Bitu neweip = call.GetOffset(); + // 3. Load CS descriptor (Set RPL of CS to CPL) + Descriptor code2; + if (!cpu.gdt.GetDescriptor(newcs,code2)) E_Exit("286 Call Gate: Invalid code segment."); + Segs.phys[cs] = code.GetBase(); + cpu.code.big = code.Big()>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; + }; + default: + E_Exit("CALL:Descriptor type %x unsupported",call.Type()); + + } + } + assert(1); +} + + +bool CPU_RET(bool use32,Bitu bytes) { + if (!cpu.pmode || cpu.v86) { + Bitu new_ip,new_cs; + if (!use32) { + new_ip=CPU_Pop16(); + new_cs=CPU_Pop16(); + } else { + new_ip=CPU_Pop32(); + new_cs=CPU_Pop32() & 0xffff; + } + reg_esp+=bytes; + SegSet16(cs,new_cs); + reg_eip=new_ip; + cpu.code.big=false; + return CPU_CheckCodeType(CODE_REAL); + } else { + Bitu offset,selector; + if (!use32) { + offset=CPU_Pop16(); + selector=CPU_Pop16(); + } else { + offset=CPU_Pop32(); + selector=CPU_Pop32() & 0xffff; + } + if (cpu.stack.big) { + reg_esp+=bytes; + } else { + reg_sp+=bytes; + } + Descriptor desc; + Bitu rpl=selector & 3; + if (rpl=cpu.cpl)) E_Exit("RET to C segment of higher privilege"); + break; + default: + E_Exit("RET from illegal descriptor type %X",desc.Type()); + } +RET_same_level: + Segs.phys[cs]=desc.GetBase(); + cpu.code.big=desc.Big()>0; + Segs.val[cs]=selector; + reg_eip=offset; + 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); + } else { + /* Return to higher level */ + Bitu newsp = CPU_Pop16(); + Bitu newss = CPU_Pop16(); + cpu.cpl = rpl; + CPU_SetSegGeneral(ss,newss); + reg_esp = newsp; + 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); + } + LOG(LOG_CPU,LOG_NORMAL)("Prot ret %X:%X",selector,offset); + return CPU_CheckCodeType(cpu.code.big ? CODE_PMODE32 : CODE_PMODE16); + } + return false; +} + + +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; +} + +void CPU_LTR(Bitu selector) { + tr=selector; + LOG(LOG_CPU,LOG_NORMAL)("TR Set to %X",selector); +} + + +void CPU_LGDT(Bitu limit,Bitu base) { + LOG(LOG_CPU,LOG_NORMAL)("GDT Set to base:%X limit:%X",base,limit); + cpu.gdt.SetLimit(limit); + cpu.gdt.SetBase(base); +} + +void CPU_LIDT(Bitu limit,Bitu base) { + LOG(LOG_CPU,LOG_NORMAL)("IDT Set to base:%X limit:%X",base,limit); + cpu.idt.SetLimit(limit); + cpu.idt.SetBase(base); +} + +void CPU_SGDT(Bitu & limit,Bitu & base) { + limit=cpu.gdt.GetLimit(); + base=cpu.gdt.GetBase(); +} + +void CPU_SIDT(Bitu & limit,Bitu & base) { + limit=cpu.idt.GetLimit(); + base=cpu.idt.GetBase(); +} + + +bool CPU_SET_CRX(Bitu cr,Bitu value) { + switch (cr) { + case 0: + { + Bitu changed=cpu.cr0 ^ value; + if (!changed) return true; + cpu.cr0=value; +//TODO Maybe always first change to core_full for a change to cr0 + if (value & CR0_PROTECTION) { + cpu.pmode=true; + LOG(LOG_CPU,LOG_NORMAL)("Protected mode"); + PAGING_Enable((value & CR0_PAGING)>0); + } else { + cpu.pmode=false; + PAGING_Enable(false); + LOG(LOG_CPU,LOG_NORMAL)("Real mode"); + } + return false; //Only changes with next CS change + } + case 3: + PAGING_SetDirBase(value); + break; + default: + LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV CR%d,%X",cr,value); + break; + } + return false; +} + +Bitu CPU_GET_CRX(Bitu cr) { + switch (cr) { + case 0: + return cpu.cr0; + case 3: + return PAGING_GetDirBase(); + default: + LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, CR%d",cr); + break; + } + return 0; +} + + +void CPU_SMSW(Bitu & word) { + word=cpu.cr0; +} + +bool CPU_LMSW(Bitu word) { + word&=0xffff; + word|=(cpu.cr0&0xffff0000); + return CPU_SET_CRX(0,word); +} + +void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) { + if ((dest_sel & 3) < (src_sel & 3)) { + dest_sel=(dest_sel & 0xfffc) + (src_sel & 3); +// dest_sel|=0xff3f0000; + SETFLAGBIT(ZF,true); + } else { + SETFLAGBIT(ZF,false); + } +} + +void CPU_LAR(Bitu selector,Bitu & ar) { + Descriptor desc;Bitu rpl=selector & 3; + ar=0; + if (!cpu.gdt.GetDescriptor(selector,desc)){ + 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: + break; + + case DESC_LDT: + case DESC_TASK_GATE: + + case DESC_286_TSS_A: case DESC_286_TSS_B: + case DESC_286_INT_GATE: case DESC_286_TRAP_GATE: + case DESC_286_CALL_GATE: + + case DESC_386_TSS_A: case DESC_386_TSS_B: + case DESC_386_INT_GATE: case DESC_386_TRAP_GATE: + case DESC_386_CALL_GATE: + + + case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: + case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: + case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: + case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: + 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 (desc.DPL()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; + return 0; +} + +void CPU_HLT(void) { + CPU_Cycles=0; + cpu.code.type=CODE_INIT; + cpudecoder=&HLT_Decode; +} + + +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); + CPU_CycleLeft=0;CPU_Cycles=0; + if (CPU_CycleMax==old_cycles) CPU_CycleMax++; + LOG_MSG("CPU:%d cycles",CPU_CycleMax); + GFX_SetTitle(CPU_CycleMax,-1); +} + +static void CPU_CycleDecrease(void) { + CPU_CycleMax=(Bits)(CPU_CycleMax/1.2); + CPU_CycleLeft=0;CPU_Cycles=0; + if (!CPU_CycleMax) CPU_CycleMax=1; + LOG_MSG("CPU:%d cycles",CPU_CycleMax); + GFX_SetTitle(CPU_CycleMax,-1); } @@ -161,18 +943,17 @@ void CPU_Init(Section* sec) { SegSet16(ss,0); reg_eip=0; - flags.type=t_UNKNOWN; - flags.af=0; - flags.cf=0; - flags.cf=0; - flags.sf=0; - flags.zf=0; - flags.intf=true; - flags.nt=0; - flags.io=0; + CPU_SetFlags(FLAG_IF); //Enable interrupts + cpu.cr0=0xffffffff; + CPU_SET_CRX(0,0); //Initialize + cpu.v86=false; + 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 - SetCPU16bit(); - KEYBOARD_AddEvent(KBD_f11,KBD_MOD_CTRL,CPU_CycleDecrease); KEYBOARD_AddEvent(KBD_f12,KBD_MOD_CTRL,CPU_CycleIncrease); @@ -180,7 +961,6 @@ void CPU_Init(Section* sec) { CPU_CycleMax=section->Get_int("cycles");; if (!CPU_CycleMax) CPU_CycleMax=1500; CPU_CycleLeft=0; - - MSG_Add("CPU_CONFIGFILE_HELP","The amount of cycles to execute each loop. Lowering this setting will slowdown dosbox\n"); + GFX_SetTitle(CPU_CycleMax,-1); } diff --git a/src/cpu/flags.cpp b/src/cpu/flags.cpp index 33c3224..4f3e07c 100644 --- a/src/cpu/flags.cpp +++ b/src/cpu/flags.cpp @@ -23,13 +23,14 @@ #include "dosbox.h" #include "cpu.h" +#include "lazyflags.h" #include "pic.h" /* CF Carry Flag -- Set on high-order bit carry or borrow; cleared otherwise. */ -bool get_CF(void) { +Bitu get_CF(void) { switch (flags.type) { case t_UNKNOWN: @@ -44,7 +45,7 @@ bool get_CF(void) { case t_RCLb: case t_RCLw: case t_RCLd: - return flags.cf; + return GETFLAG(CF); break; case t_ADDb: return (flags.result.b0); + break; + case t_ADDw: + SET_FLAG(FLAG_CF,(flags.result.w0); + break; + case t_ADDd: + SET_FLAG(FLAG_CF,(flags.result.d0); + break; + + + case t_ADCb: + SET_FLAG(FLAG_CF,(flags.result.b < flags.var1.b) || (flags.oldcf && (flags.result.b == flags.var1.b))); + SET_FLAG(FLAG_AF,(((flags.var1.b ^ flags.var2.b) ^ flags.result.b) & 0x10)>0); + 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); + 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); + 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); + 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); + 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); + break; + + + case t_SUBb: + case t_CMPb: + SET_FLAG(FLAG_CF,(flags.var1.b0); + break; + case t_SUBw: + case t_CMPw: + SET_FLAG(FLAG_CF,(flags.var1.w0); + break; + case t_SUBd: + case t_CMPd: + SET_FLAG(FLAG_CF,(flags.var1.d0); + break; + + + case t_ORb: + SET_FLAG(FLAG_CF,false); + break; + case t_ORw: + SET_FLAG(FLAG_CF,false); + break; + case t_ORd: + SET_FLAG(FLAG_CF,false); + break; + + + case t_TESTb: + case t_ANDb: + SET_FLAG(FLAG_CF,false); + break; + case t_TESTw: + case t_ANDw: + SET_FLAG(FLAG_CF,false); + break; + case t_TESTd: + case t_ANDd: + SET_FLAG(FLAG_CF,false); + break; + + + case t_XORb: + SET_FLAG(FLAG_CF,false); + break; + case t_XORw: + SET_FLAG(FLAG_CF,false); + break; + case t_XORd: + SET_FLAG(FLAG_CF,false); + break; + + + case t_SHLb: + if (flags.var2.b>8) SET_FLAG(FLAG_CF,false); + else SET_FLAG(FLAG_CF,(flags.var1.b >> (8-flags.var2.b)) & 1); + 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); + break; + case t_SHLd: + SET_FLAG(FLAG_CF,(flags.var1.d >> (32 - flags.var2.b)) & 1); + 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); + break; + case t_DSHLd: + SET_FLAG(FLAG_CF,(flags.var1.d >> (32 - flags.var2.b)) & 1); + break; + + + case t_SHRb: + SET_FLAG(FLAG_CF,(flags.var1.b >> (flags.var2.b - 1)) & 1); + break; + case t_SHRw: + SET_FLAG(FLAG_CF,(flags.var1.w >> (flags.var2.b - 1)) & 1); + break; + case t_SHRd: + SET_FLAG(FLAG_CF,(flags.var1.d >> (flags.var2.b - 1)) & 1); + 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); + break; + case t_DSHRd: + SET_FLAG(FLAG_CF,(flags.var1.d >> (flags.var2.b - 1)) & 1); + break; + + + case t_SARb: + SET_FLAG(FLAG_CF,(((Bit8s) flags.var1.b) >> (flags.var2.b - 1)) & 1); + break; + case t_SARw: + SET_FLAG(FLAG_CF,(((Bit16s) flags.var1.w) >> (flags.var2.b - 1)) & 1); + break; + case t_SARd: + SET_FLAG(FLAG_CF,(((Bit32s) flags.var1.d) >> (flags.var2.b - 1)) & 1); + break; + + + case t_ROLb: + SET_FLAG(FLAG_CF,flags.result.b & 1); + break; + case t_ROLw: + SET_FLAG(FLAG_CF,flags.result.w & 1); + break; + case t_ROLd: + SET_FLAG(FLAG_CF,flags.result.d & 1); + break; + + + case t_RORb: + SET_FLAG(FLAG_CF,(flags.result.b & 0x80)>0); + break; + case t_RORw: + SET_FLAG(FLAG_CF,(flags.result.w & 0x8000)>0); + break; + case t_RORd: + SET_FLAG(FLAG_CF,(flags.result.d & 0x80000000)>0); + break; + + + case t_RCRb: + SET_FLAG(FLAG_CF,(flags.var1.b >> (flags.var2.b - 1)) & 1); + break; + case t_RCRw: + SET_FLAG(FLAG_CF,(flags.var1.w >> (flags.var2.b - 1)) & 1); + break; + case t_RCRd: + SET_FLAG(FLAG_CF,(flags.var1.d >> (flags.var2.b - 1)) & 1); + break; + + + case t_INCb: + SET_FLAG(FLAG_OF,(flags.result.b == 0x80)); + SET_FLAG(FLAG_AF,((flags.result.b & 0x0f) == 0)); + break; + case t_INCw: + SET_FLAG(FLAG_OF,(flags.result.w == 0x8000)); + SET_FLAG(FLAG_AF,((flags.result.w & 0x0f) == 0)); + break; + case t_INCd: + SET_FLAG(FLAG_OF,(flags.result.d == 0x80000000)); + SET_FLAG(FLAG_AF,((flags.result.d & 0x0f) == 0)); + break; + + + case t_DECb: + SET_FLAG(FLAG_OF,(flags.result.b == 0x7f)); + break; + case t_DECw: + SET_FLAG(FLAG_OF,(flags.result.w == 0x7fff)); + break; + case t_DECd: + SET_FLAG(FLAG_OF,(flags.result.d == 0x7fffffff)); + break; + + + case t_NEGb: + SET_FLAG(FLAG_CF,(flags.var1.b!=0)); + break; + case t_NEGw: + SET_FLAG(FLAG_CF,(flags.var1.w!=0)); + break; + case t_NEGd: + SET_FLAG(FLAG_CF,(flags.var1.d!=0)); + break; + + + case t_DIV: + SET_FLAG(FLAG_CF,false); /* Unkown */ + break; + default: + LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",flags.type); + return 0; + } + flags.word=new_flags; + return 0; +} + +#endif diff --git a/src/cpu/instructions.h b/src/cpu/instructions.h index b43405d..7f0d731 100644 --- a/src/cpu/instructions.h +++ b/src/cpu/instructions.h @@ -18,41 +18,6 @@ /* Jumps */ -/* - Could perhaps do some things with 8 and 16 bit operations like shifts, doing them in 32 bit regs -*/ - -#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 INTERRUPT(blah) \ - { \ - Bit8u new_num=blah; \ - SAVEIP; \ - Interrupt(new_num); \ - LOADIP; \ - } - - - /* All Byte genereal instructions */ #define ADDB(op1,op2,load,save) \ flags.var1.b=load(op1);flags.var2.b=op2; \ @@ -254,227 +219,209 @@ save(op1,flags.result.d); \ flags.type=t_DECd; -#define NOTDONE \ - SUBIP(1);E_Exit("CPU:Opcode %2X Unhandled",Fetchb()); - -#define NOTDONE66 \ - SUBIP(1);E_Exit("CPU:Opcode 66:%2X Unhandled",Fetchb()); - - -//TODO Maybe make this into a bigger split up because of the rm >=0xc0 this seems make it a bit slower -//TODO set Zero and Sign flag in one run #define ROLB(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var2.b=op2&0x07;flags.var1.b=load(op1); \ - if (!flags.var2.b) { \ - flags.result.b=flags.var1.b; \ - } else { \ + 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; + save(op1,flags.result.b); \ + flags.type=t_ROLb; \ + #define ROLW(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var2.b=op2&0x0F;flags.var1.w=load(op1); \ - if (!flags.var2.b) { \ - flags.result.w=flags.var1.w; \ - } else { \ + 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; + save(op1,flags.result.w); \ + flags.type=t_ROLw; \ + #define ROLD(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var2.b=op2;flags.var1.d=load(op1); \ - flags.result.d=(flags.var1.d << flags.var2.b) | \ + 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; + save(op1,flags.result.d); \ + flags.type=t_ROLd; \ #define RORB(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var2.b=op2&0x07;flags.var1.b=load(op1); \ - if (!flags.var2.b) { \ - flags.result.b=flags.var1.b; \ - } else { \ + 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; + save(op1,flags.result.b); \ + flags.type=t_RORb; \ + #define RORW(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var2.b=op2&0x0F;flags.var1.w=load(op1); \ - if (!flags.var2.b) { \ - flags.result.w=flags.var1.w; \ - } else { \ + 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; + save(op1,flags.result.w); \ + flags.type=t_RORw; \ + } #define RORD(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.var2.b=op2;flags.var1.d=load(op1); \ - flags.result.d=(flags.var1.d >> flags.var2.b) | \ + 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; + save(op1,flags.result.d); \ + flags.type=t_RORd; \ + } -/* flags.oldcf=get_CF();*/ \ - #define RCLB(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.cf=get_CF();flags.type=t_RCLb; \ - flags.var2.b=op2%9;flags.var1.b=load(op1); \ - if (!flags.var2.b) { \ - flags.result.b=flags.var1.b; \ - } else { \ + 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) | \ - (flags.cf << (flags.var2.b-1)) | \ + (cf << (flags.var2.b-1)) | \ (flags.var1.b >> (9-flags.var2.b)); \ - flags.cf=((flags.var1.b >> (8-flags.var2.b)) & 1); \ - } \ - flags.of=((flags.result.b & 0x80) ^ (flags.cf ? 0x80 : 0)) != 0; \ - save(op1,flags.result.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); \ + } #define RCLW(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.cf=get_CF();flags.type=t_RCLw; \ - flags.var2.b=op2%17;flags.var1.w=load(op1); \ - if (!flags.var2.b) { \ - flags.result.w=flags.var1.w; \ - } else { \ + 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) | \ - (flags.cf << (flags.var2.b-1)) | \ + (cf << (flags.var2.b-1)) | \ (flags.var1.w >> (17-flags.var2.b)); \ - flags.cf=((flags.var1.w >> (16-flags.var2.b)) & 1); \ - } \ - flags.of=((flags.result.w & 0x8000) ^ (flags.cf ? 0x8000 : 0)) != 0; \ - save(op1,flags.result.w); + SETFLAGBIT(CF,((flags.var1.w >> (16-flags.var2.b)) & 1)); \ + SETFLAGBIT(OF,(flags.var1.w ^ flags.result.w) & 0x8000); \ + save(op1,flags.result.w); \ + } #define RCLD(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.cf=get_CF();flags.type=t_RCLd; \ - flags.var2.b=op2;flags.var1.d=load(op1); \ - if (flags.var2.b==1) { \ - flags.result.d=(flags.var1.d << 1) | flags.cf; \ - } else { \ - flags.result.d=(flags.var1.d << flags.var2.b) | \ - (flags.cf << (flags.var2.b-1)) | \ - (flags.var1.d >> (33-flags.var2.b)); \ - } \ - flags.cf=((flags.var1.d >> (32-flags.var2.b)) & 1); \ - flags.of=((flags.result.d & 0x80000000) ^ (flags.cf ? 0x80000000 : 0)) != 0; \ - save(op1,flags.result.d); + 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; \ + } else { \ + flags.result.d=(flags.var1.d << flags.var2.b) | \ + (cf << (flags.var2.b-1)) | \ + (flags.var1.d >> (33-flags.var2.b)); \ + } \ + SETFLAGBIT(CF,((flags.var1.d >> (32-flags.var2.b)) & 1)); \ + SETFLAGBIT(OF,(flags.var1.d ^ flags.result.d) & 0x80000000); \ + save(op1,flags.result.d); \ + } #define RCRB(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.cf=get_CF();flags.type=t_RCRb; \ - flags.var2.b=op2%9;flags.var1.b=load(op1); \ - if (!flags.var2.b) { \ - flags.result.b=flags.var1.b; \ - } else { \ + 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) | \ - (flags.cf << (8-flags.var2.b)) | \ + (cf << (8-flags.var2.b)) | \ (flags.var1.b << (9-flags.var2.b)); \ - } \ - save(op1,flags.result.b); + save(op1,flags.result.b); \ + } #define RCRW(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.cf=get_CF();flags.type=t_RCRw; \ - flags.var2.b=op2%17;flags.var1.w=load(op1); \ - if (!flags.var2.b) { \ - flags.result.w=flags.var1.w; \ - } else { \ + 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) | \ - (flags.cf << (16-flags.var2.b)) | \ + (cf << (16-flags.var2.b)) | \ (flags.var1.w << (17-flags.var2.b)); \ - } \ - save(op1,flags.result.w); + save(op1,flags.result.w); \ + } #define RCRD(op1,op2,load,save) \ - if (!op2) break; \ - flags.zf=get_ZF();flags.sf=get_SF();flags.af=get_AF(); \ - flags.cf=get_CF();flags.type=t_RCRd; \ - flags.var2.b=op2;flags.var1.d=load(op1); \ - if (flags.var2.b==1) { \ - flags.result.d=flags.var1.d >> 1 | flags.cf << 31; \ - } else { \ - flags.result.d=(flags.var1.d >> flags.var2.b) | \ - (flags.cf << (32-flags.var2.b)) | \ + 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; \ + } else { \ + flags.result.d=(flags.var1.d >> flags.var2.b) | \ + (cf << (32-flags.var2.b)) | \ (flags.var1.d << (33-flags.var2.b)); \ - } \ - save(op1,flags.result.d); + } \ + save(op1,flags.result.d); \ + } #define SHLB(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ + 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; #define SHLW(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.w=load(op1);flags.var2.b=op2 ; \ + 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; #define SHLD(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ + 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; #define SHRB(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ + 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; #define SHRW(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.w=load(op1);flags.var2.b=op2; \ + 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; #define SHRD(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.d=load(op1);flags.var2.b=op2; \ + 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; #define SARB(op1,op2,load,save) \ - if (!op2) break; \ - flags.var1.b=load(op1);flags.var2.b=op2; \ + 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)| \ @@ -512,34 +459,298 @@ +#define DAA() \ + if (((reg_al & 0x0F)>0x09) || get_AF()) { \ + reg_al+=0x06; \ + SETFLAGBIT(AF,true); \ + } else { \ + SETFLAGBIT(AF,false); \ + } \ + if ((reg_al > 0x9F) || get_CF()) { \ + reg_al+=0x60; \ + SETFLAGBIT(CF,true); \ + } else { \ + SETFLAGBIT(CF,false); \ + } \ + SETFLAGBIT(SF,(reg_al&0x80)); \ + SETFLAGBIT(ZF,(reg_al==0)); \ + flags.type=t_UNKNOWN; + + +#define DAS() \ + if (((reg_al & 0x0f) > 9) || get_AF()) { \ + reg_al-=6; \ + SETFLAGBIT(AF,true); \ + } else { \ + SETFLAGBIT(AF,false); \ + } \ + if ((reg_al>0x9f) || get_CF()) { \ + reg_al-=0x60; \ + SETFLAGBIT(CF,true); \ + } else { \ + SETFLAGBIT(CF,false); \ + } \ + flags.type=t_UNKNOWN; + + +#define AAA() \ + if (get_AF() || ((reg_al & 0xf) > 9)) \ + { \ + reg_al += 6; \ + reg_ah += 1; \ + SETFLAGBIT(AF,true); \ + SETFLAGBIT(CF,true); \ + } else { \ + SETFLAGBIT(AF,false); \ + SETFLAGBIT(CF,false); \ + } \ + reg_al &= 0x0F; \ + flags.type=t_UNKNOWN; + +#define AAS() \ + if (((reg_al & 0x0f)>9) || get_AF()) { \ + reg_ah--; \ + if (reg_al < 6) reg_ah--; \ + reg_al=(reg_al-6) & 0xF; \ + SETFLAGBIT(AF,true); \ + SETFLAGBIT(CF,true); \ + } else { \ + SETFLAGBIT(AF,false); \ + SETFLAGBIT(CF,false); \ + } \ + reg_al &= 0x0F; \ + flags.type=t_UNKNOWN; + +#define AAM(op1) \ + { \ + Bit8u BLAH=op1; \ + reg_ah=reg_al / BLAH; \ + reg_al=reg_al % BLAH; \ + flags.type=t_UNKNOWN; \ + SETFLAGBIT(SF,(reg_al & 0x80)); \ + SETFLAGBIT(ZF,(reg_al == 0)); \ + SETFLAGBIT(PF,parity_lookup[reg_al]); \ + } + + +//Took this from bochs, i seriously hate these weird bcd opcodes +#define AAD(op1) \ + { \ + Bit16u ax1 = reg_ah * op1; \ + Bit16u ax2 = ax1 + reg_al; \ + Bit8u old_al = reg_al; \ + reg_al = (Bit8u) ax2; \ + reg_ah = 0; \ + SETFLAGBIT(AF,(ax1 & 0x08) != (ax2 & 0x08)); \ + SETFLAGBIT(CF,ax2 > 0xff); \ + SETFLAGBIT(OF,(reg_al & 0x80) != (old_al & 0x80)); \ + SETFLAGBIT(SF,reg_al >= 0x80); \ + SETFLAGBIT(ZF,reg_al == 0); \ + SETFLAGBIT(PF,parity_lookup[reg_al]); \ + flags.type=t_UNKNOWN; \ + } + +#define MULB(op1,load,save) \ + flags.type=t_MUL; \ + reg_ax=reg_al*load(op1); \ + if (reg_ax & 0xff00) { \ + SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ + } else { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } + +#define MULW(op1,load,save) \ +{ \ + Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \ + reg_ax=(Bit16u)(tempu); \ + reg_dx=(Bit16u)(tempu >> 16); \ + flags.type=t_MUL; \ + if (reg_dx) { \ + SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ + } else { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } \ +} + +#define MULD(op1,load,save) \ +{ \ + Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \ + reg_eax=(Bit32u)(tempu); \ + reg_edx=(Bit32u)(tempu >> 32); \ + flags.type=t_MUL; \ + if (reg_edx) { \ + SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ + } else { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } \ +} + +#define DIVB(op1,load,save) \ +{ \ + Bitu val=load(op1); \ + if (val==0) EXCEPTION(0); \ + Bitu quo=reg_ax / val; \ + reg_ah=(Bit8u)(reg_ax % val); \ + reg_al=(Bit8u)quo; \ + if (quo>0xff) EXCEPTION(0); \ +} + + +#define DIVW(op1,load,save) \ +{ \ + Bitu val=load(op1); \ + if (val==0) EXCEPTION(0); \ + Bitu num=(reg_dx<<16)|reg_ax; \ + Bitu quo=num/val; \ + reg_dx=(Bit16u)(num % val); \ + reg_ax=(Bit16u)quo; \ + if (quo>0xffff) EXCEPTION(0); \ +} + +#define DIVD(op1,load,save) \ +{ \ + Bitu val=load(op1); \ + if (!val) EXCEPTION(0); \ + Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; \ + Bit64u quo=num/val; \ + reg_edx=(Bit32u)(num % val); \ + reg_eax=(Bit32u)quo; \ + if (quo!=(Bit64u)reg_eax) EXCEPTION(0); \ +} + + +#define IDIVB(op1,load,save) \ +{ \ + Bits val=(Bit8s)(load(op1)); \ + if (val==0) EXCEPTION(0); \ + Bits quo=((Bit16s)reg_ax) / val; \ + reg_ah=(Bit8s)(((Bit16s)reg_ax) % val); \ + reg_al=(Bit8s)quo; \ + if (quo!=(Bit8s)reg_al) EXCEPTION(0); \ +} + + +#define IDIVW(op1,load,save) \ +{ \ + Bits val=(Bit16s)(load(op1)); \ + if (!val) EXCEPTION(0); \ + Bits num=(Bit32s)((reg_dx<<16)|reg_ax); \ + Bits quo=num/val; \ + reg_dx=(Bit16u)(num % val); \ + reg_ax=(Bit16s)quo; \ + if (quo!=(Bit16s)reg_ax) EXCEPTION(0); \ +} + +#define IDIVD(op1,load,save) \ +{ \ + Bits val=(Bit32s)(load(op1)); \ + if (!val) EXCEPTION(0); \ + Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; \ + Bit64s quo=num/val; \ + reg_edx=(Bit32s)(num % val); \ + reg_eax=(Bit32s)(quo); \ + if (quo!=(Bit64s)((Bit32s)reg_eax)) EXCEPTION(0); \ +} + +#define IMULB(op1,load,save) \ +{ \ + flags.type=t_MUL; \ + reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \ + if ((reg_ax & 0xff80)==0xff80 || \ + (reg_ax & 0xff80)==0x0000) { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } else { \ + SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ + } \ +} + + +#define IMULW(op1,load,save) \ +{ \ + Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \ + reg_ax=(Bit16s)(temps); \ + reg_dx=(Bit16s)(temps >> 16); \ + flags.type=t_MUL; \ + if (((temps & 0xffff8000)==0xffff8000 || \ + (temps & 0xffff8000)==0x0000)) { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } else { \ + SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ + } \ +} + +#define IMULD(op1,load,save) \ +{ \ + Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \ + ((Bit64s)((Bit32s)(load(op1)))); \ + reg_eax=(Bit32u)(temps); \ + reg_edx=(Bit32u)(temps >> 32); \ + flags.type=t_MUL; \ + if ((reg_edx==0xffffffff) && \ + (reg_eax & 0x80000000) ) { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } else if ( (reg_edx==0x00000000) && \ + (reg_eax< 0x80000000) ) { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } else { \ + SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ + } \ +} + +#define DIMULW(op1,op2,op3,load,save) \ +{ \ + Bits res; \ + res=((Bit16s)op2) * ((Bit16s)op3); \ + save(op1,res & 0xffff); \ + flags.type=t_MUL; \ + if ((res> -32768) && (res<32767)) { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } else { \ + SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ + } \ +} + +#define DIMULD(op1,op2,op3,load,save) \ +{ \ + Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \ + save(op1,(Bit32s)res); \ + flags.type=t_MUL; \ + if ((res>-((Bit64s)(2147483647)+1)) && \ + (res<(Bit64s)2147483647)) { \ + SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ + } else { \ + SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ + } \ +} + #define GRP2B(blah) \ { \ - GetRM; \ + GetRM;Bitu which=(rm>>3)&7; \ if (rm >= 0xc0) { \ GetEArb; \ Bit8u val=blah & 0x1f; \ - switch (rm&0x38) { \ + switch (which) { \ case 0x00:ROLB(*earb,val,LoadRb,SaveRb);break; \ - case 0x08:RORB(*earb,val,LoadRb,SaveRb);break; \ - case 0x10:RCLB(*earb,val,LoadRb,SaveRb);break; \ - case 0x18:RCRB(*earb,val,LoadRb,SaveRb);break; \ - case 0x20:/* SHL and SAL are the same */ \ - case 0x30:SHLB(*earb,val,LoadRb,SaveRb);break; \ - case 0x28:SHRB(*earb,val,LoadRb,SaveRb);break; \ - case 0x38:SARB(*earb,val,LoadRb,SaveRb);break; \ + case 0x01:RORB(*earb,val,LoadRb,SaveRb);break; \ + case 0x02:RCLB(*earb,val,LoadRb,SaveRb);break; \ + case 0x03:RCRB(*earb,val,LoadRb,SaveRb);break; \ + case 0x04:/* SHL and SAL are the same */ \ + case 0x06:SHLB(*earb,val,LoadRb,SaveRb);break; \ + case 0x05:SHRB(*earb,val,LoadRb,SaveRb);break; \ + case 0x07:SARB(*earb,val,LoadRb,SaveRb);break; \ } \ } else { \ GetEAa; \ Bit8u val=blah & 0x1f; \ - switch (rm & 0x38) { \ + switch (which) { \ case 0x00:ROLB(eaa,val,LoadMb,SaveMb);break; \ - case 0x08:RORB(eaa,val,LoadMb,SaveMb);break; \ - case 0x10:RCLB(eaa,val,LoadMb,SaveMb);break; \ - case 0x18:RCRB(eaa,val,LoadMb,SaveMb);break; \ - case 0x20:/* SHL and SAL are the same */ \ - case 0x30:SHLB(eaa,val,LoadMb,SaveMb);break; \ - case 0x28:SHRB(eaa,val,LoadMb,SaveMb);break; \ - case 0x38:SARB(eaa,val,LoadMb,SaveMb);break; \ + case 0x01:RORB(eaa,val,LoadMb,SaveMb);break; \ + case 0x02:RCLB(eaa,val,LoadMb,SaveMb);break; \ + case 0x03:RCRB(eaa,val,LoadMb,SaveMb);break; \ + case 0x04:/* SHL and SAL are the same */ \ + case 0x06:SHLB(eaa,val,LoadMb,SaveMb);break; \ + case 0x05:SHRB(eaa,val,LoadMb,SaveMb);break; \ + case 0x07:SARB(eaa,val,LoadMb,SaveMb);break; \ } \ } \ } @@ -548,32 +759,32 @@ #define GRP2W(blah) \ { \ - GetRM; \ + GetRM;Bitu which=(rm>>3)&7; \ if (rm >= 0xc0) { \ GetEArw; \ Bit8u val=blah & 0x1f; \ - switch (rm&0x38) { \ + switch (which) { \ case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break; \ - case 0x08:RORW(*earw,val,LoadRw,SaveRw);break; \ - case 0x10:RCLW(*earw,val,LoadRw,SaveRw);break; \ - case 0x18:RCRW(*earw,val,LoadRw,SaveRw);break; \ - case 0x20:/* SHL and SAL are the same */ \ - case 0x30:SHLW(*earw,val,LoadRw,SaveRw);break; \ - case 0x28:SHRW(*earw,val,LoadRw,SaveRw);break; \ - case 0x38:SARW(*earw,val,LoadRw,SaveRw);break; \ + case 0x01:RORW(*earw,val,LoadRw,SaveRw);break; \ + case 0x02:RCLW(*earw,val,LoadRw,SaveRw);break; \ + case 0x03:RCRW(*earw,val,LoadRw,SaveRw);break; \ + case 0x04:/* SHL and SAL are the same */ \ + case 0x06:SHLW(*earw,val,LoadRw,SaveRw);break; \ + case 0x05:SHRW(*earw,val,LoadRw,SaveRw);break; \ + case 0x07:SARW(*earw,val,LoadRw,SaveRw);break; \ } \ } else { \ GetEAa; \ Bit8u val=blah & 0x1f; \ - switch (rm & 0x38) { \ + switch (which) { \ case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break; \ - case 0x08:RORW(eaa,val,LoadMw,SaveMw);break; \ - case 0x10:RCLW(eaa,val,LoadMw,SaveMw);break; \ - case 0x18:RCRW(eaa,val,LoadMw,SaveMw);break; \ - case 0x20:/* SHL and SAL are the same */ \ - case 0x30:SHLW(eaa,val,LoadMw,SaveMw);break; \ - case 0x28:SHRW(eaa,val,LoadMw,SaveMw);break; \ - case 0x38:SARW(eaa,val,LoadMw,SaveMw);break; \ + case 0x01:RORW(eaa,val,LoadMw,SaveMw);break; \ + case 0x02:RCLW(eaa,val,LoadMw,SaveMw);break; \ + case 0x03:RCRW(eaa,val,LoadMw,SaveMw);break; \ + case 0x04:/* SHL and SAL are the same */ \ + case 0x06:SHLW(eaa,val,LoadMw,SaveMw);break; \ + case 0x05:SHRW(eaa,val,LoadMw,SaveMw);break; \ + case 0x07:SARW(eaa,val,LoadMw,SaveMw);break; \ } \ } \ } @@ -581,32 +792,32 @@ #define GRP2D(blah) \ { \ - GetRM; \ + GetRM;Bitu which=(rm>>3)&7; \ if (rm >= 0xc0) { \ GetEArd; \ Bit8u val=blah & 0x1f; \ - switch (rm&0x38) { \ + switch (which) { \ case 0x00:ROLD(*eard,val,LoadRd,SaveRd);break; \ - case 0x08:RORD(*eard,val,LoadRd,SaveRd);break; \ - case 0x10:RCLD(*eard,val,LoadRd,SaveRd);break; \ - case 0x18:RCRD(*eard,val,LoadRd,SaveRd);break; \ - case 0x20:/* SHL and SAL are the same */ \ - case 0x30:SHLD(*eard,val,LoadRd,SaveRd);break; \ - case 0x28:SHRD(*eard,val,LoadRd,SaveRd);break; \ - case 0x38:SARD(*eard,val,LoadRd,SaveRd);break; \ + case 0x01:RORD(*eard,val,LoadRd,SaveRd);break; \ + case 0x02:RCLD(*eard,val,LoadRd,SaveRd);break; \ + case 0x03:RCRD(*eard,val,LoadRd,SaveRd);break; \ + case 0x04:/* SHL and SAL are the same */ \ + case 0x06:SHLD(*eard,val,LoadRd,SaveRd);break; \ + case 0x05:SHRD(*eard,val,LoadRd,SaveRd);break; \ + case 0x07:SARD(*eard,val,LoadRd,SaveRd);break; \ } \ } else { \ GetEAa; \ Bit8u val=blah & 0x1f; \ - switch (rm & 0x38) { \ + switch (which) { \ case 0x00:ROLD(eaa,val,LoadMd,SaveMd);break; \ - case 0x08:RORD(eaa,val,LoadMd,SaveMd);break; \ - case 0x10:RCLD(eaa,val,LoadMd,SaveMd);break; \ - case 0x18:RCRD(eaa,val,LoadMd,SaveMd);break; \ - case 0x20:/* SHL and SAL are the same */ \ - case 0x30:SHLD(eaa,val,LoadMd,SaveMd);break; \ - case 0x28:SHRD(eaa,val,LoadMd,SaveMd);break; \ - case 0x38:SARD(eaa,val,LoadMd,SaveMd);break; \ + case 0x01:RORD(eaa,val,LoadMd,SaveMd);break; \ + case 0x02:RCLD(eaa,val,LoadMd,SaveMd);break; \ + case 0x03:RCRD(eaa,val,LoadMd,SaveMd);break; \ + case 0x04:/* SHL and SAL are the same */ \ + case 0x06:SHLD(eaa,val,LoadMd,SaveMd);break; \ + case 0x05:SHRD(eaa,val,LoadMd,SaveMd);break; \ + case 0x07:SARD(eaa,val,LoadMd,SaveMd);break; \ } \ } \ } diff --git a/src/cpu/lazyflags.h b/src/cpu/lazyflags.h new file mode 100644 index 0000000..2ab6ca1 --- /dev/null +++ b/src/cpu/lazyflags.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2002-2003 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. + */ + +//Flag Handling +Bitu get_CF(void); +Bitu get_AF(void); +Bitu get_ZF(void); +Bitu get_SF(void); +Bitu get_OF(void); +Bitu get_PF(void); + +void FillFlags(void); + +#define SETFLAGSb(FLAGB) \ +{ \ + SETFLAGBIT(OF,get_OF()); \ + flags.type=t_UNKNOWN; \ + CPU_SetFlags((flags.word&0xffffff00)|((FLAGB) & 0xff)); \ +} + +#define SETFLAGSw(FLAGW) \ +{ \ + flags.type=t_UNKNOWN; \ + CPU_SetFlagsw(FLAGW); \ +} + +#define SETFLAGSd(FLAGD) \ +{ \ + flags.type=t_UNKNOWN; \ + CPU_SetFlags(FLAGD); \ +} + +#define LoadCF SETFLAGBIT(CF,get_CF()); +#define LoadZF SETFLAGBIT(ZF,get_ZF()); +#define LoadSF SETFLAGBIT(SF,get_SF()); +#define LoadOF SETFLAGBIT(OF,get_OF()); +#define LoadAF SETFLAGBIT(AF,get_AF()); + +//Types of Flag changing instructions +enum { + t_UNKNOWN=0, + t_ADDb,t_ADDw,t_ADDd, + t_ORb,t_ORw,t_ORd, + t_ADCb,t_ADCw,t_ADCd, + t_SBBb,t_SBBw,t_SBBd, + t_ANDb,t_ANDw,t_ANDd, + t_SUBb,t_SUBw,t_SUBd, + t_XORb,t_XORw,t_XORd, + t_CMPb,t_CMPw,t_CMPd, + t_INCb,t_INCw,t_INCd, + t_DECb,t_DECw,t_DECd, + t_TESTb,t_TESTw,t_TESTd, + t_SHLb,t_SHLw,t_SHLd, + t_SHRb,t_SHRw,t_SHRd, + t_SARb,t_SARw,t_SARd, + t_ROLb,t_ROLw,t_ROLd, + t_RORb,t_RORw,t_RORd, + 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, + t_NOTDONE, + t_LASTFLAG +}; + diff --git a/src/cpu/modrm.h b/src/cpu/modrm.h index ad0da0d..42a34d0 100644 --- a/src/cpu/modrm.h +++ b/src/cpu/modrm.h @@ -53,24 +53,12 @@ extern Bit32u * lookupRMEAregd[256]; #define GetEArb \ - union { \ - Bit8u * earb; \ - Bit8s * earbs; \ - }; \ - earb=lookupRMEAregb[rm]; + Bit8u * earb=lookupRMEAregb[rm]; #define GetEArw \ - union { \ - Bit16u * earw; \ - Bit16s * earws; \ - }; \ - earw=lookupRMEAregw[rm]; + Bit16u * earw=lookupRMEAregw[rm]; #define GetEArd \ - union { \ - Bit32u * eard; \ - Bit32s * eards; \ - }; \ - eard=lookupRMEAregd[rm]; + Bit32u * eard=lookupRMEAregd[rm]; diff --git a/src/cpu/paging.cpp b/src/cpu/paging.cpp new file mode 100644 index 0000000..8f6c68b --- /dev/null +++ b/src/cpu/paging.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2002-2003 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 +#include + +#include "dosbox.h" +#include "mem.h" +#include "paging.h" +#include "../hardware/vga.h" + + +#define LINK_TOTAL (64*1024) + +static PageLink link_list[LINK_TOTAL]; +struct PagingBlock paging; + +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; +}; + +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; +}; + + + +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); +} +PageDirectory::~PageDirectory() { + delete table_change; + delete dir_change; +} +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 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; + } + 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; + } + 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; + } + 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 PageDirectory::InvalidateLink(Bitu table,Bitu index) { + Bitu i=(table*1024)+index; + if (links[i]!=&link_init) { + MEM_UnlinkPage(links[i]); + links[i]=&link_init; + } +} + + +Bitu PAGING_GetDirBase(void) { + return paging.cr3; +} + +void PAGING_SetDirBase(Bitu cr3) { + paging.cr3=cr3; + Bitu base_page=cr3 >> 12; + LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,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; + } +} + +void PAGING_Enable(bool enabled) { + /* If paging is disable we work from a default paging table */ + if (paging.enabled==enabled) return; + 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); + } +} + +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 - SAVEIP; - if (DEBUG_HeavyIsBreakpoint()) return 1; + 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" - if (prefix.count) { - PrefixReset; - //DEBUG_HeavyWriteLogInstruction(); - LOG(LOG_CPU,"Prefix for non prefixed instruction"); - } CPU_Cycles--; } - #include "core_16/stop.h" +decode_end: + LEAVECORE; return CBRET_NONE; } -static Bitu CPU_Real_16_Slow_Decode_Trap(void) { +static Bits CPU_Real_16_Slow_Decode_Trap(void) { Bits oldCycles = CPU_Cycles; CPU_Cycles = 1; - CPU_Real_16_Slow_Decode(); + Bits ret=CPU_Real_16_Slow_Decode(); // LOG_DEBUG("TRAP: Trap Flag executed"); - INTERRUPT(1); + Interrupt(1); CPU_Cycles = oldCycles-1; cpudecoder = &CPU_Real_16_Slow_Decode; - return CBRET_NONE; + return ret; } -void CPU_Real_16_Slow_Start(void) { +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[0]=&GetEA_16_n; - EAPrefixTable[1]=&GetEA_16_s; EAPrefixTable[2]=&GetEA_32_n; EAPrefixTable[3]=&GetEA_32_s; - PrefixReset; + EAPrefixTable[0]=&GetEA_16_n; + EAPrefixTable[1]=&GetEA_16_s; + }; diff --git a/src/debug/Makefile.am b/src/debug/Makefile.am index a939db1..dfee792 100644 --- a/src/debug/Makefile.am +++ b/src/debug/Makefile.am @@ -1,5 +1,4 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -EXTRA_DIST = debug_win32.cpp noinst_LIBRARIES = libdebug.a -libdebug_a_SOURCES = debug.cpp debug_gui.cpp debug_disasm.cpp debug_inc.h disasm_tables.h \ No newline at end of file +libdebug_a_SOURCES = debug.cpp debug_gui.cpp debug_disasm.cpp debug_inc.h disasm_tables.h debug_win32.cpp \ No newline at end of file diff --git a/src/debug/Makefile.in b/src/debug/Makefile.in index 53f85b5..dadd5a1 100644 --- a/src/debug/Makefile.in +++ b/src/debug/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,83 +13,128 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ AM_CPPFLAGS = -I$(top_srcdir)/include -EXTRA_DIST = debug_win32.cpp noinst_LIBRARIES = libdebug.a -libdebug_a_SOURCES = debug.cpp debug_gui.cpp debug_disasm.cpp debug_inc.h disasm_tables.h +libdebug_a_SOURCES = debug.cpp debug_gui.cpp debug_disasm.cpp debug_inc.h disasm_tables.h debug_win32.cpp subdir = src/debug +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -98,31 +143,25 @@ LIBRARIES = $(noinst_LIBRARIES) libdebug_a_AR = $(AR) cru libdebug_a_LIBADD = am_libdebug_a_OBJECTS = debug.$(OBJEXT) debug_gui.$(OBJEXT) \ - debug_disasm.$(OBJEXT) + debug_disasm.$(OBJEXT) debug_win32.$(OBJEXT) libdebug_a_OBJECTS = $(am_libdebug_a_OBJECTS) -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/debug.Po ./$(DEPDIR)/debug_disasm.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/debug_gui.Po +@AMDEP_TRUE@ ./$(DEPDIR)/debug_gui.Po ./$(DEPDIR)/debug_win32.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ -CFLAGS = @CFLAGS@ 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 = $(libdebug_a_SOURCES) -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libdebug_a_SOURCES) all: all-am @@ -153,27 +192,37 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug_disasm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug_gui.Po@am__quote@ - -distclean-depend: - -rm -rf ./$(DEPDIR) +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug_win32.Po@am__quote@ .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -199,20 +248,41 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -237,7 +307,6 @@ check: check-am all-am: Makefile $(LIBRARIES) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -257,7 +326,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -267,9 +336,11 @@ clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am @@ -290,6 +361,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -297,18 +370,25 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags distdir dvi \ - dvi-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index 5a849e6..ba74632 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -34,6 +34,7 @@ #include "mixer.h" #include "debug_inc.h" #include "timer.h" +#include "../ints/xms.h" #include "../shell/shell_inc.h" #ifdef WIN32 @@ -44,12 +45,15 @@ void WIN32_Console(); static struct termios consolesettings; int old_cursor_state; #endif + // Forwards static void DrawCode(void); static bool DEBUG_Log_Loop(int count); static void DEBUG_RaiseTimerIrq(void); -char* AnalyzeInstruction(char* inst); +char* AnalyzeInstruction(char* inst, bool saveSelector); void SaveMemory(Bit16u seg, Bit16u ofs1, Bit32s num); +Bit32u GetHexValue(char* str, char*& hex); + class DEBUG; DEBUG* pDebugcom = 0; @@ -60,16 +64,15 @@ static struct { Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip; } oldregs; - +static char curSelectorName[3] = { 0,0,0 }; static Segment oldsegs[6]; -static Flag_Info oldflags; +static Bitu oldflags; DBGBlock dbg; -static char input_line[256]; static Bitu input_count; Bitu cycle_count; static bool debugging; -static void SetColor(bool test) { +static void SetColor(Bitu test) { if (test) { if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));} } else { @@ -90,9 +93,52 @@ struct SCodeViewData { } codeViewData; -static Bit16u dataSeg,dataOfs; +static Bit16u dataSeg; +static Bit32u dataOfs; static bool showExtend = true; +/***********/ +/* Helpers */ +/***********/ + +Bit32u PhysMakeProt(Bit16u selector, Bit32u offset) +{ + Descriptor desc; + if (cpu.gdt.GetDescriptor(selector,desc)) return desc.GetBase()+offset; + return 0; +}; + +Bit32u GetAddress(Bit16u seg, Bit32u offset) +{ + if (cpu.pmode) return PhysMakeProt(seg,offset); + return (seg<<4)+offset; +}; + +bool GetDescriptorInfo(char* selname, char* out1, char* out2) +{ + Bit16u sel; + Descriptor desc; + + if (strstr(selname,"cs") || strstr(selname,"CS")) sel = SegValue(cs); else + if (strstr(selname,"ds") || strstr(selname,"DS")) sel = SegValue(ds); else + if (strstr(selname,"es") || strstr(selname,"ES")) sel = SegValue(es); else + if (strstr(selname,"fs") || strstr(selname,"FS")) sel = SegValue(fs); else + if (strstr(selname,"gs") || strstr(selname,"GS")) sel = SegValue(gs); else + if (strstr(selname,"ss") || strstr(selname,"SS")) sel = SegValue(ss); else + sel = GetHexValue(selname,selname); + // FIXME: Call Gate Descriptors + if (cpu.gdt.GetDescriptor(sel,desc)) { + sprintf(out1,"%s: b:%08X type:%02X parbg",selname,desc.GetBase(),desc.saved.seg.type); + sprintf(out2," l:%08X dpl : %01X %1X%1X%1X%1X%1X",desc.GetLimit(),desc.saved.seg.dpl,desc.saved.seg.p,desc.saved.seg.avl,desc.saved.seg.r,desc.saved.seg.big,desc.saved.seg.g); + return true; + } else { + strcpy(out1," "); + strcpy(out2," "); + } + //out1[0] = out2[0] = 0; + return false; +}; + /********************/ /* DebugVar stuff */ /********************/ @@ -137,7 +183,7 @@ class CBreakpoint public: CBreakpoint (void) { location = 0; active = once = false; segment = 0; offset = 0; intNr = 0; ahValue = 0; type = BKPNT_UNKNOWN; }; - void SetAddress (Bit16u seg, Bit32u off) { location = PhysMake(seg,off); type = BKPNT_PHYSICAL; segment = seg; offset = off; }; + void SetAddress (Bit16u seg, Bit32u off) { location = GetAddress(seg,off); type = BKPNT_PHYSICAL; segment = seg; offset = off; }; void SetAddress (PhysPt adr) { location = adr; type = BKPNT_PHYSICAL; }; void SetInt (Bit8u _intNr, Bit16u ah) { intNr = _intNr, ahValue = ah; type = BKPNT_INTERRUPT; }; void SetOnce (bool _once) { once = _once; }; @@ -161,6 +207,7 @@ public: static CBreakpoint* AddMemBreakpoint (Bit16u seg, Bit32u off); static void ActivateBreakpoints (PhysPt adr, bool activate); static bool CheckBreakpoint (PhysPt adr); + static bool CheckBreakpoint (Bitu seg, Bitu off); static bool CheckIntBreakpoint (PhysPt adr, Bit8u intNr, Bit16u ahValue); static bool IsBreakpoint (PhysPt where); static bool IsBreakpointDrawn (PhysPt where); @@ -214,6 +261,7 @@ void CBreakpoint::Activate(bool _active) // Statics std::list CBreakpoint::BPoints; CBreakpoint* CBreakpoint::ignoreOnce = 0; +Bitu ignoreAddressOnce = 0; CBreakpoint* CBreakpoint::AddBreakpoint(Bit16u seg, Bit32u off, bool once) { @@ -259,15 +307,21 @@ void CBreakpoint::ActivateBreakpoints(PhysPt adr, bool activate) }; }; -bool CBreakpoint::CheckBreakpoint(PhysPt adr) +bool CBreakpoint::CheckBreakpoint(Bitu seg, Bitu off) // Checks if breakpoint is valid an should stop execution { + if ((ignoreAddressOnce!=0) && (GetAddress(seg,off)==ignoreAddressOnce)) { + ignoreAddressOnce = 0; + return false; + } else + ignoreAddressOnce = 0; + // Search matching breakpoint std::list::iterator i; CBreakpoint* bp; for(i=BPoints.begin(); i != BPoints.end(); i++) { bp = static_cast(*i); - if ((bp->GetType()==BKPNT_PHYSICAL) && bp->IsActive() && (bp->GetLocation()==adr)) { + if ((bp->GetType()==BKPNT_PHYSICAL) && bp->IsActive() && (bp->GetSegment()==seg) && (bp->GetOffset()==off)) { // Ignore Once ? if (ignoreOnce==bp) { ignoreOnce=0; @@ -288,12 +342,14 @@ bool CBreakpoint::CheckBreakpoint(PhysPt adr) #if C_HEAVY_DEBUG // Memory breakpoint support else if ((bp->GetType()==BKPNT_MEMORY) && bp->IsActive()) { - - Bit8u value = mem_readb(bp->GetLocation()); + + 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(0,"DEBUG: Memory breakpoint: %04X:%04X - %02X -> %02X",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value); + DEBUG_ShowMsg("DEBUG: Memory breakpoint: %04X:%04X - %02X -> %02X",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value); bp->SetValue(value); return true; }; @@ -307,6 +363,12 @@ bool CBreakpoint::CheckBreakpoint(PhysPt adr) bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue) // Checks if interrupt breakpoint is valid an should stop execution { + if ((ignoreAddressOnce!=0) && (adr==ignoreAddressOnce)) { + ignoreAddressOnce = 0; + return false; + } else + ignoreAddressOnce = 0; + // Search matching breakpoint std::list::iterator i; CBreakpoint* bp; @@ -371,7 +433,6 @@ bool CBreakpoint::DeleteByIndex(Bit16u index) bool CBreakpoint::DeleteBreakpoint(PhysPt where) { // Search matching breakpoint - int nr = 0; std::list::iterator i; CBreakpoint* bp; for(i=BPoints.begin(); i != BPoints.end(); i++) { @@ -394,6 +455,9 @@ bool CBreakpoint::IsBreakpoint(PhysPt adr) CBreakpoint* bp; for(i=BPoints.begin(); i != BPoints.end(); i++) { bp = static_cast(*i); + if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetSegment()==adr)) { + return true; + }; if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) { return true; }; @@ -442,38 +506,42 @@ void CBreakpoint::ShowList(void) bool DEBUG_Breakpoint(void) { /* First get the phyiscal address and check for a set Breakpoint */ - PhysPt where=SegPhys(cs)+reg_eip-1; - if (!CBreakpoint::CheckBreakpoint(where)) return false; +// PhysPt where=SegPhys(cs)+reg_eip-1; + PhysPt where=GetAddress(SegValue(cs),reg_eip-1); + if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip-1)) return false; // Found. Breakpoint is valid reg_eip -= 1; - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,false); // Deactivate all breakpoints - exitLoop = true; - DEBUG_Enable(); + CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints +// exitLoop = true; +// DEBUG_Enable(); return true; }; bool DEBUG_IntBreakpoint(Bit8u intNum) { /* First get the phyiscal address and check for a set Breakpoint */ - PhysPt where=SegPhys(cs)+reg_eip-2; +// PhysPt where=SegPhys(cs)+reg_eip-2; + PhysPt where=GetAddress(SegValue(cs),reg_eip-2); if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false; // Found. Breakpoint is valid reg_eip -= 2; - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,false); // Deactivate all breakpoints - exitLoop = true; - DEBUG_Enable(); + CBreakpoint::ActivateBreakpoints(where,false); // Deactivate all breakpoints +// exitLoop = true; +// DEBUG_Enable(); return true; }; static bool StepOver() { - PhysPt start=Segs[cs].phys+reg_eip; + exitLoop = false; +// PhysPt start=SegPhys(cs)+reg_eip; + PhysPt start=GetAddress(SegValue(cs),reg_eip); char dline[200];Bitu size; - size=DasmI386(dline, start, reg_eip, false); + size=DasmI386(dline, start, reg_eip, cpu.code.big); if (strstr(dline,"call") || strstr(dline,"int") || strstr(dline,"loop") || strstr(dline,"rep")) { CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip+size, true); - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip, true); + CBreakpoint::ActivateBreakpoints(start, true); debugging=false; DrawCode(); DOSBOX_SetNormalLoop(); @@ -497,13 +565,16 @@ bool DEBUG_ExitLoop(void) static void DrawData(void) { - Bit16u add = dataOfs; + Bit8u ch; + Bit32u add = dataOfs; + Bit32u address; /* Data win */ for (int y=0; y<8; y++) { // Adress mvwprintw (dbg.win_data,1+y,0,"%04X:%04X ",dataSeg,add); for (int x=0; x<16; x++) { - Bit8u ch = real_readb(dataSeg,add); + address = GetAddress(dataSeg,add); + if (address<8*1024*1024) 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); @@ -535,17 +606,39 @@ static void DrawRegisters(void) { /*Individual flags*/ - flags.cf=get_CF();SetColor(flags.cf!=oldflags.cf);oldflags.cf=flags.cf;mvwprintw (dbg.win_reg,1,53,"%01X",flags.cf); - flags.zf=get_ZF();SetColor(flags.zf!=oldflags.zf);oldflags.zf=flags.zf;mvwprintw (dbg.win_reg,1,56,"%01X",flags.zf); - flags.sf=get_SF();SetColor(flags.sf!=oldflags.sf);oldflags.sf=flags.sf;mvwprintw (dbg.win_reg,1,59,"%01X",flags.sf); - flags.of=get_OF();SetColor(flags.of!=oldflags.of);oldflags.of=flags.of;mvwprintw (dbg.win_reg,1,62,"%01X",flags.of); - flags.af=get_AF();SetColor(flags.af!=oldflags.af);oldflags.af=flags.af;mvwprintw (dbg.win_reg,1,65,"%01X",flags.af); - flags.pf=get_PF();SetColor(flags.pf!=oldflags.pf);oldflags.pf=flags.pf;mvwprintw (dbg.win_reg,1,68,"%01X",flags.pf); + SetColor((flags.word ^ oldflags)&FLAG_CF); + mvwprintw (dbg.win_reg,1,53,"%01X",GETFLAG(CF) ? 1:0); + SetColor((flags.word ^ oldflags)&FLAG_ZF); + mvwprintw (dbg.win_reg,1,56,"%01X",GETFLAG(ZF) ? 1:0); + SetColor((flags.word ^ oldflags)&FLAG_SF); + mvwprintw (dbg.win_reg,1,59,"%01X",GETFLAG(SF) ? 1:0); + SetColor((flags.word ^ oldflags)&FLAG_OF); + mvwprintw (dbg.win_reg,1,62,"%01X",GETFLAG(OF) ? 1:0); + SetColor((flags.word ^ oldflags)&FLAG_AF); + mvwprintw (dbg.win_reg,1,65,"%01X",GETFLAG(AF) ? 1:0); + SetColor((flags.word ^ oldflags)&FLAG_PF); + mvwprintw (dbg.win_reg,1,68,"%01X",GETFLAG(PF) ? 1:0); - SetColor(flags.df!=oldflags.df);oldflags.df=flags.df;mvwprintw (dbg.win_reg,1,71,"%01X",flags.df); - SetColor(flags.intf!=oldflags.intf);oldflags.intf=flags.intf;mvwprintw (dbg.win_reg,1,74,"%01X",flags.intf); - SetColor(flags.tf!=oldflags.tf);oldflags.tf=flags.tf;mvwprintw (dbg.win_reg,1,77,"%01X",flags.tf); + SetColor((flags.word ^ oldflags)&FLAG_DF); + mvwprintw (dbg.win_reg,1,71,"%01X",GETFLAG(DF) ? 1:0); + SetColor((flags.word ^ oldflags)&FLAG_IF); + mvwprintw (dbg.win_reg,1,74,"%01X",GETFLAG(IF) ? 1:0); + SetColor((flags.word ^ oldflags)&FLAG_TF); + mvwprintw (dbg.win_reg,1,77,"%01X",GETFLAG(TF) ? 1:0); + + oldflags=flags.word; + + if (cpu.pmode) mvwprintw(dbg.win_reg,0,76,"Prot"); + else mvwprintw(dbg.win_reg,0,76,"Real"); + + // Selector info, if available + if ((cpu.pmode) && curSelectorName[0]) { + char out1[200], out2[200]; + GetDescriptorInfo(curSelectorName,out1,out2); + mvwprintw(dbg.win_reg,2,28,out1); + mvwprintw(dbg.win_reg,3,28,out2); + } wattrset(dbg.win_reg,0); mvwprintw(dbg.win_reg,3,60,"%d ",cycle_count); @@ -554,11 +647,13 @@ static void DrawRegisters(void) { static void DrawCode(void) { + bool saveSel; Bit32u disEIP = codeViewData.useEIP; - PhysPt start = codeViewData.useCS*16 + codeViewData.useEIP; + PhysPt start = GetAddress(codeViewData.useCS,codeViewData.useEIP); char dline[200];Bitu size;Bitu c; - for (Bit32u i=0;i<10;i++) { + for (int i=0;i<10;i++) { + saveSel = false; if (has_colors()) { if ((codeViewData.useCS==SegValue(cs)) && (disEIP == reg_eip)) { wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK)); @@ -567,10 +662,12 @@ static void DrawCode(void) codeViewData.cursorSeg = SegValue(cs); codeViewData.cursorOfs = disEIP; } + saveSel = (i == codeViewData.cursorPos); } else if (i == codeViewData.cursorPos) { wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY)); codeViewData.cursorSeg = codeViewData.useCS; codeViewData.cursorOfs = disEIP; + saveSel = true; } else if (CBreakpoint::IsBreakpointDrawn(start)) { wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED)); } else { @@ -578,15 +675,20 @@ static void DrawCode(void) } } - size=DasmI386(dline, start, disEIP, false); + + Bitu drawsize=size=DasmI386(dline, start, disEIP, cpu.code.big); + bool toolarge = false; mvwprintw(dbg.win_code,i,0,"%04X:%04X ",codeViewData.useCS,disEIP); - for (c=0;c=size*2;c--) waddch(dbg.win_code,' '); + + if (drawsize>10) { toolarge = true; drawsize = 9; }; + for (c=0;c=drawsize*2;c--) waddch(dbg.win_code,' '); char* res = 0; - if (showExtend) res = AnalyzeInstruction(dline); + if (showExtend) res = AnalyzeInstruction(dline, saveSel); waddstr(dbg.win_code,dline); - for (c=28-strlen(dline);c>0;c--) waddch(dbg.win_code,' '); + if (strlen(dline)<28) for (c=28-strlen(dline);c>0;c--) waddch(dbg.win_code,' '); if (showExtend) { waddstr(dbg.win_code,res); for (c=strlen(res);c<20;c++) waddch(dbg.win_code,' '); @@ -639,6 +741,15 @@ Bit32u GetHexValue(char* str, char*& hex) hex = str; while (*hex==' ') hex++; + if (strstr(hex,"EAX")==hex) { hex+=3; return reg_eax; }; + if (strstr(hex,"EBX")==hex) { hex+=3; return reg_ebx; }; + if (strstr(hex,"ECX")==hex) { hex+=3; return reg_ecx; }; + if (strstr(hex,"EDX")==hex) { hex+=3; return reg_edx; }; + if (strstr(hex,"ESI")==hex) { hex+=3; return reg_esi; }; + if (strstr(hex,"EDI")==hex) { hex+=3; return reg_edi; }; + if (strstr(hex,"EBP")==hex) { hex+=3; return reg_ebp; }; + if (strstr(hex,"ESP")==hex) { hex+=3; return reg_esp; }; + if (strstr(hex,"EIP")==hex) { hex+=3; return reg_eip; }; if (strstr(hex,"AX")==hex) { hex+=2; return reg_ax; }; if (strstr(hex,"BX")==hex) { hex+=2; return reg_bx; }; if (strstr(hex,"CX")==hex) { hex+=2; return reg_cx; }; @@ -654,15 +765,6 @@ Bit32u GetHexValue(char* str, char*& hex) if (strstr(hex,"FS")==hex) { hex+=2; return SegValue(fs); }; if (strstr(hex,"GS")==hex) { hex+=2; return SegValue(gs); }; if (strstr(hex,"SS")==hex) { hex+=2; return SegValue(ss); }; - if (strstr(hex,"EAX")==hex) { hex+=3; return reg_eax; }; - if (strstr(hex,"EBX")==hex) { hex+=3; return reg_ebx; }; - if (strstr(hex,"ECX")==hex) { hex+=3; return reg_ecx; }; - if (strstr(hex,"EDX")==hex) { hex+=3; return reg_edx; }; - if (strstr(hex,"ESI")==hex) { hex+=3; return reg_esi; }; - if (strstr(hex,"EDI")==hex) { hex+=3; return reg_edi; }; - if (strstr(hex,"EBP")==hex) { hex+=3; return reg_ebp; }; - if (strstr(hex,"ESP")==hex) { hex+=3; return reg_esp; }; - if (strstr(hex,"EIP")==hex) { hex+=3; return reg_eip; }; while (*hex) { if ((*hex>='0') && (*hex<='9')) value = (value<<4)+*hex-'0'; else @@ -675,10 +777,17 @@ Bit32u GetHexValue(char* str, char*& hex) bool ChangeRegister(char* str) { - Bit32u value = 0; - char* hex = str; while (*hex==' ') hex++; + if (strstr(hex,"EAX")==hex) { hex+=3; reg_eax = GetHexValue(hex,hex); } else + if (strstr(hex,"EBX")==hex) { hex+=3; reg_ebx = GetHexValue(hex,hex); } else + if (strstr(hex,"ECX")==hex) { hex+=3; reg_ecx = GetHexValue(hex,hex); } else + if (strstr(hex,"EDX")==hex) { hex+=3; reg_edx = GetHexValue(hex,hex); } else + if (strstr(hex,"ESI")==hex) { hex+=3; reg_esi = GetHexValue(hex,hex); } else + if (strstr(hex,"EDI")==hex) { hex+=3; reg_edi = GetHexValue(hex,hex); } else + 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 @@ -694,22 +803,13 @@ bool ChangeRegister(char* str) 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,"EAX")==hex) { hex+=3; reg_eax = GetHexValue(hex,hex); } else - if (strstr(hex,"EBX")==hex) { hex+=3; reg_ebx = GetHexValue(hex,hex); } else - if (strstr(hex,"ECX")==hex) { hex+=3; reg_ecx = GetHexValue(hex,hex); } else - if (strstr(hex,"EDX")==hex) { hex+=3; reg_edx = GetHexValue(hex,hex); } else - if (strstr(hex,"ESI")==hex) { hex+=3; reg_esi = GetHexValue(hex,hex); } else - if (strstr(hex,"EDI")==hex) { hex+=3; reg_edi = GetHexValue(hex,hex); } else - 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,"AF")==hex) { hex+=2; flags.af = (GetHexValue(hex,hex)!=0); } else - if (strstr(hex,"CF")==hex) { hex+=2; flags.cf = (GetHexValue(hex,hex)!=0); } else - if (strstr(hex,"DF")==hex) { hex+=2; flags.df = (GetHexValue(hex,hex)!=0); } else - if (strstr(hex,"IF")==hex) { hex+=2; flags.intf = (GetHexValue(hex,hex)!=0); } else - if (strstr(hex,"OF")==hex) { hex+=3; flags.of = (GetHexValue(hex,hex)!=0); } else - if (strstr(hex,"ZF")==hex) { hex+=3; flags.zf = (GetHexValue(hex,hex)!=0); } else - if (strstr(hex,"PF")==hex) { hex+=3; flags.pf = (GetHexValue(hex,hex)!=0); } 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 + if (strstr(hex,"IF")==hex) { hex+=2; SETFLAGBIT(IF,GetHexValue(hex,hex)); } else + if (strstr(hex,"OF")==hex) { hex+=3; SETFLAGBIT(OF,GetHexValue(hex,hex)); } else + if (strstr(hex,"ZF")==hex) { hex+=3; SETFLAGBIT(ZF,GetHexValue(hex,hex)); } else + if (strstr(hex,"PF")==hex) { hex+=3; SETFLAGBIT(PF,GetHexValue(hex,hex)); } else { return false; }; return true; }; @@ -744,8 +844,8 @@ bool ParseCommand(char* str) }; name[15] = 0; - DEBUG_ShowMsg(0,"DEBUG: Created debug var %s at %04X:%04X",name,seg,ofs); - CDebugVar::InsertVariable(name,PhysMake(seg,ofs)); + DEBUG_ShowMsg("DEBUG: Created debug var %s at %04X:%04X",name,seg,ofs); + CDebugVar::InsertVariable(name,GetAddress(seg,ofs)); return true; } @@ -758,13 +858,13 @@ bool ParseCommand(char* str) else { name[i] = 0; break; }; }; name[12] = 0; - if (CDebugVar::SaveVars(name)) DEBUG_ShowMsg(0,"DEBUG: Variable list save (%s) : ok.",name); - else DEBUG_ShowMsg(0,"DEBUG: Variable list save (%s) : failure",name); + if (CDebugVar::SaveVars(name)) DEBUG_ShowMsg("DEBUG: Variable list save (%s) : ok.",name); + else DEBUG_ShowMsg("DEBUG: Variable list save (%s) : failure",name); return true; } found = strstr(str,"LV "); - if (found) { // Save variables + if (found) { // load variables found+=3; char name[13]; for (int i=0; i<12; i++) { @@ -772,8 +872,8 @@ bool ParseCommand(char* str) else { name[i] = 0; break; }; }; name[12] = 0; - if (CDebugVar::LoadVars(name)) DEBUG_ShowMsg(0,"DEBUG: Variable list load (%s) : ok.",name); - else DEBUG_ShowMsg(0,"DEBUG: Variable list load (%s) : failure",name); + if (CDebugVar::LoadVars(name)) DEBUG_ShowMsg("DEBUG: Variable list load (%s) : ok.",name); + else DEBUG_ShowMsg("DEBUG: Variable list load (%s) : failure",name); return true; } @@ -783,7 +883,7 @@ bool ParseCommand(char* str) Bit16u seg = GetHexValue(found,found);found++; // skip ":" Bit32u ofs = GetHexValue(found,found); CBreakpoint::AddBreakpoint(seg,ofs,false); - DEBUG_ShowMsg(0,"DEBUG: Set breakpoint at %04X:%04X",seg,ofs); + DEBUG_ShowMsg("DEBUG: Set breakpoint at %04X:%04X",seg,ofs); return true; } #if C_HEAVY_DEBUG @@ -793,7 +893,7 @@ bool ParseCommand(char* str) Bit16u seg = GetHexValue(found,found);found++; // skip ":" Bit32u ofs = GetHexValue(found,found); CBreakpoint::AddMemBreakpoint(seg,ofs); - DEBUG_ShowMsg(0,"DEBUG: Set memory breakpoint at %04X:%04X",seg,ofs); + DEBUG_ShowMsg("DEBUG: Set memory breakpoint at %04X:%04X",seg,ofs); return true; } #endif @@ -804,10 +904,10 @@ bool ParseCommand(char* str) Bit8u valAH = GetHexValue(found,found); if ((valAH==0x00) && (*found=='*')) { CBreakpoint::AddIntBreakpoint(intNr,BPINT_ALL,false); - DEBUG_ShowMsg(0,"DEBUG: Set interrupt breakpoint at INT %02X",intNr); + DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X",intNr); } else { CBreakpoint::AddIntBreakpoint(intNr,valAH,false); - DEBUG_ShowMsg(0,"DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH); + DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH); } return true; } @@ -815,7 +915,6 @@ bool ParseCommand(char* str) if (found) { wprintw(dbg.win_out,"Breakpoint list:\n"); wprintw(dbg.win_out,"-------------------------------------------------------------------------\n"); - Bit32u nr = 0; CBreakpoint::ShowList(); return true; }; @@ -826,7 +925,7 @@ bool ParseCommand(char* str) Bit8u bpNr = GetHexValue(found,found); if ((bpNr==0x00) && (*found=='*')) { // Delete all CBreakpoint::DeleteAll(); - DEBUG_ShowMsg(0,"DEBUG: Breakpoints deleted."); + DEBUG_ShowMsg("DEBUG: Breakpoints deleted."); } else { // delete single breakpoint CBreakpoint::DeleteByIndex(bpNr); @@ -838,7 +937,7 @@ bool ParseCommand(char* str) found++; Bit16u codeSeg = GetHexValue(found,found); found++; Bit32u codeOfs = GetHexValue(found,found); - DEBUG_ShowMsg(0,"DEBUG: Set code overview to %04X:%04X",codeSeg,codeOfs); + DEBUG_ShowMsg("DEBUG: Set code overview to %04X:%04X",codeSeg,codeOfs); codeViewData.useCS = codeSeg; codeViewData.useEIP = codeOfs; return true; @@ -848,22 +947,22 @@ bool ParseCommand(char* str) found++; dataSeg = GetHexValue(found,found); found++; dataOfs = GetHexValue(found,found); - DEBUG_ShowMsg(0,"DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs); + DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs); return true; } found = strstr(str,"LOG "); if (found) { // Create Cpu log file found+=4; - DEBUG_ShowMsg(0,"DEBUG: Starting log"); + DEBUG_ShowMsg("DEBUG: Starting log"); DEBUG_Log_Loop(GetHexValue(found,found)); - DEBUG_ShowMsg(0,"DEBUG: Logfile LOGCPU.TXT created."); + DEBUG_ShowMsg("DEBUG: Logfile LOGCPU.TXT created."); return true; } found = strstr(str,"SR "); if (found) { // Set register value found+=2; - if (ChangeRegister(found)) DEBUG_ShowMsg(0,"DEBUG: Set Register success."); - else DEBUG_ShowMsg(0,"DEBUG: Set Register failure."); + if (ChangeRegister(found)) DEBUG_ShowMsg("DEBUG: Set Register success."); + else DEBUG_ShowMsg("DEBUG: Set Register failure."); return true; } found = strstr(str,"SM "); @@ -876,18 +975,18 @@ bool ParseCommand(char* str) while (*found==' ') found++; if (*found) { Bit8u value = GetHexValue(found,found); found++; - mem_writeb(PhysMake(seg,ofs+count),value); + mem_writeb(GetAddress(seg,ofs+count),value); count++; } }; - DEBUG_ShowMsg(0,"DEBUG: Memory changed."); + DEBUG_ShowMsg("DEBUG: Memory changed."); return true; } found = strstr(str,"INTT "); if (found) { // Create Cpu log file found+=4; Bit8u intNr = GetHexValue(found,found); - DEBUG_ShowMsg(0,"DEBUG: Tracing INT %02X",intNr); + DEBUG_ShowMsg("DEBUG: Tracing INT %02X",intNr); Interrupt(intNr); SetCodeWinStart(); return true; @@ -896,7 +995,7 @@ bool ParseCommand(char* str) if (found) { // Create Cpu log file found+=4; Bit8u intNr = GetHexValue(found,found); - DEBUG_ShowMsg(0,"DEBUG: Starting INT %02X",intNr); + DEBUG_ShowMsg("DEBUG: Starting INT %02X",intNr); CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip, true); CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip-1,true); debugging=false; @@ -905,13 +1004,32 @@ bool ParseCommand(char* str) Interrupt(intNr); return true; } + found = strstr(str,"SELINFO "); + if (found) { + found += 8; + while (found[0]==' ') found++; + char out1[200],out2[200]; + GetDescriptorInfo(found,out1,out2); + DEBUG_ShowMsg("SelectorInfo %s:",found); + DEBUG_ShowMsg("%s",out1); + DEBUG_ShowMsg("%s",out2); + }; + +/* found = strstr(str,"EXCEPTION "); + if (found) { + found += 9; + Bit8u num = GetHexValue(found,found); + DPMI_CreateException(num,0xDD); + DEBUG_ShowMsg("Exception %04X",num); + }; +*/ #if C_HEAVY_DEBUG found = strstr(str,"HEAVYLOG"); if (found) { // Create Cpu log file logHeavy = !logHeavy; - if (logHeavy) DEBUG_ShowMsg(0,"DEBUG: Heavy cpu logging on."); - else DEBUG_ShowMsg(0,"DEBUG: Heavy cpu logging off."); + if (logHeavy) DEBUG_ShowMsg("DEBUG: Heavy cpu logging on."); + else DEBUG_ShowMsg("DEBUG: Heavy cpu logging off."); return true; } #endif @@ -950,6 +1068,7 @@ bool ParseCommand(char* str) wprintw(dbg.win_out,"LV [seg]:[off] [name] - Load var list from file\n"); 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,"H - Help\n"); wrefresh(dbg.win_out); @@ -958,7 +1077,7 @@ bool ParseCommand(char* str) return false; }; -char* AnalyzeInstruction(char* inst) +char* AnalyzeInstruction(char* inst, bool saveSelector) { static char result[256]; @@ -1001,19 +1120,28 @@ char* AnalyzeInstruction(char* inst) } else pos++; }; - switch (DasmLastOperandSize()) { - case 8 : { Bit8u val = mem_readb( PhysMake (seg,adr) ); - sprintf(result,"%s:[%04X]=%02X",prefix,adr,val); + 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( PhysMake (seg,adr) ); - sprintf(result,"%s:[%04X]=%04X",prefix,adr,val); + case 16: { Bit16u val = mem_readw(address); + outmask[12] = '4'; + sprintf(result,outmask,prefix,adr,val); } break; - case 32: { Bit32u val = mem_readd( PhysMake (seg,adr) ); - sprintf(result,"%s:[%04X]=%08X",prefix,adr,val); + case 32: { Bit32u val = mem_readd(address); + outmask[12] = '8'; + sprintf(result,outmask,prefix,adr,val); } break; } +// } // Variable found ? - CDebugVar* var = CDebugVar::FindVar(PhysMake(seg,adr)); + CDebugVar* var = CDebugVar::FindVar(address); if (var) { // Replace occurance char* pos1 = strchr(inst,'['); @@ -1026,6 +1154,10 @@ char* AnalyzeInstruction(char* inst) strcat(inst,temp); // add end }; }; + // show descriptor info, if available + if ((cpu.pmode) && saveSelector) { + strcpy(curSelectorName,prefix); + }; }; return result; }; @@ -1106,7 +1238,7 @@ Bit32u DEBUG_CheckKeys(void) { ParseCommand(codeViewData.inputStr); break; case 'T' : DEBUG_RaiseTimerIrq(); - DEBUG_ShowMsg(0,"Debug: Timer Int started."); + DEBUG_ShowMsg("Debug: Timer Int started."); break; case 'V' : showExtend = !showExtend; break; @@ -1125,11 +1257,12 @@ Bit32u DEBUG_CheckKeys(void) { break; case KEY_F(5): // Run Programm debugging=false; - CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); + CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true); + ignoreAddressOnce = SegPhys(cs)+reg_eip; DOSBOX_SetNormalLoop(); break; case KEY_F(9): // Set/Remove TBreakpoint - { PhysPt ptr = PhysMake(codeViewData.cursorSeg,codeViewData.cursorOfs); + { PhysPt ptr = GetAddress(codeViewData.cursorSeg,codeViewData.cursorOfs); if (CBreakpoint::IsBreakpoint(ptr)) CBreakpoint::DeleteBreakpoint(ptr); else CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false); } @@ -1137,26 +1270,25 @@ Bit32u DEBUG_CheckKeys(void) { case KEY_F(10): // Step over inst if (StepOver()) return 0; else { + exitLoop = false; skipFirstInstruction = true; // for heavy debugger CPU_Cycles = 1; Bitu ret=(*cpudecoder)(); + if (ret>0) ret=(*CallBack_Handlers[ret])(); SetCodeWinStart(); CBreakpoint::ignoreOnce = 0; } break; case KEY_F(11): // trace into + exitLoop = false; skipFirstInstruction = true; // for heavy debugger CPU_Cycles = 1; ret = (*cpudecoder)(); + if (ret>0) ret=(*CallBack_Handlers[ret])(); SetCodeWinStart(); CBreakpoint::ignoreOnce = 0; break; - -// default: -// // FIXME : Is this correct ? -// if (key<0x200) ret=(*cpudecoder)(1); -// break; - }; + } DEBUG_DrawScreen(); } return ret; @@ -1176,7 +1308,6 @@ Bitu DEBUG_Loop(void) { DOSBOX_SetNormalLoop(); return 0; } - return DEBUG_CheckKeys(); } @@ -1189,9 +1320,9 @@ void DEBUG_Enable(void) { } void DEBUG_DrawScreen(void) { - DrawRegisters(); DrawData(); DrawCode(); + DrawRegisters(); } static void DEBUG_RaiseTimerIrq(void) { PIC_ActivateIRQ(0); @@ -1201,19 +1332,21 @@ static void LogInstruction(Bit16u segValue, Bit32u eipValue, char* buffer) { static char empty[15] = { 32,32,32,32,32,32,32,32,32,32,32,32,32,32,0 }; - PhysPt start = PhysMake(segValue,eipValue); + PhysPt start = GetAddress(segValue,eipValue); char dline[200];Bitu size; - size = DasmI386(dline, start, reg_eip, false); + size = DasmI386(dline, start, reg_eip, cpu.code.big); Bitu len = strlen(dline); char* res = empty; if (showExtend) { - res = AnalyzeInstruction(dline); + res = AnalyzeInstruction(dline,false); if (!res || (strlen(res)==0)) res = empty; }; if (len<30) for (Bitu i=0; i<30-len; i++) strcat(dline," "); // Get register values - sprintf(buffer,"%04X:%08X %s %s EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X EBP:%08X ESP:%08X DS:%04X ES:%04X FS:%04X GS:%04X SS:%04X CF:%01X ZF:%01X SF:%01X OF:%01X AF:%01X PF:%01X\n",segValue,eipValue,dline,res,reg_eax,reg_ebx,reg_ecx,reg_edx,reg_esi,reg_edi,reg_ebp,reg_esp,SegValue(ds),SegValue(es),SegValue(fs),SegValue(gs),SegValue(ss),get_CF(),get_ZF(),get_SF(),get_OF(),get_AF(),get_PF()); + + sprintf(buffer,"%04X:%08X %s %s EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X EBP:%08X ESP:%08X DS:%04X ES:%04X FS:%04X GS:%04X SS:%04X CF:%01X ZF:%01X SF:%01X OF:%01X AF:%01X PF:%01X\n",segValue,eipValue,dline,res,reg_eax,reg_ebx,reg_ecx,reg_edx,reg_esi,reg_edi,reg_ebp,reg_esp,SegValue(ds),SegValue(es),SegValue(fs),SegValue(gs),SegValue(ss), + GETFLAGBOOL(CF),GETFLAGBOOL(ZF),GETFLAGBOOL(SF),GETFLAGBOOL(OF),GETFLAGBOOL(AF),GETFLAGBOOL(PF)); }; static bool DEBUG_Log_Loop(int count) { @@ -1237,7 +1370,8 @@ static bool DEBUG_Log_Loop(int count) { CPU_Cycles = 1; ret=(*cpudecoder)(); - + if (ret>0) ret=(*CallBack_Handlers[ret])(); + count--; if (count==0) break; @@ -1312,6 +1446,13 @@ void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off) }; }; +Bitu DEBUG_EnableDebugger(void) +{ + exitLoop = true; + DEBUG_Enable(); + return 0; +}; + static void DEBUG_ProgramStart(Program * * make) { *make=new DEBUG; } @@ -1347,6 +1488,8 @@ static void DEBUG_ShutDown(Section * sec) #endif }; +Bitu debugCallback; + void DEBUG_Init(Section* sec) { MSG_Add("DEBUG_CONFIGFILE_HELP","Nothing to setup yet!\n"); @@ -1358,6 +1501,9 @@ void DEBUG_Init(Section* sec) { memset((void*)&codeViewData,0,sizeof(codeViewData)); /* setup debug.com */ PROGRAMS_MakeFile("DEBUG.COM",DEBUG_ProgramStart); + /* Setup callback */ + debugCallback=CALLBACK_Allocate(); + CALLBACK_Setup(debugCallback,DEBUG_EnableDebugger,CB_RETF); /* shutdown function */ sec->AddDestroyFunction(&DEBUG_ShutDown); } @@ -1441,7 +1587,7 @@ void SaveMemory(Bit16u seg, Bit16u ofs1, Bit32s num) { FILE* f = fopen("MEMDUMP.TXT","wt"); if (!f) { - DEBUG_ShowMsg(0,"DEBUG: Memory dump failed."); + DEBUG_ShowMsg("DEBUG: Memory dump failed."); return; } @@ -1452,7 +1598,7 @@ void SaveMemory(Bit16u seg, Bit16u ofs1, Bit32s num) sprintf(buffer,"%04X:%04X ",seg,ofs1); for (Bit16u x=0; x<16; x++) { - sprintf (temp,"%02X ",mem_readb(PhysMake(seg,ofs1+x))); + sprintf (temp,"%02X ",mem_readb(GetAddress(seg,ofs1+x))); strcat (buffer,temp); }; ofs1+=16; @@ -1461,14 +1607,14 @@ void SaveMemory(Bit16u seg, Bit16u ofs1, Bit32s num) fprintf(f,"%s\n",buffer); }; fclose(f); - DEBUG_ShowMsg(0,"DEBUG: Memory dump success."); + DEBUG_ShowMsg("DEBUG: Memory dump success."); }; // HEAVY DEBUGGING STUFF #if C_HEAVY_DEBUG -const Bit32u LOGCPUMAX = 200; +const Bit32u LOGCPUMAX = 20000; static Bit16u logCpuCS [LOGCPUMAX]; static Bit32u logCpuEIP[LOGCPUMAX]; @@ -1494,11 +1640,11 @@ void DEBUG_HeavyWriteLogInstruction(void) logHeavy = false; - DEBUG_ShowMsg(0,"DEBUG: Creating cpu log LOGCPU_INT_CD.TXT"); + DEBUG_ShowMsg("DEBUG: Creating cpu log LOGCPU_INT_CD.TXT"); FILE* f = fopen("LOGCPU_INT_CD.TXT","wt"); if (!f) { - DEBUG_ShowMsg(0,"DEBUG: Failed."); + DEBUG_ShowMsg("DEBUG: Failed."); return; } @@ -1511,7 +1657,7 @@ void DEBUG_HeavyWriteLogInstruction(void) fclose(f); - DEBUG_ShowMsg(0,"DEBUG: Done."); + DEBUG_ShowMsg("DEBUG: Done."); }; bool DEBUG_HeavyIsBreakpoint(void) @@ -1523,14 +1669,13 @@ bool DEBUG_HeavyIsBreakpoint(void) skipFirstInstruction = false; return false; } - PhysPt where = SegPhys(cs)+reg_eip; - if (CBreakpoint::CheckBreakpoint(where)) { - exitLoop = true; - DEBUG_Enable(); - return true; - }; + 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 897a4c6..11aa326 100644 --- a/src/debug/debug_disasm.cpp +++ b/src/debug/debug_disasm.cpp @@ -116,8 +116,6 @@ static int modrmv; /* flag for getting modrm byte */ static int sibv; /* flag for getting sib byte */ static int opsize; /* just like it says ... */ static int addrsize; -static int addr20bit=0; -static int addr24bit=0; static int addr32bit=0; /* some defines for extracting instruction bit fields from bytes */ @@ -444,13 +442,8 @@ static char *addr_to_hex(UINT32 addr, int splitup) { else #endif - if (addr20bit) { - sprintf(buffer, "%05X", addr&0xfffff ); - } else if (addr24bit) { - sprintf(buffer, "%06X", addr&0xffffff ); - } else if (addr32bit) { - sprintf(buffer, "%08X", addr ); - } + sprintf(buffer, "%08X", addr ); + } return buffer; @@ -837,12 +830,12 @@ static void percent(char type, char subtype) break; case 'C': /* reg(r/m) picks control reg */ - uprintf("C%d", REG(modrm())); + uprintf("CR%d", REG(modrm())); must_do_size = 0; break; case 'D': /* reg(r/m) picks debug reg */ - uprintf("D%d", REG(modrm())); + uprintf("DR%d", REG(modrm())); must_do_size = 0; break; @@ -874,7 +867,6 @@ static void percent(char type, char subtype) vofs = (INT16)vofs; name = addr_to_hex(vofs+instruction_offset+INSTRUCTION_SIZE,0); break; -#if 0 /* i386 */ case 4: vofs = (UINT32)getbyte(); /* yuk! */ @@ -883,7 +875,6 @@ static void percent(char type, char subtype) vofs |= (UINT32)getbyte() << 24; name = addr_to_hex(vofs+instruction_offset+INSTRUCTION_SIZE,1); break; -#endif } if (vofs<0) uprintf("%s ($-%x)", name, -vofs); @@ -920,7 +911,7 @@ static void percent(char type, char subtype) break; case 'R': /* mod(r/m) picks register */ - reg_name(REG(modrm()), subtype); /* rh */ + reg_name(RM(modrm()), subtype); /* rh */ must_do_size = 0; break; @@ -1087,7 +1078,7 @@ Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32) ubufp = buffer; first_space = 1; - addr32bit=1;addr20bit=addr24bit=0; + addr32bit=1; prefix = 0; modrmv = sibv = -1; /* set modrm and sib flags */ diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index e5b06b1..840233c 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.cpp @@ -37,28 +37,36 @@ struct _LogGroup { bool enabled; }; -namespace { - _LogGroup loggrp[LOG_MAX]={"",true,0}; - - FILE* debuglog; -}; +static _LogGroup loggrp[LOG_MAX]={{"",true},{0,false}}; +static FILE* debuglog; extern int old_cursor_state; -void DEBUG_ShowMsg(Bit32u entry, char * format,...) { - - if (!(entry & LOG_ERROR) && entry && !loggrp[entry].enabled) return; - char buf[1024]; - strcpy(buf,loggrp[entry&127].front); + + +void DEBUG_ShowMsg(char * format,...) { + + char buf[512]; va_list msg; va_start(msg,format); - vsprintf(&buf[strlen(buf)],format,msg); + vsprintf(buf,format,msg); va_end(msg); wprintw(dbg.win_out,"%10d: %s\n",cycle_count,buf); wrefresh(dbg.win_out); if(debuglog) fprintf(debuglog,"%10d: %s\n",cycle_count,buf); } +void LOG::operator() (char* format, ...){ + char buf[512]; + va_list msg; + va_start(msg,format); + vsprintf(buf,format,msg); + va_end(msg); + + if (d_type>=LOG_MAX) return; + if ((d_severity!=LOG_ERROR) && (!loggrp[d_type].enabled)) return; + DEBUG_ShowMsg("%s:%s",loggrp[d_type].front,buf); +} static void Draw_RegisterLayout(void) { @@ -148,7 +156,8 @@ static void LOG_Init(Section * sec) { char buf[1024]; for (Bitu i=1;iGet_bool(buf); } } @@ -156,30 +165,34 @@ static void LOG_Init(Section * sec) { void LOG_StartUp(void) { /* Setup logging groups */ - loggrp[LOG_VGA].front="VGA:"; - loggrp[LOG_VGAGFX].front="VGAGFX:"; - loggrp[LOG_VGAMISC].front="VGAMISC:"; - loggrp[LOG_INT10].front="INT10:"; - loggrp[LOG_SB].front="SBLASTER:"; - loggrp[LOG_DMA].front="DMA:"; + loggrp[LOG_ALL].front="ALL"; + loggrp[LOG_VGA].front="VGA"; + loggrp[LOG_VGAGFX].front="VGAGFX"; + loggrp[LOG_VGAMISC].front="VGAMISC"; + loggrp[LOG_INT10].front="INT10"; + loggrp[LOG_SB].front="SBLASTER"; + loggrp[LOG_DMA].front="DMA"; - loggrp[LOG_FPU].front="FPU:"; - loggrp[LOG_CPU].front="CPU:"; + loggrp[LOG_FPU].front="FPU"; + loggrp[LOG_CPU].front="CPU"; + loggrp[LOG_PAGING].front="PAGING"; - loggrp[LOG_FCB].front="FCB:"; - loggrp[LOG_FILES].front="FILES:"; - loggrp[LOG_IOCTL].front="IOCTL:"; + loggrp[LOG_FCB].front="FCB"; + loggrp[LOG_FILES].front="FILES"; + loggrp[LOG_IOCTL].front="IOCTL"; loggrp[LOG_EXEC].front="EXEC"; - loggrp[LOG_DOSMISC].front="DOSMISC:"; + loggrp[LOG_DOSMISC].front="DOSMISC"; - loggrp[LOG_PIT].front="PIT:"; - loggrp[LOG_KEYBOARD].front="KEYBOARD:"; - loggrp[LOG_PIC].front="PIC:"; + loggrp[LOG_PIT].front="PIT"; + loggrp[LOG_KEYBOARD].front="KEYBOARD"; + loggrp[LOG_PIC].front="PIC"; - loggrp[LOG_MOUSE].front="MOUSE:"; - loggrp[LOG_BIOS].front="BIOS:"; - loggrp[LOG_GUI].front="GUI:"; - loggrp[LOG_MISC].front="MISC:"; + loggrp[LOG_MOUSE].front="MOUSE"; + loggrp[LOG_BIOS].front="BIOS"; + loggrp[LOG_GUI].front="GUI"; + loggrp[LOG_MISC].front="MISC"; + + loggrp[LOG_IO].front="IO"; /* Register the log section */ Section_prop * sect=control->AddSection_prop("log",LOG_Init); @@ -187,7 +200,6 @@ void LOG_StartUp(void) { char buf[1024]; for (Bitu i=1;iAdd_bool(buf,true); } diff --git a/src/debug/debug_inc.h b/src/debug/debug_inc.h index 880f7ea..e3d5834 100644 --- a/src/debug/debug_inc.h +++ b/src/debug/debug_inc.h @@ -51,7 +51,7 @@ struct DASMLine { extern DBGBlock dbg; - /* Local Debug Stuff */ Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32); -int DasmLastOperandSize(void); \ No newline at end of file +int DasmLastOperandSize(void); + diff --git a/src/debug/debug_win32.cpp b/src/debug/debug_win32.cpp index 28f9471..cfed35e 100644 --- a/src/debug/debug_win32.cpp +++ b/src/debug/debug_win32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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. */ +#ifdef WIN32 + #include #include #include @@ -66,9 +68,7 @@ static void ResizeConsole( HANDLE hConsole, SHORT xSize, SHORT ySize ) { void WIN32_Console() { + AllocConsole(); ResizeConsole(GetStdHandle(STD_OUTPUT_HANDLE),80,50); - - } - - +#endif diff --git a/src/dos/Makefile.in b/src/dos/Makefile.in index cd07e0c..4b63d39 100644 --- a/src/dos/Makefile.in +++ b/src/dos/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,77 +13,122 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libdos.a @@ -95,6 +140,7 @@ libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioc cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp subdir = src/dos +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -111,11 +157,7 @@ am_libdos_a_OBJECTS = dos.$(OBJEXT) dos_devices.$(OBJEXT) \ cdrom_ioctl_win32.$(OBJEXT) cdrom_aspi_win32.$(OBJEXT) libdos_a_OBJECTS = $(am_libdos_a_OBJECTS) -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/cdrom.Po \ @@ -136,14 +178,12 @@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ -CFLAGS = @CFLAGS@ 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 = $(libdos_a_SOURCES) -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libdos_a_SOURCES) all: all-am @@ -190,26 +230,35 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_virtual.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drives.Po@am__quote@ -distclean-depend: - -rm -rf ./$(DEPDIR) - .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -235,20 +284,41 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -273,7 +343,6 @@ check: check-am all-am: Makefile $(LIBRARIES) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -293,7 +362,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -303,9 +372,11 @@ clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am @@ -326,6 +397,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -333,18 +406,25 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags distdir dvi \ - dvi-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/dos/cdrom.cpp b/src/dos/cdrom.cpp index 86cf831..6d8febe 100644 --- a/src/dos/cdrom.cpp +++ b/src/dos/cdrom.cpp @@ -66,46 +66,43 @@ bool CDROM_Interface_SDL::SetDevice (char* path, int forceCD) bool CDROM_Interface_SDL::GetAudioTracks (int& stTrack, int& end, TMSF& leadOut) { - SDL_CDStatus(cd); - if (CD_INDRIVE(cd->status)) { + + if (CD_INDRIVE(SDL_CDStatus(cd))) { stTrack = 1; end = cd->numtracks; FRAMES_TO_MSF(cd->track[cd->numtracks].offset,&leadOut.min,&leadOut.sec,&leadOut.fr); } - return CD_INDRIVE(cd->status); + return CD_INDRIVE(SDL_CDStatus(cd)); }; bool CDROM_Interface_SDL::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) { - SDL_CDStatus(cd); - if (CD_INDRIVE(cd->status)) { + if (CD_INDRIVE(SDL_CDStatus(cd))) { FRAMES_TO_MSF(cd->track[track-1].offset+150,&start.min,&start.sec,&start.fr); attr = cd->track[track-1].type; } - return CD_INDRIVE(cd->status); + return CD_INDRIVE(SDL_CDStatus(cd)); }; bool CDROM_Interface_SDL::GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) { - SDL_CDStatus(cd); - if (CD_INDRIVE(cd->status)) { + if (CD_INDRIVE(SDL_CDStatus(cd))) { track = cd->cur_track; index = cd->cur_track; attr = cd->track[track].type; FRAMES_TO_MSF(cd->cur_frame,&relPos.min,&relPos.sec,&relPos.fr); FRAMES_TO_MSF(cd->cur_frame+cd->track[track].offset,&absPos.min,&absPos.sec,&absPos.fr); } - return CD_INDRIVE(cd->status); + return CD_INDRIVE(SDL_CDStatus(cd)); }; bool CDROM_Interface_SDL::GetAudioStatus (bool& playing, bool& pause) { - SDL_CDStatus(cd); - if (CD_INDRIVE(cd->status)) { + if (CD_INDRIVE(SDL_CDStatus(cd))) { playing = (cd->status==CD_PLAYING); pause = (cd->status==CD_PAUSED); } - return CD_INDRIVE(cd->status); + return CD_INDRIVE(SDL_CDStatus(cd)); }; bool CDROM_Interface_SDL::GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) @@ -124,7 +121,7 @@ bool CDROM_Interface_SDL::PlayAudioSector (unsigned long start,unsigned long len // Has to be there, otherwise wrong cd status report (dunno why, sdl bug ?) SDL_CDClose(cd); cd = SDL_CDOpen(driveID); - bool success = (SDL_CDPlay(cd,start,len)==0); + bool success = (SDL_CDPlay(cd,start+150,len)==0); return success; }; @@ -169,7 +166,7 @@ int CDROM_GetMountType(char* path, int forceCD) int num = SDL_CDNumDrives(); // If cd drive is forced then check if its in range and return 0 if ((forceCD>=0) && (forceCD +#include "mem.h" #include "SDL.h" #define RAW_SECTOR_SIZE 2352 @@ -40,7 +41,7 @@ public: virtual bool PauseAudio (bool resume) = 0; virtual bool StopAudio (void) = 0; - virtual bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num) = 0; + virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0; virtual bool LoadUnloadMedia (bool unload) = 0; }; @@ -61,7 +62,7 @@ public: bool PlayAudioSector (unsigned long start,unsigned long len); bool PauseAudio (bool resume); bool StopAudio (void); - bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num) { return true; }; + bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; }; bool LoadUnloadMedia (bool unload); private: @@ -86,7 +87,7 @@ public: bool PlayAudioSector (unsigned long start,unsigned long len) { return true; }; bool PauseAudio (bool resume) { return true; }; bool StopAudio (void) { return true; }; - bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num) { return true; }; + bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return true; }; bool LoadUnloadMedia (bool unload) { return true; }; }; @@ -117,7 +118,7 @@ public: bool PauseAudio (bool resume); bool StopAudio (void); - bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num); + bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num); bool LoadUnloadMedia (bool unload); @@ -164,7 +165,7 @@ public: bool PauseAudio (bool resume); bool StopAudio (void); - bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num); + bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num); bool LoadUnloadMedia (bool unload); diff --git a/src/dos/cdrom_aspi_win32.cpp b/src/dos/cdrom_aspi_win32.cpp index 33d8c2a..c3ed83c 100644 --- a/src/dos/cdrom_aspi_win32.cpp +++ b/src/dos/cdrom_aspi_win32.cpp @@ -92,13 +92,13 @@ BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID) if (sd.SRB_Status == SS_COMP) { if (sd.SRB_DeviceType == DTYPE_CDROM) { if ((target==j) && (lun==k)) { - LOG(LOG_MISC,"SCSI: Getting Hardware vendor."); + LOG(LOG_MISC,LOG_NORMAL)("SCSI: Getting Hardware vendor."); // "Hardware ID = vendor" match ? char vendor[64]; if (GetVendor(i,target,lun,vendor)) { - LOG(LOG_MISC,"SCSI: Vendor : %s",vendor); + LOG(LOG_MISC,LOG_NORMAL)("SCSI: Vendor : %s",vendor); if (strstr(strupr(hardwareID),strupr(vendor))) { - LOG(LOG_MISC,"SCSI: Host Adapter found: %d",i); + LOG(LOG_MISC,LOG_NORMAL)("SCSI: Host Adapter found: %d",i); return i; } }; @@ -108,7 +108,7 @@ BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID) } } } - LOG(LOG_ERROR,"SCSI: Host Adapter not found: %d",i); + LOG(LOG_MISC,LOG_ERROR)("SCSI: Host Adapter not found: %d",i); return 0; }; @@ -131,16 +131,16 @@ bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase) newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey); if (newKeyResult==ERROR_SUCCESS) { if (GetRegistryValue(hNewKey,"CurrentDriveLetterAssignment",buffer,256)) { - LOG(LOG_MISC,"SCSI: Drive Letter found: %s",buffer); + LOG(LOG_MISC,LOG_NORMAL)("SCSI: Drive Letter found: %s",buffer); // aha, something suspicious... if (buffer[0]==letter) { char hardwareID[256]; // found it... lets see if we can get the scsi values bool v1 = GetRegistryValue(hNewKey,"SCSILUN",buffer,256); - LOG(LOG_MISC,"SCSI: SCSILUN found: %s",buffer); + LOG(LOG_MISC,LOG_NORMAL)("SCSI: SCSILUN found: %s",buffer); lun = buffer[0]-'0'; bool v2 = GetRegistryValue(hNewKey,"SCSITargetID",buffer,256); - LOG(LOG_MISC,"SCSI: SCSITargetID found: %s",buffer); + LOG(LOG_MISC,LOG_NORMAL)("SCSI: SCSITargetID found: %s",buffer); target = buffer[0]-'0'; bool v3 = GetRegistryValue(hNewKey,"HardwareID",hardwareID,256); RegCloseKey(hNewKey); @@ -667,7 +667,7 @@ bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaCha return true; }; -bool CDROM_Interface_Aspi::ReadSectors(void* buffer, bool raw, unsigned long sector, unsigned long num) +bool CDROM_Interface_Aspi::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { SRB_ExecSCSICmd s;DWORD dwStatus; @@ -675,12 +675,8 @@ bool CDROM_Interface_Aspi::ReadSectors(void* buffer, bool raw, unsigned long sec memset(&s,0,sizeof(s)); - // FIXME : Is there a method to get cooked sectors with aspi ??? - // all combination i tried were failing. - // so we have to allocate extra mem and copy data to buffer if in cooked mode - char* inPtr = (char*)buffer; - if (!raw) inPtr = new char[num*2352]; - if (!inPtr) return false; + Bitu buflen = raw?2352*num:2048*num; + Bit8u* bufdata = new Bit8u[buflen]; s.SRB_Cmd = SC_EXEC_SCSI_CMD; s.SRB_HaId = haId; @@ -689,8 +685,8 @@ bool CDROM_Interface_Aspi::ReadSectors(void* buffer, bool raw, unsigned long sec s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; s.SRB_SenseLen = SENSE_LEN; - s.SRB_BufLen = 2352*num; //num*(raw?2352:2048); - s.SRB_BufPointer = (BYTE FAR*)inPtr; + s.SRB_BufLen = buflen; + s.SRB_BufPointer = (BYTE FAR*)bufdata; s.SRB_CDBLen = 12; s.SRB_PostProc = (LPVOID)hEvent; @@ -712,24 +708,12 @@ bool CDROM_Interface_Aspi::ReadSectors(void* buffer, bool raw, unsigned long sec CloseHandle(hEvent); - if (s.SRB_Status!=SS_COMP) { - if (!raw) delete[] inPtr; - return false; - } + // Copy to PhysPt + MEM_BlockWrite(buffer,bufdata,buflen); - if (!raw) { - // copy user data to buffer - char* source = inPtr; - source+=16; // jump 16 bytes - char* outPtr = (char*)buffer; - for (unsigned long i=0; i #include // Ioctl stuff +#include #include "ntddcdrm.h" // Ioctl stuff #include "cdrom.h" @@ -37,6 +38,7 @@ CDROM_Interface_Ioctl::CDROM_Interface_Ioctl() CDROM_Interface_Ioctl::~CDROM_Interface_Ioctl() { StopAudio(); + Close(); }; bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc) @@ -47,12 +49,12 @@ bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc) bool CDROM_Interface_Ioctl::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) { - Open(); +// Open(); CDROM_TOC toc; DWORD byteCount; BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &byteCount,NULL); - Close(); +// Close(); if (!bStat) return false; stTrack = toc.FirstTrack; @@ -65,12 +67,12 @@ bool CDROM_Interface_Ioctl::GetAudioTracks(int& stTrack, int& endTrack, TMSF& le bool CDROM_Interface_Ioctl::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) { - Open(); +// Open(); CDROM_TOC toc; DWORD byteCount; BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &byteCount,NULL); - Close(); +// Close(); if (!bStat) return false; attr = (toc.TrackData[track-1].Adr << 4) | toc.TrackData[track].Control; @@ -82,7 +84,7 @@ bool CDROM_Interface_Ioctl::GetAudioTrackInfo(int track, TMSF& start, unsigned c bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) { - Open(); +// Open(); CDROM_SUB_Q_DATA_FORMAT insub; SUB_Q_CHANNEL_DATA sub; @@ -92,7 +94,7 @@ bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& trac BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), &sub, sizeof(sub), &byteCount,NULL); - Close(); +// Close(); if (!bStat) return false; attr = (sub.CurrentPosition.ADR << 4) | sub.CurrentPosition.Control; @@ -110,7 +112,7 @@ bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& trac bool CDROM_Interface_Ioctl::GetAudioStatus(bool& playing, bool& pause) { - Open(); +// Open(); CDROM_SUB_Q_DATA_FORMAT insub; SUB_Q_CHANNEL_DATA sub; @@ -120,7 +122,7 @@ bool CDROM_Interface_Ioctl::GetAudioStatus(bool& playing, bool& pause) BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), &sub, sizeof(sub), &byteCount,NULL); - Close(); +// Close(); if (!bStat) return false; playing = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS); @@ -138,6 +140,10 @@ bool CDROM_Interface_Ioctl::GetMediaTrayStatus(bool& mediaPresent, bool& mediaCh mediaPresent = GetAudioTracks(track1, track2, leadOut), trayOpen = !mediaPresent; mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr); + if (mediaChanged) { + // Open new media + Close(); Open(); + }; // Save old values oldLeadOut.min = leadOut.min; oldLeadOut.sec = leadOut.sec; @@ -148,7 +154,7 @@ bool CDROM_Interface_Ioctl::GetMediaTrayStatus(bool& mediaPresent, bool& mediaCh bool CDROM_Interface_Ioctl::PlayAudioSector (unsigned long start,unsigned long len) { - Open(); +// Open(); CDROM_PLAY_AUDIO_MSF audio; DWORD byteCount; // Start @@ -164,79 +170,79 @@ bool CDROM_Interface_Ioctl::PlayAudioSector (unsigned long start,unsigned long l BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF, &audio, sizeof(audio), NULL, 0, &byteCount,NULL); - Close(); +// Close(); return bStat>0; }; bool CDROM_Interface_Ioctl::PauseAudio(bool resume) { - Open(); +// Open(); BOOL bStat; DWORD byteCount; if (resume) bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RESUME_AUDIO, NULL, 0, NULL, 0, &byteCount,NULL); else bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, NULL, 0, &byteCount,NULL); - Close(); +// Close(); return bStat>0; }; bool CDROM_Interface_Ioctl::StopAudio(void) { - Open(); +// Open(); BOOL bStat; DWORD byteCount; bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO, NULL, 0, NULL, 0, &byteCount,NULL); - Close(); +// Close(); return bStat>0; }; bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) { - Open(); +// Open(); BOOL bStat; DWORD byteCount; if (unload) bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &byteCount,NULL); else bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &byteCount,NULL); - Close(); +// Close(); return bStat>0; }; -bool CDROM_Interface_Ioctl::ReadSectors(void* buffer, bool raw, unsigned long sector, unsigned long num) +bool CDROM_Interface_Ioctl::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { - // TODO : How to copy cooked without current overhead ? - BOOL bStat; - DWORD byteCount; - RAW_READ_INFO in; - char* inPtr; + BOOL bStat; + DWORD byteCount = 0; - in.DiskOffset.LowPart = sector; - in.DiskOffset.HighPart = 0; - in.SectorCount = num; - in.TrackMode = CDDA; - - if (!raw) inPtr = new char[num*RAW_SECTOR_SIZE]; - else inPtr = (char*)buffer; +// Open(); - bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in), - inPtr, num*RAW_SECTOR_SIZE, &byteCount,NULL); + Bitu buflen = raw ? num*RAW_SECTOR_SIZE : num*COOKED_SECTOR_SIZE; + Bit8u* bufdata = new Bit8u[buflen]; if (!raw) { - char* source = inPtr; - source+=16; // jump 16 bytes - char* outPtr = (char*)buffer; - for (unsigned long i=0; i0); + // Cooked + int success = 0; + DWORD newPos = SetFilePointer(hIOCTL, sector*COOKED_SECTOR_SIZE, 0, FILE_BEGIN); + if (newPos != 0xFFFFFFFF) success = ReadFile(hIOCTL, bufdata, buflen, &byteCount, NULL); + bStat = (success!=0); + } else { + // Raw + RAW_READ_INFO in; + in.DiskOffset.LowPart = sector; + in.DiskOffset.HighPart = 0; + in.SectorCount = num; + in.TrackMode = CDDA; + bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in), + bufdata, buflen, &byteCount,NULL); + } +// Close(); + + MEM_BlockWrite(buffer,bufdata,buflen); + delete[] bufdata; + + return (byteCount==buflen) && (bStat>0); } bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) @@ -247,7 +253,7 @@ bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) strcpy(pathname,"\\\\.\\"); strcat(pathname,letter); if (Open()) { - Close(); +// Close(); return true; }; } diff --git a/src/dos/dev_con.h b/src/dos/dev_con.h index 6059a86..f9e4b97 100644 --- a/src/dos/dev_con.h +++ b/src/dos/dev_con.h @@ -16,8 +16,11 @@ * 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 $ */ + #include "dos_inc.h" #include "../ints/int10.h" +#include #define NUMBER_ANSI_DATA 10 @@ -35,6 +38,7 @@ private: struct ansi { /* should create a constructor which fills them with the appriorate values */ bool esc; bool sci; + bool enabled; Bit8u attr; Bit8u data[NUMBER_ANSI_DATA]; Bit8u numberofarg; @@ -45,8 +49,6 @@ private: } ansi; }; -void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page); -void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page); bool device_CON::Read(Bit8u * data,Bit16u * size) { Bit16u oldax=reg_ax; @@ -54,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,0); + INT10_TeletypeOutput(cache,7,false); } cache=0; @@ -69,8 +71,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { *size=count; reg_ax=oldax; if(dos.echo) { - INT10_TeletypeOutput(13,7,false,0); //maybe don't do this ( no need for it actually ) (but it's compatible) - INT10_TeletypeOutput(10,7,false,0); + INT10_TeletypeOutput(13,7,false); //maybe don't do this ( no need for it actually ) (but it's compatible) + INT10_TeletypeOutput(10,7,false); } return true; break; @@ -78,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,0); - INT10_TeletypeOutput(' ',7,false,0); + INT10_TeletypeOutput(8,7,false); + INT10_TeletypeOutput(' ',7,false); } else { continue; //no data read yet so restart whileloop. } @@ -96,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,0); + INT10_TeletypeOutput(reg_al,7,false); } } *size=count; @@ -108,9 +110,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) { bool device_CON::Write(Bit8u * data,Bit16u * size) { Bit16u count=0; Bitu i; - Bit8s col,row; - static bool ansiwarned=false; - + Bit8u col,row; + Bit8u tempdata; while (*size>count) { if (!ansi.esc){ if(data[count]=='\033') { @@ -119,19 +120,16 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { /* start the sequence */ ansi.esc=true; count++; - if(!ansiwarned) { - LOG(LOG_IOCTL,"ANSI sequences detected. enabling ansi support"); /* maybe LOG_MSG */ - ansiwarned=true; - } continue; } else { - INT10_TeletypeOutput(data[count],ansi.attr,true,0); - count++; - continue; + // pass attribute only if ansi is enabled + INT10_TeletypeOutput(data[count],ansi.attr,ansi.enabled); + count++; + continue; }; }; - /* ansi.esc=true */ + if(!ansi.sci){ switch(data[count]){ @@ -143,7 +141,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { case 'D':/* scrolling DOWN*/ case 'M':/* scrolling UP*/ default: - LOG(LOG_IOCTL,"ANSI: unknown char %c after a esc",data[count]); /*prob () */ + LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unknown char %c after a esc",data[count]); /*prob () */ ClearAnsi(); break; } @@ -170,22 +168,23 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { break; case 'm': /* SGR */ for(i=0;i<=ansi.numberofarg;i++){ - + ansi.enabled=true; switch(ansi.data[i]){ case 0: /* normal */ ansi.attr=0x7; + ansi.enabled=false; break; case 1: /* bold mode on*/ ansi.attr|=0x8; break; case 4: /* underline */ - LOG(LOG_IOCTL,"ANSI:no support for underline yet"); + LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet"); break; case 5: /* blinking */ - LOG(LOG_IOCTL,"ANSI:no support for blinking yet"); + LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for blinking yet"); break; case 7: /* reverse */ - LOG(LOG_IOCTL,"ANSI:no support for reverse yet"); + LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for reverse yet"); break; case 30: /* fg color black */ ansi.attr&=0xf8; @@ -265,45 +264,64 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),0); /*ansi=1 based, int10 is 0 based */ ClearAnsi(); break; + /* cursor up down and forward and backward only change the row or the col not both */ case 'A': /* cursor up*/ col=CURSOR_POS_COL(0) ; - row=CURSOR_POS_ROW(0) - (ansi.data[0]? ansi.data[0] : 1); + row=CURSOR_POS_ROW(0) ; + tempdata = (ansi.data[0]? ansi.data[0] : 1); + if(tempdata > row) + { row=0; } + else + { row-=tempdata;} + INT10_SetCursorPos(row,col,0); + ClearAnsi(); + break; + case 'B': /*cursor Down */ + col=CURSOR_POS_COL(0) ; + row=CURSOR_POS_ROW(0) ; + tempdata = (ansi.data[0]? ansi.data[0] : 1); + if(tempdata + static_cast(row) >= ansi.nrows) + { row = ansi.nrows - 1;} + else + { row += tempdata; } + INT10_SetCursorPos(row,col,0); + ClearAnsi(); + break; + case 'C': /*cursor forward */ + col=CURSOR_POS_COL(0); + row=CURSOR_POS_ROW(0); + tempdata=(ansi.data[0]? ansi.data[0] : 1); + if(tempdata + static_cast(col) >= ansi.ncols) + { col = ansi.ncols - 1;} + else + { col += tempdata;} INT10_SetCursorPos(row,col,0); ClearAnsi(); break; - case 'C': /*cursor forward */ - col=CURSOR_POS_COL(0) + (ansi.data[0]? ansi.data[0] : 1); + case 'D': /*Cursor Backward */ + col=CURSOR_POS_COL(0); row=CURSOR_POS_ROW(0); - while(col>=ansi.ncols) { - row++; - col = col - ansi.ncols; // should depend on linebrake mode - } + tempdata=(ansi.data[0]? ansi.data[0] : 1); + if(tempdata > col) + {col = 0;} + else + { col -= tempdata;} INT10_SetCursorPos(row,col,0); ClearAnsi(); break; case 'J': /*erase screen and move cursor home*/ if(ansi.data[0]==0) ansi.data[0]=2; if(ansi.data[0]!=2) {/* only number 2 (the standard one supported) */ - LOG(LOG_IOCTL,"ANSI: esc[%dJ called : not supported",ansi.data[0]); + 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,0); + for(i=0;i<(Bitu)ansi.ncols*ansi.nrows;i++) INT10_TeletypeOutput(' ',ansi.attr,true); ClearAnsi(); INT10_SetCursorPos(0,0,0); break; case 'h': /* set MODE (if code =7 enable linewrap) */ case 'I': /*RESET MODE */ - LOG(LOG_IOCTL,"ANSI: set/reset mode called(not supported)"); - ClearAnsi(); - break; - case 'D': /*Cursor Backward */ - col=CURSOR_POS_COL(0) - (ansi.data[0]? ansi.data[0] : 1); - row=CURSOR_POS_ROW(0); - while(col<0) { - row--; - col = col + ansi.ncols ; // should depend on linebrake mode - } - INT10_SetCursorPos(row,col,0); + LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: set/reset mode called(not supported)"); ClearAnsi(); break; case 'u': /* Restore Cursor Pos */ @@ -315,12 +333,15 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { ansi.saverow=CURSOR_POS_ROW(0); ClearAnsi(); break; - case 'K':/* erase till end of line */ + case 'K':/* erase till end of line */ + for(i = CURSOR_POS_COL(0);i<(Bitu) ansi.ncols; i++) INT10_TeletypeOutput(' ',ansi.attr,true); + ClearAnsi(); /* maybe set cursor back to starting place ???? */ + break; case 'l':/* (if code =7) disable linewrap */ case 'p':/* reassign keys (needs strings) */ case 'i':/* printer stuff */ default: - LOG(LOG_IOCTL,"ANSI: unhandled char %c in esc[",data[count]); + LOG(LOG_IOCTL,LOG_NORMAL)("ANSI: unhandled char %c in esc[",data[count]); ClearAnsi(); break; } @@ -353,13 +374,15 @@ device_CON::device_CON() { cache=0; ansi.esc=false; ansi.sci=false; + ansi.enabled=false; ansi.attr=0x7; ansi.numberofarg=0; for(Bit8u i=0; i #include #include @@ -28,7 +30,6 @@ #include "regs.h" #include "dos_inc.h" #include "setup.h" -#include "cpu.h" DOS_Block dos; DOS_InfoBlock dos_infoblock; @@ -43,6 +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)); + char name1[DOSNAMEBUF+1]; char name2[DOSNAMEBUF+1]; switch (reg_ah) { @@ -172,7 +177,7 @@ static Bitu DOS_21Handler(void) { }else{ reg_al=0xff; } - LOG(LOG_FCB,"DOS:0x0f FCB-fileopen used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x0f FCB-fileopen used, result:al=%d",reg_al); break; case 0x10: /* Close File using FCB */ if(DOS_FCBClose(SegValue(ds),reg_dx)){ @@ -180,7 +185,7 @@ static Bitu DOS_21Handler(void) { }else{ reg_al=0xff; } - LOG(LOG_FCB,"DOS:0x10 FCB-fileclose used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x10 FCB-fileclose used, result:al=%d",reg_al); break; case 0x11: /* Find First Matching File using FCB */ if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){ @@ -188,7 +193,7 @@ static Bitu DOS_21Handler(void) { }else{ reg_al=0xff; } - LOG(LOG_FCB,"DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al); break; case 0x12: /* Find Next Matching File using FCB */ if(DOS_FCBFindNext(SegValue(ds),reg_dx)){ @@ -196,7 +201,7 @@ static Bitu DOS_21Handler(void) { }else{ reg_al=0xff; } - LOG(LOG_FCB,"DOS:0x12 FCB-FindNext used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x12 FCB-FindNext used, result:al=%d",reg_al); break; case 0x13: /* Delete File using FCB */ if (DOS_FCBDeleteFile(SegValue(ds),reg_dx)) reg_al = 0x00; @@ -204,16 +209,16 @@ static Bitu DOS_21Handler(void) { break; case 0x14: /* Sequential read from FCB */ reg_al = DOS_FCBRead(SegValue(ds),reg_dx,0); - LOG(LOG_FCB,"DOS:0x14 FCB-Read used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x14 FCB-Read used, result:al=%d",reg_al); break; case 0x15: /* Sequential write to FCB */ reg_al=DOS_FCBWrite(SegValue(ds),reg_dx,0); - LOG(LOG_FCB,"DOS:0x15 FCB-Write used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x15 FCB-Write used, result:al=%d",reg_al); break; case 0x16: /* Create or truncate file using FCB */ if (DOS_FCBCreate(SegValue(ds),reg_dx)) reg_al = 0x00; else reg_al = 0xFF; - LOG(LOG_FCB,"DOS:0x16 FCB-Create used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x16 FCB-Create used, result:al=%d",reg_al); break; case 0x17: /* Rename file using FCB */ if (DOS_FCBRenameFile(SegValue(ds),reg_dx)) reg_al = 0x00; @@ -227,11 +232,11 @@ static Bitu DOS_21Handler(void) { break; case 0x21: /* Read random record from FCB */ reg_al = DOS_FCBRandomRead(SegValue(ds),reg_dx,1,true); - LOG(LOG_FCB,"DOS:0x21 FCB-Random read used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x21 FCB-Random read used, result:al=%d",reg_al); break; case 0x22: /* Write random record to FCB */ reg_al=DOS_FCBRandomWrite(SegValue(ds),reg_dx,1,true); - LOG(LOG_FCB,"DOS:0x22 FCB-Random write used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x22 FCB-Random write used, result:al=%d",reg_al); break; case 0x23: /* Get file size for FCB */ if (DOS_FCBGetFileSize(SegValue(ds),reg_dx,reg_cx)) reg_al = 0x00; @@ -242,11 +247,11 @@ static Bitu DOS_21Handler(void) { break; case 0x27: /* Random block read from FCB */ reg_al = DOS_FCBRandomRead(SegValue(ds),reg_dx,reg_cx,false); - LOG(LOG_FCB,"DOS:0x27 FCB-Random(block) read used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x27 FCB-Random(block) read used, result:al=%d",reg_al); break; case 0x28: /* Random Block write to FCB */ reg_al=DOS_FCBRandomWrite(SegValue(ds),reg_dx,reg_cx,false); - LOG(LOG_FCB,"DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al); break; case 0x29: /* Parse filename into FCB */ { Bit8u difference; @@ -255,7 +260,7 @@ static Bitu DOS_21Handler(void) { reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference); reg_si+=difference; } - LOG(LOG_FCB,"DOS:29:FCB Parse Filename, result:al=%d",reg_al); + LOG(LOG_FCB,LOG_NORMAL)("DOS:29:FCB Parse Filename, result:al=%d",reg_al); break; case 0x19: /* Get current default drive */ reg_al=DOS_GetDefaultDrive(); @@ -296,16 +301,18 @@ static Bitu DOS_21Handler(void) { case 0x2c: /* Get System Time */ //TODO Get time through bios calls date is fixed { - Bit32u ticks=mem_readd(BIOS_TIMER); - Bit32u seconds=(ticks*10)/182; +/* Calculate how many miliseconds have passed */ + Bitu ticks=5*mem_readd(BIOS_TIMER); + ticks = ((ticks / 59659u) << 16) + ((ticks % 59659u) << 16) / 59659u; + Bitu seconds=(ticks/100); reg_ch=(Bit8u)(seconds/3600); reg_cl=(Bit8u)((seconds % 3600)/60); reg_dh=(Bit8u)(seconds % 60); - reg_dl=(Bit8u)(((ticks * 10) % 182)*100)/182; + reg_dl=(Bit8u)(ticks % 100); } break; case 0x2d: /* Set System Time */ - LOG(LOG_ERROR,"DOS:Set System Time not supported"); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set System Time not supported"); reg_al=0; /* Noone is changing system time */ break; case 0x2e: /* Set Verify flag */ @@ -322,16 +329,12 @@ static Bitu DOS_21Handler(void) { reg_ah=dos.version.minor; break; case 0x31: /* Terminate and stay resident */ -//TODO First get normal files executing + //TODO First get normal files executing + // Important: This service does not set the carry flag! DOS_ResizeMemory(dos.psp,®_dx); - if (DOS_Terminate(true)) { - dos.return_code=reg_al; - dos.return_mode=RETURN_TSR; - CALLBACK_SCF(false); - } else { - reg_ax=dos.errorcode; - CALLBACK_SCF(true); - } + DOS_Terminate(true); + dos.return_code=reg_al; + dos.return_mode=RETURN_TSR; break; case 0x33: /* Extended Break Checking */ switch (reg_al) { @@ -383,7 +386,7 @@ static Bitu DOS_21Handler(void) { case 3: reg_al=0;break; }; - LOG(LOG_ERROR|LOG_MISC,"DOS:0x37:Call for not supported switchchar"); + LOG(LOG_MISC,LOG_ERROR)("DOS:0x37:Call for not supported switchchar"); break; case 0x38: /* Set Country Code */ if (reg_al==0) { /* Get country specidic information */ @@ -403,7 +406,7 @@ static Bitu DOS_21Handler(void) { CALLBACK_SCF(false); break; } else { /* Set country code */ - LOG(LOG_ERROR|LOG_MISC,"DOS:Setting country code not supported"); + LOG(LOG_MISC,LOG_ERROR)("DOS:Setting country code not supported"); } CALLBACK_SCF(true); break; @@ -523,11 +526,13 @@ static Bitu DOS_21Handler(void) { } break; case 0x01: /* Set */ - LOG(LOG_ERROR|LOG_MISC,"DOS:Set File Attributes for %s not supported",name1); + LOG(LOG_MISC,LOG_ERROR)("DOS:Set File Attributes for %s not supported",name1); CALLBACK_SCF(false); break; default: - E_Exit("DOS:0x43:Illegal subfunction %2X",reg_al); + LOG(LOG_MISC,LOG_ERROR)("DOS:0x43:Illegal subfunction %2X",reg_al); + CALLBACK_SCF(false); + break; } break; case 0x44: /* IOCTL Functions */ @@ -600,7 +605,7 @@ static Bitu DOS_21Handler(void) { case 0x4b: /* EXEC Load and/or execute program */ { MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - LOG(LOG_ERROR|LOG_MISC,"Execute %s %d",name1,reg_al); + LOG(LOG_EXEC,LOG_ERROR)("Execute %s %d",name1,reg_al); if (!DOS_Execute(name1,SegPhys(es)+reg_bx,reg_al)) { reg_ax=dos.errorcode; CALLBACK_SCF(true); @@ -654,7 +659,7 @@ static Bitu DOS_21Handler(void) { RealPt addr=dos_infoblock.GetPointer(); SegSet16(es,RealSeg(addr)); reg_bx=RealOff(addr); - LOG(LOG_MISC,"Call is made for list of lists - let's hope for the best"); + LOG(LOG_DOSMISC,LOG_NORMAL)("Call is made for list of lists - let's hope for the best"); break; } //TODO Think hard how shit this is gonna be //And will any game ever use this :) @@ -665,7 +670,7 @@ static Bitu DOS_21Handler(void) { reg_al=dos.verify?1:0; break; case 0x55: /* Create Child PSP*/ - DOS_NewPSP(reg_dx,reg_si); + DOS_ChildPSP(reg_dx,reg_si); dos.psp = reg_dx; break; case 0x56: /* RENAME Rename file */ @@ -684,11 +689,12 @@ static Bitu DOS_21Handler(void) { CALLBACK_SCF(false); } else { CALLBACK_SCF(true); - }; + } + } else if (reg_al==0x01) { + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:57:Set File Date Time Faked"); + CALLBACK_SCF(false); } else { - reg_cx=0; - reg_dx=0; - LOG(LOG_ERROR|LOG_MISC,"DOS:57:Setting File Date is faked",reg_ah); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:57:Unsupported subtion %X",reg_al); } break; case 0x58: /* Get/Set Memory allocation strategy */ @@ -708,7 +714,7 @@ static Bitu DOS_21Handler(void) { CALLBACK_SCF(true); break; default: - LOG(LOG_ERROR|LOG_MISC,"DOS:58:Not Supported Set//Get memory allocation call %X",reg_al); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:58:Not Supported Set//Get memory allocation call %X",reg_al); } break; case 0x59: /* Get Extended error information */ @@ -769,7 +775,7 @@ static Bitu DOS_21Handler(void) { case 0x65: /* Get extented country information and a lot of other useless shit*/ /* Todo maybe fully support this for now we set it standard for USA */ { - LOG(LOG_ERROR|LOG_MISC,"DOS:65:Extended country information call"); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:65:Extended country information call"); PhysPt data=SegPhys(es)+reg_di; switch (reg_al) { case 1: @@ -798,12 +804,12 @@ static Bitu DOS_21Handler(void) { } case 0x66: /* Get/Set global code page table */ if (reg_al==1) { - LOG(LOG_ERROR|LOG_MISC,"Getting global code page table"); + LOG(LOG_DOSMISC,LOG_ERROR)("Getting global code page table"); reg_bx=reg_dx=437; CALLBACK_SCF(false); break; } - LOG(LOG_DOSMISC,"DOS:Setting code page table is not supported"); + LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Setting code page table is not supported"); break; case 0x67: /* Set handle count */ /* Weird call to increase amount of file handles needs to allocate memory if >20 */ @@ -817,23 +823,29 @@ static Bitu DOS_21Handler(void) { { switch(reg_al) { case 0x00: /* Get */ - LOG(LOG_ERROR|LOG_MISC,"DOS:Get Disk serial number"); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Get Disk serial number"); CALLBACK_SCF(true); break; case 0x01: - LOG(LOG_ERROR|LOG_MISC,"DOS:Set Disk serial number"); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set Disk serial number"); default: E_Exit("DOS:Illegal Get Serial Number call %2X",reg_al); } break; } case 0x6c: /* Extended Open/Create */ - E_Exit("Unhandled Dos 21 call %02X",reg_ah); + MEM_StrCopy(SegPhys(ds)+reg_si,name1,DOSNAMEBUF); + if (DOS_OpenFileExtended(name1,reg_bx,reg_cx,reg_dx,®_ax,®_cx)) { + CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } break; case 0x71: /* Unknown probably 4dos detection */ reg_ax=0x7100; CALLBACK_SCF(true); - LOG(LOG_DOSMISC,"DOS:Windows long file name support call %2X",reg_al); + LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al); break; case 0x68: /* FFLUSH Commit file */ case 0x63: /* Weirdo double byte stuff (fails but say it succeeded) available only in MSDOS 2.25 */ @@ -854,7 +866,7 @@ static Bitu DOS_21Handler(void) { case 0x5e: /* More Network Functions */ case 0x5f: /* And Even More Network Functions */ default: - LOG(LOG_ERROR|LOG_MISC,"DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al); reg_al=0x00; /* default value */ break; }; @@ -879,27 +891,26 @@ static Bitu DOS_27Handler(void) return CBRET_NONE; } static Bitu DOS_25Handler(void) { - flags.type=t_UNKNOWN; + flags.type=0; if(Drives[reg_al]==0){ reg_ax=0x8002; - flags.cf=true; + SETFLAGBIT(CF,true); }else{ - flags.cf=false; + SETFLAGBIT(CF,false); reg_ax=0; if((reg_cx != 1) ||(reg_dx != 1)) - LOG(LOG_DOSMISC,"int 25 called but not as diskdetection"); + LOG(LOG_DOSMISC,LOG_NORMAL)("int 25 called but not as diskdetection"); } return CBRET_NONE; } static Bitu DOS_26Handler(void) { - LOG(LOG_DOSMISC,"int 26 called: hope for the best!"); - flags.type=t_UNKNOWN; + LOG(LOG_DOSMISC,LOG_NORMAL)("int 26 called: hope for the best!"); + flags.type=0; if(Drives[reg_al]==0){ - reg_ax=0x8002; - flags.cf=true; + SETFLAGBIT(CF,true); }else{ - flags.cf=false; + SETFLAGBIT(CF,false); reg_ax=0; } return CBRET_NONE; @@ -909,12 +920,12 @@ static Bitu DOS_28Handler(void) { } static Bitu DOS_29Handler(void) { - LOG(LOG_ERROR|LOG_MISC,"int 29 called"); + LOG(LOG_DOSMISC,LOG_ERROR)("int 29 called"); return CBRET_NONE; } static Bitu DOS_CaseMapFunc(void) { - //LOG(LOG_ERROR|LOG_MISC,"Case map routine called : %c",reg_al); + //LOG(LOG_DOSMISC,LOG_ERROR)("Case map routine called : %c",reg_al); return CBRET_NONE; }; @@ -925,7 +936,6 @@ void DOS_ShutDown(Section* sec) void DOS_Init(Section* sec) { - MSG_Add("DOS_CONFIGFILE_HELP","Setting a memory size to 0 will disable it.\n"); call_20=CALLBACK_Allocate(); CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET); RealSetVec(0x20,CALLBACK_RealPointer(call_20)); diff --git a/src/dos/dos_classes.cpp b/src/dos/dos_classes.cpp index 00b7cc7..668873f 100644 --- a/src/dos/dos_classes.cpp +++ b/src/dos/dos_classes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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: dos_classes.cpp,v 1.32 2003/10/09 13:47:06 finsterr Exp $ */ + #include #include #include "dosbox.h" @@ -73,6 +75,12 @@ void DOS_InfoBlock::SetfirstFileTable(RealPt _first_table){ sSave(sDIB,firstFileTable,_first_table); } +void DOS_InfoBlock::SetBuffers(Bit16u x,Bit16u y) { + sSave(sDIB,buffers_x,x); + sSave(sDIB,buffers_y,y); + +} + RealPt DOS_InfoBlock::GetPointer(void) { return RealMake(seg,offsetof(sDIB,firstDPB)); @@ -94,7 +102,9 @@ void DOS_PSP::MakeNew(Bit16u mem_size) sSave(sPSP,next_seg,seg+mem_size); /* far call opcode */ sSave(sPSP,far_call,0xea); -// sSave(sPSP,cmp_entry + // far call to interrupt 0x21 - faked for bill & ted + // lets hope nobody really uses this address + sSave(sPSP,cpm_entry,RealMake(0xDEAD,0xFFFF)); /* Standard blocks,int 20 and int21 retf */ sSave(sPSP,exit[0],0xcd); sSave(sPSP,exit[1],0x20); @@ -148,19 +158,34 @@ Bit16u DOS_PSP::FindFreeFileEntry(void) Bit16u DOS_PSP::FindEntryByHandle(Bit8u handle) { PhysPt files=Real2Phys(sGet(sPSP,file_table)); - Bit16u max = sGet(sPSP,max_files); for (Bit16u i=0;iGetFileHandle(i); - SetFileHandle(i,handle); + if(createchildpsp) + { //copy obeying not inherit flag.(but dont duplicate them) + bool allowCopy = (handle==0) || ((handle>0) && (FindEntryByHandle(handle)==0xff)); + if((handleflags & DOS_NOT_INHERIT) && allowCopy) + { + Files[handle]->AddRef(); + SetFileHandle(i,handle); + } + else + { + SetFileHandle(i,0xff); + } + } + else + { //normal copy so don't mind the inheritance + SetFileHandle(i,handle); + } } }; @@ -211,6 +236,7 @@ bool DOS_PSP::SetNumFiles(Bit16u fileNum) { if (fileNum>20) { // Allocate needed paragraphs + fileNum+=2; // Add a few more files for safety Bit16u para = (fileNum/16)+((fileNum%16)>0); RealPt data = RealMake(DOS_GetMemory(para),0); sSave(sPSP,file_table,data); @@ -230,7 +256,7 @@ void DOS_DTA::SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * pattern) { sSave(sDTA,sattr,_sattr); /* Fill with spaces */ Bitu i; - for (i=0;i<12;i++) mem_writeb(pt+offsetof(sDTA,sname)+i,' '); + for (i=0;i<11;i++) mem_writeb(pt+offsetof(sDTA,sname)+i,' '); char * find_ext; find_ext=strchr(pattern,'.'); if (find_ext) { diff --git a/src/dos/dos_devices.cpp b/src/dos/dos_devices.cpp index ae2630b..3cab0a7 100644 --- a/src/dos/dos_devices.cpp +++ b/src/dos/dos_devices.cpp @@ -19,7 +19,7 @@ #include #include "dosbox.h" #include "callback.h" -#include "cpu.h" +#include "regs.h" #include "mem.h" #include "bios.h" #include "dos_inc.h" diff --git a/src/dos/dos_execute.cpp b/src/dos/dos_execute.cpp index fa4e4ca..4c4147f 100644 --- a/src/dos/dos_execute.cpp +++ b/src/dos/dos_execute.cpp @@ -20,11 +20,13 @@ #include "dosbox.h" #include "mem.h" #include "dos_inc.h" -#include "cpu.h" +#include "regs.h" #include "callback.h" #include "debug.h" +#ifdef _MSC_VER #pragma pack(1) +#endif struct EXE_Header { Bit16u signature; /* EXE Signature MZ or ZM */ Bit16u extrabytes; /* Bytes on the last page */ @@ -41,7 +43,9 @@ struct EXE_Header { Bit16u reloctable; Bit16u overlay; } GCC_ATTRIBUTE(packed); +#ifdef _MSC_VER #pragma pack() +#endif #define MAGIC1 0x5a4d #define MAGIC2 0x4d5a @@ -91,11 +95,12 @@ bool DOS_Terminate(bool tsr) { dos.return_mode=RETURN_EXIT; Bit16u mempsp = dos.psp; + DOS_PSP curpsp(dos.psp); if (dos.psp==curpsp.GetParent()) return true; - /* Free Files owned by process */ - if (!tsr) curpsp.CloseFiles(); + if (!tsr) curpsp.CloseFiles(); + /* Get the termination address */ RealPt old22 = curpsp.GetInt22(); /* Restore vector 22,23,24 */ @@ -124,55 +129,64 @@ static bool MakeEnv(char * name,Bit16u * segment) { /* If segment to copy environment is 0 copy the caller's environment */ DOS_PSP psp(dos.psp); - Bit8u * envread,*envwrite; + PhysPt envread,envwrite; Bit16u envsize=1; bool parentenv=true; if (*segment==0) { if (!psp.GetEnvironment()) parentenv=false; //environment seg=0 - envread=HostMake(psp.GetEnvironment(),0); + envread=PhysMake(psp.GetEnvironment(),0); } else { if (!*segment) parentenv=false; //environment seg=0 - envread=HostMake(*segment,0); + envread=PhysMake(*segment,0); } if (parentenv) { - // hack to allow creation from envblock in unused mem (0xCD) - if (readw(envread)==0xCDCD) writew(envread,0x0000); - for (envsize=0; ;envsize++) { if (envsize>=MAXENV - ENV_KEEPFREE) { DOS_SetError(DOSERR_ENVIRONMENT_INVALID); return false; } - if (readw(envread+envsize)==0) break; + if (mem_readw(envread+envsize)==0) break; } envsize += 2; /* account for trailing \0\0 */ } Bit16u size=long2para(envsize+ENV_KEEPFREE); if (!DOS_AllocateMemory(segment,&size)) return false; - envwrite=HostMake(*segment,0); + envwrite=PhysMake(*segment,0); if (parentenv) { - bmemcpy(envwrite,envread,envsize); + MEM_BlockCopy(envwrite,envread,envsize); +// mem_memcpy(envwrite,envread,envsize); envwrite+=envsize; } else { - *envwrite++=0; + mem_writeb(envwrite++,0); } - *((Bit16u *) envwrite)=1; + mem_writew(envwrite,1); envwrite+=2; - - return DOS_Canonicalize(name,(char *)envwrite); -}; + char namebuf[DOS_PATHLENGTH]; + if (DOS_Canonicalize(name,namebuf)) { + MEM_BlockWrite(envwrite,namebuf,strlen(namebuf)+1); + return true; + } else return false; +} bool DOS_NewPSP(Bit16u segment, Bit16u size) { DOS_PSP psp(segment); psp.MakeNew(size); DOS_PSP psp_parent(psp.GetParent()); - psp.CopyFileTable(&psp_parent); + psp.CopyFileTable(&psp_parent,false); return true; }; +bool DOS_ChildPSP(Bit16u segment, Bit16u size) +{ + DOS_PSP psp(segment); + psp.MakeNew(size); + DOS_PSP psp_parent(psp.GetParent()); + psp.CopyFileTable(&psp_parent,true); + return true; +}; static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { /* Fix the PSP for psp and environment MCB's */ @@ -184,11 +198,11 @@ static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { DOS_PSP psp(pspseg); psp.MakeNew(memsize); psp.SetEnvironment(envseg); - /* Copy file handles */ - if (DOS_PSP::rootpsp!=dos.psp) { + /* Copy file handles //QBIX::ALWAYS COPY BUT LEFT ORIGINAL INCASE OF MISTAKES +/* if (DOS_PSP::rootpsp!=dos.psp) { */ // TODO: Improve this // If prog wasnt started from commandline copy file table (California Games 2) - DOS_PSP oldpsp(dos.psp); +/* DOS_PSP oldpsp(dos.psp); psp.CopyFileTable(&oldpsp); } else { psp.SetFileHandle(STDIN ,DOS_FindDevice("CON")); @@ -197,8 +211,11 @@ static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { psp.SetFileHandle(STDAUX,DOS_FindDevice("CON")); psp.SetFileHandle(STDNUL,DOS_FindDevice("CON")); psp.SetFileHandle(STDPRN,DOS_FindDevice("CON")); - } + } */ /* Save old DTA in psp */ + DOS_PSP oldpsp(dos.psp); + psp.CopyFileTable(&oldpsp,true); + psp.SetDTA(dos.dta); /* Setup the DTA */ dos.dta=RealMake(pspseg,0x80); @@ -215,9 +232,10 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { EXE_Header head;Bitu i; Bit16u fhandle;Bit16u len;Bit32u pos; Bit16u pspseg,envseg,loadseg,memsize,readsize; - HostPt loadaddress;RealPt relocpt; + PhysPt loadaddress;RealPt relocpt; Bitu headersize,imagesize; DOS_ParamBlock block(block_pt); + block.LoadData(); if (flags!=LOADNGO && flags!=OVERLAY && flags!=LOAD) { E_Exit("DOS:Not supported execute mode %d for file %s",flags,name); @@ -274,26 +292,27 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { else memsize=maxsize; if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory"); loadseg=pspseg+16; - /* Setup a psp */ - SetupPSP(pspseg,memsize,envseg); - SetupCMDLine(pspseg,block); } else loadseg=block.overlay.loadseg; /* Load the executable */ - loadaddress=HostMake(loadseg,0); + Bit8u * loadbuf=(Bit8u *)new Bit8u[0x10000]; + loadaddress=PhysMake(loadseg,0); if (iscom) { /* COM Load 64k - 256 bytes max */ pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET); readsize=0xffff-256; - DOS_ReadFile(fhandle,loadaddress,&readsize); + DOS_ReadFile(fhandle,loadbuf,&readsize); + MEM_BlockWrite(loadaddress,loadbuf,readsize); } else { /* EXE Load in 32kb blocks and then relocate */ pos=headersize;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET); while (imagesize>0x7FFF) { - readsize=0x8000;DOS_ReadFile(fhandle,loadaddress,&readsize); - if (readsize!=0x8000) LOG(LOG_EXEC,"Illegal header"); + readsize=0x8000;DOS_ReadFile(fhandle,loadbuf,&readsize); + MEM_BlockWrite(loadaddress,loadbuf,readsize); + if (readsize!=0x8000) LOG(LOG_EXEC,LOG_NORMAL)("Illegal header"); loadaddress+=0x8000;imagesize-=0x8000; } if (imagesize>0) { - readsize=(Bit16u)imagesize;DOS_ReadFile(fhandle,loadaddress,&readsize); - if (readsize!=imagesize) LOG(LOG_EXEC,"Illegal header"); + readsize=(Bit16u)imagesize;DOS_ReadFile(fhandle,loadbuf,&readsize); + MEM_BlockWrite(loadaddress,loadbuf,readsize); + if (readsize!=imagesize) LOG(LOG_EXEC,LOG_NORMAL)("Illegal header"); } /* Relocate the exe image */ Bit16u relocate; @@ -307,7 +326,16 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { mem_writew(address,mem_readw(address)+relocate); } } + delete[] loadbuf; DOS_CloseFile(fhandle); + + /* Setup a psp */ + if (flags!=OVERLAY) { + // Create psp after closing exe, to avoid dead file handle of exe in copied psp + SetupPSP(pspseg,memsize,envseg); + SetupCMDLine(pspseg,block); + }; + CALLBACK_SCF(false); /* Carry flag cleared for caller if successfull */ if (flags==OVERLAY) return true; /* Everything done for overlays */ RealPt csip,sssp; diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index 512f0bc..51b85d1 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.cpp @@ -16,6 +16,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* $Id: dos_files.cpp,v 1.47 2003/10/10 13:50:34 finsterr Exp $ */ + #include #include #include @@ -24,7 +26,7 @@ #include "dosbox.h" #include "bios.h" #include "mem.h" -#include "cpu.h" +#include "regs.h" #include "dos_inc.h" #include "drives.h" #include "cross.h" @@ -79,7 +81,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 '+': upname[w++]=c; break; default: @@ -110,7 +112,28 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { w=0;r++; continue; } - if (strcmp(tempdir,"..")==0) { + + Bit32u iDown, cDots; + bool dots = true; + Bit32u templen =strlen(tempdir); + for(iDown=0;(iDown < templen) && dots;iDown++) + if(tempdir[iDown] != '.') + dots = false; + + // only dots? + cDots = templen - 1; + if(dots && (cDots > 0)) + { + for(iDown=strlen(fullname)-1;iDown>=0;iDown--) + { + if(fullname[iDown]=='\\' || iDown==0) + { + lastdir = iDown; + cDots--; + if(cDots==0) + break; + } + } fullname[lastdir]=0; Bit32u t=0;lastdir=0; while (fullname[t]!=0) { @@ -121,13 +144,14 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { w=0;r++; continue; } + + lastdir=strlen(fullname); - //TODO Maybe another check for correct type because of .... stuff + if (lastdir!=0) strcat(fullname,"\\"); char * ext=strchr(tempdir,'.'); if (ext) { ext[4]=0; - Bitu blah=strlen(tempdir); if (strlen(tempdir)>12) memmove(tempdir+8,ext,5); } else tempdir[8]=0; strcat(fullname,tempdir); @@ -206,14 +230,13 @@ bool DOS_FindFirst(char * search,Bit16u attr) { } dta.SetupSearch(drive,(Bit8u)attr,pattern); if (Drives[drive]->FindFirst(dir,dta)) return true; - DOS_SetError(DOSERR_NO_MORE_FILES); + return false; } bool DOS_FindNext(void) { DOS_DTA dta(dos.dta); if (Drives[dta.GetSearchDrive()]->FindNext(dta)) return true; - DOS_SetError(DOSERR_NO_MORE_FILES); return false; } @@ -287,15 +310,15 @@ bool DOS_CloseFile(Bit16u entry) { DOS_SetError(DOSERR_INVALID_HANDLE); return false; }; -//TODO Figure this out with devices :) - - DOS_PSP psp(dos.psp); - if (entry>STDPRN) psp.SetFileHandle(entry,0xff); - /* Devices won't allow themselves to be closed or killed */ - if (Files[handle]->Close()) { - delete Files[handle]; - Files[handle]=0; + if (Files[handle]->Close()) + { //if close succesfull => delete file/update psp + DOS_PSP psp(dos.psp); + psp.SetFileHandle(entry,0xff); + if (Files[handle]->RemoveRef()<=0) { + delete Files[handle]; + Files[handle]=0; + } } return true; } @@ -324,6 +347,7 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) { } bool foundit=Drives[drive]->FileCreate(&Files[handle],fullname,attributes); if (foundit) { + Files[handle]->AddRef(); psp.SetFileHandle(*entry,handle); return true; } else { @@ -333,9 +357,9 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) { 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,"file open command %X file %s",flags,name); - flags&=3; + if (flags>2) LOG(LOG_FILES,LOG_ERROR)("Special file open command %X file %s",flags,name); + else LOG(LOG_FILES,LOG_NORMAL)("file open command %X file %s",flags,name); + DOS_PSP psp(dos.psp); Bit8u handle=DOS_FindDevice((char *)name); bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i; @@ -366,6 +390,12 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) { bool exists=false; if (!device) exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags); if (exists || device ) { + // devices can only be opened once + if (device && (psp.FindEntryByHandle(handle)!=0xff)) { + *entry=psp.FindEntryByHandle(handle); + return true; + } + Files[handle]->AddRef(); psp.SetFileHandle(*entry,handle); return true; } else { @@ -374,6 +404,32 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) { } } +bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status) +// FIXME: Not yet supported : Bit 13 of flags (int 0x24 on critical error +{ + Bit16u result = 0; + if (DOS_OpenFile(name, (Bit8u)flags, entry)) { + // File already exists + switch (action & 0x0f) { + case 0x00 : return false; // failed + case 0x01 : result = 1; break; // file open (already done) + case 0x02 : DOS_CloseFile(*entry); // replace + if (!DOS_CreateFile(name, flags, entry)) return false; + result = 3; + break; + default : E_Exit("DOS: OpenFileExtended: Unknown action."); + }; + } else { + // File doesnt exist + if ((action & 0xf0)==0) return false; + // Create File + if (!DOS_CreateFile(name, flags, entry)) return false; + result = 2; + }; + *status = result; + return true; +}; + bool DOS_UnlinkFile(char * name) { char fullname[DOS_PATHLENGTH];Bit8u drive; if (!DOS_MakeName(name,fullname,&drive)) return false; @@ -414,6 +470,13 @@ bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * cl } bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { + + // Dont duplicate console handles + if (entry<=STDPRN) { + *newentry = entry; + return true; + }; + Bit8u handle=RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); @@ -429,11 +492,19 @@ bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); return false; } + Files[handle]->AddRef(); psp.SetFileHandle(*newentry,handle); return true; }; bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) { + + // Dont duplicate console handles + if (entry<=STDPRN) { + newentry = entry; + return true; + }; + Bit8u orig=RealHandle(entry); if (orig>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); @@ -453,6 +524,7 @@ bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) { return false; }; DOS_PSP psp(dos.psp); + Files[orig]->AddRef(); psp.SetFileHandle(newentry,(Bit8u)entry); return true; }; @@ -478,14 +550,6 @@ bool DOS_CreateTempFile(char * name,Bit16u * entry) { return true; } - - -static bool FCB_MakeName2 (DOS_FCB & fcb, char* outname, Bit8u* outdrive){ - char short_name[DOS_FCBNAME]; - fcb.GetName(short_name); - return DOS_MakeName(short_name,outname, outdrive); -} - #define FCB_SEP ":.;,=+" #define ILLEGAL ":.;,=+ \t/\"[]<>|" @@ -494,13 +558,6 @@ static bool isvalid(const char in){ return (Bit8u(in)>0x1F) && (!strchr(ill,in)); } -static void vullen (char* veld,char* pveld){ - for(Bitu i=(pveld-veld);iIsOpen() && Files[i]->IsName(fullname)) { handle = psp.FindEntryByHandle(i); if (handle==0xFF) { // This shouldnt happen - LOG(LOG_FILES|LOG_ERROR,"DOS: File %s is opened but has no psp entry.",shortname); + LOG(LOG_FILES,LOG_ERROR)("DOS: File %s is opened but has no psp entry.",shortname); return false; } fcb.FileOpen((Bit8u)handle); diff --git a/src/dos/dos_ioctl.cpp b/src/dos/dos_ioctl.cpp index 57d4494..c3a2896 100644 --- a/src/dos/dos_ioctl.cpp +++ b/src/dos/dos_ioctl.cpp @@ -16,17 +16,15 @@ * 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 $ */ + #include #include "dosbox.h" #include "callback.h" #include "mem.h" -#include "cpu.h" +#include "regs.h" #include "dos_inc.h" -#define MAX_DEVICE 20 -static DOS_File * dos_devices[MAX_DEVICE]; - - bool DOS_IOCTL(void) { Bitu handle;Bit8u drive; if (reg_al<8) { /* call 0-7 use a file handle */ @@ -44,8 +42,26 @@ bool DOS_IOCTL(void) { case 0x00: /* Get Device Information */ reg_dx=Files[handle]->GetInformation(); return true; + case 0x06: /* Get Input Status */ + if (Files[handle]->GetInformation() & 0x8000) { //Check for device + reg_al=(Files[handle]->GetInformation() & 0x40) ? 0x0 : 0xff; + } else { // FILE + Bit32u oldlocation=0; + Files[handle]->Seek(&oldlocation, DOS_SEEK_CUR); + Bit32u endlocation=0; + Files[handle]->Seek(&endlocation, DOS_SEEK_END); + if(oldlocation < endlocation){//Still data available + reg_al=0xff; + } else + { + reg_al=0x0; //EOF or beyond + } + Files[handle]->Seek(&oldlocation, DOS_SEEK_SET); //restore filelocation + LOG(LOG_IOCTL,LOG_NORMAL)("06:Used Get Input Status on regualar file with handle %d",handle); + } + return true; case 0x07: /* Get Output Status */ - LOG(LOG_IOCTL,"DOS:IOCTL:07:Fakes output status is ready for handle %d",handle); + LOG(LOG_IOCTL,LOG_NORMAL)("07:Fakes output status is ready for handle %d",handle); reg_al=0xff; return true; case 0x08: /* Check if block device removable */ @@ -58,6 +74,17 @@ bool DOS_IOCTL(void) { DOS_SetError(DOSERR_INVALID_DRIVE); return false; } + case 0x09: /* Check if block device remote */ + drive=reg_bl;if (!drive) drive=dos.current_drive;else drive--; + if (Drives[drive]) { + reg_dx=0; + //TODO Cdrom drives are remote + //TODO Set bit 9 on drives that don't support direct I/O + return true; + } else { + DOS_SetError(DOSERR_INVALID_DRIVE); + return false; + } case 0x0D: /* Generic block device request */ { PhysPt ptr = SegPhys(ds)+reg_dx; @@ -71,7 +98,7 @@ bool DOS_IOCTL(void) { mem_writeb(ptr+6,0x00); // media type (00=other type) break; default : - LOG(LOG_IOCTL|LOG_ERROR,"DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive); + LOG(LOG_IOCTL,LOG_ERROR)("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive); return false; } return true; @@ -86,15 +113,8 @@ bool DOS_IOCTL(void) { return false; } break; - case 0x06: /* Get Input Status */ - if(reg_bx==0x00) { /* might work for other handles, but tested it only for STDIN */ - if(Files[handle]->GetInformation() & 0x40) reg_al=0x00; else - reg_al=0xFF; - return true; - break; - } default: - LOG(LOG_DOSMISC|LOG_ERROR,"DOS:IOCTL Call %2X unhandled",reg_al); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:IOCTL Call %2X unhandled",reg_al); return false; }; return false; diff --git a/src/dos/dos_misc.cpp b/src/dos/dos_misc.cpp index e054215..33b56f1 100644 --- a/src/dos/dos_misc.cpp +++ b/src/dos/dos_misc.cpp @@ -44,7 +44,7 @@ static Bitu INT2F_Handler(void) { if ((*loop_multiplex->handler)()) return CBRET_NONE; loop_multiplex=loop_multiplex->next; } - LOG(LOG_ERROR,"DOS:Multiplex Unhandled call %4X",reg_ax); + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Multiplex Unhandled call %4X",reg_ax); return CBRET_NONE; }; diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index e4e1383..26a2cb9 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -18,11 +18,12 @@ #include #include -#include "cpu.h" +#include "regs.h" #include "callback.h" #include "dos_system.h" #include "dos_inc.h" #include "setup.h" +#include "support.h" #include "cdrom.h" @@ -61,7 +62,9 @@ public: void SetStrategy (Bit16u ofs) { sSave(sDeviceHeader,strategy,ofs); }; public: + #ifdef _MSC_VER #pragma pack(1) + #endif struct sDeviceHeader{ RealPt nextDeviceHeader; Bit16u devAttributes; @@ -72,7 +75,9 @@ public: Bit8u driveLetter; Bit8u numSubUnits; } TDeviceHeader; + #ifdef _MSC_VER #pragma pack() + #endif }; class CMscdex @@ -97,10 +102,11 @@ public: int AddDrive (Bit16u _drive, char* physicalPath, Bit8u& subUnit); void GetDrives (PhysPt data); void GetDriverInfo (PhysPt data); - bool GetCopyrightName (Bit16u drive, PhysPt data) { return false; }; - bool GetAbstractName (Bit16u drive, PhysPt data) { return false; }; - bool GetDocumentationName(Bit16u drive, PhysPt data) { return false; }; - bool ReadVTOC (Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error) { return false; }; + bool GetVolumeName (Bit8u subUnit, char* name); + bool GetCopyrightName (Bit16u drive, PhysPt data); + bool GetAbstractName (Bit16u drive, PhysPt data); + bool GetDocumentationName(Bit16u drive, PhysPt data); + 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); bool ReadSectorsMSF (Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, PhysPt data); @@ -222,43 +228,40 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) // Get Mounttype and init needed cdrom interface switch (CDROM_GetMountType(physicalPath,forceCD)) { case 0x00 : { - LOG(LOG_MISC,"MSCDEX: Mounting physical cdrom: %s" ,physicalPath); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting physical cdrom: %s" ,physicalPath); #if defined (WIN32) // Check OS OSVERSIONINFO osi; osi.dwOSVersionInfoSize = sizeof(osi); GetVersionEx(&osi); if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) { - // WIN NT/200/XP - if (useCdromInterface==CDROM_USE_ASPI) { - cdrom[numDrives] = new CDROM_Interface_Aspi(); - LOG(LOG_MISC,"MSCDEX: ASPI Interface."); - break; - } else if (useCdromInterface==CDROM_USE_IOCTL) { + // only WIN NT/200/XP + if (useCdromInterface==CDROM_USE_IOCTL) { cdrom[numDrives] = new CDROM_Interface_Ioctl(); - LOG(LOG_MISC,"MSCDEX: IOCTL Interface."); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: IOCTL Interface."); break; } - } else { - // Win 95/98/ME - always use ASPI + } + if (useCdromInterface==CDROM_USE_ASPI) { + // all Wins - ASPI cdrom[numDrives] = new CDROM_Interface_Aspi(); - LOG(LOG_MISC,"MSCDEX: ASPI Interface."); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: ASPI Interface."); break; } #endif cdrom[numDrives] = new CDROM_Interface_SDL(); - LOG(LOG_MISC,"MSCDEX: SDL Interface."); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: SDL Interface."); } break; case 0x01 : // iso cdrom interface // FIXME: Not yet supported - LOG(LOG_MISC|LOG_ERROR,"MSCDEX: Mounting iso file as cdrom: %s" ,physicalPath); + LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Mounting iso file as cdrom: %s" ,physicalPath); cdrom[numDrives] = new CDROM_Interface_Fake; return 2; break; case 0x02 : // fake cdrom interface (directories) cdrom[numDrives] = new CDROM_Interface_Fake; - LOG(LOG_MISC,"MSCDEX: Mounting directory as cdrom: %s",physicalPath); - LOG(LOG_MISC,"MSCDEX: You wont have full MSCDEX support !"); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: Mounting directory as cdrom: %s",physicalPath); + LOG(LOG_MISC,LOG_NORMAL)("MSCDEX: You wont have full MSCDEX support !"); result = 5; break; default : // weird result @@ -271,7 +274,9 @@ int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit) devHeader.SetNumSubUnits(devHeader.GetNumSubUnits()+1); dinfo[numDrives].drive = (Bit8u)_drive; dinfo[numDrives].physDrive = toupper(physicalPath[0]); - numDrives++; + numDrives++; + // stop audio + StopAudio(subUnit); return result; } return 4; @@ -288,6 +293,7 @@ void CMscdex::GetDriverInfo (PhysPt data) bool CMscdex::GetCDInfo(Bit8u subUnit, Bit8u& tr1, Bit8u& tr2, TMSF& leadOut) { + if (subUnit>=numDrives) return false; int tr1i,tr2i; dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioTracks(tr1i,tr2i,leadOut); if (!dinfo[subUnit].lastResult) { @@ -302,6 +308,7 @@ bool CMscdex::GetCDInfo(Bit8u subUnit, Bit8u& tr1, Bit8u& tr2, TMSF& leadOut) bool CMscdex::GetTrackInfo(Bit8u subUnit, Bit8u track, Bit8u& attr, TMSF& start) { + if (subUnit>=numDrives) return false; dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioTrackInfo(track,start,attr); if (!dinfo[subUnit].lastResult) { attr = 0; @@ -312,6 +319,7 @@ bool CMscdex::GetTrackInfo(Bit8u subUnit, Bit8u track, Bit8u& attr, TMSF& start) bool CMscdex::PlayAudioSector(Bit8u subUnit, Bit32u sector, Bit32u length) { + if (subUnit>=numDrives) return false; // If value from last stop is used, this is meant as a resume // better start using resume command if (dinfo[subUnit].audioPaused && (sector==dinfo[subUnit].audioStart)) { @@ -330,19 +338,17 @@ bool CMscdex::PlayAudioSector(Bit8u subUnit, Bit32u sector, Bit32u length) bool CMscdex::PlayAudioMSF(Bit8u subUnit, Bit32u start, Bit32u length) { + if (subUnit>=numDrives) return false; Bit8u min = (start>>16) & 0xFF; Bit8u sec = (start>> 8) & 0xFF; Bit8u fr = (start>> 0) & 0xFF; - Bit32u sector = min*60*76+sec*75+fr - 150; - min = (length>>16) & 0xFF; - sec = (length>> 8) & 0xFF; - fr = (length>> 0) & 0xFF; - Bit32u seclen = min*60*76+sec*75+fr - 150; - return dinfo[subUnit].lastResult = PlayAudioSector(subUnit,sector,seclen); + Bit32u sector = min*60*75+sec*75+fr - 150; + return dinfo[subUnit].lastResult = PlayAudioSector(subUnit,sector,length); }; bool CMscdex::GetSubChannelData(Bit8u subUnit, Bit8u& attr, Bit8u& track, Bit8u &index, TMSF& rel, TMSF& abs) { + if (subUnit>=numDrives) return false; dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioSub(attr,track,index,rel,abs); if (!dinfo[subUnit].lastResult) { attr = track = index = 0; @@ -354,6 +360,7 @@ bool CMscdex::GetSubChannelData(Bit8u subUnit, Bit8u& attr, Bit8u& track, Bit8u bool CMscdex::GetAudioStatus(Bit8u subUnit, bool& playing, bool& pause, TMSF& start, TMSF& end) { + if (subUnit>=numDrives) return false; dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioStatus(playing,pause); if (dinfo[subUnit].lastResult) { // Start @@ -378,6 +385,7 @@ bool CMscdex::GetAudioStatus(Bit8u subUnit, bool& playing, bool& pause, TMSF& st bool CMscdex::StopAudio(Bit8u subUnit) { + if (subUnit>=numDrives) return false; if (dinfo[subUnit].audioPlay) dinfo[subUnit].lastResult = cdrom[subUnit]->PauseAudio(false); else dinfo[subUnit].lastResult = cdrom[subUnit]->StopAudio(); @@ -385,7 +393,7 @@ bool CMscdex::StopAudio(Bit8u subUnit) if (dinfo[subUnit].audioPlay) { TMSF pos; GetCurrentPos(subUnit,pos); - dinfo[subUnit].audioStart = pos.min*60*76+pos.sec*75+pos.fr - 150; + dinfo[subUnit].audioStart = pos.min*60*75+pos.sec*75+pos.fr - 150; dinfo[subUnit].audioPaused = true; } else { dinfo[subUnit].audioPaused = false; @@ -399,11 +407,13 @@ bool CMscdex::StopAudio(Bit8u subUnit) bool CMscdex::ResumeAudio(Bit8u subUnit) { + if (subUnit>=numDrives) return false; return dinfo[subUnit].lastResult = PlayAudioSector(subUnit,dinfo[subUnit].audioStart,dinfo[subUnit].audioEnd); }; Bit32u CMscdex::GetVolumeSize(Bit8u subUnit) { + if (subUnit>=numDrives) return false; Bit8u tr1,tr2; TMSF leadOut; dinfo[subUnit].lastResult = GetCDInfo(subUnit,tr1,tr2,leadOut); @@ -411,24 +421,100 @@ Bit32u CMscdex::GetVolumeSize(Bit8u subUnit) return 0; }; +bool CMscdex::ReadVTOC(Bit16u drive, Bit16u volume, PhysPt data, Bit16u& error) +{ + ReadSectors(GetSubUnit(drive),false,/*150+*/16,1,data) ? error=0:error=MSCDEX_ERROR_DRIVE_NOT_READY; + return (error==0); +}; + +bool CMscdex::GetVolumeName(Bit8u subUnit, char* data) +{ + if (subUnit>=numDrives) return false; + Bit16u drive = dinfo[subUnit].drive; + + Bit16u error,seg,size = 128; + bool success = false; + if (DOS_AllocateMemory(&seg,&size)) { + PhysPt ptoc = PhysMake(seg,0); + success = ReadVTOC(drive,0x00,ptoc,error); + if (success) { + MEM_StrCopy(ptoc+40,data,31); + data[31] = 0; + rtrim(data); + }; + DOS_FreeMemory(seg); + } + return success; +}; + +bool CMscdex::GetCopyrightName(Bit16u drive, PhysPt data) +{ + Bit16u error,seg,size = 128; + bool success = false; + if (DOS_AllocateMemory(&seg,&size)) { + PhysPt ptoc = PhysMake(seg,0); + success = ReadVTOC(drive,0x00,ptoc,error); + if (success) { + MEM_BlockCopy(data,ptoc+702,37); + mem_writeb(data+37,0); + }; + DOS_FreeMemory(seg); + } + return success; +}; + +bool CMscdex::GetAbstractName(Bit16u drive, PhysPt data) +{ + Bit16u error,seg,size = 128; + bool success = false; + if (DOS_AllocateMemory(&seg,&size)) { + PhysPt ptoc = PhysMake(seg,0); + success = ReadVTOC(drive,0x00,ptoc,error); + if (success) { + MEM_BlockCopy(data,ptoc+739,37); + mem_writeb(data+37,0); + }; + DOS_FreeMemory(seg); + } + return success; +}; + +bool CMscdex::GetDocumentationName(Bit16u drive, PhysPt data) +{ + Bit16u error,seg,size = 128; + bool success = false; + if (DOS_AllocateMemory(&seg,&size)) { + PhysPt ptoc = PhysMake(seg,0); + success = ReadVTOC(drive,0x00,ptoc,error); + if (success) { + MEM_BlockCopy(data,ptoc+776,37); + mem_writeb(data+37,0); + }; + DOS_FreeMemory(seg); + } + return success; +}; + bool CMscdex::GetUPC(Bit8u subUnit, Bit8u& attr, char* upc) { + if (subUnit>=numDrives) return false; return dinfo[subUnit].lastResult = cdrom[subUnit]->GetUPC(attr,&upc[0]); }; bool CMscdex::ReadSectors(Bit8u subUnit, bool raw, Bit32u sector, Bit16u num, PhysPt data) { - void* buffer = (void*)Phys2Host(data); - dinfo[subUnit].lastResult = cdrom[subUnit]->ReadSectors(buffer,raw,sector,num); + if (subUnit>=numDrives) return false; + dinfo[subUnit].lastResult = cdrom[subUnit]->ReadSectors(data,raw,sector,num); return dinfo[subUnit].lastResult; }; 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; - Bit32u sector = min*60*76+sec*75+fr - 150; + 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); }; @@ -441,6 +527,7 @@ bool CMscdex::ReadSectors(Bit16u drive, Bit32u sector, Bit16u num, PhysPt data) bool CMscdex::GetCurrentPos(Bit8u subUnit, TMSF& pos) { + if (subUnit>=numDrives) return false; TMSF rel; Bit8u attr,track,index; dinfo[subUnit].lastResult = GetSubChannelData(subUnit, attr, track, index, rel, pos); @@ -450,12 +537,14 @@ bool CMscdex::GetCurrentPos(Bit8u subUnit, TMSF& pos) bool CMscdex::GetMediaStatus(Bit8u subUnit, bool& media, bool& changed, bool& trayOpen) { + if (subUnit>=numDrives) return false; dinfo[subUnit].lastResult = cdrom[subUnit]->GetMediaTrayStatus(media,changed,trayOpen); return dinfo[subUnit].lastResult; }; Bit32u CMscdex::GetDeviceStatus(Bit8u subUnit) { + if (subUnit>=numDrives) return false; bool media,changed,trayOpen; dinfo[subUnit].lastResult = GetMediaStatus(subUnit,media,changed,trayOpen); @@ -470,6 +559,7 @@ Bit32u CMscdex::GetDeviceStatus(Bit8u subUnit) bool CMscdex::GetMediaStatus(Bit8u subUnit, Bit8u& status) { + if (subUnit>=numDrives) return false; bool media,changed,open,result; result = GetMediaStatus(subUnit,media,changed,open); status = changed ? 0xFF : 0x01; @@ -478,14 +568,17 @@ bool CMscdex::GetMediaStatus(Bit8u subUnit, Bit8u& status) bool CMscdex::LoadUnloadMedia(Bit8u subUnit, bool unload) { + if (subUnit>=numDrives) return false; dinfo[subUnit].lastResult = cdrom[subUnit]->LoadUnloadMedia(unload); return dinfo[subUnit].lastResult; }; bool CMscdex::SendDriverRequest(Bit16u drive, PhysPt data) { + Bit8u subUnit = GetSubUnit(drive); + if (subUnit>=numDrives) return false; // Get SubUnit - mem_writeb(data+1,GetSubUnit(drive)); + mem_writeb(data+1,subUnit); // Call Strategy / Interrupt MSCDEX_Strategy_Handler(); MSCDEX_Interrupt_Handler(); @@ -494,11 +587,11 @@ bool CMscdex::SendDriverRequest(Bit16u drive, PhysPt data) Bit16u CMscdex::GetStatusWord(Bit8u subUnit) { + if (subUnit>=numDrives) return 0x02; // error : Drive not ready + Bit16u status ; if (dinfo[subUnit].lastResult) status = REQUEST_STATUS_DONE; // ok - else { - status = REQUEST_STATUS_ERROR | 0x02; // error : Drive not ready - } + else status = REQUEST_STATUS_ERROR; if (dinfo[subUnit].audioPlay) { // Check if audio is still playing.... @@ -532,14 +625,14 @@ static Bitu MSCDEX_Interrupt_Handler(void) Bit8u subUnit = mem_readb(data+1); Bit8u funcNr = mem_readb(data+2); -// if (funcNr!=0x03) LOG("MSCDEX: Driver Function %02X",funcNr); +// LOG(LOG_MISC,LOG_ERROR)("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); - //if (subFuncNr!=0x0B) LOG("MSCDEX: IOCTL INPUT Subfunction %02X",subFuncNr); +// LOG(LOG_MISC,LOG_ERROR)("MSCDEX: IOCTL INPUT Subfunction %02X",subFuncNr); switch (subFuncNr) { case 0x00 : /* Get Device Header address */ mem_writed(buffer+1,RealMake(mscdex->rootDriverHeaderSeg,0)); @@ -565,7 +658,8 @@ static Bitu MSCDEX_Interrupt_Handler(void) break; case 0x09 : /* Media change ? */ Bit8u status; - mscdex->GetMediaStatus(subUnit,status); + //TEMP mscdex->GetMediaStatus(subUnit,status); + status = 1; mem_writeb(buffer+1,status); break; case 0x0A : /* Get Audio Disk info */ @@ -627,7 +721,7 @@ static Bitu MSCDEX_Interrupt_Handler(void) mem_writeb(buffer+10,0x00); break; }; - default : LOG(LOG_ERROR|LOG_MISC,"MSCDEX: Unsupported IOCTL INPUT Subfunction %02X",subFuncNr); + default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unsupported IOCTL INPUT Subfunction %02X",subFuncNr); break; } break; @@ -635,7 +729,7 @@ static Bitu MSCDEX_Interrupt_Handler(void) case 0x0C : { /* IOCTL OUTPUT */ PhysPt buffer = PhysMake(mem_readw(data+0x10),mem_readw(data+0x0E)); subFuncNr = mem_readb(buffer); - // if (subFuncNr!=0x0B) LOG("MSCDEX: IOCTL OUTPUT Subfunction %02X",subFuncNr); +// LOG(LOG_MISC,LOG_ERROR)("MSCDEX: IOCTL OUTPUT Subfunction %02X",subFuncNr); switch (subFuncNr) { case 0x00 : // Unload /eject) media mscdex->LoadUnloadMedia(subUnit,true); @@ -646,7 +740,7 @@ static Bitu MSCDEX_Interrupt_Handler(void) case 0x05 : // load media mscdex->LoadUnloadMedia(subUnit,false); break; - default : LOG(LOG_ERROR|LOG_MISC,"MSCDEX: Unsupported IOCTL OUTPUT Subfunction %02X",subFuncNr); + default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unsupported IOCTL OUTPUT Subfunction %02X",subFuncNr); break; }; break; @@ -683,7 +777,7 @@ static Bitu MSCDEX_Interrupt_Handler(void) case 0x88 : /* Resume Audio */ mscdex->ResumeAudio(subUnit); break; - default : LOG(LOG_ERROR|LOG_MISC,"MSCDEX: Unsupported Driver Request %02X",funcNr); + default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unsupported Driver Request %02X",funcNr); break; }; @@ -698,7 +792,7 @@ static bool MSCDEX_Handler(void) if (reg_ah!=0x15) return false; PhysPt data = PhysMake(SegValue(es),reg_bx); -// if (reg_ax!=0x1510) LOG("MSCEEX: INT 2F %04X",reg_ax); +// LOG(LOG_MISC,LOG_ERROR)("MSCDEX: INT 2F %04X",reg_ax); switch (reg_ax) { case 0x1500: /* Install check */ @@ -732,7 +826,7 @@ static bool MSCDEX_Handler(void) CALLBACK_SCF(true); }; return true; -/* case 0x1505: { // read vtoc + case 0x1505: { // read vtoc Bit16u error = 0; if (mscdex->ReadVTOC(reg_cx,reg_dx,data,error)) { CALLBACK_SCF(false); @@ -741,7 +835,7 @@ static bool MSCDEX_Handler(void) CALLBACK_SCF(true); }; }; - return true;*/ + return true; case 0x1508: { // read sectors Bit32u sector = (reg_si<<16)+reg_di; if (mscdex->ReadSectors(reg_cx,sector,reg_dx,data)) { @@ -767,9 +861,9 @@ static bool MSCDEX_Handler(void) mscdex->GetDrives(data); return true; case 0x1510: /* Device driver request */ - mscdex->SendDriverRequest(reg_cx,data); + mscdex->SendDriverRequest(reg_cx & 0xFF,data); return true; - default : LOG(LOG_ERROR|LOG_MISC,"MSCDEX: Unknwon call : %04X",reg_ax); + default : LOG(LOG_MISC,LOG_ERROR)("MSCDEX: Unknwon call : %04X",reg_ax); return true; }; @@ -781,7 +875,7 @@ public: device_MSCDEX() { name="MSCD001"; } bool Read (Bit8u * data,Bit16u * size) { return false;} bool Write(Bit8u * data,Bit16u * size) { - LOG(0,"Write to mscdex device"); + LOG(LOG_ALL,LOG_NORMAL)("Write to mscdex device"); return false; } bool Seek(Bit32u * pos,Bit32u type){return false;} @@ -797,6 +891,11 @@ int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit) return result; }; +bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name) +{ + return mscdex->GetVolumeName(subUnit,name); +}; + bool MSCDEX_HasMediaChanged(Bit8u subUnit) { static TMSF leadOut[MSCDEX_MAX_DRIVES]; diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 29d57d6..3d3d8d0 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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: dos_programs.cpp,v 1.20 2003/09/08 18:10:08 qbix79 Exp $ */ + #include #include #include @@ -35,6 +37,7 @@ public: void Run(void) { DOS_Drive * newdrive;char drive; + std::string label; // Show list of cdroms if (cmd->FindExist("-cd",false)) { @@ -67,14 +70,15 @@ public: if (type=="floppy") { str_size="512,1,2847,2847";/* All space free */ mediaid=0xF0; /* Floppy 1.44 media */ - } - if (type=="dir") { + } else if (type=="dir") { str_size="512,127,16513,1700"; mediaid=0xF8; /* Hard Disk */ - } - if (type=="cdrom") { + } else if (type=="cdrom") { str_size="650,127,16513,1700"; mediaid=0xF8; /* Hard Disk */ + } else { + WriteOut(MSG_Get("PROGAM_MOUNT_ILL_TYPE"),type.c_str()); + return; } cmd->FindString("-size",str_size,true); char number[20];const char * scan=str_size.c_str(); @@ -130,6 +134,9 @@ public: } else { newdrive=new localDrive(temp_line.c_str(),sizes[0],bit8size,sizes[2],sizes[3],mediaid); } + } else { + WriteOut(MSG_Get("PROGRAM_MOUNT_ILL_TYPE"),type.c_str()); + return; } if (Drives[drive-'A']) { WriteOut(MSG_Get("PROGRAM_MOUNT_ALLREADY_MOUNTED"),drive,Drives[drive-'A']->GetInfo()); @@ -141,6 +148,8 @@ public: /* Set the correct media byte in the table */ mem_writeb(Real2Phys(dos.tables.mediaid)+drive-'A',newdrive->GetMediaByte()); WriteOut("Drive %c mounted as %s\n",drive,newdrive->GetInfo()); + /* check if volume label is given */ + if (cmd->FindString("-label",label,true)) newdrive->dirCache.SetLabel(label.c_str()); return; showusage: WriteOut(MSG_Get("PROGRAM_MOUNT_USAGE")); @@ -290,6 +299,7 @@ void DOS_SetupPrograms(void) { MSG_Add("PROGRAM_MOUNT_STATUS_1","Current mounted drives are:\n"); MSG_Add("PROGRAM_MOUNT_ERROR_1","Directory %s doesn't exist.\n"); MSG_Add("PROGRAM_MOUNT_ERROR_2","%s isn't a directory\n"); + MSG_Add("PROGRAM_MOUNT_ILL_TYPE","Illegal type %s\n"); MSG_Add("PROGRAM_MOUNT_ALLREADY_MOUNTED","Drive %c already mounted with %s\n"); MSG_Add("PROGRAM_MOUNT_USAGE","Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n"); @@ -313,25 +323,26 @@ void DOS_SetupPrograms(void) { MSG_Add("PROGRAM_RESCAN_SUCCESS","Drive cache cleared.\n"); MSG_Add("PROGRAM_INTRO", - "Welcome to DOSBox, an x86 emulator with sound and graphics.\n" + "Welcome to DOSBox, an x86 emulator with sound and graphics.\n" "DOSBox creates a shell for you which looks like old plain DOS.\n" "\n" "Here are some commands to get you started:\n" "Before you can use the files located on your own filesystem,\n" "You have to mount the directory containing the files.\n" "For Windows:\n" - "mount c c:\\dosprog will create a C drive in dosbox with c:\\dosprog as contents.\n" + "\033[33mmount c c:\\dosprog\033[0m will create a C drive in dosbox with c:\\dosprog as contents.\n" "\n" - "For other platfroms:\n" - "mount c /home/user/dosprog will do the same.\n" + "For other platforms:\n" + "\033[33mmount c /home/user/dosprog\033[0m will do the same.\n" "\n" - "When the mount has succesfully completed you can type c: to go to your freshly\n" - "mounted C-drive. Typing dir there will show its contents. cd will allow you to\n" + "When the mount has succesfully completed you can type \033[33mc:\033[0m to go to your freshly\n" + "mounted C-drive. Typing \033[33mdir\033[0m there will show its contents." + " \033[33mcd\033[0m will allow you to\n" "enter a directory (recognised by the [] in a directory listing).\n" - "You can run programs/files which end with .exe .bat and .com .\n" + "You can run programs/files which end with .exe .bat and .com.\n" "\n" - "DOSBox will stop/exit without a warning if an error occured!\n" + "DOSBox will stop/exit without a warning if an error occured!\n" ); /*regular setup*/ diff --git a/src/dos/dos_tables.cpp b/src/dos/dos_tables.cpp index dc94f92..e903519 100644 --- a/src/dos/dos_tables.cpp +++ b/src/dos/dos_tables.cpp @@ -20,13 +20,17 @@ #include "mem.h" #include "dos_inc.h" +#ifdef _MSC_VER #pragma pack(1) +#endif struct DOS_TableCase { Bit16u size; Bit8u chars[256]; } GCC_ATTRIBUTE (packed); +#ifdef _MSC_VER #pragma pack () +#endif RealPt DOS_TableUpCase; RealPt DOS_TableLowCase; @@ -51,12 +55,14 @@ void DOS_SetupTables(void) { for (i=0;i +#endif + // STL stuff #include #include @@ -57,9 +64,9 @@ DOS_Drive_Cache::DOS_Drive_Cache(void) dirBase = new CFileInfo; save_dir = 0; srchNr = 0; - for (Bit32u i=0; i0) { + if (vname[vnamePos]==0) break; + if (!point && (vname[vnamePos]=='.')) { togo=4; point=true; } + label[labelPos] = vname[vnamePos]; + label[labelPos] = *upcase(&label[labelPos]); + labelPos++; vnamePos++; + togo--; + if ((togo==0) && !point) { + if (vname[vnamePos]=='.') vnamePos++; + label[labelPos]='.'; labelPos++; point=true; togo=3; + } + }; + label[labelPos]=0; +// LOG(LOG_ALL,LOG_ERROR)("CACHE: Set volume label to %s",label); +}; + Bit16u DOS_Drive_Cache::GetFreeID(CFileInfo* dir) { for (Bit32u i=0; ifileList.begin(), dir->fileList.end(), SortByName); - // Output list - user defined - switch (sortDirType) { - case ALPHABETICAL : std::sort(dir->outputList.begin(), dir->outputList.end(), SortByName); break; - case DIRALPHABETICAL : std::sort(dir->outputList.begin(), dir->outputList.end(), SortByDirName); break; - case ALPHABETICALREV : std::sort(dir->outputList.begin(), dir->outputList.end(), SortByNameRev); break; - case DIRALPHABETICALREV : std::sort(dir->outputList.begin(), dir->outputList.end(), SortByDirNameRev); break; - case NOSORT : break; - }; - - Bit16s index = GetLongName(dir,file); + Bits index = GetLongName(dir,file); if (index>=0) { Bit32u i; // Check if there are any open search dir that are affected by this... @@ -221,7 +250,6 @@ void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) // clear lists dir->fileList.clear(); dir->longNameList.clear(); - dir->outputList.clear(); dir->shortNr = 0; save_dir = 0; }; @@ -238,9 +266,9 @@ bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) char expand[CROSS_LEN] = {0}; CFileInfo* curDir = FindDirInfo(fullname,expand); - Bit16s low = 0; - Bit16s high = curDir->longNameList.size()-1; - Bit16s mid, res; + Bits low = 0; + Bits high = curDir->longNameList.size()-1; + Bits mid, res; while (low<=high) { mid = (low+high)/2; @@ -257,10 +285,10 @@ bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) Bit16u DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name) { - Bit16s foundNr = 0; - Bit16s low = 0; - Bit16s high = curDir->longNameList.size()-1; - Bit16s mid, res; + Bits foundNr = 0; + Bits low = 0; + Bits high = curDir->longNameList.size()-1; + Bits mid, res; while (low<=high) { mid = (low+high)/2; @@ -292,14 +320,14 @@ bool DOS_Drive_Cache::RemoveTrailingDot(char* shortname) return false; }; -Bit16s DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) +Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) { // Remove dot, if no extension... RemoveTrailingDot(shortName); // Search long name and return array number of element - Bit16s low = 0; - Bit16s high = curDir->fileList.size()-1; - Bit16s mid,res; + Bits low = 0; + Bits high = curDir->fileList.size()-1; + Bits mid,res; while (low<=high) { mid = (low+high)/2; res = strcmp(shortName,curDir->fileList[mid]->shortname); @@ -328,8 +356,8 @@ bool DOS_Drive_Cache::RemoveSpaces(char* str) void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info) { - Bit16s len = 0; - Bit16s lenExt = 0; + Bits len = 0; + Bits lenExt = 0; bool createShort = false; char tmpNameBuffer[CROSS_LEN]; @@ -406,7 +434,7 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* char dir [CROSS_LEN]; char work [CROSS_LEN]; - char* start = (char*)path; + const char* start = path; char* pos; CFileInfo* curDir = dirBase; Bit16u id; @@ -442,7 +470,7 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* else { strcpy(dir,start); }; // Path found - Bit16s nextDir = GetLongName(curDir,dir); + Bits nextDir = GetLongName(curDir,dir); strcat(expandedPath,dir); // Error check @@ -454,11 +482,8 @@ DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* if ((nextDir>=0) && curDir->fileList[nextDir]->isDir) { curDir = curDir->fileList[nextDir]; strcpy (curDir->orgname,dir); - strcpy (work,path); - // Cut Directory, if its only part of whole path - if (pos) work[(Bit32u)pos-(Bit32u)path] = 0; if (!IsCachedIn(curDir)) { - if (OpenDir(curDir,work,id)) { + if (OpenDir(curDir,expandedPath,id)) { char buffer[CROSS_LEN]; char * result; strcpy(buffer,dirPath); @@ -493,21 +518,23 @@ bool DOS_Drive_Cache::OpenDir(const char* path, Bit16u& id) return false; }; -bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, char* expand, Bit16u& id) +bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, const char* expand, Bit16u& id) { id = GetFreeID(dir); dirSearch[id] = dir; + char expandcopy [CROSS_LEN]; + strcpy(expandcopy,expand); // Add "/" char end[2]={CROSS_FILESPLIT,0}; - if (expand[strlen(expand)-1]!=CROSS_FILESPLIT) strcat(expand,end); + if (expandcopy[strlen(expandcopy)-1]!=CROSS_FILESPLIT) strcat(expandcopy,end); // open dir if (dirSearch[id]) { // open dir - DIR* dirp = opendir(expand); + DIR* dirp = opendir(expandcopy); if (dirp) { // Reset it.. closedir(dirp); - strcpy(dirPath,expand); + strcpy(dirPath,expandcopy); free[id] = false; return true; } @@ -531,7 +558,6 @@ void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name) CreateShortName(dir, info); // Put file in lists dir->fileList.push_back(info); - dir->outputList.push_back(info); }; bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) @@ -556,14 +582,6 @@ bool DOS_Drive_Cache::ReadDir(Bit16u id, char* &result) } // close dir closedir(dirp); - // Output list - user defined - switch (sortDirType) { - case ALPHABETICAL : std::sort(dirSearch[id]->outputList.begin(), dirSearch[id]->outputList.end(), SortByName); break; - case DIRALPHABETICAL : std::sort(dirSearch[id]->outputList.begin(), dirSearch[id]->outputList.end(), SortByDirName); break; - case ALPHABETICALREV : std::sort(dirSearch[id]->outputList.begin(), dirSearch[id]->outputList.end(), SortByNameRev); break; - case DIRALPHABETICALREV : std::sort(dirSearch[id]->outputList.begin(), dirSearch[id]->outputList.end(), SortByDirNameRev); break; - case NOSORT : break; - }; // Info /* if (!dirp) { LOG_DEBUG("DIR: Error Caching in %s",dirPath); @@ -584,8 +602,8 @@ bool DOS_Drive_Cache::SetResult(CFileInfo* dir, char* &result, Bit16u entryNr) static char res[CROSS_LEN]; result = res; - if (entryNr>=dir->outputList.size()) return false; - CFileInfo* info = dir->outputList[entryNr]; + if (entryNr>=dir->fileList.size()) return false; + CFileInfo* info = dir->fileList[entryNr]; // copy filename, short version strcpy(res,info->shortname); // Set to next Entry @@ -593,6 +611,73 @@ bool DOS_Drive_Cache::SetResult(CFileInfo* dir, char* &result, Bit16u entryNr) return true; }; +// FindFirst / FindNext +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 + for (Bitu n=0; ncompareCount == dtaAddress) { + // Reuse old dta + dirFindFirstID = n; break; + } + } else if (dirFindFirstID==0xffff) { + dirFindFirstID = n; + } + } + if (dirFindFirstID==0xffff) { + // no free slot found... + LOG(LOG_MISC,LOG_ERROR)("DIRCACHE: FindFirst/Next failure : All slots full."); + // always use first then + dirFindFirstID = 0; + } + // Clear and reuse slot + delete dirFindFirst[dirFindFirstID]; + 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++) { + CreateEntry(dirFindFirst[dirFindFirstID],dirSearch[dirID]->fileList[i]->orgname); + // Sort Lists - filelist has to be alphabetically sorted, even in between (for finding double file names) + std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByName); + }; + // Now re-sort the fileList accordingly to output + switch (sortDirType) { + case ALPHABETICAL : std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByName); break; + case DIRALPHABETICAL : std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByDirName); break; + case ALPHABETICALREV : std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByNameRev); break; + case DIRALPHABETICALREV : std::sort(dirFindFirst[dirFindFirstID]->fileList.begin(), dirFindFirst[dirFindFirstID]->fileList.end(), SortByDirNameRev); break; + case NOSORT : break; + }; + +// LOG(LOG_MISC,LOG_ERROR)("DIRCACHE: FindFirst : %s (ID:%02X)",path,dirFindFirstID); + id = dirFindFirstID; + return true; +}; + +bool DOS_Drive_Cache::FindNext(Bitu id, char* &result) +{ + // out of range ? + if ((id>=MAX_OPENDIRS) || !dirFindFirst[id]) { + LOG(LOG_MISC,LOG_ERROR)("DIRCACHE: FindFirst/Next failure : ID out of range: %04X",id); + return false; + } + if (!SetResult(dirFindFirst[id], result, dirFindFirst[id]->nextEntry)) { + // free slot + delete dirFindFirst[id]; dirFindFirst[id] = 0; + return false; + } + return true; +}; + // **************************************************************************** // No Dir Cache, // **************************************************************************** @@ -619,7 +704,6 @@ 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]; dirent * ent; diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index bf84f43..509d083 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -55,12 +55,13 @@ bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) { dirCache.AddEntry(newname, true); /* Make the 16 bit device information */ *file=new localFile(name,hand,0x202); + return true; }; bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { char * type; - switch (flags) { + switch (flags &3) { case OPEN_READ:type="rb"; break; case OPEN_WRITE:type="rb+"; break; case OPEN_READWRITE:type="rb+"; break; @@ -80,6 +81,7 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { // Bit32u err=errno; if (!hand) return false; *file=new localFile(name,hand,0x202); + (*file)->flags=flags; //for the inheritance flag and maybe check for others. // (*file)->SetFileName(newname); return true; }; @@ -107,10 +109,25 @@ bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { char end[2]={CROSS_FILESPLIT,0}; if (tempDir[strlen(tempDir)-1]!=CROSS_FILESPLIT) strcat(tempDir,end); - Bit16u id; - if (!dirCache.OpenDir(tempDir,id)) return false; + Bitu id; + if (!dirCache.FindFirst(tempDir,(Bitu)dos.dta,id)) + { + DOS_SetError(DOSERR_PATH_NOT_FOUND); + return false; + } strcpy(srchInfo[id].srch_dir,tempDir); dta.SetDirID(id); + + Bit8u sAttr; + dta.GetSearchParams(sAttr,tempDir); + if ((sAttr & DOS_ATTR_VOLUME) && (*_dir==0)) { + // Get Volume Label (DOS_ATTR_VOLUME) and only in basedir + if (WildFileCmp(dirCache.GetLabel(),tempDir)) { + // Get Volume Label + dta.SetResult(dirCache.GetLabel(),0,0,0,DOS_ATTR_VOLUME); + return true; + } + } return FindNext(dta); } @@ -125,10 +142,11 @@ bool localDrive::FindNext(DOS_DTA & dta) { dta.GetSearchParams(srch_attr,srch_pattern); - Bit16u id = dta.GetDirID(); + Bitu id = dta.GetDirID(); again: - if (!dirCache.ReadDir(id,dir_ent)) { + if (!dirCache.FindNext(id,dir_ent)) { + DOS_SetError(DOSERR_NO_MORE_FILES); return false; } @@ -179,6 +197,7 @@ bool localDrive::GetFileAttr(char * name,Bit16u * attr) { struct stat status; if (stat(newname,&status)==0) { *attr=DOS_ATTR_ARCHIVE; + if(status.st_mode & S_IFDIR) *attr|=DOS_ATTR_DIRECTORY; return true; } *attr=0; @@ -354,8 +373,12 @@ bool localFile::Seek(Bit32u * pos,Bit32u type) { bool localFile::Close() { - open=false; - fclose(fhandle); + // only close if one reference left + if (refCtr==1) { + fclose(fhandle); + fhandle = 0; + open = false; + }; return true; } @@ -391,6 +414,8 @@ localFile::localFile(const char* _name, FILE * handle,Bit16u devinfo) { int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit); bool MSCDEX_HasMediaChanged(Bit8u subUnit); +bool MSCDEX_GetVolumeName(Bit8u subUnit, char* name); + cdromDrive::cdromDrive(const char driveLetter, const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid, int& error) :localDrive(startdir,_bytes_sector,_sectors_cluster,_total_clusters,_free_clusters,_mediaid) @@ -398,11 +423,16 @@ cdromDrive::cdromDrive(const char driveLetter, const char * startdir,Bit16u _byt // Init mscdex error = MSCDEX_AddDrive(driveLetter,startdir,subUnit); strcpy(info,"CDRom."); + // Get Volume Label + char name[32]; + if (MSCDEX_GetVolumeName(subUnit,name)) dirCache.SetLabel(name); }; bool cdromDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { - if ((flags==OPEN_READWRITE) || (flags==OPEN_WRITE)) { + if (flags==OPEN_READWRITE) { + flags = OPEN_READ; + } else if (flags==OPEN_WRITE) { DOS_SetError(DOSERR_ACCESS_DENIED); return false; } @@ -449,13 +479,23 @@ bool cdromDrive::GetFileAttr(char * name,Bit16u * attr) bool cdromDrive::FindFirst(char * _dir,DOS_DTA & dta) { // If media has changed, reInit drivecache. - if (MSCDEX_HasMediaChanged(subUnit)) dirCache.EmptyCache(); + if (MSCDEX_HasMediaChanged(subUnit)) { + dirCache.EmptyCache(); + // Get Volume Label + char name[32]; + if (MSCDEX_GetVolumeName(subUnit,name)) dirCache.SetLabel(name); + } return localDrive::FindFirst(_dir,dta); }; void cdromDrive::SetDir(const char* path) { // If media has changed, reInit drivecache. - if (MSCDEX_HasMediaChanged(subUnit)) dirCache.EmptyCache(); + if (MSCDEX_HasMediaChanged(subUnit)) { + dirCache.EmptyCache(); + // Get Volume Label + char name[32]; + if (MSCDEX_GetVolumeName(subUnit,name)) dirCache.SetLabel(name); + } localDrive::SetDir(path); }; diff --git a/src/dos/drive_virtual.cpp b/src/dos/drive_virtual.cpp index 5243d47..64663fd 100644 --- a/src/dos/drive_virtual.cpp +++ b/src/dos/drive_virtual.cpp @@ -132,6 +132,7 @@ bool Virtual_Drive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { if (strcasecmp(name,cur_file->name)==0) { /* We have a match */ *file=new Virtual_File(cur_file->data,cur_file->size); + (*file)->flags=flags; return true; } cur_file=cur_file->next; @@ -156,6 +157,7 @@ bool Virtual_Drive::MakeDir(char * dir) { } bool Virtual_Drive::TestDir(char * dir) { + if (!dir[0]) return true; //only valid dir is the empty dir return false; } @@ -199,6 +201,7 @@ bool Virtual_Drive::FindNext(DOS_DTA & dta) { } search_file=search_file->next; } + DOS_SetError(DOSERR_NO_MORE_FILES); return false; } diff --git a/src/dos/drives.h b/src/dos/drives.h index db88226..52ddad8 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -94,6 +94,7 @@ public: bool FileExists(const char* name); bool FileStat(const char* name, FileStat_Block* const stat_block); Bit8u GetMediaByte(void); + void EmptyCache(void){} private: VFILE_Block * search_file; }; diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 5426aa9..09311a5 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -38,12 +38,12 @@ #include "support.h" Config * control; -Bitu errorlevel=1; /* The whole load of startups for all the subfunctions */ void MSG_Init(Section_prop *); void LOG_StartUp(void); void MEM_Init(Section *); +void PAGING_Init(Section *); void IO_Init(Section * ); void CALLBACK_Init(Section*); void PROGRAMS_Init(Section*); @@ -55,7 +55,9 @@ void DOS_Init(Section*); void CPU_Init(Section*); -//void FPU_Init(); +#if C_FPU +void FPU_Init(Section*); +#endif void DMA_Init(Section*); void MIXER_Init(Section*); void MIDI_Init(Section*); @@ -73,6 +75,8 @@ void PCSPEAKER_Init(Section*); void TANDYSOUND_Init(Section*); void CMS_Init(Section*); void DISNEY_Init(Section*); +void SERIAL_Init(Section*); +void MODEM_Init(Section*); void PIC_Init(Section*); void TIMER_Init(Section*); @@ -85,6 +89,8 @@ void MSCDEX_Init(Section*); /* Dos Internal mostly */ void EMS_Init(Section*); void XMS_Init(Section*); +void DPMI_Init(Section*); + void AUTOEXEC_Init(Section*); void SHELL_Init(void); @@ -92,24 +98,34 @@ void INT10_Init(Section*); static LoopHandler * loop; -Bitu RemainTicks;; -Bitu LastTicks; +Bits RemainTicks;; +Bits LastTicks; static Bitu Normal_Loop(void) { - Bitu ret,NewTicks; - while (RemainTicks) { - ret=PIC_RunQueue(); - #if C_DEBUG - if (DEBUG_ExitLoop()) return 0; - #endif - if (ret) return ret; - RemainTicks--; - TIMER_AddTick(); - GFX_Events(); + Bits ret,NewTicks; + while (1) { + if (PIC_RunQueue()) { + ret=(*cpudecoder)(); + if (ret<0) return 1; + if (ret>0) { + Bitu blah=(*CallBack_Handlers[ret])(); + if (blah) return blah; +#if C_DEBUG + if (DEBUG_ExitLoop()) return 0; +#endif + } + } else { + if (RemainTicks>0) { + TIMER_AddTick(); + RemainTicks--; + GFX_Events(); + } else goto increaseticks; + } } +increaseticks: NewTicks=GetTicks(); if (NewTicks>LastTicks) { - RemainTicks+=NewTicks-LastTicks; + RemainTicks=NewTicks-LastTicks; if (RemainTicks>20) { // LOG_DEBUG("Ticks to handle overflow %d",RemainTicks); RemainTicks=20; @@ -117,7 +133,7 @@ static Bitu Normal_Loop(void) { LastTicks=NewTicks; } //TODO Make this selectable in the config file, since it gives some lag */ - if (!RemainTicks) { + if (RemainTicks<=0) { SDL_Delay(1); return 0; } @@ -142,8 +158,7 @@ void DOSBOX_RunMachine(void){ static void DOSBOX_RealInit(Section * sec) { Section_prop * section=static_cast(sec); /* Initialize some dosbox internals */ - errorlevel=section->Get_int("warnings"); - MSG_Add("DOSBOX_CONFIGFILE_HELP","General Dosbox settings\n"); + RemainTicks=0;LastTicks=GetTicks(); DOSBOX_SetLoop(&Normal_Loop); MSG_Init(section); @@ -151,7 +166,6 @@ static void DOSBOX_RealInit(Section * sec) { void DOSBOX_Init(void) { -// Section * sec; Section_prop * secprop; Section_line * secline; @@ -160,28 +174,44 @@ void DOSBOX_Init(void) { secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit); secprop->Add_string("language",""); #if C_DEBUG - secprop->Add_int("warnings",4); LOG_StartUp(); -#else - secprop->Add_int("warnings",0); #endif - - secprop->AddInitFunction(&MEM_Init); secprop->AddInitFunction(&IO_Init); + secprop->AddInitFunction(&PAGING_Init); + secprop->AddInitFunction(&MEM_Init); + secprop->Add_int("memsize",16); secprop->AddInitFunction(&CALLBACK_Init); secprop->AddInitFunction(&PIC_Init); secprop->AddInitFunction(&PROGRAMS_Init); secprop->AddInitFunction(&TIMER_Init); secprop->AddInitFunction(&CMOS_Init); + secprop->AddInitFunction(&SERIAL_Init); + + MSG_Add("DOSBOX_CONFIGFILE_HELP", + "language -- Select another language file.\n" + "memsize -- Amount of memory dosbox has in megabytes.\n" + ); + secprop=control->AddSection_prop("render",&RENDER_Init); secprop->Add_int("frameskip",0); - secprop->Add_bool("keepsmall",false); - secprop->Add_string("snapshots","snaps"); - secprop->Add_string("scaler","none"); + secprop->Add_string("snapdir","snaps"); + 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" + "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); - + MSG_Add("CPU_CONFIGFILE_HELP", + "cycles -- Amount of instructions dosbox tries to emulate each millsecond.\n" + " Setting this higher than your machine can handle is bad!\n" + ); +#if C_FPU + secprop->AddInitFunction(&FPU_Init); +#endif secprop->AddInitFunction(&DMA_Init); secprop->AddInitFunction(&VGA_Init); secprop->AddInitFunction(&KEYBOARD_Init); @@ -190,65 +220,119 @@ void DOSBOX_Init(void) { secprop=control->AddSection_prop("mixer",&MIXER_Init); secprop->Add_bool("nosound",false); - secprop->Add_int("freq",22050); + 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" + " probably lower their sound quality.\n" + "blocksize -- Mixer block size, larger blocks might help sound stuttering\n" + " but sound will also be more lagged.\n" + "wavedir -- Directory where saved sound output goes when you use the\n" + " sound record key-combination, check README file.\n" + ); + secprop=control->AddSection_prop("midi",&MIDI_Init); secprop->AddInitFunction(&MPU401_Init); 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" + " This can be default,alsa,oss,win32,coreaudio,none.\n" + "config -- Special configuration options for the device.\n" + ); + #if C_DEBUG secprop=control->AddSection_prop("debug",&DEBUG_Init); #endif secprop=control->AddSection_prop("sblaster",&SBLASTER_Init); + secprop->Add_bool("sblaster",true); secprop->Add_hex("base",0x220); secprop->Add_int("irq",7); secprop->Add_int("dma",1); - secprop->Add_int("hdma",5); +// secprop->Add_int("hdma",5); secprop->Add_int("sbrate",22050); - secprop->Add_bool("enabled",true); - secprop->AddInitFunction(&ADLIB_Init); secprop->Add_bool("adlib",true); + secprop->Add_int("adlibrate",22050); secprop->AddInitFunction(&CMS_Init); secprop->Add_bool("cms",false); secprop->Add_int("cmsrate",22050); -// secprop=control->AddSection_prop("gus",&GUS_Init); - - secprop=control->AddSection_prop("disney",&DISNEY_Init); - secprop->Add_bool("enabled",true); + MSG_Add("SBLASTER_CONFIGFILE_HELP", + "sblaster -- Enable the soundblaster emulation.\n" + "base,irq,dma -- The IO/IRQ/DMA address of the soundblaster.\n" + "sbrate -- Sample rate of soundblaster emulation.\n" + "adlib -- Enable the adlib emulation.\n" + "adlibrate -- Sample rate of adlib emulation.\n" + "cms -- Enable the Creative Music System/Gameblaster emulation.\n" + " Enabling both the adlib and cms might give conflicts!\n" + "cmsrate -- Sample rate of cms emulation.\n" + ); secprop=control->AddSection_prop("speaker",&PCSPEAKER_Init); - secprop->Add_bool("enabled",true); + secprop->Add_bool("pcspeaker",true); secprop->Add_int("pcrate",22050); secprop->AddInitFunction(&TANDYSOUND_Init); - secprop->Add_bool("tandy",false); + secprop->Add_bool("tandy",true); + secprop->Add_int("tandyrate",22050); + secprop->AddInitFunction(&DISNEY_Init); + secprop->Add_bool("disney",true); + 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" + "tandyrate -- Sample rate of the Tandy 3-Voice generation.\n" + "disney -- Enable Disney Sound Source emulation.\n" + ); secprop=control->AddSection_prop("bios",&BIOS_Init); secprop->AddInitFunction(&INT10_Init); /* All the DOS Related stuff, which will eventually start up in the shell */ //TODO Maybe combine most of the dos stuff in one section like ems,xms secprop=control->AddSection_prop("dos",&DOS_Init); - secprop->AddInitFunction(&EMS_Init); - secprop->Add_int("emssize",4); secprop->AddInitFunction(&XMS_Init); - secprop->Add_int("xmssize",8); + secprop->Add_bool("xms",true); + secprop->AddInitFunction(&EMS_Init); + secprop->Add_bool("ems",true); + secprop->AddInitFunction(&DPMI_Init); + secprop->Add_bool("dpmi",true); + MSG_Add("DOS_CONFIGFILE_HELP", + "xms -- Enable XMS support.\n" + "ems -- Enable EMS support.\n" + "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" + ); // Mscdex secprop->AddInitFunction(&MSCDEX_Init); +#if C_MODEM + secprop=control->AddSection_prop("modem",&MODEM_Init); + secprop->Add_bool("modem",true); + secprop->Add_hex("comport",2); + secprop->Add_int("listenport",23); + + MSG_Add("MODEM_CONFIGFILE_HELP", + "modem -- Enable virtual modem emulation.\n" + "comport -- COM Port modem is connected to.\n" + "listenport -- TCP Port the momdem listens on for incoming connections.\n" + ); +#endif + secline=control->AddSection_line("autoexec",&AUTOEXEC_Init); - control->SetStartUp(&SHELL_Init); + MSG_Add("AUTOEXEC_CONFIGFILE_HELP", + "Lines in this section will be run at startup.\n" + ); -#if C_FPU - FPU_Init(); -#endif + control->SetStartUp(&SHELL_Init); } - diff --git a/src/fpu/Makefile.am b/src/fpu/Makefile.am index fb3045f..14c2d3d 100644 --- a/src/fpu/Makefile.am +++ b/src/fpu/Makefile.am @@ -1,4 +1,4 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libfpu.a -libfpu_a_SOURCES = fpu.cpp fpu_flags.cpp fpu_types.h fpu_instructions.h \ No newline at end of file +libfpu_a_SOURCES = fpu.cpp fpu_types.h fpu_instructions.h \ No newline at end of file diff --git a/src/fpu/Makefile.in b/src/fpu/Makefile.in index 4f3d7e9..a9c3142 100644 --- a/src/fpu/Makefile.in +++ b/src/fpu/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,82 +13,128 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libfpu.a -libfpu_a_SOURCES = fpu.cpp fpu_flags.cpp fpu_types.h fpu_instructions.h +libfpu_a_SOURCES = fpu.cpp fpu_types.h fpu_instructions.h subdir = src/fpu +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -96,30 +142,24 @@ LIBRARIES = $(noinst_LIBRARIES) libfpu_a_AR = $(AR) cru libfpu_a_LIBADD = -am_libfpu_a_OBJECTS = fpu.$(OBJEXT) fpu_flags.$(OBJEXT) +am_libfpu_a_OBJECTS = fpu.$(OBJEXT) libfpu_a_OBJECTS = $(am_libfpu_a_OBJECTS) -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/fpu.Po ./$(DEPDIR)/fpu_flags.Po +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/fpu.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ -CFLAGS = @CFLAGS@ 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 = $(libfpu_a_SOURCES) -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libfpu_a_SOURCES) all: all-am @@ -148,28 +188,36 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fpu.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fpu_flags.Po@am__quote@ - -distclean-depend: - -rm -rf ./$(DEPDIR) .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -195,20 +243,41 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -233,7 +302,6 @@ check: check-am all-am: Makefile $(LIBRARIES) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -253,7 +321,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -263,9 +331,11 @@ clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am @@ -286,6 +356,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -293,18 +365,25 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags distdir dvi \ - dvi-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/fpu/fpu.cpp b/src/fpu/fpu.cpp index 79ee2b9..1012d2f 100644 --- a/src/fpu/fpu.cpp +++ b/src/fpu/fpu.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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,257 +21,666 @@ #include #include +#include "cross.h" #include "mem.h" #include "fpu.h" +#include "cpu.h" typedef PhysPt EAPoint; +#define TOP fpu.top +#define ST(i) ( (fpu.top+ (i) ) & 7 ) + #define LoadMb(off) mem_readb(off) #define LoadMw(off) mem_readw(off) #define LoadMd(off) mem_readd(off) -#define LoadMbs(off) (Bit8s)(LoadMb(off)) -#define LoadMws(off) (Bit16s)(LoadMw(off)) -#define LoadMds(off) (Bit32s)(LoadMd(off)) - #define SaveMb(off,val) mem_writeb(off,val) #define SaveMw(off,val) mem_writew(off,val) #define SaveMd(off,val) mem_writed(off,val) -typedef double Real; - #include "fpu_types.h" + +struct { + FPU_Reg regs[9]; + FPU_Tag tags[9]; + Bitu cw; + FPU_Round round; + Bitu ex_mask; + Bitu sw; + Bitu top; + +} fpu; + +INLINE void FPU_SetCW(Bitu word) { + fpu.cw = word; + fpu.round = (FPU_Round)((word >> 10) & 3); + // word >>8 &3 is precission + fpu.ex_mask = word & 0x3f; +} + + + +INLINE Bitu FPU_GET_TOP(void){ + return (fpu.sw & 0x3800)>>11; +} +INLINE void FPU_SET_TOP(Bitu val){ + fpu.sw &= ~0x3800; + fpu.sw |= (val&7)<<11; + return; +} + +INLINE void FPU_SET_C0(Bitu C){ + fpu.sw &= ~0x0100; + if(C) fpu.sw |= 0x0100; +} +INLINE void FPU_SET_C1(Bitu C){ + fpu.sw &= ~0x0200; + if(C) fpu.sw |= 0x0200; +} +INLINE void FPU_SET_C2(Bitu C){ + fpu.sw &= ~0x0400; + if(C) fpu.sw |= 0x0400; +} +INLINE void FPU_SET_C3(Bitu C){ + fpu.sw &= ~0x4000; + if(C) fpu.sw |= 0x4000; +} + +INLINE Bitu FPU_GET_C0(void){ + return (fpu.sw & 0x0100)>>8; +} +INLINE Bitu FPU_GET_C1(void){ + return (fpu.sw & 0x0200)>>9; +} +INLINE Bitu FPU_GET_C2(void){ + return (fpu.sw & 0x0400)>>10; +} +INLINE Bitu FPU_GET_C3(void){ + return (fpu.sw & 0x4000)>>14; +} + #include "fpu_instructions.h" -FPU_Flag_Info fpu_flags; -FPU_Reg fpu_regs[8]; +/* TODO : ESC6normal => esc4normal+pop or a define as well +*/ -#define FPU_GetZF fpu_flags.sw.zf = FPU_get_ZF(); +/* WATCHIT : ALWAYS UPDATE REGISTERS BEFORE AND AFTER USING THEM + STATUS WORD => FPU_SET_TOP(TOP) BEFORE a read + TOP=FPU_GET_TOP() after a write; + */ +static void EATREE(Bitu _rm){ + Bitu group=(_rm >> 3) & 7; + /* data will allready be put in register 8 by caller */ + switch(group){ + case 0x00: /* FIADD */ + FPU_FADD(TOP, 8); + break; + case 0x01: /* FIMUL */ + FPU_FMUL(TOP, 8); + break; + case 0x02: /* FICOM */ + FPU_FCOM(TOP,8); + break; + case 0x03: /* FICOMP */ + FPU_FCOM(TOP,8); + FPU_FPOP(); + break; + case 0x04: /* FISUB */ + FPU_FSUB(TOP,8); + break; + case 0x05: /* FISUBR */ + FPU_FSUBR(TOP,8); + break; + case 0x06: /* FIDIV */ + FPU_FDIV(TOP, 8); + break; + case 0x07: /* FIDIVR */ + FPU_FDIVR(TOP,8); + break; + default: + break; + } -#define FPU_ParseCW(newcw) { \ - fpu_flags.cw.ic = ((bool)((newcw&0x1000)>>12)?true:false); \ - fpu_flags.cw.rc = (Bit8u)((newcw&0x0C00)>>10); \ - fpu_flags.cw.pc = (Bit8u)((newcw&0x0300)>>8); \ - fpu_flags.cw.ie = ((bool)((newcw&0x0080)>>7)?true:false); \ - fpu_flags.cw.sf = ((bool)((newcw&0x0040)>>6)?true:false); \ - fpu_flags.cw.pf = ((bool)((newcw&0x0020)>>5)?true:false); \ - fpu_flags.cw.uf = ((bool)((newcw&0x0010)>>4)?true:false); \ - fpu_flags.cw.of = ((bool)((newcw&0x0008)>>3)?true:false); \ - fpu_flags.cw.zf = ((bool)((newcw&0x0004)>>2)?true:false); \ - fpu_flags.cw.df = ((bool)((newcw&0x0002)>>1)?true:false); \ - fpu_flags.cw.in = ((bool)(newcw&0x0001)?true:false); \ -} - -#define FPU_makeCW(newcw) { \ - newcw = (Bit16u)fpu_flags.cw.in; \ - newcw |= (fpu_flags.cw.df<<1); \ - newcw |= (fpu_flags.cw.zf<<2); \ - newcw |= (fpu_flags.cw.of<<3); \ - newcw |= (fpu_flags.cw.uf<<4); \ - newcw |= (fpu_flags.cw.pf<<5); \ - newcw |= (fpu_flags.cw.sf<<6); \ - newcw |= (fpu_flags.cw.ie<<7); \ - newcw |= (fpu_flags.cw.pc<<8); \ - newcw |= (fpu_flags.cw.rc<<10); \ - newcw |= (fpu_flags.cw.ic<<12); \ -} - -#define FPU_ParseSW(newsw) { \ - fpu_flags.sw.bf = ((bool)((newsw&0x8000)>>15)?true:false); \ - fpu_flags.sw.c3 = ((bool)((newsw&0x4000)>>14)?true:false); \ - fpu_flags.sw.tos = (Bit8s)((newsw&0x3800)>>11); \ - fpu_flags.sw.c2 = ((bool)((newsw&0x0400)>>10)?true:false); \ - fpu_flags.sw.c1 = ((bool)((newsw&0x0200)>>9)?true:false); \ - fpu_flags.sw.c0 = ((bool)((newsw&0x0100)>>8)?true:false); \ - fpu_flags.sw.ir = ((bool)((newsw&0x0080)>>7)?true:false); \ - fpu_flags.sw.sf = ((bool)((newsw&0x0040)>>6)?true:false); \ - fpu_flags.sw.pf = ((bool)((newsw&0x0020)>>5)?true:false); \ - fpu_flags.sw.uf = ((bool)((newsw&0x0010)>>4)?true:false); \ - fpu_flags.sw.of = ((bool)((newsw&0x0008)>>3)?true:false); \ - fpu_flags.sw.zf = ((bool)((newsw&0x0004)>>2)?true:false); \ - fpu_flags.sw.df = ((bool)((newsw&0x0002)>>1)?true:false); \ - fpu_flags.sw.in = ((bool)(newsw&0x0001)?true:false); \ -} - -#define FPU_makeSW(newsw) { \ - newsw = (Bit16u)fpu_flags.sw.in; \ - newsw |= (fpu_flags.sw.df<<1); \ - newsw |= (fpu_flags.sw.zf<<2); \ - newsw |= (fpu_flags.sw.of<<3); \ - newsw |= (fpu_flags.sw.uf<<4); \ - newsw |= (fpu_flags.sw.pf<<5); \ - newsw |= (fpu_flags.sw.sf<<6); \ - newsw |= (fpu_flags.sw.ir<<7); \ - newsw |= (fpu_flags.sw.c0<<8); \ - newsw |= (fpu_flags.sw.c1<<9); \ - newsw |= (fpu_flags.sw.c2<<10); \ - newsw |= (fpu_flags.sw.tos<<11); \ - newsw |= (fpu_flags.sw.c3<<14); \ - newsw |= (fpu_flags.sw.bf<<15); \ -} - -#define FPU_LOADFLAGS { \ - fpu_flags.sw.bf = false; \ - fpu_flags.sw.c3 = FPU_get_C3(); \ - fpu_flags.sw.c2 = FPU_get_C2(); \ - fpu_flags.sw.c1 = FPU_get_C1(); \ - fpu_flags.sw.c0 = FPU_get_C0(); \ - fpu_flags.sw.ir = FPU_get_IR(); \ - fpu_flags.sw.sf = FPU_get_SF(); \ - fpu_flags.sw.pf = FPU_get_PF(); \ - fpu_flags.sw.uf = FPU_get_UF(); \ - fpu_flags.sw.of = FPU_get_OF(); \ - fpu_flags.sw.zf = FPU_get_ZF(); \ - fpu_flags.sw.df = FPU_get_DF(); \ - fpu_flags.sw.in = FPU_get_IN(); \ } void FPU_ESC0_EA(Bitu rm,PhysPt addr) { + /* REGULAR TREE WITH 32 BITS REALS -> float */ + union { + float f; + Bit32u l; + } blah; + blah.l = mem_readd(addr); + fpu.regs[8].d = static_cast(blah.f); + EATREE(rm); } void FPU_ESC0_Normal(Bitu rm) { + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch (group){ + case 0x00: /* FADD ST,STi */ + FPU_FADD(TOP,ST(sub)); + break; + case 0x01: /* FMUL ST,STi */ + FPU_FMUL(TOP,ST(sub)); + break; + case 0x02: /* FCOM STi */ + FPU_FCOM(TOP,ST(sub)); + break; + case 0x03: /* FCOMP STi */ + FPU_FCOM(TOP,ST(sub)); + FPU_FPOP(); + break; + case 0x04: /* FSUB ST,STi */ + FPU_FSUB(TOP,ST(sub)); + break; + case 0x05: /* FSUBR ST,STi */ + FPU_FSUBR(TOP,ST(sub)); + break; + case 0x06: /* FDIV ST,STi */ + FPU_FDIV(TOP,ST(sub)); + break; + case 0x07: /* FDIVR ST,STi */ + FPU_FDIVR(TOP,ST(sub)); + break; + default: + break; + + } } - void FPU_ESC1_EA(Bitu rm,PhysPt addr) { - Bit16u cw; - Bitu opcode = (rm&0x38)>>3; +// floats + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch(group){ + case 0x00: /* FLD float*/ + { + union { + float f; + Bit32u l; + } blah; + blah.l = mem_readd(addr); + FPU_PUSH(static_cast(blah.f)); + } + break; - switch(opcode) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 6: - break; - case 5: - FPU_ParseCW(LoadMw(addr)); /* FLDCW */ - break; - case 7: /* FSTCW */ - FPU_makeCW(cw); - SaveMw(addr,cw); - break; + case 0x01: /* UNKNOWN */ + LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); + break; + case 0x02: /* FST float*/ + { + union { + float f; + Bit32u l; + } blah; + //should depend on rounding method + blah.f = static_cast(fpu.regs[TOP].d); + mem_writed(addr,blah.l); + } + break; + + case 0x03: /* FSTP float*/ + { + union { + float f; + Bit32u l; + } blah; + blah.f = static_cast(fpu.regs[TOP].d); + mem_writed(addr,blah.l); + } + FPU_FPOP(); + break; + case 0x05: /*FLDCW */ + { + Bit16u temp =mem_readw(addr); + FPU_SetCW(temp); + } + break; + case 0x07: /* FNSTCW*/ + mem_writew(addr,fpu.cw); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub); + break; } + } void FPU_ESC1_Normal(Bitu rm) { - Bitu opcode = (rm&0xF0); + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch (group){ + case 0x00: /* FLD STi */ + FPU_PUSH(fpu.regs[ST(sub)].d); + break; + case 0x01: /* FXCH STi */ + FPU_FXCH(TOP,ST(sub)); + break; + case 0x04: + switch(sub){ + case 0x00: /* FCHS */ + fpu.regs[TOP].d = -1.0*(fpu.regs[TOP].d); + break; + case 0x01: /* FABS */ + fpu.regs[TOP].d = fabs(fpu.regs[TOP].d); + break; + case 0x02: /* UNKNOWN */ + case 0x03: /* ILLEGAL */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + case 0x04: /* FTST */ + fpu.regs[8].d=0.0; + FPU_FCOM(TOP,8); + break; + case 0x05: /* FXAM */ + FPU_FXAM(); + break; + case 0x06: /* FTSTP (cyrix)*/ + case 0x07: /* UNKNOWN */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + } + break; + case 0x05: + switch(sub){ + case 0x00: /* FLD1 */ + FPU_PUSH(1.0); + break; + case 0x01: /* FLDL2T */ + FPU_PUSH(L2T); + break; + case 0x02: /* FLDL2E */ + FPU_PUSH(L2E); + break; + case 0x03: /* FLDPI */ + FPU_PUSH(PI); + break; + case 0x04: /* FLDLG2 */ + FPU_PUSH(LG2); + break; + case 0x05: /* FLDLN2 */ + FPU_PUSH(LN2); + break; + case 0x06: /* FLDZ*/ + FPU_PUSH_ZERO(); + break; + case 0x07: /* ILLEGAL */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + } + break; + case 0x06: + switch(sub){ + case 0x00: /* F2XM1 */ + FPU_F2XM1(); + break; + case 0x01: /* FYL2X */ + FPU_FYL2X(); + break; + case 0x02: /* FPTAN */ + FPU_FPTAN(); + break; + case 0x03: /* FPATAN */ + FPU_FPATAN(); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + } + break; + case 0x07: + switch(sub){ + case 0x00: /* FPREM */ + FPU_FPREM(); + break; + case 0x02: /* FSQRT */ + FPU_FSQRT(); + break; + case 0x03: /* FSINCOS */ + FPU_FSINCOS(); + break; + case 0x04: /* FRNDINT */ + { +//TODO + Bit64s temp= static_cast(FROUND(fpu.regs[TOP].d)); + fpu.regs[TOP].d=static_cast(temp); + } + //TODO + break; + case 0x05: /* FSCALE */ + FPU_FSCALE(); + break; + case 0x06: /* FSIN */ + FPU_FSIN(); + break; + case 0x07: /* FCOS */ + FPU_FCOS(); + break; + case 0x01: /* FYL2XP1 */ + default: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + break; + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); + } - switch(opcode) { - case 0xC0: -// if(rm&8) -// else - FLDST(rm-0xC0); /* FLDST */ - break; - case 0xD0: - break; - } - switch(rm) { - case 0xE0: /* FCHS */ - FCHS; - break; - case 0xE8: /* FLD1 */ - FLD(1); - break; - case 0xEE: /* FLDZ */ - FLD(0); - break; - } +// LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub); } void FPU_ESC2_EA(Bitu rm,PhysPt addr) { + /* 32 bits integer operants */ + Bit32s blah = mem_readd(addr); + fpu.regs[8].d = static_cast(blah); + EATREE(rm); } void FPU_ESC2_Normal(Bitu rm) { + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub); } void FPU_ESC3_EA(Bitu rm,PhysPt addr) { + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch(group){ + case 0x00: /* FLD */ + { + Bit32s blah = mem_readd(addr); + FPU_PUSH( static_cast(blah)); + } + break; + case 0x01: /* FISTTP */ + LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); + break; + + case 0x02: /* FIST */ + mem_writed(addr,static_cast(FROUND(fpu.regs[TOP].d))); + break; + case 0x03: /*FISTP */ + mem_writed(addr,static_cast(FROUND(fpu.regs[TOP].d))); + FPU_FPOP(); + break; + case 0x05: /* FLD 80 Bits Real */ + FPU_FLD80(addr); + break; + case 0x07: /* FSTP 80 Bits Real */ + FPU_ST80(addr); + FPU_FPOP(); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub); + } } void FPU_ESC3_Normal(Bitu rm) { - switch( rm ) { - case 0xE3: /* FINIT */ - FPU_ParseCW(0x037F); - for(int i=0;i<8;i++) { - fpu_regs.st[i].r = 0; - fpu_regs.st[i].tag = FPUREG_EMPTY; - } + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch (group) { + case 0x04: + switch (sub) { + case 0x00: //FNENI + case 0x01: //FNDIS + LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion :%d",sub); break; + case 0x02: //FNCLEX FCLEX + FPU_FCLEX(); + break; + case 0x03: //FNINIT FINIT + FPU_FINIT(); + break; + case 0x04: //FNSETPM + case 0x05: //FRSTPM + LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); + FPU_FNOP(); + break; + default: + E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",group,sub); + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub); + break; } + return; } 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"); + fpu.regs[8].l.lower=mem_readd(addr); + fpu.regs[8].l.upper=mem_readd(addr+4); + EATREE(rm); } void FPU_ESC4_Normal(Bitu rm) { + //LOOKS LIKE number 6 without popping*/ + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch(group){ + case 0x00: /*FADDP STi,ST*/ + FPU_FADD(ST(sub),TOP); + break; + case 0x01: /* FMULP STi,ST*/ + FPU_FMUL(ST(sub),TOP); + break; + case 0x02: /* FCOM*/ + FPU_FCOM(TOP,ST(sub)); + break; /* TODO IS THIS ALLRIGHT ????????? (maybe reverse operators) */ + case 0x03: /* FCOMP*/ + FPU_FCOM(TOP,ST(sub)); + FPU_FPOP(); + break; + case 0x04: /* FSUBRP STi,ST*/ + FPU_FSUBR(ST(sub),TOP); + break; + case 0x05: /* FSUBP STi,ST*/ + FPU_FSUB(ST(sub),TOP); + break; + case 0x06: /* FDIVRP STi,ST*/ + FPU_FDIVR(ST(sub),TOP); + break; + case 0x07: /* FDIVP STi,ST*/ + FPU_FDIV(ST(sub),TOP); + break; + default: + break; + } } - void FPU_ESC5_EA(Bitu rm,PhysPt addr) { - Bit16u sw; - Bitu opcode = (rm&0x38)>>3; + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch(group){ + case 0x00: /* FLD double real*/ + { + FPU_Reg blah; + blah.l.lower=mem_readd(addr); + blah.l.upper=mem_readd(addr+4); + FPU_PUSH(blah.d); + } + break; + case 0x01: /* FISTTP longint*/ + LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); + break; - switch(opcode) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: /* FSTSW */ - FPU_LOADFLAGS; - FPU_makeSW(sw); - SaveMw(addr,sw); - break; + case 0x02: /* FIST double real*/ + mem_writed(addr,fpu.regs[TOP].l.lower); + mem_writed(addr+4,fpu.regs[TOP].l.upper); + break; + case 0x03: /*FISTP double real*/ + mem_writed(addr,fpu.regs[TOP].l.lower); + mem_writed(addr+4,fpu.regs[TOP].l.upper); + FPU_FPOP(); + break; + case 0x07: /*FNSTSW NG DISAGREES ON THIS*/ + FPU_SET_TOP(TOP); + mem_writew(addr,fpu.sw); + //seems to break all dos4gw games :) + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub); } } void FPU_ESC5_Normal(Bitu rm) { + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch(group){ + case 0x00: /* FFREE STi */ + fpu.tags[ST(sub)]=TAG_Empty; + break; + case 0x01: /* FXCH STi*/ + FPU_FXCH(TOP,ST(sub)); + break; + case 0x02: /* FST STi */ + FPU_FST(TOP,ST(sub)); + break; + case 0x03: /* FSTP STi*/ + FPU_FST(TOP,ST(sub)); + FPU_FPOP(); + break; + case 0x04: /* FUCOM STi */ + FPU_FUCOM(TOP,ST(sub)); + break; + case 0x05: /*FUCOMP STi */ + FPU_FUCOM(TOP,ST(sub)); + FPU_FPOP(); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",group,sub); + break; + } } 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); + EATREE(rm); } void FPU_ESC6_Normal(Bitu rm) { - Bitu opcode = (rm&0xF0); - - if(rm==0xD9) { /* FCOMPP */ - FCOMPP; - return; - } - switch(opcode) { - case 0xC0: -// if(rm&8) - break; - case 0xD0: -// if(rm&8) - break; - case 0xE0: -// if(rm&8) - break; - case 0xF0: - if(rm&8) - FDIVP(rm-0xF8,0); - break; + /* all P variants working only on registers */ + /* get top before switch and pop afterwards */ + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch(group){ + case 0x00: /*FADDP STi,ST*/ + FPU_FADD(ST(sub),TOP); + break; + case 0x01: /* FMULP STi,ST*/ + FPU_FMUL(ST(sub),TOP); + break; + case 0x02: /* FCOMP5*/ + FPU_FCOM(TOP,ST(sub)); + break; /* TODO IS THIS ALLRIGHT ????????? */ + case 0x03: /* weird*/ /*FCOMPP*/ + if(sub != 1){ + LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub); + ; + break; + } + FPU_FCOM(TOP,ST(1)); + FPU_FPOP(); /* extra pop at the bottom*/ + break; + case 0x04: /* FSUBRP STi,ST*/ + FPU_FSUBR(ST(sub),TOP); + break; + case 0x05: /* FSUBP STi,ST*/ + FPU_FSUB(ST(sub),TOP); + break; + case 0x06: /* FDIVRP STi,ST*/ + FPU_FDIVR(ST(sub),TOP); + break; + case 0x07: /* FDIVP STi,ST*/ + FPU_FDIV(ST(sub),TOP); + break; + default: + break; } + FPU_FPOP(); } void FPU_ESC7_EA(Bitu rm,PhysPt addr) { + /* ROUNDING*/ + + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch(group){ + case 0x00: /* FILD Bit16s */ + { + Bit16s blah = mem_readw(addr); + FPU_PUSH( static_cast(blah)); + } + break; + case 0x01: /* FISTTP Bit16s */ + LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); + break; + + case 0x02: /* FIST Bit16s */ + mem_writew(addr,static_cast(FROUND(fpu.regs[TOP].d))); + break; + case 0x03: /* FISTP Bit16s */ + mem_writew(addr,static_cast(FROUND(fpu.regs[TOP].d))); + FPU_FPOP(); + break; + case 0x05: /* FILD Bit32s */ + { + Bit32s blah = mem_readd(addr); + FPU_PUSH( static_cast(blah)); + } + 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))); + FPU_FPOP(); + break; + case 0x04: /* FBLD packed BCD */ + //Don't think anybody will ever use this. + default: + LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub); + break; + } } void FPU_ESC7_Normal(Bitu rm) { + Bitu group=(rm >> 3) & 7; + Bitu sub=(rm & 7); + switch (group){ + case 0x04: + switch(sub){ + case 0x00: /* FNSTSW AX*/ + FPU_SET_TOP(TOP); + reg_ax = fpu.sw; + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); + break; + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub); + break; + } + } -void FPU_Init(void) { - fpu_flags.type = t_FUNKNOWN; +void FPU_Init(Section*) { + FPU_FINIT(); } #endif diff --git a/src/fpu/fpu_flags.cpp b/src/fpu/fpu_flags.cpp deleted file mode 100644 index 924614f..0000000 --- a/src/fpu/fpu_flags.cpp +++ /dev/null @@ -1,235 +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. - */ - -#include "dosbox.h" -#include "fpu.h" -#include "pic.h" -#include "fpu_types.h" -extern FPU_Flag_Info fpu_flags; - -bool FPU_get_C3() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - return fpu_flags.sw.c3; - case t_FCOMP: - return (fpu_flags.result.tag==FPUREG_EMPTY||fpu_flags.result.tag==FPUREG_ZERO); - default: - E_Exit("FPU_get_C3 Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_C2() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - return fpu_flags.sw.c2; - case t_FCOMP: - return (fpu_flags.result.tag==FPUREG_EMPTY); - default: - E_Exit("FPU_get_C2 Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_C1() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - return fpu_flags.sw.c1; - case t_FCOMP: - return false; /* FIXME */ - default: - E_Exit("FPU_get_C1 Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_C0() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - return fpu_flags.sw.c0; - case t_FCOMP: - return (fpu_flags.result.tag!=FPUREG_ZERO&&fpu_flags.result.tag!=FPUREG_PNAN); - default: - E_Exit("FPU_get_C0 Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_IR() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - case t_FCOMP: - return fpu_flags.sw.ir; - default: - E_Exit("FPU_get_IR Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_SF() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - return fpu_flags.sw.sf; - case t_FCOMP: - return false; /* FIXME */ - default: - E_Exit("FPU_get_SF Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_PF() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - case t_FCOMP: - return fpu_flags.sw.pf; - default: - E_Exit("FPU_get_PF Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_UF() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - case t_FCOMP: - return fpu_flags.sw.uf; - default: - E_Exit("FPU_get_UF Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_OF() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - case t_FCOMP: - return fpu_flags.sw.of; - default: - E_Exit("FPU_get_OF Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_ZF() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - case t_FCOMP: - return fpu_flags.sw.zf; - case t_FDIV: - case t_FDIVP: - return (fpu_flags.result.tag==FPUREG_PNAN||fpu_flags.result.tag==FPUREG_NNAN); - default: - E_Exit("FPU_get_ZF Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_DF() { - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - return fpu_flags.sw.df; - case t_FCOMP: - return false; /* FIXME */ - default: - E_Exit("FPU_get_DF Unknown %d",fpu_flags.type); - } - return 0; -} - -bool FPU_get_IN(){ - switch(fpu_flags.type) { - case t_FLD: - case t_FLDST: - case t_FDIV: - case t_FDIVP: - case t_FCHS: - case t_FUNKNOWN: - case t_FNOTDONE: - return fpu_flags.sw.in; - case t_FCOMP: - return (fpu_flags.result.tag==FPUREG_EMPTY); /* FIXME */ - default: - E_Exit("FPU_get_IN Unknown %d",fpu_flags.type); - } - return 0; -} diff --git a/src/fpu/fpu_instructions.h b/src/fpu/fpu_instructions.h index 49de9d0..217b391 100644 --- a/src/fpu/fpu_instructions.h +++ b/src/fpu/fpu_instructions.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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,147 +16,306 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define FLD(op1) { \ - FPU_GetZF; \ - fpu_flags.type=t_FLD; \ - if(--fpu_flags.sw.tos < 0) \ - fpu_flags.sw.tos = 7; \ - if( fpu_regs.st[fpu_flags.sw.tos].tag != FPUREG_EMPTY ) { \ - fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ - break; \ - } \ - if(op1) \ - fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_VALID; \ - else \ - fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_ZERO; \ - fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = op1; \ +/* $Id: fpu_instructions.h,v 1.13 2003/10/07 10:42:01 qbix79 Exp $ */ + + +static void FPU_FINIT(void) { + FPU_SetCW(0x37F); + fpu.sw=0; + TOP=FPU_GET_TOP(); + fpu.tags[0]=TAG_Empty; + fpu.tags[1]=TAG_Empty; + fpu.tags[2]=TAG_Empty; + fpu.tags[3]=TAG_Empty; + fpu.tags[4]=TAG_Empty; + fpu.tags[5]=TAG_Empty; + fpu.tags[6]=TAG_Empty; + fpu.tags[7]=TAG_Empty; + fpu.tags[8]=TAG_Valid; // is only used by us +} +static void FPU_FCLEX(void){ + fpu.sw&=0x7f00; //should clear exceptions +}; + +static void FPU_FNOP(void){ + return; } -#define FLDST(op1) { \ - FPU_GetZF; \ - fpu_flags.type=t_FLDST; \ - Bit8u reg = fpu_flags.sw.tos+op1; \ - if(reg>7) reg-=8; \ - if(--fpu_flags.sw.tos < 0) \ - fpu_flags.sw.tos = 7; \ - if(fpu_regs.st[fpu_flags.sw.tos].tag!=FPUREG_EMPTY) { \ - fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ - break; \ - } \ - fpu_flags.result.tag = fpu_regs.st[fpu_flags.sw.tos].tag = fpu_regs.st[reg].tag; \ - fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = fpu_regs.st[reg].r; \ +static void FPU_PUSH(double in){ + TOP = (TOP - 1) &7; + //actually check if empty + fpu.tags[TOP]=TAG_Valid; + fpu.regs[TOP].d=in; +// LOG(LOG_FPU,LOG_ERROR)("Pushed at %d %g to the stack",newtop,in); + return; +} +static void FPU_PUSH_ZERO(void){ + FPU_PUSH(0.0); + return; //maybe oneday needed +} +static void FPU_FPOP(void){ + fpu.tags[TOP]=TAG_Empty; + //maybe set zero in it as well + TOP = ((TOP+1)&7); +// LOG(LOG_FPU,LOG_ERROR)("popped from %d %g off the stack",top,fpu.regs[top].d); + return; } -#define FPOP { \ - fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_EMPTY; \ - if(++fpu_flags.sw.tos > 7 ) \ - fpu_flags.sw.tos = 0; \ -} -/* FPOP: fpu_flags.result.r = fpu_regs.st[fpu_flags.sw.tos].r = 0; is not really neccessary */ - -#define FDIVP(op1,op2) { \ - Bit8u reg1 = fpu_flags.sw.tos+op1; \ - Bit8u reg2 = fpu_flags.sw.tos+op2; \ - fpu_flags.type=t_FDIVP; \ - if(reg1>7) reg1-=8; \ - if(reg2>7) reg2-=8; \ - if((fpu_regs.st[reg1].tag!=FPUREG_VALID && fpu_regs.st[reg1].tag!=FPUREG_ZERO)||(fpu_regs.st[reg2].tag!=FPUREG_VALID && fpu_regs.st[reg2].tag!=FPUREG_ZERO)) { \ - fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ - FPOP; \ - break; \ - } \ - if(fpu_regs.st[reg2].tag == FPUREG_ZERO) { \ - if(fpu_regs.st[reg1].r > 0) \ - fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_PNAN; \ - else \ - fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ - FPOP; \ - break; \ - } \ - if(fpu_regs.st[reg1].tag == FPUREG_ZERO) { \ - fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_ZERO; \ - FPOP; \ - break; \ - } \ - fpu_flags.result.tag = FPUREG_VALID; \ - fpu_flags.result.r = fpu_regs.st[reg1].r = fpu_regs.st[reg1].r / fpu_regs.st[reg2].r; \ - FPOP; \ +static void FPU_FADD(Bitu op1, Bitu op2){ + fpu.regs[op1].d+=fpu.regs[op2].d; + //flags and such :) + return; } -#define FDIV(op1,op2) { \ - Bit8u reg1 = fpu_flags.sw.tos+op1; \ - Bit8u reg2 = fpu_flags.sw.tos+op2; \ - fpu_flags.type=t_FDIV; \ - if(reg1>7) reg1-=7; \ - if(reg2>7) reg2-=7; \ - if((fpu_regs.st[reg1].tag!=FPUREG_VALID && fpu_regs.st[reg1].tag!=FPUREG_ZERO)||(fpu_regs.st[reg2].tag!=FPUREG_VALID && fpu_regs.st[reg2].tag!=FPUREG_ZERO)) { \ - fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ - break; \ - } \ - if(fpu_regs.st[reg2].tag == FPUREG_ZERO) { \ - if(fpu_regs.st[reg1].r > 0) \ - fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_PNAN; \ - else \ - fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_NNAN; \ - break; \ - } \ - if(fpu_regs.st[reg1].tag == FPUREG_ZERO) { \ - fpu_flags.result.tag = fpu_regs.st[reg1].tag = FPUREG_ZERO; \ - break; \ - } \ - fpu_flags.result.tag = FPUREG_VALID; \ - fpu_flags.result.r = fpu_regs.st[reg1].r = fpu_regs.st[reg1].r / fpu_regs.st[reg2].r; \ +static void FPU_FSIN(void){ + fpu.regs[TOP].d = sin(fpu.regs[TOP].d); + FPU_SET_C2(0); + //flags and such :) + return; } -#define FCHS { \ - FPU_GetZF; \ - fpu_flags.type=t_FCHS; \ - if(fpu_regs.st[fpu_flags.sw.tos].tag == FPUREG_PNAN) { \ - fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_NNAN; \ - } else if(fpu_regs.st[fpu_flags.sw.tos].tag == FPUREG_NNAN) { \ - fpu_regs.st[fpu_flags.sw.tos].tag = FPUREG_PNAN; \ - } else \ - fpu_regs.st[fpu_flags.sw.tos].r = -fpu_regs.st[fpu_flags.sw.tos].r; \ +static void FPU_FSINCOS(void){ + Real64 temp = fpu.regs[TOP].d; + fpu.regs[TOP].d = sin(temp); + FPU_PUSH(cos(temp)); + FPU_SET_C2(0); + //flags and such :) + return; } -#define FCOMPP { \ - Bit8u reg = fpu_flags.sw.tos+1; \ - FPU_GetZF; \ - fpu_flags.type=t_FCOMP; \ - if(reg>7) \ - reg=0; \ - if((fpu_regs.st[reg].tag==FPUREG_VALID||fpu_regs.st[reg].tag==FPUREG_ZERO)&&(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_VALID||fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_ZERO)) { \ - fpu_flags.result.r = fpu_regs.st[reg].r - fpu_regs.st[fpu_flags.sw.tos].r; \ - if(fpu_flags.result.r==0) \ - fpu_flags.result.tag = FPUREG_ZERO; \ - else \ - fpu_flags.result.tag = FPUREG_VALID; \ - FPOP; \ - FPOP; \ - return; \ - } else if(((fpu_regs.st[reg].tag==FPUREG_EMPTY)||(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_EMPTY))||((fpu_regs.st[reg].tag==FPUREG_VALID||fpu_regs.st[reg].tag==FPUREG_ZERO)||(fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_VALID||fpu_regs.st[fpu_flags.sw.tos].tag==FPUREG_ZERO))) { \ - fpu_flags.result.tag = FPUREG_EMPTY; \ - FPOP; \ - FPOP; \ - return; \ - } \ - Bit8s res = (fpu_regs.st[reg].tag-fpu_regs.st[fpu_flags.sw.tos].tag); \ - if(res==0||fpu_flags.cw.ic==0) { \ - fpu_flags.result.tag = FPUREG_ZERO; \ - FPOP; \ - FPOP; \ - return; \ - } else if(res>0) { \ - fpu_flags.result.tag = FPUREG_NNAN; \ - FPOP; \ - FPOP; \ - return; \ - } \ - fpu_flags.result.tag = FPUREG_PNAN; \ - FPOP; \ - FPOP; \ +static void FPU_FCOS(void){ + fpu.regs[TOP].d = cos(fpu.regs[TOP].d); + FPU_SET_C2(0); + //flags and such :) + return; +} + +static void FPU_FSQRT(void){ + fpu.regs[TOP].d = sqrt(fpu.regs[TOP].d); + //flags and such :) + return; +} +static void FPU_FPATAN(void){ + fpu.regs[ST(1)].d = atan(fpu.regs[ST(1)].d/fpu.regs[TOP].d); + FPU_FPOP(); + FPU_SET_C2(0); + //flags and such :) + return; +} +static void FPU_FPTAN(void){ + fpu.regs[TOP].d = tan(fpu.regs[TOP].d); + FPU_PUSH(1.0); + FPU_SET_C2(0); + //flags and such :) + return; +} +static void FPU_FDIV(Bitu st, Bitu other){ + fpu.regs[st].d= fpu.regs[st].d/fpu.regs[other].d; + //flags and such :) + return; +} + +static void FPU_FDIVR(Bitu st, Bitu other){ + fpu.regs[st].d= fpu.regs[other].d/fpu.regs[st].d; + // flags and such :) + return; +}; + +static void FPU_FMUL(Bitu st, Bitu other){ + fpu.regs[st].d*=fpu.regs[other].d; + //flags and such :) + return; +} + +static void FPU_FSUB(Bitu st, Bitu other){ + fpu.regs[st].d = fpu.regs[st].d - fpu.regs[other].d; + //flags and such :) + return; +} + +static void FPU_FSUBR(Bitu st, Bitu other){ + fpu.regs[st].d= fpu.regs[other].d - fpu.regs[st].d; + //flags and such :) + return; +} + +static void FPU_FXCH(Bitu st, Bitu other){ + FPU_Tag tag = fpu.tags[other]; + FPU_Reg reg = fpu.regs[other]; + fpu.tags[other] = fpu.tags[st]; + fpu.regs[other] = fpu.regs[st]; + fpu.tags[st] = tag; + fpu.regs[st] = reg; +} + +static void FPU_FST(Bitu st, Bitu other){ + fpu.tags[other] = fpu.tags[st]; + fpu.regs[other] = fpu.regs[st]; } +static void FPU_FCOM(Bitu st, Bitu other){ + if((fpu.tags[st] != TAG_Valid) || (fpu.tags[other] != TAG_Valid)){ + FPU_SET_C3(1);FPU_SET_C2(1);FPU_SET_C0(1);return; + } + if(fpu.regs[st].d == fpu.regs[other].d){ + FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0);return; + } + if(fpu.regs[st].d < fpu.regs[other].d){ + FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(1);return; + } + // st > other + FPU_SET_C3(0);FPU_SET_C2(0);FPU_SET_C0(0);return; +} + +static void FPU_FUCOM(Bitu st, Bitu other){ + //does atm the same as fcom + FPU_FCOM(st,other); +} + +static double FROUND(double in){ + switch(fpu.round){ + case ROUND_Nearest: + if (in-floor(in)>0.5) return (floor(in)+1); + else if (in-floor(in)<0.5) return (floor(in)); + else return (((static_cast(floor(in)))&1)!=0)?(floor(in)+1):(floor(in)); + break; + case ROUND_Down: + return (floor(in)); + break; + case ROUND_Up: + return (ceil(in)); + break; + case ROUND_Chop: + return in; //the cast afterwards will do it right maybe cast here + break; + default: + return in; + break; + } +} + +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; + FPU_SET_C0(static_cast(ressaved&4)); + FPU_SET_C3(static_cast(ressaved&2)); + FPU_SET_C1(static_cast(ressaved&1)); + FPU_SET_C2(0); +} + +static void FPU_FXAM(void){ + if(fpu.tags[TOP] == TAG_Empty) + { + FPU_SET_C3(1);FPU_SET_C0(1); + return; + } + if(fpu.regs[TOP].ll & LONGTYPE(0x8000000000000000)) //sign + { + FPU_SET_C1(1); + } + else + { + FPU_SET_C1(0); + } + if(fpu.regs[TOP].d == 0.0) //zero or normalized number. + { + FPU_SET_C3(1);FPU_SET_C2(0);FPU_SET_C0(0); + } + else{ + FPU_SET_C3(0);FPU_SET_C2(1);FPU_SET_C0(0); + } +} + +static void FPU_FBST(PhysPt addr) +{ + FPU_Reg val = fpu.regs[TOP]; + bool sign = false; + if(val.d<0.0){ //sign + sign=true; + val.d=-val.d; + } + //numbers from back to front + Real64 temp=val.d; + Bitu p; + for(Bitu i=0;i<9;i++){ + val.d=temp; + temp = static_cast(static_cast(floor(val.d/10.0))); + p = static_cast(val.d - 10.0*temp); + val.d=temp; + temp = static_cast(static_cast(floor(val.d/10.0))); + p |= (static_cast(val.d - 10.0*temp)<<4); + + mem_writeb(addr+i,p); + } + val.d=temp; + temp = static_cast(static_cast(floor(val.d/10.0))); + p = static_cast(val.d - 10.0*temp); + if(sign) + p|=0x80; + mem_writeb(addr+9,p); +} + +#define BIAS80 16383 +#define BIAS64 1023 + +static void FPU_FLD80(PhysPt addr) +{ + struct{ + Bit16s begin; + FPU_Reg eind; + } test; + test.eind.l.lower=mem_readd(addr); + test.eind.l.upper =mem_readd(addr+4); + test.begin=mem_readw(addr+8); + + Bit64s exp64= (((test.begin & 0x7fff) - BIAS80)); + Bit64s blah= ((exp64 >0)?exp64:-exp64)&0x3ff; + Bit64s exp64final= ((exp64 >0)?blah:-blah) +BIAS64; + + Bit64s mant64= (test.eind.ll >> 11) & LONGTYPE(0xfffffffffffff); + Bit64s sign = (test.begin &0x8000)?1:0; + FPU_Reg result; + result.ll= (sign <<63)|(exp64final << 52)| mant64; + FPU_PUSH(result.d); + //mant64= test.mant80/2***64 * 2 **53 +} + +static void FPU_ST80(PhysPt addr) +{ + struct{ + Bit16s begin; + FPU_Reg eind; + } test; + Bit64s sign80= (fpu.regs[TOP].ll&LONGTYPE(0x8000000000000000))?1:0; + Bit64s exp80 = fpu.regs[TOP].ll&LONGTYPE(0x7ff0000000000000); + Bit64s exp80final= (exp80>>52) - BIAS64 + BIAS80; + Bit64s mant80 = fpu.regs[TOP].ll&LONGTYPE(0x000fffffffffffff); + Bit64s mant80final= (mant80 << 11) | LONGTYPE(0x8000000000000000); + test.begin= (static_cast(sign80)<<15)| static_cast(exp80final); + test.eind.ll=mant80final; + mem_writed(addr,test.eind.l.lower); + mem_writed(addr+4,test.eind.l.upper); + mem_writew(addr+8,test.begin); +} + +static void FPU_F2XM1(void){ + fpu.regs[TOP].d=pow(2.0,fpu.regs[TOP].d) -1; + return; +} + +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)))); + return; //2^x where x is chopped. +} diff --git a/src/fpu/fpu_types.h b/src/fpu/fpu_types.h index 2d0ced0..c459feb 100644 --- a/src/fpu/fpu_types.h +++ b/src/fpu/fpu_types.h @@ -1,33 +1,54 @@ +/* + * Copyright (C) 2002-2003 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. + */ +typedef union { + double d; +#ifndef WORDS_BIGENDIAN + struct { + Bit32u lower; + Bit32s upper; + } l; +#else + struct { + Bit32s upper; + Bit32u lower; + } l; +#endif + Bit64s ll; +} FPU_Reg; -enum { FPUREG_VALID=0, FPUREG_ZERO, FPUREG_PNAN, FPUREG_NNAN, FPUREG_EMPTY }; - -enum { - t_FLD=0, t_FLDST, t_FDIV, - t_FDIVP, t_FCHS, t_FCOMP, - - t_FUNKNOWN, - t_FNOTDONE +enum FPU_Tag { + TAG_Valid = 0, + TAG_Zero = 1, + TAG_Weird = 2, + TAG_Empty = 3 }; -struct FPU_Flag_Info { - struct { - Real64 r; - Bit8u tag; - } var1,var2, result; - struct { - bool bf,c3,c2,c1,c0,ir,sf,pf,uf,of,zf,df,in; - Bit8s tos; - } sw; - struct { - bool ic,ie,sf,pf,uf,of,zf,df,in; - Bit8u rc,pc; - } cw; - Bitu type; - Bitu prev_type; -}; -struct FPU_Reg { - Real64 r; - Bit8u tag; +enum FPU_Round { + ROUND_Nearest = 0, + ROUND_Down = 1, + ROUND_Up = 2, + ROUND_Chop = 3 }; +//get pi from a real library +#define PI 3.14159265358979323846 +#define L2E 1.4426950408889634 +#define L2T 3.3219280948873623 +#define LN2 0.69314718055994531 +#define LG2 0.3010299956639812 diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 83664b6..fafd8e7 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -2,5 +2,5 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libgui.a libgui_a_SOURCES = sdlmain.cpp render.cpp render_normal.h render_scale2x.h \ - midi.cpp midi_win32.h midi_oss.h midi_coreaudio.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 1a557b1..ada1052 100644 --- a/src/gui/Makefile.in +++ b/src/gui/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,84 +13,130 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libgui.a libgui_a_SOURCES = sdlmain.cpp render.cpp render_normal.h render_scale2x.h \ - midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h + midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h midi_alsa.h subdir = src/gui +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -101,11 +147,7 @@ libgui_a_LIBADD = am_libgui_a_OBJECTS = sdlmain.$(OBJEXT) render.$(OBJEXT) midi.$(OBJEXT) libgui_a_OBJECTS = $(am_libgui_a_OBJECTS) -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/midi.Po ./$(DEPDIR)/render.Po \ @@ -115,14 +157,12 @@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ -CFLAGS = @CFLAGS@ 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 = $(libgui_a_SOURCES) -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libgui_a_SOURCES) all: all-am @@ -154,26 +194,35 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdlmain.Po@am__quote@ -distclean-depend: - -rm -rf ./$(DEPDIR) - .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -199,20 +248,41 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -237,7 +307,6 @@ check: check-am all-am: Makefile $(LIBRARIES) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -257,7 +326,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -267,9 +336,11 @@ clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am @@ -290,6 +361,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -297,18 +370,25 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags distdir dvi \ - dvi-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp index 589a241..8145d7b 100644 --- a/src/gui/midi.cpp +++ b/src/gui/midi.cpp @@ -86,6 +86,12 @@ MidiHandler Midi_none; #endif +#if defined (HAVE_ALSA) + +#include "midi_alsa.h" + +#endif + static struct { Bitu status; Bitu cmd_len; @@ -112,7 +118,7 @@ void MIDI_RawOutByte(Bit8u data) { /* Play a sysex message */ midi.sysex.buf[midi.sysex.used++]=0xf7; midi.handler->PlaySysex(midi.sysex.buf,midi.sysex.used); - LOG(0,"Sysex message size %d",midi.sysex.used); + LOG(LOG_ALL,LOG_NORMAL)("Sysex message size %d",midi.sysex.used); midi.sysex.active=false; if (data==0xf7) return; } @@ -142,7 +148,6 @@ bool MIDI_Available(void) { void MIDI_Init(Section * sec) { Section_prop * section=static_cast(sec); - MSG_Add("MIDI_CONFIGFILE_HELP","Set midi output device,alsa,oss,win32,coreaudio,none\n"); const char * dev=section->Get_string("device"); const char * conf=section->Get_string("config"); /* If device = "default" go for first handler that works */ diff --git a/src/gui/midi_alsa.h b/src/gui/midi_alsa.h new file mode 100644 index 0000000..9f13a65 --- /dev/null +++ b/src/gui/midi_alsa.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2002-2003 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 + +#define ADDR_DELIM ".:" + +#if SND_LIB_MINOR >= 6 +#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) +#else +/* SND_SEQ_OPEN_OUT causes oops on early version of ALSA */ +#define my_snd_seq_open(seqp) snd_seq_open(seqp, SND_SEQ_OPEN) +#endif + +class MidiHandler_alsa : public MidiHandler { +private: + snd_seq_event_t ev; + snd_seq_t *seq_handle; + int seq_client, seq_port; + int my_client, my_port; + void send_event(int do_flush) { + snd_seq_ev_set_direct(&ev); + snd_seq_ev_set_source(&ev, my_port); + snd_seq_ev_set_dest(&ev, seq_client, seq_port); + + snd_seq_event_output(seq_handle, &ev); + if (do_flush) + snd_seq_flush_output(seq_handle); + } + + int parse_addr(char *arg, int *client, int *port) { + char *p; + + if (isdigit(*arg)) { + if ((p = strpbrk(arg, ADDR_DELIM)) == NULL) + return -1; + *client = atoi(arg); + *port = atoi(p + 1); + } else { + if (*arg == 's' || *arg == 'S') { + *client = SND_SEQ_ADDRESS_SUBSCRIBERS; + *port = 0; + } else + return -1; + } + return 0; + } +public: + MidiHandler_alsa() : MidiHandler() {}; + char* GetName(void) { return "alsa"; } + void PlaySysex(Bit8u * sysex,Bitu len) { + snd_seq_ev_set_sysex(&ev, len, sysex); + send_event(1); + } + + void PlayMsg(Bit32u msg) { + unsigned int midiCmd[4]; + ev.type = SND_SEQ_EVENT_OSS; + + if (msg == 247) // to accomadate lure of the temptress + return; + + midiCmd[3] = (msg & 0xFF000000) >> 24; + midiCmd[2] = (msg & 0x00FF0000) >> 16; + midiCmd[1] = (msg & 0x0000FF00) >> 8; + midiCmd[0] = (msg & 0x000000FF); + ev.data.raw32.d[0] = midiCmd[0]; + ev.data.raw32.d[1] = midiCmd[1]; + ev.data.raw32.d[2] = midiCmd[2]; + + unsigned char chanID = midiCmd[0] & 0x0F; + switch (midiCmd[0] & 0xF0) { + case 0x80: + snd_seq_ev_set_noteoff(&ev, chanID, midiCmd[1], midiCmd[2]); + send_event(1); + break; + case 0x90: + snd_seq_ev_set_noteon(&ev, chanID, midiCmd[1], midiCmd[2]); + send_event(1); + break; + case 0xB0: + snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]); + send_event(1); + break; + case 0xC0: + snd_seq_ev_set_pgmchange(&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); + send_event(1); + } + break; + default: + LOG(LOG_MISC,LOG_WARN)("ALSA:Unknown Command: %08x", (int)msg); + send_event(1); + break; + } + } + + void Close(void) { + if (seq_handle) + snd_seq_close(seq_handle); + } + + bool Open(const char * conf) { + char var[10]; + unsigned int caps; + + // try to use port specified in config file + if (conf && conf[0]) { + strncpy(var, conf, 10); + if (parse_addr(var, &seq_client, &seq_port) < 0) { + LOG_MSG("ALSA:Invalid alsa port %s", var); + return false; + } + } + // default port if none specified + else if (parse_addr("65:0", &seq_client, &seq_port) < 0) { + LOG_MSG("ALSA:Invalid alsa port 65:0"); + return false; + } + + if (my_snd_seq_open(&seq_handle)) { + LOG_MSG("ALSA:Can't open sequencer"); + return false; + } + + my_client = snd_seq_client_id(seq_handle); + snd_seq_set_client_name(seq_handle, "DOSBOX"); + snd_seq_set_client_group(seq_handle, "input"); + + caps = SND_SEQ_PORT_CAP_READ; + if (seq_client == SND_SEQ_ADDRESS_SUBSCRIBERS) + caps = ~SND_SEQ_PORT_CAP_SUBS_READ; + my_port = + snd_seq_create_simple_port(seq_handle, "DOSBOX", caps, + SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); + if (my_port < 0) { + snd_seq_close(seq_handle); + LOG_MSG("ALSA:Can't create ALSA port"); + return false; + } + + if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) { + /* subscribe to MIDI port */ + if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) { + snd_seq_close(seq_handle); + LOG_MSG("ALSA:Can't subscribe to MIDI port (%d:%d)", seq_client, seq_port); + return false; + } + } + + LOG_MSG("ALSA:Client initialised [%d:%d]", seq_client, seq_port); + return true; + } + +}; + +MidiHandler_alsa Midi_alsa; diff --git a/src/gui/midi_win32.h b/src/gui/midi_win32.h index 54d3317..bdac5de 100644 --- a/src/gui/midi_win32.h +++ b/src/gui/midi_win32.h @@ -47,7 +47,7 @@ public: }; void PlaySysex(Bit8u * sysex,Bitu len) { if (WaitForSingleObject (m_event, 2000) == WAIT_TIMEOUT) { - LOG(LOG_MISC|LOG_ERROR,"Can't send midi message"); + LOG(LOG_MISC,LOG_ERROR)("Can't send midi message"); return; } midiOutUnprepareHeader (m_out, &m_hdr, sizeof (m_hdr)); diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 356c628..c0cbf0d 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -16,6 +16,8 @@ * 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 $ */ + #include #include @@ -36,8 +38,8 @@ struct PalData { Bit8u blue; Bit8u unused; } rgb[256]; - Bitu first; - Bitu last; + volatile Bitu first; + volatile Bitu last; union { Bit32u bpp32[256]; Bit16u bpp16[256]; @@ -80,7 +82,6 @@ static struct { const char * dir; } shot; #endif - bool keep_small; bool screenshot; bool active; } render; @@ -252,12 +253,18 @@ void RENDER_DoUpdate(void) { static void RENDER_DrawScreen(void * data) { switch (render.op.type) { +#if (C_SSHOT) doagain: +#endif case OP_None: render.op.dest=render.op.pixels=data; render.src.draw_handler(render.op.part_handler); break; - case OP_Scale2x: + case OP_Blit: + render.op.dest=render.op.pixels=data; + render.src.draw_handler(render.op.part_handler); + break; + case OP_AdvMame2x: render.op.dest=render.op.pixels=data; render.src.draw_handler(render.op.part_handler); break; @@ -288,6 +295,17 @@ static void RENDER_Resize(Bitu * width,Bitu * height) { } } +static void Render_Blit_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags) { + 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; + RENDER_ResetPal(); +} + + void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags,RENDER_Draw_Handler draw_handler) { if ((!width) || (!height) || (!pitch)) { render.active=false;return; @@ -319,27 +337,32 @@ normalop: flags=0; break; case DoubleBoth: - if (render.keep_small) { - render.src.flags=0; - flags=0; - } else { - width*=2;height*=2; - flags=GFX_SHADOW; - } + render.src.flags=0; + flags=0; break; } mode_callback=Render_Normal_CallBack; break; - case OP_Scale2x: + 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: - if (render.keep_small) goto normalop; mode_callback=Render_Scale2x_CallBack; width*=2;height*=2; -#if defined (SCALE2X_NORMAL) +#if defined (SCALE2X_MMX) + flags=GFX_SHADOW; +#else flags=GFX_SHADOW; -#elif defined (SCALE2X_MMX) - flags=GFX_FIXED_BPP; #endif break; default: @@ -355,27 +378,28 @@ normalop: GFX_Start(); } +extern void GFX_SetTitle(Bits cycles, Bits frameskip); static void IncreaseFrameSkip(void) { if (render.frameskip.max<10) render.frameskip.max++; LOG_MSG("Frame Skip at %d",render.frameskip.max); + GFX_SetTitle(-1,render.frameskip.max); } static void DecreaseFrameSkip(void) { if (render.frameskip.max>0) render.frameskip.max--; LOG_MSG("Frame Skip at %d",render.frameskip.max); + GFX_SetTitle(-1,render.frameskip.max); } void RENDER_Init(Section * sec) { - MSG_Add("RENDER_CONFIGFILE_HELP","Available scalers: scale2x, none\n"); Section_prop * section=static_cast(sec); render.pal.first=256; render.pal.last=0; - render.keep_small=section->Get_bool("keepsmall"); render.frameskip.max=section->Get_int("frameskip"); render.frameskip.count=0; #if (C_SSHOT) - render.shot.dir=section->Get_string("snapshots"); + render.shot.dir=section->Get_string("snapdir"); KEYBOARD_AddEvent(KBD_f5,KBD_MOD_CTRL,EnableScreenShot); #endif const char * scaler;std::string cline; @@ -385,12 +409,14 @@ void RENDER_Init(Section * sec) { scaler=section->Get_string("scaler"); } if (!strcasecmp(scaler,"none")) render.op.want_type=OP_None; - else if (!strcasecmp(scaler,"scale2x")) render.op.want_type=OP_Scale2x; + else if (!strcasecmp(scaler,"normal2x")) render.op.want_type=OP_Normal2x; + else if (!strcasecmp(scaler,"advmame2x")) render.op.want_type=OP_AdvMame2x; else { render.op.want_type=OP_None; LOG_MSG("Illegal scaler type %s,falling back to none.",scaler); } KEYBOARD_AddEvent(KBD_f7,KBD_MOD_CTRL,DecreaseFrameSkip); KEYBOARD_AddEvent(KBD_f8,KBD_MOD_CTRL,IncreaseFrameSkip); + GFX_SetTitle(-1,render.frameskip.max); } diff --git a/src/gui/render_normal.h b/src/gui/render_normal.h index 5d4beee..32e131a 100644 --- a/src/gui/render_normal.h +++ b/src/gui/render_normal.h @@ -79,7 +79,6 @@ static void Normal_ ## FUNC ## _ ##BPP(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy Bitu next_src=render.src.pitch-dx; \ Bitu next_dest=(LINES_ ## FUNC*render.op.pitch) - (dx*PIXELS_ ## FUNC * SIZE_ ## BPP); \ dx/=LOOPSIZE; \ - dy--; \ for (;dy>0;dy--) { \ for (Bitu tempx=dx;tempx>0;tempx--) { \ NORMAL_LOOP(LOOPSIZE,FUNC,BPP); \ diff --git a/src/gui/render_scale2x.h b/src/gui/render_scale2x.h index 2cc1547..979b9dc 100644 --- a/src/gui/render_scale2x.h +++ b/src/gui/render_scale2x.h @@ -59,10 +59,6 @@ typedef Bit8u scale2x_uint8; typedef Bit16u scale2x_uint16; typedef Bit32u scale2x_uint32; -#if !defined(__GNUC__) || !defined(__i386__) - -#define SCALE2X_NORMAL 1 - 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); @@ -306,7 +302,7 @@ static void Scale2x_32(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { scale2x_line_32((Bit32u *)dest,(Bit32u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); } -#else +#if defined(__GNUC__) && defined(__i386__) #define SCALE2X_MMX 1 @@ -495,6 +491,8 @@ static __inline__ void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_ui "movq %%mm2,(%3)\n" "movq %%mm3,8(%3)\n" + "emms" + : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) : : "cc" @@ -536,11 +534,14 @@ static void Render_Scale2x_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,B render.op.height=height; render.op.bpp=bpp; render.op.pitch=pitch; - render.op.type=OP_Scale2x; -#if defined(SCALE2X_NORMAL) + 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;; @@ -552,10 +553,6 @@ static void Render_Scale2x_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,B E_Exit("RENDER:Unsupported display depth of %d",bpp); break; } -#elif defined(SCALE2X_MMX) - assert (bpp==8); - render.op.part_handler=Scale2x_8_mmx; -#endif RENDER_ResetPal(); } diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 7aeda67..bd5e217 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -15,13 +15,18 @@ * along with this program; if not, write to the Free Software * 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 $ */ + #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include #include #include #include +#include #include "SDL.h" #include "SDL_thread.h" @@ -39,10 +44,20 @@ //#define DISABLE_JOYSTICK #define C_GFXTHREADED 1 //Enabled by default -#if defined(MACOSX) +#if !(ENVIRON_INCLUDED) extern char** environ; #endif + +#ifdef WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#define STDOUT_FILE TEXT("stdout.txt") +#define STDERR_FILE TEXT("stderr.txt") +#endif + struct SDL_Block { volatile bool active; //If this isn't set don't draw volatile bool drawing; @@ -52,9 +67,9 @@ struct SDL_Block { Bitu flags; GFX_ModeCallBack mode_callback; bool full_screen; - bool nowait; + bool wait_on_error; SDL_Surface * surface; - SDL_Surface * shadow_surface; + SDL_Surface * blit_surface; SDL_Joystick * joy; SDL_cond *cond; #if C_GFXTHREADED @@ -76,25 +91,51 @@ struct SDL_Block { static SDL_Block sdl; static void CaptureMouse(void); +void GFX_SetTitle(Bits cycles,Bits frameskip){ + char title[200]={0}; + static Bits internal_cycles=0; + static Bits internal_frameskip=0; + if(cycles != -1) internal_cycles = cycles; + if(frameskip != -1) internal_frameskip = frameskip; + sprintf(title,"DOSBox %s, Cpu Cycles: %8d, Frameskip %2d",VERSION,internal_cycles,internal_frameskip); + SDL_WM_SetCaption(title,VERSION); +} + /* 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); } 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) 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.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; + } } 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 + ); + - SDL_WM_SetCaption(VERSION,VERSION); + GFX_SetTitle(-1,-1); Bitu flags=MODE_SET; if (sdl.full_screen) flags|=MODE_FULLSCREEN; @@ -141,6 +182,19 @@ 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; if (SDL_MUSTLOCK(sdl.surface)) { @@ -245,17 +299,17 @@ static void KillSwitch(void){ } static void GUI_StartUp(Section * sec) { - MSG_Add("SDL_CONFIGFILE_HELP","SDL related options.\n"); sec->AddDestroyFunction(&GUI_ShutDown); Section_prop * section=static_cast(sec); sdl.active=false; sdl.full_screen=false; - sdl.nowait=section->Get_bool("nowait"); + sdl.wait_on_error=section->Get_bool("waitonerror"); sdl.mouse.locked=false; sdl.mouse.requestlock=false; 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(); @@ -263,6 +317,10 @@ static void GUI_StartUp(Section * sec) { sdl.thread=SDL_CreateThread(&SDL_DisplayThread,0); #endif /* Initialize screen for first time */ + sdl.surface=SDL_SetVideoMode(640,400,0,0); + if (sdl.surface->format->BitsPerPixel==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); SDL_EnableUNICODE(1); @@ -270,6 +328,7 @@ static void GUI_StartUp(Section * sec) { KEYBOARD_AddEvent(KBD_f9,KBD_MOD_CTRL,KillSwitch); KEYBOARD_AddEvent(KBD_f10,KBD_MOD_CTRL,CaptureMouse); KEYBOARD_AddEvent(KBD_enter,KBD_MOD_ALT,SwitchFullScreen); + } void Mouse_AutoLock(bool enable) { @@ -397,7 +456,7 @@ static void HandleKey(SDL_KeyboardEvent * key) { /* Special Keys */ default: code=KBD_1; - LOG(LOG_ERROR|LOG_KEYBOARD,"Unhandled SDL keysym %d",key->keysym.sym); + LOG(LOG_KEYBOARD,LOG_ERROR)("Unhandled SDL keysym %d",key->keysym.sym); break; } /* Check the modifiers */ @@ -406,6 +465,12 @@ static void HandleKey(SDL_KeyboardEvent * key) { ((key->keysym.mod & KMOD_ALT) ? KBD_MOD_ALT : 0) | ((key->keysym.mod & KMOD_SHIFT) ? KBD_MOD_SHIFT : 0); Bitu ascii=key->keysym.unicode<128 ? key->keysym.unicode : 0; +#ifdef MACOSX + // HACK: Fix backspace on Mac OS X + // REMOVE ME oneday + if (code==KBD_backspace) + ascii=8; +#endif KEYBOARD_AddKey(code,ascii,mod,(key->state==SDL_PRESSED)); } @@ -520,31 +585,54 @@ void GFX_Events() { HandleVideoResize(&event.resize); break; case SDL_QUIT: - throw(true); + throw(0); break; } } } -void GFX_ShowMsg(char * msg) { - char buf[1024]; - strcpy(buf,msg); - strcat(buf,"\n"); - printf(buf); +void GFX_ShowMsg(char * format,...) { + char buf[512]; + va_list msg; + va_start(msg,format); + vsprintf(buf,format,msg); + strcat(buf,"\n"); + va_end(msg); + printf(buf); }; int main(int argc, char* argv[]) { - try { CommandLine com_line(argc,argv); Config myconf(&com_line); control=&myconf; - + + /* Can't disable the console with debugger enabled */ +#if defined(WIN32) && !(C_DEBUG) + if (control->cmdline->FindExist("-noconsole")) { + FreeConsole(); + /* Redirect standard input and standard output */ + freopen(STDOUT_FILE, "w", stdout); + freopen(STDERR_FILE, "w", stderr); + setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */ + setbuf(stderr, NULL); /* No buffering */ + } else { + if (AllocConsole()) { + fclose(stdin); + fclose(stdout); + fclose(stderr); + freopen("CONIN$","w",stdin); + freopen("CONOUT$","w",stdout); + freopen("CONOUT$","w",stderr); + } + } +#endif //defined(WIN32) && !(C_DEBUG) + #if C_DEBUG DEBUG_SetupConsole(); #endif - if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_CDROM + if ( SDL_Init( SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_CDROM #ifndef DISABLE_JOYSTICK |SDL_INIT_JOYSTICK @@ -554,8 +642,17 @@ int main(int argc, char* argv[]) { sdl_sec->Add_bool("fullscreen",false); sdl_sec->Add_bool("autolock",true); sdl_sec->Add_int("sensitivity",100); - sdl_sec->Add_bool("nowait",true); + sdl_sec->Add_bool("waitonerror",true); /* Init all the dosbox subsystems */ + + MSG_Add("SDL_CONFIGFILE_HELP", + "fullscreen -- Start dosbox directly in fullscreen.\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" + ); + + DOSBOX_Init(); std::string config_file; if (control->cmdline->FindString("-conf",config_file,true)) { @@ -565,7 +662,9 @@ int main(int argc, char* argv[]) { } /* Parse the config file */ control->ParseConfigFile(config_file.c_str()); +#if (ENVIRON_LINKED) control->ParseEnv(environ); +#endif /* Init all the sections */ control->Init(); /* Some extra SDL Functions */ @@ -586,10 +685,19 @@ int main(int argc, char* argv[]) { } catch (char * error) { if (sdl.full_screen) SwitchFullScreen(); if (sdl.mouse.locked) CaptureMouse(); - LOG_MSG("Exit to error: %sPress enter to continue.",error); - if(!sdl.nowait) fgetc(stdin); + LOG_MSG("Exit to error: %s",error); + if(sdl.wait_on_error) { + //TODO Maybe look for some way to show message in linux? +#if (C_DEBUG) + LOG_MSG("Press enter to continue",error); + fgetc(stdin); +#elif defined(WIN32) + Sleep(5000); +#endif + } + } - catch (...){ + catch (int){ if (sdl.full_screen) SwitchFullScreen(); if (sdl.mouse.locked) CaptureMouse(); } diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am index 6fca05e..efe5959 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_fonts.cpp vga_gfx.cpp \ + vga.cpp vga.h 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 + gus.cpp mpu401.cpp serialport.cpp softmodem.cpp diff --git a/src/hardware/Makefile.in b/src/hardware/Makefile.in index b266eb2..6e218a9 100644 --- a/src/hardware/Makefile.in +++ b/src/hardware/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,77 +13,122 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ AM_CPPFLAGS = -I$(top_srcdir)/include EXTRA_DIST = fmopl.c fmopl.h @@ -92,11 +137,12 @@ 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_fonts.cpp vga_gfx.cpp \ + vga.cpp vga.h 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 + gus.cpp mpu401.cpp serialport.cpp softmodem.cpp subdir = src/hardware +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -110,17 +156,13 @@ am_libhardware_a_OBJECTS = adlib.$(OBJEXT) dma.$(OBJEXT) \ mixer.$(OBJEXT) pcspeaker.$(OBJEXT) pic.$(OBJEXT) \ sblaster.$(OBJEXT) tandy_sound.$(OBJEXT) timer.$(OBJEXT) \ vga.$(OBJEXT) vga_attr.$(OBJEXT) vga_crtc.$(OBJEXT) \ - vga_dac.$(OBJEXT) vga_draw.$(OBJEXT) vga_fonts.$(OBJEXT) \ - vga_gfx.$(OBJEXT) vga_memory.$(OBJEXT) vga_misc.$(OBJEXT) \ - vga_seq.$(OBJEXT) cmos.$(OBJEXT) disney.$(OBJEXT) gus.$(OBJEXT) \ - mpu401.$(OBJEXT) + vga_dac.$(OBJEXT) vga_draw.$(OBJEXT) vga_gfx.$(OBJEXT) \ + vga_memory.$(OBJEXT) vga_misc.$(OBJEXT) vga_seq.$(OBJEXT) \ + cmos.$(OBJEXT) disney.$(OBJEXT) gus.$(OBJEXT) mpu401.$(OBJEXT) \ + serialport.$(OBJEXT) softmodem.$(OBJEXT) libhardware_a_OBJECTS = $(am_libhardware_a_OBJECTS) -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/adlib.Po ./$(DEPDIR)/cmos.Po \ @@ -131,25 +173,24 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ ./$(DEPDIR)/memory.Po ./$(DEPDIR)/mixer.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/mpu401.Po ./$(DEPDIR)/pcspeaker.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/pic.Po ./$(DEPDIR)/sblaster.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/serialport.Po ./$(DEPDIR)/softmodem.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/tandy_sound.Po ./$(DEPDIR)/timer.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/vga.Po ./$(DEPDIR)/vga_attr.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/vga_crtc.Po ./$(DEPDIR)/vga_dac.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_draw.Po ./$(DEPDIR)/vga_fonts.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_gfx.Po ./$(DEPDIR)/vga_memory.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_misc.Po ./$(DEPDIR)/vga_seq.Po +@AMDEP_TRUE@ ./$(DEPDIR)/vga_draw.Po ./$(DEPDIR)/vga_gfx.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vga_memory.Po ./$(DEPDIR)/vga_misc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/vga_seq.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ -CFLAGS = @CFLAGS@ 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 = $(libhardware_a_SOURCES) -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libhardware_a_SOURCES) all: all-am @@ -193,6 +234,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcspeaker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sblaster.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serialport.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/softmodem.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tandy_sound.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga.Po@am__quote@ @@ -200,32 +243,40 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_crtc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_dac.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_draw.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_fonts.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_gfx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_memory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_misc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga_seq.Po@am__quote@ -distclean-depend: - -rm -rf ./$(DEPDIR) - .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -251,20 +302,41 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -289,7 +361,6 @@ check: check-am all-am: Makefile $(LIBRARIES) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -309,7 +380,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -319,9 +390,11 @@ clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am @@ -342,6 +415,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -349,18 +424,25 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags distdir dvi \ - dvi-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/hardware/adlib.cpp b/src/hardware/adlib.cpp index dc8bb48..41db8d0 100644 --- a/src/hardware/adlib.cpp +++ b/src/hardware/adlib.cpp @@ -33,9 +33,11 @@ namespace MAME { /* Defines */ # define logerror(x) +#ifdef _MSC_VER /* Disable recurring warnings */ # pragma warning ( disable : 4018 ) # pragma warning ( disable : 4244 ) +#endif /* Work around ANSI compliance problem (see driver.h) */ struct __MALLOCPTR { diff --git a/src/hardware/cmos.cpp b/src/hardware/cmos.cpp index 4ce97dc..e44933b 100644 --- a/src/hardware/cmos.cpp +++ b/src/hardware/cmos.cpp @@ -16,43 +16,49 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include + #include "dosbox.h" #include "timer.h" #include "pic.h" #include "inout.h" -#include "config.h" +#include "mem.h" static struct { - Bit8u regs[0x40]; bool nmi; + bool bcd; Bit8u reg; struct { bool enabled; Bit8u div; Bitu micro; } timer; - Bit8u status_c; + struct { + Bit64u timer; + Bit64u ended; + Bit64u alarm; + } last; bool ack; bool update_ended; - } cmos; static void cmos_timerevent(void) { PIC_ActivateIRQ(8); + if(cmos.timer.enabled) PIC_AddEvent(cmos_timerevent,cmos.timer.micro); if (cmos.ack) { PIC_AddEvent(cmos_timerevent,cmos.timer.micro); - cmos.status_c=0x20; + cmos.regs[0x0c]|=0x0a0; cmos.ack=false; } } static void cmos_checktimer(void) { PIC_RemoveEvents(cmos_timerevent); - if (!cmos.timer.div && !cmos.timer.enabled) return; if (cmos.timer.div<=2) cmos.timer.div+=7; - cmos.timer.micro=(Bitu) (10000000.0/(32768.0 / (1 << (cmos.timer.div - 1)))); - LOG(LOG_PIT,"RTC Timer at %f hz",1000000.0/cmos.timer.micro); + cmos.timer.micro=(Bitu) (1000000.0/(32768.0 / (1 << (cmos.timer.div - 1)))); + if (!cmos.timer.div || !cmos.timer.enabled) return; + LOG(LOG_PIT,LOG_NORMAL)("RTC Timer at %f hz",1000000.0/cmos.timer.micro); PIC_AddEvent(cmos_timerevent,cmos.timer.micro); } @@ -64,56 +70,138 @@ void cmos_selreg(Bit32u port,Bit8u val) { static void cmos_writereg(Bit32u port,Bit8u val) { switch (cmos.reg) { case 0x00: /* Seconds */ - case 0x01: /* Seconds Alarm */ case 0x02: /* Minutes */ - case 0x03: /* Minutes Alarm */ case 0x04: /* Hours */ - case 0x05: /* Hours Alarm */ case 0x06: /* Day of week */ case 0x07: /* Date of month */ case 0x08: /* Month */ case 0x09: /* Year */ + /* Ignore writes to change alarm */ + break; + case 0x01: /* Seconds Alarm */ + case 0x03: /* Minutes Alarm */ + case 0x05: /* Hours Alarm */ + LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Trying to set alarm"); cmos.regs[cmos.reg]=val; break; + case 0x0a: /* Status reg A */ cmos.regs[cmos.reg]=val & 0x7f; - if (val & 0x70!=0x20) LOG(LOG_ERROR|LOG_BIOS,"CMOS Illegal 22 stage divider value"); + if (val & 0x70!=0x20) LOG(LOG_BIOS,LOG_ERROR)("CMOS Illegal 22 stage divider value"); cmos.timer.div=(val & 0xf); cmos_checktimer(); break; case 0x0b: /* Status reg B */ + cmos.bcd=!(val & 0x4); cmos.regs[cmos.reg]=val & 0x7f; cmos.timer.enabled=(val & 0x40)>0; - if (val&0x10) LOG(LOG_ERROR|LOG_BIOS,"CMOS:Updated ended interrupt not supported yet"); + if (val&0x10) LOG(LOG_BIOS,LOG_ERROR)("CMOS:Updated ended interrupt not supported yet"); cmos_checktimer(); break; + case 0x0f: /* Shutdown status byte */ + cmos.regs[cmos.reg]=val & 0x7f; + break; default: cmos.regs[cmos.reg]=val & 0x7f; - LOG(LOG_ERROR|LOG_BIOS,"CMOS:Unhandled register %x",cmos.reg); + LOG(LOG_BIOS,LOG_ERROR)("CMOS:WRite to unhandled register %x",cmos.reg); } } + +#define MAKE_RETURN(_VAL) (cmos.bcd ? (((_VAL / 10) << 4) | (_VAL % 10)) : _VAL); + static Bit8u cmos_readreg(Bit32u port) { if (cmos.reg>0x3f) { - LOG(LOG_ERROR|LOG_BIOS,"CMOS:Read from illegal register %x",cmos.reg); + LOG(LOG_BIOS,LOG_ERROR)("CMOS:Read from illegal register %x",cmos.reg); return 0xff; } + time_t curtime; + struct tm *loctime; + + /* Get the current time. */ + curtime = time (NULL); + + /* Convert it to local time representation. */ + loctime = localtime (&curtime); + switch (cmos.reg) { - case 0x0c: - if (cmos.ack) return 0; - else { - cmos.ack=true; - return 0x80|cmos.status_c; + case 0x00: /* Seconds */ + return MAKE_RETURN(loctime->tm_sec); + case 0x02: /* Minutes */ + return MAKE_RETURN(loctime->tm_min); + case 0x04: /* Hours */ + return MAKE_RETURN(loctime->tm_hour); + case 0x06: /* Day of week */ + return MAKE_RETURN(loctime->tm_wday); + case 0x07: /* Date of month */ + return MAKE_RETURN(loctime->tm_mday); + case 0x08: /* Month */ + return MAKE_RETURN(loctime->tm_mon); + case 0x09: /* Year */ + return MAKE_RETURN(loctime->tm_year); + case 0x01: /* Seconds Alarm */ + case 0x03: /* Minutes Alarm */ + case 0x05: /* Hours Alarm */ + return cmos.regs[cmos.reg]; + case 0x0a: /* Status register C */ + if (PIC_Index()<0x2) { + return (cmos.regs[0x0a]&0x7f) | 0x80; + } else { + return (cmos.regs[0x0a]&0x7f); } + case 0x0c: /* Status register C */ + if (cmos.timer.enabled) { + /* In periodic interrupt mode only care for those flags */ + Bit8u val=cmos.regs[0xc]; + cmos.regs[0xc]=0; + return val; + } else { + /* Give correct values at certain times */ + Bit8u val=0; + Bit64u index=PIC_MicroCount(); + if (index>=(cmos.last.timer+cmos.timer.micro)) { + cmos.last.timer=index; + val|=0x40; + } + if (index>=(cmos.last.ended+1000000)) { + cmos.last.ended=index; + val|=0x10; + } + return val; + } + case 0x0b: /* Status register B */ + case 0x0f: /* Shutdown status byte */ + case 0x17: /* Extended memory in KB Low Byte */ + case 0x18: /* Extended memory in KB High Byte */ + case 0x30: /* Extended memory in KB Low Byte */ + case 0x31: /* Extended memory in KB High Byte */ +// LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %F : %04X",cmos.reg,cmos.regs[cmos.reg]); + return cmos.regs[cmos.reg]; default: + LOG(LOG_BIOS,LOG_NORMAL)("CMOS:Read from reg %F",cmos.reg); return cmos.regs[cmos.reg]; } } +void CMOS_SetRegister(Bitu regNr, Bit8u val) +{ + cmos.regs[regNr] = val; +}; + void CMOS_Init(Section* sec) { IO_RegisterWriteHandler(0x70,cmos_selreg,"CMOS"); IO_RegisterWriteHandler(0x71,cmos_writereg,"CMOS"); IO_RegisterReadHandler(0x71,cmos_readreg,"CMOS"); cmos.timer.enabled=false; + cmos.reg=0xa; + cmos_writereg(0x71,0x26); + cmos.reg=0xb; + cmos_writereg(0x71,0); + /* Fill in extended memory size */ + Bitu exsize=(MEM_TotalPages()*4)-1024; + cmos.regs[0x17]=(Bit8u)exsize; + cmos.regs[0x18]=(Bit8u)(exsize >> 8); + cmos.regs[0x30]=(Bit8u)exsize; + cmos.regs[0x31]=(Bit8u)(exsize >> 8); } diff --git a/src/hardware/disney.cpp b/src/hardware/disney.cpp index b03fe52..423582d 100644 --- a/src/hardware/disney.cpp +++ b/src/hardware/disney.cpp @@ -47,7 +47,7 @@ static void disney_write(Bit32u port,Bit8u val) { disney.data=val; break; case 1: /* Status Port */ - LOG(LOG_MISC,"DISNEY:Status write %x",val); + LOG(LOG_MISC,LOG_NORMAL)("DISNEY:Status write %x",val); break; case 2: /* Control Port */ // LOG_WARN("DISNEY:Control write %x",val); @@ -56,7 +56,7 @@ static void disney_write(Bit32u port,Bit8u val) { disney.buffer[disney.used++]=disney.data; } } - if (val&0x10) LOG(LOG_ERROR,"DISNEY:Parallel IRQ Enabled"); + if (val&0x10) LOG(LOG_MISC,LOG_ERROR)("DISNEY:Parallel IRQ Enabled"); disney.control=val; break; } @@ -66,7 +66,7 @@ static Bit8u disney_read(Bit32u port) { switch (port-DISNEY_BASE) { case 0: /* Data Port */ -// LOG(LOG_MISC,"DISNEY:Read from data port"); +// LOG(LOG_MISC,LOG_NORMAL)("DISNEY:Read from data port"); return disney.data; break; case 1: /* Status Port */ @@ -75,7 +75,7 @@ static Bit8u disney_read(Bit32u port) { else return 0x0; break; case 2: /* Control Port */ - LOG(LOG_MISC,"DISNEY:Read from control port"); + LOG(LOG_MISC,LOG_NORMAL)("DISNEY:Read from control port"); return disney.control; break; } diff --git a/src/hardware/dma.cpp b/src/hardware/dma.cpp index 9f9e61b..7a35d16 100644 --- a/src/hardware/dma.cpp +++ b/src/hardware/dma.cpp @@ -32,12 +32,6 @@ #include "dma.h" #include "pic.h" -#if DEBUG_DMA -#define DMA_DEBUG LOG_DEBUG -#else -#define DMA_DEBUG -#endif - #define DMA_MODE_DEMAND 0 #define DMA_MODE_SINGLE 1 #define DMA_MODE_BLOCK 2 @@ -53,11 +47,12 @@ struct DMA_CHANNEL { Bit16u base_address; Bit16u base_count; Bit16u current_address; - Bit32u current_count; + Bitu current_count; Bit8u page; bool masked; PhysPt address; bool addr_changed; + bool enabled; DMA_EnableCallBack enable_callback; }; @@ -70,6 +65,10 @@ struct DMA_CONTROLLER { }; 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]; @@ -94,7 +93,7 @@ static Bit8u read_dma(Bit32u port) { break; case 0x08: /* Read Status */ ret=cont->status_reg; - cont->status_reg&=0xf; /* Clear lower 4 bits on read */ + cont->status_reg&=~0xf; /* Clear lower 4 bits on read */ break; case 0x0a: case 0x0e: @@ -102,12 +101,12 @@ static Bit8u read_dma(Bit32u port) { ret=0x0; break; default: - LOG(LOG_ERROR,"DMA:Unhandled read from %X",port); + LOG(LOG_DMA,LOG_ERROR)("DMA:Unhandled read from %X",port); } +// 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]; @@ -132,9 +131,10 @@ static void write_dma(Bit32u port,Bit8u val) { } cont->flipflop=!cont->flipflop; chan->addr_changed=true; + DMA_CheckEnabled(chan); break; case 0x08: /* Command Register */ - if (val != 4) LOG(LOG_ERROR,"DMA1:Illegal command %2X",val); + if (val != 4) LOG(LOG_DMA,LOG_ERROR)("DMA1:Illegal command %2X",val); cont->command_reg=val; break; case 0x09: /* Request Register */ @@ -149,8 +149,13 @@ static void write_dma(Bit32u port,Bit8u val) { break; case 0x0a: /* single mask bit register */ chan=&cont->chan[val & 0x3]; - chan->masked=(val & 4)>0; - if (chan->enable_callback) chan->enable_callback(!chan->masked); + 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]; @@ -159,19 +164,18 @@ static void write_dma(Bit32u port,Bit8u val) { chan->mode.autoinit_enable = (val & 0x10) > 0; chan->mode.transfer_type = (val >> 2) & 0x03; if (chan->mode.address_decrement) { - LOG(LOG_ERROR,"DMA:Address Decrease not supported yet"); + 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_ERROR,"DMA:Unhandled write %X to %X",val,port); + 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) { @@ -188,19 +192,33 @@ void write_dma_page(Bit32u port,Bit8u val) { dma[0].chan[channel].addr_changed=true; } +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; +} 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); } - - Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { DMA_CHANNEL * chan=&dma[0].chan[dmachan]; - if (chan->masked || !count) return 0; + 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); @@ -215,8 +233,10 @@ Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { /* Set the end of counter bit */ dma[0].status_reg|=(1 << dmachan); count=chan->current_count; - chan->current_address+=count;; + chan->address+=count; chan->current_count=0; + chan->enabled=false; + LOG(LOG_DMA,LOG_NORMAL)("8-bit Channel %d reached terminal count"); return count; } else { buffer+=chan->current_count; @@ -235,7 +255,8 @@ Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { DMA_CHANNEL * chan=&dma[0].chan[dmachan]; - if (chan->masked || !count) return 0; + 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); @@ -252,6 +273,7 @@ Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { count=chan->current_count; chan->current_address+=count;; chan->current_count=0; + chan->enabled=false; return count; } else { buffer+=chan->current_count; @@ -269,8 +291,6 @@ Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { } - - Bitu DMA_16_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { return 0; @@ -282,23 +302,39 @@ Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { return 0; } +void DMA_SetEnabled(DMA_CHANNEL * chan,bool enabled) { + if (chan->enabled == enabled) return; + chan->enabled=enabled; + if (chan->enable_callback) (*chan->enable_callback)(enabled); +} +void DMA_CheckEnabled(DMA_CHANNEL * chan) { + 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; + else enabled=false; + } + DMA_SetEnabled(chan,enabled); +} void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback) { + DMA_CHANNEL * chan; if (channel<4) { - dma[0].chan[channel].enable_callback=callback; - if (callback) callback(!dma[0].chan[channel].masked); - return; - } - if (channel<8) { - dma[1].chan[channel-4].enable_callback=callback; - if (callback) callback(!dma[1].chan[channel-4].masked); - } + chan=&dma[0].chan[channel]; + } else if (channel<8) { + chan=&dma[1].chan[channel-4]; + } else return; + chan->enabled=false; + chan->enable_callback=callback; + DMA_CheckEnabled(chan); } void DMA_Init(Section* sec) { - for (Bit32u i=0;i<0x10;i++) { + Bitu i; + for (i=0;i<0x10;i++) { IO_RegisterWriteHandler(i,write_dma,"DMA1"); IO_RegisterReadHandler(i,read_dma,"DMA1"); } @@ -306,4 +342,10 @@ void DMA_Init(Section* sec) { 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"); + } diff --git a/src/hardware/fmopl.c b/src/hardware/fmopl.c index ebc9792..b4d7c8e 100644 --- a/src/hardware/fmopl.c +++ b/src/hardware/fmopl.c @@ -1118,7 +1118,7 @@ static int init_tables(void) for (x=0; x0.0) - o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */ + o = 8*log(1.0/m)/log(2.0); /* convert to 'decibels' */ else - o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */ + o = 8*log(-1.0/m)/log(2.0); /* convert to 'decibels' */ o = o / (ENV_STEP/4); diff --git a/src/hardware/gameblaster.cpp b/src/hardware/gameblaster.cpp index 3deb674..29f6568 100644 --- a/src/hardware/gameblaster.cpp +++ b/src/hardware/gameblaster.cpp @@ -358,7 +358,7 @@ static void saa1099_write_port_w( int chip, int offset, int data ) break; default: /* Error! */ // logerror("%04x: (SAA1099 #%d) Unknown operation (reg:%02x, data:%02x)\n",activecpu_get_pc(), chip, reg, data); - LOG(0|LOG_ERROR,"CMS Unkown write to reg %x with %x",reg, data); + LOG(LOG_MISC,LOG_ERROR)("CMS Unkown write to reg %x with %x",reg, data); } } diff --git a/src/hardware/iohandler.cpp b/src/hardware/iohandler.cpp index 13138f8..6e2429e 100644 --- a/src/hardware/iohandler.cpp +++ b/src/hardware/iohandler.cpp @@ -24,12 +24,12 @@ IO_WriteBlock IO_WriteTable[IO_MAX]; void IO_Write(Bitu num,Bit8u val) { if (num(val),port); IO_RegisterWriteHandler(port,&IO_WriteBlocked,"Blocked Write"); } diff --git a/src/hardware/keyboard.cpp b/src/hardware/keyboard.cpp index 373483c..c73f585 100644 --- a/src/hardware/keyboard.cpp +++ b/src/hardware/keyboard.cpp @@ -21,6 +21,7 @@ #include "keyboard.h" #include "inout.h" #include "pic.h" +#include "mem.h" #include "mixer.h" #define KEYBUFSIZE 32 @@ -29,7 +30,8 @@ enum KeyCommands { CMD_NONE, CMD_SETLEDS, - CMD_SETTYPERATE + CMD_SETTYPERATE, + CMD_SETOUTPORT }; enum KeyStates { @@ -45,7 +47,7 @@ struct KeyCode { }; struct KeyEvent { - Bitu type; + Bits type; Bitu state; KEYBOARD_EventHandler * handler; KeyEvent * next; @@ -95,7 +97,7 @@ void KEYBOARD_GetCode(void) { keyb.buf.state=STATE_NORMAL; break; } - PIC_ActivateIRQ(1); + if (keyb.enabled) PIC_ActivateIRQ(1); } void KEYBOARD_AddCode(Bit8u scancode,Bit8u ascii,Bitu mod,KeyStates state) { @@ -178,9 +180,13 @@ static void write_p60(Bit32u port,Bit8u val) { KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ break; default: - LOG(LOG_ERROR|LOG_KEYBOARD,"60:Unhandled command %X",val); + LOG(LOG_KEYBOARD,LOG_ERROR)("60:Unhandled command %X",val); } return; + case CMD_SETOUTPORT: + MEM_A20_Enable((val & 2)>0); + break; + case CMD_SETTYPERATE: case CMD_SETLEDS: keyb.command=CMD_NONE; @@ -206,14 +212,28 @@ static void write_p61(Bit32u port,Bit8u val) { static void write_p64(Bit32u port,Bit8u val) { switch (val) { - case 0xad: /* Activate keyboard */ + case 0xae: /* Activate keyboard */ keyb.active=true; + if (keyb.buf.used && !keyb.scheduled) { + keyb.scheduled=true; + PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); + } + LOG(LOG_KEYBOARD,LOG_NORMAL)("Activated"); break; - case 0xae: /* Deactivate keyboard */ + case 0xad: /* Deactivate keyboard */ keyb.active=false; + PIC_DeActivateIRQ(1); + PIC_RemoveEvents(KEYBOARD_GetCode); + LOG(LOG_KEYBOARD,LOG_NORMAL)("De-Activated"); + break; + case 0xd0: /* Outport on buffer */ + KEYBOARD_AddCode(MEM_A20_Enabled() ? 0x02 : 0,0,0,STATE_NORMAL); + break; + case 0xd1: /* Write to outport */ + keyb.command=CMD_SETOUTPORT; break; default: - LOG(LOG_ERROR|LOG_KEYBOARD,"Port 64 write with val %d",val); + LOG(LOG_KEYBOARD,LOG_ERROR)("Port 64 write with val %d",val); break; } } @@ -226,7 +246,7 @@ void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler) KeyEvent * newevent=new KeyEvent; /* Add the event in the correct key structure */ if (keytype>=KBD_LAST) { - LOG(LOG_ERROR|LOG_KEYBOARD,"Illegal key %d for handler",keytype); + LOG(LOG_KEYBOARD,LOG_ERROR)("Illegal key %d for handler",keytype); } newevent->next=event_handlers[keytype]; event_handlers[keytype]=newevent; @@ -352,7 +372,7 @@ void KEYBOARD_AddKey(KBD_KEYS keytype,Bitu unicode,Bitu mod,bool pressed) { case KBD_insert:extend=true;ret=82;break; case KBD_delete:extend=true;ret=83;break; default: - E_Exit("Unsopperted key press"); + E_Exit("Unsupported key press"); break; } /* check for active key events */ @@ -383,6 +403,7 @@ void KEYBOARD_Init(Section* sec) { port_61_data=0; /* Direct Speaker control and output disabled */ // memset(&event_handlers,0,sizeof(event_handlers)); /* Clear the keyb struct */ + keyb.active=true; keyb.enabled=true; keyb.command=CMD_NONE; keyb.last_index=0; diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index cec5c27..e91b9d5 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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,236 +20,869 @@ #include #include #include + #include "dosbox.h" #include "mem.h" +#include "inout.h" +#include "setup.h" +#include "paging.h" +#include "vga.h" -HostPt memory; -HostPt ReadHostTable[MAX_PAGES]; -HostPt WriteHostTable[MAX_PAGES]; -MEMORY_ReadHandler ReadHandlerTable[MAX_PAGES]; -MEMORY_WriteHandler WriteHandlerTable[MAX_PAGES]; +#define PAGES_IN_BLOCK ((1024*1024)/MEM_PAGE_SIZE) +#define MAX_MEMORY 64 +#define LFB_PAGES 512 -/* Page handlers only work in lower memory */ -#define LOW_PAGE_LIMIT PAGE_COUNT(1024*1024) -#define MAX_PAGE_LIMIT PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024) +static Bit8u controlport_data; +static bool a20_enabled; -void MEM_BlockRead(PhysPt off,void * data,Bitu size) { - Bit8u * idata=(Bit8u *)data; - while (size>0) { - Bitu page=off >> PAGE_SHIFT; - Bitu start=off & (PAGE_SIZE-1); - Bitu tocopy=PAGE_SIZE-start; - if (tocopy>size) tocopy=size; - size-=tocopy; - if (ReadHostTable[page]) { - memcpy(idata,ReadHostTable[page]+off,tocopy); - idata+=tocopy;off+=tocopy; - } else { - for (;tocopy>0;tocopy--) *idata++=ReadHandlerTable[page](off++); +struct AllocBlock { + Bit8u data[PAGES_IN_BLOCK*4096]; + AllocBlock * next; +}; + +static struct MemoryBlock { + Bitu pages; + Bitu free_pages; + PageEntry * entries; + struct { + Bitu pages; + HostPt cur_page; + AllocBlock *cur_block; + } block; + struct { + Bitu start_page; + 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; +} 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); + } + return 0; +} + +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); + } + return 0; +} + +Bit32u ENTRY_readd(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) | + ((*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_BlockWrite(PhysPt off,void * data,Bitu size) { - Bit8u * idata=(Bit8u *)data; - while (size>0) { - Bitu page=off >> PAGE_SHIFT; - Bitu start=off & (PAGE_SIZE-1); - Bitu tocopy=PAGE_SIZE-start; - if (tocopy>size) tocopy=size; - size-=tocopy; - if (WriteHostTable[page]) { - memcpy(WriteHostTable[page]+off,idata,tocopy); - idata+=tocopy;off+=tocopy; - } else { - for (;tocopy>0;tocopy--) WriteHandlerTable[page](off++,*idata++); +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) { + if (!mem_readb_inline(pt+x)) return x; + x++; + } + return 0; //Hope this doesn't happend +} + +void mem_strcpy(PhysPt dest,PhysPt src) { + Bit8u r; + while (r=mem_readb(src++)) mem_writeb_inline(dest++,r); + mem_writeb_inline(dest,0); +} + +void mem_memcpy(PhysPt dest,PhysPt src,Bitu size) { + while (size--) mem_writeb_inline(dest++,mem_readb_inline(src++)); +} + +void MEM_BlockRead(PhysPt pt,void * data,Bitu size) { + Bit8u * write=(Bit8u *) data; + while (size--) { + *write++=mem_readb_inline(pt++); + } +} + +void MEM_BlockWrite(PhysPt pt,void * data,Bitu size) { + Bit8u * read=(Bit8u *) data; + while (size--) { + mem_writeb_inline(pt++,*read++); } } void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size) { - Bitu c; - for (c=1;c<=(size>>2);c++) { - mem_writed(dest,mem_readd(src)); - dest+=4;src+=4; - } - for (c=1;c<=(size&3);c++) { - mem_writeb(dest,mem_readb(src)); - dest+=1;src+=1; - } -}; - -void MEM_StrCopy(PhysPt off,char * data,Bitu size) { - Bit8u c; - while ((c=mem_readb(off)) && size) { - *data=c; - off++;data++;size--; - } - *data='\0'; + mem_memcpy(dest,src,size); } -static Bit8u Illegal_ReadHandler(PhysPt pt) { - LOG(LOG_ERROR,"MEM:Illegal read from address %4X",pt); +void MEM_StrCopy(PhysPt pt,char * data,Bitu size) { + while (size--) { + Bit8u r=mem_readb_inline(pt++); + if (!r) break; + *data++=r; + } + *data=0; +} + +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; + size=0; + } + index++; + } + if (size>largest) largest=size; + return largest; +} + +Bitu MEM_FreeTotal(void) { + Bitu free=0; + Bitu index=XMS_START; + while (index0) { + pages++; + handle=memory.entries[handle].next_handle; + } + return pages; +} + +//TODO Maybe some protection for this whole allocation scheme + +INLINE Bitu BestMatch(Bitu size) { + Bitu index=XMS_START; + Bitu first=0; + Bitu best=0xfffffff; + Bitu best_first=0; + while (indexsize) { + if (pages=size) && (index-first0) { + MemHandle next=memory.entries[handle].next_handle; + memory.entries[handle].next_handle=0; + handle=next; + } +} + +bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence) { + if (handle<0) { + if (!pages) return true; + handle=MEM_AllocatePages(pages,sequence); + return (handle>0); + } + if (!pages) { + MEM_ReleasePages(handle); + handle=-1; + return true; + } + MemHandle index=handle; + MemHandle last;Bitu old_pages=0; + while (index>0) { + old_pages++; + last=index; + index=memory.entries[index].next_handle; + } + 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; + pages--;old_pages--; + } + MemHandle next=memory.entries[index].next_handle; + memory.entries[index].next_handle=-1; + index=next; + while (old_pages) { + next=memory.entries[index].next_handle; + memory.entries[index].next_handle=0; + index=next; + old_pages--; + } + return true; + } else { + /* Increase size, check for enough free space */ + Bitu need=pages-old_pages; + 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; + need--;index++; + } + memory.entries[index].next_handle=-1; + return true; + } else { + /* Not Enough space allocate new block and copy */ + MemHandle newhandle=MEM_AllocatePages(pages,true); + if (!newhandle) return false; + MEM_BlockCopy(newhandle*4096,handle*4096,old_pages*4096); + MEM_ReleasePages(handle); + handle=newhandle; + return true; + } + } else { + MemHandle rem=MEM_AllocatePages(need,false); + if (!rem) return false; + memory.entries[last].next_handle=rem; + return true; + } + } return 0; } -static void Illegal_WriteHandler(PhysPt pt,Bit8u val) { - LOG(LOG_ERROR,"Illegal write val %2X to address %4X",val,pt); -} - -/* Could only be called when the pt host entry is 0 ah well :) */ -static Bit8u Default_ReadHandler(PhysPt pt) { - return readb(WriteHostTable[pt >> PAGE_SHIFT]+pt); -} -static void Default_WriteHandler(PhysPt pt,Bit8u val) { - writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); -} -void MEM_SetupPageHandlers(Bitu startpage,Bitu pages,MEMORY_ReadHandler read,MEMORY_WriteHandler write) { - if (startpage+pages>=LOW_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); - for (Bitu i=startpage;i=LOW_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); - for (Bitu i=startpage;i=MAX_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); - HostPt base=(HostPt)(data)-startpage*PAGE_SIZE; - if (!base) LOG_MSG("MEMORY:Unlucky memory allocation"); - for (Bitu i=startpage;i=MAX_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); - for (Bitu i=startpage;i> 8) & 0xff) ); +/* + 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; } -static void HandlerWrited(Bitu page,PhysPt pt,Bit32u val) { - WriteHandlerTable[page](pt+0,(Bit8u)(val & 0xff)); - WriteHandlerTable[page](pt+1,(Bit8u)((val >> 8) & 0xff) ); - WriteHandlerTable[page](pt+2,(Bit8u)((val >> 16) & 0xff) ); - WriteHandlerTable[page](pt+3,(Bit8u)((val >> 24) & 0xff) ); -} - -void mem_writeb(PhysPt pt,Bit8u val) { - if (WriteHostTable[pt >> PAGE_SHIFT]) writeb(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); - else { - WriteHandlerTable[pt >> PAGE_SHIFT](pt,val); - } -} - -void mem_writew(PhysPt pt,Bit16u val) { - if (!WriteHostTable[pt >> PAGE_SHIFT]) { -// HandlerWritew(pt >> PAGE_SHIFT,pt,val); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff)); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) ); - } else writew(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); -} - -void mem_writed(PhysPt pt,Bit32u val) { - if (!WriteHostTable[pt >> PAGE_SHIFT]) { -// HandlerWrited(pt >> PAGE_SHIFT,pt,val); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+0,(Bit8u)(val & 0xff)); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+1,(Bit8u)((val >> 8) & 0xff) ); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+2,(Bit8u)((val >> 16) & 0xff) ); - WriteHandlerTable[pt >> PAGE_SHIFT](pt+3,(Bit8u)((val >> 24) & 0xff) ); - } else writed(WriteHostTable[pt >> PAGE_SHIFT]+pt,val); -} - - -static Bit16u HandlerReadw(Bitu page,PhysPt pt) { - return (ReadHandlerTable[page](pt+0)) | - (ReadHandlerTable[page](pt+1)) << 8; -} - -static Bit32u HandlerReadd(Bitu page,PhysPt pt) { - return (ReadHandlerTable[page](pt+0)) | - (ReadHandlerTable[page](pt+1)) << 8 | - (ReadHandlerTable[page](pt+2)) << 16 | - (ReadHandlerTable[page](pt+3)) << 24; -} - -Bit8u mem_readb(PhysPt pt) { - if (ReadHostTable[pt >> PAGE_SHIFT]) return readb(ReadHostTable[pt >> PAGE_SHIFT]+pt); - else { - return ReadHandlerTable[pt >> PAGE_SHIFT](pt); - } -} - -Bit16u mem_readw(PhysPt pt) { - if (!ReadHostTable[pt >> PAGE_SHIFT]) { -// return HandlerReadw(pt >> PAGE_SHIFT,pt); - return - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) | - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8; - } else return readw(ReadHostTable[pt >> PAGE_SHIFT]+pt); -} - -Bit32u mem_readd(PhysPt pt){ - if (ReadHostTable[pt >> PAGE_SHIFT]) return readd(ReadHostTable[pt >> PAGE_SHIFT]+pt); - else { -// return HandlerReadd(pt >> PAGE_SHIFT,pt); - return - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+0)) | - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+1)) << 8 | - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+2)) << 16 | - (ReadHandlerTable[pt >> PAGE_SHIFT](pt+3)) << 24; - } -} -#endif - - - -void MEM_Init(Section * sect) { - /* Init all tables */ +void MEM_A20_Enable(bool enabled) { + a20_enabled=enabled; Bitu i; - i=MAX_PAGES; - for (i=0;i>=8; + mem_writeb_inline(address+1,(Bit8u)val); +} + +void mem_unalignedwrited(PhysPt address,Bit32u val) { + mem_writeb_inline(address,(Bit8u)val);val>>=8; + mem_writeb_inline(address+1,(Bit8u)val);val>>=8; + mem_writeb_inline(address+2,(Bit8u)val);val>>=8; + mem_writeb_inline(address+3,(Bit8u)val); +} + + +Bit8u mem_readb(PhysPt address) { + return mem_readb_inline(address); +} + +Bit16u mem_readw(PhysPt address) { + return mem_readw_inline(address); +} + +Bit32u mem_readd(PhysPt address) { + return mem_readd_inline(address); +} + +void mem_writeb(PhysPt address,Bit8u val) { + mem_writeb_inline(address,val); +} + +void mem_writew(PhysPt address,Bit16u val) { + mem_writew_inline(address,val); +} + +void mem_writed(PhysPt address,Bit32u val) { + mem_writed_inline(address,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); + } + writeb(theentry->data.mem+(addr & 4095),val); +} + +void phys_writew(PhysPt addr,Bit16u val) { + phys_writeb(addr,(Bit8u)val); + phys_writeb(addr+1,(Bit8u)(val >> 8)); +} + +void phys_writed(PhysPt addr,Bit32u val) { + phys_writeb(addr,(Bit8u)val); + phys_writeb(addr+1,(Bit8u)(val >> 8)); + phys_writeb(addr+2,(Bit8u)(val >> 16)); + 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); + } + return 0; +} + + +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; + MEM_A20_Enable((val & 2)>0); +} + +static Bit8u read_p92(Bit32u port) { + return controlport_data | (a20_enabled ? 0x02 : 0); +} + + +PageDirectory * MEM_DefaultDirectory(void) { + return &memory.dir; +} + +HostPt MEM_GetBlockPage(void) { + HostPt ret; + if (memory.block.pages) { + ret=memory.block.cur_page; + memory.block.pages--; + memory.block.cur_page+=4096; + } else { + AllocBlock * newblock=new AllocBlock; + memset(newblock,0,sizeof(AllocBlock)); //zero new allocated memory + newblock->next=memory.block.cur_block; + memory.block.cur_block=newblock; + + memory.block.pages=PAGES_IN_BLOCK-1; + ret=&newblock->data[0]; + memory.block.cur_page=&newblock->data[4096]; + } + return ret; +} + +static void MEM_ShutDown(Section * sec) { + AllocBlock * theblock=memory.block.cur_block; + while (theblock) { + AllocBlock * next=theblock->next; + delete theblock; + theblock=next; + } +} + +void MEM_Init(Section * sec) { + Bitu i; + Section_prop * section=static_cast(sec); + + /* Setup Memory Block */ + memory.block.pages=0; + memory.block.cur_block=0; + + /* Setup the Physical Page Links */ + Bitu memsize=section->Get_int("memsize"); + + if (memsize<1) memsize=1; + if (memsize>MAX_MEMORY) { + LOG_MSG("Maximum memory size is %d MB",MAX_MEMORY); + 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]; + for (i=0;iAddDestroyFunction(&MEM_ShutDown); } diff --git a/src/hardware/mixer.cpp b/src/hardware/mixer.cpp index 6bb6bc9..f3cc674 100644 --- a/src/hardware/mixer.cpp +++ b/src/hardware/mixer.cpp @@ -230,7 +230,7 @@ static void MIXER_CallBack(void * userdata, Uint8 *stream, int len) { /* Copy data from out buffer to the stream */ Bitu size=MIXER_BUFSIZE+mixer.out.write-mixer.out.read; if (size>=MIXER_BUFSIZE) size-=MIXER_BUFSIZE; - if (size*MIXER_SSIZEd_name); char * test=strstr(tempname,".wav"); @@ -304,10 +304,9 @@ static void MIXER_Stop(Section* sec) { void MIXER_Init(Section* sec) { sec->AddDestroyFunction(&MIXER_Stop); - MSG_Add("MIXER_CONFIGFILE_HELP","Nothing to setup yet!\n"); Section_prop * section=static_cast(sec); /* Read out config section */ - mixer.freq=section->Get_int("freq"); + mixer.freq=section->Get_int("rate"); mixer.nosound=section->Get_bool("nosound"); mixer.blocksize=section->Get_int("blocksize"); mixer.wave.dir=section->Get_string("wavedir"); diff --git a/src/hardware/mpu401.cpp b/src/hardware/mpu401.cpp index ff9e9bb..d68e0a3 100644 --- a/src/hardware/mpu401.cpp +++ b/src/hardware/mpu401.cpp @@ -158,7 +158,7 @@ static void QueueByte(Bit8u data) { if (pos>=MPU_QUEUE) pos-=MPU_QUEUE; mpu.queue_used++; mpu.queue[pos]=data; - } else LOG(LOG_MISC,"MPU401:Data queue full"); + } else LOG(LOG_MISC,LOG_NORMAL)("MPU401:Data queue full"); } static void ClrQueue(void) { @@ -184,7 +184,7 @@ static void MPU401_WriteCommand(Bit32u port,Bit8u val) { break; default: - LOG(LOG_MISC,"MPU401:Unhandled command %X",val); + LOG(LOG_MISC,LOG_NORMAL)("MPU401:Unhandled command %X",val); QueueByte(MSG_CMD_ACK); break; } diff --git a/src/hardware/pcspeaker.cpp b/src/hardware/pcspeaker.cpp index 85a255a..a536195 100644 --- a/src/hardware/pcspeaker.cpp +++ b/src/hardware/pcspeaker.cpp @@ -206,9 +206,8 @@ static void PCSPEAKER_CallBack(Bit8u * stream,Bit32u len) { } void PCSPEAKER_Init(Section* sec) { - MSG_Add("SPEAKER_CONFIGFILE_HELP","PC-Speaker and TandySound options.\n"); Section_prop * section=static_cast(sec); - if(!section->Get_bool("enabled")) return; + if(!section->Get_bool("pcspeaker")) return; spkr.volume=SPKR_VOLUME; spkr.mode=MODE_NONE; spkr.pit_mode=MODE_WAVE; diff --git a/src/hardware/pic.cpp b/src/hardware/pic.cpp index 98ec2f3..1882138 100644 --- a/src/hardware/pic.cpp +++ b/src/hardware/pic.cpp @@ -16,11 +16,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include "dosbox.h" #include "inout.h" #include "cpu.h" #include "pic.h" +#include "timer.h" #define PIC_QUEUESIZE 128 @@ -28,31 +30,36 @@ struct IRQ_Block { bool masked; bool active; bool inservice; - Bit8u vector; + Bitu vector; char * name; PIC_EOIHandler * handler; }; -Bitu PIC_Ticks=0; +struct PIC_Controller { + Bitu icw_words; + Bitu icw_index; + Bitu masked; + Bitu active; + Bitu inservice; + bool auto_eoi; + bool request_issr; + Bit8u vector_base; +}; + +Bitu PIC_Ticks=0; Bitu PIC_IRQCheck; Bitu PIC_IRQActive; + static IRQ_Block irqs[16]; -static Bit8u pic0_icws=0; -static Bit8u pic1_icws=0; -static Bit8u pic0_icw_state=0; -static Bit8u pic1_icw_state=0; -static bool pic0_request_iisr=0; -static bool pic1_request_iisr=0; +static PIC_Controller pics[2]; + enum QUEUE_TYPE { IRQ,EVENT }; - - - struct PICEntry { QUEUE_TYPE type; Bitu irq; @@ -61,240 +68,125 @@ struct PICEntry { PICEntry * next; }; - static struct { PICEntry entries[PIC_QUEUESIZE]; PICEntry * free_entry; PICEntry * next_entry; } pic; -static void write_p20(Bit32u port,Bit8u val) { +static void write_command(Bit32u port,Bit8u val) { + PIC_Controller * pic=&pics[port==0x20 ? 0 : 1]; + Bitu irq_base=port==0x20 ? 0 : 8; switch (val) { case 0x0A: /* select read interrupt request register */ - pic0_request_iisr=false; + pic->request_issr=false; break; case 0x0B: /* select read interrupt in-service register */ - pic0_request_iisr=true; + pic->request_issr=true; break; case 0x10: /* ICW1 */ - pic0_icws=2; - pic0_icw_state=1; + pic->icw_index=1; + pic->icw_words=2; break; case 0x11: /* ICW1 + need for ICW4 */ - pic0_icws=3; - pic0_icw_state=1; + pic->icw_index=1; + pic->icw_words=3; break; - case 0x20: /* end of interrupt command */ - case 0x21: /* end of interrupt command */ - case 0x22: /* end of interrupt command */ - case 0x23: /* end of interrupt command */ - case 0x24: /* end of interrupt command */ - case 0x25: /* end of interrupt command */ - case 0x26: /* end of interrupt command */ - case 0x27: /* end of interrupt command */ - /* clear highest current in service bit */ - if (PIC_IRQActive<8) { + case 0x20:case 0x21:case 0x22:case 0x23:case 0x24:case 0x25:case 0x26:case 0x27: + if (PIC_IRQActive<(irq_base+8)) { irqs[PIC_IRQActive].inservice=false; if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler(); PIC_IRQActive=PIC_NOIRQ; - } + }//TODO Warnings? break; - case 0x60: /* specific EOI 0 */ - case 0x61: /* specific EOI 1 */ - case 0x62: /* specific EOI 2 */ - case 0x63: /* specific EOI 3 */ - case 0x64: /* specific EOI 4 */ - case 0x65: /* specific EOI 5 */ - case 0x66: /* specific EOI 6 */ - case 0x67: /* specific EOI 7 */ - if (PIC_IRQActive==(val-0x60U)) { + case 0x60:case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66:case 0x67: + /* Spefific EOI 0-7 */ + if (PIC_IRQActive==(irq_base+val-0x60U)) { irqs[PIC_IRQActive].inservice=false; if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler(); PIC_IRQActive=PIC_NOIRQ; - } + }//TODO Warnings? break; - // IRQ lowest priority commands - case 0xC0: // 0 7 6 5 4 3 2 1 - case 0xC1: // 1 0 7 6 5 4 3 2 - case 0xC2: // 2 1 0 7 6 5 4 3 - case 0xC3: // 3 2 1 0 7 6 5 4 - case 0xC4: // 4 3 2 1 0 7 6 5 - case 0xC5: // 5 4 3 2 1 0 7 6 - case 0xC6: // 6 5 4 3 2 1 0 7 - case 0xC7: // 7 6 5 4 3 2 1 0 - // ignore for now TODO + case 0xC0:case 0xC1:case 0xC2:case 0xC3:case 0xC4:case 0xC5:case 0xC6:case 0xC7: + /* Priority order, no need for it */ break; default: - E_Exit("PIC0:Unhandled command %02X",val); + E_Exit("PIC:Unhandled command %02X",val); } } -//Pic 0 Interrupt mask -static void write_p21(Bit32u port,Bit8u val) { - Bit8u i; - switch(pic0_icw_state) { +static void write_data(Bit32u port,Bit8u val) { + PIC_Controller * pic=&pics[port==0x21 ? 0 : 1]; + Bitu irq_base=(port==0x21) ? 0 : 8; + Bitu i; + switch(pic->icw_index) { case 0: /* mask register */ for (i=0;i<=7;i++) { - irqs[i].masked=(val&(1<0; - if (irqs[i].active && !irqs[i].masked) PIC_IRQCheck|=(1 << 1); - else PIC_IRQCheck&=~(1 << 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)); }; break; case 1: /* icw2 */ - LOG(LOG_PIC,"PIC0:Base vector %X",val); + LOG(LOG_PIC,LOG_NORMAL)("%d:Base vector %X",static_cast(port==0x21 ? 0 : 1),static_cast(val)); for (i=0;i<=7;i++) { - irqs[i].vector=(val&0xf8)+i; + irqs[i+irq_base].vector=(val&0xf8)+i; }; - default: /* icw2, 3, and 4*/ - if(pic0_icw_state++ >= pic0_icws) pic0_icw_state=0; + 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)); + if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; + break; + case 3: /* icw 4 */ + /* + 0 1 8086/8080 0 mcs-8085 mode + 1 1 Auto EOI 1 Normal EOI + 2-3 0x Non buffer Mode + 10 Buffer Mode Slave + 11 Buffer mode Master + 4 Special/Not Special nested mode + */ + pic->auto_eoi=(val & 0x2)>0; + + LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 4 %X",static_cast(port==0x21 ? 0 : 1),static_cast(val)); + if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; + break; + default: /* icw 3, and 4*/ + LOG(LOG_PIC,LOG_NORMAL)("ICW HUH? %X",val); } } -static Bit8u read_p20(Bit32u port) { - Bit8u ret=0; - Bit32u i; - Bit8u b=1; - if (pic0_request_iisr) { - for (i=0;i<=7;i++) { + +static Bit8u read_command(Bit32u port) { + PIC_Controller * pic=&pics[port==0x20 ? 0 : 1]; + Bitu irq_base=(port==0x20) ? 0 : 8; + Bitu i;Bit8u ret=0;Bit8u b=1; + if (pic->request_issr) { + for (i=irq_base;i7 && PIC_IRQActive <16) { - irqs[PIC_IRQActive].inservice=false; - if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler(); - PIC_IRQActive=PIC_NOIRQ; - } - break; - case 0x60: /* specific EOI 0 */ - case 0x61: /* specific EOI 1 */ - case 0x62: /* specific EOI 2 */ - case 0x63: /* specific EOI 3 */ - case 0x64: /* specific EOI 4 */ - case 0x65: /* specific EOI 5 */ - case 0x66: /* specific EOI 6 */ - case 0x67: /* specific EOI 7 */ - if (PIC_IRQActive==(8+val-0x60U)) { - irqs[PIC_IRQActive].inservice=false; - if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler(); - PIC_IRQActive=PIC_NOIRQ; - }; - break; - // IRQ lowest priority commands - case 0xC0: // 0 7 6 5 4 3 2 1 - case 0xC1: // 1 0 7 6 5 4 3 2 - case 0xC2: // 2 1 0 7 6 5 4 3 - case 0xC3: // 3 2 1 0 7 6 5 4 - case 0xC4: // 4 3 2 1 0 7 6 5 - case 0xC5: // 5 4 3 2 1 0 7 6 - case 0xC6: // 6 5 4 3 2 1 0 7 - case 0xC7: // 7 6 5 4 3 2 1 0 - //TODO Maybe does it even matter? - break; - default: - E_Exit("Unhandled command %04X sent to port A0",val); - } -} - - -static void write_pa1(Bit32u port,Bit8u val) { - Bit8u i; - switch(pic1_icw_state) { - case 0: /* mask register */ - for (i=0;i<=7;i++) { - irqs[i+8].masked=(val&1 <0; - }; - break; - case 1: /* icw2 */ - for (i=0;i<=7;i++) { - irqs[i+8].vector=(val&0xf8)+i; - }; - default: /* icw2, 3, and 4*/ - if(pic1_icw_state++ >= pic1_icws) pic1_icw_state=0; - } -} - -static Bit8u read_pa0(Bit32u port) { - Bit8u ret=0; - Bit32u i; - Bit8u b=1; - if (pic1_request_iisr) { - for (i=0;i<=7;i++) { - if (irqs[i+8].inservice) ret|=b; - b <<= 1; - } - } else { - for (i=0;i<=7;i++) { - if (irqs[i+8].active) ret|=b; - b <<= 1; - } - } - return ret; -} - - -static Bit8u read_pa1(Bit32u port) { - Bit8u ret=0; - Bit32u i; - Bit8u b=1; - for (i=0;i<=7;i++) { - if (irqs[i+8].masked) ret|=b; - b <<= 1; - } - return ret; -} - void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name) { if (irq>15) E_Exit("PIC:Illegal IRQ"); irqs[irq].name=name; @@ -328,17 +220,19 @@ void PIC_DeActivateIRQ(Bit32u irq) { void PIC_runIRQs(void) { Bitu i; - if (!flags.intf) return; + if (!GETFLAG(IF)) return; if (PIC_IRQActive!=PIC_NOIRQ) return; if (!PIC_IRQCheck) return; for (i=0;i<=15;i++) { if (i!=2) { if (!irqs[i].masked && irqs[i].active) { - irqs[i].inservice=true; irqs[i].active=false; PIC_IRQCheck&=~(1 << i); Interrupt(irqs[i].vector); - PIC_IRQActive=i; + if (!pics[0].auto_eoi) { + PIC_IRQActive=i; + irqs[i].inservice=true; + } return; } } @@ -350,34 +244,35 @@ static void AddEntry(PICEntry * entry) { if (!find_entry) { entry->next=0; pic.next_entry=entry; - return; - } - if (find_entry->index>entry->index) { + } else if (find_entry->index>entry->index) { pic.next_entry=entry; entry->next=find_entry; - return; - } - while (find_entry) { + } else while (find_entry) { if (find_entry->next) { /* See if the next index comes later than this one */ - if (find_entry->next->index>entry->index) { + if (find_entry->next->index > entry->index) { entry->next=find_entry->next; find_entry->next=entry; - return; + break; } else { find_entry=find_entry->next; } } else { entry->next=find_entry->next; find_entry->next=entry; - return; + break; } } + Bits cycles=PIC_MakeCycles(pic.next_entry->index-PIC_Index()); + if (cycles15) E_Exit("PIC:Illegal IRQ"); if (!pic.free_entry) { - LOG(LOG_ERROR|LOG_PIC,"Event queue full"); + LOG(LOG_PIC,LOG_ERROR)("Event queue full"); return; } PICEntry * entry=pic.free_entry; @@ -434,53 +329,101 @@ void PIC_RemoveEvents(PIC_EventHandler handler) { } } -Bitu PIC_RunQueue(void) { - Bitu ret; +bool PIC_RunQueue(void) { /* Check to see if a new milisecond needs to be started */ - if (CPU_Cycles>0) { - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=0; + CPU_CycleLeft+=CPU_Cycles; + CPU_Cycles=0; + if (CPU_CycleLeft<=0) { + return false; } - while (CPU_CycleLeft>0) { - /* Check the queue for an entry */ - Bitu index=PIC_Index(); - 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; - } - /* Put the entry in the free list */ - entry->next=pic.free_entry; - pic.free_entry=entry; + /* Check the queue for an entry */ + Bitu index=PIC_Index(); + 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; } - /* Check when to set the new cycle end */ - if (pic.next_entry) { - Bits cycles=PIC_MakeCycles(pic.next_entry->index-index); - if (!cycles) cycles=1; - if (cycles0) { - CPU_CycleLeft+=CPU_Cycles; - CPU_Cycles=0; - } - if (ret) return ret; + /* Put the entry in the free list */ + entry->next=pic.free_entry; + pic.free_entry=entry; } - /* Prepare everything for next round */ + /* Check when to set the new cycle end */ + if (pic.next_entry) { + Bits cycles=PIC_MakeCycles(pic.next_entry->index-index); + if (!cycles) cycles=1; + if (cycles Timers; + +TIMER_Block * TIMER_RegisterTickHandler(TIMER_TickHandler handler) { + Timer * new_timer=new(Timer); + new_timer->type=T_TICK; + new_timer->tick.handler=handler; + Timers.push_front(new_timer); + return (TIMER_Block *)new_timer; +} + +TIMER_Block * TIMER_RegisterMicroHandler(TIMER_MicroHandler handler,Bitu micro) { + Timer * new_timer=new(Timer); + new_timer->type=T_MICRO; + new_timer->micro.handler=handler; + Timers.push_front(new_timer); + TIMER_SetNewMicro(new_timer,micro); + return (TIMER_Block *)new_timer; +} + +void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro) { + Timer * timer=(Timer *)block; + if (timer->type!=T_MICRO) E_Exit("TIMER:Illegal handler type"); + timer->micro.total=micro; + Bitu index=PIC_Index(); + while ((1000-index)>micro) { + PIC_AddEvent(timer->micro.handler,micro); + micro+=micro; + index+=micro; + } + timer->micro.left=timer->micro.total-(1000-index); +} + +void TIMER_AddTick(void) { + /* Setup new amount of cycles for PIC */ + CPU_CycleLeft=CPU_CycleMax; + CPU_Cycles=0; PIC_Ticks++; /* Go through the list of scheduled irq's and lower their index with 1000 */ PICEntry * entry=pic.next_entry; @@ -489,15 +432,48 @@ Bitu PIC_RunQueue(void) { else entry->index=0; entry=entry->next; } - return 0; + Bits index; + /* Check if there are timer handlers that need to be called */ + std::list::iterator i; + for(i=Timers.begin(); i != Timers.end(); ++i) { + Timer * timers=(*i); + switch (timers->type) { + case T_TICK: + timers->tick.handler(1); + break; + case T_MICRO: + index=1000; + while (index>=timers->micro.left) { + PIC_AddEvent(timers->micro.handler,timers->micro.left); + index-=timers->micro.left; + timers->micro.left=timers->micro.total; + } + timers->micro.left-=index; + break; + default: + E_Exit("TIMER:Illegal handler type"); + } + } } + + void PIC_Init(Section* sec) { /* Setup pic0 and pic1 with initial values like DOS has normally */ PIC_IRQCheck=0; PIC_IRQActive=PIC_NOIRQ; PIC_Ticks=0; Bitu i; + for (i=0;i<2;i++) { + pics[i].masked=0xff; + pics[i].active=0; + pics[i].inservice=0; + pics[i].auto_eoi=false; + pics[i].auto_eoi=false; + pics[i].request_issr=false; + pics[i].icw_index=0; + pics[i].icw_words=0; + } for (i=0;i<=7;i++) { irqs[i].active=false; irqs[i].masked=true; @@ -510,15 +486,16 @@ 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 */ - IO_RegisterReadHandler(0x20,read_p20,"Master PIC Command"); - IO_RegisterReadHandler(0x21,read_p21,"Master PIC Data"); - IO_RegisterWriteHandler(0x20,write_p20,"Master PIC Command"); - IO_RegisterWriteHandler(0x21,write_p21,"Master PIC Data"); - IO_RegisterReadHandler(0xa0,read_pa0,"Slave PIC Command"); - IO_RegisterReadHandler(0xa1,read_pa1,"Slave PIC Data"); - IO_RegisterWriteHandler(0xa0,write_pa0,"Slave PIC Command"); - IO_RegisterWriteHandler(0xa1,write_pa1,"Slave PIC Data"); + IO_RegisterReadHandler(0x20,read_command,"Master PIC Command"); + IO_RegisterReadHandler(0x21,read_data,"Master PIC Data"); + IO_RegisterWriteHandler(0x20,write_command,"Master PIC Command"); + IO_RegisterWriteHandler(0x21,write_data,"Master PIC Data"); + IO_RegisterReadHandler(0xa0,read_command,"Slave PIC Command"); + IO_RegisterReadHandler(0xa1,read_data,"Slave PIC Data"); + IO_RegisterWriteHandler(0xa0,write_command,"Slave PIC Command"); + IO_RegisterWriteHandler(0xa1,write_data,"Slave PIC Data"); /* Initialize the pic queue */ for (i=0;i #include #include "dosbox.h" #include "inout.h" @@ -26,11 +27,12 @@ #include "setup.h" #include "programs.h" - #define SB_PIC_EVENTS 0 +#define SB_NEW_ADPCM 1 -#define DSP_MAJOR 2 -#define DSP_MINOR 0 + +#define DSP_MAJOR 3 +#define DSP_MINOR 1 #define MIXER_INDEX 0x04 #define MIXER_DATA 0x05 @@ -51,6 +53,8 @@ #define SB_BUF_SIZE 8096 enum {DSP_S_RESET,DSP_S_NORMAL,DSP_S_HIGHSPEED}; +enum SB_IRQS {SB_IRQ_8,SB_IRQ_16,SB_IRQ_MPU}; + enum DSP_MODES { MODE_NONE,MODE_DAC, @@ -63,6 +67,7 @@ enum DMA_MODES { DMA_8_SILENCE, DMA_4_SINGLE, DMA_8_SINGLE,DMA_8_AUTO, + DMA_16_SINGLE,DMA_16_AUTO, }; enum { @@ -72,7 +77,7 @@ enum { struct SB_INFO { Bit16u freq; struct { - bool active,stereo; + bool active,stereo,filtered; DMA_MODES mode; Bitu total,left; Bitu rate,rate_mul; @@ -87,6 +92,10 @@ struct SB_INFO { Bit8u time_constant; bool use_time_constant; DSP_MODES mode; + struct { + bool pending_8bit; + bool pending_16bit; + } irq; struct { Bit8u state; Bit8u cmd; @@ -107,11 +116,13 @@ struct SB_INFO { } dac; struct { Bit8u index; - Bit8u master; - Bit8u mic,voice,fm; + struct { + Bit8u left,right; + } dac,fm,cda,master,lin; + Bit8u mic; } mixer; struct { - Bits reference,scale; + Bits reference,stepsize; } adpcm; struct { Bitu base; @@ -189,6 +200,19 @@ static void DSP_SetSpeaker(bool how) { sb.speaker=how; } +static INLINE void SB_RaiseIRQ(SB_IRQS type) { + LOG(LOG_SB,LOG_NORMAL)("Raising IRQ"); + PIC_AddIRQ(sb.hw.irq,0); + switch (type) { + case SB_IRQ_8: + sb.irq.pending_8bit=true; + break; + case SB_IRQ_16: + sb.irq.pending_16bit=true; + break; + } +} + static INLINE void DSP_FlushData(void) { sb.dsp.out.used=0; sb.dsp.out.pos=0; @@ -202,15 +226,52 @@ static void DSP_StopDMA(void) { static void DMA_Enable(bool enable) { sb.dma.active=enable; if (sb.mode==MODE_DMA_WAIT && enable) { + LOG(LOG_SB,LOG_NORMAL)("DMA enabled,starting output"); DSP_ChangeMode(MODE_DMA); CheckDMAEnd(); + return; } if (sb.mode==MODE_DMA && !enable) { DSP_ChangeMode(MODE_DMA_WAIT); + LOG(LOG_SB,LOG_NORMAL)("DMA disabled,stopping output"); + return; } } -INLINE Bit8u decode_ADPCM_4_sample(Bit8u sample,Bits& reference,Bits& scale) { + +#define MIN_ADAPTIVE_STEP_SIZE 511 +#define MAX_ADAPTIVE_STEP_SIZE 32767 +#define DC_OFFSET_FADE 254 + +INLINE Bits Clip(Bits sample) { + if (sample>MAX_AUDIO) return MAX_AUDIO; + if (sample> 1)); + if (adpcm & 1 ) scale = Clip(scale + (stepsize >> 2)); + scale = Clip(stepsize >> 3); + if (adpcm & 8) scale = -scale; + + reference=Clip(scale+((reference * DC_OFFSET_FADE) >> 8)); + // compute the next step size + stepsize=(stepsize * quantize[adpcm & 0x7]) >> 8; + if (stepsize < MIN_ADAPTIVE_STEP_SIZE) stepsize=MIN_ADAPTIVE_STEP_SIZE; + else if (stepsize > MAX_ADAPTIVE_STEP_SIZE) stepsize=MAX_ADAPTIVE_STEP_SIZE; + + return (Bit16s)reference; +} + +#else +INLINE Bit16s decode_ADPCM_4_sample(Bit8u sample,Bits& reference,Bits& scale) { static Bits scaleMap[8] = { -2, -1, 0, 0, 1, 1, 1, 1 }; if (sample & 0x08) { @@ -219,61 +280,77 @@ INLINE Bit8u decode_ADPCM_4_sample(Bit8u sample,Bits& reference,Bits& scale) { reference = min(0xff, reference + ((sample & 0x07) << scale)); } scale = max(2, min(6, scaleMap[sample & 0x07])); - return (Bit8u)reference; + return (((Bit8s)reference)^0x80)<<8; } +#endif + static void GenerateDMASound(Bitu size) { - //TODO For stereo make sure it's multiple of 2 + /* Check some variables */ if (!size) return; - Bitu read,i; + if (!sb.dma.rate) return; + /* First check if this transfer is gonna end in the next 2 milliseconds */ + Bitu index=(Bitu)(((float)sb.dma.left*(float)1000000)/(float)sb.dma.rate); +#if (SB_PIC_EVENTS) + if (index-PIC_Index()<1000) PIC_AddEvent(END_DMA_Event,index); +#else + if (index<2000) size=sb.dma.left; +#endif + Bitu read,i; switch (sb.dma.mode) { case DMA_4_SINGLE: - if (sb.adpcm.reference<0 && sb.dma.left) { + if (sb.adpcm.reference==0x1000000 && sb.dma.left) { +//TODO Check this Bit8u ref; read=DMA_8_Read(sb.hw.dma8,&ref,1); if (!read) { sb.mode=MODE_NONE;return; } //TODO warnings? sb.dma.left--; - sb.adpcm.reference=ref; + sb.adpcm.reference=0; + sb.adpcm.stepsize=MIN_ADAPTIVE_STEP_SIZE; } if (sb.dma.left> 4,sb.adpcm.reference,sb.adpcm.scale)^0x80))<<8; - sb.tmp.buf.m[i*2+1]=((Bit8s)(decode_ADPCM_4_sample(sb.dma.buf.b8[i] & 0xf,sb.adpcm.reference,sb.adpcm.scale)^0x80))<<8; + sb.tmp.buf.m[i*2+0]=decode_ADPCM_4_sample(sb.dma.buf.b8[i] >> 4,sb.adpcm.reference,sb.adpcm.stepsize); + sb.tmp.buf.m[i*2+1]=decode_ADPCM_4_sample(sb.dma.buf.b8[i] & 0xf,sb.adpcm.reference,sb.adpcm.stepsize); } read*=2; break; case DMA_8_SINGLE: if (sb.dma.leftread) { sb.dma.left-=read; } else { sb.dma.left=(sb.dma.total+sb.dma.left)-read; - PIC_AddIRQ(sb.hw.irq,0); + SB_RaiseIRQ(SB_IRQ_8); +// LOG_MSG("SB DMA AUTO IRQ Raised"); } for (i=0;i(pos=sb.tmp.index>>16)) { - (*stream++)=sb.tmp.buf.s[pos][0]; - (*stream++)=sb.tmp.buf.s[pos][1]; - sb.tmp.index+=sb.tmp.add_index; - sb.out.pos++; + if (read&1){ + LOG_MSG("DMA Unaligned"); + } else { + Bitu pos;read>>=1;Bitu index_add=sb.tmp.add_index >> 1; + while (read>(pos=sb.tmp.index>>16)) { + (*stream++)=sb.tmp.buf.s[pos][1]; //SB default seems to be swapped + (*stream++)=sb.tmp.buf.s[pos][0]; + sb.tmp.index+=index_add; + sb.out.pos++; + } + sb.tmp.index&=0xffff; } - sb.tmp.index&=0xffff; } } @@ -337,6 +418,7 @@ static void GenerateSound(Bitu size) { Bitu len=size*sb.dma.rate_mul; if (len & 0xffff) len=1+(len>>16); else len>>=16; + if (sb.dma.stereo && (len & 1)) len++; GenerateDMASound(len); break; } @@ -344,22 +426,21 @@ static void GenerateSound(Bitu size) { } } if (sb.out.pos>SB_BUF_SIZE) { - LOG(LOG_ERROR|LOG_SB,"Generation Buffer Full!!!!"); + LOG(LOG_SB,LOG_ERROR)("Generation Buffer Full!!!!"); sb.out.pos=0; } } static void END_DMA_Event(void) { GenerateDMASound(sb.dma.left); - sb.dma.left=0; - DSP_ChangeMode(MODE_NONE); } static void CheckDMAEnd(void) { if (!sb.dma.rate) return; Bitu index=(Bitu)(((float)sb.dma.left*(float)1000000)/(float)sb.dma.rate); if (index<(1000-PIC_Index())) { -#if SB_PIC_EVENTS +#if 1 + LOG(LOG_SB,LOG_NORMAL)("Sub millisecond transfer scheduling IRQ in %d microseconds",index); PIC_AddEvent(END_DMA_Event,index); #else GenerateDMASound(sb.dma.left); @@ -380,13 +461,11 @@ static void DSP_StartDMATranfser(DMA_MODES mode) { char * type; /* First fill with current whatever is playing */ DSP_ChangeMode(MODE_NONE); - sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8); sb.dma.left=sb.dma.total; if (sb.use_time_constant) { sb.dma.rate=(1000000 / (256 - sb.time_constant)); }; sb.dma.rate_mul=(sb.dma.rate<<16)/sb.hw.rate; - sb.dma.mode=mode; sb.tmp.index=0; switch (mode) { @@ -394,7 +473,6 @@ static void DSP_StartDMATranfser(DMA_MODES mode) { PIC_AddIRQ(sb.hw.irq,((1000000*sb.dma.left)/sb.dma.rate)); sb.dma.mode=DMA_NONE; return; - break; case DMA_8_SINGLE: type="8-Bit Single Cycle"; sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; @@ -408,7 +486,7 @@ static void DSP_StartDMATranfser(DMA_MODES mode) { sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; break; default: - LOG(LOG_ERROR|LOG_SB,"DSP:Illegal transfer mode %d",mode); + LOG(LOG_SB,LOG_ERROR)("DSP:Illegal transfer mode %d",mode); return; } //TODO Use the 16-bit dma for 16-bit transfers @@ -416,7 +494,7 @@ static void DSP_StartDMATranfser(DMA_MODES mode) { sb.dma.mode=mode; DMA_SetEnableCallBack(sb.hw.dma8,DMA_Enable); //TODO with stereo divide add_index - LOG(LOG_SB,"DMA Transfer:%s rate %d size %d",type,sb.dma.rate,sb.dma.total); + LOG(LOG_SB,LOG_NORMAL)("DMA Transfer:%s rate %d size %d",type,sb.dma.rate,sb.dma.total); } static void DSP_AddData(Bit8u val) { @@ -426,7 +504,7 @@ static void DSP_AddData(Bit8u val) { sb.dsp.out.data[start]=val; sb.dsp.out.used++; } else { - LOG(LOG_ERROR|LOG_SB,"DSP:Data Output buffer full"); + LOG(LOG_SB,LOG_ERROR)("DSP:Data Output buffer full"); } } @@ -438,6 +516,7 @@ static void DSP_Reset(void) { sb.dsp.write_busy=0; sb.dma.left=0; sb.dma.total=0; + sb.dma.stereo=false; sb.freq=22050; sb.use_time_constant=true; sb.time_constant=45; @@ -445,12 +524,14 @@ static void DSP_Reset(void) { sb.dac.last=0; sb.e2.value=0xaa; sb.e2.count=0; + sb.irq.pending_8bit=false; + sb.irq.pending_16bit=false; DSP_SetSpeaker(false); } static void DSP_DoReset(Bit8u val) { - if (val&1!=0) { + if ((val&1)!=0) { //TODO Get out of highspeed mode DSP_Reset(); sb.dsp.state=DSP_S_RESET; @@ -467,12 +548,16 @@ static void DMA_E2_Enable(bool enable) { Bit8u val=sb.e2.value; DMA_8_Write(sb.hw.dma8,&val,1); DMA_SetEnableCallBack(sb.hw.dma8,0); -// PIC_AddIRQ(sb.hw.irq,0); } } static void DSP_DoCommand(void) { +// LOG_MSG("DSP Command %X",sb.dsp.cmd); switch (sb.dsp.cmd) { + case 0x04: /* DSP Statues SB 2.0/pro version */ + DSP_FlushData(); + DSP_AddData(0xff); //Everthing enabled + break; case 0x10: /* Direct DAC */ DSP_ChangeMode(MODE_DAC); if (sb.dac.used> i) & 0x01) sb.e2.value += E2_incr_table[sb.e2.count % 4][i]; sb.e2.value += E2_incr_table[sb.e2.count % 4][8]; @@ -562,12 +649,10 @@ static void DSP_DoCommand(void) { DSP_AddData(sb.dsp.test_register);; break; case 0xf2: /* Trigger 8bit IRQ */ - DSP_FlushData(); - DSP_AddData(0xaa); - PIC_AddIRQ(sb.hw.irq,0); + SB_RaiseIRQ(SB_IRQ_8); break; default: - LOG(LOG_ERROR|LOG_SB,"DSP:Unhandled command %2X",sb.dsp.cmd); + LOG(LOG_SB,LOG_ERROR)("DSP:Unhandled command %2X",sb.dsp.cmd); break; } sb.dsp.cmd=DSP_NO_COMMAND; @@ -603,28 +688,77 @@ static Bit8u DSP_ReadData(void) { static void MIXER_Write(Bit8u val) { switch (sb.mixer.index) { - case 0x0a: /* Mic Level */ - sb.mixer.mic=val; + case 0x02: /* Master Voulme (SBPRO) Obsolete? */ + case 0x22: /* Master Volume (SBPRO) */ + sb.mixer.master.left= (val & 0xf) << 1; + sb.mixer.master.right=(val >> 4) << 1; break; - case 0x22: /* Master Volume */ - sb.mixer.master=val; + case 0x04: /* DAC Volume (SBPRO) */ + sb.mixer.dac.left= (val & 0xf) << 1; + sb.mixer.dac.right=(val >> 4) << 1; + break; + case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro */ + sb.mixer.fm.left= (val & 0xf) << 1; + sb.mixer.fm.right=(val & 0xf) << 1; + //TODO Change FM Mode if only 1 fm channel is selected + break; + case 0x0a: /* Mic Level */ + sb.mixer.mic=(val & 0xf) << 1; + break; + case 0x0e: /* Output/Stereo Select */ + sb.dma.stereo=(val & 0x2) > 0; + sb.dma.filtered=(val & 0x20) > 0; + LOG(LOG_SB,LOG_WARN)("Mixer set to %s",sb.dma.stereo ? "STEREO" : "MONO"); + break; + case 0x26: /* FM Volume (SBPRO) */ + sb.mixer.fm.left= (val & 0xf) << 1; + sb.mixer.fm.right=(val >> 4) << 1; + break; + case 0x28: /* CD Audio Volume (SBPRO) */ + sb.mixer.cda.left= (val & 0xf) << 1; + sb.mixer.cda.right=(val >> 4) << 1; + break; + case 0x2e: /* Line-IN Volume (SBPRO) */ + sb.mixer.lin.left= (val & 0xf) << 1; + sb.mixer.lin.right=(val >> 4) << 1; break; default: - LOG(LOG_ERROR|LOG_SB,"MIXER:Write to unhandled index %X",sb.mixer.index); + LOG(LOG_SB,LOG_WARN)("MIXER:Write %X to unhandled index %X",val,sb.mixer.index); } } static Bit8u MIXER_Read(void) { Bit8u ret; switch (sb.mixer.index) { - case 0x0a: /* Mic Level */ - ret=sb.mixer.mic; - case 0x22: /* Master Volume */ - ret=sb.mixer.master; - break; - default: - LOG(LOG_ERROR|LOG_SB,"MIXER:Read from unhandled index %X",sb.mixer.index); - ret=0xff; + case 0x00: /* RESET */ + return 0x00; + case 0x02: /* Master Voulme (SBPRO) Obsolete? */ + case 0x22: /* Master Volume (SBPRO) */ + return ((sb.mixer.master.left & 0x1e) >> 1) | + ((sb.mixer.master.right & 0x1e) << 3); + case 0x04: /* DAC Volume (SBPRO) */ + return ((sb.mixer.dac.left & 0x1e) >> 1) | + ((sb.mixer.dac.right & 0x1e) << 3); +// case 0x06: /* FM output selection, Somewhat obsolete with dual OPL SBpro */ + case 0x0a: /* Mic Level (SBPRO) */ + return (sb.mixer.mic >> 1); + case 0x0e: /* Output/Stereo Select */ + return 0x11|(sb.dma.stereo ? 0x02 : 0x00)|(sb.dma.filtered ? 0x20 : 0x00); + case 0x26: /* FM Volume (SBPRO) */ + return ((sb.mixer.fm.left & 0x1e) >> 1) | + ((sb.mixer.fm.right & 0x1e) << 3); + case 0x28: /* CD Audio Volume (SBPRO) */ + return ((sb.mixer.cda.left & 0x1e) >> 1) | + ((sb.mixer.cda.right & 0x1e) << 3); + case 0x2e: /* Line-IN Volume (SBPRO) */ + return ((sb.mixer.lin.left & 0x1e) >> 1) | + ((sb.mixer.lin.right & 0x1e) << 3); + case 0x82: + return (sb.irq.pending_8bit ? 0x1 : 0) | + (sb.irq.pending_16bit ? 0x2 : 0); + default: /* IRQ Status */ + LOG(LOG_SB,LOG_WARN)("MIXER:Read from unhandled index %X",sb.mixer.index); + ret=0xa; } return ret; } @@ -639,8 +773,8 @@ static Bit8u read_sb(Bit32u port) { case DSP_READ_DATA: return DSP_ReadData(); case DSP_READ_STATUS: - //TODO Acknowledge 8bit irq //TODO See for high speed dma :) + sb.irq.pending_8bit=false; if (sb.dsp.out.used) return 0xff; else return 0x7f; case DSP_WRITE_STATUS: @@ -659,7 +793,7 @@ static Bit8u read_sb(Bit32u port) { case DSP_RESET: return 0xff; default: - LOG(LOG_SB,"Unhandled read from SB Port %4X",port); + LOG(LOG_SB,LOG_NORMAL)("Unhandled read from SB Port %4X",port); break; } return 0xff; @@ -688,7 +822,7 @@ static void write_sb(Bit32u port,Bit8u val) { break; default: - LOG(LOG_SB,"Unhandled write to SB Port %4X",port); + LOG(LOG_SB,LOG_NORMAL)("Unhandled write to SB Port %4X",port); break; } } @@ -709,9 +843,8 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) { void SBLASTER_Init(Section* sec) { Bitu i; - MSG_Add("SBLASTER_CONFIGFILE_HELP","Sound Blaster related options.\n"); Section_prop * section=static_cast(sec); - if(!section->Get_bool("enabled")) return; + if(!section->Get_bool("sblaster")) return; sb.chan=MIXER_AddChannel(&SBLASTER_CallBack,22050,"SBLASTER"); MIXER_Enable(sb.chan,false); sb.dsp.state=DSP_S_NORMAL; @@ -730,5 +863,5 @@ void SBLASTER_Init(Section* sec) { PIC_RegisterIRQ(sb.hw.irq,0,"SB"); DSP_Reset(); - SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d T3",sb.hw.base,sb.hw.irq,sb.hw.dma8); + SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d T4",sb.hw.base,sb.hw.irq,sb.hw.dma8); } diff --git a/src/hardware/serialport.cpp b/src/hardware/serialport.cpp new file mode 100644 index 0000000..c2ba4a9 --- /dev/null +++ b/src/hardware/serialport.cpp @@ -0,0 +1,442 @@ +/* + * 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. + */ + +#include + +#include "dosbox.h" +#include "inout.h" +#include "mixer.h" +#include "pic.h" +#include "setup.h" +#include "timer.h" +#include "math.h" +#include "regs.h" +#include "serialport.h" + +#define SERIALBASERATE 115200 +#define SERIALPORT_COUNT 2 + +#define LOG_UART LOG_MSG +CSerial *serialports[SERIALPORT_COUNT]; + + +void CSerial::setdivisor(Bit8u dmsb, Bit8u dlsb) { + Bitu divsize=(dmsb << 8) | dlsb; + if (divsize!=0) { + bps = SERIALBASERATE / divsize; + } +} + + +void CSerial::checkint(void) { + /* Find lowest priority interrupt to activate */ + Bitu i; + for (i=0;i> 6) { + case 0: + FIFOsize = 1; + break; + case 1: + FIFOsize = 4; + break; + case 2: + FIFOsize = 8; + break; + case 3: + FIFOsize = 14; + break; + } + break; + case 0xb: // Line control register + linectrl = val; + wordlen = (val & 0x3); + dlab = (val & 0x80) > 0; + break; + case 0xc: // Modem control register + dtr = val & 0x01; + rts = (val & 0x02) > 0 ; + out1 = (val & 0x04) > 0; + out2 = (val & 0x08) > 0; + if (mc_handler) (*mc_handler)(val & 0xf); + local_loopback = (val & 0x10) > 0; + break; + case 0xf: // Scratch register + scratch = val; + break; + default: + LOG_UART("Modem: Write to 0x%x, with 0x%x '%c'\n", port,val,val); + break; + } +} + +void CSerial::write_serial(Bit32u port, Bit8u val) { + int i; + + for(i=0;i=serialports[i]->base+0x8) && (port<=(serialports[i]->base+0xf)) ) { + serialports[i]->write_port(port,val); + } + } +} + +Bit8u CSerial::read_port(Bit32u port) { + Bit8u outval = 0; + + port-=base; +// LOG_MSG("Serial read form %X",port); + switch(port) { + case 0x8: // Receive buffer + Divisor LSB + if (dlab) { + return divisor_lsb ; + } else { + outval = rx_readb(); +// LOG_UART("Read from %X %X %c remain %d",port,outval,outval,rx_fifo.used); + return outval; + } + case 0x9: // Interrupt enable register + Divisor MSB + if (dlab) { + return divisor_msb ; + } else { +// LOG_UART("Read from %X %X",port,ierval); + return ierval; + } + case 0xa: // Interrupt identification register + switch (ints.active) { + case INT_MS: + outval = 0x0; + break; + case INT_TX: + outval = 0x2; + lowerint(INT_TX); + goto skipreset; + case INT_RX: + outval = 0x4; + break; + case INT_RX_FIFO: + lowerint(INT_RX_FIFO); + outval = 0xc; + goto skipreset; + case INT_LS: + outval = 0x6; + break; + case INT_NONE: + outval = 0x1; + break; + } + ints.active=INT_NONE; +skipreset: + if (FIFOenabled) outval |= 3 << 6; +// LOG_UART("Read from %X %X",port,outval); + return outval; + case 0xb: // Line control register + LOG_UART("Read from %X %X",port,outval); + return linectrl; + case 0xC: // Modem control register + outval = dtr | (rts << 1) | (out1 << 2) | (out2 << 3) | (local_loopback << 4); +// LOG_UART("Read from %X %X",port,outval); + return outval; + case 0xD: // Line status register + lowerint(INT_LS); + outval = 0x40; + if (FIFOenabled) { + if (!tx_fifo.used) outval|=0x20; + } else if (tx_fifo.used=serialports[i]->base+0x8) && (port<=(serialports[i]->base+0xf)) ) { + return serialports[i]->read_port(port); + } + } + return 0x00; +} + +Bitu CSerial::rx_free() { + return FIFO_SIZE-rx_fifo.used; +} + +Bitu CSerial::tx_free() { + return FIFO_SIZE-tx_fifo.used; +} + +Bitu CSerial::tx_size() { + if (FIFOenabled && rx_fifo.used && (rx_lastread < (PIC_Ticks-2))) { + raiseint(INT_RX_FIFO); + } + return tx_fifo.used; +} + +Bitu CSerial::rx_size() { + return rx_fifo.used; +} + +void CSerial::rx_addb(Bit8u data) { + LOG_UART("RX add %c",data); + if (rx_fifo.used=FIFO_SIZE) where-=FIFO_SIZE; + rx_fifo.data[where]=data; + rx_fifo.used++; + if (FIFOenabled && (rx_fifo.used < FIFOsize)) return; + /* Raise rx irq if possible */ + if (ints.active != INT_RX) raiseint(INT_RX); + } +} + +void CSerial::rx_adds(Bit8u * data,Bitu size) { + if ((rx_fifo.used+size)<=FIFO_SIZE) { + Bitu where=rx_fifo.pos+rx_fifo.used; + rx_fifo.used+=size; + while (size--) { + if (where>=FIFO_SIZE) where-=FIFO_SIZE; + rx_fifo.data[where++]=*data++; + } + if (FIFOenabled && (rx_fifo.used < FIFOsize)) return; + if (ints.active != INT_RX) raiseint(INT_RX); + } +// else LOG_MSG("WTF"); +} + +void CSerial::tx_addb(Bit8u data) { + LOG_UART("TX add %c",data); + if (tx_fifo.used=FIFO_SIZE) where-=FIFO_SIZE; + tx_fifo.data[where]=data; + tx_fifo.used++; + if (tx_fifo.used<(FIFO_SIZE-16)) { + /* Only generate FIFO irq's every 16 bytes */ + if (FIFOenabled && (tx_fifo.used & 0xf)) return; + raiseint(INT_TX); + } + } else { +// LOG_MSG("tx addb"); + } +} + +Bit8u CSerial::rx_readb() { + if (rx_fifo.used) { + rx_lastread=PIC_Ticks; + Bit8u val=rx_fifo.data[rx_fifo.pos]; + rx_fifo.pos++; + if (rx_fifo.pos>=FIFO_SIZE) rx_fifo.pos-=FIFO_SIZE; + rx_fifo.used--; + //Don't care for FIFO Size + if (FIFOenabled || !rx_fifo.used) lowerint(INT_RX); + else raiseint(INT_RX); + return val; + } else { +// LOG_MSG("WTF rx readb"); + return 0; + } +} + +Bit8u CSerial::tx_readb() { + if (tx_fifo.used) { + Bit8u val=tx_fifo.data[tx_fifo.pos]; + tx_fifo.pos++; + if (tx_fifo.pos>=FIFO_SIZE) tx_fifo.pos-=FIFO_SIZE; + tx_fifo.used--; + if (FIFOenabled && !tx_fifo.used) raiseint(INT_TX); + return val; + } else { +// LOG_MSG("WTF tx readb"); + return 0; + } +} + + +void CSerial::setmodemstatus(Bit8u status) { + Bitu oldstatus=mstatus >> 4; + if(oldstatus ^ status ) { + mstatus=status << 4; + mstatus|=(oldstatus ^ status); + raiseint(INT_MS); + } +} + +Bit8u CSerial::getmodemstatus() { + return (mstatus >> 4); +} + +Bit8u CSerial::getlinestatus() { + return read_port(0xd); +} + + +void CSerial::SetMCHandler(MControl_Handler * mcontrol) { + mc_handler=mcontrol; +} + +CSerial::CSerial (Bit16u initbase, Bit8u initirq, Bit32u initbps) { + + int i; + Bit16u initdiv; + + base=initbase; + irq=initirq; + bps=initbps; + + mc_handler = 0; + tx_fifo.used = tx_fifo.pos = 0; + rx_fifo.used = rx_fifo.pos = 0; + + rx_lastread = PIC_Ticks; + linectrl = dtr = rts = out1 = out2 = 0; + local_loopback = 0; + ierval = 0; + ints.enabled=1 << INT_RX_FIFO; + ints.active=INT_NONE; + ints.requested=0; + + FIFOenabled = false; + FIFOsize = 1; + timeout = 0; + dlab = 0; + ierval = 0; + + initdiv = SERIALBASERATE / bps; + setdivisor(initdiv >> 8, initdiv & 0x0f); + + for (i=8;i<=0xf;i++) { + + IO_RegisterWriteHandler(initbase+i,write_serial,"Serial Port"); + IO_RegisterReadHandler(initbase+i,read_serial,"Serial Port"); + } + + PIC_RegisterIRQ(irq,0,"SERIAL"); + + +}; + +CSerial::~CSerial(void) +{ + +}; + + + +CSerial *getComport(Bitu portnum) +{ + return serialports[portnum-1]; +} + +void SERIAL_Init(Section* sec) { + + unsigned long args = 1; + Section_prop * section=static_cast(sec); + +// if(!section->Get_bool("enabled")) return; + + serialports[0] = new CSerial(0x3f0,4,SERIALBASERATE); + serialports[1] = new CSerial(0x2f0,3,SERIALBASERATE); +} + diff --git a/src/hardware/softmodem.cpp b/src/hardware/softmodem.cpp new file mode 100644 index 0000000..38e568e --- /dev/null +++ b/src/hardware/softmodem.cpp @@ -0,0 +1,640 @@ +/* + * 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. + */ + + + +#include "dosbox.h" + +#if C_MODEM + +#include +#include +#include "SDL_net.h" + +#include "inout.h" +#include "mixer.h" +#include "dma.h" +#include "pic.h" +#include "hardware.h" +#include "setup.h" +#include "programs.h" +#include "debug.h" +#include "timer.h" +#include "callback.h" +#include "math.h" +#include "regs.h" +#include "serialport.h" + +#define MODEMSPD 57600 +#define CONNECTED (M_CTS | M_DSR | M_DCD ) +#define DISCONNECTED (M_CTS | M_DSR ) + + +/* DTMF tone generator */ +float col[] = { 1209.0, 1336.0, 1477.0, 1633.0 }; +float row[] = { 697.0, 770.0, 852.0, 941.0 }; +char positions[] = "123A456B789C*0#D"; +#define duration 1000 +#define pause 400 + +static Bit8u tmpbuf[FIFO_SIZE+1]; + +struct ModemHd { + char cmdbuf[FIFO_SIZE]; + bool commandmode; + bool cantrans; + bool incomingcall; + bool autoanswer; + bool echo; + Bitu cmdpause; + Bits ringcounter; + Bit16u plusinc; + Bit16u cmdpos; + + + TCPsocket socket; + TCPsocket listensocket; + SDLNet_SocketSet socketset; + + IPaddress openip; + + Bitu comport; + Bitu listenport; + + char remotestr[4096]; + + bool dialing; + double f1, f2; + Bitu diallen; + Bitu dialpos; + char dialstr[256]; + MIXER_Channel * chan; +}; + +static CSerial * mdm; +static ModemHd mhd; + +static void sendStr(const char *usestr) { + if (!mhd.echo) return; + Bitu i=0; + while (*usestr != 0) { + if (*usestr == 10) { + mdm->rx_addb(0xd); + mdm->rx_addb(0xa); + } else { + mdm->rx_addb((Bit8u)*usestr); + } + usestr++; + } +} + +static void sendOK() { + sendStr("\nOK\n"); +} + +static void sendError() { + sendStr("\nERROR\n"); +} + +static void toUpcase(char *buffer) { + Bitu i=0; + while (buffer[i] != 0) { + buffer[i] = toupper(buffer[i]); + i++; + } +} + +static void openConnection() { + if (mhd.socket) { + LOG_MSG("Huh? already connected"); + SDLNet_TCP_DelSocket(mhd.socketset,mhd.socket); + SDLNet_TCP_Close(mhd.socket); + } + mhd.socket = SDLNet_TCP_Open(&mhd.openip); + if (mhd.socket) { + SDLNet_TCP_AddSocket(mhd.socketset,mhd.socket); + sendStr("\nCONNECT 57600\n"); + mhd.commandmode = false; + mdm->setmodemstatus(CONNECTED); + } else { + sendStr("\nNO DIALTONE\n"); + } +} + +static bool Dial(char * host) { + + /* Scan host for port */ + Bit16u port; + char * hasport=strrchr(host,':'); + if (hasport) { + *hasport++=0; + port=(Bit16u)atoi(hasport); + } else port=23; + /* Resolve host we're gonna dial */ + LOG_MSG("host %s port %x",host,port); + if (!SDLNet_ResolveHost(&mhd.openip,host,port)) { + /* Prepare string for dial sound generator */ + int c; + char *addrptr=host; + mhd.dialstr[0] = 'd'; + mhd.dialstr[1] = 'd'; + mhd.dialstr[2] = 'd'; + mhd.dialstr[3] = 'd'; + mhd.dialstr[4] = 'd'; + mhd.dialstr[5] = 'p'; + c=6; + while(*addrptr != 0x00) { + if (strchr(positions, *addrptr)) { + mhd.dialstr[c] = *addrptr; + c++; + } + addrptr++; + } + mhd.dialstr[c] = 0x00; + + mhd.diallen = strlen(mhd.dialstr) * (Bit32u)(duration + pause); + mhd.dialpos = 0; + mhd.f1 = 0; + mhd.f2 = 0; + mhd.dialing = true; + MIXER_Enable(mhd.chan,true); + return true; + } else { + LOG_MSG("Failed to resolve host %s:%s",host,SDLNet_GetError()); + sendStr("\nNO CARRIER\n"); + return false; + } +} + + +static void DoCommand() { + bool found = false; + bool foundat = false; + char *foundstr; + bool connResult = false; + char msgbuf[4096]; + + Bitu result; + mhd.cmdbuf[mhd.cmdpos] = 0; + toUpcase(mhd.cmdbuf); + LOG_MSG("Modem Sent Command: %s\n", mhd.cmdbuf); + mhd.cmdpos = 0; + + result = 0; + + + /* Just for kicks */ + if ((mhd.cmdbuf[0] == 'A') && (mhd.cmdbuf[1] == 'T')) foundat = true; + if (foundat) { + if (strstr(mhd.cmdbuf,"I3")) { + sendStr("\nDosBox Emulated Modem Firmware V1.00\n"); + result = 1; + } + if (strstr(mhd.cmdbuf,"I4")) { + sprintf(msgbuf, "\nModem compiled for DosBox version %s\n", VERSION); + sendStr(msgbuf); + result = 1; + } + if (strstr(mhd.cmdbuf,"S0=1")) { + mhd.autoanswer = true; + } + if (strstr(mhd.cmdbuf,"S0=0")) { + mhd.autoanswer = false; + } + + if (strstr(mhd.cmdbuf,"E0")) { + mhd.echo = false; + } + if (strstr(mhd.cmdbuf,"E1")) { + mhd.echo = true; + } + + if (strstr(mhd.cmdbuf,"ATH")) { + /* Check if we're actually connected */ + if (mhd.socket) { + sendStr("\nNO CARRIER\n"); + SDLNet_TCP_DelSocket(mhd.socketset,mhd.socket); + SDLNet_TCP_Close(mhd.socket); + mhd.socket=0; + mdm->setmodemstatus(DISCONNECTED); + mhd.commandmode = true; + result = 3; + } else result = 2; + } + if(strstr(mhd.cmdbuf,"ATO")) { + /* Check for connection before switching to data mode */ + if (mhd.socket) { + mhd.commandmode = false; + result=3; + } else { + result=2; + } + } + if(strstr(mhd.cmdbuf,"ATDT")) { + foundstr = strstr(mhd.cmdbuf,"ATDT"); + foundstr+=4; + /* Small protection against empty line */ + if (!foundstr[0]) { + result=2; + } else { + connResult = Dial(foundstr); + result=3; + } + } + if(strstr(mhd.cmdbuf,"ATA")) { + if (mhd.incomingcall) { + sendStr("\nCONNECT 57600\n"); + LOG_MSG("Connected!\n"); + MIXER_Enable(mhd.chan,false); + mdm->setmodemstatus(CONNECTED); + mhd.incomingcall = false; + mhd.commandmode = false; + SDLNet_TCP_AddSocket(mhd.socketset,mhd.socket); + result = 3; + } else { + mhd.autoanswer = true; + result = 3; + } + } + if (result==0) result = 1; + } else result=2; + + if (strlen(mhd.cmdbuf)<2) { + if(!mhd.dialing) { + result = 0; + mhd.autoanswer = false; + } else { + MIXER_Enable(mhd.chan,false); + mhd.dialing = false; + sendStr("\nNO CARRIER\n"); + result = 0; + } + } + + switch (result) { + case 1: + sendOK(); + break; + case 2: + sendError(); + break; + } + +} + + +static void MC_Changed(Bitu new_mc) { + + +} + +static void MODEM_Hardware(Bitu ticks) { + int result =0; + unsigned long args = 1; + bool sendbyte = true; + Bitu usesize; + Bit8u txval; + + /* Check for eventual break command */ + if (!mhd.commandmode) mhd.cmdpause++; + /* Handle incoming data from serial port, read as much as available */ + Bitu tx_size=mdm->tx_size(); + while (tx_size--) { + txval = mdm->tx_readb(); + if (mhd.commandmode) { + if(txval != 0xd) { + if(txval == 0x8) { + if (mhd.cmdpos > 0) { + --mhd.cmdpos; + } + } else { + if (txval != '+') { + if(mhd.cmdposrx_addb(txval); + } else if (mhd.echo) { + mdm->rx_addb(10); + mdm->rx_addb(13); + } + } else { + DoCommand(); + } + } else { + /* 1000 ticks have passed, can check for pause command */ + if (mhd.cmdpause > 1000) { + if(txval == '+') { + mhd.plusinc++; + if(mhd.plusinc>=3) { + mhd.commandmode = true; + sendStr("\nOK\n"); + mhd.plusinc = 0; + } + sendbyte=false; + } else { + mhd.plusinc=0; + } +//If not a special pause command, should go for bigger blocks to send + } + + tmpbuf[0] = txval; + tmpbuf[1] = 0x0; + + if (mhd.socket && sendbyte) { + SDLNet_TCP_Send(mhd.socket, tmpbuf,1); + //TODO error testing + } + } + } + + SDLNet_CheckSockets(mhd.socketset,0); + /* Handle outgoing to the serial port */ + if(!mhd.commandmode && mhd.socket && mdm->rx_free() && SDLNet_SocketReady(mhd.socket)) { + usesize = mdm->rx_free(); + result = SDLNet_TCP_Recv(mhd.socket, tmpbuf, usesize); + if (result>0) { + mdm->rx_adds(tmpbuf,result); + mhd.cmdpause = 0; + } else { + /* Error close the socket and disconnect */ + mdm->setmodemstatus(DISCONNECTED); + mhd.commandmode = true; + sendStr("\nNO CARRIER\n"); + SDLNet_TCP_DelSocket(mhd.socketset,mhd.socket); + SDLNet_TCP_Close(mhd.socket); + mhd.socket=0; + } + } + + /* Check for incoming calls */ + if (!mhd.socket && !mhd.incomingcall && mhd.listensocket) { + mhd.socket = SDLNet_TCP_Accept(mhd.listensocket); + if (mhd.socket) { + mhd.dialpos = 0; + mhd.incomingcall = true; + mhd.diallen = 12000; + mhd.dialpos = 0; +//TODO Set ring in Modemstatus? + sendStr("\nRING\n"); + MIXER_Enable(mhd.chan,true); + mhd.ringcounter = 24000; + } + } + + if (mhd.incomingcall) { + if (mhd.ringcounter <= 0) { + if (mhd.autoanswer) { + mhd.incomingcall = false; + sendStr("\nCONNECT 57600\n"); + MIXER_Enable(mhd.chan,false); + mdm->setmodemstatus(CONNECTED); + mhd.incomingcall = false; + mhd.commandmode = false; + SDLNet_TCP_AddSocket(mhd.socketset,mhd.socket); + return; + } + sendStr("\nRING\n"); + mhd.diallen = 12000; + mhd.dialpos = 0; + + MIXER_Enable(mhd.chan,true); + + mhd.ringcounter = 3000; /* Ring every three seconds for accurate emulation */ + + } + if (mhd.ringcounter > 0) --mhd.ringcounter; + + } + +} + +/* +03F8 -W serial port, transmitter holding register (THR), which contains the + character to be sent. Bit 0 is sent first. + bit 7-0 data bits when DLAB=0 (Divisor Latch Access Bit) +03F8 R- receiver buffer register (RBR), which contains the received + character. Bit 0 is received first + bit 7-0 data bits when DLAB=0 (Divisor Latch Access Bit) +03F8 RW divisor latch low byte (DLL) when DLAB=1 (see #P0876) +03F9 RW divisor latch high byte (DLM) when DLAB=1 (see #P0876) +03F9 RW interrupt enable register (IER) when DLAB=0 (see #P0877) +03FA R- interrupt identification register (see #P0878) + Information about a pending interrupt is stored here. When the ID + register is addressed, thehighest priority interrupt is held, and + no other interrupts are acknowledged until the CPU services that + interrupt. +03FA -W 16650 FIFO Control Register (FCR) (see #P0879) +03FB RW line control register (LCR) (see #P0880) +03FC RW modem control register (see #P0881) +03FD R- line status register (LSR) (see #P0882) +03FE R- modem status register (MSR) (see #P0883) +03FF RW scratch register (SCR) + (not used for serial I/O; available to any application using 16450, + 16550) (not present on original 8250) +*/ + +static void MODEM_CallBack(Bit8u * stream,Bit32u len) { + char *cp; + float ci,ri; + int innum, splitnum, quad, eighth, sixth, amp; + Bit8u curchar; + Bit32s buflen = (Bit32s)len; + if(mhd.incomingcall) { + + if(mhd.dialpos>=mhd.diallen) { + MIXER_Enable(mhd.chan,false); + return; + } else { + quad = (mhd.diallen/14); + eighth = quad / 2; + sixth = eighth /2; + + while ((buflen>0) && (mhd.dialpos=mhd.diallen) { + while(len-->0) { + *(Bit16s*)(stream) = 0; + stream+=2; + } + MIXER_Enable(mhd.chan,false); + mhd.dialing = false; + openConnection(); + return; + } else { + + while ((buflen>0) && (mhd.dialpos(sec); + + if(!section->Get_bool("enabled")) return; + + if(SDLNet_Init()==-1) { + LOG_MSG("SDLNet_Init failed: %s\n", SDLNet_GetError()); + return; + } + + mhd.cmdpos = 0; + mhd.commandmode = true; + mhd.plusinc = 0; + mhd.cantrans = false; + mhd.incomingcall = false; + mhd.autoanswer = false; + mhd.cmdpause = 0; + mhd.echo = true; + + /* Bind the modem to the correct serial port */ + mhd.comport=section->Get_int("comport"); + strcpy(mhd.remotestr, section->Get_string("remote")); + mdm = getComport(mhd.comport); + mdm->setmodemstatus(DISCONNECTED); + mdm->SetMCHandler(&MC_Changed); + + TIMER_RegisterTickHandler(&MODEM_Hardware); + + /* Initialize the sockets and setup the listening port */ + mhd.socketset = SDLNet_AllocSocketSet(1); + if (!mhd.socketset) { + LOG_MSG("MODEM:Can't open socketset:%s",SDLNet_GetError()); +//TODO Should probably just exit + return; + } + mhd.socket=0; + mhd.listenport=section->Get_int("listenport"); + if (mhd.listenport) { + IPaddress listen_ip; + SDLNet_ResolveHost(&listen_ip, NULL, mhd.listenport); + mhd.listensocket=SDLNet_TCP_Open(&listen_ip); + if (!mhd.listensocket) LOG_MSG("MODEM:Can't open listen port:%s",SDLNet_GetError()); + } else mhd.listensocket=0; + + mhd.chan=MIXER_AddChannel(&MODEM_CallBack,8000,"MODEM"); + MIXER_Enable(mhd.chan,false); + MIXER_SetMode(mhd.chan,MIXER_16MONO); +} + +#endif + diff --git a/src/hardware/tandy_sound.cpp b/src/hardware/tandy_sound.cpp index c71c1db..d7d55fa 100644 --- a/src/hardware/tandy_sound.cpp +++ b/src/hardware/tandy_sound.cpp @@ -17,7 +17,7 @@ */ /* - Probably just use the mame code for the same chip sometime + Based of sn76496.c of the M.A.M.E. project */ #include @@ -26,121 +26,309 @@ #include "mixer.h" #include "mem.h" #include "setup.h" +#include "pic.h" -#define TANDY_DIV 111860 -#define TANDY_RATE 22050 -#define BIT_SHIFT 16 -#define TANDY_VOLUME 10000 -static MIXER_Channel * tandy_chan; -struct TandyChannel { - Bit32u div; - Bit32u freq_add; - Bit32u freq_pos; +#define MAX_OUTPUT 0x7fff +#define STEP 0x10000 + +/* Formulas for noise generator */ +/* bit0 = output */ + +/* noise feedback for white noise mode (verified on real SN76489 by John Kortink) */ +#define FB_WNOISE 0x14002 /* (16bits) bit16 = bit0(out) ^ bit2 ^ bit15 */ + +/* noise feedback for periodic noise mode */ +//#define FB_PNOISE 0x10000 /* 16bit rorate */ +#define FB_PNOISE 0x08000 /* JH 981127 - fixes Do Run Run */ + +/* +0x08000 is definitely wrong. The Master System conversion of Marble Madness +uses periodic noise as a baseline. With a 15-bit rotate, the bassline is +out of tune. +The 16-bit rotate has been confirmed against a real PAL Sega Master System 2. +Hope that helps the System E stuff, more news on the PSG as and when! +*/ + +/* noise generator start preset (for periodic noise) */ +#define NG_PRESET 0x0f35 + + +struct SN76496 +{ + int SampleRate; + unsigned int UpdateStep; + int VolTable[16]; /* volume table */ + int Register[8]; /* registers */ + int LastRegister; /* last register written */ + int Volume[4]; /* volume of voice 0-2 and noise */ + unsigned int RNG; /* noise generator */ + int NoiseFB; /* noise feedback mask */ + int Period[4]; + int Count[4]; + int Output[4]; }; - -struct TandyBlock { - TandyChannel chan[3]; - - Bit32s volume[4]; - Bit8u reg; -}; - -static TandyBlock tandy; +static struct SN76496 sn; +static struct { + MIXER_Channel * chan; + bool enabled; + Bitu last_write; +} tandy; -#define REG_CHAN0DIV 0 /* 0 0 0 */ -#define REG_CHAN0ATT 1 /* 0 0 1 */ -#define REG_CHAN1DIV 2 /* 0 1 0 */ -#define REG_CHAN1ATT 3 /* 0 1 1 */ -#define REG_CHAN2DIV 4 /* 1 0 0 */ -#define REG_CHAN2ATT 5 /* 1 0 1 */ -#define REG_NOISEATT 7 /* 1 1 1 */ +static void SN76496Write(Bit32u port,Bit8u data) +{ + struct SN76496 *R = &sn; -//TODO a db volume table :) -static Bit32s vol_table[16]; - - -static void write_pc0(Bit32u port,Bit8u val) { - /* Test for a command byte */ - if (val & 0x80) { - tandy.reg=(val>>4) & 7; - switch (tandy.reg) { - case REG_CHAN0DIV: - case REG_CHAN1DIV: - case REG_CHAN2DIV: - tandy.chan[tandy.reg>>1].div=val&15; - break; - case REG_CHAN0ATT: - case REG_CHAN1ATT: - case REG_CHAN2ATT: - case REG_NOISEATT: - tandy.volume[tandy.reg>>1]=vol_table[val&15]; - if (tandy.volume[0] || tandy.volume[1] || tandy.volume[2] || tandy.volume[3]) { - MIXER_Enable(tandy_chan,true); - } else { - MIXER_Enable(tandy_chan,false); - } - break; - default: -// LOG_WARN("TANDY:Illegal register %d selected",tandy.reg); - break; - } - } else { -/* Dual byte command */ - switch (tandy.reg) { -#define MAKE_ADD(DIV)(Bit32u)((2 << BIT_SHIFT)/((float)TANDY_RATE/((float)TANDY_DIV/(float)DIV))); - case REG_CHAN0DIV: - case REG_CHAN1DIV: - case REG_CHAN2DIV: - tandy.chan[tandy.reg>>1].div|=(val & 63)<<4; - tandy.chan[tandy.reg>>1].freq_add=MAKE_ADD(tandy.chan[tandy.reg>>1].div); -// tandy.chan[tandy.reg>>1].freq_pos=0; - break; - default: - LOG(0,"TANDY:Illegal dual byte reg %d",tandy.reg); - }; + tandy.last_write=PIC_Ticks; + if (!tandy.enabled) { + MIXER_Enable(tandy.chan,true); + tandy.enabled=true; } + /* update the output buffer before changing the registers */ + + if (data & 0x80) + { + int r = (data & 0x70) >> 4; + int c = r/2; + + R->LastRegister = r; + R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); + switch (r) + { + case 0: /* tone 0 : frequency */ + case 2: /* tone 1 : frequency */ + case 4: /* tone 2 : frequency */ + R->Period[c] = R->UpdateStep * R->Register[r]; + if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; + if (r == 4) + { + /* update noise shift frequency */ + if ((R->Register[6] & 0x03) == 0x03) + R->Period[3] = 2 * R->Period[2]; + } + break; + case 1: /* tone 0 : volume */ + case 3: /* tone 1 : volume */ + case 5: /* tone 2 : volume */ + case 7: /* noise : volume */ + R->Volume[c] = R->VolTable[data & 0x0f]; + break; + case 6: /* noise : frequency, mode */ + { + int n = R->Register[6]; + R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE; + n &= 3; + /* N/512,N/1024,N/2048,Tone #3 output */ + R->Period[3] = (n == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+n)); + + /* reset noise shifter */ + R->RNG = NG_PRESET; + R->Output[3] = R->RNG & 1; + } + break; + } + } + else + { + int r = R->LastRegister; + int c = r/2; + + switch (r) + { + case 0: /* tone 0 : frequency */ + case 2: /* tone 1 : frequency */ + case 4: /* tone 2 : frequency */ + R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4); + R->Period[c] = R->UpdateStep * R->Register[r]; + if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; + if (r == 4) + { + /* update noise shift frequency */ + if ((R->Register[6] & 0x03) == 0x03) + R->Period[3] = 2 * R->Period[2]; + } + break; + } + } } -static void TANDYSOUND_CallBack(Bit8u * stream,Bit32u len) { - for (Bit32u i=0;i=(2 << BIT_SHIFT)) tandy.chan[c].freq_pos-=(2 << BIT_SHIFT); - } - } - /* Generate the noise channel */ - - if (sample>MAX_AUDIO) *(Bit16s *)stream=MAX_AUDIO; - else if (sampleVolume[i] == 0) + { + /* note that I do count += length, NOT count = length + 1. You might think */ + /* it's the same since the volume is 0, but doing the latter could cause */ + /* interferencies when the program is rapidly modulating the volume. */ + if (R->Count[i] <= (int)length*STEP) R->Count[i] += length*STEP; + } + } + + while (length > 0) + { + int vol[4]; + unsigned int out; + int left; + + + /* vol[] keeps track of how long each square wave stays */ + /* in the 1 position during the sample period. */ + vol[0] = vol[1] = vol[2] = vol[3] = 0; + + for (i = 0;i < 3;i++) + { + if (R->Output[i]) vol[i] += R->Count[i]; + R->Count[i] -= STEP; + /* Period[i] is the half period of the square wave. Here, in each */ + /* loop I add Period[i] twice, so that at the end of the loop the */ + /* square wave is in the same status (0 or 1) it was at the start. */ + /* vol[i] is also incremented by Period[i], since the wave has been 1 */ + /* exactly half of the time, regardless of the initial position. */ + /* If we exit the loop in the middle, Output[i] has to be inverted */ + /* and vol[i] incremented only if the exit status of the square */ + /* wave is 1. */ + while (R->Count[i] <= 0) + { + R->Count[i] += R->Period[i]; + if (R->Count[i] > 0) + { + R->Output[i] ^= 1; + if (R->Output[i]) vol[i] += R->Period[i]; + break; + } + R->Count[i] += R->Period[i]; + vol[i] += R->Period[i]; + } + if (R->Output[i]) vol[i] -= R->Count[i]; + } + + left = STEP; + do + { + int nextevent; + + + if (R->Count[3] < left) nextevent = R->Count[3]; + else nextevent = left; + + if (R->Output[3]) vol[3] += R->Count[3]; + R->Count[3] -= nextevent; + if (R->Count[3] <= 0) + { + if (R->RNG & 1) R->RNG ^= R->NoiseFB; + R->RNG >>= 1; + R->Output[3] = R->RNG & 1; + R->Count[3] += R->Period[3]; + if (R->Output[3]) vol[3] += R->Period[3]; + } + if (R->Output[3]) vol[3] -= R->Count[3]; + + left -= nextevent; + } while (left > 0); + + out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] + + vol[2] * R->Volume[2] + vol[3] * R->Volume[3]; + + if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; + + *(buffer++) = out / STEP; + + length--; + } +} + + + +static void SN76496_set_clock(int clock) +{ + struct SN76496 *R = &sn; + + + /* the base clock for the tone generators is the chip clock divided by 16; */ + /* for the noise generator, it is clock / 256. */ + /* Here we calculate the number of steps which happen during one sample */ + /* at the given sample rate. No. of events = sample rate / (clock/16). */ + /* STEP is a multiplier used to turn the fraction into a fixed point */ + /* number. */ + R->UpdateStep = (unsigned int)(((double)STEP * R->SampleRate * 16) / clock); +} + + + +static void SN76496_set_gain(int gain) +{ + struct SN76496 *R = &sn; + int i; + double out; + + + gain &= 0xff; + + /* increase max output basing on gain (0.2 dB per step) */ + out = MAX_OUTPUT / 3; + while (gain-- > 0) + out *= 1.023292992; /* = (10 ^ (0.2/20)) */ + + /* build volume table (2dB per step) */ + for (i = 0;i < 15;i++) + { + /* limit volume to avoid clipping */ + if (out > MAX_OUTPUT / 3) R->VolTable[i] = MAX_OUTPUT / 3; + else R->VolTable[i] = (int)out; + + out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */ + } + R->VolTable[15] = 0; +} + + + void TANDYSOUND_Init(Section* sec) { Section_prop * section=static_cast(sec); if(!section->Get_bool("tandy")) return; - IO_RegisterWriteHandler(0xc0,write_pc0,"Tandy Sound"); - tandy_chan=MIXER_AddChannel(&TANDYSOUND_CallBack,TANDY_RATE,"TANDY"); - MIXER_Enable(tandy_chan,false); - MIXER_SetMode(tandy_chan,MIXER_16MONO); - /* Calculate the volume table */ - float out=TANDY_VOLUME; - for (Bit32u i=0;i<15;i++) { - vol_table[i]=(Bit32s)out; - out /= (float)1.258925412; /* = 10 ^ (2/20) = 2dB */ + + IO_RegisterWriteHandler(0xc0,SN76496Write,"Tandy Sound"); + + Bit32u sample_rate = section->Get_int("tandyrate"); + tandy.chan=MIXER_AddChannel(&SN76496Update,sample_rate,"TANDY"); + + MIXER_Enable(tandy.chan,false); + tandy.enabled=false; + MIXER_SetMode(tandy.chan,MIXER_16MONO); + + Bitu i; + struct SN76496 *R = &sn; + R->SampleRate = sample_rate; + SN76496_set_clock(2386360); + for (i = 0;i < 4;i++) R->Volume[i] = 0; + R->LastRegister = 0; + for (i = 0;i < 8;i+=2) + { + R->Register[i] = 0; + R->Register[i + 1] = 0x0f; /* volume = 0 */ } - vol_table[15]=0; - /* Setup a byte for tandy detection */ - real_writeb(0xffff,0xe,0xfd); + + for (i = 0;i < 4;i++) + { + R->Output[i] = 0; + R->Period[i] = R->Count[i] = R->UpdateStep; + } + R->RNG = NG_PRESET; + R->Output[3] = R->RNG & 1; + SN76496_set_gain(0x1); } diff --git a/src/hardware/timer.cpp b/src/hardware/timer.cpp index 4194f53..b071dc0 100644 --- a/src/hardware/timer.cpp +++ b/src/hardware/timer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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,8 @@ * 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 $ */ - - -#include #include "dosbox.h" #include "inout.h" #include "pic.h" @@ -29,8 +27,6 @@ #include "mixer.h" #include "timer.h" - - struct PIT_Block { Bit8u mode; /* Current Counter Mode */ @@ -84,7 +80,7 @@ static void counter_latch(Bitu counter) { else p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); break; default: - LOG(LOG_ERROR|LOG_PIT,"Illegal Mode %d for reading counter %d",p->mode,counter); + LOG(LOG_PIT,LOG_ERROR)("Illegal Mode %d for reading counter %d",p->mode,counter); micro%=p->micro; p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); break; @@ -115,19 +111,19 @@ static void write_latch(Bit32u port,Bit8u val) { if (p->write_latch == 0) p->cntr = 0x10000; else p->cntr = p->write_latch; p->start=PIC_MicroCount(); - p->micro=1000000/((float)PIT_TICK_RATE/(float)p->cntr); + p->micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)p->cntr)); switch (counter) { case 0x00: /* Timer hooked to IRQ 0 */ PIC_RemoveEvents(PIT0_Event); PIC_AddEvent(PIT0_Event,p->micro); - LOG(LOG_PIT,"PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode); + LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,(Bit32u)p->mode); break; case 0x02: /* Timer hooked to PC-Speaker */ // LOG(LOG_PIT,"PIT 2 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode); PCSPEAKER_SetCounter(p->cntr,p->mode); break; default: - LOG(LOG_ERROR|LOG_PIT,"PIT:Illegal timer selected for writing"); + LOG(LOG_PIT,LOG_ERROR)("PIT:Illegal timer selected for writing"); } } } @@ -149,12 +145,12 @@ static Bit8u read_latch(Bit32u port) { else pit[counter].read_state = 0; break; - case 1: /* read MSB */ - ret = (pit[counter].read_latch >> 8) & 0xff; + case 1: /* read LSB */ + ret = (pit[counter].read_latch & 0xff); pit[counter].read_latch = -1; break; - case 2: /* read LSB */ - ret = (pit[counter].read_latch & 0xff); + case 2: /* read MSB */ + ret = (pit[counter].read_latch >> 8) & 0xff; pit[counter].read_latch = -1; break; default: @@ -165,10 +161,6 @@ static Bit8u read_latch(Bit32u port) { return ret; } - - - - static void write_p43(Bit32u port,Bit8u val) { Bitu latch=(val >> 6) & 0x03; switch (latch) { @@ -190,87 +182,13 @@ static void write_p43(Bit32u port,Bit8u val) { if (val & 0x02) counter_latch(0); if (val & 0x04) counter_latch(1); if (val & 0x08) counter_latch(2); - } else E_Exit("PIT:Latch Timer Status %X",val); + } else if ((val & 0x10)==0) { /* Latch status words */ + LOG(LOG_PIT,LOG_ERROR)("Unsupported Latch status word call"); + } else LOG(LOG_PIT,LOG_ERROR)("Unhandled command:%X",val); break; } } -/* The TIMER Part */ - -enum { T_TICK,T_MICRO,T_DELAY}; - -struct Timer { - Bitu type; - union { - struct { - TIMER_TickHandler handler; - } tick; - struct{ - Bits left; - Bits total; - TIMER_MicroHandler handler; - } micro; - }; -}; - -static Timer * first_timer=0; -static std::list Timers; - -TIMER_Block * TIMER_RegisterTickHandler(TIMER_TickHandler handler) { - Timer * new_timer=new(Timer); - new_timer->type=T_TICK; - new_timer->tick.handler=handler; - Timers.push_front(new_timer); - return (TIMER_Block *)new_timer; -} - -TIMER_Block * TIMER_RegisterMicroHandler(TIMER_MicroHandler handler,Bitu micro) { - Timer * new_timer=new(Timer); - new_timer->type=T_MICRO; - new_timer->micro.handler=handler; - Timers.push_front(new_timer); - TIMER_SetNewMicro(new_timer,micro); - return (TIMER_Block *)new_timer; -} - -void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro) { - Timer * timer=(Timer *)block; - if (timer->type!=T_MICRO) E_Exit("TIMER:Illegal handler type"); - timer->micro.total=micro; - Bitu index=PIC_Index(); - while ((1000-index)>micro) { - PIC_AddEvent(timer->micro.handler,micro); - micro+=micro; - index+=micro; - } - timer->micro.left=timer->micro.total-(1000-index); -} - -void TIMER_AddTick(void) { - Bits index; - /* Check if there are timer handlers that need to be called */ - std::list::iterator i; - for(i=Timers.begin(); i != Timers.end(); ++i) { - Timer * timers=(*i); - switch (timers->type) { - case T_TICK: - timers->tick.handler(1); - break; - case T_MICRO: - index=1000; - while (index>=timers->micro.left) { - PIC_AddEvent(timers->micro.handler,timers->micro.left); - index-=timers->micro.left; - timers->micro.left=timers->micro.total; - } - timers->micro.left-=index; - break; - default: - E_Exit("TIMER:Illegal handler type"); - } - - } -} void TIMER_Init(Section* sect) { IO_RegisterWriteHandler(0x40,write_latch,"PIT Timer 0"); @@ -286,9 +204,12 @@ void TIMER_Init(Section* sect) { pit[0].read_latch=-1; pit[0].write_latch=0; pit[0].mode=3; + - pit[0].micro=1000000/((float)PIT_TICK_RATE/(float)pit[0].cntr); + pit[0].micro=(Bits)(1000000/((float)PIT_TICK_RATE/(float)pit[0].cntr)); pit[2].micro=100; + pit[2].read_latch=-1; /* MadTv1 */ + PIC_AddEvent(PIT0_Event,pit[0].micro); } diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index f07c5aa..17a0373 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -22,221 +22,65 @@ #include "dosbox.h" #include "video.h" #include "pic.h" -#include "render.h" #include "timer.h" #include "vga.h" +#include "inout.h" VGA_Type vga; -Bit32u CGAWriteTable[256]; +Bit32u CGA_4_Table[256]; Bit32u ExpandTable[256]; Bit32u Expand16Table[4][16]; Bit32u Expand16BigTable[0x10000]; Bit32u FillTable[16]; -static void EndRetrace(void) { - /* start the actual display update now */ - RENDER_DoUpdate(); - vga.config.retrace=false; -} -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; - vga.config.retrace=true; -} - -static 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,"Split at %d",stop); - goto drawnormal; - } - switch (vga.mode) { - case GFX_16: - buf=&vga.buffer[vga.config.real_start*8+vga.config.pel_panning]; - bufsplit=vga.buffer; - break; - case GFX_256U: - buf=&vga.mem.linear[vga.config.real_start*4+vga.config.pel_panning/2]; - bufsplit=vga.mem.linear; - break; - case GFX_256C: - buf=memory+0xa0000; - bufsplit=memory+0xa0000; - break; - default: - LOG(LOG_VGAGFX,"VGA:Unhandled split screen mode %d",vga.mode); - goto norender; - } - part_handler(buf,0,0,vga.draw.width,stop); - part_handler(bufsplit,0,stop,vga.draw.width,vga.draw.height-stop); - } else { -drawnormal: - switch (vga.mode) { - case GFX_2: - VGA_DrawGFX2_Fast(vga.buffer,vga.draw.width); - buf=vga.buffer; - break; - case GFX_4: - VGA_DrawGFX4_Fast(vga.buffer,vga.draw.width); - buf=vga.buffer; - break; - case TEXT_16: - VGA_DrawTEXT(vga.buffer,vga.draw.width); - buf=vga.buffer; - break; - case GFX_16: - buf=&vga.buffer[vga.config.real_start*8+vga.config.pel_panning]; - break; - case GFX_256C: - buf=memory+0xa0000; - break; - case GFX_256U: - buf=&vga.mem.linear[vga.config.real_start*4+vga.config.pel_panning/2]; - break; - } - part_handler(buf,0,0,vga.draw.width,vga.draw.height); - } -norender:; - } - -} - -void VGA_FindSettings(void) { - /* Sets up the correct memory handler from the vga.mode setting */ - MEM_ClearPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x20000)); - /* Detect the kind of video mode this is */ - if (vga.config.gfxmode) { - if (vga.config.vga_enabled) { - if (vga.config.chained) { - /* 256 color chained vga */ - vga.mode=GFX_256C; - //Doesn't need a memory handler - } else { - /* 256 color unchained vga */ - vga.mode=GFX_256U; - MEM_SetupPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x10000), - &VGA_NormalReadHandler,&VGA_GFX_256U_WriteHandler); - } - } else if (vga.config.cga_enabled) { - /* 4 color cga */ - //TODO Detect hercules modes, probably set them up in bios too - if (vga.seq.clocking_mode & 0x8) { - vga.mode=GFX_4; -// MEM_SetupPageHandlers(PAGE_COUNT(0x0b8000),PAGE_COUNT(0x10000),&VGA_GFX_4_ReadHandler,&VGA_GFX_4_WriteHandler); - } else vga.mode=GFX_2; - //TODO Maybe also use a page handler for cga mode - } else { - /* 16 color ega */ - vga.mode=GFX_16; - MEM_SetupPageHandlers(PAGE_COUNT(0xa0000),PAGE_COUNT(0x10000), - &VGA_NormalReadHandler,&VGA_GFX_16_WriteHandler); - } - } else { - vga.mode=TEXT_16; - } +void VGA_SetMode(VGAModes mode) { + vga.mode=mode; + VGA_SetupHandlers(); VGA_StartResize(); } -static void VGA_DoResize(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 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 hdispend = 1 + (vga.crtc.horizontal_display_end); - //TODO Maybe check if blanking comes before display_end - - double clock=(double)vga.config.clock; - /* 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; - - LOG(LOG_VGA,"H total %d, V Total %d",htotal,vtotal); - LOG(LOG_VGA,"H D End %d, V D End %d",hdispend,vdispend); - fps=clock/(vtotal*htotal); - - vga.draw.resizing=false; - Bitu width,height,pitch,flags; - - 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; - switch (vga.mode) { - case GFX_256C: - case GFX_256U: - 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; - } - } - width<<=2; - pitch=vga.config.scan_len*8; - break; - case GFX_16: - width<<=3; - pitch=vga.config.scan_len*16; - break; - case GFX_4: - width<<=3; - pitch=width; - break; - case GFX_2: - width<<=3; - pitch=width; - break; - case TEXT_16: - /* probably a 16-color text mode, got to detect mono mode somehow */ - width<<=3; /* 8 bit wide text font */ - if (width>640) width=640; - if (height>480) height=480; - pitch=width; - }; - 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 */ - } - if (( width != vga.draw.width) || (height != vga.draw.height) || (pitch != vga.draw.pitch)) { - PIC_RemoveEvents(VGA_BlankTimer); - vga.draw.width=width; - vga.draw.height=height; - vga.draw.pitch=pitch; - - LOG(LOG_VGA,"Width %d, Height %d",width,height); - LOG(LOG_VGA,"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); - } -}; - void VGA_StartResize(void) { if (!vga.draw.resizing) { vga.draw.resizing=true; /* Start a resize after 50 ms */ - PIC_AddEvent(VGA_DoResize,50000); + PIC_AddEvent(VGA_SetupDrawing,50000); } } +void VGA_SetClock(Bitu which,Bitu target) { + struct{ + Bitu n,m; + Bits err; + } best; + best.err=target; + Bitu n,m,r; + + for (r = 0; r <= 3; r++) { + Bitu f_vco = target * (1 << r); + if (MIN_VCO <= f_vco && f_vco < MAX_VCO) break; + } + for (n=1;n<=31;n++) { + m=(target * (n + 2) * (1 << r) + (S3_CLOCK_REF/2)) / S3_CLOCK_REF - 2; + if (0 <= m && m <= 127) { + Bitu temp_target = S3_CLOCK(m,n,r); + Bits err = target - temp_target; + if (err < 0) err = -err; + if (err < best.err) { + best.err = err; + best.m = m; + best.n = n; + } + } + } + /* Program the s3 clock chip */ + vga.s3.clk[which].m=best.m; + vga.s3.clk[which].r=r; + vga.s3.clk[which].n=best.n; + VGA_StartResize(); +} + void VGA_Init(Section* sec) { vga.draw.resizing=false; VGA_SetupMemory(); @@ -245,14 +89,16 @@ void VGA_Init(Section* sec) { VGA_SetupGFX(); VGA_SetupSEQ(); VGA_SetupAttr(); + VGA_SetClock(0,CLK_25); + VGA_SetClock(1,CLK_28); /* Generate tables */ Bitu i,j; for (i=0;i<256;i++) { ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24); #ifdef WORDS_BIGENDIAN - CGAWriteTable[i]=((i>>0)&3) | (((i>>2)&3) << 8)| (((i>>4)&3) <<16) | (((i>>6)&3) << 24); + CGA_4_Table[i]=((i>>0)&3) | (((i>>2)&3) << 8)| (((i>>4)&3) <<16) | (((i>>6)&3) << 24); #else - CGAWriteTable[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24); + 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++) { diff --git a/src/hardware/vga.h b/src/hardware/vga.h index 9ce4b99..51d0edc 100644 --- a/src/hardware/vga.h +++ b/src/hardware/vga.h @@ -22,39 +22,57 @@ #include #include "dosbox.h" -#undef TEXT -#undef GRAPH -/* conflicts with int10.h */ -enum { TEXT, GRAPH }; -enum { GFX_256C,GFX_256U,GFX_16,GFX_4,GFX_2, TEXT_16 }; +enum VGAModes { + M_TEXT16, + M_CGA2,M_CGA4, + M_TANDY16, + M_EGA2,M_EGA4,M_EGA16, + M_VGA, + M_LIN8, + M_ERROR, +}; + +#define CLK_25 25175 +#define CLK_28 28322 + +#define MIN_VCO 180000 +#define MAX_VCO 360000 + +#define S3_CLOCK_REF 14318 /* KHz */ +#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; - Bit16u cursor; } VGA_Internal; typedef struct { +/* Memory handlers */ + Bitu mh_mask; /* Video drawing */ - Bit16u display_start; - Bit16u real_start; - bool retrace; /* A retrace has started */ + Bitu display_start; + Bitu real_start; + bool retrace; /* A retrace is active */ Bitu scan_len; + Bitu cursor_start; /* Some other screen related variables */ Bitu line_compare; - Bitu clock; - bool clock_half; - bool chained; /* Enable or Disabled Chain 4 Mode */ - bool gfxmode; /* Yes or No Easy no */ bool blinking; /* Attribute bit 7 is blinking */ - bool vga_enabled; - bool cga_enabled; - bool vline_double; Bit8u vline_height; @@ -64,6 +82,10 @@ typedef struct { Bit8u bytes_skip; /* Specific stuff memory write/read handling */ + + VGA_ReadHandler * readhandler; + VGA_WriteHandler * writehandler; + Bit8u read_mode; Bit8u write_mode; Bit8u read_map_select; @@ -91,13 +113,51 @@ typedef struct { bool double_width; bool double_height; Bitu lines; - Bit8u * font; Bit8u font_height; + Bit8u font[64*1024]; + Bitu font1_start; + Bitu font2_start; + Bitu rows,cols; struct { - Bitu row,col,sline,eline,count; + Bit8u sline,eline; + Bit8u count,delay; + Bit8u enabled; } cursor; } VGA_Draw; +typedef struct { + Bit8u bank; + Bit8u reg_lock1; + Bit8u reg_lock2; + Bit8u reg_31; + Bit8u reg_35; + Bit8u reg_43; + Bit8u reg_58; + Bit8u reg_51; + Bit8u reg_55; + Bit8u ex_hor_overflow; + Bit8u ex_ver_overflow; + Bit16u la_window; + struct { + Bit8u r; + Bit8u n; + Bit8u m; + } clk[4],mclk; + struct { + Bit8u lock; + Bit8u cmd; + } pll; +} VGA_S3; + +typedef struct { + Bit8u color_select; +} VGA_CGA; + +typedef struct { + Bit8u mem_bank; + Bit8u disp_bank; + Bit8u reg_index; +} VGA_TANDY; typedef struct { Bit8u index; @@ -109,7 +169,6 @@ typedef struct { Bit8u memory_mode; } VGA_Seq; - typedef struct { Bit8u palette[16]; Bit8u mode_control; @@ -118,9 +177,9 @@ typedef struct { Bit8u color_plane_enable; Bit8u color_select; Bit8u index; + Bit8u enabled; } VGA_Attr; - typedef struct { Bit8u horizontal_total; Bit8u horizontal_display_end; @@ -143,12 +202,13 @@ typedef struct { Bit8u vertical_display_end; Bit8u offset; Bit8u underline_location; - Bit8u start_vertical_blank; - Bit8u end_vertical_blank; + Bit8u start_vertical_blanking; + Bit8u end_vertical_blanking; Bit8u mode_control; Bit8u line_compare; Bit8u index; + bool read_only; } VGA_Crtc; typedef struct { @@ -188,15 +248,14 @@ union VGA_Latch { }; union VGA_Memory { - Bit8u linear[64*1024*4]; - Bit8u paged[64*1024][4]; - VGA_Latch latched[64*1024]; + Bit8u linear[512*1024*4]; + Bit8u paged[512*1024][4]; + VGA_Latch latched[512*1024]; }; - - typedef struct { - Bitu mode; /* The mode the vga system is in */ + VGAModes mode; /* The mode the vga system is in */ + Bit8u misc_output; VGA_Draw draw; VGA_Config config; VGA_Internal internal; @@ -207,40 +266,23 @@ typedef struct { VGA_Gfx gfx; VGA_Dac dac; VGA_Latch latch; + VGA_S3 s3; + VGA_CGA cga; + VGA_TANDY tandy; VGA_Memory mem; -/* Extra buffer following main video ram with double data for overflowing of addresses */ - Bit8u buffer[1024*1024]; /* 256 kb vid ram with 16 colors and double addresses */ } VGA_Type; - - /* Functions for different resolutions */ -//void VGA_FindSize(void); -void VGA_FindSettings(void); +void VGA_SetMode(VGAModes mode); +void VGA_SetupHandlers(void); void VGA_StartResize(void); +void VGA_SetupDrawing(void); -/* The Different Drawing functions */ -void VGA_DrawTEXT(Bit8u * bitdata,Bitu next_line); -void VGA_DrawGFX256U_Full(Bit8u * bitdata,Bitu next_line); -void VGA_DrawGFX16_Fast(Bit8u * bitdata,Bitu next_line); -void VGA_DrawGFX4_Fast(Bit8u * bitdata,Bitu next_line); -void VGA_DrawGFX2_Fast(Bit8u * bitdata,Bitu next_line); -/* The Different Memory Read/Write Handlers */ -Bit8u VGA_NormalReadHandler(Bit32u start); - -void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val); -void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val); -void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val); - -Bit8u VGA_GFX_4_ReadHandler(Bit32u start); - - - -/* Some support functions */ +/* Some DAC/Attribute functions */ void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal); - +void VGA_ATTR_SetPalette(Bit8u index,Bit8u val); /* The VGA Subfunction startups */ void VGA_SetupAttr(void); @@ -252,17 +294,16 @@ void VGA_SetupGFX(void); void VGA_SetupSEQ(void); /* Some Support Functions */ +void VGA_SetClock(Bitu which,Bitu target); void VGA_DACSetEntirePalette(void); void VGA_StartRetrace(void); +void VGA_StartUpdateLFB(void); extern VGA_Type vga; -extern Bit8u vga_rom_08[256 * 8]; -extern Bit8u vga_rom_14[256 * 14]; -extern Bit8u vga_rom_16[256 * 16]; extern Bit32u ExpandTable[256]; extern Bit32u FillTable[16]; -extern Bit32u CGAWriteTable[256]; +extern Bit32u CGA_4_Table[256]; extern Bit32u Expand16Table[4][16]; extern Bit32u Expand16BigTable[0x10000]; diff --git a/src/hardware/vga_attr.cpp b/src/hardware/vga_attr.cpp index 8c5d06a..e94936c 100644 --- a/src/hardware/vga_attr.cpp +++ b/src/hardware/vga_attr.cpp @@ -22,14 +22,23 @@ #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); + else val|=(vga.attr.color_select & 0xc) << 4; + VGA_DAC_CombineColor(index,val); +} + void write_p3c0(Bit32u port,Bit8u val) { if (!vga.internal.attrindex) { attr(index)=val & 0x1F; vga.internal.attrindex=true; + attr(enabled)=val & 0x20; /* - 0-4 Address of data register to write to port 3C0h or read from port 3C1h - If set screen output is enabled and the palette can not be modified, - if clear screen output is disabled and the palette can be modified. + 0-4 Address of data register to write to port 3C0h or read from port 3C1h + 5 If set screen output is enabled and the palette can not be modified, + if clear screen output is disabled and the palette can be modified. */ return; } else { @@ -40,20 +49,29 @@ void write_p3c0(Bit32u port,Bit8u val) { case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: - val&=0x3f; - attr(palette[attr(index)])=val; - VGA_DAC_CombineColor(attr(index),val); + if (!attr(enabled)) VGA_ATTR_SetPalette(attr(index),val); /* 0-5 Index into the 256 color DAC table. May be modified by 3C0h index 10h and 14h. */ break; case 0x10: /* Mode Control Register */ - if (val != attr(mode_control)) { + if ((attr(mode_control) ^ val) & 0x80) { attr(mode_control)=val; - vga.config.gfxmode=val&1; - vga.config.vga_enabled=(val & 0x40)>0; - VGA_FindSettings(); + for (Bitu i=0;i<0x10;i++) { + VGA_ATTR_SetPalette(i,vga.attr.palette[i]); + } + } + attr(mode_control)=val; + /* + Special hacks for games programming registers themselves, + Doesn't work if they program EGA16 themselves, + but haven't encountered that yet + */ + if (val&0x40) { + if (vga.mode0x7) vga.config.pel_panning=0; + else vga.config.pel_panning=val+1; + break; + case M_VGA: + case M_LIN8: + vga.config.pel_panning=(val & 0x7)/2; + break; + default: + vga.config.pel_panning=(val & 0x7); + } /* 0-3 Indicates number of pixels to shift the display left Value 9bit textmode 256color mode Other modes @@ -114,7 +141,12 @@ void write_p3c0(Bit32u port,Bit8u val) { */ break; case 0x14: /* Color Select Register */ - attr(color_select)=val; + if (attr(color_select) ^ val) { + attr(color_select)=val; + for (Bitu i=0;i<0x10;i++) { + VGA_ATTR_SetPalette(i,vga.attr.palette[i]); + } + } /* 0-1 If 3C0h index 10h bit 7 is set these 2 bits are used as bits 4-5 of the index into the DAC table. @@ -122,10 +154,9 @@ void write_p3c0(Bit32u port,Bit8u val) { except in 256 color mode. Note: this register does not affect 256 color modes. */ - if (val) LOG(LOG_VGAGFX,"VGA:ATTR:DAC index set to %d",val); break; default: - LOG(LOG_VGAMISC,"VGA:ATTR:Write to unkown Index %2X",attr(index)); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:Write to unkown Index %2X",attr(index)); break; } } @@ -151,7 +182,7 @@ Bit8u read_p3c1(Bit32u port) { case 0x14: /* Color Select Register */ return attr(color_select); default: - LOG(LOG_VGAMISC,"VGA:ATTR:Read from unkown Index %2X",attr(index)); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:ATTR:Read from unkown Index %2X",attr(index)); } return 0; }; diff --git a/src/hardware/vga_crtc.cpp b/src/hardware/vga_crtc.cpp index 56b558b..ad7becd 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.cpp @@ -19,7 +19,8 @@ #include "dosbox.h" #include "inout.h" #include "vga.h" - +#include "debug.h" +#include "cpu.h" #define crtc(blah) vga.crtc.blah @@ -34,12 +35,15 @@ Bit8u read_p3d4(Bit32u port) { void write_p3d5(Bit32u port,Bit8u val) { +// if (crtc(index)>0x18) LOG_MSG("VGA CRCT write %X to reg %X",val,crtc(index)); switch(crtc(index)) { case 0x00: /* Horizontal Total Register */ + if (crtc(read_only)) break; crtc(horizontal_total)=val; /* 0-7 Horizontal Total Character Clocks-5 */ break; case 0x01: /* Horizontal Display End Register */ + if (crtc(read_only)) break; if (val != crtc(horizontal_display_end)) { crtc(horizontal_display_end)=val; VGA_StartResize(); @@ -47,10 +51,12 @@ void write_p3d5(Bit32u port,Bit8u val) { /* 0-7 Number of Character Clocks Displayed -1 */ break; case 0x02: /* Start Horizontal Blanking Register */ + if (crtc(read_only)) break; crtc(start_horizontal_blanking)=val; /* 0-7 The count at which Horizontal Blanking starts */ break; case 0x03: /* End Horizontal Blanking Register */ + if (crtc(read_only)) break; crtc(end_horizontal_blanking)=val; /* 0-4 Horizontal Blanking ends when the last 6 bits of the character @@ -62,10 +68,12 @@ void write_p3d5(Bit32u port,Bit8u val) { */ break; case 0x04: /* Start Horizontal Retrace Register */ + if (crtc(read_only)) break; crtc(start_horizontal_retrace)=val; /* 0-7 Horizontal Retrace starts when the Character Counter reaches this value. */ break; case 0x05: /* End Horizontal Retrace Register */ + if (crtc(read_only)) break; crtc(end_horizontal_retrace)=val; /* 0-4 Horizontal Retrace ends when the last 5 bits of the character counter @@ -76,6 +84,7 @@ void write_p3d5(Bit32u port,Bit8u val) { */ break; case 0x06: /* Vertical Total Register */ + if (crtc(read_only)) break; if (val != crtc(vertical_total)) { crtc(vertical_total)=val; VGA_StartResize(); @@ -86,9 +95,10 @@ void write_p3d5(Bit32u port,Bit8u val) { */ break; case 0x07: /* Overflow Register */ - crtc(overflow)=val; - vga.config.line_compare=(vga.config.line_compare & 0x2ff) | (val & 0x10) << 4; - if ((vga.crtc.overflow ^ val) & 0xef) { + //Line compare bit ignores read only */ + vga.config.line_compare=(vga.config.line_compare & 0x6ff) | (val & 0x10) << 4; + if (crtc(read_only)) break; + if ((vga.crtc.overflow ^ val) & 0xd6) { crtc(overflow)=val; VGA_StartResize(); } else crtc(overflow)=val; @@ -119,7 +129,7 @@ void write_p3d5(Bit32u port,Bit8u val) { 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 & 0x1ff)|(val&0x40)<<3; + 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; VGA_StartResize(); @@ -137,6 +147,8 @@ void write_p3d5(Bit32u port,Bit8u val) { break; case 0x0A: /* Cursor Start Register */ crtc(cursor_start)=val; + vga.draw.cursor.sline=val&0x1f; + vga.draw.cursor.enabled=!(val&0x20); /* 0-4 First scanline of cursor within character. 5 Turns Cursor off if set @@ -144,6 +156,9 @@ void write_p3d5(Bit32u port,Bit8u val) { break; case 0x0B: /* Cursor End Register */ crtc(cursor_end)=val; + vga.draw.cursor.eline=val&0x1f; + vga.draw.cursor.delay=(val>>5)&0x3; + /* 0-4 Last scanline of cursor within character 5-6 Delay of cursor data in character clocks. @@ -151,27 +166,25 @@ void write_p3d5(Bit32u port,Bit8u val) { break; case 0x0C: /* Start Address High Register */ crtc(start_address_high)=val; - vga.config.display_start=(vga.config.display_start & 0x00FF)| (val << 8); + vga.config.display_start=(vga.config.display_start & 0xFF00FF)| (val << 8); /* 0-7 Upper 8 bits of the start address of the display buffer */ break; case 0x0D: /* Start Address Low Register */ crtc(start_address_low)=val; - vga.config.display_start=(vga.config.display_start & 0xFF00)| val; + vga.config.display_start=(vga.config.display_start & 0xFFFF00)| val; /* 0-7 Lower 8 bits of the start address of the display buffer */ break; case 0x0E: /*Cursor Location High Register */ crtc(cursor_location_high)=val; - if (vga.config.scan_len<2) break; - vga.draw.cursor.row=(crtc(cursor_location_high)<<8|crtc(cursor_location_low))/(vga.config.scan_len*2); - vga.draw.cursor.col=(crtc(cursor_location_high)<<8|crtc(cursor_location_low))%(vga.config.scan_len*2); + vga.config.cursor_start&=0xff00ff; + vga.config.cursor_start|=val << 8; /* 0-7 Upper 8 bits of the address of the cursor */ break; case 0x0F: /* Cursor Location Low Register */ //TODO update cursor on screen crtc(cursor_location_low)=val; - if (vga.config.scan_len<2) break; - vga.draw.cursor.row=(crtc(cursor_location_high)<<8|crtc(cursor_location_low))/(vga.config.scan_len*2); - vga.draw.cursor.col=(crtc(cursor_location_high)<<8|crtc(cursor_location_low))%(vga.config.scan_len*2); + vga.config.cursor_start&=0xffff00; + vga.config.cursor_start|=val; /* 0-7 Lower 8 bits of the address of the cursor */ break; case 0x10: /* Vertical Retrace Start Register */ @@ -184,6 +197,7 @@ void write_p3d5(Bit32u port,Bit8u val) { break; case 0x11: /* Vertical Retrace End Register */ crtc(vertical_retrace_end)=val; + crtc(read_only)=(val & 128)>0; /* 0-3 Vertical Retrace ends when the last 4 bits of the line counter equals this value. @@ -209,7 +223,8 @@ void write_p3d5(Bit32u port,Bit8u val) { case 0x13: /* Offset register */ if (val!=crtc(offset)) { crtc(offset)=val; - vga.config.scan_len=val; + vga.config.scan_len&=0x300; + vga.config.scan_len|=val; VGA_StartResize(); } /* @@ -226,7 +241,10 @@ void write_p3d5(Bit32u port,Bit8u val) { */ break; case 0x15: /* Start Vertical Blank Register */ - crtc(start_vertical_blank)=val; + if (val!=crtc(start_vertical_blanking)) { + crtc(start_vertical_blanking)=val; + VGA_StartResize(); + } /* 0-7 Lower 8 bits of Vertical Blank Start. Vertical blanking starts when the line counter reaches this value. Bit 8 is found in 3d4h index 7 @@ -234,18 +252,14 @@ void write_p3d5(Bit32u port,Bit8u val) { */ break; case 0x16: /* End Vertical Blank Register */ - crtc(end_vertical_blank)=val; + crtc(end_vertical_blanking)=val; /* 0-6 Vertical blanking stops when the lower 7 bits of the line counter equals this field. Some SVGA chips uses all 8 bits! */ break; case 0x17: /* Mode Control Register */ - if (val!=crtc(mode_control)) { - crtc(mode_control)=val; - vga.config.cga_enabled=!((val&1)>0); - VGA_FindSettings(); - } + crtc(mode_control)=val; /* 0 If clear use CGA compatible memory addressing system by substituting character row scan counter bit 0 for address bit 13, @@ -264,21 +278,229 @@ void write_p3d5(Bit32u port,Bit8u val) { break; case 0x18: /* Line Compare Register */ crtc(line_compare)=val; - vga.config.line_compare=(vga.config.line_compare & 0x300) | val; + vga.config.line_compare=(vga.config.line_compare & 0x700) | val; /* 0-7 Lower 8 bits of the Line Compare. When the Line counter reaches this value, the display address wraps to 0. Provides Split Screen facilities. Bit 8 is found in 3d4h index 7 bit 4. Bit 9 is found in 3d4h index 9 bit 6. */ - break; +/* S3 specific group */ + case 0x31: /* CR31 Memory Configuration */ +//TODO Base address + vga.s3.reg_31=val; + break; + /* + 0 Enable Base Address Offset (CPUA BASE). Enables bank operation if + set, disables if clear. + 1 Two Page Screen Image. If set enables 2048 pixel wide screen setup + 2 VGA 16bit Memory Bus Width. Set for 16bit, clear for 8bit + 3 Use Enhanced Mode Memory Mapping (ENH MAP). Set to enable access to + video memory above 256k. + 4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index + 51h, for the 864/964 see index 69h. + 6 High Speed Text Display Font Fetch Mode. If set enables Page Mode + for Alpha Mode Font Access. + 7 (not 864/964) Extended BIOS ROM Space Mapped out. If clear the area + C6800h-C7FFFh is mapped out, if set it is accessible. + */ + case 0x35: /* CR35 CRT Register Lock */ + if (vga.s3.reg_lock1 != 0x48) return; //Needed for uvconfig detection + vga.s3.reg_35=val & 0xf0; + if ((vga.s3.bank & 0xf) ^ (val & 0xf)) { + vga.s3.bank&=0xf0; + vga.s3.bank|=val & 0xf; + VGA_SetupHandlers(); + } + break; + /* + 0-3 CPU Base Address. 64k bank number. For the 801/5 and 928 see 3d4h + index 51h bits 2-3. For the 864/964 see index 6Ah. + 4 Lock Vertical Timing Registers (LOCK VTMG). Locks 3d4h index 6, 7 + (bits 0,2,3,5,7), 9 bit 5, 10h, 11h bits 0-3, 15h, 16h if set + 5 Lock Horizontal Timing Registers (LOCK HTMG). Locks 3d4h index + 0,1,2,3,4,5,17h bit 2 if set + 6 (911/924) Lock VSync Polarity. + 7 (911/924) Lock HSync Polarity. + */ + case 0x38: /* CR38 Register Lock 1 */ + vga.s3.reg_lock1=val; + break; + case 0x39: /* CR39 Register Lock 2 */ + vga.s3.reg_lock2=val; + break; + case 0x43: /* CR43 Extended Mode */ + vga.s3.reg_43=val & ~0x4; + if (((val & 0x4) ^ (vga.config.scan_len >> 6)) & 0x4) { + vga.config.scan_len&=0x2ff; + vga.config.scan_len|=(val & 0x4) << 6; + VGA_StartResize(); + } + break; + /* + 2 Logical Screen Width bit 8. Bit 8 of the Display Offset Register/ + (3d4h index 13h). (801/5,928) Only active if 3d4h index 51h bits 4-5 + are 0 + */ + case 0x51: /* Extended System Control 2 */ + vga.s3.reg_51=val & 0xc0; //Only store bits 6,7 + //TODO Display start + vga.config.display_start&=0xFCFFFF; + vga.config.display_start|=(val & 3) << 16; + if ((vga.s3.bank&0xcf) ^ ((val&0xc)<<2)) { + vga.s3.bank&=0xcf; + vga.s3.bank|=(val&0xc)<<2; + VGA_SetupHandlers(); + } + if (((val & 0x30) ^ (vga.config.scan_len >> 4)) & 0x30) { + vga.config.scan_len&=0xff; + vga.config.scan_len|=(val & 0x30) << 4; + VGA_StartResize(); + } + break; + /* + 0 (80x) Display Start Address bit 18 + 0-1 (928 +) Display Start Address bit 18-19 + Bits 16-17 are in index 31h bits 4-5, Bits 0-15 are in 3d4h index + 0Ch,0Dh. For the 864/964 see 3d4h index 69h + 2 (80x) CPU BASE. CPU Base Address Bit 18. + 2-3 (928 +) Old CPU Base Address Bits 19-18. + 64K Bank register bits 4-5. Bits 0-3 are in 3d4h index 35h. + For the 864/964 see 3d4h index 6Ah + 4-5 Logical Screen Width Bit [8-9]. Bits 8-9 of the CRTC Offset register + (3d4h index 13h). If this field is 0, 3d4h index 43h bit 2 is active + 6 (928,964) DIS SPXF. Disable Split Transfers if set. Spilt Transfers + allows transferring one half of the VRAM shift register data while + the other half is being output. For the 964 Split Transfers + must be enabled in enhanced modes (4AE8h bit 0 set). Guess: They + probably can't time the VRAM load cycle closely enough while the + graphics engine is running. + 7 (not 864/964) Enable EPROM Write. If set enables flash memory write + control to the BIOS ROM address + */ + case 0x55: /* Extended Video DAC Control */ + vga.s3.reg_55=val; + break; + /* + 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the + RAMDAC, allowing access to all 8 or 16 registers on advanced RAMDACs. + If this field is 0, 3d4h index 43h bit 1 is active. + 2 Enable General Input Port Read. If set DAC reads are disabled and the + STRD strobe for reading the General Input Port is enabled for reading + while DACRD is active, if clear DAC reads are enabled. + 3 (928) Enable External SID Operation if set. If set video data is + passed directly from the VRAMs to the DAC rather than through the + VGA chip + 4 Hardware Cursor MS/X11 Mode. If set the Hardware Cursor is in X11 + mode, if clear in MS-Windows mode + 5 (80x,928) Hardware Cursor External Operation Mode. If set the two + bits of cursor data ,is output on the HC[0-1] pins for the video DAC + The SENS pin becomes HC1 and the MID2 pin becomes HC0. + 6 ?? + 7 (80x,928) Disable PA Output. If set PA[0-7] and VCLK are tristated. + (864/964) TOFF VCLK. Tri-State Off VCLK Output. VCLK output tri + -stated if set + */ + case 0x58: /* Linear Address Window Control */ + vga.s3.reg_58=val; + break; + /* + 0-1 Linear Address Window Size. Must be less than or equal to video + memory size. 0: 64K, 1: 1MB, 2: 2MB, 3: 4MB (928)/8Mb (864/964) + 2 (not 864/964) Enable Read Ahead Cache if set + 3 (80x,928) ISA Latch Address. If set latches address during every ISA + cycle, unlatches during every ISA cycle if clear. + (864/964) LAT DEL. Address Latch Delay Control (VL-Bus only). If set + address latching occours in the T1 cycle, if clear in the T2 cycle + (I.e. one clock cycle delayed). + 4 ENB LA. Enable Linear Addressing if set. + 5 (not 864/964) Limit Entry Depth for Write-Post. If set limits Write + -Post Entry Depth to avoid ISA bus timeout due to wait cycle limit. + 6 (928,964) Serial Access Mode (SAM) 256 Words Control. If set SAM + control is 256 words, if clear 512 words. + 7 (928) RAS 6-MCLK. If set the random read/write cycle time is 6MCLKs, + if clear 7MCLKs + */ + case 0x59: /* Linear Address Window Position High */ + if ((vga.s3.la_window&0xff00) ^ (val << 8)) { + vga.s3.la_window=(vga.s3.la_window&0x00ff) | (val << 8); + VGA_StartUpdateLFB(); + } + break; + case 0x5a: /* Linear Address Window Position Low */ + if ((vga.s3.la_window&0x00ff) ^ val) { + vga.s3.la_window=(vga.s3.la_window&0xff00) | val; + VGA_StartUpdateLFB(); + } + break; + case 0x5D: /* Extended Horizontal Overflow */ + if ((val & vga.s3.ex_hor_overflow) ^ 3) { + vga.s3.ex_hor_overflow=val; + VGA_StartResize(); + } else vga.s3.ex_hor_overflow=val; + break; + /* + 0 Horizontal Total bit 8. Bit 8 of the Horizontal Total register (3d4h + index 0) + 1 Horizontal Display End bit 8. Bit 8 of the Horizontal Display End + register (3d4h index 1) + 2 Start Horizontal Blank bit 8. Bit 8 of the Horizontal Start Blanking + register (3d4h index 2). + 3 (864,964) EHB+64. End Horizontal Blank +64. If set the /BLANK pulse + is extended by 64 DCLKs. Note: Is this bit 6 of 3d4h index 3 or + does it really extend by 64 ? + 4 Start Horizontal Sync Position bit 8. Bit 8 of the Horizontal Start + Retrace register (3d4h index 4). + 5 (864,964) EHS+32. End Horizontal Sync +32. If set the HSYNC pulse + is extended by 32 DCLKs. Note: Is this bit 5 of 3d4h index 5 or + does it really extend by 32 ? + 6 (928,964) Data Transfer Position bit 8. Bit 8 of the Data Transfer + Position register (3d4h index 3Bh) + 7 (928,964) Bus-Grant Terminate Position bit 8. Bit 8 of the Bus Grant + Termination register (3d4h index 5Fh). + */ + case 0x5e: /* Extended Vertical Overflow */ + vga.config.line_compare=(vga.config.line_compare & 0x3ff) | (val & 0x40) << 4; + if ((val ^ vga.s3.ex_ver_overflow) & 0x3) { + vga.s3.ex_ver_overflow=val; + VGA_StartResize(); + } else vga.s3.ex_ver_overflow=val; + break; + /* + 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h + index 6). Bits 8 and 9 are in 3d4h index 7 bit 0 and 5. + 1 Vertical Display End bit 10. Bit 10 of the Vertical Display End + register (3d4h index 12h). Bits 8 and 9 are in 3d4h index 7 bit 1 + and 6 + 2 Start Vertical Blank bit 10. Bit 10 of the Vertical Start Blanking + register (3d4h index 15h). Bit 8 is in 3d4h index 7 bit 3 and bit 9 + in 3d4h index 9 bit 5 + 4 Vertical Retrace Start bit 10. Bit 10 of the Vertical Start Retrace + register (3d4h index 10h). Bits 8 and 9 are in 3d4h index 7 bit 2 + and 7. + 6 Line Compare Position bit 10. Bit 10 of the Line Compare register + (3d4h index 18h). Bit 8 is in 3d4h index 7 bit 4 and bit 9 in 3d4h + index 9 bit 6. + */ + case 0x69: /* Extended System Control 3 */ + if (((vga.config.display_start & 0x1f0000)>>16) ^ (val & 0x1f)) { + vga.config.display_start&=0xffff; + vga.config.display_start|=(val & 0x1f) << 16; + } + break; + case 0x6a: /* Extended System Control 4 */ + vga.s3.bank=val & 0x3f; + VGA_SetupHandlers(); + break; + default: - LOG(LOG_VGAMISC,"VGA:CRTC:Write to unknown index %2X",val,crtc(index)); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:Write %X to unknown index %2X",val,crtc(index)); } } Bit8u read_p3d5(Bit32u port) { +// LOG_MSG("VGA CRCT read from reg %X",crtc(index)); switch(crtc(index)) { case 0x00: /* Horizontal Total Register */ return crtc(horizontal_total); @@ -323,17 +545,64 @@ Bit8u read_p3d5(Bit32u port) { case 0x14: /* Underline Location Register */ return crtc(underline_location); case 0x15: /* Start Vertical Blank Register */ - return crtc(start_vertical_blank); + return crtc(start_vertical_blanking); case 0x16: /* End Vertical Blank Register */ - return crtc(end_vertical_blank); + return crtc(end_vertical_blanking); case 0x17: /* Mode Control Register */ return crtc(mode_control); case 0x18: /* Line Compare Register */ return crtc(line_compare); + + +/* Additions for S3 SVGA Support */ + case 0x2d: /* Extended Chip ID. */ + return 0x88; + // Always 88h ? + case 0x2e: /* New Chip ID */ + return 0x11; + //Trio 64 id + case 0x2f: /* Revision */ + return 0x80; + case 0x30: /* CR30 Chip ID/REV register */ + return 0xe0; //Trio+ dual byte + // Trio32/64 has 0xe0. extended + case 0x31: /* CR31 Memory Configuration */ +//TODO mix in bits from baseaddress; + return vga.s3.reg_31; + case 0x35: /* CR35 CRT Register Lock */ + return vga.s3.reg_35|(vga.s3.bank & 0xf); + case 0x36: /* CR36 Reset State Read 1 */ + return 0x8f; + //2 Mb PCI and some bios settings + case 0x37: /* Reset state read 2 */ + return 0x2b; + case 0x38: /* CR38 Register Lock 1 */ + return vga.s3.reg_lock1; + case 0x39: /* CR39 Register Lock 2 */ + return vga.s3.reg_lock2; + case 0x43: /* CR43 Extended Mode */ + return vga.s3.reg_43|((vga.config.scan_len>>6)&0x4); + case 0x51: /* Extended System Control 2 */ + return ((vga.config.display_start >> 16) & 3 ) | + ((vga.s3.bank & 0x30) >> 2) | + ((vga.config.scan_len & 0x300) >> 4) | + vga.s3.reg_51; + case 0x55: /* Extended Video DAC Control */ + return vga.s3.reg_55; + case 0x58: /* Linear Address Window Control */ + return vga.s3.reg_58; + case 0x5D: /* Extended Horizontal Overflow */ + return vga.s3.ex_hor_overflow; + case 0x5e: /* Extended Vertical Overflow */ + return vga.s3.ex_ver_overflow; + case 0x69: /* Extended System Control 3 */ + return (Bit8u)((vga.config.display_start & 0x1f0000)>>16); + case 0x6a: /* Extended System Control 4 */ + return (Bit8u)(vga.s3.bank & 0x3f); default: - LOG(LOG_VGAMISC,"VGA:CRTC:Read from unknown index %X",crtc(index)); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:Read from unknown index %X",crtc(index)); } - return 0; + return 0x0; } diff --git a/src/hardware/vga_dac.cpp b/src/hardware/vga_dac.cpp index f03db34..b387d91 100644 --- a/src/hardware/vga_dac.cpp +++ b/src/hardware/vga_dac.cpp @@ -54,7 +54,7 @@ enum {DAC_READ,DAC_WRITE}; static void write_p3c6(Bit32u port,Bit8u val) { - if (val!=0xff) LOG(LOG_VGAGFX,"VGA:Pel Mask not 0xff"); + if (val!=0xff) LOG(LOG_VGAGFX,LOG_NORMAL)("VGA:Pel Mask not 0xff"); vga.dac.pel_mask=val; } @@ -68,6 +68,12 @@ static void write_p3c7(Bit32u port,Bit8u val) { vga.dac.read_index=val; vga.dac.pel_index=0; vga.dac.state=DAC_READ; + +} + +static Bit8u read_p3c7(Bit32u port) { + if (vga.dac.state==DAC_READ) return 0x3; + else return 0x0; } static void write_p3c8(Bit32u port,Bit8u val) { @@ -89,8 +95,8 @@ static void write_p3c9(Bit32u port,Bit8u val) { case 2: vga.dac.rgb[vga.dac.write_index].blue=val; switch (vga.mode) { - case GFX_256C: - case GFX_256U: + case M_VGA: + case M_LIN8: RENDER_SetPal(vga.dac.write_index, vga.dac.rgb[vga.dac.write_index].red << 2, vga.dac.rgb[vga.dac.write_index].green << 2, @@ -112,7 +118,7 @@ static void write_p3c9(Bit32u port,Bit8u val) { vga.dac.pel_index=0; break; default: - LOG(LOG_VGAGFX,"VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day + LOG(LOG_VGAGFX,LOG_NORMAL)("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day }; } @@ -133,7 +139,7 @@ static Bit8u read_p3c9(Bit32u port) { vga.dac.pel_index=0; break; default: - LOG(LOG_VGAMISC,"VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day } return ret; } @@ -141,12 +147,17 @@ static Bit8u read_p3c9(Bit32u port) { void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal) { /* Check if this is a new color */ vga.dac.attr[attr]=pal; - if (vga.mode != GFX_256U && vga.mode != GFX_256C) - RENDER_SetPal(attr, - vga.dac.rgb[pal].red << 2, - vga.dac.rgb[pal].green << 2, - vga.dac.rgb[pal].blue << 2 + switch (vga.mode) { + case M_VGA: + case M_LIN8: + break; + default: + RENDER_SetPal(attr, + vga.dac.rgb[pal].red << 2, + vga.dac.rgb[pal].green << 2, + vga.dac.rgb[pal].blue << 2 ); + } } void VGA_SetupDAC(void) { @@ -157,11 +168,11 @@ void VGA_SetupDAC(void) { vga.dac.state=DAC_READ; vga.dac.read_index=0; vga.dac.write_index=0; - /* Setup the DAC IO port Handlers */ IO_RegisterWriteHandler(0x3c6,write_p3c6,"PEL Mask"); IO_RegisterReadHandler(0x3c6,read_p3c6,"PEL Mask"); IO_RegisterWriteHandler(0x3c7,write_p3c7,"PEL Read Mode"); + IO_RegisterReadHandler(0x3c7,read_p3c7,"PEL Status Mode"); IO_RegisterWriteHandler(0x3c8,write_p3c8,"PEL Write Mode"); IO_RegisterWriteHandler(0x3c9,write_p3c9,"PEL Data"); IO_RegisterReadHandler(0x3c9,read_p3c9,"PEL Data"); diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 055cefd..cbdb01c 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -19,13 +19,15 @@ #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. -void VGA_DrawGFX2_Fast(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=HostMake(0xB800,0); - Bit8u * flip=HostMake(0xB800,8*1024); +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--) { + for (Bitu x=vga.draw.width>>3;x>0;x--) { Bit8u val=*(tempread++); *(draw+0)=(val>>7)&1; *(draw+1)=(val>>6)&1; @@ -52,9 +54,9 @@ void VGA_DrawGFX2_Fast(Bit8u * bitdata,Bitu pitch) { } } -void VGA_DrawGFX4_Fast(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=HostMake(0xB800,vga.config.display_start*2); - Bit8u * flip=HostMake(0xB800,8*1024); +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 (Bit32u x=0;x>2;x++) { + for (Bitu x=0;x>2;x++) { Bit8u val=*(tempread++); - *(Bit32u *)draw=CGAWriteTable[val]; + *(Bit32u *)draw=CGA_4_Table[val]; draw+=4; } bitdata+=pitch; } } -/* Draw the screen using the lookup buffer */ -void VGA_DrawGFX16_Fast(Bit8u * bitdata,Bitu next_line) { - Bit8u * reader=&vga.buffer[vga.config.display_start*8+vga.config.pel_panning]; - for (Bitu y=0;y>2;x++) { - for (Bit32u dx=0;dx<4;dx++) { - (*bitdata++)=vga.mem.paged[xreader][dx]; - } - xreader++; + 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; } - yreader+=vga.config.scan_len*2; - bitdata+=next_line; + bitdata+=pitch; + if ((y & 3)==3)reader+=160; } } -void VGA_DrawTEXT(Bit8u * bitdata,Bitu pitch) { - Bit8u * reader=HostMake(0xB800,0); + +void VGA_TEXT_Draw(Bit8u * bitdata,Bitu start,Bitu panning,Bitu rows) { + Bit8u * reader=&vga.mem.linear[start*2]; Bit8u * draw_start=bitdata; /* Todo Blinking and high intensity colors */ - for (Bitu cy=0;cy<(vga.draw.height/16);cy++) { + Bitu next_charline=vga.draw.font_height*vga.draw.width; + Bitu next_line=vga.draw.width; + Bitu next_start=(vga.config.scan_len*2)-vga.draw.cols; + for (Bitu cy=rows;cy>0;cy--) { Bit8u * draw_char=draw_start; - for (Bitu cx=0;cx<(vga.draw.width/8);cx++) { + /* Do first character keeping track of panning */ + { Bit8u c=*(reader++); - Bit8u * findex=&vga_rom_16[c*16]; + 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=0;y<16;y++) { + for (Bitu y=vga.draw.font_height;y>0;y--) { Bit8u bit_mask=*findex++; #include "font-switch.h" - draw+=pitch; - }; + draw+=next_line; + } draw_char+=8; - }; - draw_start+=16*pitch; - }; - if(!(vga.internal.cursor & 0x2000)) { - /* Draw a cursor */ - if (((Bitu)vga.draw.cursor.col*8)>=vga.draw.width) return; - if (((Bitu)vga.draw.cursor.row*16)>=vga.draw.height) return; - Bit8u * cursor_draw=bitdata+(vga.draw.cursor.row*16+15)*pitch+vga.draw.cursor.col*8; - if (vga.draw.cursor.count>8) { - for (Bit8u loop=0;loop<8;loop++) *cursor_draw++=15; } - vga.draw.cursor.count++; - if (vga.draw.cursor.count>16) vga.draw.cursor.count=0; - } -}; + /* 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; + } +/* 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; + } + } +} + +static void EndRetrace(void) { + /* start the actual display update now */ + RENDER_DoUpdate(); + vga.config.retrace=false; +} + +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; + vga.config.retrace=true; +} + + +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); + } +norender:; + } + +} + + +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 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 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; + /* 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); + + vga.draw.resizing=false; + Bitu width,height,pitch,flags; + + 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; + 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; + } + } + width<<=2; + pitch=vga.config.scan_len*8; + 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; + break; + case M_EGA16: + width<<=3; + pitch=vga.config.scan_len*16; + break; + case M_CGA4: + width<<=3; + pitch=width; + break; + case M_CGA2: + width<<=3; + pitch=width; + break; + case M_TANDY16: + width<<=3; + pitch=width; + break; + 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++; + width<<=3; /* 8 bit wide text font */ + if (width>640) width=640; + if (height>480) height=480; + pitch=width; + 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 */ + } + if (( width != vga.draw.width) || (height != vga.draw.height) || (pitch != vga.draw.pitch)) { + PIC_RemoveEvents(VGA_BlankTimer); + vga.draw.width=width; + vga.draw.height=height; + vga.draw.pitch=pitch; + + 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); + } +}; diff --git a/src/hardware/vga_fonts.cpp b/src/hardware/vga_fonts.cpp deleted file mode 100644 index f5e7564..0000000 --- a/src/hardware/vga_fonts.cpp +++ /dev/null @@ -1,1254 +0,0 @@ -/* - * Copyright (C) 2002-2003 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. - */ - -/* - * Bitmap fonts for the VGA emulation; taken from - * ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip - * - * See copyleft_vgafonts.txt for the copyright notice. - */ -#include "dosbox.h" -#include "mem.h" -#include "vga.h" - -Bit8u vga_rom_08[256 * 8] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, - 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, - 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, - 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, - 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, - 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, - 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, - 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, - 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, - 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, - 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, - 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, - 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, - 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, - 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, - 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, - 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, - 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, - 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, - 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, - 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, - 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, - 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, - 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, - 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, - 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, - 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, - 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, - 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, - 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, - 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, - 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, - 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, - 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, - 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, - 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, - 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, - 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, - 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, - 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, - 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, - 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, - 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, - 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, - 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, - 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, - 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, - 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, - 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, - 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, - 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, - 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, - 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, - 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, - 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, - 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, - 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, - 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, - 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, - 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, - 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, - 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, - 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, - 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, - 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, - 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, - 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, - 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, - 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, - 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, - 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, - 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, - 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, - 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, - 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, - 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, - 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, - 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, - 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, - 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, - 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, - 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, - 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, - 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, - 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, - 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, - 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, - 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, - 0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, - 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, - 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, - 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, - 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, - 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, - 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, - 0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, - 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, - 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, - 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, - 0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, - 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, - 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, - 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, - 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, - 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, - 0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00, - 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, - 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, - 0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, - 0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f, - 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03, - 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, - 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, - 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, - 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, - 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, - 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, - 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, - 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, - 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, - 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, - 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, - 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, - 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, - 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, - 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, - 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, - 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, - 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, - 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, - 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, - 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, - 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, - 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, - 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00, - 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, - 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, - 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, - 0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00, - 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, - 0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -Bit8u vga_rom_14[256 * 14] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, - 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, - 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, - 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, - 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, - 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, - 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, - 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, - 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, - 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, - 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, - 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, - 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x7c, - 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, - 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, - 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, - 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, - 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, - 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, - 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, - 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, - 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, - 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, - 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, - 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, - 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, - 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, - 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, - 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x60, - 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, - 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, - 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, - 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, - 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, - 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, - 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, - 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, - 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, - 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, - 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, - 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, - 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, - 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, - 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, - 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xe6, - 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, - 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, - 0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, - 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, - 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, - 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, - 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, - 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, - 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x3c, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, - 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, - 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, - 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, - 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, - 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, - 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, - 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, - 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, - 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, - 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, - 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, - 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, - 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, - 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, - 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, - 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, - 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, - 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, - 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, - 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, - 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, 0x00, - 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, - 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, - 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, - 0x76, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, - 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, - 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, - 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, - 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x10, - 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, - 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, - 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, - 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, - 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, - 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, - 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0xcc, - 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, - 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, 0x00, 0xc6, - 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, - 0x38, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x00, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, - 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, - 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, - 0x18, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, - 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, - 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, - 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x0c, - 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, - 0x3c, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, - 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x76, 0xdc, - 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, - 0xc6, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, - 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, - 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, - 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, - 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, - 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, - 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, - 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x55, 0xaa, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, - 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, - 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, - 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, - 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, - 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, - 0xc0, 0xc0, 0x40, 0x00, 0x00, 0x00, 0xfe, 0xc6, - 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, - 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, - 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, - 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, - 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, - 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, - 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, - 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, - 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, - 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, - 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, - 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, - 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, - 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, - 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -Bit8u vga_rom_16[256 * 16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, - 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, - 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, - 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, - 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, - 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, - 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, - 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, - 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, - 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, - 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, - 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, - 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, - 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, - 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, - 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, - 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, - 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, - 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, - 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, - 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, - 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, - 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, - 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, - 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, - 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, - 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, - 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, - 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, - 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, - 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, - 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, - 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, - 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, - 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, - 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, - 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, - 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, - 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, - 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, - 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, - 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, - 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, - 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, - 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, - 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, - 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, - 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, - 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, - 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, - 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, - 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, - 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, - 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, - 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, - 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, - 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, - 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, - 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, - 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, - 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, - 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, - 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, - 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, - 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, - 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, - 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, - 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, - 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, - 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, - 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, - 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, - 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, - 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, - 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, - 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, - 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, - 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, - 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, - 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, - 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, - 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, - 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, - 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, - 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, - 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, - 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, - 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, - 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, - 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, - 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, - 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, - 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, - 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, - 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, - 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, - 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, - 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, - 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, - 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, - 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00, - 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, - 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, - 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, - 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, - 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, - 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, - 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, - 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, - 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, - 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, - 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, - 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, - 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, - 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, - 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, - 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, - 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, - 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, - 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, - 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, - 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, - 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, - 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, - 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, - 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, - 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, - 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - - diff --git a/src/hardware/vga_gfx.cpp b/src/hardware/vga_gfx.cpp index 89fdf02..8304651 100644 --- a/src/hardware/vga_gfx.cpp +++ b/src/hardware/vga_gfx.cpp @@ -56,6 +56,8 @@ void write_p3cf(Bit32u port,Bit8u val) { vga.config.full_not_enable_set_reset=~vga.config.full_enable_set_reset; vga.config.full_enable_and_set_reset=vga.config.full_set_reset & vga.config.full_enable_set_reset; +// if (gfx(enable_set_reset)) vga.config.mh_mask|=MH_SETRESET else vga.config.mh_mask&=~MH_SETRESET; + break; case 2: /* Color Compare Register */ gfx(color_compare)=val & 0x0f; /* @@ -70,7 +72,7 @@ void write_p3cf(Bit32u port,Bit8u val) { case 3: /* Data Rotate */ gfx(data_rotate)=val; vga.config.data_rotate=val & 7; - if (vga.config.data_rotate) LOG(LOG_VGAGFX,"VGA:Data Rotate used %d",val &7); +// if (val) vga.config.mh_mask|=MH_ROTATEOP else vga.config.mh_mask&=~MH_ROTATEOP; vga.config.raster_op=(val>>3) & 3; /* 0-2 Number of positions to rotate data right before it is written to @@ -83,7 +85,6 @@ void write_p3cf(Bit32u port,Bit8u val) { 2: CPU data is ORed with the latch data. 3: CPU data is XORed with the latched data. */ -// if (vga.config.data_rotate || vga.config.raster_op ) LOG_DEBUG("Data Rotate = %2X Raster op %2X",val & 7,(val>>3) & 3 ); break; case 4: /* Read Map Select Register */ /* 0-1 number of the plane Read Mode 0 will read from */ @@ -138,6 +139,7 @@ void write_p3cf(Bit32u port,Bit8u val) { break; case 6: /* Miscellaneous Register */ gfx(miscellaneous)=val; + VGA_SetupHandlers(); /* 0 Indicates Graphics Mode if set, Alphanumeric mode else. 1 Enables Odd/Even mode if set. @@ -171,18 +173,18 @@ void write_p3cf(Bit32u port,Bit8u val) { case 9: /* Unknown */ /* Crystal Dreams seems to like to write tothis register very weird */ if (!index9warned) { - LOG(LOG_VGAMISC,"VGA:3CF:Write %2X to illegal index 9",val); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index 9",val); index9warned=true; } break; default: - LOG(LOG_VGAMISC,"VGA:3CF:Write %2X to illegal index %2X",val,gfx(index)); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:3CF:Write %2X to illegal index %2X",val,gfx(index)); break; } } Bit8u read_p3cf(Bit32u port) { -switch (gfx(index)) { + switch (gfx(index)) { case 0: /* Set/Reset Register */ return gfx(set_reset); case 1: /* Enable Set/Reset Register */ @@ -202,7 +204,7 @@ switch (gfx(index)) { case 8: /* Bit Mask Register */ return gfx(bit_mask); default: - LOG(LOG_VGAMISC,"Reading from illegal index %2X in port %4X",gfx(index),port); + LOG(LOG_VGAMISC,LOG_NORMAL)("Reading from illegal index %2X in port %4X",static_cast(gfx(index)),port); } return 0; /* Compiler happy */ } diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 693d4a3..23e43b4 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -24,19 +24,10 @@ #include "dosbox.h" #include "mem.h" #include "vga.h" +#include "paging.h" +#include "pic.h" - -Bit8u VGA_ChainedReadHandler(Bit32u start) { - return vga.mem.linear[start]; -} - -void VGA_ChainedWriteHandler(Bit32u start,Bit8u val) { - vga.mem.linear[start]=val; -}; - - -Bit8u VGA_NormalReadHandler(PhysPt start) { - start-=0xa0000; +static Bit8u VGA_NormalReadHandler(PhysPt start) { vga.latch.d=vga.mem.latched[start].d; switch (vga.config.read_mode) { case 0: @@ -50,6 +41,7 @@ Bit8u VGA_NormalReadHandler(PhysPt start) { } //Nice one from DosEmu + INLINE static Bit32u RasterOp(Bit32u input,Bit32u mask) { switch (vga.config.raster_op) { case 0x00: /* None */ @@ -86,31 +78,13 @@ INLINE static Bit32u ModeOperation(Bit8u val) { full=RasterOp(vga.config.full_set_reset,ExpandTable[val] & vga.config.full_bit_mask); break; default: - LOG(LOG_VGAMISC,"VGA:Unsupported write mode %d",vga.config.write_mode); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:Unsupported write mode %d",vga.config.write_mode); } return full; } -Bit8u VGA_GFX_4_ReadHandler(Bit32u start) { - return vga.mem.linear[start-0xb8000]; -} - -void VGA_GFX_4_WriteHandler(Bit32u start,Bit8u val) { - start-=0xb8000; - vga.mem.linear[start]=val; - Bitu off; - if (start>0x2000) off=320*(((start-0x2000)/80)*2+1)+((start-0x2000) % 80)*4; - else off=320*(((start)/80)*2)+(start % 80)*4; - Bit32u * draw=(Bit32u *)&vga.buffer[off]; - /* TODO Could also use a Bit32u lookup table for this */ - *draw=CGAWriteTable[val]; - draw=(Bit32u *)&vga.buffer[off+0x4000*4]; - *draw=CGAWriteTable[val]; - -} - -void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val) { - start-=0xa0000; +static void VGA_GFX_16_WriteHandler(PhysPt start,Bit8u val) { + 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; @@ -118,7 +92,7 @@ void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val) { pixels.d&=vga.config.full_not_map_mask; pixels.d|=(data & vga.config.full_map_mask); vga.mem.latched[start].d=pixels.d; - Bit8u * write_pixels=&vga.buffer[start<<3]; + Bit8u * write_pixels=&vga.mem.linear[512*1024+(start<<3)]; Bit32u colors0_3, colors4_7; VGA_Latch temp;temp.d=(pixels.d>>4) & 0x0f0f0f0f; @@ -140,36 +114,102 @@ void VGA_GFX_16_WriteHandler(Bit32u start,Bit8u val) { } -void VGA_GFX_256U_WriteHandler(Bit32u start,Bit8u val) { - start-=0xa0000; +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; pixels.d|=(data & vga.config.full_map_mask); vga.mem.latched[start].d=pixels.d; 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 +} +static Bit8u VGA_TEXT16_Read(PhysPt start) { + return vga.draw.font[start]; +} +void VGA_SetupHandlers(void) { + HostPt where; + switch (vga.mode) { + case M_LIN8: + where=&vga.mem.linear[vga.s3.bank*64*1024]; + break; + case M_VGA: + if (vga.config.chained) { + where=&vga.mem.linear[vga.s3.bank*64*1024]; + } else { + vga.config.readhandler=&VGA_NormalReadHandler, + vga.config.writehandler=&VGA_GFX_256U_WriteHandler; + where=0; + } + break; + case M_EGA16: + vga.config.readhandler=&VGA_NormalReadHandler, + vga.config.writehandler=&VGA_GFX_16_WriteHandler; + where=0; + break; + case M_TEXT16: + /* Check if we're not in odd/even mode */ + if (vga.gfx.miscellaneous & 0x2) { + where=&vga.mem.linear[0]; + } else { + vga.config.readhandler=&VGA_TEXT16_Read; + vga.config.writehandler=&VGA_TEXT16_Write; + where=0; + } + break; + case M_TANDY16: + where=&vga.mem.linear[vga.tandy.mem_bank << 14]; + break; + case M_CGA4: + case M_CGA2: + where=&vga.mem.linear[0]; + break; + default: + LOG_MSG("Unhandled vga mode %X",vga.mode); + } + VGA_RANGES range; + switch ((vga.gfx.miscellaneous >> 2) & 3) { + case 0: + case 1: + range=VGA_RANGE_A000; + break; + case 2: + range=VGA_RANGE_B000; + break; + case 3: + range=VGA_RANGE_B800; + break; + } + MEM_SetupVGA(range,where); +} +bool lfb_update; +static void VGA_DoUpdateLFB(void) { + lfb_update=false; + MEM_SetLFB(vga.s3.la_window << 4 ,sizeof(vga.mem.linear)/4096,&vga.mem.linear[0]); +} +void VGA_StartUpdateLFB(void) { + if (!lfb_update) { + lfb_update=true; + PIC_AddEvent(VGA_DoUpdateLFB,100); //100 microseconds later + } +} void VGA_SetupMemory() { - memset((void *)&vga.mem,0,256*1024); - /* Alocate Video Memory */ - /* Not needed for VGA memory it gets allocated together with emulator maybe - later for VESA memory */ - + 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 1f4fcf4..6bb0188 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -22,9 +22,6 @@ #include "vga.h" static Bit8u flip=0; -static Bit32u keep_vretrace; -static bool keeping=false; -static Bit8u p3c2data=0; void write_p3d4(Bit32u port,Bit8u val); Bit8u read_p3d4(Bit32u port); @@ -48,16 +45,95 @@ static Bit8u read_p3da(Bit32u port) { static void write_p3d8(Bit32u port,Bit8u val) { - LOG(LOG_VGAMISC,"Write %2X to 3da",val); + switch (vga.mode) { + case M_CGA4: + + break; + default: + break; + } + 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. */ } -static void write_p3c2(Bit32u port,Bit8u val) { - p3c2data=val; +static void write_p3d9(Bit32u port,Bit8u 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]); + 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); + } + 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. + */ + 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) { + switch (vga.mode) { + case M_TANDY16: + 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. + 0: 0K, 1: 16K...7: 112K. In 32K modes (bits 6-7 = 2) only 0,2,4 and + 6 are valid, as the next page will also be used. + 3-5 Identifies the page of main memory that can be read/written at B8000h + in units of 16K. 0: 0K, 1: 16K...7: 112K. In 32K modes (bits 6-7 = 2) + only 0,2,4 and 6 are valid, as the next page will also be used. + 6-7 Display mode. 0: Text, 1: 16K graphics mode (4,5,6,8) + 2: 32K graphics mode (9,Ah) + */ + default: + LOG(LOG_VGAMISC,LOG_NORMAL)("Unhandled Write %2X to %X in mode %d",val,port,vga.mode); + break; + } +} + +static Bit8u read_p3d9(Bit32u port) { + switch (vga.mode) { + case M_CGA2: + case M_CGA4: + 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"); @@ -77,11 +153,6 @@ static void write_p3c2(Bit32u port,Bit8u val) { IO_FreeWriteHandler(0x3d5); IO_FreeReadHandler(0x3d5); } - if (val & 0x4) vga.config.clock=28322000; - else vga.config.clock=25175000; - - VGA_StartResize(); - /* 0 If set Color Emulation. Base Address=3Dxh else Mono Emulation. Base Address=3Bxh. 2-3 Clock Select. 0: 25MHz, 1: 28MHz @@ -97,7 +168,7 @@ static void write_p3c2(Bit32u port,Bit8u val) { static Bit8u read_p3cc(Bit32u port) { - return p3c2data; + return vga.misc_output; } void VGA_SetupMisc(void) { @@ -105,8 +176,17 @@ void VGA_SetupMisc(void) { IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1"); 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_RegisterReadHandler(0x3cc,read_p3cc,"VGA Misc Output"); + IO_RegisterWriteHandler(0x3df,write_p3df,"PCJR Setting"); + } diff --git a/src/hardware/vga_seq.cpp b/src/hardware/vga_seq.cpp index 2fdaa17..4433f76 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.cpp @@ -31,6 +31,8 @@ void write_p3c4(Bit32u port,Bit8u val) { }; void write_p3c5(Bit32u port,Bit8u val) { + if (seq(index)>0x8 && vga.s3.pll.lock!=0x6) return; +// LOG_MSG("SEQ WRITE reg %X val %X",seq(index),val); switch(seq(index)) { case 0: /* Reset */ seq(reset)=val; @@ -65,7 +67,13 @@ void write_p3c5(Bit32u port,Bit8u val) { */ break; case 3: /* Character Map Select */ - seq(character_map_select)=val; + { + seq(character_map_select)=val; + Bit8u font1=(val & 0x3) | ((val & 0x10) >> 2); + vga.draw.font1_start=((font1&3) * 16*1024) + ((font1 > 4) ? (8*1024) : 0); + Bit8u font2=((val & 0xc) >> 2) | ((val & 0x20) >> 3); + vga.draw.font2_start=((font2&3) * 16*1024) + ((font2 > 4) ? (8*1024) : 0); + } /* 0,1,4 Selects VGA Character Map (0..7) if bit 3 of the character attribute is clear. @@ -88,32 +96,71 @@ void write_p3c5(Bit32u port,Bit8u val) { /* Changing this means changing the VGA Memory Read/Write Handler */ if (val&0x08) vga.config.chained=true; else vga.config.chained=false; - VGA_FindSettings(); + VGA_SetupHandlers(); break; +/* S3 specific group */ + case 0x08: + vga.s3.pll.lock=val; + break; + case 0x10: /* Memory PLL Data Low */ + vga.s3.mclk.n=val & 0x1f; + vga.s3.mclk.r=val >> 5; + break; + case 0x11: /* Memory PLL Data High */ + vga.s3.mclk.m=val & 0x7f; + break; + case 0x12: /* Video PLL Data Low */ + vga.s3.clk[3].n=val & 0x1f; + vga.s3.clk[3].r=val >> 5; + break; + case 0x13: /* Video PLL Data High */ + vga.s3.clk[3].m=val & 0x7f; + break; + case 0x15: + vga.s3.pll.cmd=val; + VGA_StartResize(); + break; + default: - LOG(LOG_VGAMISC,"VGA:SEQ:Write to illegal index %2X",seq(index)); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:Write to illegal index %2X",seq(index)); }; }; Bit8u read_p3c5(Bit32u port) { +// LOG_MSG("VGA:SEQ:Read from index %2X",seq(index)); + if (seq(index)>0x8 && vga.s3.pll.lock!=0x6) return seq(index); switch(seq(index)) { - case 0: /* Reset */ + case 0: /* Reset */ return seq(reset); break; - case 1: /* Clocking Mode */ + case 1: /* Clocking Mode */ return seq(clocking_mode); break; - case 2: /* Map Mask */ + case 2: /* Map Mask */ return seq(map_mask); break; - case 3: /* Character Map Select */ + case 3: /* Character Map Select */ return seq(character_map_select); break; - case 4: /* Memory Mode */ + case 4: /* Memory Mode */ return seq(memory_mode); + /* S3 specific group */ + case 0x08: /* PLL Unlock */ + return vga.s3.pll.lock; + case 0x10: /* Memory PLL Data Low */ + return vga.s3.mclk.n || (vga.s3.mclk.r << 5); + case 0x11: /* Memory PLL Data High */ + return vga.s3.mclk.m; + case 0x12: /* Video PLL Data Low */ + return vga.s3.clk[3].n || (vga.s3.clk[3].r << 5); + case 0x13: /* Video Data High */ + return vga.s3.clk[3].m; + case 0x15: + return vga.s3.pll.cmd; + default: - LOG(LOG_VGAMISC,"VGA:SEQ:Read from illegal index %2X",seq(index)); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:Read from illegal index %2X",seq(index)); }; return 0; }; diff --git a/src/ints/Makefile.am b/src/ints/Makefile.am index f5a095e..e1ffaba 100644 --- a/src/ints/Makefile.am +++ b/src/ints/Makefile.am @@ -1,6 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libints.a -libints_a_SOURCES = mouse.cpp xms.cpp ems.cpp \ - int10.cpp int10.h int10_char.cpp int10_memory.cpp int10_misc.cpp int10_modes.cpp int10_pal.cpp int10_put_pixel.cpp \ +libints_a_SOURCES = mouse.cpp xms.cpp xms.h ems.cpp dpmi.cpp \ + int10.cpp int10.h int10_char.cpp int10_memory.cpp int10_misc.cpp int10_modes.cpp \ + int10_vesa.cpp int10_pal.cpp int10_put_pixel.cpp \ bios.cpp bios_disk.cpp bios_keyboard.cpp diff --git a/src/ints/Makefile.in b/src/ints/Makefile.in index f5dd55a..6e1fd36 100644 --- a/src/ints/Makefile.in +++ b/src/ints/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,85 +13,132 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libints.a -libints_a_SOURCES = mouse.cpp xms.cpp ems.cpp \ - int10.cpp int10.h int10_char.cpp int10_memory.cpp int10_misc.cpp int10_modes.cpp int10_pal.cpp int10_put_pixel.cpp \ +libints_a_SOURCES = mouse.cpp xms.cpp xms.h ems.cpp dpmi.cpp \ + int10.cpp int10.h int10_char.cpp int10_memory.cpp int10_misc.cpp int10_modes.cpp \ + int10_vesa.cpp int10_pal.cpp int10_put_pixel.cpp \ bios.cpp bios_disk.cpp bios_keyboard.cpp subdir = src/ints +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -100,40 +147,37 @@ LIBRARIES = $(noinst_LIBRARIES) libints_a_AR = $(AR) cru libints_a_LIBADD = am_libints_a_OBJECTS = mouse.$(OBJEXT) xms.$(OBJEXT) ems.$(OBJEXT) \ - int10.$(OBJEXT) int10_char.$(OBJEXT) int10_memory.$(OBJEXT) \ - int10_misc.$(OBJEXT) int10_modes.$(OBJEXT) int10_pal.$(OBJEXT) \ + dpmi.$(OBJEXT) int10.$(OBJEXT) int10_char.$(OBJEXT) \ + int10_memory.$(OBJEXT) int10_misc.$(OBJEXT) \ + int10_modes.$(OBJEXT) int10_vesa.$(OBJEXT) int10_pal.$(OBJEXT) \ int10_put_pixel.$(OBJEXT) bios.$(OBJEXT) bios_disk.$(OBJEXT) \ bios_keyboard.$(OBJEXT) libints_a_OBJECTS = $(am_libints_a_OBJECTS) -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/bios.Po ./$(DEPDIR)/bios_disk.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/bios_keyboard.Po ./$(DEPDIR)/ems.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/int10.Po ./$(DEPDIR)/int10_char.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/bios_keyboard.Po ./$(DEPDIR)/dpmi.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/ems.Po ./$(DEPDIR)/int10.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/int10_char.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/int10_memory.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/int10_misc.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/int10_modes.Po ./$(DEPDIR)/int10_pal.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/int10_put_pixel.Po ./$(DEPDIR)/mouse.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/int10_put_pixel.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/int10_vesa.Po ./$(DEPDIR)/mouse.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/xms.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ -CFLAGS = @CFLAGS@ 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 = $(libints_a_SOURCES) -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libints_a_SOURCES) all: all-am @@ -164,6 +208,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios_disk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bios_keyboard.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dpmi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ems.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_char.Po@am__quote@ @@ -172,29 +217,39 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_modes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_pal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_put_pixel.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/int10_vesa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mouse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xms.Po@am__quote@ -distclean-depend: - -rm -rf ./$(DEPDIR) - .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -220,20 +275,41 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -258,7 +334,6 @@ check: check-am all-am: Makefile $(LIBRARIES) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -278,7 +353,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -288,9 +363,11 @@ clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am @@ -311,6 +388,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -318,18 +397,25 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags distdir dvi \ - dvi-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index 5f5fa25..b1e4fef 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -15,6 +15,9 @@ * along with this program; if not, write to the Free Software * 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 $ */ + #include #include "dosbox.h" #include "bios.h" @@ -26,7 +29,30 @@ #include "joystick.h" static Bitu call_int1a,call_int11,call_int8,call_int17,call_int12,call_int15,call_int1c; -static Bitu call_int1; +static Bitu call_int1,call_int70; + +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); + if (count>997) { + mem_writed(BIOS_WAIT_FLAG_COUNT,count-997); + } else { + mem_writed(BIOS_WAIT_FLAG_COUNT,0); + PhysPt where=Real2Phys(mem_readd(BIOS_WAIT_FLAG_POINTER)); + mem_writeb(where,mem_readb(where)|0x80); + mem_writeb(BIOS_WAIT_FLAG_ACTIVE,0); + IO_Write(0x70,0xb); + IO_Write(0x71,IO_Read(0x71)&~0x40); + } + } + /* Signal EOI to both pics */ + IO_Write(0xa0,0x20); + IO_Write(0x20,0x20); + return 0; +} static Bitu INT1A_Handler(void) { switch (reg_ah) { @@ -42,20 +68,25 @@ static Bitu INT1A_Handler(void) { mem_writed(BIOS_TIMER,(reg_cx<<16)|reg_dx); break; case 0x02: /* GET REAL-TIME CLOCK TIME (AT,XT286,PS) */ - reg_dx=reg_cx=0; + IO_Write(0x70,0x04); //Hours + reg_ch=IO_Read(0x71); + IO_Write(0x70,0x02); //Minutes + reg_cl=IO_Read(0x71); + IO_Write(0x70,0x00); //Seconds + reg_dh=IO_Read(0x71); + reg_dl=0; //Daylight saving disabled CALLBACK_SCF(false); - LOG(LOG_BIOS,"INT1A:02:Faked RTC get time call"); break; case 0x04: /* GET REAL-TIME ClOCK DATA (AT,XT286,PS) */ reg_dx=reg_cx=0; CALLBACK_SCF(false); - LOG(LOG_ERROR|LOG_BIOS,"INT1A:04:Faked RTC get date call"); + LOG(LOG_BIOS,LOG_ERROR)("INT1A:04:Faked RTC get date call"); break; case 0x80: /* Pcjr Setup Sound Multiplexer */ - LOG(LOG_ERROR|LOG_BIOS,"INT1A:80:Setup tandy sound multiplexer to %d",reg_al); + LOG(LOG_BIOS,LOG_ERROR)("INT1A:80:Setup tandy sound multiplexer to %d",reg_al); break; case 0x81: /* Tandy sound system checks */ - LOG(LOG_ERROR|LOG_BIOS,"INT1A:81:Tandy DAC Check failing"); + LOG(LOG_BIOS,LOG_ERROR)("INT1A:81:Tandy DAC Check failing"); break; /* INT 1A - Tandy 2500, Tandy 1000L series - DIGITAL SOUND - INSTALLATION CHECK @@ -66,38 +97,19 @@ static Bitu INT1A_Handler(void) { CF clear if sound chip is free Note: the value of CF is not definitive; call this function until CF is clear on return, then call AH=84h"Tandy" -*/ + */ + case 0xb1: /* PCI Bios Calls */ + LOG(LOG_BIOS,LOG_ERROR)("INT1A:PCI bios call %2X",reg_al); + CALLBACK_SCF(true); + break; default: - LOG(LOG_ERROR|LOG_BIOS,"INT1A:Undefined call %2X",reg_ah); + LOG(LOG_BIOS,LOG_ERROR)("INT1A:Undefined call %2X",reg_ah); } return CBRET_NONE; } static Bitu INT11_Handler(void) { - /* - AX = BIOS equipment list word - bits - 0 floppy disk(s) installed (see bits 6-7) - 1 80x87 coprocessor installed - 2,3 number of 16K banks of RAM on motherboard (PC only) - number of 64K banks of RAM on motherboard (XT only) - 2 pointing device installed (PS) - 3 unused (PS) - 4-5 initial video mode - 00 EGA, VGA, or PGA - 01 40x25 color - 10 80x25 color - 11 80x25 monochrome - 6-7 number of floppies installed less 1 (if bit 0 set) - 8 DMA support installed (PCjr, some Tandy 1000s, 1400LT) - 9-11 number of serial ports installed - 12 game port installed - 13 serial printer attached (PCjr) - internal modem installed (PC/Convertible) - 14-15 number of parallel ports installed - */ - reg_ax=0x104D; - LOG(LOG_BIOS,"INT11:Equipment list returned %X",reg_ax); + reg_ax=mem_readw(BIOS_CONFIGURATION); return CBRET_NONE; } @@ -133,7 +145,7 @@ static Bitu INT12_Handler(void) { }; static Bitu INT17_Handler(void) { - LOG(LOG_BIOS,"INT17:Function %X",reg_ah); + LOG(LOG_BIOS,LOG_NORMAL)("INT17:Function %X",reg_ah); switch(reg_ah) { case 0x00: /* PRINTER: Write Character */ reg_ah=1; /* Report a timeout */ @@ -143,25 +155,23 @@ static Bitu INT17_Handler(void) { case 0x02: /* PRINTER: Get Status */ reg_ah=0; break; + case 0x20: /* Some sort of printerdriver install check*/ + break; default: E_Exit("Unhandled INT 17 call %2X",reg_ah); + }; return CBRET_NONE; } -static void WaitFlagEvent(void) { - PhysPt where=Real2Phys(mem_readd(BIOS_WAIT_FLAG_POINTER)); - mem_writeb(where,mem_readb(where)|0x80); - mem_writeb(BIOS_WAIT_FLAG_ACTIVE,0); -} static Bitu INT15_Handler(void) { switch (reg_ah) { case 0x06: - LOG(LOG_BIOS,"INT15 Unkown Function 6"); + LOG(LOG_BIOS,LOG_NORMAL)("INT15 Unkown Function 6"); break; case 0xC0: /* Get Configuration*/ - LOG(LOG_ERROR|LOG_BIOS,"Request BIOS Configuration INT 15 C0"); + LOG(LOG_BIOS,LOG_ERROR)("Request BIOS Configuration INT 15 C0"); CALLBACK_SCF(true); break; case 0x4f: /* BIOS - Keyboard intercept */ @@ -169,11 +179,21 @@ static Bitu INT15_Handler(void) { CALLBACK_SCF(true); break; case 0x83: /* BIOS - SET EVENT WAIT INTERVAL */ - mem_writed(BIOS_WAIT_FLAG_POINTER,RealMake(SegValue(es),reg_bx)); - mem_writed(BIOS_WAIT_FLAG_COUNT,reg_cx<<16|reg_dx); - mem_writeb(BIOS_WAIT_FLAG_ACTIVE,1); - PIC_RemoveEvents(&WaitFlagEvent); - PIC_AddEvent(&WaitFlagEvent,reg_cx<<16|reg_dx); + { + if (mem_readb(BIOS_WAIT_FLAG_ACTIVE)) { + reg_ah=0x80; + CALLBACK_SCF(true); + break; + } + Bit32u count=(reg_cx<<16)|reg_dx; + mem_writed(BIOS_WAIT_FLAG_POINTER,RealMake(SegValue(es),reg_bx)); + mem_writed(BIOS_WAIT_FLAG_COUNT,count); + mem_writeb(BIOS_WAIT_FLAG_ACTIVE,1); + /* Reprogram RTC to start */ + IO_Write(0x70,0xb); + IO_Write(0x71,IO_Read(0x71)|0x40); + CALLBACK_SCF(false); + } break; case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */ if (reg_dx==0x0000) { @@ -199,7 +219,7 @@ static Bitu INT15_Handler(void) { CALLBACK_SCF(true); } } else { - LOG(LOG_ERROR|LOG_BIOS,"INT15:84:Unknown Bios Joystick functionality."); + LOG(LOG_BIOS,LOG_ERROR)("INT15:84:Unknown Bios Joystick functionality."); } break; case 0x86: /* BIOS - WAIT (AT,PS) */ @@ -208,8 +228,26 @@ static Bitu INT15_Handler(void) { Bit32u micro=(reg_cx<<16)|reg_dx; CALLBACK_SCF(false); } + case 0x87: /* Copy extended memory */ + { + bool enabled = MEM_A20_Enabled(); + MEM_A20_Enable(true); + Bitu bytes = reg_cx * 2; + PhysPt data = SegPhys(es)+reg_si; + PhysPt source = mem_readd(data+0x12) & 0x00FFFFFF + (mem_readb(data+0x16)<<24); + PhysPt dest = mem_readd(data+0x1A) & 0x00FFFFFF + (mem_readb(data+0x1E)<<24); + MEM_BlockCopy(dest,source,bytes); + reg_ax = 0x00; + MEM_A20_Enable(enabled); + CALLBACK_SCF(false); + break; + } case 0x88: /* SYSTEM - GET EXTENDED MEMORY SIZE (286+) */ - reg_ax=0; + IO_Write(0x70,0x30); + reg_al=IO_Read(0x71); + IO_Write(0x70,0x31); + reg_ah=IO_Read(0x71); + LOG(LOG_BIOS,LOG_NORMAL)("INT15:Function 0x88 Remaining %04X kb",reg_ax); CALLBACK_SCF(false); break; case 0x90: /* OS HOOK - DEVICE BUSY */ @@ -226,11 +264,11 @@ static Bitu INT15_Handler(void) { Damn programs should use the mouse drivers So let's fail these calls */ - LOG(LOG_BIOS,"INT15:Function %X called,bios mouse not supported",reg_ah); + LOG(LOG_BIOS,LOG_NORMAL)("INT15:Function %X called,bios mouse not supported",reg_ah); CALLBACK_SCF(true); break; default: - LOG(LOG_ERROR|LOG_BIOS,"INT15:Unknown call %2X",reg_ah); + LOG(LOG_BIOS,LOG_ERROR)("INT15:Unknown call %4X",reg_ax); reg_ah=0x86; CALLBACK_SCF(false); } @@ -241,7 +279,7 @@ static Bitu INT1_Single_Step(void) { static bool warned=false; if (!warned) { warned=true; - LOG(LOG_CPU,"INT 1:Single Step called"); + LOG(LOG_CPU,LOG_NORMAL)("INT 1:Single Step called"); } return CBRET_NONE; } @@ -292,14 +330,29 @@ void BIOS_Init(Section* sec) { call_int1c=CALLBACK_Allocate(); CALLBACK_Setup(call_int1c,&INT1C_Handler,CB_IRET); RealSetVec(0x1C,CALLBACK_RealPointer(call_int1c)); + /* IRQ 8 RTC Handler */ + call_int70=CALLBACK_Allocate(); + CALLBACK_Setup(call_int70,&INT70_Handler,CB_IRET); + RealSetVec(0x70,CALLBACK_RealPointer(call_int70)); /* Some defeault CPU error interrupt handlers */ call_int1=CALLBACK_Allocate(); CALLBACK_Setup(call_int1,&INT1_Single_Step,CB_IRET); RealSetVec(0x1,CALLBACK_RealPointer(call_int1)); - /* Test for some hardware */ - if (IO_Read(0x378)!=0xff) real_writed(0x40,0x08,0x378); + /* Setup some stuff in 0x40 bios segment */ + /* Test for parallel port */ + if (IO_Read(0x378)!=0xff) real_writew(0x40,0x08,0x378); + /* Test for serial port */ + Bitu index=0; + if (IO_Read(0x3f8)!=0xff) real_writew(0x40,(index++)*2,0x3f8); + if (IO_Read(0x2f8)!=0xff) real_writew(0x40,(index++)*2,0x2f8); + /* Setup equipment list */ +#if (C_FPU) + mem_writew(BIOS_CONFIGURATION,0xc823); //1 Floppy,FPU,2 serial, 1 parallel +#else + mem_writew(BIOS_CONFIGURATION,0xc821); //1 Floppy,FPU,2 serial, 1 parallel +#endif } diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index 298ad39..afbe92c 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.cpp @@ -34,10 +34,10 @@ static Bitu INT13_SmallHandler(void) { case 0x0: reg_ah=0x00; CALLBACK_SCF(false); - LOG(LOG_BIOS,"reset disk return succesfull"); + LOG(LOG_BIOS,LOG_NORMAL)("reset disk return succesfull"); break; case 0x02: /* Read Disk Sectors */ - LOG(LOG_BIOS,"INT13:02:Read Disk Sectors not supported failing"); + LOG(LOG_BIOS,LOG_NORMAL)("INT13:02:Read Disk Sectors not supported failing"); reg_ah=0x80; CALLBACK_SCF(true); break; @@ -50,17 +50,17 @@ static Bitu INT13_SmallHandler(void) { reg_ah=0x80; CALLBACK_SCF(true); } - LOG(LOG_BIOS,"INT 13:04 Verify sector used on %d, with result %d",reg_dl,reg_ah); + LOG(LOG_BIOS,LOG_NORMAL)("INT 13:04 Verify sector used on %d, with result %d",reg_dl,reg_ah); break; case 0x08: /* Get Drive Parameters */ - LOG(LOG_BIOS,"INT13:08:Get Drive parameters not supported failing"); + LOG(LOG_BIOS,LOG_NORMAL)("INT13:08:Get Drive parameters not supported failing"); reg_ah=0xff; CALLBACK_SCF(true); break; case 0xff: default: - LOG(LOG_ERROR|LOG_BIOS,"Illegal int 13h call %2X Fail it",reg_ah); + LOG(LOG_BIOS,LOG_ERROR)("Illegal int 13h call %2X Fail it",reg_ah); reg_ah=0xff; CALLBACK_SCF(true); } diff --git a/src/ints/bios_keyboard.cpp b/src/ints/bios_keyboard.cpp index f84a9b5..80de081 100644 --- a/src/ints/bios_keyboard.cpp +++ b/src/ints/bios_keyboard.cpp @@ -322,7 +322,7 @@ static Bitu INT16_Handler(void) { reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); break; case 0x03: /* SET TYPEMATIC RATE AND DELAY */ - LOG(LOG_ERROR|LOG_BIOS,"INT16:Unhandled Typematic Rate Call %2X",reg_al); + LOG(LOG_BIOS,LOG_ERROR)("INT16:Unhandled Typematic Rate Call %2X",reg_al); break; case 0x05: /* STORE KEYSTROKE IN KEYBOARD BUFFER */ //TODO make add_key bool :) @@ -335,10 +335,10 @@ static Bitu INT16_Handler(void) { break; case 0x55: /* Weird call used by some dos apps */ - LOG(LOG_BIOS,"INT16:55:Word TSR compatible call"); + LOG(LOG_BIOS,LOG_NORMAL)("INT16:55:Word TSR compatible call"); break; default: - LOG(LOG_ERROR|LOG_BIOS,"INT16:Unhandled call %02X",reg_ah); + LOG(LOG_BIOS,LOG_ERROR)("INT16:Unhandled call %02X",reg_ah); break; }; diff --git a/src/ints/dpmi.cpp b/src/ints/dpmi.cpp new file mode 100644 index 0000000..1f6f869 --- /dev/null +++ b/src/ints/dpmi.cpp @@ -0,0 +1,3175 @@ +/* + * Copyright (C) 2002-2003 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. + */ + +// Pharlap Special Infos: +// - Dont hook hardware ints +// - CMOS Memory Size has to return 0 otherwise it tries to map physical memory +// - Set PM Int Vector : Use it on current idt, not only dpmi one (ultima 8 mouse check fails otherwise) +// - Ultima 8 wants 40 Files (Hack in PSP::SetNumFiles +// - Ultima 8 and Bioforge work with DPL 3 +// - Crusaders 1+2 seem to need DPL 0, which is bad... +// - Bioforge uses more than 2048 descriptos in ldt (4096) + +#include +#include +#include +#include "dosbox.h" +#include "dos_inc.h" +#include "callback.h" +#include "mem.h" +#include "regs.h" +#include "dos_system.h" +#include "setup.h" +#include "inout.h" +#include "cpu.h" + +#include "debug.h" + +//#define DPMI_LOG LOG(LOG_MISC,LOG_ERROR) +#define DPMI_LOG + +#define DPMI_LOG_ERROR LOG(LOG_MISC,LOG_ERROR) +//#define DPMI_LOG_ERROR + +#define DPMI_ALLOC_NEEDEDMEM_HIGH 1 + +#define DPMI_DPL 3 + +#define GDT_ZERO 0 +#define GDT_LDT ((0x1 << 3) | DPMI_DPL) +#define GDT_CODE ((0x2 << 3) | DPMI_DPL) +#define GDT_PROTCODE ((0x3 << 3) | DPMI_DPL) +#define GDT_DOSDATA ((0x4 << 3) | DPMI_DPL) +#define GDT_ENVIRONMENT ((0x5 << 3) | DPMI_DPL) + +#define GDT_DOSSEG40 (0x40) + +/* Amount of descriptors in each table */ +#define GDT_SIZE 32 +#define IDT_SIZE 256 +#define LDT_SIZE 4096 +#define INT_SIZE 256 + +#define TOTAL_SIZE ((GDT_SIZE+IDT_SIZE+LDT_SIZE+INT_SIZE)*8) + +#define LDT_ENTRY(BLAH_) (BLAH_ << 3) + +#define LDT_FIRSTSELECTOR 16 + +#define DPMI_ERROR_UNSUPPORTED 0x8001 +#define DPMI_ERROR_DESCRIPTOR_UNAVAILABLE 0x8011 +#define DPMI_ERROR_LINEAR_MEMORY_UNAVAILABLE 0x8012 +#define DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE 0x8013 +#define DPMI_ERROR_CALLBACK_UNAVAILABLE 0x8015 +#define DPMI_ERROR_INVALID_SELECTOR 0x8022 +#define DPMI_ERROR_INVALID_VALUE 0x8022 +#define DPMI_ERROR_INVALID_HANDLE 0x8023 +#define DPMI_ERROR_INVALID_CALLBACK 0x8024 +#define DPMI_ERROR_INVALID_LINEAR_ADDRESS 0x8025 + +#define DPMI_XMSHANDLES_MAX 256 +#define DPMI_XMSHANDLE_FREE 0xFFFF +#define DPMI_EXCEPTION_MAX 0x20 +#define DPMI_PAGE_SIZE (4*1024) +#define DPMI_REALMODE_CALLBACK_MAX 32 +#define DPMI_REALMODE_STACKSIZE 4096 +#define DPMI_PROTMODE_STACK_MAX 3 +#define DPMI_PROTMODE_STACKSIZE (4*1024) +#define DPMI_REALVEC_MAX 17 +#define DPMI_SAVESTACK_MAX 1024 + +#define DPMI_CB_APIMSDOSENTRY_OFFSET 256*8 +#define DPMI_CB_ENTERREALMODE_OFFSET 257*8 +#define DPMI_CB_SAVESTATE_OFFSET 258*8 +#define DPMI_CB_EXCEPTION_OFFSET 259*8 +#define DPMI_CB_EXCEPTIONRETURN_OFFSET 260*8 +#define DPMI_CB_VENDORENTRY_OFFSET 261*8 + +static bool g_hookHardwareInts = true; + +void CMOS_SetRegister(Bitu regNr, Bit8u val); + +static Bitu rmIndexToInt[DPMI_REALVEC_MAX] = +{ 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x1C }; + +// General functions +void CALLBACK32_SCF(bool val) +{ + Bitu v_esp = 0; + if (cpu.stack.big) v_esp = reg_esp; else v_esp = reg_sp; + Bit32u tempf=mem_readd(SegPhys(ss)+v_esp+8) & 0xFFFFFFFE; + Bit32u newCF=(val==true); + mem_writed(SegPhys(ss)+v_esp+8,(tempf | newCF)); +}; + +#define DPMI_CALLBACK_SCF(b) if (dpmi.client.bit32) CALLBACK32_SCF(b); else CALLBACK_SCF(b) + +// ********************************************** +// SetDescriptor Class +// ********************************************** + +#pragma pack(1) +class SetDescriptor : public Descriptor { +public: + void Save(PhysPt address) { + Bit32u* data = (Bit32u*)&saved; + mem_writed(address,*data); + mem_writed(address+4,*(data+1)); + } + + void SetBase(Bitu _base) { + saved.seg.base_24_31=_base >> 24; + saved.seg.base_16_23=_base >> 16; + saved.seg.base_0_15=_base; + } + void SetLimit (Bitu _limit) { + if (_limit<1048576) saved.seg.g=false; + else { + saved.seg.g=true; + _limit>>=12; + } + saved.seg.limit_0_15=_limit; + saved.seg.limit_16_19=_limit>>16; + } + void SetOffset(Bitu _offset) { + saved.gate.offset_0_15=_offset; + saved.gate.offset_16_31=(_offset>>16); + } + void SetSelector(Bitu _selector) { + saved.gate.selector=_selector; + } + void SetType(Bitu _type) { + saved.seg.type=_type; + } + void Clear(void) { + saved.fill[0]=saved.fill[1]=0; + } +}; +#pragma pack() + +// ********************************************** +// Shared Memory +// ********************************************** + +typedef struct SSharedMem { + + std::string name; + Bitu handle; + Bitu pages; + +} TSharedMem; + +std::list g_sharedMemList; + +// ********************************************** +// DPMI Class +// ********************************************** + +class DPMI { + +public: + DPMI (void); + ~DPMI (void); + + // Settp/Startup methods + void Setup (void); + Bitu Entrypoint (void); + RealPt HookInterrupt (Bitu num, Bitu intHandler); + void RestoreHookedInterrupt (Bitu num, RealPt oldVec); + void CreateStackSpace (void); + bool HasClient (void) { return dpmi.client.have; }; + void Terminate (void); + void Reactivate (void); + + // DPMI Services + Bitu AllocateLDTDescriptor (Bitu count,Bitu & base); + Bitu AllocateLDTDescriptor2 (Bitu count,Bitu & base); // TEMP + bool AllocateMem (Bitu size, Bitu& outHandle, Bitu& linear); + Bitu CreateAlias (Bitu selector, Bit16u& alias); + void ReloadSegments (Bitu selector); + bool SetAccessRights (Bitu selector, SetDescriptor& desc, Bitu rights); + + // Special Interrupt handlers + Bitu Int2fHandler (void); + Bitu Int31Handler (void); + + // Exceptions + void CreateException (Bitu num, Bitu errorCode); + Bitu ExceptionReturn (void); + + // Realmode callbacks + bool AllocateRealModeCallback(Bitu codeSel,Bitu codeOff,Bitu dataSel, Bitu dataOff, Bitu& segment, Bitu& offset); + Bitu RealModeCallback (void); + Bitu RealModeCallbackReturn (void); + + // Real mode reflection callbacks + void PrepareReflectToReal (Bitu num); + Bitu CallRealIRETFrame (void); + Bitu CallRealIRETFrameReturn (void); + Bitu SimulateInt (void); + Bitu SimulateIntReturn (void); + Bitu ptorHandler (void); + Bitu ptorHandlerReturn (void); + Bitu Int21Handler (void); + Bitu Int21HandlerReturn (void); + Bitu HWIntDefaultHandler (void); + void RemoveIntCallbacks (void); + void RestoreIntCallbacks (void); + + // Switching modes + void SaveRegisterState (Bitu num); + void LoadRegisterState (Bitu num); + Bitu EnterProtMode (void); + Bitu EnterRealMode (void); + Bitu RealSaveState (void); + Bitu ProtSaveState (void); + + // virtual interrupt flag + bool GetVirtualIntFlag (void); + void SetVirtualIntFlag (bool on); + + // Internal Stack for saving processor status + void PushStack (Bitu val) { saveStack[savePtr++] = val; }; + Bitu PopStack (void) { return saveStack[--savePtr]; }; + void SaveSegments (void); + void SaveRegister (void); + void RestoreSegments (void); + void RestoreRegister (void); + + void CopyRegistersToBuffer (PhysPt data); + void LoadRegistersFromBuffer (PhysPt data); + + void ProvideRealModeStack (PhysPt prStack, Bitu toCopy); + void UpdateRealModeStack (void); + + // xms handle information + void SetXMSHandle (Bitu handle); + void ClearXMSHandles (void); + void FreeXMSHandle (Bitu handle); + + // shared memory + void SetSharedMem (const char* name, Bitu handle, Bitu pages); + bool GetSharedMem (const char* name, Bitu& handle, Bitu& pages); + bool IsSharedMem (Bitu handle); + bool RemoveSharedMem (Bitu handle); + + // special msdos api stuff + void SetupPharlapSelectors (void); + bool Pharlap_AllocateMem (Bitu size, Bitu& outHandle, Bitu& linear); + Bitu GetSegmentFromSelector (Bitu selector); + bool GetMsdosSelector (Bitu realseg, Bitu realoff, Bitu &protsel, Bitu &protoff); + void API_Init_MSDOS (void); + Bitu API_Entry_MSDOS (void); + Bitu API_Int21_MSDOS (void); + + // debug + void Debug_ShowDescriptors (void); + +private: + Bitu Mask (Bitu value); + + Bitu saveStack[DPMI_SAVESTACK_MAX]; + Bitu savePtr; + Bitu rm_ss, rm_sp; + + struct { + struct { + bool have; + bool bit32; + Bitu psp; + } client; + Bit16u mem_handle; /* Handle for GDT/IDT */ + struct { + PhysPt base; + Bitu limit; + } gdt,idt,ldt; + struct { + bool inCall; + bool inUse; + bool stop; + Bitu callCount; + Bitu id; + Bitu dataSelector,dataOffset; + Bitu codeSelector,codeOffset; + Bitu realSegment ,realOffset; + } rmCallback[DPMI_REALMODE_CALLBACK_MAX]; + + RealPt realModeVec [DPMI_REALVEC_MAX]; + Bitu oldRealVec [DPMI_REALVEC_MAX]; + Bitu defaultHWIntFromProtMode[DPMI_REALVEC_MAX]; + + PhysPt ptorint_base; /* Base of pmode int handlers that reflect to realmode */ + Bitu exceptionSelector[DPMI_EXCEPTION_MAX],exceptionOffset[DPMI_EXCEPTION_MAX]; + + Bitu xmsHandles[DPMI_XMSHANDLES_MAX]; + Bitu protStack; + + Bitu protStackSelector[DPMI_PROTMODE_STACK_MAX]; + Bitu realStackSelector[DPMI_PROTMODE_STACK_MAX]; + Bitu dataSelector [DPMI_PROTMODE_STACK_MAX]; + Bitu protStackCurrent; + + Bitu vIntFlag; + + bool pharlap; + bool suppressRMCB; + + // Pharlap stuff + Bitu initialcs,initialds; + Bitu initialenv; + } dpmi; + + Bit32u* modIntTable; + DPMI* prevDPMI; + std::vector dosSelectorList; + + Bitu dtaAddress; + Bitu save_cs[2],save_ds[2],save_es[2],save_fs[2],save_gs[2],save_ss[2]; + Bitu save_eax[2],save_ebx[2],save_ecx[2],save_edx[2],save_esi[2],save_edi[2]; + Bitu save_ebp[2],save_esp[2],save_eip[2],save_fl[2]; +}; + +struct { + Bitu entry; + Bitu ptorint; + Bitu ptorintReturn; + Bitu int31; + Bitu int21; + Bitu int21Return; + Bitu int2f; + Bitu enterpmode; + Bitu enterrmode; + Bitu protsavestate; + Bitu realsavestate; + Bitu simint; + Bitu simintReturn; + Bitu rmIntFrame; + Bitu rmIntFrameReturn; + Bitu rmCallbackReturn; + Bitu exception; + Bitu exceptionret; + // Special callbacks for special dos extenders + Bitu apimsdosentry; + Bitu int21msdos; +} callback; + +// ************************************************ +// DPMI static functions +// ************************************************ + +static DPMI* activeDPMI = 0; +static Bit32u originalIntTable[256]; + +bool DPMI_IsActive(void) +{ + return (cpu.cr0 & CR0_PROTECTION) && activeDPMI && activeDPMI->HasClient(); +} + +void DPMI_SetVirtualIntFlag(bool on) +{ + if (activeDPMI) activeDPMI->SetVirtualIntFlag(on); +} + +void DPMI_CreateException(Bitu num, Bitu errorCode) +{ + if (activeDPMI) activeDPMI->CreateException(num,errorCode); +} + +// ************************************************ +// DPMI Methods +// ************************************************ + +DPMI::DPMI(void) +{ + memset(&dpmi,0,sizeof(dpmi)); + savePtr = 0; + dtaAddress = 0; + rm_ss = rm_sp = 0; + modIntTable = 0; + prevDPMI = activeDPMI; +}; + +DPMI::~DPMI(void) +{ + MEM_ReleasePages(dpmi.mem_handle); + dosSelectorList.clear(); + // TODO: Free all memory allocated with DOS_GetMemory + // Activate previous dpmi + activeDPMI = prevDPMI; + // Restore hookHardwareInts ability which may be changed by a pharlap program + if (!activeDPMI) g_hookHardwareInts = true; +}; + +void DPMI::ClearXMSHandles(void) +{ + for (Bitu i=0; iname = name; + smem->handle= handle; + smem->pages = pages; + g_sharedMemList.push_back(smem); +}; + +bool DPMI::GetSharedMem(const char* name, Bitu& handle, Bitu& pages) +{ + TSharedMem* smem; + std::list::iterator i; + for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { + smem = static_cast(*i); + if (smem->name.compare(name)==0) { + handle = smem->handle; + pages = smem->pages; + return true; + } + + }; + return false; +}; + +bool DPMI::IsSharedMem(Bitu handle) +{ + std::list::iterator i; + for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { + if ((*i)->handle==handle) return true; + }; + return false; +}; + +bool DPMI::RemoveSharedMem(Bitu handle) +{ + TSharedMem* smem; + std::list::iterator i; + for(i = g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) { + smem = static_cast(*i); + if (smem->handle==handle) { + g_sharedMemList.remove(*i); + delete smem; + return true; + } + + }; + return false; +}; + +void DPMI::SetXMSHandle(Bitu handle) { + for (Bitu i=0; i=DPMI_SAVESTACK_MAX) E_Exit("DPMI: Stack too small."); + saveStack[savePtr++] = SegValue(ds); + saveStack[savePtr++] = SegValue(es); + saveStack[savePtr++] = SegValue(fs); + saveStack[savePtr++] = SegValue(gs); + saveStack[savePtr++] = SegValue(ss); +} + +void DPMI::SaveRegister(void) +{ + SaveSegments(); + if (savePtr+8>=DPMI_SAVESTACK_MAX) E_Exit("DPMI: Stack too small."); + saveStack[savePtr++] = reg_eax; + saveStack[savePtr++] = reg_ebx; + saveStack[savePtr++] = reg_ecx; + saveStack[savePtr++] = reg_edx; + saveStack[savePtr++] = reg_esi; + saveStack[savePtr++] = reg_edi; + saveStack[savePtr++] = reg_ebp; + saveStack[savePtr++] = reg_esp; +}; + +void DPMI::RestoreSegments(void) +{ + CPU_SetSegGeneral(ss,saveStack[--savePtr]); + CPU_SetSegGeneral(gs,saveStack[--savePtr]); + CPU_SetSegGeneral(fs,saveStack[--savePtr]); + CPU_SetSegGeneral(es,saveStack[--savePtr]); + CPU_SetSegGeneral(ds,saveStack[--savePtr]); +}; + +void DPMI::RestoreRegister(void) +{ + reg_esp = saveStack[--savePtr]; + reg_ebp = saveStack[--savePtr]; + reg_edi = saveStack[--savePtr]; + reg_esi = saveStack[--savePtr]; + reg_edx = saveStack[--savePtr]; + reg_ecx = saveStack[--savePtr]; + reg_ebx = saveStack[--savePtr]; + reg_eax = saveStack[--savePtr]; + RestoreSegments(); +}; + +void DPMI::CopyRegistersToBuffer(PhysPt data) +{ + // Save Values in structure + mem_writed(data+0x00, reg_edi); + mem_writed(data+0x04, reg_esi); + mem_writed(data+0x08, reg_ebp); + mem_writed(data+0x0C, 0x0000); + mem_writed(data+0x10, reg_ebx); + 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+0x22, SegValue(es)); + mem_writew(data+0x24, SegValue(ds)); + mem_writew(data+0x26, SegValue(fs)); + mem_writew(data+0x28, SegValue(gs)); + mem_writew(data+0x2A, reg_ip); + mem_writew(data+0x2C, SegValue(cs)); + mem_writew(data+0x2E, reg_sp); + mem_writew(data+0x30, SegValue(ss)); +} + +void DPMI::LoadRegistersFromBuffer(PhysPt data) +{ + reg_edi = mem_readd(data+0x00); + reg_esi = mem_readd(data+0x04); + reg_ebp = mem_readd(data+0x08); + reg_ebx = mem_readd(data+0x10); + reg_edx = mem_readd(data+0x14); + reg_ecx = mem_readd(data+0x18); + reg_eax = mem_readd(data+0x1C); + CPU_SetFlagsw(mem_readw(data+0x20)); + SegSet16(es,mem_readw(data+0x22)); + SegSet16(ds,mem_readw(data+0x24)); + SegSet16(fs,mem_readw(data+0x26)); + SegSet16(gs,mem_readw(data+0x28)); + reg_esp = mem_readw(data+0x2E); + SegSet16(ss,mem_readw(data+0x30)); + if (!dpmi.client.bit32) { + reg_eax &= 0xFFFF; + reg_ebx &= 0xFFFF; + reg_ecx &= 0xFFFF; + reg_edx &= 0xFFFF; + reg_edi &= 0xFFFF; + reg_esi &= 0xFFFF; + reg_ebp &= 0xFFFF; + reg_esp &= 0xFFFF; + }; +}; + +void DPMI::ProvideRealModeStack(PhysPt prStack, Bitu toCopy) +{ + // Check stack, if zero provide it + if ((SegValue(ss)==0) && (reg_sp==0)) { + SegSet16(ss,rm_ss); + reg_esp = rm_sp; + } else { + if (SegValue(ss)==rm_ss) reg_esp = rm_sp; + }; + // We have to be in realmode here + if (toCopy>0) { + Bitu numBytes = toCopy*2; + if (reg_espDPMI_REALMODE_STACKSIZE) E_Exit("DPMI:Realmode stack out of range: %04X",reg_esp); + rm_sp = reg_sp; + } +}; + +Bitu DPMI::AllocateLDTDescriptor(Bitu count,Bitu & base) { + + SetDescriptor test; + Bitu i=16, found=0; + PhysPt address = dpmi.ldt.base + LDT_FIRSTSELECTOR*8; + while (i0;found--) { + test.Save(address); + address+=8; + } + return true; + } + } + return false; +} + +Bitu DPMI::AllocateLDTDescriptor2(Bitu count,Bitu & base) { + + static Bitu allocated = 0; + + SetDescriptor desc; + Bitu nr = LDT_FIRSTSELECTOR + allocated; + if (nr+count < LDT_SIZE) { + desc.Clear(); + desc.SetType(DESC_DATA_EU_RW_NA); + desc.saved.seg.p = 1; + desc.saved.seg.big = dpmi.client.bit32; + desc.saved.seg.dpl = DPMI_DPL; + base = (nr << 3)|(4|DPMI_DPL); /* Make it an LDT Entry */ + allocated += count; + Bitu address = dpmi.ldt.base+(base & ~7); + for (;count>0;count--) { + desc.Save(address); + address+=8; + } + return true; + }; + return false; +} + +Bitu DPMI::CreateAlias(Bitu selector, Bit16u& alias) +{ + Descriptor oldDesc; + Bitu base; + if (!cpu.gdt.GetDescriptor(selector,oldDesc)) { alias = DPMI_ERROR_INVALID_SELECTOR; return false; }; + if (!AllocateLDTDescriptor(1,base)) { alias = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; return false; }; + SetDescriptor desc; + desc.Clear(); + desc.SetLimit(oldDesc.GetLimit()); + desc.SetBase (oldDesc.GetBase()); + desc.SetType (DESC_DATA_ED_RW_A); + desc.saved.seg.p=1; + desc.saved.seg.dpl = DPMI_DPL; + desc.Save (dpmi.ldt.base+(base & ~7)); + alias = base; + return true; +}; + +void DPMI::ReloadSegments(Bitu selector) +{ + if (SegValue(cs)==selector) CPU_SetSegGeneral(cs,selector); + if (SegValue(ds)==selector) CPU_SetSegGeneral(ds,selector); + if (SegValue(es)==selector) CPU_SetSegGeneral(es,selector); + if (SegValue(fs)==selector) CPU_SetSegGeneral(fs,selector); + if (SegValue(gs)==selector) CPU_SetSegGeneral(gs,selector); + if (SegValue(ss)==selector) CPU_SetSegGeneral(ss,selector); +}; + +void DPMI::CreateException(Bitu num, Bitu errorCode) +{ + if (dpmi.client.bit32) { + 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(errorCode); + CPU_Push32(GDT_PROTCODE); // return cs + CPU_Push32(DPMI_CB_EXCEPTIONRETURN_OFFSET); // return eip + } else { + 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(errorCode); + CPU_Push16(GDT_PROTCODE); // return cs + CPU_Push16(DPMI_CB_EXCEPTIONRETURN_OFFSET); // return eip + }; + DPMI_LOG("DPMI: Exception occured : %04X (%04X:%08X)",num,dpmi.exceptionSelector[num],dpmi.exceptionOffset[num]); + CPU_JMP(dpmi.client.bit32,dpmi.exceptionSelector[num],dpmi.exceptionOffset[num]); +}; + +Bitu DPMI::ExceptionReturn(void) +{ + Bitu error; + // Restore Registers + Bitu newcs; + if (dpmi.client.bit32) { + error = CPU_Pop32(); + reg_eip = CPU_Pop32(); + newcs = CPU_Pop32(); + CPU_SetFlagsd(CPU_Pop32()); + reg_esp = CPU_Pop32(); + CPU_SetSegGeneral(ss,CPU_Pop32()); + } else { + error = CPU_Pop16(); + reg_eip = CPU_Pop16(); + newcs = CPU_Pop16(); + CPU_SetFlagsw(CPU_Pop16()); + reg_esp = CPU_Pop16(); + CPU_SetSegGeneral(ss,CPU_Pop16()); + }; + DPMI_LOG("DPMI: Return from Exception. Jump to %04X:%08X",SegValue(cs),reg_eip); + CPU_JMP(dpmi.client.bit32,newcs,reg_eip); + return 0; +}; + +void DPMI::RemoveIntCallbacks() +// When switching dpmi clients, remove active callbacks from hardware int +{ + Bitu i; + modIntTable = new Bit32u[256]; + // read and store interrupt table + for (i=0; i<256; i++) modIntTable[i] = mem_readd(i*4); + // set a clean interrupt table + for (i=0; i<256; i++) mem_writed(i*4,originalIntTable[i]); +}; + +void DPMI::RestoreIntCallbacks() +{ + if (modIntTable) { + // restore modified interrupt table + for (int i=0; i<256; i++) mem_writed(i*4,modIntTable[i]); + delete[] modIntTable; modIntTable = 0; + } +}; + +bool DPMI::AllocateRealModeCallback(Bitu codeSel,Bitu codeOff,Bitu dataSel, Bitu dataOff, Bitu& segment, Bitu& offset) +{ + Bitu num = 0; + for (Bitu i=0; i=DPMI_REALMODE_CALLBACK_MAX) || !dpmi.rmCallback[num].inUse) E_Exit("DPMI: Illegal Realmode callback %02X.",num); + + if (dpmi.rmCallback[num].inCall) DPMI_LOG("DPMI: Recursive Realmode callback %02X",num); + if (dpmi.protStackCurrent>DPMI_PROTMODE_STACK_MAX) E_Exit("DPMI: Too many recursive Realmode callbacks. Stack failure."); + + PushStack(num); + + DPMI_LOG("DPMI: Realmode Callback %02X (%04X:%08X) enter",num,dpmi.rmCallback[num].codeSelector,dpmi.rmCallback[num].codeOffset); + dpmi.rmCallback[num].inCall= true; + dpmi.rmCallback[num].callCount++; + + // Important! Update realmode stack + UpdateRealModeStack(); + // Setup stack selector of real mode stack + SetDescriptor desc; + if (cpu.gdt.GetDescriptor(dpmi.realStackSelector[dpmi.protStackCurrent],desc)) { + desc.SetBase (SegValue(ss)<<4); + desc.SetLimit(0xFFFF); + 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); + // Setup dataSelector + Descriptor data; + Bitu dataSelector; + if (dpmi.rmCallback[num].dataSelector==0x0000) dataSelector = dpmi.dataSelector[dpmi.protStackCurrent]; + else dataSelector = dpmi.rmCallback[num].dataSelector; + if (!cpu.gdt.GetDescriptor(dataSelector,data)) E_Exit("DPMI: Init RM-Callback failed."); + + DPMI_LOG("DPMI: CB: Writing RegData at = %04X:%04X",dataSelector,dpmi.rmCallback[num].dataOffset); + // Prepare data buffer + CopyRegistersToBuffer(PhysPt(data.GetBase()+dpmi.rmCallback[num].dataOffset)); + DPMI_LOG("DPMI: CB: Stored cs:ip = %04X:%04X",SegValue(cs),reg_ip); + // setup registers for protected mode func + CPU_SetSegGeneral(ds,dpmi.realStackSelector[dpmi.protStackCurrent]); // DS:ESI = RM Stack + reg_esi = reg_esp; + CPU_SetSegGeneral(es,dataSelector); // ES:EDI = RM Register data + reg_edi = dpmi.rmCallback[num].dataOffset; + // SS:ESP = API stack + 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); + // Setup cs:ip to return to DPMI_ReturnFromRealModeCallback + CPU_SetSegGeneral(cs,GDT_CODE); + reg_eip = RealOff(CALLBACK_RealPointer(callback.rmCallbackReturn)); + // call protected mode func + SetVirtualIntFlag(false); + SETFLAGBIT(IF,false); + SETFLAGBIT(TF,false); + CPU_Push32(flags.word); + CPU_CALL(dpmi.client.bit32,dpmi.rmCallback[num].codeSelector,dpmi.rmCallback[num].codeOffset); + return 0; +}; + +Bitu DPMI::RealModeCallbackReturn(void) +{ + // returning from protected mode function, now back to real mode + Bitu num = PopStack(); + DPMI_LOG("DPMI: Realmode Callback leave %02X",num); + dpmi.suppressRMCB = false; + dpmi.rmCallback[num].inCall = false; + dpmi.rmCallback[num].stop = false; + dpmi.rmCallback[num].callCount--; + 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); + dpmi.protStackCurrent--; + // Restore Registers + LoadRegistersFromBuffer(data); + Bitu newCS = mem_readw(data+0x2C); + Bitu newIP = mem_readw(data+0x2A); + UpdateRealModeStack(); + SetVirtualIntFlag(true); + DPMI_LOG("DPMI: CB: Retored cs:ip = %04X:%04X (%d)",newCS,newIP); + CPU_JMP(false,newCS,newIP); + return 0; +}; + +static Bitu count = 0; + +Bitu DPMI::CallRealIRETFrame(void) +{ + Bitu calledIP = mem_readd(SegPhys(ss)+reg_esp); + Bitu calledCS = mem_readd(SegPhys(ss)+reg_esp+4); + DPMI_LOG("DPMI: ENTER REAL PROC IRETF %04X:%08X",calledCS,calledIP); + // Save changed registers + PushStack(SegValue(cs)); + SaveRegister(); + Bitu toCopy = reg_cx; + // Load Registers + PhysPt data = SegPhys(es) + reg_edi; + PhysPt prStack = SegPhys(ss) + reg_esp; + LoadRegistersFromBuffer(data); + PushStack(data); + /* Switch to real mode */ + CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + // Provide Stack + ProvideRealModeStack(prStack,toCopy); + // Push flags + CPU_Push16(flags.word); + // Setup IP + Bitu newCS = mem_readw(data+0x2C); + Bitu newIP = mem_readw(data+0x2A); + // Setup cs:ip to return to DPMI_CallRealIRETFrame callback + SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.rmIntFrameReturn))); + reg_ip = RealOff(CALLBACK_RealPointer(callback.rmIntFrameReturn)); + SetVirtualIntFlag(false); + SETFLAGBIT(IF,false); + SETFLAGBIT(TF,false); + CPU_CALL(false,newCS,newIP); + return 0; +} + +Bitu DPMI::CallRealIRETFrameReturn(void) +{ + UpdateRealModeStack(); + // 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); + // Save registers into real mode structure + CopyRegistersToBuffer(PopStack()); + // Restore changed Resgisters + RestoreRegister(); + Bitu newcs = PopStack(); + + CPU_JMP(dpmi.client.bit32,newcs,reg_eip); + + SetVirtualIntFlag(true); + DPMI_CALLBACK_SCF(false); + return 0; +}; + +Bitu DPMI::SimulateInt(void) +{ + Bitu num = reg_bl; + DPMI_LOG("DPMI: SIM INT %02X %04X called. cs = %04X",num,reg_ax,SegValue(cs)); + // Save changed registers + PushStack(SegValue(cs)); + SaveRegister(); + Bitu toCopy = reg_cx; + // Load Registers + PhysPt data = SegPhys(es) + reg_edi; + PhysPt prStack = SegPhys(ss) + reg_esp; + LoadRegistersFromBuffer(data); + PushStack(data); + /* Switch to real mode */ + CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + // Provide Stack + ProvideRealModeStack(prStack,toCopy); + // prepare for return + SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.simintReturn))); + 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); + DPMI_LOG("DPMI: SimInt2: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); + return 0; +}; + +Bitu DPMI::SimulateIntReturn(void) +{ + // returning from realmode func + DPMI_LOG("DPMI: SIM INT return"); + DPMI_LOG("DPMI: SimIntRet1: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); + + UpdateRealModeStack(); + /* Switch to protected mode */ + CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + // Save registers into real mode structure + CopyRegistersToBuffer(PopStack()); + // Restore changed Resgisters + RestoreRegister(); + Bitu newcs = PopStack(); + DPMI_LOG("DPMI: SimIntRet: JUMP to %04X:%08X",newcs,reg_eip); + CPU_JMP(dpmi.client.bit32,newcs,reg_eip); + SetVirtualIntFlag(true); + // Free last realmode stack + DPMI_CALLBACK_SCF(false); + DPMI_LOG("DPMI: SimIntRet2: StackInfo %04X:%04X (%02X %02X)",SegValue(ss),reg_esp,mem_readb(0xD0100+0x01FA),mem_readb(0xD0100+0x01FB)); + return 0; +}; + +void DPMI::PrepareReflectToReal(Bitu num) +{ + // Save segment and stack register + SaveSegments(); + PushStack(reg_esp); + PushStack(num); + PushStack(reg_eip); + PushStack(SegValue(cs)); + /* Swtich to real mode */ + CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + // Setup cs:ip to return to intreturn + Bitu retcs = RealSeg(CALLBACK_RealPointer(callback.ptorintReturn)); + Bitu retip = RealOff(CALLBACK_RealPointer(callback.ptorintReturn)); + + SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.ptorintReturn))); + reg_ip = RealOff(CALLBACK_RealPointer(callback.ptorintReturn)); + // setup stack + SegSet16(ss,rm_ss); + reg_esp = rm_sp; +} + +Bitu DPMI::ptorHandler(void) +{ + /* Pmode interrupt handler that maps the interrupt to realmode */ + Bitu num = reg_eip >> 3; +// if (!dpmi.vIntFlag) { +// if ((num>=0x08) && (num<=0x0F)) return 0; +// if ((num>=0x70) && (num<=0x77)) return 0; +// }; + PrepareReflectToReal(num); +// 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); + return 0; +} + +Bitu DPMI::ptorHandlerReturn(void) +// Return from reflected real mode int +{ + UpdateRealModeStack(); + /* Switch to protected mode */ + CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + // Restore Registers + Bitu newcs = PopStack(); + reg_eip = PopStack(); + Bitu num = PopStack(); + reg_esp = PopStack(); + RestoreSegments(); +// if (num==0x0F) + DPMI_LOG("DPMI: INT %02X RETURN",num); + // hardware ints exit here + if (((num>=0x08) && (num<=0x0F)) || ((num>=0x70) && (num<=0x77))) { + SetVirtualIntFlag(true); + CPU_JMP(dpmi.client.bit32,newcs,reg_eip); + return 0; + } + // 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) + 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) + mem_writew(SegPhys(ss)+reg_sp+4,oldFlags|userFlags); + }; + SetVirtualIntFlag(true); + CPU_JMP(dpmi.client.bit32,newcs,reg_eip); + return 0; +} + +Bitu DPMI::Int21Handler(void) +{ + // Check for exit + if (reg_ah==0x4C) { + DPMI_LOG("DPMI: INT 21: Terminating."); + Terminate(); + } + // Save segment and stack register + PushStack(SegValue(ss)); + PushStack(reg_esp); + PushStack(SegValue(ds)); + PushStack(SegValue(es)); + PushStack(SegValue(cs)); + + /* Swtich to real mode */ + CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + // Setup cs:ip to return to intreturn + SegSet16(cs,RealSeg(CALLBACK_RealPointer(callback.int21Return))); + reg_ip = RealOff(CALLBACK_RealPointer(callback.int21Return)); + // setup stack + SegSet16(ss,rm_ss); + reg_esp = rm_sp; + // Call realmode interrupt + DPMI_LOG("DPMI: INT 21 %04X called.",reg_ax); + Interrupt(0x21); + if (reg_ah==0x4C) { + // Shut doen dpmi and restore previous one + delete this; + if (activeDPMI) activeDPMI->Reactivate(); + } + return 0; +}; + +Bitu DPMI::Int21HandlerReturn(void) +{ + UpdateRealModeStack(); + /* Switch to protected mode */ + CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + // Restore Registers + Bitu newcs = PopStack(); + CPU_SetSegGeneral(es,PopStack()); + CPU_SetSegGeneral(ds,PopStack()); + reg_esp = PopStack(); + CPU_SetSegGeneral(ss,PopStack()); + // Set carry flag + DPMI_CALLBACK_SCF(flags.word & 1); + DPMI_LOG("DPMI: INT 21 RETURN"); + SetVirtualIntFlag(true); + CPU_JMP(dpmi.client.bit32,newcs,reg_eip); + return 0; +} + +Bitu DPMI::HWIntDefaultHandler() +// Wir sind hier im Protected mode +// a) durch einen INTerrupt im protected mode +// b) durch einen INTerrupt im real mode (durch RMCB) +{ + Bitu index = mem_readw(PhysPt(SegPhys(cs)+reg_eip-2)) - dpmi.defaultHWIntFromProtMode[0]; + if (index>=DPMI_REALVEC_MAX) E_Exit("DPMI: Illegal realmode interrupt callback: %02X",index); + Bitu num = rmIndexToInt[index]; + + RealPt vec = RealGetVec(num); + + if (dpmi.rmCallback[index].callCount==0) { + // INT PROT (Use Handler is already done). + // Wenn rmcb noch in Realmode Int table installiert, dann originalMethode aufrufef + if (vec==dpmi.realModeVec[index]) { + // originalroutine aufrufen + dpmi.rmCallback[index].stop = false; + PrepareReflectToReal(num); + CPU_Push16(flags.word); + SetVirtualIntFlag(false); + SETFLAGBIT(IF,false); + SETFLAGBIT(TF,false); + CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); + } else { + // user real mode handler in real mode int table aktiv. + // Moeglich, dass dieser den RMCB von Hand noch aufruft + // dann wird aber callCount>0 sein (da RMCB aktiv) und + // dann die alte Routine aufgerufen... + // RMCB sperren, um einen erneuten Aufruf des User Handlers zu vermeiden,.. + + // This is a hack for cybermage wich wont work otherwise. But why ? + if (num==0x0F) { + if (dpmi.suppressRMCB) { + dpmi.suppressRMCB = false; + return 0; + } else { + dpmi.suppressRMCB = true; + } + }; + PrepareReflectToReal(num); + SetVirtualIntFlag(false); + SETFLAGBIT(IF,false); + SETFLAGBIT(TF,false); + CPU_Push16(flags.word); + CPU_CALL(false,RealSeg(vec),RealOff(vec)); + } + } else { + // INT REAL (vom RMCB aktiviert) + // Falls user handler schon aktiv war (int von prot->reflected to real) + // rufe original routine auf + if (dpmi.rmCallback[index].stop) { + dpmi.rmCallback[index].stop = false; + PrepareReflectToReal(num); + CPU_Push16(flags.word); + SetVirtualIntFlag(false); + SETFLAGBIT(IF,false); + SETFLAGBIT(TF,false); + CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); + } else { + // User routine wurde noch nicht aktiviert, callback aber ausgeführt + // falls spezieller protected mode handler aktiviert wurde, + // wird dieser jetzt aufgerufen (user routine im protected mode) + Descriptor gate; + gate.Load(dpmi.idt.base+num*8); + if ((gate.GetSelector()!=GDT_CODE) || (gate.GetOffset()!=RealOff(dpmi.defaultHWIntFromProtMode[index]))) { + dpmi.rmCallback[index].stop = true; // vermeide rekursion + CPU_JMP(dpmi.client.bit32,gate.GetSelector(),gate.GetOffset()); + } else { + // kein spezieller Protmode handler - Rufe originalroutine auf + PrepareReflectToReal(num); + CPU_Push16(flags.word); + SetVirtualIntFlag(false); + SETFLAGBIT(IF,false); + SETFLAGBIT(TF,false); + CPU_CALL(false,RealSeg(dpmi.oldRealVec[index]),RealOff(dpmi.oldRealVec[index])); + }; + }; + } + return 0; +}; + +void DPMI::SaveRegisterState(Bitu num) +// Copy Current Registers to structure +{ + return; + save_cs[num] = SegValue(cs); + save_ds[num] = SegValue(ds); + save_es[num] = SegValue(es); + save_fs[num] = SegValue(fs); + save_gs[num] = SegValue(gs); + save_ss[num] = SegValue(ss); + save_eip[num] = reg_eip; + save_eax[num] = reg_eax; + save_ebx[num] = reg_ebx; + save_ecx[num] = reg_ecx; + save_edx[num] = reg_edx; + save_esi[num] = reg_esi; + save_edi[num] = reg_edi; + save_ebp[num] = reg_ebp; + save_esp[num] = reg_esp; + save_fl [num] = flags.word; +}; + +void DPMI::LoadRegisterState(Bitu num) +// Copy Current Registers to structure +{ + return; + CPU_SetSegGeneral(fs,save_fs[num]); + CPU_SetSegGeneral(gs,save_gs[num]); + reg_eax = save_eax[num]; + reg_ebx = save_ebx[num]; + reg_ecx = save_ecx[num]; + reg_edx = save_edx[num]; + reg_esi = save_esi[num]; + reg_edi = save_edi[num]; + flags.word = save_fl [num]; +}; + +Bitu DPMI::EnterProtMode(void) { + + /* Save real mode register state */ + SaveRegisterState(0); + + /* Switch to protected mode */ + CPU_SET_CRX(0,cpu.cr0 | CR0_PROTECTION); + + CPU_SetSegGeneral(ds,reg_ax); + CPU_SetSegGeneral(es,reg_cx); + CPU_SetSegGeneral(ss,reg_dx); + CPU_SetSegGeneral(ds,reg_ax); + + if (dpmi.client.bit32) { + reg_esp = reg_ebx; + CPU_JMP(true,reg_si,reg_edi); + } else { + reg_sp = reg_bx; + CPU_JMP(false,reg_si,reg_di); + }; + + /* Load prot mode register state (all other unchanged registers */ + LoadRegisterState(1); + + DPMI_LOG("DPMI: Switch to protected mode."); + return 0; +} + +Bitu DPMI::EnterRealMode(void) { + + /* Save Prot Mode Registers */ + SaveRegisterState(1); + + /* Swtich to real mode */ + CPU_SET_CRX(0,cpu.cr0 & ~CR0_PROTECTION); + // (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). + SegSet16(ds,reg_ax); + SegSet16(es,reg_cx); + SegSet16(ss,reg_dx); + SegSet16(fs,0); + SegSet16(gs,0); + if (dpmi.client.bit32) { + reg_esp = reg_ebx; + CPU_JMP(true,reg_si,reg_edi); + } else { + reg_sp = reg_bx; + CPU_JMP(false,reg_si,reg_di); + }; + + /* Load real mode register state (all other unchanged registers) */ + LoadRegisterState(0); + DPMI_LOG("DPMI: Switch to real mode."); + return CBRET_NONE; +}; + +Bitu DPMI::RealSaveState(void) +{ + return CBRET_NONE; + /* Save Protected mode state */ + if (reg_al==0) { + PhysPt data = SegPhys(es) + reg_edi; + mem_writew(data+ 0,save_cs[1]); + mem_writew(data+ 2,save_ds[1]); + mem_writew(data+ 4,save_es[1]); + mem_writew(data+ 6,save_fs[1]); + mem_writew(data+ 8,save_gs[1]); + mem_writew(data+10,save_ss[1]); + mem_writed(data+12,save_eax[1]); + mem_writed(data+16,save_ebx[1]); + mem_writed(data+20,save_ecx[1]); + mem_writed(data+24,save_edx[1]); + mem_writed(data+28,save_esi[1]); + mem_writed(data+32,save_edi[1]); + mem_writed(data+36,save_ebp[1]); + mem_writed(data+40,save_esp[1]); + mem_writed(data+44,save_fl [1]); + DPMI_LOG("DPMI: Prot Save State."); + } else if (reg_al==1) { + /* restore state of prot mode registers */ + PhysPt data = SegPhys(es) + reg_edi; + save_cs [1] = mem_readw(data+ 0); + save_ds [1] = mem_readw(data+ 2); + save_es [1] = mem_readw(data+ 4); + save_fs [1] = mem_readw(data+ 6); + save_gs [1] = mem_readw(data+ 8); + save_ss [1] = mem_readw(data+10); + save_eax[1] = mem_readd(data+12); + save_ebx[1] = mem_readd(data+16); + save_ecx[1] = mem_readd(data+20); + save_edx[1] = mem_readd(data+24); + save_edi[1] = mem_readd(data+28); + save_esi[1] = mem_readd(data+32); + save_ebp[1] = mem_readd(data+36); + save_esp[1] = mem_readd(data+40); +// save_eip[1] = mem_readd(data+44); + save_fl [1] = mem_readd(data+44); + DPMI_LOG("DPMI: Prot Restore State."); + }; + return CBRET_NONE; +}; + +Bitu DPMI::ProtSaveState(void) +{ + return CBRET_NONE; + if (reg_al==0) { + /* Save State of real mode registers */ + PhysPt data = SegPhys(es) + reg_edi; + mem_writew(data+ 0,save_cs[0]); + mem_writew(data+ 2,save_ds[0]); + mem_writew(data+ 4,save_es[0]); + mem_writew(data+ 6,save_fs[0]); + mem_writew(data+ 8,save_gs[0]); + mem_writew(data+10,save_ss[0]); + mem_writed(data+12,save_eax[0]); + mem_writed(data+16,save_ebx[0]); + mem_writed(data+20,save_ecx[0]); + mem_writed(data+24,save_edx[0]); + mem_writed(data+28,save_esi[0]); + mem_writed(data+32,save_edi[0]); + mem_writed(data+36,save_ebp[0]); + mem_writed(data+40,save_esp[0]); + mem_writed(data+44,save_eip[0]); + mem_writed(data+48,save_fl [0]); + DPMI_LOG("DPMI: Real Save State."); + } else if (reg_al==1) { + /* restore state of real mode registers */ + PhysPt data = SegPhys(es) + reg_edi; + save_cs [0] = mem_readw(data+ 0); + save_ds [0] = mem_readw(data+ 2); + save_es [0] = mem_readw(data+ 4); + save_fs [0] = mem_readw(data+ 6); + save_gs [0] = mem_readw(data+ 8); + save_ss [0] = mem_readw(data+10); + save_eax[0] = mem_readd(data+12); + save_ebx[0] = mem_readd(data+16); + save_ecx[0] = mem_readd(data+20); + save_edx[0] = mem_readd(data+24); + save_edi[0] = mem_readd(data+28); + save_esi[0] = mem_readd(data+32); + save_ebp[0] = mem_readd(data+36); + save_esp[0] = mem_readd(data+40); + save_eip[0] = mem_readd(data+44); + save_fl [0] = mem_readd(data+48); + DPMI_LOG("DPMI: Real Restore State."); + }; + return CBRET_NONE; +}; + +bool DPMI::GetVirtualIntFlag(void) +// only to call from int 31 cos it uses the pushed flags on int stack +{ + if (dpmi.client.bit32) return (mem_readd(SegPhys(ss)+reg_esp+8) & FLAG_IF)>0; + else return (mem_readd(SegPhys(ss)+reg_sp+4) & FLAG_IF)>0; +}; + +void DPMI::SetVirtualIntFlag(bool on) +{ + dpmi.vIntFlag = 1; //on; +}; + +bool DPMI::AllocateMem(Bitu size, Bitu& outHandle, Bitu& linear) +{ + Bitu pages = (size/DPMI_PAGE_SIZE) + ((size%DPMI_PAGE_SIZE)>0); // Convert to 4KB pages + outHandle = MEM_AllocatePages(pages,true); + linear = outHandle*DPMI_PAGE_SIZE; + if (outHandle!=0) SetXMSHandle(outHandle); + return (outHandle!=0); +}; + +bool DPMI::SetAccessRights(Bitu selector, SetDescriptor& desc, Bitu rights) +{ + // must equal caller DPL + if (((rights & 0x60)>>5)!=DPMI_DPL) { + DPMI_LOG("DPMI: Set Rights %04X : %04X failure (dpl=%02X)",selector,rights,(rights & 0x60)>>5); +// return false; + } + // must be 1 + if ((rights & 0x10)==0) { + DPMI_LOG_ERROR("DPMI: Set Rights %04X : %04X failure (must be 1)",selector,rights); + return false; + }; + // must be 0 + if (dpmi.client.bit32 && desc.saved.seg.p && (rights & 0x2000)) { + DPMI_LOG_ERROR("DPMI: Set Rights %04X : %04X failure (must be 0)",selector,rights); + return false; + }; + // all tests passed, set rights for 16 + 32 Bit + desc.SetType (rights&0x1F); + desc.saved.seg.dpl = (rights&0x60)>>5; + desc.saved.seg.dpl = DPMI_DPL; + desc.saved.seg.p = (rights&0x80)>0; + // extended rights for 32 Bit apps + if (dpmi.client.bit32) { + desc.saved.seg.avl = (rights&0x1000)>0; + desc.saved.seg.r = (rights&0x2000)>0; + desc.saved.seg.big = (rights&0x4000)>0; + desc.saved.seg.g = (rights&0x8000)>0; + }; + return true; +}; + +Bitu DPMI::Int31Handler(void) +{ + switch (reg_ax) { + + case 0x0000:{// Allocate LDT Descriptors + Bitu base; + Descriptor desc; + if (AllocateLDTDescriptor(reg_cx,base)) { + reg_ax = base; + DPMI_LOG("DPMI: 0000: Allocate %d descriptors: %04X",reg_cx,base); + DPMI_CALLBACK_SCF(false); + } else { + DPMI_LOG_ERROR("DPMI: 0000: Allocate %d descriptors failure",reg_cx); + reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x0001:{// Free Descriptor + SetDescriptor desc; + if (cpu.gdt.GetDescriptor(reg_bx,desc)) { + desc.saved.seg.p = 0; + desc.Save (dpmi.ldt.base+(reg_bx & ~7)); + DPMI_LOG("DPMI: 0001: Free Descriptor: %04X",reg_bx); + DPMI_CALLBACK_SCF(false); + } else { + DPMI_LOG_ERROR("DPMI: 0001: Free Descriptor failure : %04X",reg_bx); + reg_ax = DPMI_ERROR_INVALID_SELECTOR; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x0002:{// Segment to Descriptor + SetDescriptor desc; Bitu base; + if (AllocateLDTDescriptor(1,base)) { + desc.Load (dpmi.ldt.base+(base & ~7)); + desc.SetLimit(0xFFFF); + desc.SetBase (reg_bx<<4); + desc.saved.seg.dpl=3; + desc.Save (dpmi.ldt.base+(base & ~7)); + reg_ax = base; + DPMI_LOG("DPMI: 0000: Seg %04X to Desc: %04X",reg_bx,base); + DPMI_CALLBACK_SCF(false); + } else { + // No more Descriptors available + DPMI_LOG_ERROR("DPMI: 0002: No more Descriptors available."); + reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x0003:// Get Next Selector Increment Value + reg_ax = 8; + DPMI_LOG("DPMI: 0003: Get Selector Inc Value: %04X",reg_ax); + DPMI_CALLBACK_SCF(false); + break; + case 0x0004:// undocumented (reserved) lock selector + case 0x0005:// undocumented (reserved) unlock selector + DPMI_LOG("DPMI: 0004: Undoc: (un)lock selector",reg_ax); + DPMI_CALLBACK_SCF(true); + break; + case 0x0006:{ // Get Segment Base Address + 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; + DPMI_CALLBACK_SCF(false); + } else { + DPMI_LOG_ERROR("DPMI: 0006: Invalid Selector: %04X",reg_bx); + reg_ax = DPMI_ERROR_INVALID_SELECTOR; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x0007:{// Set Segment base address + SetDescriptor desc; + if (cpu.gdt.GetDescriptor(reg_bx,desc)) { + Bitu base; + if (!dpmi.client.bit32) base = (reg_cl<<16)+reg_dx; + else base = (reg_cx<<16)+reg_dx; + desc.SetBase(base); + desc.Save (dpmi.ldt.base+(reg_bx & ~7)); + ReloadSegments(reg_bx); + DPMI_CALLBACK_SCF(false); + DPMI_LOG("DPMI: 0007: Set Base %04X : B:%08X",reg_bx,base); + } else { + DPMI_LOG_ERROR("DPMI: 0007: Invalid Selector: %04X",reg_bx); + reg_ax = DPMI_ERROR_INVALID_SELECTOR; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x0008:{// Set Segment limit + SetDescriptor desc; + 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); + reg_ax = DPMI_ERROR_INVALID_VALUE; + DPMI_CALLBACK_SCF(true); + } else if (cpu.gdt.GetDescriptor(reg_bx,desc)) { + desc.SetLimit((reg_cx<<16)+reg_dx); + desc.Save (dpmi.ldt.base+(reg_bx & ~7)); + ReloadSegments(reg_bx); + DPMI_CALLBACK_SCF(false); + DPMI_LOG("DPMI: 0008: Set Limit %08X",(reg_cx<<16)+reg_dx); + } else { + DPMI_LOG_ERROR("DPMI: 0008: Invalid Selector: %04X",reg_bx); + reg_ax = DPMI_ERROR_INVALID_SELECTOR; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x0009:{// Set Descriptor Access Rights + SetDescriptor desc; + Bit8u rcl = reg_cl; + Bit8u rch = reg_ch; + if (cpu.gdt.GetDescriptor(reg_bx,desc)) { + if (!SetAccessRights(reg_bx,desc,reg_cx)) { + DPMI_LOG_ERROR("DPMI: 0009: Set Rights %04X : failure",reg_bx); + reg_ax = DPMI_ERROR_INVALID_VALUE; + DPMI_CALLBACK_SCF(true); + break; + }; + desc.Save(dpmi.ldt.base+(reg_bx & ~7)); + ReloadSegments(reg_bx); + DPMI_CALLBACK_SCF(false); + DPMI_LOG("DPMI: 0009: Set Rights %04X : %04X",reg_bx,reg_cx); + } else { + DPMI_LOG_ERROR("DPMI: 0009: Set Rights %04X : invalid selector",reg_bx); + reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x000A:{// Create Alias Descriptor + Descriptor desc; + if (CreateAlias(reg_bx, reg_ax)) { + DPMI_LOG("DPMI: 000A: Create Alias : %04X - %04X",reg_bx,reg_ax); + DPMI_CALLBACK_SCF(false); + } else { + DPMI_CALLBACK_SCF(true); + DPMI_LOG_ERROR("DPMI: 000A: Invalid Selector: %04X",reg_bx); + }; }; break; + case 0x000B:{//Get Descriptor + SetDescriptor desc; + if (cpu.gdt.GetDescriptor(reg_bx,desc)) { + desc.Save(SegPhys(es)+Mask(reg_edi)); + DPMI_CALLBACK_SCF(false); + DPMI_LOG("DPMI: 000B: Get Descriptor %04X : B:%08X L:%08X",reg_bx,desc.GetBase(),desc.GetLimit()); + } else { + DPMI_LOG_ERROR("DPMI: 000B: Get Descriptor %04X : failure",reg_bx); + reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x000C:{//Set Descriptor + SetDescriptor desc; + if (cpu.gdt.GetDescriptor(reg_bx,desc)) { + desc.Load (SegPhys(es)+Mask(reg_edi)); + Bitu rights = (mem_readb(SegPhys(es)+Mask(reg_edi)+6)<<8) + mem_readb(SegPhys(es)+Mask(reg_edi)+5); + if (!SetAccessRights(reg_bx,desc,rights)) { + DPMI_LOG_ERROR("DPMI: 000C: Set Rights %04X : failure",reg_bx); + reg_ax = DPMI_ERROR_INVALID_VALUE; + DPMI_CALLBACK_SCF(true); + break; + }; + 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); + DPMI_CALLBACK_SCF(false); + } else { + DPMI_LOG_ERROR("DPMI: 000C: Set Descriptor %04X failed",reg_bx); + reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x000D:{ // Allocate specific LDT Descriptor : TODO: Support it + DPMI_LOG("DPMI: 000D: Alloc Specific LDT Selector: %04X",reg_bx); + SetDescriptor desc; + if (cpu.gdt.GetDescriptor(reg_bx,desc)) { +// if (!desc.saved.seg.p) { + desc.saved.seg.p = 1; +// desc.SetLimit(0xDEADAAAA); +// desc.SetBase (0xDEADBBBB); + desc.Save (dpmi.ldt.base+(reg_bx & ~7)); + DPMI_CALLBACK_SCF(false); + break; +// } else { +// DPMI_LOG_ERROR("DPMI: 000D: Invalid Selector: %04X",reg_bx); +// reg_ax = DPMI_ERROR_DESCRIPTOR_UNAVAILABLE; +// }; + } else reg_ax = DPMI_ERROR_INVALID_SELECTOR; + DPMI_CALLBACK_SCF(true); + }; break; + case 0x0100:{// Allocate DOS Memory Block + Bit16u blocks = reg_bx; + DPMI_LOG("DPMI: 0100: Allocate DOS Mem: (%04X Blocks)",blocks); + if (DOS_AllocateMemory(®_ax,&blocks)) { + // Allocate Selector for block + SetDescriptor desc; Bitu base; Bitu numDesc; + numDesc = reg_bx/0x1000 + ((reg_bx%0x1000)>0); + if (AllocateLDTDescriptor(numDesc,base)) { + reg_dx = base; + // First selector + if (numDesc>1) { + Bitu descBase = reg_ax*16; + Bitu length = reg_bx*16; + desc.Load (dpmi.ldt.base+(base & ~7)); + desc.SetBase (descBase); + desc.SetLimit(dpmi.client.bit32?length:0xFFFF); + desc.Save (dpmi.ldt.base+(base & ~7)); + for (Bitu i=1; i>4; + DOS_MCB mcb(seg-1); + Bitu size = mcb.GetSize()*16; + if (DOS_FreeMemory(seg)) { + while (size>0) { + desc.Load(dpmi.ldt.base+(sel & ~7)); + desc.saved.seg.p = 0; + desc.Save(dpmi.ldt.base+(sel & ~7)); + size -= (size>=0x10000)?0x10000:size; + sel+=8; + }; + DPMI_CALLBACK_SCF(false); + DPMI_LOG("DPMI: 0101: Free Dos Mem: %04X",reg_dx); + break; + } + } + DPMI_LOG_ERROR("DPMI: 0101: Invalid Selector: %04X",reg_bx); + reg_ax = DPMI_ERROR_INVALID_SELECTOR; + DPMI_CALLBACK_SCF(true); + };break; + case 0x0200:{// Get Real Mode Interrupt Vector + RealPt vec = RealGetVec(reg_bl); + reg_cx = RealSeg(vec); + reg_dx = RealOff(vec); + DPMI_LOG("DPMI: 0200: Get Real Int Vector %02X (%04X:%04X)",reg_bl,reg_cx,reg_dx); + DPMI_CALLBACK_SCF(false); + }; break; + case 0x0201:{// Set Real Mode Interrupt Vector + DPMI_LOG("DPMI: 0201: Set Real Int Vector %02X (%04X:%04X)",reg_bl,reg_cx,reg_dx); + RealSetVec(reg_bl,RealMake(reg_cx,reg_dx)); + DPMI_CALLBACK_SCF(false); + }; break; + case 0x0202:// Get Processor Exception Handler Vector + if (reg_bl>16; + reg_di = handle&0xFFFF; + reg_bx = linear>>16; + reg_cx = linear&0xFFFF; + DPMI_CALLBACK_SCF(false); + // TEMP +// Bitu total = MEM_FreeLargest(); // in KB +// DPMI_LOG_ERROR("DPMI: 0501: Allocation success: H:%04X%04X (%d KB) (R:%d KB)",reg_si,reg_di,length/1024 + ((length%1024)>0),total*4); + } else { + reg_ax = DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE; + DPMI_CALLBACK_SCF(true); + // TEMP + Bitu total = MEM_FreeLargest(); // in KB + DPMI_LOG("DPMI: 0501: Allocation failure (%d KB) (R:%d KB)",length/1024 + ((length%1024)>0),total*4); + }; + }; break; + case 0x0502://Free Memory Block + DPMI_LOG("DPMI: 0502: Free Mem: H:%04X%04X",reg_si,reg_di); + MEM_ReleasePages((reg_si<<16)+reg_di); + FreeXMSHandle((reg_si<<16)+reg_di); + DPMI_CALLBACK_SCF(false); + break; + case 0x0503:{//Resize Memory Block + Bitu linear,newHandle; + Bitu newByte = (reg_bx<<16)+reg_cx; + Bitu newSize = (newByte/DPMI_PAGE_SIZE)+((newByte & (DPMI_PAGE_SIZE-1))>0); + MemHandle handle = (reg_si<<16)+reg_di; + 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; + 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; + // copy contents + Bitu size = MEM_AllocatedPages(handle); + if (newSize>16; + reg_cx = linear & 0xFFFF; + DPMI_LOG_ERROR("DPMI: 0800: Phys-adr-map not supported : Start:%08X (Size:%08X) - Linear:%08X.",phys,size,linear); + DPMI_CALLBACK_SCF(false); + }; break; + case 0x0801:// Free physical address mapping + DPMI_LOG("DPMI: 0801: Free physical address mapping"); + DPMI_CALLBACK_SCF(false); + break; + case 0x0900://Get and Disable Virtual Interrupt State + reg_al = dpmi.vIntFlag; + dpmi.vIntFlag = 0; + DPMI_LOG("DPMI: 0900: Get and disbale vi : %01X",reg_al); + DPMI_CALLBACK_SCF(false); + break; + case 0x0901://Get and Enable Virtual Interrupt State + reg_al = dpmi.vIntFlag; + dpmi.vIntFlag = 1; + DPMI_LOG("DPMI: 0901: Get and enable vi : %01X",reg_al); + DPMI_CALLBACK_SCF(false); + break; + case 0x0902:{//Get Virtual Interrupt State + reg_al = 0; //dpmi.vIntFlag; + DPMI_LOG("DPMI: 0902: Get vi : %01X",reg_al); + DPMI_CALLBACK_SCF(false); + }; break; + case 0x0A00:{//Get Vendor Specific API Entry Point + char name[256]; + MEM_StrCopy(SegPhys(ds)+Mask(reg_esi),name,255); + LOG(LOG_MISC,LOG_WARN)("DPMI: Get API: %s",name); + if (strcmp(name,"MS-DOS")==0) { + CPU_SetSegGeneral(es,GDT_PROTCODE); + if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; + else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; + API_Init_MSDOS(); + DPMI_CALLBACK_SCF(false); + } else if (strstr(name,"HWINT_SUPPORT")!=0) { + reg_ax = DPMI_ERROR_UNSUPPORTED; + DPMI_CALLBACK_SCF(true); + } else if (strstr(name,"CE_SUPPORT")!=0) { + reg_ax = DPMI_ERROR_UNSUPPORTED; + DPMI_CALLBACK_SCF(true); + } else if (strstr(name,"PHARLAP")!=0) { + CPU_SetSegGeneral(es,GDT_PROTCODE); + if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; + else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; + API_Init_MSDOS(); + DPMI_CALLBACK_SCF(false); + dpmi.pharlap = true; + } else { + reg_ax = DPMI_ERROR_UNSUPPORTED; + DPMI_CALLBACK_SCF(true); + } + }; break; + case 0x0D00:{//Allocate Shared Memory + char name[256]; + PhysPt data = SegPhys(es)+Mask(reg_edi); + Bitu length = mem_readd(data); + Bitu pages = (length/DPMI_PAGE_SIZE)+((length%DPMI_PAGE_SIZE)>0); + Bitu handle = mem_readd(data+0x08); + Bitu linear = mem_readd(data+0x0C); + Bitu strOffset = mem_readd(data+0x10); + Bitu strSelect = mem_readw(data+0x14); + + Descriptor desc; + if (!cpu.gdt.GetDescriptor(strSelect,desc)) { + DPMI_LOG_ERROR("DPMI: 0D00: shared memory: invalid name selector"); + reg_ax = DPMI_ERROR_INVALID_VALUE; + DPMI_CALLBACK_SCF(true); + return false; + }; + MEM_StrCopy(desc.GetBase()+strOffset,name,256); + + // Already allocated ? + if (!GetSharedMem(name,handle,pages)) { + if (!AllocateMem(length,handle,linear)) { + DPMI_LOG_ERROR("DPMI: 0D00: Allocation shared failure %s (%d KB)",name,pages*4); + reg_ax = DPMI_ERROR_PHYSICAL_MEMORY_UNAVAILABLE; + DPMI_CALLBACK_SCF(true); + break; + }; + // Init first paragraph with zeros + for (Bitu i=0; i<16; i++) mem_writeb(linear+i,0); + SetSharedMem(name,handle,pages); + DPMI_LOG("DPMI: 0D00: Allocate shared memory %s (%d KB) ",name,pages*4); + } else { + linear = handle*DPMI_PAGE_SIZE; + DPMI_LOG("DPMI: 0D00: Reuse shared memory %s (%d KB) ",name,pages*4); + }; + + mem_writed(data+0x04,pages*DPMI_PAGE_SIZE); + mem_writed(data+0x08,handle); + mem_writed(data+0x0C,linear); + DPMI_CALLBACK_SCF(false); + }; break; + case 0x0B00:// Set debug watchpoint + case 0x0B01:// Clear debug watchpoint + DPMI_CALLBACK_SCF(true); + break; + case 0x0E00:// Get Coprocessor Status + DPMI_LOG("DPMI: 0E00: Get Coprocessor status"); + reg_ax = 0x45; // nope, no coprocessor + DPMI_CALLBACK_SCF(false); + break; + case 0x0E01:// Set Coprocessor Emulation + DPMI_LOG("DPMI: 0E01: Set Coprocessor emulation"); + DPMI_CALLBACK_SCF(true); // failure + break; + default :LOG(LOG_MISC,LOG_ERROR)("DPMI: Unsupported func %04X",reg_ax); + reg_ax = DPMI_ERROR_UNSUPPORTED; + DPMI_CALLBACK_SCF(true); // failure + break; + }; + return 0; +} + +Bitu DPMI::Int2fHandler(void) +{ + // Only available in ProtectedMode + // LOG(LOG_MISC,LOG_WARN)("DPMI: 0x2F %04x",reg_ax); + switch (reg_ax) { + case 0x1686: /* Get CPU Mode */ + reg_ax = 0; + break; + case 0x168A: // Only available in protected mode + // Get Vendor-Specific API Entry Point + char name[256]; + MEM_StrCopy(SegPhys(ds)+Mask(reg_esi),name,255); + LOG(LOG_MISC,LOG_WARN)("DPMI: 0x2F 0x168A: Get Specific API :%s",name); + if (strcmp(name,"MS-DOS")==0) { + CPU_SetSegGeneral(es,GDT_PROTCODE); + if (dpmi.client.bit32) reg_edi = DPMI_CB_APIMSDOSENTRY_OFFSET; + else reg_di = DPMI_CB_APIMSDOSENTRY_OFFSET; + reg_al = 0x00; // Success, whatever they want... + API_Init_MSDOS(); + }; + break; + default : // reflect to real + ptorHandler(); + break; + } + return 0; +}; + +// ********************************************************************* +// Callbacks and Callback-Returns +// ********************************************************************* + +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_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;}; +static Bitu DPMI_ptorHandler(void) { if (activeDPMI) return activeDPMI->ptorHandler(); return 0;}; +static Bitu DPMI_ptorHandlerReturn(void) { if (activeDPMI) return activeDPMI->ptorHandlerReturn(); return 0;}; +static Bitu DPMI_Int21Handler(void) { if (activeDPMI) return activeDPMI->Int21Handler(); return 0;}; +static Bitu DPMI_Int21HandlerReturn(void) { if (activeDPMI) return activeDPMI->Int21HandlerReturn(); return 0;}; +static Bitu DPMI_HWIntDefaultHandler(void) { if (activeDPMI) return activeDPMI->HWIntDefaultHandler(); return 0;}; +static Bitu DPMI_EnterProtMode(void) { if (activeDPMI) return activeDPMI->EnterProtMode(); return 0;}; +static Bitu DPMI_EnterRealMode(void) { if (activeDPMI) return activeDPMI->EnterRealMode(); return 0;}; +static Bitu DPMI_RealSaveState(void) { if (activeDPMI) return activeDPMI->RealSaveState(); return 0;}; +static Bitu DPMI_ProtSaveState(void) { if (activeDPMI) return activeDPMI->ProtSaveState(); return 0;}; +static Bitu DPMI_Int2fHandler(void) { if (activeDPMI) return activeDPMI->Int2fHandler(); return 0;}; +static Bitu DPMI_Int31Handler(void) { if (activeDPMI) return activeDPMI->Int31Handler(); return 0;}; +static Bitu DPMI_API_Int21_MSDOS(void) { if (activeDPMI) return activeDPMI->API_Int21_MSDOS(); return 0;}; +static Bitu DPMI_API_Entry_MSDOS(void) { if (activeDPMI) return activeDPMI->API_Entry_MSDOS(); return 0;}; + + +// **************************************************************** +// Setup stuff +// **************************************************************** + +RealPt DPMI::HookInterrupt(Bitu num, Bitu intHandler) +{ + // Setup realmode hook + RealPt oldVec; + Bitu segment, offset; + // Allocate Realmode callback + RealPt func = CALLBACK_RealPointer(intHandler); + if (AllocateRealModeCallback(GDT_CODE,RealOff(func),0x0000,0x0000,segment,offset)) { + oldVec = RealGetVec(num); + RealSetVec(num,RealMake(segment,offset)); + } 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); + return oldVec; +} + +void DPMI::RestoreHookedInterrupt(Bitu num, RealPt oldVec) +{ + //.Restore hooked int + RealSetVec(num,oldVec); + RealPt func = CALLBACK_RealPointer(callback.ptorint); + SetDescriptor gate; + gate.Load (dpmi.idt.base+num*8); + gate.SetSelector(GDT_CODE); + gate.SetOffset (RealOff(func)); + gate.Save (dpmi.idt.base+num*8); +} + +void DPMI::Debug_ShowDescriptors(void) +{ + char out1[512]; + SetDescriptor desc; + Bitu i=0; + PhysPt address = dpmi.ldt.base; + while (iRemoveIntCallbacks(); + } + activeDPMI = new DPMI(); + return activeDPMI->Entrypoint(); +} + +Bitu DPMI::Entrypoint(void) +{ + /* This should switch to pmode */ + if (dpmi.client.have) E_Exit("DPMI:Already have a client"); + + LOG(LOG_MISC,LOG_ERROR)("DPMI: Entrypoint (%d Bit)",(reg_ax & 1) ? 32:16); + + MEM_A20_Enable(true); + // Create gdt, ldt, idt and other stuff + Setup(); + + // Save Realmode Registers + SaveRegisterState(0); + + dpmi.client.have = true; + dpmi.client.bit32 = reg_ax & 1; + + // Clear XMS Handles + ClearXMSHandles(); + /* Clear the LDT */ + Bitu i; + for (i=0;i::iterator i; + for(i=g_sharedMemList.begin(); i != g_sharedMemList.end(); i++) + delete static_cast(*i); + (g_sharedMemList.clear)(); +}; + +void DPMI_Init(Section* sec) +{ + Section_prop * section=static_cast(sec); + if (!section->Get_bool("dpmi")) return; + + memset(&callback,0,sizeof(callback)); + + /* setup Real mode Callbacks */ + callback.entry=CALLBACK_Allocate(); + CALLBACK_Setup(callback.entry,DPMI_EntryPoint,CB_RETF); + callback.enterpmode=CALLBACK_Allocate(); + CALLBACK_Setup(callback.enterpmode,DPMI_EnterProtMode,CB_RETF); + callback.realsavestate=CALLBACK_Allocate(); + CALLBACK_Setup(callback.realsavestate,DPMI_RealSaveState,CB_RETF); + callback.simint=CALLBACK_Allocate(); + CALLBACK_Setup(callback.simint,DPMI_SimulateInt,CB_IRET); + callback.simintReturn=CALLBACK_Allocate(); + CALLBACK_Setup(callback.simintReturn,DPMI_SimulateIntReturn,CB_IRET); + callback.rmIntFrame=CALLBACK_Allocate(); + CALLBACK_Setup(callback.rmIntFrame,DPMI_CallRealIRETFrame,CB_IRET); + callback.rmIntFrameReturn=CALLBACK_Allocate(); + CALLBACK_Setup(callback.rmIntFrameReturn,DPMI_CallRealIRETFrameReturn,CB_IRET); + callback.ptorint=CALLBACK_Allocate(); + CALLBACK_Setup(callback.ptorint,DPMI_ptorHandler,CB_IRET); + callback.ptorintReturn=CALLBACK_Allocate(); + CALLBACK_Setup(callback.ptorintReturn,DPMI_ptorHandlerReturn,CB_IRET); + callback.int21Return=CALLBACK_Allocate(); + CALLBACK_Setup(callback.int21Return,DPMI_Int21HandlerReturn,CB_IRET); + callback.rmCallbackReturn=CALLBACK_Allocate(); + CALLBACK_Setup(callback.rmCallbackReturn,DPMI_RealModeCallbackReturn,CB_IRET); + callback.int21msdos=CALLBACK_Allocate(); + CALLBACK_Setup(callback.int21msdos,DPMI_API_Int21_MSDOS,CB_IRET); + + /* Setup multiplex */ + DOS_AddMultiplexHandler(DPMI_Multiplex); + + /* shutdown function */ + sec->AddDestroyFunction(&DPMI_ShutDown); +} + +void DPMI::Reactivate() +{ + /* Load GDT and IDT */ + CPU_LIDT(dpmi.idt.limit,dpmi.idt.base); + CPU_LGDT(dpmi.gdt.limit,dpmi.gdt.base); + CPU_LLDT(GDT_LDT); + cpu.cpl = DPMI_DPL; + RestoreIntCallbacks(); +}; + +void DPMI::Setup() +{ + Bitu i; + Bitu xmssize = (TOTAL_SIZE|(DPMI_PAGE_SIZE-1))+1; + Bitu protStackSize = ((DPMI_PROTMODE_STACK_MAX*DPMI_PROTMODE_STACKSIZE)|(DPMI_PAGE_SIZE-1))+1; + Bitu numPages = ((xmssize+protStackSize) >> 12); + +#if DPMI_ALLOC_NEEDEDMEM_HIGH + // Allocate the GDT,LDT,IDT Stack space (High Mem) + Bitu max = MEM_FreeLargest(); + Bitu temphandle = MEM_AllocatePages(max-numPages,true); + dpmi.mem_handle = MEM_AllocatePages(numPages,true); + if (dpmi.mem_handle==0) { + LOG_MSG("DPMI:Can't allocate XMS memory, disabling dpmi support."); + return; + } + Bitu address = dpmi.mem_handle*DPMI_PAGE_SIZE;; + MEM_ReleasePages(temphandle); +#else + // load LDT and stuff in low mem ( + Bit16u segment; + Bit16u blocks = numPages*4096/16; + if (!DOS_AllocateMemory(&segment,&blocks)) { + LOG_MSG("DPMI:Can't allocate XMS memory, disabling dpmi support."); + return; + }; + Bitu address = segment * 16; +#endif + // Allocate real mode stack space + rm_ss = DOS_GetMemory(DPMI_REALMODE_STACKSIZE/16); + rm_sp = DPMI_REALMODE_STACKSIZE; + // Get Begin of protected mode stack + dpmi.protStack = address + xmssize; + /* Clear the memory */ + PhysPt w; + for (w=address;w0); // Convert to 4KB pages + Bitu maxPages = MEM_FreeLargest(); + if (maxPages0xFFFFF) || (base & 0x0F)) E_Exit("DPMI:MSDOS: Invalid Selector (convert to segment not possible)"); + base >>= 4; + } else E_Exit("DPMI:MSDOS: Invalid Selector (not found)"); + return base; +}; + +bool DPMI::GetMsdosSelector(Bitu realseg, Bitu realoff, Bitu &protsel, Bitu &protoff) +{ + // Check if selector is already in list + for (Bitu i=0; i0xFFFF) E_Exit("DPMI:DOS: Read file size > 0xffff"); + + Bit16u toread = Mask(reg_ecx); + dos.echo = true; + if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { + MEM_BlockWrite(SegPhys(ds)+Mask(reg_edx),dos_copybuf,toread); + if (dpmi.client.bit32) reg_eax=toread; else reg_ax=toread; +// LOG(LOG_MISC,LOG_ERROR)("READ FILE Handle:%d Size:%d Read:%d",reg_bx,toread,reg_eax); + DPMI_CALLBACK_SCF(false); + + } else { + LOG(LOG_MISC,LOG_ERROR)("DOS: Read file %d failed",reg_bx); + reg_ax=dos.errorcode; + DPMI_CALLBACK_SCF(true); + } + dos.echo=false; + break; + } + case 0x40: {/* WRITE Write to file or device */ + Bit16u towrite = Mask(reg_ecx); + MEM_BlockRead(SegPhys(ds)+Mask(reg_edx),dos_copybuf,towrite); +// if (reg_bx<=5) LOG(LOG_MISC,LOG_ERROR)("INT 21 40: %s",(char *)dos_copybuf); + if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) { + if (dpmi.client.bit32) reg_eax=towrite; + else reg_ax =towrite; + DPMI_CALLBACK_SCF(false); + } else { + DPMI_LOG("DPMI:MSDOS:Write %d file failure.",reg_bx); + reg_ax=dos.errorcode; + DPMI_CALLBACK_SCF(true); + } + }; break; + case 0x41: { /* UNLINK Delete file */ + char name1[256]; + MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); + if (DOS_UnlinkFile(name1)) { + DPMI_CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + DPMI_CALLBACK_SCF(true); + } + }; break; + case 0x42: /* LSEEK Set current file position */ + { + Bit32u pos=(reg_cx<<16) + reg_dx; + Bit32u topos = pos; + if (DOS_SeekFile(reg_bx,&pos,reg_al)) { + reg_dx=(Bit16u)(pos >> 16); + reg_ax=(Bit16u)(pos & 0xFFFF); + DPMI_CALLBACK_SCF(false); + if ((reg_al==0) && (topos!=pos)) { + LOG(LOG_MISC,LOG_ERROR)("SEEK FILE Handle:%d Seek:%d Pos:%d",reg_bx,topos,pos); + LOG(LOG_MISC,LOG_ERROR)("SEEK FILE ERROR : Pos differs"); + } + } else { + LOG(LOG_MISC,LOG_ERROR)("DOS: Seek file %d failed",reg_bx); + reg_ax=dos.errorcode; + DPMI_CALLBACK_SCF(true); + } + break; + } + case 0x43: { /* Get/Set file attributes */ + char name1[256]; + MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); + switch (reg_al) + case 0x00: /* Get */ + { + if (DOS_GetFileAttr(name1,®_cx)) { + DPMI_CALLBACK_SCF(false); + } else { + DPMI_CALLBACK_SCF(true); + reg_ax=dos.errorcode; + } + break; + case 0x01: /* Set */ + DPMI_LOG("DOS:Set File Attributes for %s not supported",name1); + DPMI_CALLBACK_SCF(false); + break; + default: + E_Exit("DOS:0x43:Illegal subfunction %2X",reg_al); + } + }; break; + + case 0x47: { /* CWD Get current directory */ + char name1[256]; + if (DOS_GetCurrentDir(reg_dl,name1)) { + MEM_BlockWrite(SegPhys(ds)+Mask(reg_esi),name1,strlen(name1)+1); + LOG(LOG_MISC,LOG_ERROR)("DOS: Get Dir %s ",name1); + reg_ax=0x0100; + CALLBACK_SCF(false); + } else { + LOG(LOG_MISC,LOG_ERROR)("DOS: Get Dir failed %s ",name1); + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + } + }; break; + + case 0x4E: {/* Get first dir entry */ + char name1[256]; + MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,255); + if (DOS_FindFirst(name1,reg_cx)) { + LOG(LOG_MISC,LOG_ERROR)("DOS: Find Dir entry %s success",name1); + DPMI_CALLBACK_SCF(false); + // Copy result to internal dta + if (dtaAddress) MEM_BlockCopy(dtaAddress,PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dpmi.pharlap?43:128); + reg_ax=0; /* Undocumented */ + } else { + LOG(LOG_MISC,LOG_ERROR)("DOS: Find Dir entry %s failure",name1); + reg_ax=dos.errorcode; + DPMI_CALLBACK_SCF(true); + }; + }; break; + case 0x4f: /* FINDNEXT Find next matching file */ + // Copy data to dos dta + if (dtaAddress) MEM_BlockCopy(PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dtaAddress,dpmi.pharlap?43:128); + if (DOS_FindNext()) { + LOG(LOG_MISC,LOG_ERROR)("DOS: FindNext Dir entry success"); + CALLBACK_SCF(false); + // Copy result to internal dta + if (dtaAddress) MEM_BlockCopy(dtaAddress,PhysMake(RealSeg(dos.dta),RealOff(dos.dta)),dpmi.pharlap?43:128); + reg_ax=0xffff; /* Undocumented */ + } else { + LOG(LOG_MISC,LOG_ERROR)("DOS: FindNext Dir entry failure"); + reg_ax=dos.errorcode; + CALLBACK_SCF(true); + }; + break; + case 0x50: /* Set current PSP */ + if (dpmi.pharlap) dos.psp = reg_bx; // pharlap uses real mode paragraph address + else + dos.psp = GetSegmentFromSelector(reg_bx); + DPMI_LOG("DPMI:MSDOS:0x50:Set current psp:%04X",reg_bx); + break; + case 0x51: /* Get current PSP */ + if (dpmi.pharlap) reg_bx = dos.psp; // pharlap uses real mode paragraph address + else { + GetMsdosSelector(dos.psp,0x0000,protsel,protoff); + reg_bx = protsel; + }; + DPMI_LOG("DPMI:MSDOS:0x51:Get current psp:%04X",reg_bx); + break; + case 0x55 : { // Neuen PSP erstellen + Bitu segment = GetSegmentFromSelector(reg_dx); + DOS_ChildPSP(segment,reg_si); + dos.psp = segment; + DPMI_LOG("DPMI:MSDOS:0x55:Create new psp:%04X",segment); + }; break; + case 0x56: { /* RENAME Rename file */ + char name1[256+1]; + char name2[256+1]; + MEM_StrCopy(SegPhys(ds)+Mask(reg_edx),name1,256); + MEM_StrCopy(SegPhys(es)+Mask(reg_edi),name2,256); + if (DOS_Rename(name1,name2)) { + DPMI_CALLBACK_SCF(false); + } else { + reg_ax=dos.errorcode; + DPMI_CALLBACK_SCF(true); + } + }; break; + case 0x5D : // Get Address of dos swappable area + // FIXME: This is totally faked... + // FIXME: Add size in bytes (at least pharlap) + // FIXME: Depending on al, two functions (pharlap) + GetMsdosSelector(0xDEAD,0xDEAD,protsel,protoff); + CPU_SetSegGeneral(ds,protsel); + reg_si = protoff; + DPMI_LOG("DPMI:MSDOS:0x5D:Get Addres of DOS SwapArea:%04X",reg_si); + break; + case 0x62 : /* Get Current PSP Address */ + GetMsdosSelector(dos.psp,0x0000,protsel,protoff); + reg_bx = protsel; + DPMI_LOG("DPMI:MSDOS:0x62:Get current psp:%04X",reg_bx); + break; + case 0x68: // Flush file to disc + DPMI_CALLBACK_SCF(false); + break; + + case 0x09: + case 0x0A: + case 0x0C: + case 0x1B: + case 0x1C: + case 0x26: // Pharlap != MS-DOS +// case 0x30: // Pharlap extended information + case 0x31: + case 0x32: + case 0x3A: + case 0x48: // Pharlap = 4KB mem pages + case 0x49: + case 0x4A: // Pharlap = 4KB mem pages + case 0x4B: + case 0x52: + case 0x53: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5E: + case 0x5F: + case 0x60: +// case 0x62: + case 0x65: + case 0x6C: + E_Exit("DPMI:MSDOS-API:function %04X not yet supported.",reg_ax); + break; + + // *** PASS THROUGH *** + case 0x44: if ((reg_al==0x02) || (reg_al==0x03) || (reg_al==0x04) || (reg_al==0x05) || (reg_al==0x0C) || (reg_al==0x0D)) { + E_Exit("DPMI:MSDOS-API:function %04X not yet supported.",reg_ax); + }; + case 0x07: case 0x0B: case 0x0E: case 0x19: case 0x2A: case 0x2C: case 0x2D: case 0x30: + case 0x36: case 0x3E: case 0x4C: case 0x58: case 0x67: + { + // reflect to real mode + DPMI_Int21Handler(); + }; + break; + default: E_Exit("DPMI:MSDOS-API:Missing function %04X",reg_ax); + + }; + return 0; +}; + + diff --git a/src/ints/ems.cpp b/src/ints/ems.cpp index 78ba177..de226fd 100644 --- a/src/ints/ems.cpp +++ b/src/ints/ems.cpp @@ -22,6 +22,7 @@ #include "dosbox.h" #include "callback.h" #include "mem.h" +#include "paging.h" #include "bios.h" #include "keyboard.h" #include "regs.h" @@ -29,11 +30,10 @@ #include "dos_inc.h" #include "setup.h" -#define EMM_USEHANDLER 1 - #define EMM_PAGEFRAME 0xE000 -#define EMM_MAX_HANDLES 50 /* 255 Max */ -#define EMM_PAGE_SIZE (16*1024) +#define EMM_PAGEFRAME4K ((EMM_PAGEFRAME*16)/4096) +#define EMM_MAX_HANDLES 100 /* 255 Max */ +#define EMM_PAGE_SIZE (16*1024U) #define EMM_MAX_PAGES (32 * 1024 / 16 ) #define EMM_MAX_PHYS 4 /* 4 16kb pages in pageframe */ @@ -67,7 +67,7 @@ public: device_EMM(){name="EMMXXXX0";} bool Read(Bit8u * data,Bit16u * size) { return false;} bool Write(Bit8u * data,Bit16u * size){ - LOG(LOG_IOCTL,"EMS:Write to device"); + LOG(LOG_IOCTL,LOG_NORMAL)("EMS:Write to device"); return false; } bool Seek(Bit32u * pos,Bit32u type){return false;} @@ -82,26 +82,17 @@ struct EMM_Mapping { Bit16u page; }; -struct EMM_Page { - HostPt memory; - Bit16u handle; - Bit16u next; -}; - struct EMM_Handle { - Bit16u first_page; Bit16u pages; + MemHandle mem; char name[8]; bool saved_page_map; EMM_Mapping page_map[EMM_MAX_PHYS]; }; static EMM_Handle emm_handles[EMM_MAX_HANDLES]; -static EMM_Page emm_pages[EMM_MAX_PAGES]; static EMM_Mapping emm_mappings[EMM_MAX_PHYS]; -static HostPt emm_pagebase[EMM_MAX_PHYS]; -static Bitu emm_page_count; -Bitu call_int67; +static Bitu call_int67; struct MoveRegion { Bit32u bytes; @@ -115,26 +106,10 @@ struct MoveRegion { Bit16u dest_page_seg; }; -#if EMM_USEHANDLER -Bit8u EMM_ReadHandler(PhysPt start) { - start-=EMM_PAGEFRAME * 16; - Bitu page=start>>14; - return readb(emm_pagebase[page]+(start&0x3fff)); -} - -void EMM_WriteHandler(PhysPt start,Bit8u val) { - start-=EMM_PAGEFRAME * 16; - Bitu page=start>>14; - writeb(emm_pagebase[page]+(start&0x3fff),val); -} -#endif - static Bit16u EMM_GetFreePages(void) { - Bit16u count=0; - for (Bitu index=0;index0x7fff) count=0x7fff; + return (Bit16u)count; } static bool INLINE ValidHandle(Bit16u handle) { @@ -147,118 +122,47 @@ static Bit8u EMM_AllocateMemory(Bit16u pages,Bit16u & handle) { /* Check for 0 page allocation */ if (!pages) return EMM_ZERO_PAGES; /* Check for enough free pages */ - if (EMM_GetFreePages()=EMM_MAX_HANDLES) {handle=NULL_HANDLE;return EMM_OUT_OF_HANDLES;} } - /* Allocate the pages */ - Bit16u page=0;Bit16u last=NULL_PAGE; + MemHandle mem=MEM_AllocatePages(pages*4,false); + if (!mem) E_Exit("EMS:Memory allocation failure"); emm_handles[handle].pages=pages; - while (pages) { - if (emm_pages[page].handle==NULL_HANDLE) { - emm_pages[page].handle=handle; - emm_pages[page].memory=(HostPt)malloc(EMM_PAGE_SIZE); - if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory"); - if (last!=NULL_PAGE) emm_pages[last].next=page; - else emm_handles[handle].first_page=page; - last=page; - pages--; - } else { - if (++page>=emm_page_count) E_Exit("EMM:Ran out of pages"); - } - } + emm_handles[handle].mem=mem; return EMM_NO_ERROR; } static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) { /* Check for valid handle */ - if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE; + if (!ValidHandle(handle)) return EMM_INVALID_HANDLE; /* Check for enough pages */ - if ((emm_handles[handle].pages+EMM_GetFreePages())0 && page_count>0) { - if (emm_pages[page].handle!=handle) E_Exit("EMM:Error illegal handle reference"); - last=page; - page=emm_pages[page].next; - pages--; - page_count--; - } - /* Free the rest of the handles */ - if (page_count && !pages) { - emm_handles[handle].pages-=page_count; - while (page_count>0) { - free(emm_pages[page].memory); - emm_pages[page].memory=0; - emm_pages[page].handle=NULL_HANDLE; - Bit16u next_page=emm_pages[page].next; - emm_pages[page].next=NULL_PAGE; - page=next_page;page_count--; - } - pages=emm_handles[handle].pages; - if (!pages) emm_handles[handle].first_page=NULL_PAGE; - return EMM_NO_ERROR; - } - if (!page_count && pages) { - /* Allocate extra pages */ - emm_handles[handle].pages+=pages; - page=0; - while (pages) { - if (emm_pages[page].handle==NULL_HANDLE) { - emm_pages[page].handle=handle; - emm_pages[page].memory=(HostPt)malloc(EMM_PAGE_SIZE); - if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory"); - if (last!=NULL_PAGE) emm_pages[last].next=page; - else emm_handles[handle].first_page=page; - last=page; - pages--; - } else { - if (++page>=emm_page_count) E_Exit("EMM:Ran out of pages"); - } - } - pages=emm_handles[handle].pages; - return EMM_NO_ERROR; - } - /* Size exactly the same as the original size */ - pages=emm_handles[handle].pages; + if (!MEM_ReAllocatePages(emm_handles[handle].mem,pages*4,false)) return EMM_OUT_OF_LOG; + /* Update size */ + emm_handles[handle].pages=pages; return EMM_NO_ERROR; } static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) { +// LOG_MSG("EMS MapPage handle %d phys %d log %d",handle,phys_page,log_page); /* Check for too high physical page */ if (phys_page>=EMM_MAX_PHYS) return EMM_ILL_PHYS; /* Check for valid handle */ - if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE; + if (!ValidHandle(handle)) return EMM_INVALID_HANDLE; /* Check to do unmapping or mappning */ if (log_page=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE; - Bit16u page=emm_handles[handle].first_page; - Bit16u pages=emm_handles[handle].pages; - while (pages) { - free(emm_pages[page].memory); - emm_pages[page].memory=0; - emm_pages[page].handle=NULL_HANDLE; - Bit16u next_page=emm_pages[page].next; - emm_pages[page].next=NULL_PAGE; - page=next_page;pages--; - } + if (!ValidHandle(handle)) return EMM_INVALID_HANDLE; + MEM_ReleasePages(emm_handles[handle].mem); /* Reset handle */ - emm_handles[handle].first_page=NULL_PAGE; + emm_handles[handle].mem=0; emm_handles[handle].pages=NULL_HANDLE; emm_handles[handle].saved_page_map=false; memset(&emm_handles[handle].name,0,8); @@ -346,7 +241,8 @@ static Bit8u EMM_PartialPageMapping(void) { mem_writew(data,count);data+=2; for (;count>0;count--) { Bit16u page=mem_readw(list);list+=2; - if (page>=EMM_MAX_PHYS) return EMM_ILL_PHYS; + if ((page=EMM_PAGEFRAME+0x1000)) return EMM_ILL_PHYS; + page = (page-EMM_PAGEFRAME) / (EMM_PAGE_SIZE>>4); mem_writew(data,page);data+=2; MEM_BlockWrite(data,&emm_mappings[page],sizeof(EMM_Mapping)); data+=sizeof(EMM_Mapping); @@ -367,7 +263,7 @@ static Bit8u EMM_PartialPageMapping(void) { reg_al=2+reg_bx*(2+sizeof(EMM_Mapping)); break; default: - LOG(LOG_ERROR|LOG_MISC,"EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); + LOG(LOG_MISC,LOG_ERROR)("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); return EMM_FUNC_NOSUP; } return EMM_NO_ERROR; @@ -404,7 +300,7 @@ static Bit8u HandleNameSearch(void) { reg_bx=EMM_MAX_HANDLES; break; default: - LOG(LOG_ERROR|LOG_MISC,"EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); + LOG(LOG_MISC,LOG_ERROR)("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); return EMM_FUNC_NOSUP; } return EMM_NO_ERROR; @@ -422,7 +318,7 @@ static Bit8u GetSetHandleName(void) { MEM_BlockRead(SegPhys(es)+reg_di,emm_handles[handle].name,8); break; default: - LOG(LOG_ERROR|LOG_MISC,"EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); + LOG(LOG_MISC,LOG_ERROR)("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); return EMM_FUNC_NOSUP; } return EMM_NO_ERROR; @@ -446,55 +342,52 @@ static void LoadMoveRegion(PhysPt data,MoveRegion & region) { static Bit8u MemoryRegion(void) { MoveRegion region; - Bit8u buf_src[EMM_PAGE_SIZE]; - Bit8u buf_dest[EMM_PAGE_SIZE]; + Bit8u buf_src[MEM_PAGE_SIZE]; + Bit8u buf_dest[MEM_PAGE_SIZE]; if (reg_al>1) { - LOG(LOG_ERROR|LOG_MISC,"EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); + LOG(LOG_MISC,LOG_ERROR)("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); return EMM_FUNC_NOSUP; } LoadMoveRegion(SegPhys(ds)+reg_si,region); -/* Parse the region for information */ + /* Parse the region for information */ PhysPt src_mem,dest_mem; - Bit16u src_page,dest_page;Bitu src_off,dest_off;Bitu src_remain,dest_remain; + MemHandle src_handle,dest_handle; + Bitu src_off,dest_off;Bitu src_remain,dest_remain; if (!region.src_type) { src_mem=region.src_page_seg*16+region.src_offset; } else { if (!ValidHandle(region.src_handle)) return EMM_INVALID_HANDLE; - if (emm_handles[region.src_handle].pages*EMM_PAGE_SIZE < (region.src_page_seg*EMM_PAGE_SIZE)+region.src_offset+region.bytes) return EMM_LOG_OUT_RANGE; - src_page=emm_handles[region.src_handle].first_page; - while (region.src_page_seg>0) { - src_page=emm_pages[src_page].next; - region.src_page_seg--; - } - src_off=region.src_offset; - src_remain=EMM_PAGE_SIZE-src_off; + if ((emm_handles[region.src_handle].pages*EMM_PAGE_SIZE) < ((region.src_page_seg*EMM_PAGE_SIZE)+region.src_offset+region.bytes)) return EMM_LOG_OUT_RANGE; + src_handle=emm_handles[region.src_handle].mem; + Bitu pages=region.src_page_seg*4+(region.src_offset/MEM_PAGE_SIZE); + for (;pages>0;pages--) src_handle=MEM_NextHandle(src_handle); + src_off=region.src_offset&(MEM_PAGE_SIZE-1); + src_remain=MEM_PAGE_SIZE-src_off; } if (!region.dest_type) { dest_mem=region.dest_page_seg*16+region.dest_offset; } else { if (!ValidHandle(region.dest_handle)) return EMM_INVALID_HANDLE; if (emm_handles[region.dest_handle].pages*EMM_PAGE_SIZE < (region.dest_page_seg*EMM_PAGE_SIZE)+region.dest_offset+region.bytes) return EMM_LOG_OUT_RANGE; - dest_page=emm_handles[region.dest_handle].first_page; - while (region.dest_page_seg>0) { - dest_page=emm_pages[dest_page].next; - region.dest_page_seg--; - } - dest_off=region.dest_offset; - dest_remain=EMM_PAGE_SIZE-dest_off; + dest_handle=emm_handles[region.dest_handle].mem; + Bitu pages=region.dest_page_seg*4+(region.dest_offset/MEM_PAGE_SIZE); + for (;pages>0;pages--) dest_handle=MEM_NextHandle(dest_handle); + dest_off=region.dest_offset&(MEM_PAGE_SIZE-1); + dest_remain=MEM_PAGE_SIZE-dest_off; } Bitu toread; while (region.bytes>0) { - if (region.bytes>EMM_PAGE_SIZE) toread=EMM_PAGE_SIZE; + if (region.bytes>MEM_PAGE_SIZE) toread=MEM_PAGE_SIZE; else toread=region.bytes; /* Read from the source */ if (!region.src_type) { MEM_BlockRead(src_mem,buf_src,toread); } else { if (toread(sec); - Bitu size=section->Get_int("emssize"); - if (!size) return; - if ((size*(1024/16))>EMM_MAX_PAGES) { - LOG_MSG("EMS Max size is %d",EMM_MAX_PAGES/(1024/16)); - emm_page_count=EMM_MAX_PAGES; - } else { - emm_page_count=size*(1024/16); - } + if (!section->Get_bool("ems")) return; call_int67=CALLBACK_Allocate(); CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET); /* Register the ems device */ @@ -710,13 +594,8 @@ void EMS_Init(Section* sec) { RealSetVec(0x67,RealMake(seg,0)); /* Clear handle and page tables */ Bitu i; - for (i=0;itwidth*rnew)*(curmode->cheight/2)+cleft)*2; - PhysPt src=base+((curmode->twidth*rold)*(curmode->cheight/2)+cleft)*2; - Bitu copy=(cright-cleft)*2;Bitu nextline=curmode->twidth*2; - for (Bits i=0;icheight/2;i++) { +static INLINE void CGA_CopyRow(Bit8u cleft,Bit8u cright,Bit8u rold,Bit8u rnew,PhysPt base) { + Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); + PhysPt dest=base+((CurMode->twidth*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)*curmode->cheight+cleft; - src=base+(curmode->twidth*rold)*curmode->cheight+cleft; - Bitu nextline=curmode->twidth; + Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); + dest=base+(CurMode->twidth*rnew)*cheight+cleft; + src=base+(CurMode->twidth*rold)*cheight+cleft; + Bitu nextline=CurMode->twidth; /* Setup registers correctly */ IO_Write(0x3ce,5);IO_Write(0x3cf,1); /* Memory transfer mode */ IO_Write(0x3c4,2);IO_Write(0x3c5,0xf); /* Enable all Write planes */ /* Do some copying */ Bitu rowsize=(cright-cleft); - copy=curmode->cheight; + copy=cheight; for (;copy>0;copy--) { for (Bitu x=0;xtwidth+cleft)*2; - dest=base+(rnew*curmode->twidth+cleft)*2; + src=base+(rold*CurMode->twidth+cleft)*2; + dest=base+(rnew*CurMode->twidth+cleft)*2; MEM_BlockCopy(dest,src,(cright-cleft)*2); } -static INLINE void CGA_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) { - PhysPt dest=base+((curmode->twidth*row)*(curmode->cheight/2)+cleft)*2; - Bitu copy=(cright-cleft)*2;Bitu nextline=curmode->twidth*2; - for (Bits i=0;icheight/2;i++) { +static INLINE void CGA_FillRow(Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) { + Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); + PhysPt dest=base+((CurMode->twidth*row)*(cheight/2)+cleft)*2; + Bitu copy=(cright-cleft)*2;Bitu nextline=CurMode->twidth*2; + for (Bitu i=0;itwidth*row)*curmode->cheight+cleft; - Bitu nextline=curmode->twidth; - Bitu copy=curmode->cheight; Bitu rowsize=(cright-cleft); + Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); + dest=base+(CurMode->twidth*row)*cheight+cleft; + Bitu nextline=CurMode->twidth; + Bitu copy = cheight; Bitu rowsize=(cright-cleft); for (;copy>0;copy--) { for (Bitu x=0;xtwidth+cleft)*2; + dest=base+(row*CurMode->twidth+cleft)*2; Bit16u fill=(attr<<8)+' '; for (Bit8u x=0;x<(cright-cleft);x++) { mem_writew(dest,fill); @@ -107,8 +112,7 @@ static INLINE void TEXT_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,Bit8 void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page) { /* Do some range checking */ - VGAMODES * curmode=GetCurrentMode(); - if (curmode->type==GRAPH) page=0xff; + if (CurMode->type!=M_TEXT16) page=0xff; BIOS_NCOLS;BIOS_NROWS; if(rul>rlr) return; if(cul>clr) return; @@ -118,14 +122,14 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit /* Get the correct page */ if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - PhysPt base=PhysMake(curmode->sstart,curmode->slength*page); + PhysPt base=CurMode->pstart+page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); - /* See how much lines need to be copies */ + /* See how much lines need to be copied */ Bit8u start,end;Bits next; /* Copy some lines */ if (nlines>0) { start=rlr-nlines+1; - end=cul; + end=rul; next=-1; } else if (nlines<0) { start=rul-nlines-1; @@ -137,15 +141,16 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit } while (start!=end) { start+=next; - switch (curmode->memmodel) { - case MTEXT: - case CTEXT: - TEXT_CopyRow(curmode,cul,clr,start,start+nlines,base);break; - case CGA2: - case CGA: - CGA_CopyRow(curmode,cul,clr,start,start+nlines,base);break; - case PLANAR4: - PLANAR4_CopyRow(curmode,cul,clr,start,start+nlines,base);break; + switch (CurMode->type) { + case M_TEXT16: + TEXT_CopyRow(cul,clr,start,start+nlines,base);break; + case M_CGA2: + case M_CGA4: + CGA_CopyRow(cul,clr,start,start+nlines,base);break; + case M_EGA16: + EGA16_CopyRow(cul,clr,start,start+nlines,base);break; + default: + LOG(LOG_INT10,LOG_ERROR)("Unhandled mode %d for scroll",CurMode->type); } } /* Fill some lines */ @@ -157,14 +162,16 @@ filling: start=rlr-nlines+1; } for (;nlines>0;nlines--) { - switch (curmode->memmodel) { - case MTEXT: - case CTEXT: - TEXT_FillRow(curmode,cul,clr,start,base,attr);break; - case CGA: - CGA_FillRow(curmode,cul,clr,start,base,attr);break; - case PLANAR4: - PLANAR4_FillRow(curmode,cul,clr,start,base,attr);break; + switch (CurMode->type) { + case M_TEXT16: + TEXT_FillRow(cul,clr,start,base,attr);break; + case M_CGA2: + case M_CGA4: + CGA_FillRow(cul,clr,start,base,attr);break; + case M_EGA16: + EGA16_FillRow(cul,clr,start,base,attr);break; + default: + LOG(LOG_INT10,LOG_ERROR)("Unhandled mode %d for scroll",CurMode->type); } start++; } @@ -173,30 +180,73 @@ filling: void INT10_SetActivePage(Bit8u page) { Bit16u mem_address; - Bit8u cur_col=0 ,cur_row=0 ; - VGAMODES * curmode=GetCurrentMode(); - if (curmode==0) return; if (page>7) return; - mem_address=page*curmode->slength; + mem_address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); /* Write the new page start */ real_writew(BIOSMEM_SEG,BIOSMEM_CURRENT_START,mem_address); - if (curmode->svgamode<8) mem_address>>=1; - - + 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,(mem_address&0xff00)>>8); + 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,mem_address&0x00ff); + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(Bit8u)mem_address); // And change the BIOS page real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page); - + Bit8u cur_row=CURSOR_POS_ROW(page); + Bit8u cur_col=CURSOR_POS_COL(page); // Display the cursor, now the page is active INT10_SetCursorPos(cur_row,cur_col,page); } +void INT10_SetCursorShape(Bit8u first,Bit8u last) { + real_writew(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,last|(first<<8)); + /* Skip CGA cursor emulation if EGA/VGA system is active */ + if (!(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0x8)) { + /* Check for CGA type 01, invisible */ + if ((first & 0x60) == 0x20) { + first=0x1e; + last=0x00; + goto dowrite; + } + /* Check if we need to convert CGA Bios cursor values */ + if (!(real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL) & 0x1)) { + if (CurMode->mode>0x3) goto dowrite; //Only mode 0-3 are text modes on cga + if ((first & 0xe0) || (last & 0xe0)) goto dowrite; + Bit8u cheight=real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)-1; + /* Creative routine i based of the original ibmvga bios */ + if (last=cheight) || !(last==(cheight-1)) || !(first==cheight) ) { + if (last<=3) goto dowrite; + if (first+22) { + first=(cheight+1)/2; + last=cheight; + } else { + last=cheight; + } + } else { + first=(first-last)+cheight; + last=cheight; + if (cheight>0xc) { + first--; + last--; + } + } + } + + } + } +dowrite: + IO_Write(0x3d4,0xa);IO_Write(0x3d5,first); + IO_Write(0x3d4,0xb);IO_Write(0x3d5,last); +} + void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) { Bit16u address; @@ -209,89 +259,83 @@ void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) { Bit8u current=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); if(page==current) { // Get the dimensions - BIOS_NCOLS;BIOS_NROWS; + BIOS_NCOLS; // Calculate the address knowing nbcols nbrows and page num - address=SCREEN_IO_START(ncols,nrows,page)+col+row*ncols; + 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,(address&0xff00)>>8); + 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,address&0x00ff); - } + IO_Write(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)+1,(Bit8u)address); + } } void INT10_ReadCharAttr(Bit16u * result,Bit8u page) { - if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - BIOS_NCOLS;BIOS_NROWS; Bit8u cur_row=CURSOR_POS_ROW(page); Bit8u cur_col=CURSOR_POS_COL(page); - Bit16u address=SCREEN_MEM_START(ncols,nrows,page)+(cur_col+cur_row*ncols)*2; - *result=real_readw(0xb800,address); + // Compute the address + Bit16u address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); + address+=(cur_row*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)+cur_col)*2; + // REad the char + PhysPt where = CurMode->pstart+address; + *result=mem_readw(where); } - -INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool useattr) { - VGAMODES * curmode=GetCurrentMode(); - switch (curmode->type) { - case TEXT: +static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u attr,bool useattr) { + PhysPt fontdata; + Bitu x,y; + Bit8u cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); + switch (CurMode->type) { + case M_TEXT16: { // Compute the address - Bit16u address=SCREEN_MEM_START(curmode->twidth,curmode->theight,page)+(col+row*curmode->twidth)*2; + Bit16u address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE); + address+=(row*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)+col)*2; // Write the char - real_writeb(0xb800,address,chr); + PhysPt where = CurMode->pstart+address; + mem_writeb(where,chr); if (useattr) { - real_writeb(0xb800,address+1,attr); + mem_writeb(where+1,attr); } } + return; + case M_CGA4: + case M_CGA2: + if (chr<128) fontdata=Real2Phys(RealGetVec(0x43))+chr*cheight; //was plain 8 + else { + chr-=128; + fontdata=Real2Phys(RealGetVec(0x1F))+(chr)*cheight; //was plain 8 + } break; - case GRAPH: - { - /* Amount of lines */ - Bit8u * fontdata; - Bit16u x,y; - switch (curmode->cheight) { - case 8: -// fontdata=&int10_font_08[chr*8]; - if (chr<128) fontdata=Real2Host(RealGetVec(0x43))+chr*8; - else fontdata=Real2Host(RealGetVec(0x1F))+(chr-128)*8; - break; - case 14: - fontdata=&int10_font_14[chr*14]; - break; - case 16: - fontdata=&int10_font_16[chr*16]; - break; - default: - LOG(LOG_ERROR|LOG_INT10,"Teletype Illegal Font Height"); - return; - } - x=8*col; - y=curmode->cheight*row; - //TODO Check for out of bounds - for (Bit8u h=0;hcheight;h++) { - Bit8u bitsel=128; - Bit8u bitline=*fontdata++; - Bit16u tx=x; - while (bitsel) { - if (bitline&bitsel) INT10_PutPixel(tx,y,page,attr); - else INT10_PutPixel(tx,y,page,attr & 0x80); - tx++; - bitsel>>=1; - } - y++; - } - } + default: + fontdata=Real2Phys(RealGetVec(0x43))+chr*cheight; break; } + x=8*col; + y=cheight*row; + //TODO Check for out of bounds + for (Bit8u h=0;h>=1; + } + y++; + } + } void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) { - VGAMODES * curmode=GetCurrentMode(); - if (curmode->type==GRAPH) page=0xff; + //TODO Check if this page thing is correct + 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); @@ -308,10 +352,9 @@ void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) } -void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page) { - VGAMODES * curmode=GetCurrentMode(); - if (curmode->type==GRAPH) page=0xff; - if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); +void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr) { + //TODO Check if this page thing is correct + Bit8u page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); BIOS_NCOLS;BIOS_NROWS; Bit8u cur_row=CURSOR_POS_ROW(page); Bit8u cur_col=CURSOR_POS_COL(page); @@ -332,10 +375,10 @@ void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page) { break; case '\t': do { - INT10_TeletypeOutput(' ',attr,showattr,page); + INT10_TeletypeOutput(' ',attr,showattr); cur_row=CURSOR_POS_ROW(page); cur_col=CURSOR_POS_COL(page); - } while(cur_col%8==0); + } while(cur_col%8); break; default: /* Draw the actual Character */ @@ -356,8 +399,8 @@ void INT10_TeletypeOutput(Bit8u chr,Bit8u attr,bool showattr, Bit8u page) { } void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page) { - VGAMODES * curmode=GetCurrentMode(); - if (curmode->type==GRAPH) page=0xff; + //TODO Check if this page thing is correct + if (CurMode->type!=M_TEXT16) page=0xff; if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); BIOS_NCOLS;BIOS_NROWS; @@ -378,7 +421,7 @@ void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,B attr=mem_readb(string); string++; } - INT10_TeletypeOutput(chr,attr,true,page); + INT10_TeletypeOutput(chr,attr,true); count--; } if (flag & 1) { diff --git a/src/ints/int10_memory.cpp b/src/ints/int10_memory.cpp index 84b21e0..af827ce 100644 --- a/src/ints/int10_memory.cpp +++ b/src/ints/int10_memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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 @@ #include "int10.h" -VGAROMAREA int10_romarea; static Bit8u static_functionality[0x10]= { /* 0 */ 0xff, // All modes supported #1 @@ -40,35 +39,69 @@ static Bit8u static_functionality[0x10]= /* f */ 0x00 // reserved }; +static Bit16u map_offset[8]={ + 0x0000,0x4000,0x8000,0xc000, + 0x2000,0x6000,0xa000,0xe000 +}; + +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 + for (Bitu i=0;isheight/height)-1); + real_writeb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,height); + //TODO Reprogram cursor size? + } +} + + void INT10_SetupRomMemory(void) { /* This should fill up certain structures inside the Video Bios Rom Area */ - Bit32u i; - - Bit16u segoff=0; - int10_romarea.font_8_first=RealMake(0xC000,segoff); + PhysPt rom_base=PhysMake(0xc000,0); + Bitu i; + int10.rom.used=2; + phys_writew(rom_base+0,0xaa55); + int10.rom.font_8_first=RealMake(0xC000,int10.rom.used); for (i=0;i<128*8;i++) { - real_writeb(0xC000,segoff++,int10_font_08[i]); + phys_writeb(rom_base+int10.rom.used++,int10_font_08[i]); } - int10_romarea.font_8_second=RealMake(0xC000,segoff); + int10.rom.font_8_second=RealMake(0xC000,int10.rom.used); for (i=0;i<128*8;i++) { - real_writeb(0xC000,segoff++,int10_font_08[i+128*8]); + phys_writeb(rom_base+int10.rom.used++,int10_font_08[i+128*8]); } - int10_romarea.font_14=RealMake(0xC000,segoff); + int10.rom.font_14=RealMake(0xC000,int10.rom.used); for (i=0;i<256*14;i++) { - real_writeb(0xC000,segoff++,int10_font_14[i]); + phys_writeb(rom_base+int10.rom.used++,int10_font_14[i]); } - int10_romarea.font_16=RealMake(0xC000,segoff); + int10.rom.font_16=RealMake(0xC000,int10.rom.used); for (i=0;i<256*16;i++) { - real_writeb(0xC000,segoff++,int10_font_16[i]); + phys_writeb(rom_base+int10.rom.used++,int10_font_16[i]); } - int10_romarea.static_state=RealMake(0xC000,segoff); + int10.rom.static_state=RealMake(0xC000,int10.rom.used); for (i=0;i<0x10;i++) { - real_writeb(0xC000,segoff++,static_functionality[i]); + phys_writeb(rom_base+int10.rom.used++,static_functionality[i]); } - MEM_BlockWrite(PhysMake(0xf000,0xfa6e),int10_font_08,128*8); - RealSetVec(0x1F,int10_romarea.font_8_second); + for (i=0;i<128*8;i++) { + phys_writeb(PhysMake(0xf000,0xfa6e)+i,int10_font_08[i]); + } + RealSetVec(0x1F,int10.rom.font_8_second); }; diff --git a/src/ints/int10_misc.cpp b/src/ints/int10_misc.cpp index 2ec9f01..40a8a91 100644 --- a/src/ints/int10_misc.cpp +++ b/src/ints/int10_misc.cpp @@ -73,12 +73,12 @@ struct Dynamic_Functionality { void INT10_GetFuncStateInformation(PhysPt save) { /* set static state pointer */ - mem_writed(save,int10_romarea.static_state); + mem_writed(save,int10.rom.static_state); /* Copy BIOS Segment areas */ Bit16u i; /* First area in Bios Seg */ - for (i=0;i<30;i++) { + for (i=0;i<0x1e;i++) { mem_writeb(save+0x4+i,real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE+i)); } /* Second area */ @@ -89,31 +89,27 @@ void INT10_GetFuncStateInformation(PhysPt save) { for (i=0x25;i<0x40;i++) mem_writeb(save+i,0); /* DCC Index */ mem_writeb(save+0x25,real_readb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX)); - VGAMODES * curmode=GetCurrentMode(); - if (!curmode) return; Bit16u col_count=0; - switch (curmode->memmodel) { - case CTEXT: - col_count=2;break; - case MTEXT: + switch (CurMode->type) { + case M_TEXT16: col_count=16;break; - case CGA: - col_count=4;break; - case PLANAR1: + case M_CGA2: col_count=2;break; - case PLANAR2: + case M_CGA4: col_count=4;break; - case PLANAR4: + case M_EGA16: col_count=16;break; - case LINEAR8: + case M_VGA: col_count=256;break; + default: + LOG(LOG_INT10,LOG_ERROR)("Get Func State illegal mode type %d",CurMode->type); } /* Colour count */ mem_writew(save+0x27,col_count); /* Page count */ - mem_writeb(save+0x29,curmode->nbpages); + mem_writeb(save+0x29,CurMode->ptotal); /* scan lines */ - switch (curmode->sheight) { + switch (CurMode->sheight) { case 200: mem_writeb(save+0x2a,0);break; case 350: diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index 9674f99..9cf4e1f 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.cpp @@ -1,20 +1,4 @@ -/* - * Copyright (C) 2002-2003 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 "mem.h" @@ -22,373 +6,489 @@ #include "int10.h" #include "mouse.h" -//TODO Maybe also add PCJR Video Modes could be nice :) -//TODO include some credits to bochs/plex86 bios i used for info/tables +#define _HALF_CLOCK 0x0001 +#define _LINE_DOUBLE 0x0002 +#define _VGA_LINE_DOUBLE 0x0004 +#define _VGA_PIXEL_DOUBLE 0x0008 -VGAMODES vga_modes[MODE_MAX+1]= -{//mode vesa class model pg bits sw sh tw th cw ch sstart slength misc pelm crtc actl gdc sequ dac - {0x00, 0xFFFF, TEXT, CTEXT, 8, 4, 360, 400, 40, 25, 9, 16, 0xB800, 0x0800, 0x67, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x01, 0xFFFF, TEXT, CTEXT, 8, 4, 360, 400, 40, 25, 9, 16, 0xB800, 0x0800, 0x67, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02}, - {0x02, 0xFFFF, TEXT, CTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB800, 0x1000, 0x67, 0xFF, 0x01, 0x00, 0x00, 0x01, 0x02}, - {0x03, 0xFFFF, TEXT, CTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB800, 0x1000, 0x67, 0xFF, 0x01, 0x00, 0x00, 0x01, 0x02}, - {0x04, 0xFFFF, GRAPH, CGA, 4, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01}, - {0x05, 0xFFFF, GRAPH, CGA, 1, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01}, - {0x06, 0xFFFF, GRAPH, CGA2, 1, 1, 640, 200, 80, 25, 8, 8, 0xB800, 0x1000, 0x63, 0xFF, 0x03, 0x02, 0x02, 0x03, 0x01}, - {0x07, 0xFFFF, TEXT, MTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB000, 0x1000, 0x66, 0xFF, 0x04, 0x03, 0x03, 0x01, 0x00}, +#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 }, +/* 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 }, - {0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x2000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01}, - {0x0E, 0xFFFF, GRAPH, PLANAR4, 4, 4, 640, 200, 80, 25, 8, 8, 0xA000, 0x4000, 0x63, 0xFF, 0x06, 0x04, 0x04, 0x05, 0x01}, - {0x0F, 0xFFFF, GRAPH, PLANAR2, 2, 2, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa2, 0xFF, 0x07, 0x05, 0x04, 0x05, 0x00}, - {0x10, 0xFFFF, GRAPH, PLANAR4, 2, 4, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa3, 0xFF, 0x07, 0x06, 0x04, 0x05, 0x02}, - {0x11, 0xFFFF, GRAPH, PLANAR1, 1, 1, 640, 480, 80, 30, 8, 16, 0xA000, 0xA000, 0xe3, 0xFF, 0x08, 0x07, 0x04, 0x05, 0x02}, - {0x12, 0xFFFF, GRAPH, PLANAR4, 1, 4, 640, 480, 80, 30, 8, 16, 0xA000, 0xA000, 0xe3, 0xFF, 0x08, 0x06, 0x04, 0x05, 0x02}, - {0x13, 0xFFFF, GRAPH, LINEAR8, 1, 8, 320, 200, 40, 25, 8, 8, 0xA000, 0xFA00, 0x63, 0xFF, 0x09, 0x08, 0x05, 0x06, 0x03} +{ 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 }, + +{ 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 }, + +{0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 }, + }; -/* CRTC */ -#define CRTC_MAX_REG 0x18 -#define CRTC_MAX_MODEL 0x09 -static Bit8u crtc_access[CRTC_MAX_REG+1]= -{ /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; -static Bit8u crtc_regs[CRTC_MAX_MODEL+1][CRTC_MAX_REG+1]= -{/* Model 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 */ - /* 00 */ 0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,0xff, - /* 01 */ 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff, - /* 02 */ 0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,0xff, - /* 03 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,0xff, - /* 04 */ 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,0xff, - /* 05 */ 0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,0xff, - /* 06 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,0xff, - /* 07 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3,0xff, - /* 08 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xe3,0xff, - /* 09 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,0xff -}; - -/* Attribute Controler 0x3c0 */ -#define ACTL_MAX_REG 0x14 -#define ACTL_MAX_MODEL 0x08 - -static Bit8u actl_access[ACTL_MAX_REG+1]= -{/* 00 01 02 03 04 05 06 07 08 09 0A 0B OC OD OE OF 10 11 12 13 14 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; - -static Bit8u actl_regs[ACTL_MAX_MODEL+1][ACTL_MAX_REG+1]= -{/* Model 00 01 02 03 04 05 06 07 08 09 0A 0B OC OD OE OF 10 11 12 13 14 */ - /* 00 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00, - /* 01 */ 0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x01,0x00,0x03,0x00,0x00, - /* 02 */ 0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x01,0x00,0x01,0x00,0x00, - /* 03 */ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x0e,0x00,0x0f,0x08,0x00, - /* 04 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x01,0x00,0x0f,0x00,0x00, - /* 05 */ 0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x0b,0x00,0x05,0x00,0x00, - /* 06 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x01,0x00,0x0f,0x00,0x00, - /* 07 */ 0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x01,0x00,0x01,0x00,0x00, - /* 08 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x41,0x00,0x0f,0x00,0x00 -}; - -/* Sequencer 0x3c4 */ -#define SEQU_MAX_REG 0x04 -#define SEQU_MAX_MODEL 0x06 - -static Bit8u sequ_access[SEQU_MAX_REG+1]= -{ /* 00 01 02 03 04 */ - 0x00,0x00,0x00,0x00,0x00 -}; - -static Bit8u sequ_regs[SEQU_MAX_MODEL+1][SEQU_MAX_REG+1]= -{/* Model 00 01 02 03 04 */ - /* 00 */ 0x03,0x08,0x03,0x00,0x02, - /* 01 */ 0x03,0x00,0x03,0x00,0x02, - /* 02 */ 0x03,0x09,0x03,0x00,0x02, - /* 03 */ 0x03,0x01,0x01,0x00,0x06, - /* 04 */ 0x03,0x09,0x0f,0x00,0x06, - /* 05 */ 0x03,0x01,0x0f,0x00,0x06, - /* 06 */ 0x03,0x01,0x0f,0x00,0x0e -}; - -/* Graphic ctl 0x3ce */ -#define GRDC_MAX_REG 0x08 -#define GRDC_MAX_MODEL 0x05 - -static Bit8u grdc_access[GRDC_MAX_REG+1]= -{ /* 00 01 02 03 04 05 06 07 08 */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; - -static Bit8u grdc_regs[GRDC_MAX_MODEL+1][GRDC_MAX_REG+1]= -{/* Model 00 01 02 03 04 05 06 07 08 */ - /* 00 */ 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x0f,0xff, - /* 01 */ 0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x0f,0xff, - /* 02 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x0f,0xff, - /* 03 */ 0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x0f,0xff, - /* 04 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,0xff, - /* 05 */ 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,0xff -}; - -/* Default Palette */ -#define DAC_MAX_MODEL 3 - -static Bit8u dac_regs[DAC_MAX_MODEL+1]= -{0x3f,0x3f,0x3f,0xff}; - -/* Mono */ -static Bit8u palette0[63+1][3]= +static Bit8u text_palette[64][3]= { - 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, - 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, - 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, - 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, - 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, - 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, - 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, - 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f + {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x2a,0x00},{0x2a,0x2a,0x2a}, + {0x00,0x00,0x15},{0x00,0x00,0x3f},{0x00,0x2a,0x15},{0x00,0x2a,0x3f},{0x2a,0x00,0x15},{0x2a,0x00,0x3f},{0x2a,0x2a,0x15},{0x2a,0x2a,0x3f}, + {0x00,0x15,0x00},{0x00,0x15,0x2a},{0x00,0x3f,0x00},{0x00,0x3f,0x2a},{0x2a,0x15,0x00},{0x2a,0x15,0x2a},{0x2a,0x3f,0x00},{0x2a,0x3f,0x2a}, + {0x00,0x15,0x15},{0x00,0x15,0x3f},{0x00,0x3f,0x15},{0x00,0x3f,0x3f},{0x2a,0x15,0x15},{0x2a,0x15,0x3f},{0x2a,0x3f,0x15},{0x2a,0x3f,0x3f}, + {0x15,0x00,0x00},{0x15,0x00,0x2a},{0x15,0x2a,0x00},{0x15,0x2a,0x2a},{0x3f,0x00,0x00},{0x3f,0x00,0x2a},{0x3f,0x2a,0x00},{0x3f,0x2a,0x2a}, + {0x15,0x00,0x15},{0x15,0x00,0x3f},{0x15,0x2a,0x15},{0x15,0x2a,0x3f},{0x3f,0x00,0x15},{0x3f,0x00,0x3f},{0x3f,0x2a,0x15},{0x3f,0x2a,0x3f}, + {0x15,0x15,0x00},{0x15,0x15,0x2a},{0x15,0x3f,0x00},{0x15,0x3f,0x2a},{0x3f,0x15,0x00},{0x3f,0x15,0x2a},{0x3f,0x3f,0x00},{0x3f,0x3f,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} }; -static Bit8u palette1[63+1][3]= +static Bit8u ega_palette[64][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, - 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, - 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f, - 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a, - 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, - 0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f + {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, + {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}, + {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}, + {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a}, + {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}, + {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f} }; -static Bit8u palette2[63+1][3]= + +static Bit8u vga_palette[256][3]= { - 0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a, - 0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f, - 0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a, - 0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f, - 0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a, - 0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f, - 0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,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 + {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}, + {0x00,0x00,0x00},{0x05,0x05,0x05},{0x08,0x08,0x08},{0x0b,0x0b,0x0b},{0x0e,0x0e,0x0e},{0x11,0x11,0x11},{0x14,0x14,0x14},{0x18,0x18,0x18}, + {0x1c,0x1c,0x1c},{0x20,0x20,0x20},{0x24,0x24,0x24},{0x28,0x28,0x28},{0x2d,0x2d,0x2d},{0x32,0x32,0x32},{0x38,0x38,0x38},{0x3f,0x3f,0x3f}, + {0x00,0x00,0x3f},{0x10,0x00,0x3f},{0x1f,0x00,0x3f},{0x2f,0x00,0x3f},{0x3f,0x00,0x3f},{0x3f,0x00,0x2f},{0x3f,0x00,0x1f},{0x3f,0x00,0x10}, + {0x3f,0x00,0x00},{0x3f,0x10,0x00},{0x3f,0x1f,0x00},{0x3f,0x2f,0x00},{0x3f,0x3f,0x00},{0x2f,0x3f,0x00},{0x1f,0x3f,0x00},{0x10,0x3f,0x00}, + {0x00,0x3f,0x00},{0x00,0x3f,0x10},{0x00,0x3f,0x1f},{0x00,0x3f,0x2f},{0x00,0x3f,0x3f},{0x00,0x2f,0x3f},{0x00,0x1f,0x3f},{0x00,0x10,0x3f}, + {0x1f,0x1f,0x3f},{0x27,0x1f,0x3f},{0x2f,0x1f,0x3f},{0x37,0x1f,0x3f},{0x3f,0x1f,0x3f},{0x3f,0x1f,0x37},{0x3f,0x1f,0x2f},{0x3f,0x1f,0x27}, + + {0x3f,0x1f,0x1f},{0x3f,0x27,0x1f},{0x3f,0x2f,0x1f},{0x3f,0x37,0x1f},{0x3f,0x3f,0x1f},{0x37,0x3f,0x1f},{0x2f,0x3f,0x1f},{0x27,0x3f,0x1f}, + {0x1f,0x3f,0x1f},{0x1f,0x3f,0x27},{0x1f,0x3f,0x2f},{0x1f,0x3f,0x37},{0x1f,0x3f,0x3f},{0x1f,0x37,0x3f},{0x1f,0x2f,0x3f},{0x1f,0x27,0x3f}, + {0x2d,0x2d,0x3f},{0x31,0x2d,0x3f},{0x36,0x2d,0x3f},{0x3a,0x2d,0x3f},{0x3f,0x2d,0x3f},{0x3f,0x2d,0x3a},{0x3f,0x2d,0x36},{0x3f,0x2d,0x31}, + {0x3f,0x2d,0x2d},{0x3f,0x31,0x2d},{0x3f,0x36,0x2d},{0x3f,0x3a,0x2d},{0x3f,0x3f,0x2d},{0x3a,0x3f,0x2d},{0x36,0x3f,0x2d},{0x31,0x3f,0x2d}, + {0x2d,0x3f,0x2d},{0x2d,0x3f,0x31},{0x2d,0x3f,0x36},{0x2d,0x3f,0x3a},{0x2d,0x3f,0x3f},{0x2d,0x3a,0x3f},{0x2d,0x36,0x3f},{0x2d,0x31,0x3f}, + {0x00,0x00,0x1c},{0x07,0x00,0x1c},{0x0e,0x00,0x1c},{0x15,0x00,0x1c},{0x1c,0x00,0x1c},{0x1c,0x00,0x15},{0x1c,0x00,0x0e},{0x1c,0x00,0x07}, + {0x1c,0x00,0x00},{0x1c,0x07,0x00},{0x1c,0x0e,0x00},{0x1c,0x15,0x00},{0x1c,0x1c,0x00},{0x15,0x1c,0x00},{0x0e,0x1c,0x00},{0x07,0x1c,0x00}, + {0x00,0x1c,0x00},{0x00,0x1c,0x07},{0x00,0x1c,0x0e},{0x00,0x1c,0x15},{0x00,0x1c,0x1c},{0x00,0x15,0x1c},{0x00,0x0e,0x1c},{0x00,0x07,0x1c}, + + {0x0e,0x0e,0x1c},{0x11,0x0e,0x1c},{0x15,0x0e,0x1c},{0x18,0x0e,0x1c},{0x1c,0x0e,0x1c},{0x1c,0x0e,0x18},{0x1c,0x0e,0x15},{0x1c,0x0e,0x11}, + {0x1c,0x0e,0x0e},{0x1c,0x11,0x0e},{0x1c,0x15,0x0e},{0x1c,0x18,0x0e},{0x1c,0x1c,0x0e},{0x18,0x1c,0x0e},{0x15,0x1c,0x0e},{0x11,0x1c,0x0e}, + {0x0e,0x1c,0x0e},{0x0e,0x1c,0x11},{0x0e,0x1c,0x15},{0x0e,0x1c,0x18},{0x0e,0x1c,0x1c},{0x0e,0x18,0x1c},{0x0e,0x15,0x1c},{0x0e,0x11,0x1c}, + {0x14,0x14,0x1c},{0x16,0x14,0x1c},{0x18,0x14,0x1c},{0x1a,0x14,0x1c},{0x1c,0x14,0x1c},{0x1c,0x14,0x1a},{0x1c,0x14,0x18},{0x1c,0x14,0x16}, + {0x1c,0x14,0x14},{0x1c,0x16,0x14},{0x1c,0x18,0x14},{0x1c,0x1a,0x14},{0x1c,0x1c,0x14},{0x1a,0x1c,0x14},{0x18,0x1c,0x14},{0x16,0x1c,0x14}, + {0x14,0x1c,0x14},{0x14,0x1c,0x16},{0x14,0x1c,0x18},{0x14,0x1c,0x1a},{0x14,0x1c,0x1c},{0x14,0x1a,0x1c},{0x14,0x18,0x1c},{0x14,0x16,0x1c}, + {0x00,0x00,0x10},{0x04,0x00,0x10},{0x08,0x00,0x10},{0x0c,0x00,0x10},{0x10,0x00,0x10},{0x10,0x00,0x0c},{0x10,0x00,0x08},{0x10,0x00,0x04}, + {0x10,0x00,0x00},{0x10,0x04,0x00},{0x10,0x08,0x00},{0x10,0x0c,0x00},{0x10,0x10,0x00},{0x0c,0x10,0x00},{0x08,0x10,0x00},{0x04,0x10,0x00}, + + {0x00,0x10,0x00},{0x00,0x10,0x04},{0x00,0x10,0x08},{0x00,0x10,0x0c},{0x00,0x10,0x10},{0x00,0x0c,0x10},{0x00,0x08,0x10},{0x00,0x04,0x10}, + {0x08,0x08,0x10},{0x0a,0x08,0x10},{0x0c,0x08,0x10},{0x0e,0x08,0x10},{0x10,0x08,0x10},{0x10,0x08,0x0e},{0x10,0x08,0x0c},{0x10,0x08,0x0a}, + {0x10,0x08,0x08},{0x10,0x0a,0x08},{0x10,0x0c,0x08},{0x10,0x0e,0x08},{0x10,0x10,0x08},{0x0e,0x10,0x08},{0x0c,0x10,0x08},{0x0a,0x10,0x08}, + {0x08,0x10,0x08},{0x08,0x10,0x0a},{0x08,0x10,0x0c},{0x08,0x10,0x0e},{0x08,0x10,0x10},{0x08,0x0e,0x10},{0x08,0x0c,0x10},{0x08,0x0a,0x10}, + {0x0b,0x0b,0x10},{0x0c,0x0b,0x10},{0x0d,0x0b,0x10},{0x0f,0x0b,0x10},{0x10,0x0b,0x10},{0x10,0x0b,0x0f},{0x10,0x0b,0x0d},{0x10,0x0b,0x0c}, + {0x10,0x0b,0x0b},{0x10,0x0c,0x0b},{0x10,0x0d,0x0b},{0x10,0x0f,0x0b},{0x10,0x10,0x0b},{0x0f,0x10,0x0b},{0x0d,0x10,0x0b},{0x0c,0x10,0x0b}, + {0x0b,0x10,0x0b},{0x0b,0x10,0x0c},{0x0b,0x10,0x0d},{0x0b,0x10,0x0f},{0x0b,0x10,0x10},{0x0b,0x0f,0x10},{0x0b,0x0d,0x10},{0x0b,0x0c,0x10}, + {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00} }; -static Bit8u palette3[256][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, - 0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18, - 0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f, - 0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10, - 0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00, - 0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f, - 0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27, +VideoModeBlock * CurMode; - 0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f, - 0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f, - 0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31, - 0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d, - 0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f, - 0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07, - 0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00, - 0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c, - - 0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11, - 0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e, - 0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c, - 0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16, - 0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14, - 0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c, - 0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04, - 0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00, - - 0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10, - 0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a, - 0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08, - 0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10, - 0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c, - 0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b, - 0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10, - 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00 -}; - -static Bit8u static_functionality[0x10]= -{ - /* 0 */ 0xff, // All modes supported #1 - /* 1 */ 0xff, // All modes supported #2 - /* 2 */ 0x0f, // All modes supported #3 - /* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved - /* 7 */ 0x07, // 200, 350, 400 scan lines - /* 8 */ 0xFF, // FIXME i don't know what this is - /* 9 */ 0xFF, // FIXME i don't know what this is - /* a */ 0xe3, // Change to add new functions - /* b */ 0x0c, // Change to add new functions - /* c */ 0x00, // reserved - /* d */ 0x00, // reserved - /* e */ 0x00, // Change to add new functions - /* f */ 0x00 // reserved -}; - -static Bit8u FindVideoMode(Bit8u mode) { - Bit8u line=0xff; - for(Bit8u i=0;i<=MODE_MAX;i++) { - if(vga_modes[i].svgamode==mode) { - line=i; - break; - } - } - return line; - -} - -VGAMODES * GetCurrentMode(void) { - Bit8u mode=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)&127; - if (mode==int10.mode) return int10.entry; - int10.mode=mode; - int10.entry=&vga_modes[FindVideoMode(mode)]; - return int10.entry; -} +bool INT10_SetVideoMode(Bitu mode) { -void INT10_SetVideoMode(Bit8u mode) { - - bool clearmem=(mode & 128)==0; - Bit8u *palette; - Bit16u i,twidth,theight,cheight; + bool clearmem=true; Bit8u modeset_ctl,video_ctl,vga_switches; Bit16u crtc_addr; - Bit8u line; - mode&=mode & 127; - line=FindVideoMode(mode); - if (line==0xff) { - LOG(LOG_ERROR|LOG_INT10,"INT10:Trying to set non supported video mode %X",mode); - return; + if (mode<256) { + if (mode & 128) { + clearmem=false; + mode-=128; + } + } else { + /* Check for special vesa mode bits */ + mode&=0xfff; } - - twidth=vga_modes[line].twidth; - theight=vga_modes[line].theight; - cheight=vga_modes[line].cheight; - - // Read the bios vga control + LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode); + Bitu i=0; + while (ModeList[i].mode!=0xffff) { + if (ModeList[i].mode==mode) goto foundmode; + i++; + } + LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode); + return false; +foundmode: + CurMode=&ModeList[i]; + + /* First read mode setup settings from bios area */ video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL); - - // Read the bios vga switches vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES); - - // Read the bios mode set control modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); + /* Setup the VGA to the correct mode */ + VGA_SetMode(CurMode->type); - - /* Reset Attribute ctl into address mode just to be safe */ - - IO_Read(VGAREG_ACTL_RESET); - // Set the High Attribute Ctl - for(i=0x10;i<=ACTL_MAX_REG;i++) { - IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i); - IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]); + /* Setup MISC Output Register */ + Bit8u misc_output=0x3; //Color and cpu memory access + /* 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; + seq_data[4]|=0x02; //More than 64kb + switch (CurMode->type) { + case M_TEXT16: + seq_data[2]|=0x3; //Enable plane 0 and 1 + seq_data[4]|=0x05; //Alpanumeric and odd/even enabled + break; + case M_EGA16: + seq_data[2]|=0xf; //Enable all planes for writing + break; + case M_LIN8: //Seems to have the same reg layout from testing + case M_VGA: + seq_data[2]|=0xf; //Enable all planes for writing + seq_data[4]|=0xc; //Graphics - odd/even - Chained + break; } - // Set Sequencer Ctl - for(i=0;i<=SEQU_MAX_REG;i++) { - IO_Write(VGAREG_SEQU_ADDRESS,(Bit8u)i); - IO_Write(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]); + for (i=0;ihtotal-5); + hor_overflow|=((CurMode->htotal-5) & 0x100) >> 8; + /* Horizontal Display End */ + IO_Write(0x3d4,0x01);IO_Write(0x3d5,CurMode->hdispend-1); + hor_overflow|=((CurMode->hdispend-1) & 0x100) >> 7; + /* Start horizontal Blanking */ + IO_Write(0x3d4,0x02);IO_Write(0x3d5,CurMode->hdispend); + hor_overflow|=((CurMode->hdispend) & 0x100) >> 6; + /* End horizontal Blanking */ + Bitu blank_end; + if (CurMode->special & _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)); +// hor_overflow|=(blank_end & 0x40) >> 3; - // Set the misc register - IO_Write(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg); - - // Enable video - IO_Write(VGAREG_ACTL_ADDRESS,0x20); - IO_Read(VGAREG_ACTL_RESET); - - //Set the palette - if ((modeset_ctl&0x08)==0x8) LOG(LOG_INT10,"Mode set without palette"); - if((modeset_ctl&0x08)==0) { - // Set the PEL mask - IO_Write(VGAREG_PEL_MASK,vga_modes[line].pelmask); - // Set the whole dac always, from 0 - IO_Write(VGAREG_DAC_WRITE_ADDRESS,0x00); - // From which palette - switch(vga_modes[line].dacmodel) { - case 0: - palette=(Bit8u*)&palette0; - break; - case 1: - palette=(Bit8u*)&palette1; - break; - case 2: - palette=(Bit8u*)&palette2; - break; - case 3: - palette=(Bit8u*)&palette3; - break; - default: - palette=(Bit8u*)&palette0;/*for gcc*/ - E_Exit("INT10: palette error in setvidmode"); - break; - } - // Set the actual palette - for (i=0;i<256;i++) { - if (i<=dac_regs[vga_modes[line].dacmodel]) { - IO_Write(VGAREG_DAC_DATA,palette[(i*3)+0]); - IO_Write(VGAREG_DAC_DATA,palette[(i*3)+1]); - IO_Write(VGAREG_DAC_DATA,palette[(i*3)+2]); - } else { - IO_Write(VGAREG_DAC_DATA,0); - IO_Write(VGAREG_DAC_DATA,0); - IO_Write(VGAREG_DAC_DATA,0); - } - } + /* Start Horizontal Retrace */ + Bitu ret_start; + if (CurMode->special & _HALF_CLOCK) { + ret_start = (CurMode->hdispend+2); + } else { + ret_start = (CurMode->hdispend+4); } - - IO_Read(VGAREG_ACTL_RESET); - // Set the Low Attribute Ctl - for(i=0;i<=0xf;i++) { - IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i); - IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]); + IO_Write(0x3d4,0x04);IO_Write(0x3d5,ret_start); + hor_overflow|=(ret_start & 0x100) >> 4; + /* End Horizontal Retrace */ + Bitu ret_end; + if (CurMode->special & _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); +// 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)); + overflow|=((CurMode->vtotal-2) & 0x100) >> 8; + overflow|=((CurMode->vtotal-2) & 0x200) >> 4; + ver_overflow|=((CurMode->vtotal-2) & 0x400) >> 10; +/* + These aren't exactly accurate i think, + Should be more like a certain percentage based on vertical total + So you get same sized borders, but okay :) + */ + /* Vertical Retrace Start */ + IO_Write(0x3d4,0x10);IO_Write(0x3d5,(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); + + /* Vertical Display End */ + IO_Write(0x3d4,0x12);IO_Write(0x3d5,(CurMode->vdispend-1)); + overflow|=((CurMode->vdispend-1) & 0x100) >> 7; + overflow|=((CurMode->vdispend-1) & 0x200) >> 3; + ver_overflow|=((CurMode->vdispend-1) & 0x400) >> 9; - Bit32u tel; - if(clearmem) { - if(vga_modes[line].type==TEXT) { - PhysPt dest=PhysMake(vga_modes[line].sstart,0); - for (tel=0;tel<0x4000;tel++) { - mem_writew(dest,0x0720); - dest+=2; + /* Vertical Blank Start */ + IO_Write(0x3d4,0x15);IO_Write(0x3d5,(CurMode->vdispend+8)); + overflow|=((CurMode->vdispend+8) & 0x100) >> 5; + max_scanline|=((CurMode->vdispend+8) & 0x200) >> 3; + ver_overflow|=((CurMode->vdispend+8) & 0x400) >> 8; + /* Vertical Retrace End */ + IO_Write(0x3d4,0x16);IO_Write(0x3d5,(CurMode->vtotal-8)); + /* Line Compare */ + Bitu line_compare=CurMode->vtotal+1; //Out of range + IO_Write(0x3d4,0x18);IO_Write(0x3d5,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; + switch (CurMode->type) { + case M_TEXT16: + max_scanline|=CurMode->theight-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; + break; + } + IO_Write(0x3d4,0x09);IO_Write(0x3d5,max_scanline); + IO_Write(0x3d4,0x14);IO_Write(0x3d5,underline); + + /* OverFlow */ + IO_Write(0x3d4,0x07);IO_Write(0x3d5,overflow); + /* Extended Horizontal Overflow */ + IO_Write(0x3d4,0x5d);IO_Write(0x3d5,hor_overflow); + /* Extended Vertical Overflow */ + IO_Write(0x3d4,0x5e);IO_Write(0x3d5,ver_overflow); + /* Offset Register */ + IO_Write(0x3d4,0x13); + switch (CurMode->type) { + case M_LIN8: + IO_Write(0x3d5,CurMode->swidth/8); + break; + default: + IO_Write(0x3d5,CurMode->hdispend/2); + } + /* Mode Control */ + Bit8u mode_control=0; + switch (CurMode->type) { + case M_CGA4: + case M_CGA2: + mode_control=0xa2; + break; + case M_EGA16: + mode_control=0xe3; + break; + case M_TEXT16: + case M_VGA: + mode_control=0xa3; + break; + case M_LIN8: + mode_control=0xab; + break; + + } + IO_Write(0x3d4,0x17);IO_Write(0x3d5,mode_control); + /* Renable write protection */ + IO_Write(0x3d4,0x11); + IO_Write(0x3d5,IO_Read(0x3d5)|0x80); + /* Setup the correct clock */ + if (CurMode->mode<0x100) { + //Stick to 25mhz clock for now + } else { + misc_output|=0xef; //Select clock 3 + Bitu clock=CurMode->vtotal*8*CurMode->htotal*70; + VGA_SetClock(3,clock/1000); + } + /* Write Misc Output */ + IO_Write(0x3c2,misc_output); + + /* Program Graphics controller */ + Bit8u gfx_data[GFX_REGS]; + memset(gfx_data,0,GFX_REGS); + gfx_data[0x7]=0xf; /* Color don't care */ + gfx_data[0x8]=0xff; /* BitMask */ + switch (CurMode->type) { + case M_TEXT16: + gfx_data[0x5]|=0x10; //Odd-Even Mode + gfx_data[0x6]|=0x0e; //alphanumeric mode at 0xb800=0xbfff + break; + case M_LIN8: + case M_VGA: + gfx_data[0x5]|=0x40; //256 color mode + gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff + break; + case M_EGA16: + gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff + break; + case M_CGA2: + case M_CGA4: + case M_TANDY16: + gfx_data[0x5]|=0x20; //CGA mode + gfx_data[0x6]|=0x0f; //graphics mode at at 0xb800=0xbfff + break; + } + for (i=0;itype) { + 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++) { + att_data[i]=i; + att_data[i+8]=i+0x10; + } + break; + 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 +att_text16: + for (i=0;i<8;i++) { + att_data[i]=i; + att_data[i+8]=i+0x38; + } + break; + case M_CGA2: + case M_CGA4: + IO_Write(0x3d9,0x20); //Setup using CGA color select register + goto skipatt; + case M_VGA: + case M_LIN8: + for (i=0;i<16;i++) { + att_data[i]=i; + } + att_data[0x10]=0x41; //Color Graphics 8-bit + break; + } + + IO_Read(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_TEXT16: +dac_text16: + for (i=0;i<64;i++) { + IO_Write(0x3c9,text_palette[i][0]); + IO_Write(0x3c9,text_palette[i][1]); + IO_Write(0x3c9,text_palette[i][2]); + } + break; + case M_VGA: + case M_LIN8: + for (i=0;i<256;i++) { + IO_Write(0x3c9,vga_palette[i][0]); + IO_Write(0x3c9,vga_palette[i][1]); + IO_Write(0x3c9,vga_palette[i][2]); + } + break; + } + /* Setup registers for special video modes */ + switch (CurMode->type) { + case M_TANDY16: + IO_Write(0x3df,0x80); //Enter 32k mode and banks on 0 + break; + } + /* Setup the CPU Window */ + IO_Write(0x3d4,0x6a); + IO_Write(0x3d5,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)); + + /* 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 + + /* Load text mode font */ + if (CurMode->type==M_TEXT16) { + INT10_LoadFont(Real2Phys(int10.rom.font_16),true,256,0,0,16); + } + /* Clear video memory if needs be */ + if (clearmem) { + switch (CurMode->type) { + case M_CGA4: + case M_CGA2: + for (i=0;i<16*1024;i++) { + real_writew(0xb800,i*2,0x0000); } - } else { - PhysPt dest=PhysMake(0xb800,0); - for (tel=0;tel<0x4000;tel++) { - mem_writew(dest,0x0000); - dest+=2; + break; + case M_TEXT16: + for (i=0;i<16*1024;i++) { + real_writew(0xb800,i*2,0x0700); } - dest=PhysMake(0xa000,0); - for (tel=0;tel<0x8000;tel++) { - mem_writew(dest,0x0000); - dest+=2; + break; + case M_EGA16: + case M_VGA: + case M_LIN8: + /* Just clear the whole 2 mb of memory */ + for (i=0;i<2*1024*1024/4;i++) { + mem_writed(S3_LFB_BASE+i*4,0); } - // FIXME should handle gfx mode } } - // Set the BIOS mem - real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode|((!clearmem) << 7)); - real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth); - real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,vga_modes[line].slength); + /* 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_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theight-1); - real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight); + 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))); real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09); real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f); @@ -403,27 +503,23 @@ void INT10_SetVideoMode(Bit8u mode) { real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but... // Set cursor shape - if(vga_modes[line].type==TEXT) { -//TODO cursor shape biosfn_set_cursor_shape(0x06,0x07); + if(CurMode->type==M_TEXT16) { + INT10_SetCursorShape(0x06,07); } // Set cursor pos for page 0..7 for(i=0;i<8;i++) INT10_SetCursorPos(0,0,(Bit8u)i); // Set active page 0 INT10_SetActivePage(0); /* Set some interrupt vectors */ - RealSetVec(0x43,int10_romarea.font_8_first); + switch (CurMode->cheight) { + case 8:RealSetVec(0x43,int10.rom.font_8_first);break; + case 14:RealSetVec(0x43,int10.rom.font_14);break; + case 16:RealSetVec(0x43,int10.rom.font_16);break; + } /* Tell mouse resolution change */ - Mouse_SetResolution(vga_modes[line].swidth,vga_modes[line].sheight); -}; + Mouse_NewVideoMode(); + return true; +} + + -void INT10_SetGfxControllerToDefault() -// reset gfx controller to default values -// needed for drawing mouse pointer -{ - Bit8u line=FindVideoMode(real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)&127); - // Set Grafx Ctl - for(Bit8u i=0;i<=GRDC_MAX_REG;i++) { - IO_Write(VGAREG_GRDC_ADDRESS,(Bit8u)i); - IO_Write(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]); - } -}; \ No newline at end of file diff --git a/src/ints/int10_pal.cpp b/src/ints/int10_pal.cpp index c73553a..2563e30 100644 --- a/src/ints/int10_pal.cpp +++ b/src/ints/int10_pal.cpp @@ -29,6 +29,7 @@ void INT10_SetSinglePaletteRegister(Bit8u reg,Bit8u val) { IO_Write(VGAREG_ACTL_ADDRESS,reg); IO_Write(VGAREG_ACTL_WRITE_DATA,val); } + IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette } @@ -36,6 +37,7 @@ void INT10_SetOverscanBorderColor(Bit8u val) { IO_Read(VGAREG_ACTL_RESET); IO_Write(VGAREG_ACTL_ADDRESS,0x11); IO_Write(VGAREG_ACTL_WRITE_DATA,val); + IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette } void INT10_SetAllPaletteRegisters(PhysPt data) { @@ -49,6 +51,7 @@ void INT10_SetAllPaletteRegisters(PhysPt data) { // Then the border IO_Write(VGAREG_ACTL_ADDRESS,0x11); IO_Write(VGAREG_ACTL_WRITE_DATA,mem_readb(data)); + IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette } void INT10_ToggleBlinkingBit(Bit8u state) { @@ -64,19 +67,20 @@ void INT10_ToggleBlinkingBit(Bit8u state) { IO_Read(VGAREG_ACTL_RESET); IO_Write(VGAREG_ACTL_ADDRESS,0x10); IO_Write(VGAREG_ACTL_WRITE_DATA,value); + IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette } void INT10_GetSinglePaletteRegister(Bit8u reg,Bit8u * val) { if(reg<=ACTL_MAX_REG) { IO_Read(VGAREG_ACTL_RESET); - IO_Write(VGAREG_ACTL_ADDRESS,reg); + IO_Write(VGAREG_ACTL_ADDRESS,reg+32); *val=IO_Read(VGAREG_ACTL_READ_DATA); } } void INT10_GetOverscanBorderColor(Bit8u * val) { IO_Read(VGAREG_ACTL_RESET); - IO_Write(VGAREG_ACTL_ADDRESS,0x11); + IO_Write(VGAREG_ACTL_ADDRESS,0x11+32); *val=IO_Read(VGAREG_ACTL_READ_DATA); } @@ -89,7 +93,7 @@ void INT10_GetAllPaletteRegisters(PhysPt data) { data++; } // Then the border - IO_Write(VGAREG_ACTL_ADDRESS,0x11); + IO_Write(VGAREG_ACTL_ADDRESS,0x11+32); mem_writeb(data,IO_Read(VGAREG_ACTL_READ_DATA)); } @@ -123,4 +127,46 @@ void INT10_GetDACBlock(Bit16u index,Bit16u count,PhysPt data) { mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); mem_writeb(data++,IO_Read(VGAREG_DAC_DATA)); } -}; +} + +void INT10_SelectDACPage(Bit8u function,Bit8u mode) { + IO_Read(VGAREG_ACTL_RESET); + IO_Write(VGAREG_ACTL_ADDRESS,0x10); + Bit8u old10=IO_Read(VGAREG_ACTL_READ_DATA); + if (!function) { //Select paging mode + if (mode) old10|=0x80; + else old10&=0x7f; + IO_Write(VGAREG_ACTL_ADDRESS,0x10); + IO_Write(VGAREG_ACTL_WRITE_DATA,old10); + } else { //Select page + if (!(old10 & 0x80)) mode<<=2; + mode&=0xf; + IO_Write(VGAREG_ACTL_ADDRESS,0x14); + IO_Write(VGAREG_ACTL_WRITE_DATA,mode); + } + IO_Write(VGAREG_ACTL_ADDRESS,32); //Enable output and protect palette +} + +void INT10_SetPelMask(Bit8u mask) { + IO_Write(VGAREG_PEL_MASK,mask); +} + +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); +} + +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); +} + diff --git a/src/ints/int10_put_pixel.cpp b/src/ints/int10_put_pixel.cpp index 934b727..efa0a33 100644 --- a/src/ints/int10_put_pixel.cpp +++ b/src/ints/int10_put_pixel.cpp @@ -25,9 +25,8 @@ static Bit8u cga_masks[4]={~192,~48,~12,~3}; static Bit8u cga_masks2[8]={~128,~64,~32,~16,~8,~4,~2,~1}; void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { - VGAMODES * curmode=GetCurrentMode(); - switch (curmode->memmodel) { - case CGA: + switch (CurMode->type) { + case M_CGA4: { Bit16u off=(y>>1)*80+(x>>2); if (y&1) off+=8*1024; @@ -41,7 +40,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { real_writeb(0xb800,off,old); } break; - case CGA2: + case M_CGA2: { Bit16u off=(y>>1)*80+(x>>3); if (y&1) off+=8*1024; @@ -55,7 +54,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { real_writeb(0xb800,off,old); } break; - case PLANAR4: + case M_EGA16: { /* Set the correct bitmask for the pixel position */ IO_Write(0x3ce,0x8);Bit8u mask=128>>(x&7);IO_Write(0x3cf,mask); @@ -67,7 +66,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x18); } //Perhaps also set mode 1 /* Calculate where the pixel is in video memory */ - PhysPt off=0xa0000+curmode->slength*page+((y*curmode->swidth+x)>>3); + PhysPt off=0xa0000+CurMode->plength*page+((y*CurMode->swidth+x)>>3); /* Bitmask and set/reset should do the rest */ mem_readb(off); mem_writeb(off,0xff); @@ -78,23 +77,18 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); } break; } - case LINEAR8: + case M_VGA: mem_writeb(Real2Phys(RealMake(0xa000,y*320+x)),color); break; - case PLANAR1: - case PLANAR2: - case CTEXT: - case MTEXT: default: - LOG(LOG_ERROR|LOG_INT10,"PutPixel Unhandled memory model %d",curmode->memmodel); + LOG(LOG_INT10,LOG_ERROR)("PutPixel unhandled mode type %d",CurMode->type); break; } } void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { - VGAMODES * curmode=GetCurrentMode(); - switch (curmode->memmodel) { - case CGA: + switch (CurMode->type) { + case M_CGA4: { Bit16u off=(y>>1)*80+(x>>2); if (y&1) off+=8*1024; @@ -102,7 +96,7 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { *color=(val>>(((3-x&3))*2)) & 3 ; } break; - case CGA2: + case M_CGA2: { Bit16u off=(y>>1)*80+(x>>3); if (y&1) off+=8*1024; @@ -110,10 +104,10 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { *color=(val>>(((7-x&7)))) & 1 ; } break; - case PLANAR4: + case M_EGA16: { /* Calculate where the pixel is in video memory */ - PhysPt off=0xa0000+curmode->slength*page+((y*curmode->swidth+x)>>3); + PhysPt off=0xa0000+CurMode->plength*page+((y*CurMode->swidth+x)>>3); Bitu shift=7-(x & 7); /* Set the read map */ *color=0; @@ -127,15 +121,11 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { *color|=((mem_readb(off)>>shift) & 1) << 3; break; } - case LINEAR8: + case M_VGA: *color=mem_readb(PhysMake(0xa000,320*y+x)); break; - case PLANAR1: - case PLANAR2: - case CTEXT: - case MTEXT: default: - LOG(LOG_ERROR|LOG_INT10,"GetPixel Unhandled memory model %d",curmode->memmodel); + LOG(LOG_INT10,LOG_ERROR)("GetPixel unhandled mode type %d",CurMode->type); break; } } diff --git a/src/ints/int10_vesa.cpp b/src/ints/int10_vesa.cpp new file mode 100644 index 0000000..644c45a --- /dev/null +++ b/src/ints/int10_vesa.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2002-2003 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 + +#include "dosbox.h" +#include "callback.h" +#include "regs.h" +#include "mem.h" +#include "inout.h" +#include "int10.h" +#include "dos_inc.h" + +static struct { + Bitu setwindow; +} callback; + +static char string_oem[]="S3 Incorporated. Trio64"; +static char string_vendorname[]="DOSBox Development Team"; +static char string_productname[]="DOSBox - The DOS Emulator"; +static char string_productrev[]="DOSBox "VERSION; + +#ifdef _MSC_VER +#pragma pack (1) +#endif +struct MODE_INFO{ + Bit16u ModeAttributes; + Bit8u WinAAttributes; + Bit8u WinBAttributes; + Bit16u WinGranularity; + Bit16u WinSize; + Bit16u WinASegment; + Bit16u WinBSegment; + Bit32u WinFuncPtr; + Bit16u BytesPerScanLine; + Bit16u XResolution; + Bit16u YResolution; + Bit8u XCharSize; + Bit8u YCharSize; + Bit8u NumberOfPlanes; + Bit8u BitsPerPixel; + Bit8u NumberOfBanks; + Bit8u MemoryModel; + Bit8u BankSize; + Bit8u NumberOfImagePages; + Bit8u Reserved_page; + Bit8u RedMaskSize; + Bit8u RedMaskPos; + Bit8u GreenMaskSize; + Bit8u GreenMaskPos; + Bit8u BlueMaskSize; + Bit8u BlueMaskPos; + Bit8u ReservedMaskSize; + Bit8u ReservedMaskPos; + Bit8u DirectColorModeInfo; + Bit32u PhysBasePtr; + Bit32u OffScreenMemOffset; + Bit16u OffScreenMemSize; + Bit8u Reserved[206]; +} GCC_ATTRIBUTE(packed); +#ifdef _MSC_VER +#pragma pack() +#endif + + + +Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off) { + /* Fill 256 byte buffer with VESA information */ + PhysPt buffer=PhysMake(seg,off); + Bitu i; + bool vbe2=false;Bit16u vbe2_pos=256+off; + if (mem_readd(buffer)==0x32454256) vbe2=true; + if (vbe2) { + for (i=0;i<0x200;i++) mem_writeb(buffer+i,0); + } else { + for (i=0;i<0x100;i++) mem_writeb(buffer+i,0); + } + /* Fill common data */ + MEM_BlockWrite(buffer,(void *)"VESA",4); //Identification + if (vbe2) { + mem_writew(buffer+0x04,0x200); //Vesa version 0x200 + mem_writed(buffer+0x06,RealMake(seg,vbe2_pos)); + for (i=0;itype) { + case M_LIN8: //Linear 8-bit + WLE(minfo.ModeAttributes,0x9b); + WLE(minfo.WinAAttributes,0x7); //Exists/readable/writable + WLE(minfo.WinGranularity,64); + WLE(minfo.WinSize,64); + WLE(minfo.WinASegment,0xa000); +// WLE(minfo.WinBSegment,0xa000); + WLE(minfo.WinFuncPtr,CALLBACK_RealPointer(callback.setwindow)); + WLE(minfo.BytesPerScanLine,mblock->swidth); + WLE(minfo.NumberOfPlanes,0x1); + WLE(minfo.BitsPerPixel,0x08); + WLE(minfo.NumberOfBanks,0x1); + WLE(minfo.MemoryModel,0x04); //packed pixel + WLE(minfo.NumberOfImagePages,0x05); + WLE(minfo.Reserved_page,0x1); + break; + } + WLE(minfo.XResolution,mblock->swidth); + WLE(minfo.YResolution,mblock->sheight); + WLE(minfo.XCharSize,mblock->cwidth); + WLE(minfo.YCharSize,mblock->cheight); + WLE(minfo.PhysBasePtr,S3_LFB_BASE); + + MEM_BlockWrite(buf,&minfo,sizeof(MODE_INFO)); + return 0x00; +} + + +Bit8u VESA_SetSVGAMode(Bit16u mode) { + if (INT10_SetVideoMode(mode)) return 0x00; + return 0x01; +}; + +Bit8u VESA_GetSVGAMode(Bit16u & mode) { + mode=CurMode->mode; + return 0x00; +} + +Bit8u VESA_SetCPUWindow(Bit8u window,Bit16u address) { + if (window) return 0x1; + if ((address<32)) { + IO_Write(0x3d4,0x6a); + IO_Write(0x3d5,(Bit8u)address); + return 0x0; + } else return 0x1; +} + +Bit8u VESA_GetCPUWindow(Bit8u window,Bit16u & address) { + if (window) return 0x1; + IO_Write(0x3d4,0x6a); + address=IO_Read(0x3d5); + return 0x0; +} + + +Bit8u VESA_SetPalette(PhysPt data,Bitu index,Bitu count) { + if (index>255) return 0x1; + if (index+count>256) return 0x1; + IO_Write(0x3c8,index); + while (count) { + IO_Write(0x3c9,mem_readb(data++)); + IO_Write(0x3c9,mem_readb(data++)); + IO_Write(0x3c9,mem_readb(data++)); + data++; + count--; + } + return 0x00; +} + + +Bit8u VESA_GetPalette(PhysPt data,Bitu index,Bitu count) { + if (index>255) return 0x1; + if (index+count>256) return 0x1; + IO_Write(0x3c7,index); + while (count) { + mem_writeb(data++,IO_Read(0x3c9)); + mem_writeb(data++,IO_Read(0x3c9)); + mem_writeb(data++,IO_Read(0x3c9)); + data++; + count--; + } + return 0x00; +} + + +Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u & bytes,Bit16u & pixels,Bit16u & lines) { + Bit8u bpp; + switch (CurMode->type) { + case M_LIN8: + bpp=1;break; + default: + return 0x1; + } + Bitu scan_len; + lines=0xfff; //Does anyone care? + switch (subcall) { + case 0x00: /* Set in pixels */ + bytes=(pixels*bpp); + case 0x02: /* Set in bytes */ + scan_len=bytes/4; + if (bytes % 4) scan_len++; + vga.config.scan_len=scan_len; + VGA_StartResize(); + break; + case 0x03: /* Get maximum */ + bytes=0x400*4; + pixels=bytes/bpp; + return 0x00; + case 0x01: /* Get lengths */ + break; + default: + return 0x1; //Illegal call + } + /* Write the scan line to video card the simple way */ + pixels=(vga.config.scan_len*4)/bpp; + bytes=vga.config.scan_len*4; + return 0x0; +} + + +/* Based of the s3 univbe driver */ +static Bit8u PmodeInterface[]={ + 0x08,0x00,0x19,0x00,0x57,0x00,0x00,0x00,0x50,0x52,0x8b,0xc2,0x8a,0xe0,0xb0,0x6a, + 0x66,0xba,0xd4,0x03,0x66,0xef,0x5a,0x58,0xc3,0x52,0x66,0xba,0xda,0x03,0xec,0xa8, + 0x01,0x75,0xfb,0x5a,0x53,0x8a,0xf9,0xb3,0x0d,0xb1,0x0c,0x66,0x8b,0xf2,0x66,0xba, + 0xd4,0x03,0x66,0x8b,0xc3,0x66,0xef,0x66,0x8b,0xc1,0x66,0xef,0x66,0x8b,0xde,0x8a, + 0xe3,0xb0,0x69,0x66,0xef,0x5b,0x52,0xf6,0xc3,0x80,0x74,0x09,0x66,0xba,0xda,0x03, + 0xec,0xa8,0x08,0x74,0xfb,0x5a,0xc3,0xf6,0xc3,0x80,0x74,0x10,0x52,0x66,0xba,0xda, + 0x03,0xec,0xa8,0x08,0x75,0xfb,0xec,0xa8,0x08,0x74,0xfb,0x5a,0x1e,0x06,0x1f,0x0f, + 0xb7,0xc9,0x8b,0xc2,0x66,0xba,0xc8,0x03,0xee,0x42,0xfc,0x8a,0x47,0x02,0xee,0x8a, + 0x47,0x01,0xee,0x8a,0x07,0xee,0x83,0xc7,0x04,0x49,0x75,0xef,0x1f,0xc3 +}; + +Bit8u VESA_SetDisplayStart(Bit16u x,Bit16u y) { + //TODO Maybe do things differently with lowres double line modes? + Bitu start; + switch (CurMode->type) { + case M_LIN8: + start=vga.config.scan_len*8*y+x; + vga.config.display_start=start/4; + IO_Read(0x3da); + IO_Write(0x3c0,0x13+32); + IO_Write(0x3c0,(start % 4)*2); + break; + default: + return 0x1; + } + return 0x00; +} + +Bit8u VESA_GetDisplayStart(Bit16u & x,Bit16u & y) { + Bitu times=(vga.config.display_start*4)/(vga.config.scan_len*8); + Bitu rem=(vga.config.display_start*4) % (vga.config.scan_len*8); + Bitu pan=vga.config.pel_panning; + switch (CurMode->type) { + case M_LIN8: + y=times; + x=rem*4+pan; + break; + default: + 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); + reg_al=0x4f; + return 0; +} + + +void INT10_SetupVESA(void) { + /* Put the mode list somewhere in memory */ + Bitu i; + i=0; + int10.rom.vesa_modes=RealMake(0xc000,int10.rom.used); +//TODO Maybe add normal vga modes too, but only seems to complicate things + while (ModeList[i].mode!=0xffff) { + if (ModeList[i].mode>=0x100){ + phys_writew(PhysMake(0xc000,int10.rom.used),ModeList[i].mode); + int10.rom.used+=2; + } + i++; + } + phys_writew(PhysMake(0xc000,int10.rom.used),0xffff); + int10.rom.used+=2; + int10.rom.oemstring=RealMake(0xc000,int10.rom.used); + Bitu len=strlen(string_oem)+1; + for (i=0;i #include "dosbox.h" @@ -181,18 +182,19 @@ void SaveVgaRegisters() for (int i=0; i<9; i++) { IO_Write (0x3CE,i); gfxReg[i] = IO_Read(0x3CF); - }; - // Set default - INT10_SetGfxControllerToDefault(); -}; + } + /* Setup some default values in GFX regs that should work */ + IO_Write (0x3CE,3);IO_Write(0x3Cf,0); //disable rotate and operation + IO_Write (0x3CE,5);IO_Write(0x3Cf,0); //Force read/write mode 0 +} void RestoreVgaRegisters() { for (int i=0; i<9; i++) { IO_Write(0x3CE,i); IO_Write(0x3CF,gfxReg[i]); - }; -}; + } +} void ClipCursorArea(Bit16s& x1, Bit16s& x2, Bit16s& y1, Bit16s& y2, Bit16u& addx1, Bit16u& addx2, Bit16u& addy) { @@ -253,18 +255,18 @@ void DrawCursor() { if (mouse.shown<0) return; // Get Clipping ranges - VGAMODES * curmode=GetCurrentMode(); - if (!curmode) return; - + // In Textmode ? - if (curmode->type==TEXT) { + if (CurMode->type==M_TEXT16) { DrawCursorText(); return; } - mouse.clipx = curmode->swidth-1; - mouse.clipy = curmode->sheight-1; - + mouse.clipx = CurMode->swidth-1; /* Get from bios ? */ + mouse.clipy = CurMode->sheight-1; + Bit16s xratio = 640 / CurMode->swidth; /* might be mouse.max_x-.mouse.min_x+1/swidth */ + /* might even be vidmode == 0x13?2:1 */ + RestoreCursorBackground(); SaveVgaRegisters(); @@ -273,7 +275,7 @@ void DrawCursor() { Bit16s x,y; Bit16u addx1,addx2,addy; Bit16u dataPos = 0; - Bit16s x1 = POS_X - mouse.hotx; + Bit16s x1 = POS_X / xratio - mouse.hotx; Bit16s y1 = POS_Y - mouse.hoty; Bit16s x2 = x1 + CURSORX - 1; Bit16s y2 = y1 + CURSORY - 1; @@ -289,7 +291,7 @@ void DrawCursor() { dataPos += addx2; }; mouse.background= true; - mouse.backposx = POS_X - mouse.hotx; + mouse.backposx = POS_X / xratio - mouse.hotx; mouse.backposy = POS_Y - mouse.hoty; // Draw Mousecursor @@ -389,9 +391,10 @@ static void SetMickeyPixelRate(Bit16s px, Bit16s py) } }; -void Mouse_SetResolution(Bit16u width, Bit16u height) -{ - mouse.shown = -1; // hide cursor +static void mouse_reset_hardware(void){ + mouse.sub_mask=0; + mouse.sub_seg=0; + mouse.sub_ofs=0; }; static void mouse_reset(void) @@ -425,7 +428,7 @@ static void mouse_reset(void) break; default: mouse.max_y=199; - LOG(LOG_MOUSE|LOG_ERROR,"Unhandled videomode %X on reset",mode); + LOG(LOG_MOUSE,LOG_ERROR)("Unhandled videomode %X on reset",mode); break; } mouse.max_x=639; @@ -433,13 +436,10 @@ static void mouse_reset(void) mouse.min_y=0; // Dont set max coordinates here. it is done by SetResolution! mouse.x=0; // civ wont work otherwise - mouse.y=mouse.max_y/2; + mouse.y=static_cast(mouse.max_y/2); mouse.events=0; mouse.mickey_x=0; mouse.mickey_y=0; - mouse.sub_mask=0; - mouse.sub_seg=0; - mouse.sub_ofs=0; mouse.hotx = 0; mouse.hoty = 0; @@ -452,14 +452,22 @@ static void mouse_reset(void) SetMickeyPixelRate(8,16); } +void Mouse_NewVideoMode(void) +{ + //mouse.shown = -1; + mouse_reset(); + //Added this for cd-v19 +} + static Bitu INT33_Handler(void) { -// LOG(0,"MOUSE: %04X",reg_ax); +// LOG(LOG_MOUSE,LOG_NORMAL)("MOUSE: %04X",reg_ax); switch (reg_ax) { case 0x00: /* Reset Driver and Read Status */ + mouse_reset_hardware(); /* fallthrough */ case 0x21: /* Software Reset */ reg_ax=0xffff; - reg_bx=MOUSE_BUTTONS; + reg_bx=MOUSE_BUTTONS; mouse_reset(); Mouse_AutoLock(true); break; @@ -471,9 +479,8 @@ static Bitu INT33_Handler(void) { break; case 0x02: /* Hide Mouse */ { - VGAMODES * curmode=GetCurrentMode(); - if (curmode && curmode->type==GRAPH) RestoreCursorBackground(); - else RestoreCursorBackgroundText(); + if (CurMode->type!=M_TEXT16) RestoreCursorBackground(); + else RestoreCursorBackgroundText(); mouse.shown--; } break; @@ -483,8 +490,8 @@ static Bitu INT33_Handler(void) { reg_dx=POS_Y; break; case 0x04: /* Position Mouse */ - mouse.x=(float)reg_cx; - mouse.y=(float)reg_dx; + mouse.x = static_cast(((reg_cx > mouse.max_x) ? mouse.max_x : reg_cx)); + mouse.y = static_cast(((reg_dx > mouse.max_y) ? mouse.max_y : reg_dx)); DrawCursor(); break; case 0x05: /* Return Button Press Data */ @@ -510,25 +517,27 @@ static Bitu INT33_Handler(void) { break; } case 0x07: /* Define horizontal cursor range */ - { + { //lemmings set 1-640 and wants that. iron seeds set 0-640 but doesn't like 640 Bits max,min; if ((Bit16s)reg_cx<(Bit16s)reg_dx) { min=(Bit16s)reg_cx;max=(Bit16s)reg_dx;} else { min=(Bit16s)reg_dx;max=(Bit16s)reg_cx;} - if (!(max & 1)) max--; + //if(max - min + 1 > 640) max = min + 640 - 1; mouse.min_x=min; mouse.max_x=max; - LOG(LOG_MOUSE,"Define Hortizontal range min:%d max:%d",min,max); + LOG(LOG_MOUSE,LOG_NORMAL)("Define Hortizontal range min:%d max:%d",min,max); } break; case 0x08: /* Define vertical cursor range */ - { + { // not sure what to take instead of the CurMode (see case 0x07 as well) + // especially the cases where sheight= 400 and we set it with the mouse_reset to 200 + //disabled it at the moment. Seems to break syndicate who want 400 in mode 13 Bits max,min; if ((Bit16s)reg_cx<(Bit16s)reg_dx) { min=(Bit16s)reg_cx;max=(Bit16s)reg_dx;} else { min=(Bit16s)reg_dx;max=(Bit16s)reg_cx;} - if (!(max & 1)) max--; + // if(static_cast(max - min + 1) > CurMode->sheight) max = min + CurMode->sheight - 1; mouse.min_y=min; mouse.max_y=max; - LOG(LOG_MOUSE,"Define Vertical range min:%d max:%d",min,max); + LOG(LOG_MOUSE,LOG_NORMAL)("Define Vertical range min:%d max:%d",min,max); } break; case 0x09: /* Define GFX Cursor */ @@ -595,7 +604,7 @@ static Bitu INT33_Handler(void) { reg_cl=0; /* Hmm ps2 irq dunno */ break; default: - LOG(LOG_ERROR|LOG_MOUSE,"Mouse Function %2X",reg_ax); + LOG(LOG_MOUSE,LOG_ERROR)("Mouse Function %2X",reg_ax); } return CBRET_NONE; } @@ -630,6 +639,7 @@ static Bitu INT74_Handler(void) { } } IO_Write(0xa0,0x20); + IO_Write(0x20,0x20); /* Check for more Events if so reactivate IRQ */ if (mouse.events) { PIC_ActivateIRQ(12); @@ -652,11 +662,11 @@ void CreateMouseCallback(void) // Create a mouse vector with weird address // for strange mouse detection routines in Sim City & Wasteland Bit16u ofs = call_int33<<4; - real_writeb((Bit16u)CB_SEG,ofs+0,(Bit8u)0x90); //NOP - real_writeb((Bit16u)CB_SEG,ofs+1,(Bit8u)0xFE); //GRP 4 - real_writeb((Bit16u)CB_SEG,ofs+2,(Bit8u)0x38); //Extra Callback instruction - real_writew((Bit16u)CB_SEG,ofs+3,call_int33); //The immediate word - real_writeb((Bit16u)CB_SEG,ofs+5,(Bit8u)0xCF); //An IRET Instruction + phys_writeb(CB_BASE+ofs+0,(Bit8u)0x90); //NOP + phys_writeb(CB_BASE+ofs+1,(Bit8u)0xFE); //GRP 4 + phys_writeb(CB_BASE+ofs+2,(Bit8u)0x38); //Extra Callback instruction + phys_writew(CB_BASE+ofs+3,call_int33); //The immediate word + phys_writeb(CB_BASE+ofs+5,(Bit8u)0xCF); //An IRET Instruction // Write weird vector WriteMouseIntVector(); }; @@ -671,6 +681,7 @@ void MOUSE_Init(Section* sec) { real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); memset(&mouse,0,sizeof(mouse)); + mouse_reset_hardware(); mouse_reset(); } diff --git a/src/ints/xms.cpp b/src/ints/xms.cpp index be28a19..f610ef9 100644 --- a/src/ints/xms.cpp +++ b/src/ints/xms.cpp @@ -24,7 +24,8 @@ #include "regs.h" #include "dos_system.h" #include "setup.h" - +#include "inout.h" +#include "xms.h" #define XMS_HANDLES 50 /* 50 XMS Memory Blocks */ #define XMS_VERSION 0x0300 /* version 3.00 */ @@ -49,7 +50,8 @@ #define XMS_ALLOCATE_UMB 0x10 #define XMS_DEALLOCATE_UMB 0x11 -#define HIGH_MEMORY_IN_USE 0x92 +#define HIGH_MEMORY_NOT_EXIST 0x90 +#define HIGH_MEMORY_IN_USE 0x91 #define HIGH_MEMORY_NOT_ALLOCATED 0x93 #define XMS_OUT_OF_SPACE 0xa0 #define XMS_OUT_OF_HANDLES 0xa1 @@ -58,33 +60,10 @@ #define XMS_BLOCK_LOCKED 0xab struct XMS_Block { - Bit16u prev,next; - Bit16u size; /* Size in kb's */ - PhysPt phys; - Bit8u locked; - void * data; - bool active; -}; - -static Bit16u call_xms; -static RealPt xms_callback; - -static XMS_Block xms_handles[XMS_HANDLES]; - - - -static bool multiplex_xms(void) { - switch (reg_ax) { - case 0x4300: /* XMS installed check */ - reg_al=0x80; - return true; - case 0x4310: /* XMS handler seg:offset */ - SegSet16(es,RealSeg(xms_callback)); - reg_bx=RealOff(xms_callback); - return true; - } - return false; - + Bitu size; + MemHandle mem; + Bit8u locked; + bool free; }; #pragma pack (push,1) @@ -104,219 +83,237 @@ struct XMS_MemMove{ } GCC_ATTRIBUTE(packed); #pragma pack (pop) +Bitu XMS_EnableA20(bool enable) +{ + Bit8u val = IO_Read (0x92); + if (enable) IO_Write(0x92,val | 2); + else IO_Write(0x92,val & ~2); + return 0; +}; + +Bitu XMS_GetEnabledA20(void) +{ + return (IO_Read(0x92)&2)>0; +}; + +static Bit16u call_xms; +static RealPt xms_callback; + +static XMS_Block xms_handles[XMS_HANDLES]; + +static INLINE bool InvalidHandle(Bitu handle) { + return (!handle || (handle>=XMS_HANDLES) || xms_handles[handle].free); +} + +Bitu XMS_QueryFreeMemory(Bit16u& largestFree, Bit16u& totalFree) { + /* Scan the tree for free memory and find largest free block */ + totalFree=(Bit16u)(MEM_FreeTotal()*4); + largestFree=(Bit16u)(MEM_FreeLargest()*4); + if (!totalFree) return XMS_OUT_OF_SPACE; + return 0; +}; + +Bitu XMS_AllocateMemory(Bitu size, Bit16u& handle) +// size = kb +{ + /* Find free handle */ + Bit16u index=1; + while (!xms_handles[index].free) { + if (++index>XMS_HANDLES) return XMS_OUT_OF_HANDLES; + } + Bitu pages=(size/4) + ((size & 3) ? 1 : 0); + MemHandle mem=MEM_AllocatePages(pages,true); + if (!mem) return XMS_OUT_OF_SPACE; + xms_handles[index].free=false; + xms_handles[index].mem=mem; + xms_handles[index].locked=0; + xms_handles[index].size=size; + handle=index; + return 0; +}; + +Bitu XMS_FreeMemory(Bitu handle) +{ + if (InvalidHandle(handle)) return XMS_INVALID_HANDLE; + MEM_ReleasePages(xms_handles[handle].mem); + xms_handles[handle].mem=-1; + xms_handles[handle].size=0; + xms_handles[handle].free=true; + return 0; +}; + +Bitu XMS_MoveMemory(PhysPt bpt) +{ + /* Read the block with mem_read's */ + Bitu length=mem_readd(bpt+offsetof(XMS_MemMove,length)); + Bitu src_handle=mem_readw(bpt+offsetof(XMS_MemMove,src_handle)); + union { + RealPt realpt; + Bit32u offset; + } src,dest; + src.offset=mem_readd(bpt+offsetof(XMS_MemMove,src.offset)); + Bitu dest_handle=mem_readw(bpt+offsetof(XMS_MemMove,dest_handle)); + dest.offset=mem_readd(bpt+offsetof(XMS_MemMove,dest.offset)); + PhysPt srcpt,destpt; + if (src_handle) { + if (InvalidHandle(src_handle)) { + return 0xa3; /* Src Handle invalid */ + } + if (src.offset>=(xms_handles[src_handle].size*1024U)) { + return 0xa4; /* Src Offset invalid */ + } + if (length>xms_handles[src_handle].size*1024U-src.offset) { + return 0xa7; /* Length invalid */ + } + srcpt=(xms_handles[src_handle].mem*4096)+src.offset; + } else { + srcpt=Real2Phys(src.realpt); + } + if (dest_handle) { + if (InvalidHandle(dest_handle)) { + return 0xa3; /* Dest Handle invalid */ + } + if (dest.offset>=(xms_handles[dest_handle].size*1024U)) { + return 0xa4; /* Dest Offset invalid */ + } + if (length>xms_handles[dest_handle].size*1024U-dest.offset) { + return 0xa7; /* Length invalid */ + } + destpt=(xms_handles[dest_handle].mem*4096)+dest.offset; + } else { + destpt=Real2Phys(dest.realpt); + } +// LOG_MSG("XMS move src %X dest %X length %X",srcpt,destpt,length); + mem_memcpy(destpt,srcpt,length); + return 0; +} + +Bitu XMS_LockMemory(Bitu handle, Bit32u& address) +{ + if (InvalidHandle(handle)) return XMS_INVALID_HANDLE; + if (xms_handles[handle].locked<255) xms_handles[handle].locked++; + address = xms_handles[handle].mem*4096; + return 0; +}; + +Bitu XMS_UnlockMemory(Bitu handle) +{ + if (InvalidHandle(handle)) return XMS_INVALID_HANDLE; + if (xms_handles[handle].locked) { + xms_handles[handle].locked--; + return 0; + } + return XMS_BLOCK_NOT_LOCKED; +}; + +Bitu XMS_GetHandleInformation(Bitu handle, Bit8u& lockCount, Bit8u& numFree, Bit16u& size) +{ + if (InvalidHandle(handle)) return XMS_INVALID_HANDLE; + lockCount = xms_handles[handle].locked; + /* Find available blocks */ + numFree=0; + for (Bitu i=1;i0) return XMS_BLOCK_LOCKED; + Bitu pages=newSize/4 + ((newSize & 3) ? 1 : 0); + if (MEM_ReAllocatePages(xms_handles[handle].mem,pages,true)) { + return 0; + } else return XMS_OUT_OF_SPACE; +} + +static bool multiplex_xms(void) { + switch (reg_ax) { + case 0x4300: /* XMS installed check */ + reg_al=0x80; + return true; + case 0x4310: /* XMS handler seg:offset */ + SegSet16(es,RealSeg(xms_callback)); + reg_bx=RealOff(xms_callback); + return true; + } + return false; + +}; + Bitu XMS_Handler(void) { +// LOG(LOG_MISC,LOG_ERROR)("XMS: CALL %02X",reg_ah); switch (reg_ah) { + case XMS_GET_VERSION: /* 00 */ reg_ax=XMS_VERSION; reg_bx=XMS_DRIVER_VERSION; reg_dx=0; /* No we don't have HMA */ break; case XMS_ALLOCATE_HIGH_MEMORY: /* 01 */ + reg_ax=0; + reg_bl=HIGH_MEMORY_NOT_EXIST; + break; case XMS_FREE_HIGH_MEMORY: /* 02 */ + reg_ax=0; + reg_bl=HIGH_MEMORY_NOT_EXIST; + break; + case XMS_GLOBAL_ENABLE_A20: /* 03 */ - case XMS_GLOBAL_DISABLE_A20: /* 04 */ case XMS_LOCAL_ENABLE_A20: /* 05 */ + reg_bl = XMS_EnableA20(true); + reg_ax = (reg_bl==0); + break; + case XMS_GLOBAL_DISABLE_A20: /* 04 */ case XMS_LOCAL_DISABLE_A20: /* 06 */ - case XMS_QUERY_A20: /* 07 */ - LOG(LOG_ERROR|LOG_MISC,"XMS:Unhandled call %2X",reg_ah); + reg_bl = XMS_EnableA20(false); + reg_ax = (reg_bl==0); break; + case XMS_QUERY_A20: /* 07 */ + reg_ax = XMS_GetEnabledA20(); + reg_bl = 0; + break; case XMS_QUERY_FREE_EXTENDED_MEMORY: /* 08 */ - /* Scan the tree for free memory and find largest free block */ - { - Bit16u index=1;reg_ax=0;reg_dx=0; - while (xms_handles[index].active) { - if (!xms_handles[index].data) { - if(xms_handles[index].size>reg_ax) reg_ax=xms_handles[index].size; - reg_dx+=xms_handles[index].size; - } - if (xms_handles[index].next=reg_dx) { - /* Check if block is bigger than request */ - if (xms_handles[index].size>reg_dx) { - /* Split Block, find new handle and split up memory */ - Bit16u new_index=1; - while (new_index=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) { - reg_ax=0; - reg_bl=XMS_INVALID_HANDLE; - return CBRET_NONE; - } - /* Remove the mapping to the memory */ - MEM_ClearMapping(PAGE_COUNT(xms_handles[reg_dx].phys),PAGE_COUNT(xms_handles[reg_dx].size*1024)); - /* Free the memory in the block and merge the blocks previous and next block */ - Bit16u prev=xms_handles[reg_dx].prev; - Bit16u next=xms_handles[reg_dx].next; - free(xms_handles[reg_dx].data); - xms_handles[reg_dx].data=0; - if ((next=XMS_HANDLES) || !xms_handles[block.src_handle].active ||!xms_handles[block.src_handle].data) { - reg_ax=0; - reg_bl=0xa3; /* Src Handle invalid */ - return CBRET_NONE; - } - if (block.src.offset>=(xms_handles[block.src_handle].size*1024U)) { - reg_ax=0; - reg_bl=0xa4; /* Src Offset invalid */ - return CBRET_NONE; - } - if (block.length>xms_handles[block.src_handle].size*1024U-block.src.offset) { - reg_ax=0; - reg_bl=0xa7; /* Length invalid */ - return CBRET_NONE; - - } - src=xms_handles[block.src_handle].phys+block.src.offset; - } else { - src=Real2Phys(block.src.realpt); - } - if (block.dest_handle) { - if ((block.dest_handle>=XMS_HANDLES) || !xms_handles[block.dest_handle].active ||!xms_handles[block.dest_handle].data) { - reg_ax=0; - reg_bl=0xa3; /* Dest Handle invalid */ - return CBRET_NONE; - } - if (block.dest.offset>=(xms_handles[block.dest_handle].size*1024U)) { - reg_ax=0; - reg_bl=0xa4; /* Dest Offset invalid */ - return CBRET_NONE; - } - if (block.length>xms_handles[block.dest_handle].size*1024U-block.dest.offset) { - reg_ax=0; - reg_bl=0xa7; /* Length invalid */ - return CBRET_NONE; - } - dest=xms_handles[block.dest_handle].phys+block.dest.offset; - } else { - dest=Real2Phys(block.dest.realpt); - } - MEM_BlockCopy(dest,src,block.length); - reg_ax=1;reg_bl=0; - } + reg_bl = XMS_MoveMemory(SegPhys(ds)+reg_si); + reg_ax = (reg_bl==0); break; - case XMS_LOCK_EXTENDED_MEMORY_BLOCK: /* 0c */ - { - /* Check for a valid handle */ - if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) { - reg_ax=0; - reg_bl=XMS_INVALID_HANDLE; - return CBRET_NONE; - } - if (xms_handles[reg_dx].locked<255) xms_handles[reg_dx].locked++; - reg_bx=(Bit16u)(xms_handles[reg_dx].phys & 0xFFFF); - reg_dx=(Bit16u)(xms_handles[reg_dx].phys>>16); - reg_ax=1; - break; - } + case XMS_LOCK_EXTENDED_MEMORY_BLOCK: { /* 0c */ + Bit32u address; + reg_bl = XMS_LockMemory(reg_dx, address); + if (reg_bl==0) { // success + reg_bx=(Bit16u)(address & 0xFFFF); + reg_dx=(Bit16u)(address >> 16); + }; + reg_ax = (reg_bl==0); + }; break; case XMS_UNLOCK_EXTENDED_MEMORY_BLOCK: /* 0d */ - /* Check for a valid handle */ - if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) { - reg_ax=0; - reg_bl=XMS_INVALID_HANDLE; - return CBRET_NONE; - } - if (xms_handles[reg_dx].locked) { - xms_handles[reg_dx].locked--; - reg_ax=1;reg_bl=0; - } else { - reg_ax=0; - reg_bl=XMS_BLOCK_NOT_LOCKED; - } + reg_bl = XMS_UnlockMemory(reg_dx); + reg_ax = (reg_bl==0); break; case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */ - /* Check for a valid handle */ - if (!reg_dx || (reg_dx>=XMS_HANDLES) || !xms_handles[reg_dx].active || !xms_handles[reg_dx].data ) { - reg_ax=0; - reg_bl=XMS_INVALID_HANDLE; - return CBRET_NONE; - } - reg_bh=xms_handles[reg_dx].locked; - /* Find available blocks */ - reg_bx=0;{ for (Bitu i=1;i(sec); - Bitu size=section->Get_int("xmssize"); - if (!size) return; - if (size>C_MEM_MAX_SIZE-1) size=C_MEM_MAX_SIZE-1; + if (!section->Get_bool("xms")) return; + Bitu i; + DOS_AddMultiplexHandler(multiplex_xms); call_xms=CALLBACK_Allocate(); CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF); xms_callback=CALLBACK_RealPointer(call_xms); - /* Setup the handler table */ - Bitu i; for (i=0;iGetEnvironment(),0); - while (*envscan) envscan+=strlen(envscan)+1; + PhysPt envscan=PhysMake(psp->GetEnvironment(),0); + while (mem_readb(envscan)) envscan+=mem_strlen(envscan)+1; envscan+=3; CommandTail tail; MEM_BlockRead(PhysMake(dos.psp,128),&tail,128); if (tail.count<127) tail.buffer[tail.count]=0; else tail.buffer[126]=0; - cmd = new CommandLine(envscan,tail.buffer); + char filename[256]; + MEM_StrCopy(envscan,filename,256); + cmd = new CommandLine(filename,tail.buffer); } void Program::WriteOut(const char * format,...) { diff --git a/src/misc/setup.cpp b/src/misc/setup.cpp index 5209172..39785d0 100644 --- a/src/misc/setup.cpp +++ b/src/misc/setup.cpp @@ -155,7 +155,7 @@ void Section_line::PrintData(FILE* outfile) { } void Config::PrintConfig(const char* configfilename){ - char temp[50]; + char temp[50];char helpline[256]; FILE* outfile=fopen(configfilename,"w+t"); if(outfile==NULL) return; for (it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ @@ -165,9 +165,20 @@ void Config::PrintConfig(const char* configfilename){ fprintf(outfile,"[%s]\n",temp); upcase(temp); strcat(temp,"_CONFIGFILE_HELP"); - fprintf(outfile,"# %s",MSG_Get(temp)); + const char * helpstr=MSG_Get(temp); + char * helpwrite=helpline; + while (*helpstr) { + *helpwrite++=*helpstr; + if (*helpstr == '\n') { + *helpwrite=0; + fprintf(outfile,"# %s",helpline); + helpwrite=helpline; + } + helpstr++; + } + fprintf(outfile,"\n"); (*tel)->PrintData(outfile); - fprintf(outfile,"\n"); /* Always an empty line between sections */ + fprintf(outfile,"\n"); /* Always an empty line between sections */ } fclose(outfile); } @@ -313,7 +324,7 @@ bool CommandLine::FindString(char * name,std::string & value,bool remove) { return true; } -bool CommandLine::FindCommand(int which,std::string & value) { +bool CommandLine::FindCommand(unsigned int which,std::string & value) { if (which<1) return false; if (which>cmds.size()) return false; cmd_it it=cmds.begin(); @@ -356,7 +367,7 @@ bool CommandLine::FindStringRemain(char * name,std::string & value) { } -int CommandLine::GetCount(void) { +unsigned int CommandLine::GetCount(void) { return cmds.size(); } diff --git a/src/misc/support.cpp b/src/misc/support.cpp index dd9a9bf..ca70674 100644 --- a/src/misc/support.cpp +++ b/src/misc/support.cpp @@ -16,6 +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 $ */ #include #include @@ -25,6 +26,7 @@ #include #include #include "dosbox.h" +#include "debug.h" #include "support.h" #include "video.h" @@ -88,7 +90,7 @@ bool ScanCMDBool(char * cmd,char * check) { while ((scan=strchr(scan,'/'))) { /* found a / now see behind it */ scan++; - if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]==0)) { + if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]=='/' || scan[c_len]==0)) { /* Found a math now remove it from the string */ memmove(scan-1,scan+c_len,strlen(scan+c_len)+1); trim(scan-1); @@ -155,33 +157,16 @@ char * StripWord(char * cmd) { return trim(cmd+strlen(begin)+1); } -void GFX_ShowMsg(char * msg); - -void S_Warn(char * format,...) { - char buf[1024]; +static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95) +void E_Exit(char * format,...) { +#if C_DEBUG && C_HEAVY_DEBUG + DEBUG_HeavyWriteLogInstruction(); +#endif va_list msg; - va_start(msg,format); vsprintf(buf,format,msg); va_end(msg); -#if C_DEBUG - DEBUG_ShowMsg(0,buf); -#else - GFX_ShowMsg(buf); -#endif -} + strcat(buf,"\n"); -static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95) -void E_Exit(char * format,...) { - if(errorlevel>=1) { - va_list msg; - va_start(msg,format); - vsprintf(buf,format,msg); - va_end(msg); - - strcat(buf,"\n"); - } else { - strcpy(buf,"an unsupported feature\n"); - } throw(buf); } diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in index c31af00..65973d2 100644 --- a/src/platform/Makefile.in +++ b/src/platform/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,89 +13,136 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ SUBDIRS = visualc subdir = src/platform +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = -RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ - uninstall-info-recursive all-recursive install-data-recursive \ - install-exec-recursive installdirs-recursive install-recursive \ - uninstall-recursive check-recursive installcheck-recursive -DIST_COMMON = Makefile.am Makefile.in +RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ + ps-recursive install-info-recursive uninstall-info-recursive \ + all-recursive install-data-recursive install-exec-recursive \ + installdirs-recursive install-recursive uninstall-recursive \ + check-recursive installcheck-recursive +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am DIST_SUBDIRS = $(SUBDIRS) all: all-recursive @@ -161,10 +208,17 @@ tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -180,9 +234,15 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ + if (etags --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + else \ + include_option=--include; \ + fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ - test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + test -f $$subdir/TAGS && \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ @@ -195,20 +255,41 @@ TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -266,7 +347,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -276,7 +357,7 @@ clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive - + -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive @@ -298,31 +379,39 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive - + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive -.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ - clean-generic clean-recursive distclean distclean-generic \ - distclean-recursive distclean-tags distdir dvi dvi-am \ - dvi-recursive info info-am info-recursive install install-am \ - install-data install-data-am install-data-recursive \ +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \ + clean-generic clean-recursive ctags ctags-recursive distclean \ + distclean-generic distclean-recursive distclean-tags distdir \ + dvi dvi-am dvi-recursive info info-am info-recursive install \ + install-am install-data install-data-am install-data-recursive \ install-exec install-exec-am install-exec-recursive \ install-info install-info-am install-info-recursive install-man \ install-recursive install-strip installcheck installcheck-am \ installdirs installdirs-am installdirs-recursive \ maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-generic \ - mostlyclean-recursive tags tags-recursive uninstall \ - uninstall-am uninstall-info-am uninstall-info-recursive \ - uninstall-recursive + mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \ + ps-recursive tags tags-recursive uninstall uninstall-am \ + uninstall-info-am uninstall-info-recursive uninstall-recursive # 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. diff --git a/src/platform/visualc/Makefile.in b/src/platform/visualc/Makefile.in index fa436d6..ca8ad37 100644 --- a/src/platform/visualc/Makefile.in +++ b/src/platform/visualc/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,84 +13,130 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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 = dirent.c dirent.h unistd.h config.h subdir = src/platform/visualc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am all: all-am .SUFFIXES: @@ -103,13 +149,22 @@ 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) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -134,7 +189,6 @@ check: check-am all-am: Makefile installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -154,7 +208,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -164,6 +218,7 @@ clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am + -rm -f Makefile distclean-am: clean-am distclean-generic @@ -186,6 +241,7 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -193,6 +249,14 @@ 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 \ @@ -201,7 +265,8 @@ uninstall-am: uninstall-info-am install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic uninstall uninstall-am uninstall-info-am + 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. diff --git a/src/platform/visualc/config.h b/src/platform/visualc/config.h index 811ebc7..f05615f 100644 --- a/src/platform/visualc/config.h +++ b/src/platform/visualc/config.h @@ -1,6 +1,6 @@ #define INLINE __forceinline -#define VERSION "0.58" +#define VERSION "0.60" /* Define to 1 to enable internal debugger, requires libcurses */ #define C_DEBUG 0 @@ -8,16 +8,22 @@ /* Define to 1 to enable screenshots, requires libpng */ #define C_SSHOT 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 -/* Enable some big compile-time increasing inlines */ -#define C_EXTRAINLINE 0 +/* Enable memory function inlining in */ +#define C_CORE_INLINE 0 /* Enable the FPU module, still only for beta testing */ -#define C_FPU 0 +#define C_FPU 1 -/* Maximum memory address range in megabytes */ -#define C_MEM_MAX_SIZE 12 +/* environ is defined */ +#define ENVIRON_INCLUDED 1 + +/* environ can be linked */ +#define ENVIRON_LINKED 1 #define GCC_ATTRIBUTE(x) /* attribute not supported */ diff --git a/src/platform/visualc/dirent.c b/src/platform/visualc/dirent.c index cc536bf..d2e25c2 100644 --- a/src/platform/visualc/dirent.c +++ b/src/platform/visualc/dirent.c @@ -20,7 +20,7 @@ DIR * opendir(const char *dirname) { static DIR dir; - int len; + size_t len; /* Stash the directory name */ strcpy(dir.pathName,dirname); @@ -81,7 +81,7 @@ struct dirent * readdir(DIR *dirp) { memset(&d,'\0', sizeof(struct dirent)); strcpy(d.d_name,dirp->findFileData.cFileName); - d.d_namlen = strlen(d.d_name); + d.d_namlen = (char)strlen(d.d_name); return &d; } diff --git a/src/shell/Makefile.in b/src/shell/Makefile.in index d6aa076..b005121 100644 --- a/src/shell/Makefile.in +++ b/src/shell/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,82 +13,128 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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@ 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 subdir = src/shell +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = @@ -100,11 +146,7 @@ am_libshell_a_OBJECTS = shell.$(OBJEXT) shell_batch.$(OBJEXT) \ shell_cmds.$(OBJEXT) shell_misc.$(OBJEXT) libshell_a_OBJECTS = $(am_libshell_a_OBJECTS) -DEFS = @DEFS@ DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -CPPFLAGS = @CPPFLAGS@ -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/shell.Po ./$(DEPDIR)/shell_batch.Po \ @@ -114,14 +156,12 @@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ -CXXFLAGS = @CXXFLAGS@ -CFLAGS = @CFLAGS@ 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 = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am SOURCES = $(libshell_a_SOURCES) all: all-am @@ -154,26 +194,35 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shell_cmds.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shell_misc.Po@am__quote@ -distclean-depend: - -rm -rf ./$(DEPDIR) - .cpp.o: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< .cpp.obj: -@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ -@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - $(CXXCOMPILE) -c -o $@ `cygpath -w $<` -CXXDEPMODE = @CXXDEPMODE@ +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \ +@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \ +@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \ +@am__fastdepCXX_TRUE@ fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi` uninstall-info-am: ETAGS = etags ETAGSFLAGS = +CTAGS = ctags +CTAGSFLAGS = + tags: TAGS ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) @@ -199,20 +248,41 @@ TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -237,7 +307,6 @@ check: check-am all-am: Makefile $(LIBRARIES) installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -257,7 +326,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -267,9 +336,11 @@ clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-depend \ - distclean-generic distclean-tags +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags dvi: dvi-am @@ -290,6 +361,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -297,18 +370,25 @@ mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + uninstall-am: uninstall-info-am -.PHONY: GTAGS all all-am check check-am clean clean-generic \ - clean-noinstLIBRARIES distclean distclean-compile \ - distclean-depend distclean-generic distclean-tags distdir dvi \ - dvi-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic tags uninstall uninstall-am \ - uninstall-info-am +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ + ps ps-am tags uninstall uninstall-am uninstall-info-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index 455f528..9610fd1 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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,9 +16,11 @@ * 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 $ */ #include #include +#include #include "setup.h" #include "shell_inc.h" @@ -50,56 +52,128 @@ void SHELL_AddAutoexec(char * line,...) { sprintf((autoexec_data+auto_len),"%s\r\n",buf); } - DOS_Shell::DOS_Shell():Program(){ input_handle=STDIN; echo=true; exit=false; bf=0; - memset(&old.buffer,0,CMD_OLDSIZE); - old.size=0; + call=false; + completion_start = NULL; } -Bit32u DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn) { +Bitu DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn,bool * append) { + char * lr=s; + char * lw=s; + char ch; + Bitu num=0; - return 1; + while (ch=*lr++) { + switch (ch) { + case '>': + *append=((*lr)=='>'); + if (*append) lr++; + lr=ltrim(lr); + if (*ofn) free(*ofn); + *ofn=lr; + while (*lr && *lr!=' ') lr++; + if(*lr && *(lr+1)) + *lr++=0; + else + *lr=0; + *ofn=strdup(*ofn); + continue; + case '<': + if (*ifn) free(*ifn); + lr=ltrim(lr); + *ifn=lr; + while (*lr && *lr!=' ') lr++; + if(*lr && *(lr+1)) + *lr++=0; + else + *lr=0; + *ifn=strdup(*ifn); + continue; + case '|': + ch=0; + num++; + } + *lw++=ch; + } + *lw=0; + return num; } - - void DOS_Shell::ParseLine(char * line) { - char * in=0; - char * out=0; - char * fname0=0; - char * fname1=0; - /* Check for a leading @ */ if (line[0]=='@') line[0]=' '; line=trim(line); - Bit32u num=0; /* Number of commands in this line */ - num = GetRedirection(line,&in, &out); +#if 1 + /* Do redirection and pipe checks */ + + char * in=0; + char * out=0; + + Bit16u old_in,old_out; + + Bitu num=0; /* Number of commands in this line */ + bool append; + + num = GetRedirection(line,&in, &out,&append); + if (num>1) LOG_MSG("SHELL:Multiple command on 1 line not supported"); +// if (in || num>1) DOS_DuplicateEntry(0,&old_in); + + if (in) { + LOG_MSG("SHELL:Redirect input from %s",in); + DOS_CloseFile(0); + free(in); + } + if (out) { + LOG_MSG("SHELL:Redirect output to %s",out); + free(out); + } +#endif -/* TODO in and out redirection */ - DoCommand(line); } +void DOS_Shell::RunInternal(void) +{ + char input_line[CMD_MAXLINE]; + std::string line; + while(bf && bf->ReadLine(input_line)) + { + if (echo) { + if (input_line[0]!='@') { + ShowPrompt(); + WriteOut(input_line); + WriteOut("\n"); + }; + }; + ParseLine(input_line); + } + return; +} + + void DOS_Shell::Run(void) { char input_line[CMD_MAXLINE]; std::string line; if (cmd->FindStringRemain("/C",line)) { strcpy(input_line,line.c_str()); - ParseLine(input_line); + DOS_Shell temp; + temp.echo = echo; + temp.ParseLine(input_line); //for *.exe *.com |*.bat creates the bf needed by runinternal; + temp.RunInternal(); // exits when no bf is found. return; } /* Start a normal shell and check for a first command init */ @@ -110,21 +184,24 @@ void DOS_Shell::Run(void) { ParseLine(input_line); } do { - if (bf && bf->ReadLine(input_line)) { - if (echo) { - if (input_line[0]!='@') { - ShowPrompt(); - WriteOut(input_line); - WriteOut("\n"); + if (bf){ + if(bf->ReadLine(input_line)) { + if (echo) { + if (input_line[0]!='@') { + ShowPrompt(); + WriteOut(input_line); + WriteOut("\n"); + }; }; - }; + ParseLine(input_line); + if (echo) WriteOut("\n"); + } } else { if (echo) ShowPrompt(); InputCommand(input_line); - + ParseLine(input_line); + if (echo) WriteOut("\n"); } - ParseLine(input_line); - if (echo) WriteOut("\n"); } while (!exit); } @@ -135,23 +212,24 @@ void DOS_Shell::SyntaxError(void) { void AUTOEXEC_Init(Section * sec) { - MSG_Add("AUTOEXEC_CONFIGFILE_HELP","Add here the lines you want to execute on startup.\n"); /* Register a virtual AUOEXEC.BAT file */ - + std::string line; Section_line * section=static_cast(sec); char * extra=(char *)section->data.c_str(); - if (extra) SHELL_AddAutoexec(extra); - /* Check to see for extra command line options to be added */ - std::string line; - while (control->cmdline->FindString("-c",line,true)) { - SHELL_AddAutoexec((char *)line.c_str()); - } + if (extra) SHELL_AddAutoexec("%s",extra); + /* Check to see for extra command line options to be added (before the command specified on commandline) */ + while (control->cmdline->FindString("-c",line,true)) + SHELL_AddAutoexec((char *)line.c_str()); + + /* Check for the -exit switch which causes dosbox to when the command on the commandline has finished */ + bool addexit = control->cmdline->FindExist("-exit",true); + /* Check for first command being a directory or file */ char buffer[CROSS_LEN]; if (control->cmdline->FindCommand(1,line)) { struct stat test; strcpy(buffer,line.c_str()); - if (stat(buffer,&test)) { + if (stat(buffer,&test)){ getcwd(buffer,CROSS_LEN); strcat(buffer,line.c_str()); if (stat(buffer,&test)) goto nomount; @@ -167,6 +245,7 @@ void AUTOEXEC_Init(Section * sec) { SHELL_AddAutoexec("MOUNT C \"%s\"",buffer); SHELL_AddAutoexec("C:"); SHELL_AddAutoexec(name); + if(addexit) SHELL_AddAutoexec("exit"); } } nomount: @@ -210,10 +289,10 @@ void SHELL_Init() { MSG_Add("SHELL_CMD_COPY_SUCCESS"," %d File(s) copied.\n"); MSG_Add("SHELL_STARTUP","DOSBox Shell v" VERSION "\n" - "DOSBox does not run protected mode games!\n" - "For supported shell commands type: HELP\n" - "For a short introduction type: INTRO\n\n" - "For more information read the README file in DOSBox directory.\n" + "This version runs some protected mode games!\n" + "For supported shell commands type: HELP\n" + "For a short introduction type: INTRO\n\n" + "For more information read the README file in DOSBox directory.\n" "\nHAVE FUN!\nThe DOSBox Team\n\n" ); @@ -234,7 +313,7 @@ void SHELL_Init() { MSG_Add("SHELL_CMD_RENAME_HELP","Renames files.\n"); MSG_Add("SHELL_CMD_DELETE_HELP","Removes files.\n"); MSG_Add("SHELL_CMD_COPY_HELP","Copy files.\n"); - MSG_Add("SHELL_CMD_INTRO_HELP","Gives an introduction into dosbox\n"); + MSG_Add("SHELL_CMD_CALL_HELP","Start a batch file from within another batch file.\n"); /* Regular startup */ call_shellstop=CALLBACK_Allocate(); /* Setup the startup CS:IP to kill the last running machine when exitted */ diff --git a/src/shell/shell_batch.cpp b/src/shell/shell_batch.cpp index 304f598..c927e88 100644 --- a/src/shell/shell_batch.cpp +++ b/src/shell/shell_batch.cpp @@ -27,7 +27,7 @@ BatchFile::BatchFile(DOS_Shell * host,char * name, char * cmd_line) { echo=host->echo; shell=host; cmd=new CommandLine(0,cmd_line); - if (!DOS_OpenFile(name,0,&file_handle)) { + if (!DOS_OpenFile(name,128,&file_handle)) { //TODO Come up with something better E_Exit("SHELL:Can't open BatchFile"); } @@ -49,7 +49,7 @@ emptyline: n=1; DOS_ReadFile(file_handle,&c,&n); if (n>0) { - if (c>31 || c==0x1b) + if (c>31 || c==0x1b || c=='\t') *cmd_write++=c; } } while (c!='\n' && n); diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index 7d3fe73..2bb7113 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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 @@ -15,40 +15,41 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* $Id: shell_cmds.cpp,v 1.33 2003/10/14 23:34:23 harekiet Exp $ */ + #include #include "shell_inc.h" #include "callback.h" #include "regs.h" - - static SHELL_Cmd cmd_list[]={ - "CD", 0, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP", - "CLS", 0, &DOS_Shell::CMD_CLS, "SHELL_CMD_CLS_HELP", - "COPY", 0, &DOS_Shell::CMD_COPY, "SHELL_CMD_COPY_HELP", - "DIR", 0, &DOS_Shell::CMD_DIR, "SHELL_CMD_DIR_HELP", - "DEL", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP", - "DELETE", 0, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP", - "ECHO", 0, &DOS_Shell::CMD_ECHO, "SHELL_CMD_ECHO_HELP", - "EXIT", 0, &DOS_Shell::CMD_EXIT, "SHELL_CMD_EXIT_HELP", - "HELP", 0, &DOS_Shell::CMD_HELP, "SHELL_CMD_HELP_HELP", - "MD", 0, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP", - "RD", 0, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP", - "SET", 0, &DOS_Shell::CMD_SET, "SHELL_CMD_SET_HELP", - "IF", 0, &DOS_Shell::CMD_IF, "SHELL_CMD_IF_HELP", - "GOTO", 0, &DOS_Shell::CMD_GOTO, "SHELL_CMD_GOTO_HELP", - "TYPE", 0, &DOS_Shell::CMD_TYPE, "SHELL_CMD_TYPE_HELP", - "REM", 0, &DOS_Shell::CMD_REM, "SHELL_CMD_REM_HELP", - "RENAME", 0, &DOS_Shell::CMD_RENAME, "SHELL_CMD_RENAME_HELP", - "REN", 1, &DOS_Shell::CMD_RENAME, "SHELL_CMD_RENAME_HELP", - "PAUSE", 0, &DOS_Shell::CMD_PAUSE, "SHELL_CMD_PAUSE_HELP", -/* - "CHDIR", 0, &DOS_Shell::CMD_CHDIR, "Change Directory", - "MKDIR", 0, &DOS_Shell::CMD_MKDIR, "Make Directory", - "RMDIR", 0, &DOS_Shell::CMD_RMDIR, "Remove Directory", -*/ - 0,0,0,0 +{ "CHDIR", 0, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP"}, +{ "CD", 1, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP"}, +{ "CLS", 0, &DOS_Shell::CMD_CLS, "SHELL_CMD_CLS_HELP"}, +{ "COPY", 0, &DOS_Shell::CMD_COPY, "SHELL_CMD_COPY_HELP"}, +{ "DIR", 0, &DOS_Shell::CMD_DIR, "SHELL_CMD_DIR_HELP"}, +{ "DEL", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"}, +{ "DELETE", 0, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"}, +{ "ERASE", 1, &DOS_Shell::CMD_DELETE, "SHELL_CMD_DELETE_HELP"}, +{ "ECHO", 0, &DOS_Shell::CMD_ECHO, "SHELL_CMD_ECHO_HELP"}, +{ "EXIT", 0, &DOS_Shell::CMD_EXIT, "SHELL_CMD_EXIT_HELP"}, +{ "HELP", 0, &DOS_Shell::CMD_HELP, "SHELL_CMD_HELP_HELP"}, +{ "MKDIR", 0, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"}, +{ "MD", 1, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP"}, +{ "RMDIR", 0, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP"}, +{ "RD", 1, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP"}, +{ "SET", 0, &DOS_Shell::CMD_SET, "SHELL_CMD_SET_HELP"}, +{ "IF", 0, &DOS_Shell::CMD_IF, "SHELL_CMD_IF_HELP"}, +{ "GOTO", 0, &DOS_Shell::CMD_GOTO, "SHELL_CMD_GOTO_HELP"}, +{ "TYPE", 0, &DOS_Shell::CMD_TYPE, "SHELL_CMD_TYPE_HELP"}, +{ "REM", 0, &DOS_Shell::CMD_REM, "SHELL_CMD_REM_HELP"}, +{ "RENAME", 0, &DOS_Shell::CMD_RENAME, "SHELL_CMD_RENAME_HELP"}, +{ "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} }; void DOS_Shell::DoCommand(char * line) { @@ -59,13 +60,22 @@ void DOS_Shell::DoCommand(char * line) { while (*line) { if (*line==32) break; if (*line=='/') break; - if ((*line=='.') && (*(line+1)=='.')) break; -// if ((*line=='.') && (*(line+1)==0)) break; + if (*line=='\t') break; + if ((*line=='.') ||(*line =='\\')) { //allow stuff like cd.. and dir.exe cd\kees + *cmd_write=0; + Bit32u cmd_index=0; + while (cmd_list[cmd_index].name) { + if (strcasecmp(cmd_list[cmd_index].name,cmd)==0) { + (this->*(cmd_list[cmd_index].handler))(line); + return; + } + cmd_index++; + } + } *cmd_write++=*line++; } *cmd_write=0; if (strlen(cmd)==0) return; - line=trim(line); /* Check the internal list */ Bit32u cmd_index=0; while (cmd_list[cmd_index].name) { @@ -86,15 +96,21 @@ void DOS_Shell::CMD_CLS(char * args) { }; void DOS_Shell::CMD_DELETE(char * args) { + char * rem=ScanCMDRemain(args); if (rem) { WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); return; } + /* If delete accept switches mind the space infront of them. See the dir /p code */ + char full[DOS_PATHLENGTH]; + char buffer[CROSS_LEN]; + args = ExpandDot(args,buffer); + StripSpaces(args); if (!DOS_Canonicalize(args,full)) { WriteOut(MSG_Get("SHELL_ILLEGAL_PATH"));return; } //TODO Maybe support confirmation for *.* like dos does. - bool res=DOS_FindFirst(args,0xff); + bool res=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME); if (!res) { WriteOut(MSG_Get("SHELL_CMD_DEL_ERROR"),args);return; } @@ -124,38 +140,42 @@ void DOS_Shell::CMD_HELP(char * args){ } void DOS_Shell::CMD_RENAME(char * args){ - if(!*args) {SyntaxError();return;} - if((strchr(args,'*')!=NULL) || (strchr(args,'?')!=NULL) ) { WriteOut(MSG_Get("SHELL_CMD_NO_WILD"));return;} - char * arg2 =StripWord(args); - DOS_Rename(args,arg2); + StripSpaces(args); + if(!*args) {SyntaxError();return;} + if((strchr(args,'*')!=NULL) || (strchr(args,'?')!=NULL) ) { WriteOut(MSG_Get("SHELL_CMD_NO_WILD"));return;} + char * arg2 =StripWord(args); + DOS_Rename(args,arg2); } - - - - -void DOS_Shell::CMD_ECHO(char * args) { +void DOS_Shell::CMD_ECHO(char * args){ if (!*args) { if (echo) { WriteOut(MSG_Get("SHELL_CMD_ECHO_ON"));} else { WriteOut(MSG_Get("SHELL_CMD_ECHO_OFF"));} - return; + return; } - if (strcasecmp(args,"OFF")==0) { + char buffer[512]; + char* pbuffer = buffer; + strcpy(buffer,args); + StripSpaces(pbuffer); + if (strcasecmp(pbuffer,"OFF")==0) { echo=false; return; } - if (strcasecmp(args,"ON")==0) { + if (strcasecmp(pbuffer,"ON")==0) { echo=true; return; } + args++;//skip first character. either a slash or dot or space WriteOut("%s\n",args); }; + void DOS_Shell::CMD_EXIT(char * args) { exit=true; }; void DOS_Shell::CMD_CHDIR(char * args) { + StripSpaces(args); if (!*args) { Bit8u drive=DOS_GetDefaultDrive()+'A'; char dir[DOS_PATHLENGTH]; @@ -171,6 +191,7 @@ void DOS_Shell::CMD_CHDIR(char * args) { }; void DOS_Shell::CMD_MKDIR(char * args) { + StripSpaces(args); char * rem=ScanCMDRemain(args); if (rem) { WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); @@ -182,6 +203,7 @@ void DOS_Shell::CMD_MKDIR(char * args) { }; void DOS_Shell::CMD_RMDIR(char * args) { + StripSpaces(args); char * rem=ScanCMDRemain(args); if (rem) { WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); @@ -223,21 +245,27 @@ void DOS_Shell::CMD_DIR(char * args) { return; } Bit32u byte_count,file_count,dir_count; - Bit32u w_count=0; + Bitu w_count=0; + Bitu p_count=0; + Bitu w_size = optW?5:1; byte_count=file_count=dir_count=0; - - if (strlen(args)==0) args="*.*"; + + char buffer[CROSS_LEN]; + if (strlen(args)==0) args="*.*"; //no arguments. + if ((strlen(args)==1) && (args[0]==' ')) args="*.*"; //stuff like dir /p + args = ExpandDot(args,buffer); + StripSpaces(args); /* Make a full path in the args */ if (!DOS_Canonicalize(args,path)) { - WriteOut(MSG_Get("SHELL_CMD_ILLEGAL_PATH")); + WriteOut(MSG_Get("SHELL_ILLEGAL_PATH")); return; } *(strrchr(path,'\\')+1)=0; WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path); DOS_DTA dta(dos.dta); - bool ret=DOS_FindFirst(args,0xffff); + bool ret=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME); if (!ret) { WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); return; @@ -282,10 +310,16 @@ void DOS_Shell::CMD_DIR(char * args) { w_count++; } ret=DOS_FindNext(); + if(optP) { + if(!(++p_count%(22*w_size))) { + CMD_PAUSE(args); + } + } } if (optW) { if (w_count%5) WriteOut("\n"); } + /* Show the summary of results */ FormatNumber(byte_count,numformat); WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_USED"),file_count,numformat); @@ -302,7 +336,7 @@ void DOS_Shell::CMD_DIR(char * args) { } void DOS_Shell::CMD_COPY(char * args) { - + StripSpaces(args); DOS_DTA dta(dos.dta); Bit32u size;Bit16u date;Bit16u time;Bit8u attr; char name[DOS_NAMELENGTH_ASCII]; @@ -327,7 +361,7 @@ void DOS_Shell::CMD_COPY(char * args) { char pathTarget[DOS_PATHLENGTH]; if (!DOS_Canonicalize(source,pathSource)) { - WriteOut(MSG_Get("SHELL_CMD_ILLEGAL_PATH")); + WriteOut(MSG_Get("SHELL_ILLEGAL_PATH")); return; } // cut search pattern @@ -335,19 +369,22 @@ void DOS_Shell::CMD_COPY(char * args) { if (pos) *(pos+1) = 0; if (!DOS_Canonicalize(target,pathTarget)) { - WriteOut(MSG_Get("SHELL_CMD_ILLEGAL_PATH")); + WriteOut(MSG_Get("SHELL_ILLEGAL_PATH")); return; } - // add '\\' if target is a directoy + char* temp = strstr(pathTarget,"*.*"); + if(temp) *temp = 0;//strip off *.* from target + + // add '\\' if target is a directoy if (pathTarget[strlen(pathTarget)-1]!='\\') { - if (DOS_FindFirst(pathTarget,0xffff)) { + if (DOS_FindFirst(pathTarget,0xffff & ~DOS_ATTR_VOLUME)) { dta.GetResult(name,size,date,time,attr); if (attr & DOS_ATTR_DIRECTORY) strcat(pathTarget,"\\"); } }; - bool ret=DOS_FindFirst(args,0xffff); + bool ret=DOS_FindFirst(args,0xffff & ~DOS_ATTR_VOLUME); if (!ret) { WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); return; @@ -396,6 +433,7 @@ void DOS_Shell::CMD_COPY(char * args) { } void DOS_Shell::CMD_SET(char * args) { + StripSpaces(args); std::string line; if (!*args) { /* No command line show all environment lines */ @@ -419,8 +457,8 @@ void DOS_Shell::CMD_SET(char * args) { void DOS_Shell::CMD_IF(char * args) { + StripSpaces(args); bool has_not=false; - char * comp=strchr(args,'='); if (comp) { if (comp[1]!='=') {SyntaxError();return;} @@ -460,9 +498,7 @@ void DOS_Shell::CMD_IF(char * args) { return; } /* Read the error code from DOS */ - reg_ah=0x4d; - CALLBACK_RunRealInt(0x21); - if ((reg_al>=n) ==(!has_not)) DoCommand(args); + if ((dos.return_code>=n) ==(!has_not)) DoCommand(args); return; } /* Normal if string compare */ @@ -473,8 +509,9 @@ void DOS_Shell::CMD_IF(char * args) { } void DOS_Shell::CMD_GOTO(char * args) { + StripSpaces(args); if (!bf) return; - if (*args==':') args++; + if (*args &&(*args==':')) args++; if (!*args) { WriteOut(MSG_Get("SHELL_CMD_GOTO_MISSING_LABEL")); return; @@ -487,7 +524,7 @@ void DOS_Shell::CMD_GOTO(char * args) { void DOS_Shell::CMD_TYPE(char * args) { - + StripSpaces(args); if (!*args) { WriteOut(MSG_Get("SHELL_SYNTAXERROR")); return; @@ -515,8 +552,15 @@ void DOS_Shell::CMD_REM(char * args) { } void DOS_Shell::CMD_PAUSE(char * args){ - WriteOut(MSG_Get("SHELL_CMD_PAUSE")); - Bit8u c;Bit16u n=1; + WriteOut(MSG_Get("SHELL_CMD_PAUSE")); + Bit8u c;Bit16u n=1; DOS_ReadFile (STDIN,&c,&n); } + +void DOS_Shell::CMD_CALL(char * args){ + this->call=true; /* else the old batchfile will be closed first */ + this->ParseLine(args); + this->call=false; +} + diff --git a/src/shell/shell_inc.h b/src/shell/shell_inc.h index 2194780..fdc8831 100644 --- a/src/shell/shell_inc.h +++ b/src/shell/shell_inc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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 @@ -15,6 +15,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* $Id: shell_inc.h,v 1.17 2003/09/08 18:19:28 qbix79 Exp $ */ + #include #include #include "dosbox.h" @@ -26,6 +29,9 @@ #include "callback.h" #include "setup.h" +#include +#include + #define CMD_MAXLINE 4096 #define CMD_MAXCMDS 20 #define CMD_OLDSIZE 4096 @@ -46,15 +52,24 @@ public: CommandLine * cmd; }; - - class DOS_Shell : public Program { + +private: + + std::list l_history, l_completion; + + char *completion_start; + Bit16u completion_index; + public: + DOS_Shell(); + void Run(void); + void RunInternal(void); //for command /C /* A load of subfunctions */ void ParseLine(char * line); - Bit32u GetRedirection(char *s, char **ifn, char **ofn); + Bitu GetRedirection(char *s, char **ifn, char **ofn,bool * append); void InputCommand(char * line); void ShowPrompt(); void DoCommand(char * cmd); @@ -78,6 +93,7 @@ public: void CMD_TYPE(char * args); void CMD_REM(char * args); void CMD_RENAME(char * args); + void CMD_CALL(char * args); void SyntaxError(void); void CMD_PAUSE(char * args); /* The shell's variables */ @@ -85,12 +101,7 @@ public: BatchFile * bf; bool echo; bool exit; - struct { - char buffer[CMD_OLDSIZE]; - Bitu index; - Bitu size; - } old; - + bool call; }; struct SHELL_Cmd { @@ -100,4 +111,32 @@ struct SHELL_Cmd { const char * help; /* String with command help */ }; +static inline void StripSpaces(char*&args) +{ + while(*args && (*args == ' ')) + args++; +} + + +static inline char* ExpandDot(char*args, char* buffer) +{ + if(*args=='.') + { + if(*(args+1)==0) + { + strcpy(buffer,"*.*"); + return buffer; + } + if( (*(args+1)!='.') && (*(args+1)!='\\') ) + { + buffer[0]='*'; + buffer[1]=0; + strcat(buffer,args); + return buffer; + } + } + else strcpy(buffer,args); + return buffer; +} + diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index 2712a5f..3b94cc2 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 The DOSBox Team + * Copyright (C) 2002-2003 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: shell_misc.cpp,v 1.26 2003/10/10 09:21:35 qbix79 Exp $ */ + #include #include #include "shell_inc.h" -#include "cpu.h" +#include "regs.h" void DOS_Shell::ShowPrompt(void) { @@ -40,11 +42,14 @@ static void outs(char * str) { } void DOS_Shell::InputCommand(char * line) { - char * prev=old.buffer; - char * reader; Bitu size=CMD_MAXLINE-1; Bit8u c;Bit16u n=1; Bitu str_len=0;Bitu str_index=0; + Bit16u len; + + line[0] = '\0'; + + std::list::iterator it_history = l_history.begin(), it_completion = l_completion.begin(); while (size) { dos.echo=false; @@ -58,42 +63,99 @@ void DOS_Shell::InputCommand(char * line) { { DOS_ReadFile(input_handle,&c,&n); switch (c) { + case 0x3d: /* F3 */ - if (strlen(old.buffer)>str_len) { - reader=&old.buffer[str_len]; - while ((c=*reader++)) { - line[str_index]=c; - str_len++; - str_index++; - size--; + if (!l_history.size()) break; + it_history = l_history.begin(); + if (it_history != l_history.end() && it_history->length() > str_len) { + const char *reader = &(it_history->c_str())[str_len]; + while ((c = *reader++)) { + line[str_index ++] = c; DOS_WriteFile(STDOUT,&c,&n); } + str_len = str_index = it_history->length(); + size = CMD_MAXLINE - str_index - 1; } break; - default: + + case 0x4B: /* LEFT */ + if (str_index) { + outc(8); + str_index --; + } break; + case 0x4D: /* RIGHT */ + if (str_index < str_len) { + outc(line[str_index++]); + } + break; + case 0x48: /* UP */ + if (l_history.empty() || it_history == l_history.end()) break; + + for (;str_index>0; str_index--) { + // removes all characters + outc(8); outc(' '); outc(8); + } + strcpy(line, it_history->c_str()); + len = it_history->length(); + str_len = str_index = len; + size = CMD_MAXLINE - str_index - 1; + DOS_WriteFile(STDOUT, (Bit8u *)line, &len); + it_history ++; + + break; + + case 0x50: /* DOWN */ + if (l_history.empty() || it_history == l_history.begin()) break; + + // not very nice but works .. + it_history --; + if (it_history == l_history.begin()) { + // no previous commands in history + it_history ++; + break; + } else it_history --; + + for (;str_index>0; str_index--) { + // removes all characters + outc(8); outc(' '); outc(8); + } + strcpy(line, it_history->c_str()); + len = it_history->length(); + str_len = str_index = len; + size = CMD_MAXLINE - str_index - 1; + DOS_WriteFile(STDOUT, (Bit8u *)line, &len); + it_history ++; + + break; + + default: + break; } }; break; case 0x08: /* BackSpace */ - if (str_index>0) { - Bit32u str_remain=str_len-str_index; + if (str_index) { + outc(8); + Bit32u str_remain=str_len - str_index; if (str_remain) { - memcpy(&line[str_index-1],&line[str_index],str_remain); - line[str_len]=0; + memmove(&line[str_index-1],&line[str_index],str_remain); + line[--str_len]=0; + str_index --; /* Go back to redraw */ - for (;str_remain>0;str_remain--) { - outc(8); - } + for (Bit16u i=str_index; i < str_len; i++) + outc(line[i]); + } else { + line[--str_index] = '\0'; + str_len--; } - str_index--;str_len--; - outc(8); - outc(' '); - outc(8); - + outc(' '); outc(8); + // moves the cursor left + while (str_remain--) outc(8); } + if (strlen(line) == 0 && l_completion.size()) l_completion.clear(); break; case 0x0a: /* New Line not handled */ /* Don't care */ @@ -102,34 +164,121 @@ void DOS_Shell::InputCommand(char * line) { outc('\n'); size=0; //Kill the while loop break; + case'\t': + { + if (l_completion.size()) { + it_completion ++; + if (it_completion == l_completion.end()) it_completion = l_completion.begin(); + } else { + // build new completion list + + // get completion mask + char *completion_start = strrchr(line, ' '); + + if (completion_start) { + completion_start ++; + completion_index = str_index - strlen(completion_start); + } else { + completion_start = line; + completion_index = 0; + } + + // build the completion list + char mask[DOS_PATHLENGTH]; + if (completion_start) { + strcpy(mask, completion_start); + // not perfect when line already contains wildcards, but works + strcat(mask, "*.*"); + } else { + strcpy(mask, "*.*"); + } + + bool res = DOS_FindFirst(mask, 0xffff & ~DOS_ATTR_VOLUME); + if (!res) break; // TODO: beep + + DOS_DTA dta(dos.dta); + char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr; + + while (res) { + dta.GetResult(name,size,date,time,attr); + // add result to completion list + + char *ext; // file extension + if (strcmp(name, ".") && strcmp(name, "..")) { + ext = strrchr(name, '.'); + if (ext && (strcmp(ext, ".BAT") == 0 || strcmp(ext, ".COM") == 0 || strcmp(ext, ".EXE") == 0)) + // we add executables to the start of the list + l_completion.push_front(name); + else + l_completion.push_back(name); + } + + res=DOS_FindNext(); + } + + it_completion = l_completion.begin(); + } + + if (l_completion.size() && it_completion->length()) { + for (;str_index > completion_index; str_index--) { + // removes all characters + outc(8); outc(' '); outc(8); + } + + strcpy(&line[completion_index], it_completion->c_str()); + len = it_completion->length(); + str_len = str_index = completion_index + len; + size = CMD_MAXLINE - str_index - 1; + DOS_WriteFile(STDOUT, (Bit8u *)it_completion->c_str(), &len); + } + } + break; + case 0x1b: /* ESC */ + //write a backslash and return to the next line + outc('\\'); + outc('\n'); + *line = 0; // reset the line. + if (l_completion.size()) l_completion.clear(); //reset the completion list. + this->InputCommand(line); //Get the NEW line. + size = 0; // stop the next loop + str_len = 0; // prevent multiple adds of the same line + break; default: + if (l_completion.size()) l_completion.clear(); line[str_index]=c; + str_index ++; + if (str_index > str_len) line[str_index] = '\0'; str_len++;//This should depend on insert being active - str_index++; size--; DOS_WriteFile(STDOUT,&c,&n); break; } } -/* String is inputted now save it in the buffer */ - line[str_len]=0; + if (!str_len) return; str_len++; - //Not quite perfect last entries can get screwed :) - size_t first_len=strlen(old.buffer)+1; - memmove(&old.buffer[first_len],&old.buffer[0],CMD_OLDSIZE-first_len); - strcpy(old.buffer,line); + + // add command line to history + l_history.push_front(line); it_history = l_history.begin(); + if (l_completion.size()) l_completion.clear(); } void DOS_Shell::Execute(char * name,char * args) { char * fullname; - char line[255]; - if(strlen(args)!=0){ - line[0]=' ';line[1]=0; - strcat(line,args); - }else{ - line[0]=0; - }; + char line[255]; + if(strlen(args)!= 0){ + if(*args != ' '){ //put a space in front + line[0]=' ';line[1]=0; + strcat(line,args); + } + else + { + strcpy(line,args); + } + }else{ + line[0]=0; + }; + /* check for a drive change */ if ((strcmp(name + 1, ":") == 0) && isalpha(*name)) { @@ -144,10 +293,63 @@ void DOS_Shell::Execute(char * name,char * args) { WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),name); return; } - if (strcasecmp(strrchr(fullname, '.'), ".bat") == 0) { - /* Run the .bat file */ + + char* extension =strrchr(fullname,'.'); + + /*always disallow files without extension from being executed. */ + /*only internal commands can be run this way and they never get in this handler */ + if(extension == 0) + { + char temp_name[256],* temp_fullname; + //try to add .com, .exe and .bat extensions to filename + + strcpy(temp_name,fullname); + strcat(temp_name,".COM"); + temp_fullname=Which(temp_name); + if (temp_fullname) { extension=".com";strcpy(fullname,temp_fullname); } + + else + { + strcpy(temp_name,fullname); + strcat(temp_name,".EXE"); + temp_fullname=Which(temp_name); + if (temp_fullname) { extension=".exe";strcpy(fullname,temp_fullname);} + + else + { + strcpy(temp_name,fullname); + strcat(temp_name,".BAT"); + temp_fullname=Which(temp_name); + if (temp_fullname) { extension=".bat";strcpy(fullname,temp_fullname);} + + else + { + WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),fullname); + return; + } + + } + } + } + + if (strcasecmp(extension, ".bat") == 0) + { /* Run the .bat file */ + /* delete old batch file if call is not active*/ + bool temp_echo=echo; /*keep the current echostate (as delete bf might change it )*/ + if(bf && !call) delete bf; bf=new BatchFile(this,fullname,line); - } else { + echo=temp_echo; //restore it. + } + else + { /* only .bat .exe .com extensions maybe be executed by the shell */ + if(strcasecmp(extension, ".com") !=0) + { + if(strcasecmp(extension, ".exe") !=0) + { + WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),fullname); + return; + } + } /* Run the .exe or .com file from the shell */ /* Allocate some stack space for tables in physical memory */ reg_sp-=0x200; @@ -174,12 +376,14 @@ void DOS_Shell::Execute(char * name,char * args) { /* Set the command line in the block and save it */ block.exec.cmdtail=RealMakeSeg(ss,reg_sp+0x100); block.SaveData(); +#if 0 /* Save CS:IP to some point where i can return them from */ Bit32u oldeip=reg_eip; Bit16u oldcs=SegValue(cs); RealPt newcsip=CALLBACK_RealPointer(call_shellstop); SegSet16(cs,RealSeg(newcsip)); reg_ip=RealOff(newcsip); +#endif /* Start up a dos execute interrupt */ reg_ax=0x4b00; //Filename pointer @@ -188,12 +392,14 @@ void DOS_Shell::Execute(char * name,char * args) { //Paramblock SegSet16(es,SegValue(ss)); reg_bx=reg_sp; - flags.intf=false; + SETFLAGBIT(IF,false); CALLBACK_RunRealInt(0x21); /* Restore CS:IP and the stack */ reg_sp+=0x200; +#if 0 reg_eip=oldeip; SegSet16(cs,oldcs); +#endif } } @@ -208,25 +414,21 @@ static char which_ret[DOS_PATHLENGTH]; char * DOS_Shell::Which(char * name) { /* Parse through the Path to find the correct entry */ /* Check if name is already ok but just misses an extension */ - char * ext=strrchr(name,'.'); - if (ext) if (strlen(ext)>4) ext=0; - if (ext) { - if (DOS_FileExists(name)) return name; - } else { - /* try to find .com .exe .bat */ - strcpy(which_ret,name); - strcat(which_ret,com_ext); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,name); - strcat(which_ret,exe_ext); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,name); - strcat(which_ret,bat_ext); - if (DOS_FileExists(which_ret)) return which_ret; - } + if (DOS_FileExists(name)) return name; + /* try to find .com .exe .bat */ + strcpy(which_ret,name); + strcat(which_ret,com_ext); + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,name); + strcat(which_ret,exe_ext); + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,name); + strcat(which_ret,bat_ext); + if (DOS_FileExists(which_ret)) return which_ret; + /* No Path in filename look through path environment string */ - static char path[DOS_PATHLENGTH];std::string temp; + char path[DOS_PATHLENGTH];std::string temp; if (!GetEnvStr("PATH",temp)) return 0; const char * pathenv=temp.c_str(); if (!pathenv) return 0; @@ -235,30 +437,36 @@ char * DOS_Shell::Which(char * name) { pathenv++; char * path_write=path; while (*pathenv) { - if (*pathenv!=';') { + /* remove ; and ;; at the beginning. (and from the second entry etc) */ + while(*pathenv && (*pathenv ==';')) + pathenv++; + + /* Clear old path */ + for(Bitu dummy = 0;dummy < DOS_PATHLENGTH; dummy++) + path[dummy] = 0; //OVERKILL could be strlen(path). but run no risks + + /* get next entry */ + while(*pathenv && (*pathenv !=';')) *path_write++=*pathenv++; - } - if (*pathenv==';' || *(pathenv)==0) { - if (*path_write!='\\') *path_write++='\\'; - *path_write++=0; + + /* check entry */ + if(Bitu len=strlen(path)){ + if(path[strlen(path)-1]!='\\') strcat(path,"\\"); strcat(path,name); strcpy(which_ret,path); - if (ext) { - if (DOS_FileExists(which_ret)) return which_ret; - } else { - strcpy(which_ret,path); - strcat(which_ret,com_ext); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,path); - strcat(which_ret,exe_ext); - if (DOS_FileExists(which_ret)) return which_ret; - strcpy(which_ret,path); - strcat(which_ret,bat_ext); - if (DOS_FileExists(which_ret)) return which_ret; - } - path_write=path; - if (*pathenv) pathenv++; + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,path); + strcat(which_ret,com_ext); + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,path); + strcat(which_ret,exe_ext); + if (DOS_FileExists(which_ret)) return which_ret; + strcpy(which_ret,path); + strcat(which_ret,bat_ext); + if (DOS_FileExists(which_ret)) return which_ret; } + path_write=path; /* reset it */ + } return 0; } diff --git a/visualc/Makefile.in b/visualc/Makefile.in index 675fd34..84c777b 100644 --- a/visualc/Makefile.in +++ b/visualc/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.6.3 from Makefile.am. +# Makefile.in generated by automake 1.7.7 from Makefile.am. # @configure_input@ -# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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, @@ -13,84 +13,130 @@ # PARTICULAR PURPOSE. @SET_MAKE@ -SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ - -bindir = @bindir@ -sbindir = @sbindir@ -libexecdir = @libexecdir@ -datadir = @datadir@ -sysconfdir = @sysconfdir@ -sharedstatedir = @sharedstatedir@ -localstatedir = @localstatedir@ -libdir = @libdir@ -infodir = @infodir@ -mandir = @mandir@ -includedir = @includedir@ -oldincludedir = /usr/include pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. -ACLOCAL = @ACLOCAL@ -AUTOCONF = @AUTOCONF@ -AUTOMAKE = @AUTOMAKE@ -AUTOHEADER = @AUTOHEADER@ - am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c -INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_HEADER = $(INSTALL_DATA) -transform = @program_transform_name@ +transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -host_alias = @host_alias@ host_triplet = @host@ - -EXEEXT = @EXEEXT@ -OBJEXT = @OBJEXT@ -PATH_SEPARATOR = @PATH_SEPARATOR@ +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.dsw dosbox.dsp subdir = visualc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = DIST_SOURCES = -DIST_COMMON = Makefile.am Makefile.in +DIST_COMMON = $(srcdir)/Makefile.in Makefile.am all: all-am .SUFFIXES: @@ -103,13 +149,22 @@ 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) - @list='$(DISTFILES)'; for file in $$list; do \ + @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 \ @@ -134,7 +189,6 @@ check: check-am all-am: Makefile installdirs: - install: install-am install-exec: install-exec-am install-data: install-data-am @@ -154,7 +208,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -164,6 +218,7 @@ clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am + -rm -f Makefile distclean-am: clean-am distclean-generic @@ -186,6 +241,7 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-am + -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -193,6 +249,14 @@ 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 \ @@ -201,7 +265,8 @@ uninstall-am: uninstall-info-am install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-generic uninstall uninstall-am uninstall-info-am + 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. diff --git a/visualc/dosbox.dsp b/visualc/dosbox.dsp index cb541c3..6328322 100644 --- a/visualc/dosbox.dsp +++ b/visualc/dosbox.dsp @@ -20,6 +20,7 @@ CFG=dosbox - Win32 Debug !MESSAGE "dosbox - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "dosbox - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE + # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" @@ -49,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 winmm.lib zlib.lib libpng.lib sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 winmm.lib zlib.lib libpng.lib sdl_net.lib sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 !ELSEIF "$(CFG)" == "dosbox - Win32 Debug" @@ -74,7 +75,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 winmm.lib zlib.lib libpng.lib sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 sdl_net.lib winmm.lib zlib.lib libpng.lib sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept !ENDIF @@ -128,12 +129,96 @@ SOURCE=..\src\cpu\core_16\support.h SOURCE=..\src\cpu\core_16\table_ea.h # End Source File # End Group +# Begin Group "core_full" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\cpu\core_full\ea_lookup.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_full\load.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_full\loadwrite.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_full\main.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_full\op.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_full\optable.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_full\save.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_full\string.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_full\support.h +# End Source File +# End Group +# Begin Group "core_normal" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\src\cpu\core_normal\helpers.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_normal\prefix_0f.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_normal\prefix_66.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_normal\prefix_66_0f.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_normal\prefix_none.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_normal\string.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_normal\support.h +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_normal\table_ea.h +# End Source File +# End Group # Begin Source File SOURCE=..\src\cpu\callback.cpp # End Source File # Begin Source File +SOURCE=..\src\cpu\core_full.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\cpu\core_normal.cpp +# End Source File +# Begin Source File + SOURCE=..\src\cpu\cpu.cpp # End Source File # Begin Source File @@ -146,6 +231,10 @@ SOURCE=..\src\cpu\instructions.h # End Source File # Begin Source File +SOURCE=..\src\cpu\lazyflags.h +# End Source File +# Begin Source File + SOURCE=..\src\cpu\modrm.cpp # End Source File # Begin Source File @@ -154,6 +243,10 @@ SOURCE=..\src\cpu\modrm.h # End Source File # Begin Source File +SOURCE=..\src\cpu\paging.cpp +# End Source File +# Begin Source File + SOURCE=..\src\cpu\slow_16.cpp # End Source File # End Group @@ -357,10 +450,6 @@ SOURCE=..\src\hardware\vga_draw.cpp # End Source File # Begin Source File -SOURCE=..\src\hardware\vga_fonts.cpp -# End Source File -# Begin Source File - SOURCE=..\src\hardware\vga_gfx.cpp # End Source File # Begin Source File @@ -442,6 +531,14 @@ SOURCE=..\src\hardware\sblaster.cpp # End Source File # Begin Source File +SOURCE=..\src\hardware\serialport.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\hardware\softmodem.cpp +# End Source File +# Begin Source File + SOURCE=..\src\hardware\tandy_sound.cpp # End Source File # Begin Source File @@ -487,6 +584,10 @@ SOURCE=..\src\ints\int10_pal.cpp SOURCE=..\src\ints\int10_put_pixel.cpp # End Source File +# Begin Source File + +SOURCE=..\src\ints\int10_vesa.cpp +# End Source File # End Group # Begin Source File @@ -502,6 +603,10 @@ SOURCE=..\src\ints\bios_keyboard.cpp # End Source File # Begin Source File +SOURCE=..\src\ints\dpmi.cpp +# End Source File +# Begin Source File + SOURCE=..\src\ints\ems.cpp # End Source File # Begin Source File @@ -512,6 +617,10 @@ SOURCE=..\src\ints\mouse.cpp SOURCE=..\src\ints\xms.cpp # End Source File +# Begin Source File + +SOURCE=..\src\ints\xms.h +# End Source File # End Group # Begin Group "misc" @@ -659,6 +768,10 @@ SOURCE=..\include\keyboard.h # End Source File # Begin Source File +SOURCE=..\include\logging.h +# End Source File +# Begin Source File + SOURCE=..\include\mem.h # End Source File # Begin Source File @@ -671,6 +784,10 @@ SOURCE=..\include\mouse.h # End Source File # Begin Source File +SOURCE=..\include\paging.h +# End Source File +# Begin Source File + SOURCE=..\include\pic.h # End Source File # Begin Source File