diff --git a/ChangeLog b/ChangeLog index dc4db42..3745cf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +0.58 + - fixed date and time issues with fcbs + - added more commands to the internal Shell + - corrected config system when a old configfile was used + - fixed cga put and get pixel + - fixed some vga register getting reset to wrong values + - improved support for foreign keyboards + - improved joystick support + - made dosbox multithreaded again + - lot's of soundblaster fixes + - dma fixes + - cdrom support + - midi support + - added scale2x + - reenabled screenshot support + - joystick support fixes + - mouse improvements + - support for writing wavefiles + - added directory cache and longfilename support (longfilenames will be mangled) + - mouse fixes + - date and time updates at z:\ + - added (partial) direct disk support. (works probably only if directory is mounted under a:\) + - added support for env variables. (must be set before starting dosbox: DOSBOX_SECTION_PROPERTY=value + like DOSBOX_SBLASTER_IRQ=1) 0.57 - added support for command /C - fixed all fcb-write functions diff --git a/INSTALL b/INSTALL index 53dfc97..fae0057 100644 --- a/INSTALL +++ b/INSTALL @@ -1,6 +1,3 @@ -First of all if you are running a non-x86 machine this will not work, -code only works for big-endian machines for now :) - Things needed for compilation. SDL @@ -12,7 +9,7 @@ Curses For win32 get pdcurses at http://pdcurses.sourceforge.net Libpng - Needed for the screenshots. + Needed for the screenshots. (--enable-shots when configuring dosbox) For win32 get libpng from http://www.sourceforge.net/projects/gnuwin32 Zlib @@ -27,8 +24,12 @@ For building on unix systems. If you are building from the cvs run ./autogen.sh first before doing the following. 1. ./configure -2. Check settings.h for some setup options. -3. make +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) Check the src subdir for the binary. diff --git a/Makefile.am b/Makefile.am index 2a94591..cb2acfb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Main Makefile for DOSBox -EXTRA_DIST = settings.h autogen.sh -SUBDIRS = src include visualc +EXTRA_DIST = autogen.sh +SUBDIRS = src include visualc docs diff --git a/Makefile.in b/Makefile.in index b780a8c..c769f67 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -51,6 +51,7 @@ 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@ @@ -66,6 +67,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -84,8 +87,8 @@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ -EXTRA_DIST = settings.h autogen.sh -SUBDIRS = src include visualc +EXTRA_DIST = autogen.sh +SUBDIRS = src include visualc docs subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -106,6 +109,9 @@ all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: + +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) cd $(top_srcdir) && \ $(AUTOMAKE) --gnits Makefile @@ -135,7 +141,7 @@ $(srcdir)/config.h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) touch $(srcdir)/config.h.in distclean-hdr: - -rm -f config.h + -rm -f config.h stamp-h1 uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd @@ -254,7 +260,7 @@ distdir: $(DISTFILES) fi $(am__remove_distdir) mkdir $(distdir) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -364,7 +370,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -374,7 +380,7 @@ clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive - -rm -f config.status config.cache config.log + -rm -f $(am__CONFIG_DISTCLEAN_FILES) distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive @@ -396,7 +402,8 @@ install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive - + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf autom4te.cache maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive diff --git a/NEWS b/NEWS index 037b060..6afcd45 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,25 @@ +0.58 + - fixed date and time issues with fcbs + - added more commands to the internal Shell + - corrected config system when a old configfile was used + - fixed cga put and get pixel + - fixed some vga register getting reset to wrong values + - improved support for foreign keyboards + - improved joystick support + - made dosbox multithreaded again + - lot's of soundblaster fixes + - dma fixes + - cdrom support + - midi support + - added scale2x + - reenabled screenshot support + - joystick support fixes + - mouse improvements + - support for writing wavefiles + - added directory cache and longfilename support (longfilenames will be mangled) + - mouse fixes + + 0.57 - added support for command /C - fixed all fcb-write functions diff --git a/README b/README index 391b1d5..1369451 100644 --- a/README +++ b/README @@ -1,19 +1,23 @@ -DOSBox v0.57 +DOSBox v0.58 Usage: ====== -With the new internal shell I've changed the command line a bit, so let's just give some -examples of what you can do now. +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 - With nothing on the command line you'll end up on the internal drive and from there you - can mount directories as drives. + 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 c:\ and then start the shell. - 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. Then it'll strip the directory - from the filename and mount that as c:\ and then run the file. + 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. + +There also are a couple of command line switches. dosbox -fullscreen starts dosbox in fullscreen mode. @@ -22,64 +26,81 @@ dosbox -conf file dosbox -lang file loads file as a languagefile. -You can also add commands to be executed before the main program starts. Or you can use them -to start the program. +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. -For example -dosbox c:\atlantis\atlantis.exe -c "MOUNT D C:\SAVES" "SET TEST=blah" - This would mount c:\atlanis as c:\ and run atlantis.exe from that directory but before it - does that it would first mount C:\SAVES as the D drive and set the environment variable test to blah. -Dragging files or directories onto the DOSBox executable should also work. +For example: +dosbox c:\atlantis\atlantis.exe -c "MOUNT D C:\SAVES" + This would mount c:\atlanis 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. Internal Programs: ================== MOUNT Program to mount local directories as drives inside DOSBox. -The option -t specifies the media: dir = harddisk, floppy = floppy drive. -The option -size specifies the size. -For example to mount c:\floppy as a floppy : mount -t floppy a c:\floppy +The option -t specifies the media: Where can be. + dir = harddisk + floppy = floppy drive + cdrom = cdrom drive + +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) + +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). + +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 + +It is also possible to mount a directory as cdrom, but it's limited. MEM Program to display the amount of free memory CONFIG -Utility for generating a configfile with the current settings and for generating the languagefile. +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. -UPCASE -Utility to convert all files subdirectories of a local directory into upcase so DOSBox can use that directory -for mounting. This tool can be quite dangerous if used unproperly. You have been warned. +For more information use the the /? command line switch with the programs. -To get more information about how to use one these programs use the the /? command line switch. - -The Configfile: +The Config File: =============== -A configfile can be generated by CONFIG.COM. You can 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. +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. -For example in the section sblaster you can change the irq of the soundblaster and disable/enable the -adlib emulation. -The Languagefile: +The Language File: ================= -A languagefile can be generated by CONFIG.COM. If you read it you will understand how to change it. -Start Dosbox with -lang switch to use your language file or enter the location of the languagefile -in the configfile.(section:[dosbox] language=full path to languagefile.) +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. Special Keys: ============= ALT-ENTER Go full screen and back. -CTRL-F5 Save a screenshot -CTRL-F7 Decrease frameskip -CTRL-F8 Increase frameskip -CTRL-F9 Go full screen and back. +CTRL-F5 Save a screenshot. +CTRL-F6 Start/Stop recording sound output to a wave file. +CTRL-F7 Decrease frameskip. +CTRL-F8 Increase frameskip. +CTRL-F9 Kill dosbox. CTRL-F10 Capture/Release the mouse. CTRL-F11 Slowdown emulation. CTRL-F12 Speedup emulation. @@ -93,21 +114,55 @@ of games written for an 286 machine. FAQ: ==== -1.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: 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 -2.Q: The window is too small. - A: When you mouse touches the edges of the DOSBox screen you can click and drag it to - the size you prefer. +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. -3.Q: The mouse(cursor) acts weird. (eg only updated when you press the mousebutton) - A: Lock the mouse with ctrl-F10. It should then behave the way you expect it to do. +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. + + +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 +you'll be limited by the power of your actual CPU. You can see how much free +time your true CPU has by looking at the Task Manager in Windows 2000/XP and +the System Monitor in Windows 95/98/ME. Once 100% of your real CPU time is +used there is no further way to speed up DOSBox unless you reduce the load +generated by the non-CPU parts of DOSBox. + +So: + +Close every program but DOSBox + +Overclock DOSBox until 100% of your CPU is used (use the utilities above to +check) + +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 + +You can also try to disable the sound through the setup utility of the game +to further reduce load on your CPU. -4. Check the site/forum. Building your own Version DOSBox: ================================= diff --git a/THANKS b/THANKS index 6e7ae90..9a46546 100644 --- a/THANKS +++ b/THANKS @@ -3,7 +3,10 @@ We would like to thank: Vlad R. of the vdmsound project for excellent sound blaster info. Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator. +Jarek Burczynski for the new OPL emulator. + The Bochs and DOSemu projects which I used for information. Freedos for ideas in making my shell. + All the people who submitted a bug. The Beta Testers. diff --git a/acinclude.m4 b/acinclude.m4 index 2491c4e..bdf2763 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -160,9 +160,155 @@ int main (int argc, char *argv[]) rm -f conf.sdltest ]) +dnl Configure Paths for Alsa +dnl Some modifications by Richard Boulton +dnl Christopher Lansdown +dnl Jaroslav Kysela +dnl Last modification: alsa.m4,v 1.22 2002/05/27 11:14:20 tiwai Exp +dnl AM_PATH_ALSA([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for libasound, and define ALSA_CFLAGS and ALSA_LIBS as appropriate. +dnl enables arguments --with-alsa-prefix= +dnl --with-alsa-enc-prefix= +dnl --disable-alsatest (this has no effect, as yet) +dnl +dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified, +dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result. +dnl +AC_DEFUN(AM_PATH_ALSA, +[dnl Save the original CFLAGS, LDFLAGS, and LIBS +alsa_save_CFLAGS="$CFLAGS" +alsa_save_LDFLAGS="$LDFLAGS" +alsa_save_LIBS="$LIBS" +alsa_found=yes + +dnl +dnl Get the cflags and libraries for alsa +dnl +AC_ARG_WITH(alsa-prefix, +[ --with-alsa-prefix=PFX Prefix where Alsa library is installed(optional)], +[alsa_prefix="$withval"], [alsa_prefix=""]) + +AC_ARG_WITH(alsa-inc-prefix, +[ --with-alsa-inc-prefix=PFX Prefix where include libraries are (optional)], +[alsa_inc_prefix="$withval"], [alsa_inc_prefix=""]) + +dnl FIXME: this is not yet implemented +AC_ARG_ENABLE(alsatest, +[ --disable-alsatest Do not try to compile and run a test Alsa program], +[enable_alsatest=no], +[enable_alsatest=yes]) + +dnl Add any special include directories +AC_MSG_CHECKING(for ALSA CFLAGS) +if test "$alsa_inc_prefix" != "" ; then + ALSA_CFLAGS="$ALSA_CFLAGS -I$alsa_inc_prefix" + CFLAGS="$CFLAGS -I$alsa_inc_prefix" +fi +AC_MSG_RESULT($ALSA_CFLAGS) + +dnl add any special lib dirs +AC_MSG_CHECKING(for ALSA LDFLAGS) +if test "$alsa_prefix" != "" ; then + ALSA_LIBS="$ALSA_LIBS -L$alsa_prefix" + LDFLAGS="$LDFLAGS $ALSA_LIBS" +fi + +dnl add the alsa library +ALSA_LIBS="$ALSA_LIBS -lasound -lm -ldl -lpthread" +LIBS=`echo $LIBS | sed 's/-lm//'` +LIBS=`echo $LIBS | sed 's/-ldl//'` +LIBS=`echo $LIBS | sed 's/-lpthread//'` +LIBS=`echo $LIBS | sed 's/ //'` +LIBS="$ALSA_LIBS $LIBS" +AC_MSG_RESULT($ALSA_LIBS) + +dnl Check for a working version of libasound that is of the right version. +min_alsa_version=ifelse([$1], ,0.1.1,$1) +AC_MSG_CHECKING(for libasound headers version >= $min_alsa_version) +no_alsa="" + alsa_min_major_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + alsa_min_minor_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + alsa_min_micro_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILE([ +#include +], [ +/* ensure backward compatibility */ +#if !defined(SND_LIB_MAJOR) && defined(SOUNDLIB_VERSION_MAJOR) +#define SND_LIB_MAJOR SOUNDLIB_VERSION_MAJOR +#endif +#if !defined(SND_LIB_MINOR) && defined(SOUNDLIB_VERSION_MINOR) +#define SND_LIB_MINOR SOUNDLIB_VERSION_MINOR +#endif +#if !defined(SND_LIB_SUBMINOR) && defined(SOUNDLIB_VERSION_SUBMINOR) +#define SND_LIB_SUBMINOR SOUNDLIB_VERSION_SUBMINOR +#endif + +# if(SND_LIB_MAJOR > $alsa_min_major_version) + exit(0); +# else +# if(SND_LIB_MAJOR < $alsa_min_major_version) +# error not present +# endif + +# if(SND_LIB_MINOR > $alsa_min_minor_version) + exit(0); +# else +# if(SND_LIB_MINOR < $alsa_min_minor_version) +# error not present +# endif + +# if(SND_LIB_SUBMINOR < $alsa_min_micro_version) +# error not present +# endif +# endif +# endif +exit(0); +], + [AC_MSG_RESULT(found.)], + [AC_MSG_RESULT(not present.) + ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libasound not found.)]) + alsa_found=no] +) +AC_LANG_RESTORE + +dnl Now that we know that we have the right version, let's see if we have the library and not just the headers. +AC_CHECK_LIB([asound], [snd_ctl_open],, + [ifelse([$3], , [AC_MSG_ERROR(No linkable libasound was found.)]) + alsa_found=no] +) + +if test "x$alsa_found" = "xyes" ; then + ifelse([$2], , :, [$2]) + LIBS=`echo $LIBS | sed 's/-lasound//g'` + LIBS=`echo $LIBS | sed 's/ //'` + LIBS="-lasound $LIBS" +fi +if test "x$alsa_found" = "xno" ; then + ifelse([$3], , :, [$3]) + CFLAGS="$alsa_save_CFLAGS" + LDFLAGS="$alsa_save_LDFLAGS" + LIBS="$alsa_save_LIBS" + ALSA_CFLAGS="" + ALSA_LIBS="" +fi + +dnl That should be it. Now just export out symbols: +AC_SUBST(ALSA_CFLAGS) +AC_SUBST(ALSA_LIBS) +]) + + + + AH_TOP([ /* - * 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 @@ -180,7 +326,7 @@ AH_TOP([ */ ]) -AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures]) +AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures.]) AH_BOTTOM([#define INLINE inline]) @@ -190,5 +336,18 @@ 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 331d899..29c8c7b 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,4 +1,4 @@ -# aclocal.m4 generated automatically by aclocal 1.6.1 -*- Autoconf -*- +# aclocal.m4 generated automatically by aclocal 1.6.3 -*- Autoconf -*- # Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. @@ -173,9 +173,155 @@ int main (int argc, char *argv[]) rm -f conf.sdltest ]) +dnl Configure Paths for Alsa +dnl Some modifications by Richard Boulton +dnl Christopher Lansdown +dnl Jaroslav Kysela +dnl Last modification: alsa.m4,v 1.22 2002/05/27 11:14:20 tiwai Exp +dnl AM_PATH_ALSA([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for libasound, and define ALSA_CFLAGS and ALSA_LIBS as appropriate. +dnl enables arguments --with-alsa-prefix= +dnl --with-alsa-enc-prefix= +dnl --disable-alsatest (this has no effect, as yet) +dnl +dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified, +dnl and the alsa libraries are not found, a fatal AC_MSG_ERROR() will result. +dnl +AC_DEFUN(AM_PATH_ALSA, +[dnl Save the original CFLAGS, LDFLAGS, and LIBS +alsa_save_CFLAGS="$CFLAGS" +alsa_save_LDFLAGS="$LDFLAGS" +alsa_save_LIBS="$LIBS" +alsa_found=yes + +dnl +dnl Get the cflags and libraries for alsa +dnl +AC_ARG_WITH(alsa-prefix, +[ --with-alsa-prefix=PFX Prefix where Alsa library is installed(optional)], +[alsa_prefix="$withval"], [alsa_prefix=""]) + +AC_ARG_WITH(alsa-inc-prefix, +[ --with-alsa-inc-prefix=PFX Prefix where include libraries are (optional)], +[alsa_inc_prefix="$withval"], [alsa_inc_prefix=""]) + +dnl FIXME: this is not yet implemented +AC_ARG_ENABLE(alsatest, +[ --disable-alsatest Do not try to compile and run a test Alsa program], +[enable_alsatest=no], +[enable_alsatest=yes]) + +dnl Add any special include directories +AC_MSG_CHECKING(for ALSA CFLAGS) +if test "$alsa_inc_prefix" != "" ; then + ALSA_CFLAGS="$ALSA_CFLAGS -I$alsa_inc_prefix" + CFLAGS="$CFLAGS -I$alsa_inc_prefix" +fi +AC_MSG_RESULT($ALSA_CFLAGS) + +dnl add any special lib dirs +AC_MSG_CHECKING(for ALSA LDFLAGS) +if test "$alsa_prefix" != "" ; then + ALSA_LIBS="$ALSA_LIBS -L$alsa_prefix" + LDFLAGS="$LDFLAGS $ALSA_LIBS" +fi + +dnl add the alsa library +ALSA_LIBS="$ALSA_LIBS -lasound -lm -ldl -lpthread" +LIBS=`echo $LIBS | sed 's/-lm//'` +LIBS=`echo $LIBS | sed 's/-ldl//'` +LIBS=`echo $LIBS | sed 's/-lpthread//'` +LIBS=`echo $LIBS | sed 's/ //'` +LIBS="$ALSA_LIBS $LIBS" +AC_MSG_RESULT($ALSA_LIBS) + +dnl Check for a working version of libasound that is of the right version. +min_alsa_version=ifelse([$1], ,0.1.1,$1) +AC_MSG_CHECKING(for libasound headers version >= $min_alsa_version) +no_alsa="" + alsa_min_major_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + alsa_min_minor_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + alsa_min_micro_version=`echo $min_alsa_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + +AC_LANG_SAVE +AC_LANG_C +AC_TRY_COMPILE([ +#include +], [ +/* ensure backward compatibility */ +#if !defined(SND_LIB_MAJOR) && defined(SOUNDLIB_VERSION_MAJOR) +#define SND_LIB_MAJOR SOUNDLIB_VERSION_MAJOR +#endif +#if !defined(SND_LIB_MINOR) && defined(SOUNDLIB_VERSION_MINOR) +#define SND_LIB_MINOR SOUNDLIB_VERSION_MINOR +#endif +#if !defined(SND_LIB_SUBMINOR) && defined(SOUNDLIB_VERSION_SUBMINOR) +#define SND_LIB_SUBMINOR SOUNDLIB_VERSION_SUBMINOR +#endif + +# if(SND_LIB_MAJOR > $alsa_min_major_version) + exit(0); +# else +# if(SND_LIB_MAJOR < $alsa_min_major_version) +# error not present +# endif + +# if(SND_LIB_MINOR > $alsa_min_minor_version) + exit(0); +# else +# if(SND_LIB_MINOR < $alsa_min_minor_version) +# error not present +# endif + +# if(SND_LIB_SUBMINOR < $alsa_min_micro_version) +# error not present +# endif +# endif +# endif +exit(0); +], + [AC_MSG_RESULT(found.)], + [AC_MSG_RESULT(not present.) + ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libasound not found.)]) + alsa_found=no] +) +AC_LANG_RESTORE + +dnl Now that we know that we have the right version, let's see if we have the library and not just the headers. +AC_CHECK_LIB([asound], [snd_ctl_open],, + [ifelse([$3], , [AC_MSG_ERROR(No linkable libasound was found.)]) + alsa_found=no] +) + +if test "x$alsa_found" = "xyes" ; then + ifelse([$2], , :, [$2]) + LIBS=`echo $LIBS | sed 's/-lasound//g'` + LIBS=`echo $LIBS | sed 's/ //'` + LIBS="-lasound $LIBS" +fi +if test "x$alsa_found" = "xno" ; then + ifelse([$3], , :, [$3]) + CFLAGS="$alsa_save_CFLAGS" + LDFLAGS="$alsa_save_LDFLAGS" + LIBS="$alsa_save_LIBS" + ALSA_CFLAGS="" + ALSA_LIBS="" +fi + +dnl That should be it. Now just export out symbols: +AC_SUBST(ALSA_CFLAGS) +AC_SUBST(ALSA_LIBS) +]) + + + + AH_TOP([ /* - * 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 @@ -193,7 +339,7 @@ AH_TOP([ */ ]) -AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures]) +AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures.]) AH_BOTTOM([#define INLINE inline]) @@ -203,6 +349,19 @@ 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 +]) @@ -333,7 +492,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.6"]) # 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.1])]) + [AM_AUTOMAKE_VERSION([1.6.3])]) # Helper functions for option handling. -*- Autoconf -*- @@ -665,7 +824,7 @@ AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'] + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) @@ -790,7 +949,13 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` - if (sed 1q $mf | fgrep 'generated by automake') > /dev/null 2>&1; then + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue diff --git a/autogen.sh b/autogen.sh index 8b08a7e..9126bca 100644 --- a/autogen.sh +++ b/autogen.sh @@ -10,8 +10,4 @@ autoheader automake --gnits --include-deps --add-missing --copy autoconf -#Copy settings.h.cvs to settings.h and that's it, - -directory=`dirname $0` -cp $directory/settings.h.cvs $directory/settings.h -echo "Now you are ready to run ./configure also check settings.h for extra build settings" +echo "Now you are ready to run ./configure, afterwards check config.h for extra build settings" diff --git a/config.h.in b/config.h.in index 63982de..52bd4e0 100644 --- a/config.h.in +++ b/config.h.in @@ -2,7 +2,7 @@ /* - * 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,14 +20,23 @@ */ -/* Determines if the compilers supports attributes for structures */ +/* Define to 1 to enable internal debugger, requires libcurses */ +#undef C_DEBUG + +/* Determines if the compilers supports attributes for structures. */ #undef C_HAS_ATTRIBUTE +/* Define to 1 to enable screenshots, requires libpng */ +#undef C_SSHOT + +/* Define to 1 to use ALSA for MIDI */ +#undef HAVE_ALSA + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H -/* Define to 1 if you have the `png' library (-lpng). */ -#undef HAVE_LIBPNG +/* Define to 1 if you have the `asound' library (-lasound). */ +#undef HAVE_LIBASOUND /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H @@ -53,6 +62,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Compiling on Mac OS X */ +#undef MACOSX + /* Name of package */ #undef PACKAGE @@ -80,6 +92,10 @@ /* Version number of package */ #undef VERSION +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + /* Define to empty if `const' does not conform to ANSI C. */ #undef const @@ -97,3 +113,17 @@ #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 f365797..04baf3d 100644 --- a/config.sub +++ b/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -timestamp='2002-03-07' +timestamp='2003-01-03' # 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* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -229,24 +229,36 @@ case $basic_machine in | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | c4x | clipper \ - | d10v | d30v | dsp16xx \ - | fr30 \ + | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ + | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ - | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el | mips64vr4300 \ - | mips64vr4300el | mips64vr5000 | mips64vr5000el \ - | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ - | mipsisa32 | mipsisa64 \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ + | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ @@ -281,34 +293,47 @@ case $basic_machine in | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armv*-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ | clipper-* | cydra-* \ - | d10v-* | d30v-* \ + | d10v-* | d30v-* | dlx-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | fx80-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ - | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ - | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ - | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | msp430-* \ + | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ + | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ + | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ @@ -695,6 +720,10 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + nv1) + basic_machine=nv1-cray + os=-unicosmp + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -728,13 +757,13 @@ case $basic_machine in pbb) basic_machine=m68k-tti ;; - pc532 | pc532-*) + pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; - pentiumpro | p6 | 6x86 | athlon) + pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2) @@ -755,22 +784,22 @@ case $basic_machine in power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown - ;; + ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown - ;; + ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown - ;; + ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown - ;; + ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; @@ -801,6 +830,12 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; sequent) basic_machine=i386-sequent ;; @@ -866,7 +901,7 @@ case $basic_machine in sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; - sv1) + sv1) basic_machine=sv1-cray os=-unicos ;; @@ -874,10 +909,6 @@ case $basic_machine in basic_machine=i386-sequent os=-dynix ;; - t3d) - basic_machine=alpha-cray - os=-unicos - ;; t3e) basic_machine=alphaev5-cray os=-unicos @@ -886,6 +917,10 @@ 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 @@ -924,8 +959,8 @@ case $basic_machine in os=-vms ;; vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -946,11 +981,7 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt - ;; - xps | xps100) + xps | xps100) basic_machine=xps100-honeywell ;; ymp) @@ -996,7 +1027,7 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh3eb | sh4eb) + sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) basic_machine=sh-unknown ;; sh64) @@ -1005,7 +1036,7 @@ case $basic_machine in sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; - cydra) + cydra) basic_machine=cydra-cydrome ;; orion) @@ -1020,10 +1051,6 @@ case $basic_machine in pmac | pmac-mpw) basic_machine=powerpc-apple ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; @@ -1086,11 +1113,12 @@ case $os in | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova*) + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -microbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1102,8 +1130,10 @@ case $os in ;; esac ;; + -nto-qnx*) + ;; -nto*) - os=-nto-qnx + os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ @@ -1155,7 +1185,7 @@ case $os in os=-rtmk-nova ;; -ns2 ) - os=-nextstep2 + os=-nextstep2 ;; -nsk*) os=-nsk @@ -1194,8 +1224,8 @@ case $os in -xenix) os=-xenix ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint ;; -none) ;; @@ -1232,7 +1262,7 @@ case $basic_machine in pdp10-*) os=-tops20 ;; - pdp11-*) + pdp11-*) os=-none ;; *-dec | vax-*) @@ -1325,19 +1355,19 @@ case $basic_machine in *-next) os=-nextstep3 ;; - *-gould) + *-gould) os=-sysv ;; - *-highlevel) + *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; - *-sgi) + *-sgi) os=-irix ;; - *-siemens) + *-siemens) os=-sysv4 ;; *-masscomp) @@ -1409,7 +1439,7 @@ case $basic_machine in -ptx*) vendor=sequent ;; - -vxsim* | -vxworks*) + -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) diff --git a/configure b/configure index d6e06a8..b38d92a 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.53a for dosbox 0.57. +# Generated by GNU Autoconf 2.57 for dosbox 0.58. # # Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 # Free Software Foundation, Inc. @@ -21,7 +21,6 @@ elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi -# NLS nuisances. # Support unset when possible. if (FOO=FOO; unset FOO) >/dev/null 2>&1; then as_unset=unset @@ -29,31 +28,25 @@ else as_unset=false fi -(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && - { $as_unset LANG || test "${LANG+set}" != set; } || - { LANG=C; export LANG; } -(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && - { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || - { LC_ALL=C; export LC_ALL; } -(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && - { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || - { LC_TIME=C; export LC_TIME; } -(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && - { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || - { LC_CTYPE=C; export LC_CTYPE; } -(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && - { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || - { LANGUAGE=C; export LANGUAGE; } -(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && - { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || - { LC_COLLATE=C; export LC_COLLATE; } -(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && - { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || - { LC_NUMERIC=C; export LC_NUMERIC; } -(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && - { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || - { LC_MESSAGES=C; export LC_MESSAGES; } +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then @@ -92,15 +85,15 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conftest.sh - echo "exit 0" >>conftest.sh - chmod +x conftest.sh - if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi - rm -f conftest.sh + rm -f conf$$.sh fi @@ -244,7 +237,7 @@ as_nl=' IFS=" $as_nl" # CDPATH. -$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } +$as_unset CDPATH # Name of the host. @@ -258,6 +251,7 @@ exec 6>&1 # Initializations. # ac_default_prefix=/usr/local +ac_config_libobj_dir=. cross_compiling=no subdirs= MFLAGS= @@ -272,8 +266,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='dosbox' PACKAGE_TARNAME='dosbox' -PACKAGE_VERSION='0.57' -PACKAGE_STRING='dosbox 0.57' +PACKAGE_VERSION='0.58' +PACKAGE_STRING='dosbox 0.58' PACKAGE_BUGREPORT='' ac_unique_file="README" @@ -314,6 +308,8 @@ 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_files='' # Initialize some variables set by options. ac_init_help= @@ -737,6 +733,9 @@ if test ! -r $srcdir/$ac_unique_file; then { (exit 1); exit 1; }; } fi fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` ac_env_build_alias_set=${build_alias+set} ac_env_build_alias_value=$build_alias @@ -786,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.57 to adapt to many kinds of systems. +\`configure' configures dosbox 0.58 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -853,7 +852,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of dosbox 0.57:";; + short | recursive ) echo "Configuration of dosbox 0.58:";; esac cat <<\_ACEOF @@ -863,12 +862,17 @@ Optional Features: --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors --disable-sdltest Do not try to compile and run a test SDL program + --disable-alsatest Do not try to compile and run a test Alsa program + --enable-debug Enable debug mode + --enable-shots Enable screenshot support Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-sdl-prefix=PFX Prefix where SDL is installed (optional) --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional) + --with-alsa-prefix=PFX Prefix where Alsa library is installed(optional) + --with-alsa-inc-prefix=PFX Prefix where include libraries are (optional) Some influential environment variables: CC C compiler command @@ -946,8 +950,8 @@ fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -dosbox configure 0.57 -generated by GNU Autoconf 2.53a +dosbox configure 0.58 +generated by GNU Autoconf 2.57 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. @@ -961,8 +965,8 @@ cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by dosbox $as_me 0.57, which was -generated by GNU Autoconf 2.53a. Invocation command line was +It was created by dosbox $as_me 0.58, which was +generated by GNU Autoconf 2.57. Invocation command line was $ $0 $@ @@ -1014,27 +1018,54 @@ _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= +ac_configure_args0= +ac_configure_args1= ac_sep= -for ac_arg +ac_must_keep_next=false +for ac_pass in 1 2 do - case $ac_arg in - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n ) continue ;; - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - continue ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" - ac_sep=" " ;; - esac - # Get rid of the leading space. + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there @@ -1045,6 +1076,7 @@ trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo + cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## @@ -1067,6 +1099,35 @@ _ASBOX esac; } echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## @@ -1074,7 +1135,7 @@ _ASBOX ## ----------- ## _ASBOX echo - sed "/^$/d" confdefs.h + sed "/^$/d" confdefs.h | sort echo fi test "$ac_signal" != 0 && @@ -1240,6 +1301,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + ac_aux_dir= @@ -1540,15 +1602,15 @@ fi test -n "$AWK" && break done -echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 -echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 +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_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: - @echo 'ac_maketemp="${MAKE}"' + @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` @@ -1579,7 +1641,7 @@ fi # Define the identity of the package. PACKAGE=dosbox - VERSION=0.57 + VERSION=0.58 cat >>confdefs.h <<_ACEOF @@ -1712,15 +1774,15 @@ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" -echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 -echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 +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_,'` if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF all: - @echo 'ac_maketemp="${MAKE}"' + @echo 'ac_maketemp="$(MAKE)"' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` @@ -2050,8 +2112,10 @@ fi fi -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH" >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH" >&2;} +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. @@ -2076,14 +2140,12 @@ ac_compiler=`set X $ac_compile; echo $2` cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -2093,7 +2155,7 @@ main () } _ACEOF ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe" +ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. @@ -2112,26 +2174,39 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 # Be careful to initialize this variable, since it used to be cached. # Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. ac_cv_exeext= -for ac_file in `ls a_out.exe a.exe conftest.exe 2>/dev/null; - ls a.out conftest 2>/dev/null; - ls a.* conftest.* 2>/dev/null`; do +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; - a.out ) # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool --akim. - export ac_cv_exeext - break;; - * ) break;; + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; esac done else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables" >&5 -echo "$as_me: error: C compiler cannot create executables" >&2;} +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi @@ -2158,9 +2233,11 @@ if test "$cross_compiling" != yes; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'." >&5 +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'." >&2;} +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi @@ -2168,7 +2245,7 @@ fi echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 -rm -f a.out a.exe conftest$ac_cv_exeext +rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. @@ -2188,7 +2265,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. -for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` @@ -2198,8 +2276,10 @@ for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do esac done else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link" >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link" >&2;} + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi @@ -2217,14 +2297,12 @@ if test "${ac_cv_objext+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -2248,9 +2326,12 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 done else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile" >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile" >&2;} +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi @@ -2267,14 +2348,12 @@ if test "${ac_cv_c_compiler_gnu+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -2301,7 +2380,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_compiler_gnu=no fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -2321,14 +2401,12 @@ if test "${ac_cv_prog_cc_g+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -2352,7 +2430,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_prog_cc_g=no fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -2383,7 +2462,11 @@ else ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include #include #include @@ -2412,12 +2495,6 @@ struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -2452,7 +2529,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 break else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + fi rm -f conftest.$ac_objext done @@ -2503,15 +2581,13 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include $ac_declaration -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -2535,20 +2611,19 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 : else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + continue fi rm -f conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ $ac_declaration -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -2572,7 +2647,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 break else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + fi rm -f conftest.$ac_objext conftest.$ac_ext done @@ -2585,7 +2661,8 @@ fi else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + fi rm -f conftest.$ac_objext conftest.$ac_ext ac_ext=c @@ -2759,18 +2836,28 @@ for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" -#include +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? - egrep -v '^ *\+' conftest.er1 >conftest.err + grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 @@ -2787,7 +2874,8 @@ if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 - cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + # Broken: fails on valid input. continue fi @@ -2797,13 +2885,17 @@ rm -f conftest.err conftest.$ac_ext # can be detected and how. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* 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=$? - egrep -v '^ *\+' conftest.er1 >conftest.err + grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 @@ -2821,7 +2913,8 @@ if test -z "$ac_cpp_err"; then continue else echo "$as_me: failed program was:" >&5 - cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + # Passes both tests. ac_preproc_ok=: break @@ -2850,18 +2943,28 @@ for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" -#include +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif Syntax error _ACEOF if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 ac_status=$? - egrep -v '^ *\+' conftest.er1 >conftest.err + grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 @@ -2878,7 +2981,8 @@ if test -z "$ac_cpp_err"; then : else echo "$as_me: failed program was:" >&5 - cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + # Broken: fails on valid input. continue fi @@ -2888,13 +2992,17 @@ rm -f conftest.err conftest.$ac_ext # can be detected and how. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* 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=$? - egrep -v '^ *\+' conftest.er1 >conftest.err + grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 @@ -2912,7 +3020,8 @@ if test -z "$ac_cpp_err"; then continue else echo "$as_me: failed program was:" >&5 - cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + # Passes both tests. ac_preproc_ok=: break @@ -2925,8 +3034,10 @@ rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else - { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check" >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;} + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi @@ -3056,14 +3167,12 @@ if test "${ac_cv_cxx_compiler_gnu+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -3090,7 +3199,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_compiler_gnu=no fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -3110,14 +3220,12 @@ if test "${ac_cv_prog_cxx_g+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -3141,7 +3249,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_prog_cxx_g=no fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -3174,15 +3283,13 @@ for ac_declaration in \ do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include $ac_declaration -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -3206,20 +3313,19 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 : else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + continue fi rm -f conftest.$ac_objext conftest.$ac_ext cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ $ac_declaration -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -3243,7 +3349,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 break else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + fi rm -f conftest.$ac_objext conftest.$ac_ext done @@ -3593,7 +3700,11 @@ echo $ECHO_N "checking for SDL - version >= $min_sdl_version... $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include #include @@ -3668,11 +3779,12 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ( exit $ac_status ) no_sdl=yes fi -rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" @@ -3699,17 +3811,15 @@ echo "${ECHO_T}no" >&6 LIBS="$LIBS $SDL_LIBS" cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include #include "SDL.h" -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -3741,7 +3851,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + echo "*** The test program failed to compile or link. See the file config.log for the" echo "*** exact error that occured. This usually means SDL was incorrectly installed" echo "*** or that you have moved SDL since it was installed. In the latter case, you" @@ -3774,14 +3885,12 @@ if test "${ac_cv_c_const+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -3851,7 +3960,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_cv_c_const=yes else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_c_const=no fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -3875,7 +3985,11 @@ else for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } @@ -3898,7 +4012,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_cv_c_inline=$ac_kw; break else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + fi rm -f conftest.$ac_objext conftest.$ac_ext done @@ -3920,6 +4035,21 @@ _ACEOF esac +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 if test "${ac_cv_header_stdc+set}" = set; then @@ -3927,48 +4057,59 @@ if test "${ac_cv_header_stdc+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include #include #include #include +int +main () +{ + + ; + return 0; +} _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 ac_status=$? - egrep -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 + (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_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 - cat conftest.$ac_ext >&5 - ac_cv_header_stdc=no +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "memchr" >/dev/null 2>&1; then + $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no @@ -3981,12 +4122,16 @@ if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "free" >/dev/null 2>&1; then + $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no @@ -4002,13 +4147,18 @@ if test $ac_cv_header_stdc = yes; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else -# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \ +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) @@ -4041,11 +4191,12 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ( exit $ac_status ) ac_cv_header_stdc=no fi -rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi @@ -4080,7 +4231,11 @@ if eval "test \"\${$as_ac_Header+set}\" = set"; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ $ac_includes_default #include <$ac_header> @@ -4100,7 +4255,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + eval "$as_ac_Header=no" fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -4124,14 +4280,12 @@ if test "${ac_cv_type_size_t+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ $ac_includes_default -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -4158,7 +4312,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_cv_type_size_t=yes else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_type_size_t=no fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -4182,16 +4337,14 @@ if test "${ac_cv_struct_tm+set}" = set; then else cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ #include #include -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -4215,7 +4368,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 ac_cv_struct_tm=time.h else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_struct_tm=sys/time.h fi rm -f conftest.$ac_objext conftest.$ac_ext @@ -4232,88 +4386,17 @@ fi -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 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpng -lz $LIBS" -cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -#include "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 png_check_sig (); -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif -int -main () -{ -png_check_sig (); - ; - 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_png_png_check_sig=yes -else - echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&5 -ac_cv_lib_png_png_check_sig=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_png_png_check_sig" >&5 -echo "${ECHO_T}$ac_cv_lib_png_png_check_sig" >&6 -if test $ac_cv_lib_png_png_check_sig = yes; then - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBPNG 1 -_ACEOF - - LIBS="-lpng $LIBS" - -else - { { echo "$as_me:$LINENO: error: *** libpng not found!" >&5 -echo "$as_me: error: *** libpng not found!" >&2;} - { (exit 1); exit 1; }; } -fi - - #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 #line $LINENO "configure" -#include "confdefs.h" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ -#ifdef F77_DUMMY_MAIN -# ifdef __cplusplus - extern "C" -# endif - int F77_DUMMY_MAIN() { return 1; } -#endif int main () { @@ -4341,14 +4424,908 @@ _ACEOF else echo "$as_me: failed program was:" >&5 -cat conftest.$ac_ext >&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_ext +alsa_save_CFLAGS="$CFLAGS" +alsa_save_LDFLAGS="$LDFLAGS" +alsa_save_LIBS="$LIBS" +alsa_found=yes - 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" + +# Check whether --with-alsa-prefix or --without-alsa-prefix was given. +if test "${with_alsa_prefix+set}" = set; then + withval="$with_alsa_prefix" + alsa_prefix="$withval" +else + alsa_prefix="" +fi; + + +# Check whether --with-alsa-inc-prefix or --without-alsa-inc-prefix was given. +if test "${with_alsa_inc_prefix+set}" = set; then + withval="$with_alsa_inc_prefix" + alsa_inc_prefix="$withval" +else + alsa_inc_prefix="" +fi; + +# Check whether --enable-alsatest or --disable-alsatest was given. +if test "${enable_alsatest+set}" = set; then + enableval="$enable_alsatest" + enable_alsatest=no +else + enable_alsatest=yes +fi; + +echo "$as_me:$LINENO: checking for ALSA CFLAGS" >&5 +echo $ECHO_N "checking for ALSA CFLAGS... $ECHO_C" >&6 +if test "$alsa_inc_prefix" != "" ; then + ALSA_CFLAGS="$ALSA_CFLAGS -I$alsa_inc_prefix" + CFLAGS="$CFLAGS -I$alsa_inc_prefix" +fi +echo "$as_me:$LINENO: result: $ALSA_CFLAGS" >&5 +echo "${ECHO_T}$ALSA_CFLAGS" >&6 + +echo "$as_me:$LINENO: checking for ALSA LDFLAGS" >&5 +echo $ECHO_N "checking for ALSA LDFLAGS... $ECHO_C" >&6 +if test "$alsa_prefix" != "" ; then + ALSA_LIBS="$ALSA_LIBS -L$alsa_prefix" + LDFLAGS="$LDFLAGS $ALSA_LIBS" +fi + +ALSA_LIBS="$ALSA_LIBS -lasound -lm -ldl -lpthread" +LIBS=`echo $LIBS | sed 's/-lm//'` +LIBS=`echo $LIBS | sed 's/-ldl//'` +LIBS=`echo $LIBS | sed 's/-lpthread//'` +LIBS=`echo $LIBS | sed 's/ //'` +LIBS="$ALSA_LIBS $LIBS" +echo "$as_me:$LINENO: result: $ALSA_LIBS" >&5 +echo "${ECHO_T}$ALSA_LIBS" >&6 + +min_alsa_version=0.9.0 +echo "$as_me:$LINENO: checking for libasound headers version >= $min_alsa_version" >&5 +echo $ECHO_N "checking for libasound headers version >= $min_alsa_version... $ECHO_C" >&6 +no_alsa="" + alsa_min_major_version=`echo $min_alsa_version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'` + alsa_min_minor_version=`echo $min_alsa_version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'` + alsa_min_micro_version=`echo $min_alsa_version | \ + sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'` + + + +ac_ext=c +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 + +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 + +int +main () +{ + +/* ensure backward compatibility */ +#if !defined(SND_LIB_MAJOR) && defined(SOUNDLIB_VERSION_MAJOR) +#define SND_LIB_MAJOR SOUNDLIB_VERSION_MAJOR +#endif +#if !defined(SND_LIB_MINOR) && defined(SOUNDLIB_VERSION_MINOR) +#define SND_LIB_MINOR SOUNDLIB_VERSION_MINOR +#endif +#if !defined(SND_LIB_SUBMINOR) && defined(SOUNDLIB_VERSION_SUBMINOR) +#define SND_LIB_SUBMINOR SOUNDLIB_VERSION_SUBMINOR +#endif + +# if(SND_LIB_MAJOR > $alsa_min_major_version) + exit(0); +# else +# if(SND_LIB_MAJOR < $alsa_min_major_version) +# error not present +# endif + +# if(SND_LIB_MINOR > $alsa_min_minor_version) + exit(0); +# else +# if(SND_LIB_MINOR < $alsa_min_minor_version) +# error not present +# endif + +# if(SND_LIB_SUBMINOR < $alsa_min_micro_version) +# error not present +# endif +# endif +# endif +exit(0); + + ; + return 0; +} +_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 + echo "$as_me:$LINENO: result: found." >&5 +echo "${ECHO_T}found." >&6 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +echo "$as_me:$LINENO: result: not present." >&5 +echo "${ECHO_T}not present." >&6 + + alsa_found=no + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +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 + + + +echo "$as_me:$LINENO: checking for snd_ctl_open in -lasound" >&5 +echo $ECHO_N "checking for snd_ctl_open in -lasound... $ECHO_C" >&6 +if test "${ac_cv_lib_asound_snd_ctl_open+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lasound $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +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 snd_ctl_open (); +int +main () +{ +snd_ctl_open (); + ; + 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_asound_snd_ctl_open=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_asound_snd_ctl_open=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_asound_snd_ctl_open" >&5 +echo "${ECHO_T}$ac_cv_lib_asound_snd_ctl_open" >&6 +if test $ac_cv_lib_asound_snd_ctl_open = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBASOUND 1 +_ACEOF + + LIBS="-lasound $LIBS" + +else + + alsa_found=no + +fi + + +if test "x$alsa_found" = "xyes" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALSA 1 +_ACEOF + + LIBS=`echo $LIBS | sed 's/-lasound//g'` + LIBS=`echo $LIBS | sed 's/ //'` + LIBS="-lasound $LIBS" +fi +if test "x$alsa_found" = "xno" ; then + : + CFLAGS="$alsa_save_CFLAGS" + LDFLAGS="$alsa_save_LDFLAGS" + LIBS="$alsa_save_LIBS" + ALSA_CFLAGS="" + ALSA_LIBS="" +fi + + + + + +#Check for big endian machine, should #define WORD_BIGENDIAN if so +echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 +echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6 +if test "${ac_cv_c_bigendian+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # See if sys/param.h defines the BYTE_ORDER macro. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN + bogus endian macros +#endif + + ; + return 0; +} +_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 + # It does; now see whether it defined to BIG_ENDIAN or not. +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian +#endif + + ; + return 0; +} +_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_cv_c_bigendian=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_bigendian=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +# It does not; compile a test program. +if test "$cross_compiling" = yes; then + # try to guess the endianness by grepping values into an object file + ac_cv_c_bigendian=unknown + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; +short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; +void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; } +short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; +short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; +void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; } +int +main () +{ + _ascii (); _ebcdic (); + ; + return 0; +} +_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 + if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then + ac_cv_c_bigendian=yes +fi +if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi +fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +else + 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. */ +int +main () +{ + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long l; + char c[sizeof (long)]; + } u; + u.l = 1; + exit (u.c[sizeof (long) - 1] == 1); +} +_ACEOF +rm -f 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='./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_c_bigendian=no +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +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 +fi +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5 +echo "${ECHO_T}$ac_cv_c_bigendian" >&6 +case $ac_cv_c_bigendian in + yes) + +cat >>confdefs.h <<\_ACEOF +#define WORDS_BIGENDIAN 1 +_ACEOF + ;; + no) + ;; + *) + { { echo "$as_me:$LINENO: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&5 +echo "$as_me: error: unknown endianness +presetting ac_cv_c_bigendian=no (or yes) will help" >&2;} + { (exit 1); exit 1; }; } ;; +esac + + +#Features to enable/disable + + +# Check whether --enable-debug or --disable-debug was given. +if test "${enable_debug+set}" = set; then + enableval="$enable_debug" + + if test "${ac_cv_header_curses_h+set}" = set; then + echo "$as_me:$LINENO: checking for curses.h" >&5 +echo $ECHO_N "checking for curses.h... $ECHO_C" >&6 +if test "${ac_cv_header_curses_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_curses_h" >&5 +echo "${ECHO_T}$ac_cv_header_curses_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking curses.h usability" >&5 +echo $ECHO_N "checking curses.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +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 curses.h presence" >&5 +echo $ECHO_N "checking curses.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +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: curses.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: curses.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: curses.h: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: curses.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: curses.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: curses.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: curses.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: curses.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: curses.h: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for curses.h" >&5 +echo $ECHO_N "checking for curses.h... $ECHO_C" >&6 +if test "${ac_cv_header_curses_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_curses_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_curses_h" >&5 +echo "${ECHO_T}$ac_cv_header_curses_h" >&6 + +fi +if test $ac_cv_header_curses_h = yes; then + have_curses_h=yes +fi + + + echo "$as_me:$LINENO: checking for initscr in -lcurses" >&5 +echo $ECHO_N "checking for initscr in -lcurses... $ECHO_C" >&6 +if test "${ac_cv_lib_curses_initscr+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcurses $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +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_curses_initscr=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_curses_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_curses_initscr" >&5 +echo "${ECHO_T}$ac_cv_lib_curses_initscr" >&6 +if test $ac_cv_lib_curses_initscr = yes; then + have_curses_lib=yes +fi + + + if test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then + LIBS="$LIBS -lcurses" + cat >>confdefs.h <<\_ACEOF +#define C_DEBUG 1 +_ACEOF + + 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;} + fi + +fi; + + + +# Check whether --enable-shots or --disable-shots was given. +if test "${enable_shots+set}" = set; then + enableval="$enable_shots" + + 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 + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5 +echo "${ECHO_T}$ac_cv_header_png_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking png.h usability" >&5 +echo $ECHO_N "checking png.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +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 png.h presence" >&5 +echo $ECHO_N "checking png.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +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: png.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: png.h: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: png.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: png.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: png.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: png.h: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +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 + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_png_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5 +echo "${ECHO_T}$ac_cv_header_png_h" >&6 + +fi +if test $ac_cv_header_png_h = yes; then + have_png_h=yes +fi + + + 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 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpng -lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +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 png_check_sig (); +int +main () +{ +png_check_sig (); + ; + 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_png_png_check_sig=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_png_png_check_sig=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_check_sig" >&5 +echo "${ECHO_T}$ac_cv_lib_png_png_check_sig" >&6 +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 +#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 + +fi; + +case "$target" in + *-*-cygwin* | *-*-mingw32*) + LIBS="$LIBS -lwinmm" + ;; + *-*-darwin*) + +cat >>confdefs.h <<\_ACEOF +#define MACOSX 1 +_ACEOF + + LIBS="$LIBS -framework AudioUnit" + ;; +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" 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 @@ -4394,7 +5371,7 @@ _ACEOF t end /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ : end' >>confcache -if cmp -s $cache_file confcache; then :; else +if diff $cache_file confcache >/dev/null 2>&1; then :; else if test -w $cache_file; then test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" cat confcache >$cache_file @@ -4425,6 +5402,21 @@ fi DEFS=-DHAVE_CONFIG_H +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 @@ -4446,6 +5438,8 @@ cat >$CONFIG_STATUS <<_ACEOF # configure, is in config.log if it exists. debug=false +ac_cs_recheck=false +ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF @@ -4465,7 +5459,6 @@ elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then set -o posix fi -# NLS nuisances. # Support unset when possible. if (FOO=FOO; unset FOO) >/dev/null 2>&1; then as_unset=unset @@ -4473,31 +5466,25 @@ else as_unset=false fi -(set +x; test -n "`(LANG=C; export LANG) 2>&1`") && - { $as_unset LANG || test "${LANG+set}" != set; } || - { LANG=C; export LANG; } -(set +x; test -n "`(LC_ALL=C; export LC_ALL) 2>&1`") && - { $as_unset LC_ALL || test "${LC_ALL+set}" != set; } || - { LC_ALL=C; export LC_ALL; } -(set +x; test -n "`(LC_TIME=C; export LC_TIME) 2>&1`") && - { $as_unset LC_TIME || test "${LC_TIME+set}" != set; } || - { LC_TIME=C; export LC_TIME; } -(set +x; test -n "`(LC_CTYPE=C; export LC_CTYPE) 2>&1`") && - { $as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set; } || - { LC_CTYPE=C; export LC_CTYPE; } -(set +x; test -n "`(LANGUAGE=C; export LANGUAGE) 2>&1`") && - { $as_unset LANGUAGE || test "${LANGUAGE+set}" != set; } || - { LANGUAGE=C; export LANGUAGE; } -(set +x; test -n "`(LC_COLLATE=C; export LC_COLLATE) 2>&1`") && - { $as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set; } || - { LC_COLLATE=C; export LC_COLLATE; } -(set +x; test -n "`(LC_NUMERIC=C; export LC_NUMERIC) 2>&1`") && - { $as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set; } || - { LC_NUMERIC=C; export LC_NUMERIC; } -(set +x; test -n "`(LC_MESSAGES=C; export LC_MESSAGES) 2>&1`") && - { $as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set; } || - { LC_MESSAGES=C; export LC_MESSAGES; } +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1; then @@ -4536,15 +5523,15 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conftest.sh - echo "exit 0" >>conftest.sh - chmod +x conftest.sh - if (PATH=".;."; conftest.sh) >/dev/null 2>&1; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi - rm -f conftest.sh + rm -f conf$$.sh fi @@ -4690,7 +5677,7 @@ as_nl=' IFS=" $as_nl" # CDPATH. -$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=$PATH_SEPARATOR; export CDPATH; } +$as_unset CDPATH exec 6>&1 @@ -4706,8 +5693,8 @@ _ASBOX } >&5 cat >&5 <<_CSEOF -This file was extended by dosbox $as_me 0.57, which was -generated by GNU Autoconf 2.53a. Invocation command line was +This file was extended by dosbox $as_me 0.58, which was +generated by GNU Autoconf 2.57. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -4747,6 +5734,7 @@ Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number, then exit + -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] @@ -4768,8 +5756,8 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -dosbox config.status 0.57 -configured by $0, generated by GNU Autoconf 2.53a, +dosbox config.status 0.58 +configured by $0, generated by GNU Autoconf 2.57, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 @@ -4806,12 +5794,9 @@ do case $ac_option in # Handling of the options. _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion" - exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;; -_ACEOF cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; --version | --vers* | -V ) echo "$ac_cs_version"; exit 0 ;; --he | --h) @@ -4833,6 +5818,9 @@ Try \`$0 --help' for more information." >&2;} $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; # This is an error. -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 @@ -4847,6 +5835,20 @@ Try \`$0 --help' for more information." >&2;} shift done +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + _ACEOF cat >>$CONFIG_STATUS <<_ACEOF @@ -4881,6 +5883,7 @@ do "src/platform/visualc/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/platform/visualc/Makefile" ;; "visualc/Makefile" ) CONFIG_FILES="$CONFIG_FILES visualc/Makefile" ;; "include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "docs/Makefile" ) CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 @@ -4899,6 +5902,9 @@ if $ac_need_defaults; then test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. # Create a temporary directory, and hook for its removal unless debugging. $debug || { @@ -4907,17 +5913,17 @@ $debug || } # Create a (secure) tmp directory for tmp files. -: ${TMPDIR=/tmp} + { - tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` && + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { - tmp=$TMPDIR/cs$$-$RANDOM + tmp=./confstat$$-$RANDOM (umask 077 && mkdir $tmp) } || { - echo "$me: cannot create a temporary directory in $TMPDIR" >&2 + echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } @@ -5018,6 +6024,11 @@ s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t s,@SDL_CONFIG@,$SDL_CONFIG,;t t s,@SDL_CFLAGS@,$SDL_CFLAGS,;t t s,@SDL_LIBS@,$SDL_LIBS,;t t +s,@EGREP@,$EGREP,;t t +s,@ALSA_CFLAGS@,$ALSA_CFLAGS,;t t +s,@ALSA_LIBS@,$ALSA_LIBS,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF _ACEOF @@ -5331,7 +6342,7 @@ _ACEOF # Break up conftest.defines because some shells have a limit on the size # of here documents, and old seds have small limits too (100 cmds). echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS -echo ' if egrep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS echo ' :' >>$CONFIG_STATUS rm -f conftest.tail @@ -5355,7 +6366,7 @@ do mv conftest.tail conftest.defines done rm -f conftest.defines -echo ' fi # egrep' >>$CONFIG_STATUS +echo ' fi # grep' >>$CONFIG_STATUS echo >>$CONFIG_STATUS # Break up conftest.undefs because some shells have a limit on the size @@ -5395,7 +6406,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF cat $tmp/in >>$tmp/config.h rm -f $tmp/in if test x"$ac_file" != x-; then - if cmp -s $ac_file $tmp/config.h 2>/dev/null; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else @@ -5510,7 +6521,13 @@ echo "$as_me: executing $ac_dest commands" >&6;} depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` - if (sed 1q $mf | fgrep 'generated by automake') > /dev/null 2>&1; then + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`(dirname "$mf") 2>/dev/null || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ @@ -5614,8 +6631,11 @@ ac_clean_files=$ac_clean_files_save # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null - $SHELL $CONFIG_STATUS || ac_cs_success=false + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. diff --git a/configure.in b/configure.in index 9417a9d..adb4ad8 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,6 @@ dnl Init. -AC_INIT(dosbox,0.57) +AC_INIT(dosbox,0.58) +AC_PREREQ(2.50) AC_CONFIG_SRCDIR(README) dnl Detect the canonical host and target build environment @@ -36,13 +37,58 @@ AC_TYPE_SIZE_T AC_STRUCT_TM dnl Checks for libraries. -AC_CHECK_LIB(png, png_check_sig, , AC_MSG_ERROR([*** libpng not found!]), -lz) #Check if the compiler support attributes 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)) +AM_PATH_ALSA(0.9.0, AC_DEFINE(HAVE_ALSA,1,[Define to 1 to use ALSA for MIDI]) , : ) + +#Check for big endian machine, should #define WORD_BIGENDIAN if so +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],[ + AC_CHECK_HEADER(curses.h,have_curses_h=yes,) + AC_CHECK_LIB(curses, initscr, have_curses_lib=yes, , ) + + if test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then + LIBS="$LIBS -lcurses" + AC_DEFINE(C_DEBUG,1) + else + AC_MSG_WARN([Can't enable debug mode without libcurses]) + 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]) + fi +],) + +dnl Some host detection and actions for them +case "$target" in + *-*-cygwin* | *-*-mingw32*) + LIBS="$LIBS -lwinmm" + ;; + *-*-darwin*) + dnl We have a problem here: both MacOS X and Darwin report + dnl the same signature "powerpc-apple-darwin*" - so we have + dnl to do more to distinguish them. + dnl For now I am lazy and do not add proper detection code. + AC_DEFINE(MACOSX, 1, [Compiling on Mac OS X]) + LIBS="$LIBS -framework AudioUnit" + ;; +esac + AC_OUTPUT([ Makefile @@ -61,4 +107,5 @@ src/platform/Makefile src/platform/visualc/Makefile visualc/Makefile include/Makefile +docs/Makefile ]) diff --git a/depcomp b/depcomp index 3480ce4..807b991 100644 --- a/depcomp +++ b/depcomp @@ -209,16 +209,20 @@ aix) 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'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - base=`echo "$object" | sed -e 's/\.o$//' -e 's/\.lo$//'` - tmpdepfile1="$base.o.d" - tmpdepfile2="$base.d" if test "$libtool" = yes; then + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir.libs/$base.d" "$@" -Wc,-MD else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" "$@" -MD fi @@ -250,34 +254,40 @@ tru64) dashmstdout) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - test -z "$dashmflag" && dashmflag=-M - ( IFS=" " - case " $* " in - *" --mode=compile "*) # this is libtool, let us make it quiet - for arg - do # cycle over the arguments - case "$arg" in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done + # always write the proprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + 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 + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg ;; esac - "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi + done + + test -z "$dashmflag" && dashmflag=-M + "$@" -o /dev/null $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' @@ -295,33 +305,28 @@ dashXmstdout) ;; makedepend) + "$@" || exit $? # X makedepend - ( - shift - cleared=no - for arg in "$@"; do - case $cleared in no) - set ""; shift - cleared=yes - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift;; - -*) - ;; - *) - set fnord "$@" "$arg"; shift;; - esac - done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + -*) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' @@ -334,35 +339,39 @@ makedepend) cpp) # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - ( IFS=" " - case " $* " in - *" --mode=compile "*) - for arg - do # cycle over the arguments - case $arg in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done + # always write the proprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg ;; esac - "$@" -E | + done + + "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" @@ -374,47 +383,25 @@ msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the proprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. - ( IFS=" " - case " $* " in - *" --mode=compile "*) - for arg - do # cycle over the arguments - case $arg in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done - ;; - esac - for arg - do - case "$arg" in - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; - *) + *) set fnord "$@" "$arg" shift shift ;; - esac - done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..1773854 --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1,8 @@ +# Main Makefile for DOSBox + +man_MANS = dosbox.1 +EXTRA_DIST = $(man_MANS) + + + + diff --git a/docs/Makefile.in b/docs/Makefile.in new file mode 100644 index 0000000..d81d2dc --- /dev/null +++ b/docs/Makefile.in @@ -0,0 +1,262 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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@ + +# 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@ +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@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +man_MANS = dosbox.1 +EXTRA_DIST = $(man_MANS) +subdir = docs +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +NROFF = nroff +MANS = $(man_MANS) +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnits docs/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +man1dir = $(mandir)/man1 +install-man1: $(man1_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + 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; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done +tags: TAGS +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 \ + 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 $(MANS) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(man1dir) + +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 Makefile $(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 + +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: + +install-info: install-info-am + +install-man: install-man1 + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-man: uninstall-man1 + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-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 + +# 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/docs/dosbox.1 b/docs/dosbox.1 new file mode 100644 index 0000000..805b853 --- /dev/null +++ b/docs/dosbox.1 @@ -0,0 +1,60 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH DOSBOX 1 "March 31, 2003" +.\" Please adjust this date whenever revising the manpage. +.SH NAME +dosbox \- an x86/DOS emulator with sound/graphics primarily for games +.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 +.SH DESCRIPTION +This manual page briefly documents +\fBdosbox\fR, an x86/DOS emulator capable of running many games. +.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:. +.SH OPTIONS +A summary of options is included below. +.TP +\fB-fullscreen\fR +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. +.TP +\fB-conf\fR \fIconfigfile\fR +Start \fBdosbox\fR with the options specified in \fIconfigfile\fR +.TP +\fB-lang\fR \fIlangfile\fR +Start \fBdosbox\fR with the language specified in \fIlangfile\fR +.SH INTERNAL COMMANDS +.B dosbox +supports most of the DOS commands found in command.com. In addition, the +following extra commands are available: +.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. +.TP +\fBMEM\fR +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 +.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. +.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 +The README in /usr/share/doc/dosbox +.SH AUTHOR +This manual page was written by Peter Veenstra and James Oakley , +for the Debian system (but may be used by others). diff --git a/include/Makefile.in b/include/Makefile.in index 16604c5..23b4139 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -169,7 +172,7 @@ top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -214,7 +217,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/include/cross.h b/include/cross.h index 65066cd..813ff25 100644 --- a/include/cross.h +++ b/include/cross.h @@ -50,7 +50,5 @@ #define ftruncate(blah,blah2) chsize(blah,blah2) #endif -extern const char * dosbox_datadir; - #endif diff --git a/include/dma.h b/include/dma.h index 56a271b..58f78c6 100644 --- a/include/dma.h +++ b/include/dma.h @@ -16,10 +16,14 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +typedef void (* DMA_EnableCallBack)(bool enable); -Bit16u DMA_8_Read(Bit32u channel,Bit8u * buffer,Bit16u count); -Bit16u DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count); -Bit16u DMA_16_Read(Bit32u channel,Bit8u * buffer,Bit16u count); -Bit16u DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count); +void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback); + +Bitu DMA_8_Read(Bitu channel,Bit8u * buffer,Bitu count); +Bitu DMA_8_Write(Bitu dmachan,Bit8u * buffer,Bitu count); + +Bitu DMA_16_Read(Bitu channel,Bit8u * buffer,Bitu count); +Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count); diff --git a/include/dos_inc.h b/include/dos_inc.h index 2a039bd..1c4036b 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -29,14 +29,6 @@ struct CommandTail{ } GCC_ATTRIBUTE(packed); -struct MCB { - Bit8u type; - Bit16u psp_segment; - Bit16u size; - Bit8u unused[3]; - Bit8u filename[8]; -} GCC_ATTRIBUTE(packed); - #pragma pack () struct DOS_Date { @@ -267,7 +259,9 @@ public: void SetFCB1 (RealPt src); void SetFCB2 (RealPt src); void SetCommandTail (RealPt src); - + bool SetNumFiles (Bit16u fileNum); + Bit16u FindEntryByHandle (Bit8u handle); + private: #pragma pack(1) struct sPSP { @@ -362,6 +356,9 @@ public: Bit8u GetSearchDrive(void); void GetSearchParams(Bit8u & _sattr,char * _spattern); void GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr); + + void SetDirID(Bit16u entry) { sSave(sDTA,dirID,entry); }; + Bit16u GetDirID(void) { return sGet(sDTA,dirID); }; private: #pragma pack(1) struct sDTA { @@ -369,7 +366,8 @@ private: Bit8u sattr; /* The Attributes that need to be found */ Bit8u sname[8]; /* The Search pattern for the filename */ Bit8u sext[3]; /* The Search pattern for the extenstion */ - Bit8u fill[8]; + Bit16u dirID; /* custom: dir-search ID for multiple searches at the same time */ + Bit8u fill[6]; Bit8u attr; Bit16u time; Bit16u date; @@ -419,10 +417,32 @@ private: #pragma pack () }; +class DOS_MCB : public MemStruct{ +public: + DOS_MCB(Bit16u seg) { SetPt(seg); } + void SetFileName(char * _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); } + void GetFileName(char * _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;} + void SetType(Bit8u _type) { sSave(sMCB,type,_type);} + void SetSize(Bit16u _size) { sSave(sMCB,size,_size);} + void SetPSPSeg(Bit16u _pspseg) { sSave(sMCB,psp_segment,_pspseg);} + Bit8u GetType(void) { return sGet(sMCB,type);} + Bit16u GetSize(void) { return sGet(sMCB,size);} + Bit16u GetPSPSeg(void) { return sGet(sMCB,psp_segment);} +private: + #pragma pack (1) + struct sMCB { + Bit8u type; + Bit16u psp_segment; + Bit16u size; + Bit8u unused[3]; + Bit8u filename[8]; + } GCC_ATTRIBUTE(packed); + #pragma pack () +}; + extern DOS_InfoBlock dos_infoblock;; INLINE Bit8u RealHandle(Bit16u handle) { - DOS_PSP psp(dos.psp); return psp.GetFileHandle(handle); } diff --git a/include/dos_system.h b/include/dos_system.h index 545f661..0ea54ef 100644 --- a/include/dos_system.h +++ b/include/dos_system.h @@ -19,7 +19,10 @@ #ifndef DOSSYSTEM_H_ #define DOSSYSTEM_H_ +#include +#include #include "dosbox.h" +#include "cross.h" #define DOS_NAMELENGTH 12 #define DOS_NAMELENGTH_ASCII (DOS_NAMELENGTH+1) @@ -48,18 +51,25 @@ class DOS_DTA; class DOS_File { public: - virtual ~DOS_File(){}; - virtual bool Read(Bit8u * data,Bit16u * size)=0; - virtual bool Write(Bit8u * data,Bit16u * size)=0; - virtual bool Seek(Bit32u * pos,Bit32u type)=0; - virtual bool Close()=0; - virtual Bit16u GetInformation(void)=0; + DOS_File() { name=0; }; + virtual ~DOS_File(){}; + virtual bool Read(Bit8u * data,Bit16u * size)=0; + virtual bool Write(Bit8u * data,Bit16u * size)=0; + virtual bool Seek(Bit32u * pos,Bit32u type)=0; + virtual bool Close()=0; + virtual Bit16u GetInformation(void)=0; + virtual void SetName(const char* _name) { if (name) delete[] name; name = new char[strlen(_name)+1]; strcpy(name,_name); } + 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; }; Bit8u type; Bit32u flags; Bit16u time; Bit16u date; Bit16u attr; Bit32u size; + bool open; + char* name; /* Some Device Specific Stuff */ }; @@ -70,6 +80,114 @@ public: Bit8u fhandle; }; +#define MAX_OPENDIRS 16 + +class DOS_Drive_Cache { +public: + DOS_Drive_Cache (void); + DOS_Drive_Cache (const char* path); + ~DOS_Drive_Cache (void); + + typedef enum TDirSort { NOSORT, ALPHABETICAL, DIRALPHABETICAL, ALPHABETICALREV, DIRALPHABETICALREV }; + + void SetBaseDir (const char* path); + void SetDirSort (TDirSort sort) { sortDirType = sort; }; + bool OpenDir (const char* path, Bit16u& id); + bool ReadDir (Bit16u id, char* &result); + + void ExpandName (char* path); + char* GetExpandName (const char* path); + bool GetShortName (const char* fullname, char* shortname); + + 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); + + class CFileInfo { + public: + ~CFileInfo(void) { + for (Bit32u i=0; i fileList; + std::vector longNameList; + std::vector outputList; + }; + +private: + + bool RemoveTrailingDot (char* shortname); + Bit16s 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); + void CreateEntry (CFileInfo* dir, const char* name); + Bit16u GetFreeID (CFileInfo* dir); + void Clear (void); + + + CFileInfo* dirBase; + char dirPath [CROSS_LEN]; + char basePath [CROSS_LEN]; + bool dirFirstTime; + TDirSort sortDirType; + CFileInfo* save_dir; + char save_path [CROSS_LEN]; + char save_expanded [CROSS_LEN]; + + Bit16u srchNr; + CFileInfo* dirSearch [MAX_OPENDIRS]; + char dirSearchName [MAX_OPENDIRS]; + bool free [MAX_OPENDIRS]; + +}; + +class DOS_No_Drive_Cache { +public: + DOS_No_Drive_Cache (void) {}; + DOS_No_Drive_Cache (const char* path); + ~DOS_No_Drive_Cache (void) {}; + + typedef enum TDirSort { NOSORT, ALPHABETICAL, DIRALPHABETICAL, ALPHABETICALREV, DIRALPHABETICALREV }; + + void SetBaseDir (const char* path); + void SetDirSort (TDirSort sort) {}; + bool OpenDir (const char* path, Bit16u& id); + bool ReadDir (Bit16u id, char * &result); + + void ExpandName (char* path) {}; + char* GetExpandName (const char* path) { return (char*)path; }; + bool GetShortName (const char* fullname, char* shortname) { return false; }; + + void CacheOut (const char* path, bool ignoreLastDir = false) {}; + void AddEntry (const char* path, bool checkExists = false) {}; + void DeleteEntry (const char* path, bool ignoreLastDir = false) {}; + + void SetCurrentEntry (Bit16u entry) {}; + Bit16u GetCurrentEntry (void) { return 0; }; + + void EmptyCache (void) {}; + +public: + char basePath [CROSS_LEN]; + char dirPath [CROSS_LEN]; +}; + class DOS_Drive { public: DOS_Drive(); @@ -88,9 +206,13 @@ public: virtual bool FileExists(const char* name)=0; virtual bool FileStat(const char* name, FileStat_Block * const stat_block)=0; virtual Bit8u GetMediaByte(void)=0; + virtual void SetDir(const char* path) { strcpy(curdir,path); }; + virtual void EmptyCache(void) { dirCache.EmptyCache(); }; char * GetInfo(void); char curdir[DOS_PATHLENGTH]; char info[256]; + + DOS_Drive_Cache dirCache; }; enum { OPEN_READ=0,OPEN_WRITE=1,OPEN_READWRITE=2 }; diff --git a/include/dosbox.h b/include/dosbox.h index 25606f6..03205ec 100644 --- a/include/dosbox.h +++ b/include/dosbox.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 @@ -48,11 +48,9 @@ typedef signed int Bits; #include #include "config.h" -#include "../settings.h" class Section; - typedef Bitu (LoopHandler)(void); void DOSBOX_RunMachine(); @@ -65,101 +63,25 @@ class Config; extern Config * control; extern Bitu errorlevel; -inline void LOG_MSG(char* message) -{ - if(errorlevel>=0) S_Warn(message); -} +#define LOG_MSG S_Warn -template -inline void LOG_MSG(char* message,type1 arg1) -{ - - if(errorlevel>=0) S_Warn(message,arg1); -} - -template -inline void LOG_MSG(char* message,type1 arg1,type2 arg2) -{ - - if(errorlevel>=0) S_Warn(message,arg1,arg2); -} - -template -inline void LOG_MSG(char* message,type1 arg1,type2 arg2,type3 arg3) -{ - - if (errorlevel>=0)S_Warn(message,arg1,arg2,arg3); -} - -#if C_LOGGING -inline void LOG_DEBUG(char * message) -{ - - if(errorlevel>=2) S_Warn(message); -} - -template -inline void LOG_DEBUG(char * message, type type1) -{ - - if(errorlevel>=2) S_Warn(message,type1); -} - -template -inline void LOG_WARN(char * message, type type1) -{ - - if(errorlevel>=1) S_Warn(message,type1); -} - -inline void LOG_WARN(char* message) -{ - - if(errorlevel>=1) S_Warn(message); -} - -inline void LOG_ERROR(char * message) -{ - - if(errorlevel>=0) S_Warn(message); -} - -template -inline void LOG_ERROR(char * message, type type1) -{ - - if(errorlevel>=0) S_Warn(message,type1); -} - -template -inline void LOG_ERROR(char * message, type1 arg1,type2 arg2) -{ - - if(errorlevel>=0) S_Warn(message,arg1,arg2); -} - -template -inline void LOG_WARN(char * message, type1 arg1,type2 arg2) -{ - - if(errorlevel>=1) S_Warn(message,arg1,arg2); -} - -template -inline void LOG_DEBUG(char * message, type1 arg1,type2 arg2) -{ - - if(errorlevel>=2) S_Warn(message,arg1,arg2); -} +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_DEBUG -#define LOG_WARN -#define LOG_ERROR -#endif +#define LOG +#endif /* C_DEBUG */ - - - -#endif +#endif /* __DOSBOX_H */ diff --git a/include/joystick.h b/include/joystick.h index 3317db1..6c14091 100644 --- a/include/joystick.h +++ b/include/joystick.h @@ -22,4 +22,12 @@ void JOYSTICK_Button(Bitu which,Bitu num,bool pressed); void JOYSTICK_Move_X(Bitu which,float x); -void JOYSTICK_Move_Y(Bitu which,float y); \ No newline at end of file +void JOYSTICK_Move_Y(Bitu which,float y); + +bool JOYSTICK_IsEnabled(Bitu which); + +bool JOYSTICK_GetButton(Bitu which, Bitu num); + +float JOYSTICK_GetMove_X(Bitu which); + +float JOYSTICK_GetMove_Y(Bitu which); diff --git a/include/keyboard.h b/include/keyboard.h index 0ff524e..db7b0c1 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -19,17 +19,7 @@ #ifndef _KEYBOARD_H_ #define _KEYBOARD_H_ -typedef void(KEYBOARD_EventHandler)(void); -void KEYBOARD_AddCode(Bit8u code); -void KEYBOARD_AddKey(Bitu keytype,bool pressed); -void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler); - - -#define ALT_PRESSED 0x1 -#define CTRL_PRESSED 0x2 -#define SHIFT_PRESSED 0x4 - -enum { +enum KBD_KEYS { KBD_1, KBD_2, KBD_3, KBD_4, KBD_5, KBD_6, KBD_7, KBD_8, KBD_9, KBD_0, KBD_q, KBD_w, KBD_e, KBD_r, KBD_t, KBD_y, KBD_u, KBD_i, KBD_o, KBD_p, KBD_a, KBD_s, KBD_d, KBD_f, KBD_g, KBD_h, KBD_j, KBD_k, KBD_l, KBD_z, @@ -54,4 +44,16 @@ enum { KBD_LAST }; +typedef void(KEYBOARD_EventHandler)(void); + +void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler); +void KEYBOARD_AddKey(KBD_KEYS key,Bitu ascii,Bitu mod,bool pressed); +void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod); + + +#define KBD_MOD_ALT 0x1 +#define KBD_MOD_CTRL 0x2 +#define KBD_MOD_SHIFT 0x4 + + #endif diff --git a/include/mem.h b/include/mem.h index 169e49c..19e3d30 100644 --- a/include/mem.h +++ b/include/mem.h @@ -60,6 +60,33 @@ extern HostPt memory; Working on big or little endian machines */ +#ifdef WORDS_BIGENDIAN + +INLINE Bit8u readb(HostPt off) { + return off[0]; +}; +INLINE Bit16u readw(HostPt off) { + return off[0] | (off[1] << 8); +}; +INLINE Bit32u readd(HostPt off) { + return off[0] | (off[1] << 8) | (off[2] << 16) | (off[3] << 24); +}; +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); +}; +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); +}; + +#else + INLINE Bit8u readb(HostPt off) { return *(Bit8u *)off; }; @@ -79,6 +106,7 @@ INLINE void writed(HostPt off,Bit32u val) { *(Bit32u *)(off)=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 diff --git a/include/mixer.h b/include/mixer.h index 3c02d93..3144a8b 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -39,7 +39,6 @@ void MIXER_Enable(MIXER_Channel * chan,bool enable); /* PC Speakers functions, tightly related to the timer functions */ -void PCSPEAKER_Enable(bool enable); void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode); - +void PCSPEAKER_SetType(Bitu mode); diff --git a/include/regs.h b/include/regs.h index d4bd3c4..2c3954f 100644 --- a/include/regs.h +++ b/include/regs.h @@ -43,14 +43,30 @@ struct Segment { enum SegNames { cs=0,ds,es,fs,gs,ss}; +union GenReg32 { + Bit32u dword[1]; + Bit16u word[2]; + Bit8u byte[4]; +}; + +#ifdef WORDS_BIGENDIAN + +#define DW_INDEX 0 +#define W_INDEX 1 +#define BH_INDEX 2 +#define BL_INDEX 3 + +#else + +#define DW_INDEX 0 +#define W_INDEX 0 +#define BH_INDEX 1 +#define BL_INDEX 0 + +#endif + struct CPU_Regs { - union { - Bit32u d; - Bit16u w; - struct { - Bit8u l,h; - }b; - } regs[8],ip; + GenReg32 regs[8],ip; }; extern Segment Segs[6]; @@ -87,46 +103,47 @@ enum REG_NUM { }; //macros to convert a 3-bit register index to the correct register -#define reg_8l(reg) (cpu_regs.regs[(reg)].b.l) -#define reg_8h(reg) (cpu_regs.regs[(reg)].b.h) +#define reg_8l(reg) (cpu_regs.regs[(reg)].byte[BL_INDEX]) +#define reg_8h(reg) (cpu_regs.regs[(reg)].byte[BH_INDEX]) #define reg_8(reg) ((reg) & 4 ? reg_8h((reg) & 3) : reg_8l((reg) & 3)) -#define reg_16(reg) (cpu_regs.regs[(reg)].w) -#define reg_32(reg) (cpu_regs.regs[(reg)].d) +#define reg_16(reg) (cpu_regs.regs[(reg)].word[W_INDEX]) +#define reg_32(reg) (cpu_regs.regs[(reg)].dword[DW_INDEX]) -#define reg_al cpu_regs.regs[REG_NUM_AX].b.l -#define reg_ah cpu_regs.regs[REG_NUM_AX].b.h -#define reg_ax cpu_regs.regs[REG_NUM_AX].w -#define reg_eax cpu_regs.regs[REG_NUM_AX].d -#define reg_bl cpu_regs.regs[REG_NUM_BX].b.l -#define reg_bh cpu_regs.regs[REG_NUM_BX].b.h -#define reg_bx cpu_regs.regs[REG_NUM_BX].w -#define reg_ebx cpu_regs.regs[REG_NUM_BX].d +#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_cl cpu_regs.regs[REG_NUM_CX].b.l -#define reg_ch cpu_regs.regs[REG_NUM_CX].b.h -#define reg_cx cpu_regs.regs[REG_NUM_CX].w -#define reg_ecx cpu_regs.regs[REG_NUM_CX].d +#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_dl cpu_regs.regs[REG_NUM_DX].b.l -#define reg_dh cpu_regs.regs[REG_NUM_DX].b.h -#define reg_dx cpu_regs.regs[REG_NUM_DX].w -#define reg_edx cpu_regs.regs[REG_NUM_DX].d +#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_si cpu_regs.regs[REG_NUM_SI].w -#define reg_esi cpu_regs.regs[REG_NUM_SI].d +#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_di cpu_regs.regs[REG_NUM_DI].w -#define reg_edi cpu_regs.regs[REG_NUM_DI].d +#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_sp cpu_regs.regs[REG_NUM_SP].w -#define reg_esp cpu_regs.regs[REG_NUM_SP].d +#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_bp cpu_regs.regs[REG_NUM_BP].w -#define reg_ebp cpu_regs.regs[REG_NUM_BP].d +#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_ip cpu_regs.ip.w -#define reg_eip cpu_regs.ip.d +#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_ip cpu_regs.ip.word[W_INDEX] +#define reg_eip cpu_regs.ip.dword[DW_INDEX] #endif diff --git a/include/render.h b/include/render.h index e7a0b84..054941c 100644 --- a/include/render.h +++ b/include/render.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 @@ -19,7 +19,8 @@ enum RENDER_Operation { - OP_None,OP_2xSai,OP_Scale2x + OP_None,OP_Shot, + OP_2xSai,OP_Scale2x, }; enum { @@ -29,12 +30,13 @@ enum { DoubleBoth= 0x03 }; -bool RENDER_StartUpdate(void); -void RENDER_EndUpdate(void); -void RENDER_Part(Bit8u * data,Bitu x,Bitu y,Bitu dx,Bitu dy); +typedef void (* RENDER_Part_Handler)(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy); +typedef void (* RENDER_Draw_Handler)(RENDER_Part_Handler part_handler); -void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags); +void RENDER_DoUpdate(void); + +void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags,RENDER_Draw_Handler draw_handler); void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue); diff --git a/include/setup.h b/include/setup.h index 248acf7..21ea765 100644 --- a/include/setup.h +++ b/include/setup.h @@ -179,7 +179,8 @@ public: void StartUp(); void PrintConfig(const char* configfilename); void ParseConfigFile(const char* configfilename); - + void ParseEnv(char ** envp); + std::list sectionlist; typedef std::list::iterator it; typedef std::list::reverse_iterator reverse_it; diff --git a/include/video.h b/include/video.h index d642412..a7304ff 100644 --- a/include/video.h +++ b/include/video.h @@ -22,6 +22,8 @@ typedef void (* GFX_ModeCallBack)(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags); +typedef void (* GFX_DrawCallBack)(void * data); + struct GFX_PalEntry { Bit8u r; Bit8u g; @@ -31,6 +33,8 @@ struct GFX_PalEntry { #define GFX_FIXED_BPP 0x01 #define GFX_RESIZEABLE 0x02 +#define GFX_SHADOW 0x04 + #define MODE_SET 0x01 #define MODE_FULLSCREEN 0x02 @@ -40,14 +44,13 @@ void GFX_Events(void); void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries); Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue); -void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu flags,GFX_ModeCallBack callback); +void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu flags,GFX_ModeCallBack mode_callback, GFX_DrawCallBack draw_callback); void GFX_Start(void); void GFX_Stop(void); void GFX_SwitchFullScreen(void); -void * GFX_StartUpdate(void); -void GFX_EndUpdate(void); +void GFX_DoUpdate(void); #endif diff --git a/install-sh b/install-sh index 398a88e..11870f1 100644 --- a/install-sh +++ b/install-sh @@ -128,7 +128,7 @@ else # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. - if [ -f $src -o -d $src ] + if [ -f "$src" ] || [ -d "$src" ] then : else diff --git a/missing b/missing index dd58370..6a37006 100644 --- a/missing +++ b/missing @@ -1,6 +1,6 @@ #! /bin/sh # Common stub for a few missing GNU programs while installing. -# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify @@ -293,23 +293,23 @@ WARNING: \`$1' is missing on your system. You should only need it if # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then - gnutar ${1+"$@"} && exit 0 + gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then - gtar ${1+"$@"} && exit 0 + gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" ${1+"$@"} && exit 0 + tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" ${1+"$@"} && exit 0 + tar "$firstarg" "$@" && exit 0 ;; esac fi diff --git a/mkinstalldirs b/mkinstalldirs index f9c37af..8ab885e 100644 --- a/mkinstalldirs +++ b/mkinstalldirs @@ -4,8 +4,6 @@ # Created: 1993-05-16 # Public domain -# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ - errstatus=0 dirmode="" diff --git a/settings.h b/settings.h deleted file mode 100644 index f0580eb..0000000 --- a/settings.h +++ /dev/null @@ -1,43 +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. - */ - -#ifndef _SETTINGS_H_ -#define _SETTINGS_H_ - -/* Enable the debugger, under linux/freebsd dosbox must be started in an xterm under X */ -#define C_DEBUG 0 -#define C_HEAVY_DEBUG 0 - -/* Enable the logging of extra information for debugging to the console */ -#define C_LOGGING 0 - -/* Enable some big compile-time increasing inlines, great for speed though */ -#define C_EXTRAINLINE 0 - -/* Enable the FPU module, still only for beta testing */ -#define C_FPU 0 - -/* Maximum memory range in megabytes */ -#define C_MEM_MAX_SIZE 12 - -/* Enable debug messages for several modules, requires C_LOGGING */ -#define DEBUG_SBLASTER 0 /* SoundBlaster Debugging*/ -#define DEBUG_DMA 0 /* DMA Debugging */ -#define DEBUG_DOS 0 /* DOS Debugging */ - -#endif diff --git a/src/Makefile.am b/src/Makefile.am index 151e5e0..24279b3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,5 +6,5 @@ bin_PROGRAMS = dosbox dosbox_SOURCES = dosbox.cpp dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \ - ints/libints.a misc/libmisc.a shell/libshell.a -lcurses -lpng + ints/libints.a misc/libmisc.a shell/libshell.a diff --git a/src/Makefile.in b/src/Makefile.in index e7f9ea5..cfd9289 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -89,7 +92,7 @@ bin_PROGRAMS = dosbox dosbox_SOURCES = dosbox.cpp dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \ - ints/libints.a misc/libmisc.a shell/libshell.a -lcurses -lpng + ints/libints.a misc/libmisc.a shell/libshell.a subdir = src mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -146,8 +149,7 @@ install-binPROGRAMS: $(bin_PROGRAMS) p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ - p1=`echo "$$p1" | sed -e 's,^.*/,,'`; \ - f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ + 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; \ else :; fi; \ @@ -156,8 +158,7 @@ install-binPROGRAMS: $(bin_PROGRAMS) uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ - f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ - f=`echo "$$f" | sed -e 's,^.*/,,'`; \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ rm -f $(DESTDIR)$(bindir)/$$f; \ done @@ -294,7 +295,7 @@ top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -353,7 +354,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/cpu/Makefile.am b/src/cpu/Makefile.am index 5a8f26a..97ef51e 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -2,4 +2,4 @@ SUBDIRS = core_16 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 \ No newline at end of file +libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp instructions.h \ No newline at end of file diff --git a/src/cpu/Makefile.in b/src/cpu/Makefile.in index 043f52b..0a41ab0 100644 --- a/src/cpu/Makefile.in +++ b/src/cpu/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -85,7 +88,7 @@ SUBDIRS = core_16 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 +libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp instructions.h subdir = src/cpu mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h @@ -278,7 +281,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -336,7 +339,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index 7d5efa5..ce79268 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.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 @@ -67,7 +67,7 @@ void CALLBACK_Idle(void) { } static Bitu default_handler(void) { - LOG_WARN("Illegal Unhandled Interrupt Called %X",lastint); + LOG(LOG_ERROR|LOG_CPU,"Illegal Unhandled Interrupt Called %X",lastint); return CBRET_NONE; }; @@ -167,14 +167,13 @@ void CALLBACK_Init(Section* sec) { real_writeb((Bit16u)CB_SEG,(call_idle<<4)+13,0x38); real_writew((Bit16u)CB_SEG,(call_idle<<4)+14,call_idle); -#if C_DEBUG /* Setup all Interrupt to point to the default handler */ call_default=CALLBACK_Allocate(); CALLBACK_Setup(call_default,&default_handler,CB_IRET); - for (i=0;i<256;i++) { + /* Only setup default handler for first half of interrupt table */ + for (i=0;i<0x40;i++) { real_writed(0,i*4,CALLBACK_RealPointer(call_default)); } -#endif } diff --git a/src/cpu/core_16/Makefile.am b/src/cpu/core_16/Makefile.am index f2f2d54..27aa284 100644 --- a/src/cpu/core_16/Makefile.am +++ b/src/cpu/core_16/Makefile.am @@ -1,3 +1,3 @@ -noinst_HEADERS = helpers.h instructions.h main.h prefix_66.h prefix_of.h start.h stop.h support.h table_ea.h \ +noinst_HEADERS = helpers.h main.h prefix_66.h prefix_of.h start.h stop.h support.h table_ea.h \ prefix_66_of.h diff --git a/src/cpu/core_16/Makefile.in b/src/cpu/core_16/Makefile.in index 21af21e..c09a376 100644 --- a/src/cpu/core_16/Makefile.in +++ b/src/cpu/core_16/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -82,7 +85,7 @@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ -noinst_HEADERS = helpers.h instructions.h main.h prefix_66.h prefix_of.h start.h stop.h support.h table_ea.h \ +noinst_HEADERS = helpers.h main.h prefix_66.h prefix_of.h start.h stop.h support.h table_ea.h \ prefix_66_of.h subdir = src/cpu/core_16 @@ -144,7 +147,7 @@ top_distdir = ../../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -189,7 +192,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/cpu/core_16/main.h b/src/cpu/core_16/main.h index 4926826..5bfe47c 100644 --- a/src/cpu/core_16/main.h +++ b/src/cpu/core_16/main.h @@ -961,7 +961,7 @@ restart: case 0xde: /* FPU ESC 6 */ case 0xdf: /* FPU ESC 7 */ { - LOG_WARN("FPU used"); + LOG(LOG_CPU,"FPU used"); Bit8u rm=Fetchb(); if (rm<0xc0) GetEAa; } @@ -1037,7 +1037,7 @@ restart: IO_Write(reg_dx+1,reg_ah); break; case 0xf0: /* LOCK */ - LOG_ERROR("CPU:LOCK"); + LOG(LOG_CPU,"CPU:LOCK"); break; case 0xf1: /* Weird call undocumented */ // INTERRUPT(1); diff --git a/src/cpu/core_16/prefix_66.h b/src/cpu/core_16/prefix_66.h index 340be2d..60cb966 100644 --- a/src/cpu/core_16/prefix_66.h +++ b/src/cpu/core_16/prefix_66.h @@ -146,7 +146,7 @@ switch(Fetchb()) { Push_32(reg_esp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi); break; case 0x61: /* POPAD */ - reg_edi=Pop_32();reg_edi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP + reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32(); break; case 0x64: /* SEG FS: */ @@ -276,7 +276,7 @@ switch(Fetchb()) { break; } case 0x8c: - LOG_WARN("CPU:66:8c looped back"); + LOG(LOG_CPU,"CPU:66:8c looped back"); break; case 0x8d: /* LEA */ { diff --git a/src/cpu/core_16/prefix_of.h b/src/cpu/core_16/prefix_of.h index ebac6f2..039f660 100644 --- a/src/cpu/core_16/prefix_of.h +++ b/src/cpu/core_16/prefix_of.h @@ -62,7 +62,7 @@ switch(Fetchb()) { case 0x23: /* MOV DRx,Rd */ { GetRM; - LOG_DEBUG("CPU:0F:23 does nothing"); + LOG(LOG_CPU,"CPU:0F:23 does nothing"); } break; /* 0x24 MOV Rd,TRx (386) */ diff --git a/src/cpu/core_16/support.h b/src/cpu/core_16/support.h index 5f540a0..93d48c6 100644 --- a/src/cpu/core_16/support.h +++ b/src/cpu/core_16/support.h @@ -98,7 +98,6 @@ static INLINE Bit32u Pop_32() { #include "helpers.h" #include "table_ea.h" #include "../modrm.h" -#include "instructions.h" static Bit8s table_df_8[2]={1,-1}; @@ -354,8 +353,8 @@ rep_again: break; default: IPPoint--; - LOG_DEBUG("Unhandled REP Prefix %X",Fetchb()); - + 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 */ diff --git a/src/cpu/core_16/table_ea.h b/src/cpu/core_16/table_ea.h index d702fe1..9393a25 100644 --- a/src/cpu/core_16/table_ea.h +++ b/src/cpu/core_16/table_ea.h @@ -233,7 +233,7 @@ 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;return Sib(1)+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(); } @@ -242,7 +242,7 @@ 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;return Sib(2)+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(); } diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 18f2a31..854d383 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.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 @@ -40,12 +40,14 @@ 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); } 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); } @@ -57,12 +59,12 @@ void Interrupt(Bit8u num) { switch (num) { case 0x00: - LOG_WARN("Divide Error"); + LOG(LOG_CPU,"Divide Error"); break; case 0x06: break; case 0x07: - LOG_WARN("Co Processor Exception"); + LOG(LOG_FPU,"Co Processor Exception"); break; case 0x08: case 0x09: @@ -84,7 +86,7 @@ void Interrupt(Bit8u num) { break; case 0xcd: #if C_HEAVY_DEBUG - LOG_DEBUG("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"); @@ -94,7 +96,7 @@ void Interrupt(Bit8u num) { #endif break; case 0x05: - LOG_MSG("CPU:Out Of Bounds interrupt"); + LOG(LOG_CPU,"CPU:Out Of Bounds interrupt"); break; default: // LOG_WARN("Call to unsupported INT %02X call %02X",num,reg_ah); @@ -171,8 +173,8 @@ void CPU_Init(Section* sec) { SetCPU16bit(); - KEYBOARD_AddEvent(KBD_f11,CTRL_PRESSED,CPU_CycleDecrease); - KEYBOARD_AddEvent(KBD_f12,CTRL_PRESSED,CPU_CycleIncrease); + KEYBOARD_AddEvent(KBD_f11,KBD_MOD_CTRL,CPU_CycleDecrease); + KEYBOARD_AddEvent(KBD_f12,KBD_MOD_CTRL,CPU_CycleIncrease); CPU_Cycles=0; CPU_CycleMax=section->Get_int("cycles");; diff --git a/src/cpu/flags.cpp b/src/cpu/flags.cpp index 6e78c3e..33c3224 100644 --- a/src/cpu/flags.cpp +++ b/src/cpu/flags.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 @@ -134,7 +134,7 @@ bool get_CF(void) { case t_DIV: return false; /* Unkown */ default: - LOG_WARN("get_CF Unknown %d",flags.type); + LOG(LOG_ERROR|LOG_CPU,"get_CF Unknown %d",flags.type); } return 0; } @@ -229,7 +229,7 @@ again: case t_MUL: return false; /* Unkown */ default: - LOG_WARN("get_AF Unknown %d",flags.type); + LOG(LOG_ERROR|LOG_CPU,"get_AF Unknown %d",flags.type); } return 0; } @@ -314,7 +314,7 @@ again: case t_MUL: return false; /* Unkown */ default: - LOG_WARN("get_ZF Unknown %d",flags.type); + LOG(LOG_ERROR|LOG_CPU,"get_ZF Unknown %d",flags.type); } return false; } @@ -398,7 +398,7 @@ again: case t_MUL: return false; /* Unkown */ default: - LOG_WARN("get_SF Unkown %d",flags.type); + LOG(LOG_ERROR|LOG_CPU,"get_SF Unkown %d",flags.type); } return false; @@ -539,7 +539,7 @@ again: case t_DIV: return false; /* Unkown */ default: - LOG_WARN("get_OF Unkown %d",flags.type); + LOG(LOG_ERROR|LOG_CPU,"get_OF Unkown %d",flags.type); } return false; } diff --git a/src/cpu/core_16/instructions.h b/src/cpu/instructions.h similarity index 100% rename from src/cpu/core_16/instructions.h rename to src/cpu/instructions.h diff --git a/src/cpu/slow_16.cpp b/src/cpu/slow_16.cpp index 40146a3..5ee529e 100644 --- a/src/cpu/slow_16.cpp +++ b/src/cpu/slow_16.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 @@ -63,6 +63,7 @@ extern Bitu cycle_count; #endif +#include "instructions.h" #include "core_16/support.h" static Bitu CPU_Real_16_Slow_Decode_Trap(void); @@ -71,16 +72,16 @@ static Bitu CPU_Real_16_Slow_Decode(void) { while (CPU_Cycles>0) { #if C_DEBUG cycle_count++; -#endif #if C_HEAVY_DEBUG SAVEIP; if (DEBUG_HeavyIsBreakpoint()) return 1; +#endif #endif #include "core_16/main.h" if (prefix.count) { PrefixReset; //DEBUG_HeavyWriteLogInstruction(); - LOG_DEBUG("Prefix for non prefixed instruction"); + LOG(LOG_CPU,"Prefix for non prefixed instruction"); } CPU_Cycles--; } @@ -103,6 +104,7 @@ static Bitu CPU_Real_16_Slow_Decode_Trap(void) { return CBRET_NONE; } + void CPU_Real_16_Slow_Start(void) { cpudecoder=&CPU_Real_16_Slow_Decode; EAPrefixTable[0]=&GetEA_16_n; diff --git a/src/debug/Makefile.in b/src/debug/Makefile.in index 4280ba0..53f85b5 100644 --- a/src/debug/Makefile.in +++ b/src/debug/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -209,7 +212,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -254,7 +257,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index 3c3d1bd..5a849e6 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.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 @@ -38,12 +38,18 @@ #ifdef WIN32 void WIN32_Console(); +#else +#include +#include +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); +void SaveMemory(Bit16u seg, Bit16u ofs1, Bit32s num); class DEBUG; DEBUG* pDebugcom = 0; @@ -84,7 +90,37 @@ struct SCodeViewData { } codeViewData; -static Bit16u dataSeg,dataOfs; +static Bit16u dataSeg,dataOfs; +static bool showExtend = true; + +/********************/ +/* DebugVar stuff */ +/********************/ + +class CDebugVar +{ +public: + CDebugVar(char* _name, PhysPt _adr) { adr=_adr; (strlen(name)<15)?strcpy(name,_name):strncpy(name,_name,15); name[15]=0; }; + + char* GetName(void) { return name; }; + PhysPt GetAdr (void) { return adr; }; + +private: + PhysPt adr; + char name[16]; + +public: + static void InsertVariable (char* name, PhysPt adr); + static CDebugVar* FindVar (PhysPt adr); + static void DeleteAll (); + static bool SaveVars (char* name); + static bool LoadVars (char* name); + + static std::list varList; +}; + +std::list CDebugVar::varList; + /********************/ /* Breakpoint stuff */ @@ -256,9 +292,8 @@ bool CBreakpoint::CheckBreakpoint(PhysPt adr) Bit8u value = mem_readb(bp->GetLocation()); if (bp->GetValue() != value) { // Yup, memory value changed - char buffer[200]; - sprintf(buffer,"DEBUG: Memory breakpoint: %04X:%04X - %02X -> %02X",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value); - LOG_DEBUG(buffer); + + DEBUG_ShowMsg(0,"DEBUG: Memory breakpoint: %04X:%04X - %02X -> %02X",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value); bp->SetValue(value); return true; }; @@ -547,8 +582,17 @@ static void DrawCode(void) mvwprintw(dbg.win_code,i,0,"%04X:%04X ",codeViewData.useCS,disEIP); for (c=0;c=size*2;c--) waddch(dbg.win_code,' '); + + char* res = 0; + if (showExtend) res = AnalyzeInstruction(dline); waddstr(dbg.win_code,dline); - for (c=30-strlen(dline);c>0;c--) waddch(dbg.win_code,' '); + 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,' '); + } else { + for (c=0;c<20;c++) waddch(dbg.win_code,' '); + } start+=size; disEIP+=size; @@ -673,14 +717,73 @@ bool ChangeRegister(char* str) bool ParseCommand(char* str) { char* found = str; - while (*found) *found++=toupper(*found); + for(char* idx = found;*idx != 0; idx++) + *idx = toupper(*idx); + + found = trim(found); + + found = strstr(str,"MEMDUMP "); + if (found) { // Insert variable + found+=8; + Bit16u seg = GetHexValue(found,found); found++; + Bit32u ofs = GetHexValue(found,found); found++; + Bit32u num = GetHexValue(found,found); found++; + SaveMemory(seg,ofs,num); + return true; + }; + + found = strstr(str,"IV "); + if (found) { // Insert variable + found+=3; + Bit16u seg = GetHexValue(found,found); found++; + Bit32u ofs = GetHexValue(found,found); found++; + char name[16]; + for (int i=0; i<16; i++) { + if ((found[i]!=' ') && (found[i]!=0)) name[i] = found[i]; + else { name[i] = 0; break; }; + }; + name[15] = 0; + + DEBUG_ShowMsg(0,"DEBUG: Created debug var %s at %04X:%04X",name,seg,ofs); + CDebugVar::InsertVariable(name,PhysMake(seg,ofs)); + return true; + } + + found = strstr(str,"SV "); + if (found) { // Save variables + found+=3; + char name[13]; + for (int i=0; i<12; i++) { + if ((found[i]!=' ') && (found[i]!=0)) name[i] = found[i]; + 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); + return true; + } + + found = strstr(str,"LV "); + if (found) { // Save variables + found+=3; + char name[13]; + for (int i=0; i<12; i++) { + if ((found[i]!=' ') && (found[i]!=0)) name[i] = found[i]; + 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); + return true; + } + found = strstr(str,"BP "); if (found) { // Add new breakpoint found+=3; Bit16u seg = GetHexValue(found,found);found++; // skip ":" Bit32u ofs = GetHexValue(found,found); CBreakpoint::AddBreakpoint(seg,ofs,false); - LOG_DEBUG("DEBUG: Set breakpoint at %04X:%04X",seg,ofs); + DEBUG_ShowMsg(0,"DEBUG: Set breakpoint at %04X:%04X",seg,ofs); return true; } #if C_HEAVY_DEBUG @@ -690,7 +793,7 @@ bool ParseCommand(char* str) Bit16u seg = GetHexValue(found,found);found++; // skip ":" Bit32u ofs = GetHexValue(found,found); CBreakpoint::AddMemBreakpoint(seg,ofs); - LOG_DEBUG("DEBUG: Set memory breakpoint at %04X:%04X",seg,ofs); + DEBUG_ShowMsg(0,"DEBUG: Set memory breakpoint at %04X:%04X",seg,ofs); return true; } #endif @@ -701,10 +804,10 @@ bool ParseCommand(char* str) Bit8u valAH = GetHexValue(found,found); if ((valAH==0x00) && (*found=='*')) { CBreakpoint::AddIntBreakpoint(intNr,BPINT_ALL,false); - LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X",intNr); + DEBUG_ShowMsg(0,"DEBUG: Set interrupt breakpoint at INT %02X",intNr); } else { CBreakpoint::AddIntBreakpoint(intNr,valAH,false); - LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH); + DEBUG_ShowMsg(0,"DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH); } return true; } @@ -723,7 +826,7 @@ bool ParseCommand(char* str) Bit8u bpNr = GetHexValue(found,found); if ((bpNr==0x00) && (*found=='*')) { // Delete all CBreakpoint::DeleteAll(); - LOG_DEBUG("DEBUG: Breakpoints deleted."); + DEBUG_ShowMsg(0,"DEBUG: Breakpoints deleted."); } else { // delete single breakpoint CBreakpoint::DeleteByIndex(bpNr); @@ -731,36 +834,36 @@ bool ParseCommand(char* str) return true; } found = strstr(str,"C "); - if (found) { // Set code overview + if (found==(char*)str) { // Set code overview found++; Bit16u codeSeg = GetHexValue(found,found); found++; Bit32u codeOfs = GetHexValue(found,found); - LOG_DEBUG("DEBUG: Set code overview to %04X:%04X",codeSeg,codeOfs); + DEBUG_ShowMsg(0,"DEBUG: Set code overview to %04X:%04X",codeSeg,codeOfs); codeViewData.useCS = codeSeg; codeViewData.useEIP = codeOfs; return true; } found = strstr(str,"D "); - if (found) { // Set data overview + if (found==(char*)str) { // Set data overview found++; dataSeg = GetHexValue(found,found); found++; dataOfs = GetHexValue(found,found); - LOG_DEBUG("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs); + DEBUG_ShowMsg(0,"DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs); return true; } found = strstr(str,"LOG "); if (found) { // Create Cpu log file found+=4; - LOG_DEBUG("DEBUG: Starting log"); + DEBUG_ShowMsg(0,"DEBUG: Starting log"); DEBUG_Log_Loop(GetHexValue(found,found)); - LOG_DEBUG("DEBUG: Logfile LOGCPU.TXT created."); + DEBUG_ShowMsg(0,"DEBUG: Logfile LOGCPU.TXT created."); return true; } found = strstr(str,"SR "); if (found) { // Set register value found+=2; - if (ChangeRegister(found)) LOG_DEBUG("DEBUG: Set Register success."); - else LOG_DEBUG("DEBUG: Set Register failure."); + if (ChangeRegister(found)) DEBUG_ShowMsg(0,"DEBUG: Set Register success."); + else DEBUG_ShowMsg(0,"DEBUG: Set Register failure."); return true; } found = strstr(str,"SM "); @@ -777,14 +880,14 @@ bool ParseCommand(char* str) count++; } }; - LOG_DEBUG("DEBUG: Memory changed."); + DEBUG_ShowMsg(0,"DEBUG: Memory changed."); return true; } found = strstr(str,"INTT "); if (found) { // Create Cpu log file found+=4; Bit8u intNr = GetHexValue(found,found); - LOG_DEBUG("DEBUG: Tracing INT %02X",intNr); + DEBUG_ShowMsg(0,"DEBUG: Tracing INT %02X",intNr); Interrupt(intNr); SetCodeWinStart(); return true; @@ -793,7 +896,7 @@ bool ParseCommand(char* str) if (found) { // Create Cpu log file found+=4; Bit8u intNr = GetHexValue(found,found); - LOG_DEBUG("DEBUG: Starting INT %02X",intNr); + DEBUG_ShowMsg(0,"DEBUG: Starting INT %02X",intNr); CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip, true); CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip-1,true); debugging=false; @@ -801,13 +904,14 @@ bool ParseCommand(char* str) DOSBOX_SetNormalLoop(); Interrupt(intNr); return true; - } + } + #if C_HEAVY_DEBUG found = strstr(str,"HEAVYLOG"); if (found) { // Create Cpu log file logHeavy = !logHeavy; - if (logHeavy) LOG_DEBUG("DEBUG: Heavy cpu logging on."); - else LOG_DEBUG("DEBUG: Heavy cpu logging off."); + if (logHeavy) DEBUG_ShowMsg(0,"DEBUG: Heavy cpu logging on."); + else DEBUG_ShowMsg(0,"DEBUG: Heavy cpu logging off."); return true; } #endif @@ -821,6 +925,7 @@ bool ParseCommand(char* str) wprintw(dbg.win_out,"Return - Enable command line input\n"); wprintw(dbg.win_out,"D/E/S/X/B - Set data view to DS:SI/ES:DI/SS:SP/DS:DX/ES:BX\n"); wprintw(dbg.win_out,"R/F - Scroll data view\n"); + wprintw(dbg.win_out,"V - Toggle additional info\n"); wprintw(dbg.win_out,"Debugger commands (enter all values in hex or as register):\n"); wprintw(dbg.win_out,"--------------------------------------------------------------------------\n"); wprintw(dbg.win_out,"BP [segment]:[offset] - Set breakpoint\n"); @@ -839,13 +944,93 @@ bool ParseCommand(char* str) #endif wprintw(dbg.win_out,"SR [reg] [value] - Set register value\n"); wprintw(dbg.win_out,"SM [seg]:[off] [val] [.]..- Set memory with following values\n"); + + wprintw(dbg.win_out,"IV [seg]:[off] [name] - Create var name for memory address\n"); + wprintw(dbg.win_out,"SV [filename] - Save var list in file\n"); + 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,"H - Help\n"); + wrefresh(dbg.win_out); return TRUE; } return false; }; +char* AnalyzeInstruction(char* inst) +{ + static char result[256]; + + char instu[256]; + char prefix[3]; + Bit16u seg; + + strcpy(instu,inst); + upcase(instu); + + result[0] = 0; + char* pos = strchr(instu,'['); + if (pos) { + // Segment prefix ? + if (*(pos-1)==':') { + char* segpos = pos-3; + prefix[0] = tolower(*segpos); + prefix[1] = tolower(*(segpos+1)); + prefix[2] = 0; + seg = GetHexValue(segpos,segpos); + } else { + if (strstr(pos,"SP") || strstr(pos,"BP")) { + seg = SegValue(ss); + strcpy(prefix,"ss"); + } else { + seg = SegValue(ds); + strcpy(prefix,"ds"); + }; + }; + + pos++; + Bit32u adr = GetHexValue(pos,pos); + while (*pos!=']') { + if (*pos=='+') { + pos++; + adr += GetHexValue(pos,pos); + } else if (*pos=='-') { + pos++; + adr -= GetHexValue(pos,pos); + } else + pos++; + }; + switch (DasmLastOperandSize()) { + case 8 : { Bit8u val = mem_readb( PhysMake (seg,adr) ); + sprintf(result,"%s:[%04X]=%02X",prefix,adr,val); + } break; + case 16: { Bit16u val = mem_readw( PhysMake (seg,adr) ); + sprintf(result,"%s:[%04X]=%04X",prefix,adr,val); + } break; + case 32: { Bit32u val = mem_readd( PhysMake (seg,adr) ); + sprintf(result,"%s:[%04X]=%08X",prefix,adr,val); + } break; + } + // Variable found ? + CDebugVar* var = CDebugVar::FindVar(PhysMake(seg,adr)); + if (var) { + // Replace occurance + char* pos1 = strchr(inst,'['); + char* pos2 = strchr(inst,']'); + if (pos1 && pos2) { + char temp[256]; + strcpy(temp,pos2); // save end + pos1++; *pos1 = 0; // cut after '[' + strcat(inst,var->GetName()); // add var name + strcat(inst,temp); // add end + }; + }; + }; + return result; +}; + + Bit32u DEBUG_CheckKeys(void) { if (codeViewData.inputMode) { @@ -855,6 +1040,7 @@ Bit32u DEBUG_CheckKeys(void) { case 0x0A: codeViewData.inputMode = FALSE; ParseCommand(codeViewData.inputStr); break; + case 0x107: //backspace (linux) case 0x08: // delete if (strlen(codeViewData.inputStr)>0) codeViewData.inputStr[strlen(codeViewData.inputStr)-1] = 0; break; @@ -920,7 +1106,9 @@ Bit32u DEBUG_CheckKeys(void) { ParseCommand(codeViewData.inputStr); break; case 'T' : DEBUG_RaiseTimerIrq(); - LOG_DEBUG("Debug: Timer Int started."); + DEBUG_ShowMsg(0,"Debug: Timer Int started."); + break; + case 'V' : showExtend = !showExtend; break; case 0x0A : // Return : input @@ -1011,13 +1199,21 @@ static void DEBUG_RaiseTimerIrq(void) { 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); char dline[200];Bitu size; size = DasmI386(dline, start, reg_eip, false); Bitu len = strlen(dline); + char* res = empty; + if (showExtend) { + res = AnalyzeInstruction(dline); + 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 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,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),get_CF(),get_ZF(),get_SF(),get_OF(),get_AF(),get_PF()); }; static bool DEBUG_Log_Loop(int count) { @@ -1126,9 +1322,10 @@ void DEBUG_SetupConsole(void) { #ifdef WIN32 WIN32_Console(); - #else - printf("\e[8;50;80t"); //resize terminal - fflush(NULL); + #else + tcgetattr(0,&consolesettings); + printf("\e[8;50;80t"); //resize terminal + fflush(NULL); #endif memset((void *)&dbg,0,sizeof(dbg)); debugging=false; @@ -1141,6 +1338,13 @@ void DEBUG_SetupConsole(void) static void DEBUG_ShutDown(Section * sec) { CBreakpoint::DeleteAll(); + CDebugVar::DeleteAll(); + #ifndef WIN32 + curs_set(old_cursor_state); + tcsetattr(0, TCSANOW,&consolesettings); + printf("\e[0m\e[2J"); + fflush(NULL); + #endif }; void DEBUG_Init(Section* sec) { @@ -1158,18 +1362,120 @@ void DEBUG_Init(Section* sec) { sec->AddDestroyFunction(&DEBUG_ShutDown); } +// DEBUGGING VAR STUFF + +void CDebugVar::InsertVariable(char* name, PhysPt adr) +{ + varList.push_back(new CDebugVar(name,adr)); +}; + +void CDebugVar::DeleteAll(void) +{ + std::list::iterator i; + CDebugVar* bp; + for(i=varList.begin(); i != varList.end(); i++) { + bp = static_cast(*i); + delete bp; + }; + (varList.clear)(); +}; + +CDebugVar* CDebugVar::FindVar(PhysPt pt) +{ + std::list::iterator i; + CDebugVar* bp; + for(i=varList.begin(); i != varList.end(); i++) { + bp = static_cast(*i); + if (bp->GetAdr()==pt) return bp; + }; + return 0; +}; + +bool CDebugVar::SaveVars(char* name) +{ + FILE* f = fopen(name,"wb+"); + if (!f) return false; + + // write number of vars + Bit16u num = varList.size(); + fwrite(&num,1,sizeof(num),f); + + std::list::iterator i; + CDebugVar* bp; + for(i=varList.begin(); i != varList.end(); i++) { + bp = static_cast(*i); + // name + fwrite(bp->GetName(),1,16,f); + // adr + PhysPt adr = bp->GetAdr(); + fwrite(&adr,1,sizeof(adr),f); + }; + fclose(f); + return true; +}; + +bool CDebugVar::LoadVars(char* name) +{ + FILE* f = fopen(name,"rb"); + if (!f) return false; + + // read number of vars + Bit16u num; + fread(&num,1,sizeof(num),f); + + for (Bit16u i=0; i0) { + + sprintf(buffer,"%04X:%04X ",seg,ofs1); + for (Bit16u x=0; x<16; x++) { + sprintf (temp,"%02X ",mem_readb(PhysMake(seg,ofs1+x))); + strcat (buffer,temp); + }; + ofs1+=16; + num-=16; + + fprintf(f,"%s\n",buffer); + }; + fclose(f); + DEBUG_ShowMsg(0,"DEBUG: Memory dump success."); +}; + // HEAVY DEBUGGING STUFF #if C_HEAVY_DEBUG -const Bit16u LOGCPUMAX = 200; +const Bit32u LOGCPUMAX = 200; static Bit16u logCpuCS [LOGCPUMAX]; static Bit32u logCpuEIP[LOGCPUMAX]; static Bit32u logCount = 0; typedef struct SLogInst { - char buffer[256]; + char buffer[512]; } TLogInst; TLogInst logInst[LOGCPUMAX]; @@ -1177,22 +1483,26 @@ TLogInst logInst[LOGCPUMAX]; void DEBUG_HeavyLogInstruction(void) { LogInstruction(SegValue(cs),reg_eip,logInst[logCount++].buffer); - if (logCount>=LOGCPUMAX) logCount = 0; + if (logCount>=LOGCPUMAX) { + logCount = 0; + }; }; void DEBUG_HeavyWriteLogInstruction(void) { if (!logHeavy) return; + + logHeavy = false; - LOG_DEBUG("DEBUG: Creating cpu log LOGCPU_INT_CD.TXT"); + DEBUG_ShowMsg(0,"DEBUG: Creating cpu log LOGCPU_INT_CD.TXT"); FILE* f = fopen("LOGCPU_INT_CD.TXT","wt"); if (!f) { - LOG_DEBUG("DEBUG: Failed."); + DEBUG_ShowMsg(0,"DEBUG: Failed."); return; } - Bit16u startLog = logCount; + Bit32u startLog = logCount; do { // Write Intructions fprintf(f,"%s",logInst[startLog++].buffer); @@ -1201,7 +1511,7 @@ void DEBUG_HeavyWriteLogInstruction(void) fclose(f); - LOG_DEBUG("DEBUG: Done."); + DEBUG_ShowMsg(0,"DEBUG: Done."); }; bool DEBUG_HeavyIsBreakpoint(void) @@ -1213,8 +1523,9 @@ bool DEBUG_HeavyIsBreakpoint(void) skipFirstInstruction = false; return false; } - + PhysPt where = SegPhys(cs)+reg_eip; + if (CBreakpoint::CheckBreakpoint(where)) { exitLoop = true; DEBUG_Enable(); @@ -1227,3 +1538,4 @@ bool DEBUG_HeavyIsBreakpoint(void) #endif // DEBUG + diff --git a/src/debug/debug_disasm.cpp b/src/debug/debug_disasm.cpp index 67559cd..897a4c6 100644 --- a/src/debug/debug_disasm.cpp +++ b/src/debug/debug_disasm.cpp @@ -1111,5 +1111,11 @@ Bitu DasmI386(char* buffer, PhysPt pc, Bitu cur_ip, bool bit32) return getbyte_mac-pc; } +int DasmLastOperandSize() +{ + return opsize; +}; + + +#endif -#endif \ No newline at end of file diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index 64eb95f..e5b06b1 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.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,24 +20,43 @@ #include "dosbox.h" #if C_DEBUG - +#include "setup.h" #include #include #include #include #include +#include "support.h" #include "regs.h" #include "debug.h" #include "debug_inc.h" -void DEBUG_ShowMsg(char * msg) { - char buf[1024]; - strcpy(buf,msg); +struct _LogGroup { + char * front; + bool enabled; +}; - waddstr(dbg.win_out,buf); - wprintw(dbg.win_out," %d\n",cycle_count); +namespace { + _LogGroup loggrp[LOG_MAX]={"",true,0}; + + 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); + va_list msg; + va_start(msg,format); + vsprintf(&buf[strlen(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); } @@ -113,24 +132,87 @@ static void MakePairs(void) { init_pair(PAIR_BLACK_GREY, COLOR_BLACK /*| FOREGROUND_INTENSITY */, COLOR_WHITE); init_pair(PAIR_GREY_RED, COLOR_WHITE/*| FOREGROUND_INTENSITY */, COLOR_RED); } +static void LOG_Destroy(Section* sec) { + + if(debuglog) fclose(debuglog); +} + +static void LOG_Init(Section * sec) { + Section_prop * sect=static_cast(sec); + const char * blah=sect->Get_string("logfile"); + if(blah && blah[0] &&(debuglog = fopen(blah,"wt+"))){ + }else{ + debuglog=0; + } + sect->AddDestroyFunction(LOG_Destroy); + char buf[1024]; + for (Bitu i=1;iGet_bool(buf); + } +} + + +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_FPU].front="FPU:"; + loggrp[LOG_CPU].front="CPU:"; + + 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_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:"; + + /* Register the log section */ + Section_prop * sect=control->AddSection_prop("log",LOG_Init); + sect->Add_string("logfile",""); + char buf[1024]; + for (Bitu i=1;iAdd_bool(buf,true); + } +} + + void DBGUI_StartUp(void) { /* Start the main window */ dbg.win_main=initscr(); - cbreak(); /* take input chars one at a time, no wait for \n */ - noecho(); /* don't echo input */ + cbreak(); /* take input chars one at a time, no wait for \n */ + noecho(); /* don't echo input */ nodelay(dbg.win_main,true); keypad(dbg.win_main,true); - #ifndef WIN32 - resizeterm(50,80); - touchwin(dbg.win_main); - #endif + #ifndef WIN32 + resizeterm(50,80); + touchwin(dbg.win_main); + old_cursor_state = curs_set(0); + #endif + start_color(); cycle_count=0; MakePairs(); MakeSubWindows(); - } #endif diff --git a/src/debug/debug_inc.h b/src/debug/debug_inc.h index e77806d..880f7ea 100644 --- a/src/debug/debug_inc.h +++ b/src/debug/debug_inc.h @@ -37,6 +37,7 @@ struct DBGBlock { WINDOW * win_out; /* Text Output Window */ Bit32u active_win; /* Current active window */ Bit32u input_y; + Bit32u global_mask; /* Current msgmask */ }; @@ -53,3 +54,4 @@ 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 diff --git a/src/dos/Makefile.am b/src/dos/Makefile.am index 1a41482..821a71b 100644 --- a/src/dos/Makefile.am +++ b/src/dos/Makefile.am @@ -1,7 +1,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libdos.a +EXTRA_DIST = Ntddcdrm.h Ntddscsi.h Ntddstor.h scsidefs.h wnaspi32.h libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \ dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \ - drives.cpp drives.h drive_virtual.cpp drive_local.cpp \ - dev_con.h + drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp \ + dev_con.h dos_mscdex.cpp \ + cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp diff --git a/src/dos/Makefile.in b/src/dos/Makefile.in index a1e3579..cd07e0c 100644 --- a/src/dos/Makefile.in +++ b/src/dos/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -84,10 +87,12 @@ install_sh = @install_sh@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libdos.a +EXTRA_DIST = Ntddcdrm.h Ntddscsi.h Ntddstor.h scsidefs.h wnaspi32.h libdos_a_SOURCES = dos.cpp dos_devices.cpp dos_execute.cpp dos_files.cpp dos_ioctl.cpp dos_memory.cpp \ dos_misc.cpp dos_classes.cpp dos_programs.cpp dos_tables.cpp \ - drives.cpp drives.h drive_virtual.cpp drive_local.cpp \ - dev_con.h + drives.cpp drives.h drive_virtual.cpp drive_local.cpp drive_cache.cpp \ + dev_con.h dos_mscdex.cpp \ + cdrom.h cdrom.cpp cdrom_ioctl_win32.cpp cdrom_aspi_win32.cpp subdir = src/dos mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -101,7 +106,9 @@ am_libdos_a_OBJECTS = dos.$(OBJEXT) dos_devices.$(OBJEXT) \ dos_execute.$(OBJEXT) dos_files.$(OBJEXT) dos_ioctl.$(OBJEXT) \ dos_memory.$(OBJEXT) dos_misc.$(OBJEXT) dos_classes.$(OBJEXT) \ dos_programs.$(OBJEXT) dos_tables.$(OBJEXT) drives.$(OBJEXT) \ - drive_virtual.$(OBJEXT) drive_local.$(OBJEXT) + drive_virtual.$(OBJEXT) drive_local.$(OBJEXT) \ + drive_cache.$(OBJEXT) dos_mscdex.$(OBJEXT) cdrom.$(OBJEXT) \ + cdrom_ioctl_win32.$(OBJEXT) cdrom_aspi_win32.$(OBJEXT) libdos_a_OBJECTS = $(am_libdos_a_OBJECTS) DEFS = @DEFS@ @@ -111,12 +118,17 @@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dos.Po ./$(DEPDIR)/dos_classes.Po \ +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/cdrom.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_aspi_win32.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/cdrom_ioctl_win32.Po ./$(DEPDIR)/dos.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dos_classes.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_devices.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_execute.Po ./$(DEPDIR)/dos_files.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_ioctl.Po ./$(DEPDIR)/dos_memory.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/dos_misc.Po ./$(DEPDIR)/dos_programs.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dos_misc.Po ./$(DEPDIR)/dos_mscdex.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dos_programs.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/dos_tables.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/drive_cache.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/drive_local.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/drive_virtual.Po ./$(DEPDIR)/drives.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ @@ -159,6 +171,9 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_aspi_win32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cdrom_ioctl_win32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_classes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_devices.Po@am__quote@ @@ -167,8 +182,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_ioctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_memory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_mscdex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_programs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dos_tables.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_cache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_local.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_virtual.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drives.Po@am__quote@ @@ -231,7 +248,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -276,7 +293,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/dos/Ntddcdrm.h b/src/dos/Ntddcdrm.h new file mode 100644 index 0000000..6590a4e --- /dev/null +++ b/src/dos/Ntddcdrm.h @@ -0,0 +1,548 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + ntddcdrm.h + +Abstract: + + This module contains structures and definitions + associated with CDROM IOCTls. + +Author: + + Mike Glass + +Revision History: + +--*/ + +// begin_winioctl + +#ifndef _NTDDCDRM_ +#define _NTDDCDRM_ + +#if _MSC_VER >= 1200 +#pragma warning(push) +#endif + +#if _MSC_VER > 1000 +#pragma once +#endif + +// +// remove some level 4 warnings for this header file: +#pragma warning(disable:4200) // array[0] +#pragma warning(disable:4201) // nameless struct/unions +#pragma warning(disable:4214) // bit fields other than int + +#ifdef __cplusplus +extern "C" { +#endif + +// +// NtDeviceIoControlFile IoControlCode values for this device. +// +// Warning: Remember that the low two bits of the code specify how the +// buffers are passed to the driver! +// + +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM + +#define IOCTL_CDROM_UNLOAD_DRIVER CTL_CODE(IOCTL_CDROM_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS) + +// +// CDROM Audio Device Control Functions +// + +#define IOCTL_CDROM_READ_TOC CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_SEEK_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_STOP_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_PAUSE_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RESUME_AUDIO CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_PLAY_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_SET_VOLUME CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_READ_Q_CHANNEL CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_CONTROL CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_LAST_SESSION CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#define IOCTL_CDROM_DISK_TYPE CTL_CODE(IOCTL_CDROM_BASE, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_CDROM_BASE, 0x0014, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_CDROM_READ_TOC_EX CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_GET_CONFIGURATION CTL_CODE(IOCTL_CDROM_BASE, 0x0016, METHOD_BUFFERED, FILE_READ_ACCESS) + +// end_winioctl + +// +// The following device control codes are common for all class drivers. The +// functions codes defined here must match all of the other class drivers. +// +// Warning: these codes will be replaced in the future with the IOCTL_STORAGE +// codes included below +// + +#define IOCTL_CDROM_CHECK_VERIFY CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_MEDIA_REMOVAL CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_EJECT_MEDIA CTL_CODE(IOCTL_CDROM_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_LOAD_MEDIA CTL_CODE(IOCTL_CDROM_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RESERVE CTL_CODE(IOCTL_CDROM_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_RELEASE CTL_CODE(IOCTL_CDROM_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_FIND_NEW_DEVICES CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) + +// +// The following file contains the IOCTL_STORAGE class ioctl definitions +// + +#include "ntddstor.h" + +// begin_winioctl + +// +// The following device control code is for the SIMBAD simulated bad +// sector facility. See SIMBAD.H in this directory for related structures. +// + +#define IOCTL_CDROM_SIMBAD CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS) + +// +// Maximum CD Rom size +// + +#define MAXIMUM_NUMBER_TRACKS 100 +#define MAXIMUM_CDROM_SIZE 804 +#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2 // two bytes min transferred + +// +// READ_TOC_EX structure +// +typedef struct _CDROM_READ_TOC_EX { + UCHAR Format : 4; + UCHAR Reserved1 : 3; // future expansion + UCHAR Msf : 1; + UCHAR SessionTrack; + UCHAR Reserved2; // future expansion + UCHAR Reserved3; // future expansion +} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX; + +#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00 +#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01 +#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02 +#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03 +#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04 +#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05 + +// +// CD ROM Table OF Contents (TOC) +// Format 0 - Get table of contents +// + +typedef struct _TRACK_DATA { + UCHAR Reserved; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR TrackNumber; + UCHAR Reserved1; + UCHAR Address[4]; +} TRACK_DATA, *PTRACK_DATA; + +typedef struct _CDROM_TOC { + + // + // Header + // + + UCHAR Length[2]; // add two bytes for this field + UCHAR FirstTrack; + UCHAR LastTrack; + + // + // Track data + // + + TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS]; +} CDROM_TOC, *PCDROM_TOC; + +#define CDROM_TOC_SIZE sizeof(CDROM_TOC) + +// +// CD ROM Table OF Contents +// Format 1 - Session Information +// + +typedef struct _CDROM_TOC_SESSION_DATA { + + // + // Header + // + + UCHAR Length[2]; // add two bytes for this field + UCHAR FirstCompleteSession; + UCHAR LastCompleteSession; + + // + // One track, representing the first track + // of the last finished session + // + + TRACK_DATA TrackData[1]; + +} CDROM_TOC_SESSION_DATA, *PCDROM_TOC_SESSION_DATA; + + +// +// CD ROM Table OF Contents +// Format 2 - Full TOC +// + +typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK { + UCHAR SessionNumber; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR Reserved1; + UCHAR Point; + UCHAR MsfExtra[3]; + UCHAR Zero; + UCHAR Msf[3]; +} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK; + +typedef struct _CDROM_TOC_FULL_TOC_DATA { + + // + // Header + // + + UCHAR Length[2]; // add two bytes for this field + UCHAR FirstCompleteSession; + UCHAR LastCompleteSession; + + // + // one to N descriptors included + // + + CDROM_TOC_FULL_TOC_DATA_BLOCK Descriptors[0]; + +} CDROM_TOC_FULL_TOC_DATA, *PCDROM_TOC_FULL_TOC_DATA; + +// +// CD ROM Table OF Contents +// Format 3 - Program Memory Area +// +typedef struct _CDROM_TOC_PMA_DATA { + + // + // Header + // + + UCHAR Length[2]; // add two bytes for this field + UCHAR Reserved1; + UCHAR Reserved2; + + // + // one to N descriptors included + // + + CDROM_TOC_FULL_TOC_DATA_BLOCK Descriptors[0]; + +} CDROM_TOC_PMA_DATA, *PCDROM_TOC_PMA_DATA; + +// +// CD ROM Table OF Contents +// Format 4 - Absolute Time In Pregroove +// + +typedef struct _CDROM_TOC_ATIP_DATA_BLOCK { + + UCHAR CdrwReferenceSpeed : 3; + UCHAR Reserved3 : 1; + UCHAR WritePower : 3; + UCHAR True1 : 1; + UCHAR Reserved4 : 6; + UCHAR UnrestrictedUse : 1; + UCHAR Reserved5 : 1; + UCHAR A3Valid : 1; + UCHAR A2Valid : 1; + UCHAR A1Valid : 1; + UCHAR DiscSubType : 3; + UCHAR IsCdrw : 1; + UCHAR True2 : 1; + UCHAR Reserved7; + + UCHAR LeadInMsf[3]; + UCHAR Reserved8; + + UCHAR LeadOutMsf[3]; + UCHAR Reserved9; + + UCHAR A1Values[3]; + UCHAR Reserved10; + + UCHAR A2Values[3]; + UCHAR Reserved11; + + UCHAR A3Values[3]; + UCHAR Reserved12; + +} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK; + +typedef struct _CDROM_TOC_ATIP_DATA { + + // + // Header + // + + UCHAR Length[2]; // add two bytes for this field + UCHAR Reserved1; + UCHAR Reserved2; + + // + // zero? to N descriptors included. + // + + CDROM_TOC_ATIP_DATA_BLOCK Descriptors[0]; + +} CDROM_TOC_ATIP_DATA, *PCDROM_TOC_ATIP_DATA; + +// +// CD ROM Table OF Contents +// Format 5 - CD Text Info +// +typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK { + UCHAR PackType; + UCHAR TrackNumber : 7; + UCHAR ExtensionFlag : 1; // should be zero! + UCHAR SequenceNumber; + UCHAR CharacterPosition : 4; + UCHAR BlockNumber : 3; + UCHAR Unicode : 1; + union { + UCHAR Text[12]; + WCHAR WText[6]; + }; + UCHAR CRC[2]; +} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK; + +typedef struct _CDROM_TOC_CD_TEXT_DATA { + + // + // Header + // + + UCHAR Length[2]; // add two bytes for this field + UCHAR Reserved1; + UCHAR Reserved2; + + // + // the text info comes in discrete blocks of + // a heavily-overloaded structure + // + + CDROM_TOC_CD_TEXT_DATA_BLOCK Descriptors[0]; + +} CDROM_TOC_CD_TEXT_DATA, *PCDROM_TOC_CD_TEXT_DATA; + +// +// These are the types used for PackType field in CDROM_TOC_CD_TEXT_DATA_BLOCK +// and also for requesting specific info from IOCTL_CDROM_READ_CD_TEXT +// +#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80 +#define CDROM_CD_TEXT_PACK_PERFORMER 0x81 +#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82 +#define CDROM_CD_TEXT_PACK_COMPOSER 0x83 +#define CDROM_CD_TEXT_PACK_ARRANGER 0x84 +#define CDROM_CD_TEXT_PACK_MESSAGES 0x85 +#define CDROM_CD_TEXT_PACK_DISC_ID 0x86 +#define CDROM_CD_TEXT_PACK_GENRE 0x87 +#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88 +#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89 +// 0x8a - 0x8d are reserved.... +#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e +#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f + +// +// Play audio starting at MSF and ending at MSF +// + +typedef struct _CDROM_PLAY_AUDIO_MSF { + UCHAR StartingM; + UCHAR StartingS; + UCHAR StartingF; + UCHAR EndingM; + UCHAR EndingS; + UCHAR EndingF; +} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF; + +// +// Seek to MSF +// + +typedef struct _CDROM_SEEK_AUDIO_MSF { + UCHAR M; + UCHAR S; + UCHAR F; +} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; + + +// +// Flags for the disk type +// + +typedef struct _CDROM_DISK_DATA { + + ULONG DiskData; + +} CDROM_DISK_DATA, *PCDROM_DISK_DATA; + +#define CDROM_DISK_AUDIO_TRACK (0x00000001) +#define CDROM_DISK_DATA_TRACK (0x00000002) + +// +// CD ROM Data Mode Codes, used with IOCTL_CDROM_READ_Q_CHANNEL +// + +#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 +#define IOCTL_CDROM_CURRENT_POSITION 0x01 +#define IOCTL_CDROM_MEDIA_CATALOG 0x02 +#define IOCTL_CDROM_TRACK_ISRC 0x03 + +typedef struct _CDROM_SUB_Q_DATA_FORMAT { + UCHAR Format; + UCHAR Track; +} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; + + +// +// CD ROM Sub-Q Channel Data Format +// + +typedef struct _SUB_Q_HEADER { + UCHAR Reserved; + UCHAR AudioStatus; + UCHAR DataLength[2]; +} SUB_Q_HEADER, *PSUB_Q_HEADER; + +typedef struct _SUB_Q_CURRENT_POSITION { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Control : 4; + UCHAR ADR : 4; + UCHAR TrackNumber; + UCHAR IndexNumber; + UCHAR AbsoluteAddress[4]; + UCHAR TrackRelativeAddress[4]; +} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; + +typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved[3]; + UCHAR Reserved1 : 7; + UCHAR Mcval : 1; + UCHAR MediaCatalog[15]; +} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; + +typedef struct _SUB_Q_TRACK_ISRC { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved0; + UCHAR Track; + UCHAR Reserved1; + UCHAR Reserved2 : 7; + UCHAR Tcval : 1; + UCHAR TrackIsrc[15]; +} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; + +typedef union _SUB_Q_CHANNEL_DATA { + SUB_Q_CURRENT_POSITION CurrentPosition; + SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; + SUB_Q_TRACK_ISRC TrackIsrc; +} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; + +// +// Audio Status Codes +// + +#define AUDIO_STATUS_NOT_SUPPORTED 0x00 +#define AUDIO_STATUS_IN_PROGRESS 0x11 +#define AUDIO_STATUS_PAUSED 0x12 +#define AUDIO_STATUS_PLAY_COMPLETE 0x13 +#define AUDIO_STATUS_PLAY_ERROR 0x14 +#define AUDIO_STATUS_NO_STATUS 0x15 + +// +// ADR Sub-channel Q Field +// + +#define ADR_NO_MODE_INFORMATION 0x0 +#define ADR_ENCODES_CURRENT_POSITION 0x1 +#define ADR_ENCODES_MEDIA_CATALOG 0x2 +#define ADR_ENCODES_ISRC 0x3 + +// +// Sub-channel Q Control Bits +// + +#define AUDIO_WITH_PREEMPHASIS 0x1 +#define DIGITAL_COPY_PERMITTED 0x2 +#define AUDIO_DATA_TRACK 0x4 +#define TWO_FOUR_CHANNEL_AUDIO 0x8 + +// +// Get Audio control parameters +// + +typedef struct _CDROM_AUDIO_CONTROL { + UCHAR LbaFormat; + USHORT LogicalBlocksPerSecond; +} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL; + +// +// Volume control - Volume takes a value between 1 and 0xFF. +// SCSI-II CDROM audio suppports up to 4 audio ports with +// Independent volume control. +// + +typedef struct _VOLUME_CONTROL { + UCHAR PortVolume[4]; +} VOLUME_CONTROL, *PVOLUME_CONTROL; + +typedef enum _TRACK_MODE_TYPE { + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +// +// Passed to cdrom to describe the raw read, ie. Mode 2, Form 2, CDDA... +// + +typedef struct __RAW_READ_INFO { + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +#ifdef __cplusplus +} +#endif + + +#if _MSC_VER >= 1200 +#pragma warning(pop) // un-sets any local warning changes +#else +#pragma warning(default:4200) // array[0] is not a warning for this file +#pragma warning(default:4201) // nameless struct/unions +#pragma warning(default:4214) // bit fields other than int +#endif + + +#endif // _NTDDCDRM_ + +// end_winioctl + + diff --git a/src/dos/Ntddscsi.h b/src/dos/Ntddscsi.h new file mode 100644 index 0000000..61f5b25 --- /dev/null +++ b/src/dos/Ntddscsi.h @@ -0,0 +1,313 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + ntddscsi.h + +Abstract: + + This is the include file that defines all constants and types for + accessing the SCSI port adapters. + +Author: + + Jeff Havens + +Revision History: + +--*/ + + +// +// Interface GUIDs +// +// need these GUIDs outside conditional includes so that user can +// #include in precompiled header +// #include in a single source file +// #include in that source file a second time to instantiate the GUIDs +// +#ifdef DEFINE_GUID +// +// Make sure FAR is defined... +// +#ifndef FAR +#ifdef _WIN32 +#define FAR +#else +#define FAR _far +#endif +#endif + +DEFINE_GUID(ScsiRawInterfaceGuid, 0x53f56309L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(WmiScsiAddressGuid, 0x53f5630fL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +#endif + +#ifndef _NTDDSCSIH_ +#define _NTDDSCSIH_ + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Device Name - this string is the name of the device. It is the name +// that should be passed to NtOpenFile when accessing the device. +// +// Note: For devices that support multiple units, it should be suffixed +// with the Ascii representation of the unit number. +// + +#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER + +#define DD_SCSI_DEVICE_NAME "\\Device\\ScsiPort" + + +// +// NtDeviceIoControlFile IoControlCode values for this device. +// +// Warning: Remember that the low two bits of the code specify how the +// buffers are passed to the driver! +// + +#define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_MINIPORT CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_SCSI_GET_ADDRESS CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_RESCAN_BUS CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0408, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_FREE_DUMP_POINTERS CTL_CODE(IOCTL_SCSI_BASE, 0x0409, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_IDE_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x040a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +// +// Define the SCSI pass through structure. +// + +typedef struct _SCSI_PASS_THROUGH { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG DataBufferOffset; //ULONG_PTR DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; + +// +// Define the SCSI pass through direct structure. +// + +typedef struct _SCSI_PASS_THROUGH_DIRECT { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + PVOID DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; + + +// +// Define the SCSI pass through direct structure for Win64 (thunking). +// +#if defined(_WIN64) +typedef struct _SCSI_PASS_THROUGH32 { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG32 DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}SCSI_PASS_THROUGH32, *PSCSI_PASS_THROUGH32; + +// +// Define the SCSI pass through direct structure. +// + +typedef struct _SCSI_PASS_THROUGH_DIRECT32 { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + VOID * POINTER_32 DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +}SCSI_PASS_THROUGH_DIRECT32, *PSCSI_PASS_THROUGH_DIRECT32; + +#endif + +// +// Define SCSI information. +// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. +// + +typedef struct _SCSI_BUS_DATA { + UCHAR NumberOfLogicalUnits; + UCHAR InitiatorBusId; + ULONG InquiryDataOffset; +}SCSI_BUS_DATA, *PSCSI_BUS_DATA; + +// +// Define SCSI adapter bus information structure.. +// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. +// + +typedef struct _SCSI_ADAPTER_BUS_INFO { + UCHAR NumberOfBuses; + SCSI_BUS_DATA BusData[1]; +} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; + +// +// Define SCSI adapter bus information. +// Used with the IOCTL_SCSI_GET_INQUIRY_DATA IOCTL. +// + +typedef struct _SCSI_INQUIRY_DATA { + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + BOOLEAN DeviceClaimed; + ULONG InquiryDataLength; + ULONG NextInquiryDataOffset; + UCHAR InquiryData[1]; +}SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; + +// +// Define header for I/O control SRB. +// + +typedef struct _SRB_IO_CONTROL { + ULONG HeaderLength; + UCHAR Signature[8]; + ULONG Timeout; + ULONG ControlCode; + ULONG ReturnCode; + ULONG Length; +} SRB_IO_CONTROL, *PSRB_IO_CONTROL; + +// +// SCSI port driver capabilities structure. +// + +typedef struct _IO_SCSI_CAPABILITIES { + + // + // Length of this structure + // + + ULONG Length; + + // + // Maximum transfer size in single SRB + // + + ULONG MaximumTransferLength; + + // + // Maximum number of physical pages per data buffer + // + + ULONG MaximumPhysicalPages; + + // + // Async calls from port to class + // + + ULONG SupportedAsynchronousEvents; + + // + // Alignment mask for data transfers. + // + + ULONG AlignmentMask; + + // + // Supports tagged queuing + // + + BOOLEAN TaggedQueuing; + + // + // Host adapter scans down for bios devices. + // + + BOOLEAN AdapterScansDown; + + // + // The host adapter uses programmed I/O. + // + + BOOLEAN AdapterUsesPio; + +} IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES; + +typedef struct _SCSI_ADDRESS { + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +}SCSI_ADDRESS, *PSCSI_ADDRESS; + +// +// Define structure for returning crash dump pointers. +// + +struct _ADAPTER_OBJECT; + +typedef struct _DUMP_POINTERS { + struct _ADAPTER_OBJECT *AdapterObject; + PVOID MappedRegisterBase; + PVOID DumpData; + PVOID CommonBufferVa; + LARGE_INTEGER CommonBufferPa; + ULONG CommonBufferSize; + BOOLEAN AllocateCommonBuffers; + BOOLEAN UseDiskDump; + UCHAR Spare1[2]; + PVOID DeviceObject; +} DUMP_POINTERS, *PDUMP_POINTERS; + +// +// Define values for pass-through DataIn field. +// + +#define SCSI_IOCTL_DATA_OUT 0 +#define SCSI_IOCTL_DATA_IN 1 +#define SCSI_IOCTL_DATA_UNSPECIFIED 2 + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/src/dos/Ntddstor.h b/src/dos/Ntddstor.h new file mode 100644 index 0000000..766f19c --- /dev/null +++ b/src/dos/Ntddstor.h @@ -0,0 +1,746 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + ntddstor.h + +Abstract: + + This is the include file that defines all common constants and types + accessing the storage class drivers + +Author: + + Peter Wieland 19-Jun-1996 + +Revision History: + +--*/ + + +// +// Interface GUIDs +// +// need these GUIDs outside conditional includes so that user can +// #include in precompiled header +// #include in a single source file +// #include in that source file a second time to instantiate the GUIDs +// +#ifdef DEFINE_GUID +// +// Make sure FAR is defined... +// +#ifndef FAR +#ifdef _WIN32 +#define FAR +#else +#define FAR _far +#endif +#endif + +// begin_wioctlguids +DEFINE_GUID(GUID_DEVINTERFACE_DISK, 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_CDROM, 0x53f56308L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_PARTITION, 0x53f5630aL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_TAPE, 0x53f5630bL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_WRITEONCEDISK, 0x53f5630cL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_VOLUME, 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_MEDIUMCHANGER, 0x53f56310L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_FLOPPY, 0x53f56311L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_CDCHANGER, 0x53f56312L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +DEFINE_GUID(GUID_DEVINTERFACE_STORAGEPORT, 0x2accfe60L, 0xc130, 0x11d2, 0xb0, 0x82, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); +// end_wioctlguids + +// begin_wioctlobsoleteguids +#define DiskClassGuid GUID_DEVINTERFACE_DISK +#define CdRomClassGuid GUID_DEVINTERFACE_CDROM +#define PartitionClassGuid GUID_DEVINTERFACE_PARTITION +#define TapeClassGuid GUID_DEVINTERFACE_TAPE +#define WriteOnceDiskClassGuid GUID_DEVINTERFACE_WRITEONCEDISK +#define VolumeClassGuid GUID_DEVINTERFACE_VOLUME +#define MediumChangerClassGuid GUID_DEVINTERFACE_MEDIUMCHANGER +#define FloppyClassGuid GUID_DEVINTERFACE_FLOPPY +#define CdChangerClassGuid GUID_DEVINTERFACE_CDCHANGER +#define StoragePortClassGuid GUID_DEVINTERFACE_STORAGEPORT +// end_wioctlobsoleteguids +#endif + +// begin_winioctl + +#ifndef _NTDDSTOR_H_ +#define _NTDDSTOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// +// IoControlCode values for storage devices +// + +#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE + +// +// The following device control codes are common for all class drivers. They +// should be used in place of the older IOCTL_DISK, IOCTL_CDROM and IOCTL_TAPE +// common codes +// + +#define IOCTL_STORAGE_CHECK_VERIFY CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_MEDIA_REMOVAL CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_EJECT_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_LOAD_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_LOAD_MEDIA2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_RESERVE CTL_CODE(IOCTL_STORAGE_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_RELEASE CTL_CODE(IOCTL_STORAGE_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_FIND_NEW_DEVICES CTL_CODE(IOCTL_STORAGE_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_STORAGE_EJECTION_CONTROL CTL_CODE(IOCTL_STORAGE_BASE, 0x0250, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_MCN_CONTROL CTL_CODE(IOCTL_STORAGE_BASE, 0x0251, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_STORAGE_GET_MEDIA_TYPES CTL_CODE(IOCTL_STORAGE_BASE, 0x0300, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_GET_MEDIA_TYPES_EX CTL_CODE(IOCTL_STORAGE_BASE, 0x0301, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_GET_HOTPLUG_INFO CTL_CODE(IOCTL_STORAGE_BASE, 0x0305, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_SET_HOTPLUG_INFO CTL_CODE(IOCTL_STORAGE_BASE, 0x0306, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +#define IOCTL_STORAGE_RESET_BUS CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_RESET_DEVICE CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_BREAK_RESERVATION CTL_CODE(IOCTL_STORAGE_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define IOCTL_STORAGE_GET_DEVICE_NUMBER CTL_CODE(IOCTL_STORAGE_BASE, 0x0420, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_PREDICT_FAILURE CTL_CODE(IOCTL_STORAGE_BASE, 0x0440, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// end_winioctl + + +#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) + + +// begin_winioctl + +// +// These ioctl codes are obsolete. They are defined here to avoid resuing them +// and to allow class drivers to respond to them more easily. +// + +#define OBSOLETE_IOCTL_STORAGE_RESET_BUS CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define OBSOLETE_IOCTL_STORAGE_RESET_DEVICE CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + + +// +// IOCTL_STORAGE_GET_HOTPLUG_INFO +// + +typedef struct _STORAGE_HOTPLUG_INFO { + ULONG Size; // version + BOOLEAN MediaRemovable; // ie. zip, jaz, cdrom, mo, etc. vs hdd + BOOLEAN MediaHotplug; // ie. does the device succeed a lock even though its not lockable media? + BOOLEAN DeviceHotplug; // ie. 1394, USB, etc. + BOOLEAN WriteCacheEnableOverride; // This field should not be relied upon because it is no longer used +} STORAGE_HOTPLUG_INFO, *PSTORAGE_HOTPLUG_INFO; + +// +// IOCTL_STORAGE_GET_DEVICE_NUMBER +// +// input - none +// +// output - STORAGE_DEVICE_NUMBER structure +// The values in the STORAGE_DEVICE_NUMBER structure are guaranteed +// to remain unchanged until the system is rebooted. They are not +// guaranteed to be persistant across boots. +// + +typedef struct _STORAGE_DEVICE_NUMBER { + + // + // The FILE_DEVICE_XXX type for this device. + // + + DEVICE_TYPE DeviceType; + + // + // The number of this device + // + + ULONG DeviceNumber; + + // + // If the device is partitionable, the partition number of the device. + // Otherwise -1 + // + + ULONG PartitionNumber; +} STORAGE_DEVICE_NUMBER, *PSTORAGE_DEVICE_NUMBER; + +// +// Define the structures for scsi resets +// + +typedef struct _STORAGE_BUS_RESET_REQUEST { + UCHAR PathId; +} STORAGE_BUS_RESET_REQUEST, *PSTORAGE_BUS_RESET_REQUEST; + +// +// IOCTL_STORAGE_MEDIA_REMOVAL disables the mechanism +// on a storage device that ejects media. This function +// may or may not be supported on storage devices that +// support removable media. +// +// TRUE means prevent media from being removed. +// FALSE means allow media removal. +// +#if defined (_MSC_VER) /* MS Visual C++ */ +typedef struct _PREVENT_MEDIA_REMOVAL { + BOOLEAN PreventMediaRemoval; +} PREVENT_MEDIA_REMOVAL, *PPREVENT_MEDIA_REMOVAL; +#endif + +// begin_ntminitape + + +typedef struct _TAPE_STATISTICS { + ULONG Version; + ULONG Flags; + LARGE_INTEGER RecoveredWrites; + LARGE_INTEGER UnrecoveredWrites; + LARGE_INTEGER RecoveredReads; + LARGE_INTEGER UnrecoveredReads; + UCHAR CompressionRatioReads; + UCHAR CompressionRatioWrites; +} TAPE_STATISTICS, *PTAPE_STATISTICS; + +#define RECOVERED_WRITES_VALID 0x00000001 +#define UNRECOVERED_WRITES_VALID 0x00000002 +#define RECOVERED_READS_VALID 0x00000004 +#define UNRECOVERED_READS_VALID 0x00000008 +#define WRITE_COMPRESSION_INFO_VALID 0x00000010 +#define READ_COMPRESSION_INFO_VALID 0x00000020 + +typedef struct _TAPE_GET_STATISTICS { + ULONG Operation; +} TAPE_GET_STATISTICS, *PTAPE_GET_STATISTICS; + +#define TAPE_RETURN_STATISTICS 0L +#define TAPE_RETURN_ENV_INFO 1L +#define TAPE_RESET_STATISTICS 2L + +// +// IOCTL_STORAGE_GET_MEDIA_TYPES_EX will return an array of DEVICE_MEDIA_INFO +// structures, one per supported type, embedded in the GET_MEDIA_TYPES struct. +// + +typedef enum _STORAGE_MEDIA_TYPE { + // + // Following are defined in ntdddisk.h in the MEDIA_TYPE enum + // + // Unknown, // Format is unknown + // F5_1Pt2_512, // 5.25", 1.2MB, 512 bytes/sector + // F3_1Pt44_512, // 3.5", 1.44MB, 512 bytes/sector + // F3_2Pt88_512, // 3.5", 2.88MB, 512 bytes/sector + // F3_20Pt8_512, // 3.5", 20.8MB, 512 bytes/sector + // F3_720_512, // 3.5", 720KB, 512 bytes/sector + // F5_360_512, // 5.25", 360KB, 512 bytes/sector + // F5_320_512, // 5.25", 320KB, 512 bytes/sector + // F5_320_1024, // 5.25", 320KB, 1024 bytes/sector + // F5_180_512, // 5.25", 180KB, 512 bytes/sector + // F5_160_512, // 5.25", 160KB, 512 bytes/sector + // RemovableMedia, // Removable media other than floppy + // FixedMedia, // Fixed hard disk media + // F3_120M_512, // 3.5", 120M Floppy + // F3_640_512, // 3.5" , 640KB, 512 bytes/sector + // F5_640_512, // 5.25", 640KB, 512 bytes/sector + // F5_720_512, // 5.25", 720KB, 512 bytes/sector + // F3_1Pt2_512, // 3.5" , 1.2Mb, 512 bytes/sector + // F3_1Pt23_1024, // 3.5" , 1.23Mb, 1024 bytes/sector + // F5_1Pt23_1024, // 5.25", 1.23MB, 1024 bytes/sector + // F3_128Mb_512, // 3.5" MO 128Mb 512 bytes/sector + // F3_230Mb_512, // 3.5" MO 230Mb 512 bytes/sector + // F8_256_128, // 8", 256KB, 128 bytes/sector + // F3_200Mb_512, // 3.5", 200M Floppy (HiFD) + // + + DDS_4mm = 0x20, // Tape - DAT DDS1,2,... (all vendors) + MiniQic, // Tape - miniQIC Tape + Travan, // Tape - Travan TR-1,2,3,... + QIC, // Tape - QIC + MP_8mm, // Tape - 8mm Exabyte Metal Particle + AME_8mm, // Tape - 8mm Exabyte Advanced Metal Evap + AIT1_8mm, // Tape - 8mm Sony AIT + DLT, // Tape - DLT Compact IIIxt, IV + NCTP, // Tape - Philips NCTP + IBM_3480, // Tape - IBM 3480 + IBM_3490E, // Tape - IBM 3490E + IBM_Magstar_3590, // Tape - IBM Magstar 3590 + IBM_Magstar_MP, // Tape - IBM Magstar MP + STK_DATA_D3, // Tape - STK Data D3 + SONY_DTF, // Tape - Sony DTF + DV_6mm, // Tape - 6mm Digital Video + DMI, // Tape - Exabyte DMI and compatibles + SONY_D2, // Tape - Sony D2S and D2L + CLEANER_CARTRIDGE, // Cleaner - All Drive types that support Drive Cleaners + CD_ROM, // Opt_Disk - CD + CD_R, // Opt_Disk - CD-Recordable (Write Once) + CD_RW, // Opt_Disk - CD-Rewriteable + DVD_ROM, // Opt_Disk - DVD-ROM + DVD_R, // Opt_Disk - DVD-Recordable (Write Once) + DVD_RW, // Opt_Disk - DVD-Rewriteable + MO_3_RW, // Opt_Disk - 3.5" Rewriteable MO Disk + MO_5_WO, // Opt_Disk - MO 5.25" Write Once + MO_5_RW, // Opt_Disk - MO 5.25" Rewriteable (not LIMDOW) + MO_5_LIMDOW, // Opt_Disk - MO 5.25" Rewriteable (LIMDOW) + PC_5_WO, // Opt_Disk - Phase Change 5.25" Write Once Optical + PC_5_RW, // Opt_Disk - Phase Change 5.25" Rewriteable + PD_5_RW, // Opt_Disk - PhaseChange Dual Rewriteable + ABL_5_WO, // Opt_Disk - Ablative 5.25" Write Once Optical + PINNACLE_APEX_5_RW, // Opt_Disk - Pinnacle Apex 4.6GB Rewriteable Optical + SONY_12_WO, // Opt_Disk - Sony 12" Write Once + PHILIPS_12_WO, // Opt_Disk - Philips/LMS 12" Write Once + HITACHI_12_WO, // Opt_Disk - Hitachi 12" Write Once + CYGNET_12_WO, // Opt_Disk - Cygnet/ATG 12" Write Once + KODAK_14_WO, // Opt_Disk - Kodak 14" Write Once + MO_NFR_525, // Opt_Disk - Near Field Recording (Terastor) + NIKON_12_RW, // Opt_Disk - Nikon 12" Rewriteable + IOMEGA_ZIP, // Mag_Disk - Iomega Zip + IOMEGA_JAZ, // Mag_Disk - Iomega Jaz + SYQUEST_EZ135, // Mag_Disk - Syquest EZ135 + SYQUEST_EZFLYER, // Mag_Disk - Syquest EzFlyer + SYQUEST_SYJET, // Mag_Disk - Syquest SyJet + AVATAR_F2, // Mag_Disk - 2.5" Floppy + MP2_8mm, // Tape - 8mm Hitachi + DST_S, // Ampex DST Small Tapes + DST_M, // Ampex DST Medium Tapes + DST_L, // Ampex DST Large Tapes + VXATape_1, // Ecrix 8mm Tape + VXATape_2, // Ecrix 8mm Tape + STK_9840, // STK 9840 + LTO_Ultrium, // IBM, HP, Seagate LTO Ultrium + LTO_Accelis, // IBM, HP, Seagate LTO Accelis + DVD_RAM, // Opt_Disk - DVD-RAM + AIT_8mm, // AIT2 or higher + ADR_1, // OnStream ADR Mediatypes + ADR_2 +} STORAGE_MEDIA_TYPE, *PSTORAGE_MEDIA_TYPE; + +#define MEDIA_ERASEABLE 0x00000001 +#define MEDIA_WRITE_ONCE 0x00000002 +#define MEDIA_READ_ONLY 0x00000004 +#define MEDIA_READ_WRITE 0x00000008 + +#define MEDIA_WRITE_PROTECTED 0x00000100 +#define MEDIA_CURRENTLY_MOUNTED 0x80000000 + +// +// Define the different storage bus types +// Bus types below 128 (0x80) are reserved for Microsoft use +// + +typedef enum _STORAGE_BUS_TYPE { + BusTypeUnknown = 0x00, + BusTypeScsi, + BusTypeAtapi, + BusTypeAta, + BusType1394, + BusTypeSsa, + BusTypeFibre, + BusTypeUsb, + BusTypeRAID, + BusTypeMaxReserved = 0x7F +} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE; + +typedef struct _DEVICE_MEDIA_INFO { + union { + struct { + LARGE_INTEGER Cylinders; + STORAGE_MEDIA_TYPE MediaType; + ULONG TracksPerCylinder; + ULONG SectorsPerTrack; + ULONG BytesPerSector; + ULONG NumberMediaSides; + ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values. + } DiskInfo; + + struct { + LARGE_INTEGER Cylinders; + STORAGE_MEDIA_TYPE MediaType; + ULONG TracksPerCylinder; + ULONG SectorsPerTrack; + ULONG BytesPerSector; + ULONG NumberMediaSides; + ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values. + } RemovableDiskInfo; + + struct { + STORAGE_MEDIA_TYPE MediaType; + ULONG MediaCharacteristics; // Bitmask of MEDIA_XXX values. + ULONG CurrentBlockSize; + STORAGE_BUS_TYPE BusType; + + // + // Bus specific information describing the medium supported. + // + + union { + struct { + UCHAR MediumType; + UCHAR DensityCode; + } ScsiInformation; + } BusSpecificData; + + } TapeInfo; + } DeviceSpecific; +} DEVICE_MEDIA_INFO, *PDEVICE_MEDIA_INFO; + +typedef struct _GET_MEDIA_TYPES { + ULONG DeviceType; // FILE_DEVICE_XXX values + ULONG MediaInfoCount; + DEVICE_MEDIA_INFO MediaInfo[1]; +} GET_MEDIA_TYPES, *PGET_MEDIA_TYPES; + + +// +// IOCTL_STORAGE_PREDICT_FAILURE +// +// input - none +// +// output - STORAGE_PREDICT_FAILURE structure +// PredictFailure returns zero if no failure predicted and non zero +// if a failure is predicted. +// +// VendorSpecific returns 512 bytes of vendor specific information +// if a failure is predicted +// +typedef struct _STORAGE_PREDICT_FAILURE +{ + ULONG PredictFailure; + UCHAR VendorSpecific[512]; +} STORAGE_PREDICT_FAILURE, *PSTORAGE_PREDICT_FAILURE; + +// end_ntminitape +// end_winioctl + +// +// Property Query Structures +// + +// +// IOCTL_STORAGE_QUERY_PROPERTY +// +// Input Buffer: +// a STORAGE_PROPERTY_QUERY structure which describes what type of query +// is being done, what property is being queried for, and any additional +// parameters which a particular property query requires. +// +// Output Buffer: +// Contains a buffer to place the results of the query into. Since all +// property descriptors can be cast into a STORAGE_DESCRIPTOR_HEADER, +// the IOCTL can be called once with a small buffer then again using +// a buffer as large as the header reports is necessary. +// + + +// +// Types of queries +// + +typedef enum _STORAGE_QUERY_TYPE { + PropertyStandardQuery = 0, // Retrieves the descriptor + PropertyExistsQuery, // Used to test whether the descriptor is supported + PropertyMaskQuery, // Used to retrieve a mask of writeable fields in the descriptor + PropertyQueryMaxDefined // use to validate the value +} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE; + +// +// define some initial property id's +// + +typedef enum _STORAGE_PROPERTY_ID { + StorageDeviceProperty = 0, + StorageAdapterProperty, + StorageDeviceIdProperty +} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID; + +// +// Query structure - additional parameters for specific queries can follow +// the header +// + +typedef struct _STORAGE_PROPERTY_QUERY { + + // + // ID of the property being retrieved + // + + STORAGE_PROPERTY_ID PropertyId; + + // + // Flags indicating the type of query being performed + // + + STORAGE_QUERY_TYPE QueryType; + + // + // Space for additional parameters if necessary + // + + UCHAR AdditionalParameters[1]; + +} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY; + +// +// Standard property descriptor header. All property pages should use this +// as their first element or should contain these two elements +// + +typedef struct _STORAGE_DESCRIPTOR_HEADER { + + ULONG Version; + + ULONG Size; + +} STORAGE_DESCRIPTOR_HEADER, *PSTORAGE_DESCRIPTOR_HEADER; + +// +// Device property descriptor - this is really just a rehash of the inquiry +// data retrieved from a scsi device +// +// This may only be retrieved from a target device. Sending this to the bus +// will result in an error +// + +typedef struct _STORAGE_DEVICE_DESCRIPTOR { + + // + // Sizeof(STORAGE_DEVICE_DESCRIPTOR) + // + + ULONG Version; + + // + // Total size of the descriptor, including the space for additional + // data and id strings + // + + ULONG Size; + + // + // The SCSI-2 device type + // + + UCHAR DeviceType; + + // + // The SCSI-2 device type modifier (if any) - this may be zero + // + + UCHAR DeviceTypeModifier; + + // + // Flag indicating whether the device's media (if any) is removable. This + // field should be ignored for media-less devices + // + + BOOLEAN RemovableMedia; + + // + // Flag indicating whether the device can support mulitple outstanding + // commands. The actual synchronization in this case is the responsibility + // of the port driver. + // + + BOOLEAN CommandQueueing; + + // + // Byte offset to the zero-terminated ascii string containing the device's + // vendor id string. For devices with no such ID this will be zero + // + + ULONG VendorIdOffset; + + // + // Byte offset to the zero-terminated ascii string containing the device's + // product id string. For devices with no such ID this will be zero + // + + ULONG ProductIdOffset; + + // + // Byte offset to the zero-terminated ascii string containing the device's + // product revision string. For devices with no such string this will be + // zero + // + + ULONG ProductRevisionOffset; + + // + // Byte offset to the zero-terminated ascii string containing the device's + // serial number. For devices with no serial number this will be zero + // + + ULONG SerialNumberOffset; + + // + // Contains the bus type (as defined above) of the device. It should be + // used to interpret the raw device properties at the end of this structure + // (if any) + // + + STORAGE_BUS_TYPE BusType; + + // + // The number of bytes of bus-specific data which have been appended to + // this descriptor + // + + ULONG RawPropertiesLength; + + // + // Place holder for the first byte of the bus specific property data + // + + UCHAR RawDeviceProperties[1]; + +} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR; + + +// +// Adapter properties +// +// This descriptor can be retrieved from a target device object of from the +// device object for the bus. Retrieving from the target device object will +// forward the request to the underlying bus +// + +typedef struct _STORAGE_ADAPTER_DESCRIPTOR { + + ULONG Version; + + ULONG Size; + + ULONG MaximumTransferLength; + + ULONG MaximumPhysicalPages; + + ULONG AlignmentMask; + + BOOLEAN AdapterUsesPio; + + BOOLEAN AdapterScansDown; + + BOOLEAN CommandQueueing; + + BOOLEAN AcceleratedTransfer; + + UCHAR BusType; + + USHORT BusMajorVersion; + + USHORT BusMinorVersion; + +} STORAGE_ADAPTER_DESCRIPTOR, *PSTORAGE_ADAPTER_DESCRIPTOR; + +// +// Storage identification descriptor. +// The definitions here are based on the SCSI/SBP vital product data +// device identifier page. +// + +typedef enum _STORAGE_IDENTIFIER_CODE_SET { + StorageIdCodeSetReserved = 0, + StorageIdCodeSetBinary = 1, + StorageIdCodeSetAscii = 2 +} STORAGE_IDENTIFIER_CODE_SET, *PSTORAGE_IDENTIFIER_CODE_SET; + +typedef enum _STORAGE_IDENTIFIER_TYPE { + StorageIdTypeVendorSpecific = 0, + StorageIdTypeVendorId = 1, + StorageIdTypeEUI64 = 2, + StorageIdTypeFCPHName = 3, + StorageIdTypePortRelative = 4 +} STORAGE_IDENTIFIER_TYPE, *PSTORAGE_IDENTIFIER_TYPE; + +typedef enum _STORAGE_ASSOCIATION_TYPE { + StorageIdAssocDevice = 0, + StorageIdAssocPort = 1 +} STORAGE_ASSOCIATION_TYPE, *PSTORAGE_ASSOCIATION_TYPE; + +typedef struct _STORAGE_IDENTIFIER { + STORAGE_IDENTIFIER_CODE_SET CodeSet; + STORAGE_IDENTIFIER_TYPE Type; + USHORT IdentifierSize; + USHORT NextOffset; + + // + // Add new fields here since existing code depends on + // the above layout not changing. + // + + STORAGE_ASSOCIATION_TYPE Association; + + // + // The identifier is a variable length array of bytes. + // + + UCHAR Identifier[1]; +} STORAGE_IDENTIFIER, *PSTORAGE_IDENTIFIER; + +typedef struct _STORAGE_DEVICE_ID_DESCRIPTOR { + + ULONG Version; + + ULONG Size; + + // + // The number of identifiers reported by the device. + // + + ULONG NumberOfIdentifiers; + + // + // The following field is actually a variable length array of identification + // descriptors. Unfortunately there's no C notation for an array of + // variable length structures so we're forced to just pretend. + // + + UCHAR Identifiers[1]; +} STORAGE_DEVICE_ID_DESCRIPTOR, *PSTORAGE_DEVICE_ID_DESCRIPTOR; + + +#pragma warning(push) +#pragma warning(disable:4200) +typedef struct _STORAGE_MEDIA_SERIAL_NUMBER_DATA { + + USHORT Reserved; + + // + // the SerialNumberLength will be set to zero + // if the command is supported and the media + // does not have a valid serial number. + // + + USHORT SerialNumberLength; + + // + // the following data is binary, and is not guaranteed + // to be NULL terminated. this is an excercise for the + // caller. + // + + UCHAR SerialNumber[0]; + +} STORAGE_MEDIA_SERIAL_NUMBER_DATA, *PSTORAGE_MEDIA_SERIAL_NUMBER_DATA; +#pragma warning(push) + + +// begin_winioctl + +#ifdef __cplusplus +} +#endif + +#endif // _NTDDSTOR_H_ +// end_winioctl + diff --git a/src/dos/cdrom.cpp b/src/dos/cdrom.cpp new file mode 100644 index 0000000..86cf831 --- /dev/null +++ b/src/dos/cdrom.cpp @@ -0,0 +1,229 @@ +/* + * 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. + */ + + +// ****************************************************** +// SDL CDROM +// ****************************************************** + +#include "SDL.h" +#include "support.h" +#include "cdrom.h" + +CDROM_Interface_SDL::CDROM_Interface_SDL(void) +{ + driveID = 0; + oldLeadOut = 0; + cd = 0; +}; + +CDROM_Interface_SDL::~CDROM_Interface_SDL(void) +{ + StopAudio(); + SDL_CDClose(cd); + cd = 0; +}; + +bool CDROM_Interface_SDL::SetDevice (char* path, int forceCD) +{ + char buffer[512]; + strcpy(buffer,path); + upcase(buffer); + + int num = SDL_CDNumDrives(); + if ((forceCD>=0) && (forceCDstatus)) { + stTrack = 1; + end = cd->numtracks; + FRAMES_TO_MSF(cd->track[cd->numtracks].offset,&leadOut.min,&leadOut.sec,&leadOut.fr); + } + return CD_INDRIVE(cd->status); +}; + +bool CDROM_Interface_SDL::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) +{ + SDL_CDStatus(cd); + if (CD_INDRIVE(cd->status)) { + 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); +}; + +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)) { + 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); +}; + +bool CDROM_Interface_SDL::GetAudioStatus (bool& playing, bool& pause) +{ + SDL_CDStatus(cd); + if (CD_INDRIVE(cd->status)) { + playing = (cd->status==CD_PLAYING); + pause = (cd->status==CD_PAUSED); + } + return CD_INDRIVE(cd->status); +}; + +bool CDROM_Interface_SDL::GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) +{ + SDL_CDStatus(cd); + mediaPresent = (cd->status!=CD_TRAYEMPTY) && (cd->status!=CD_ERROR); + mediaChanged = (oldLeadOut!=cd->track[cd->numtracks].offset); + trayOpen = !mediaPresent; + oldLeadOut = cd->track[cd->numtracks].offset; + if (mediaChanged) SDL_CDStatus(cd); + return true; +}; + +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); + return success; +}; + +bool CDROM_Interface_SDL::PauseAudio (bool resume) +{ + bool success; + if (resume) success = (SDL_CDResume(cd)==0); + else success = (SDL_CDPause (cd)==0); + return success; +}; + +bool CDROM_Interface_SDL::StopAudio (void) +{ + // Has to be there, otherwise wrong cd status report (dunno why, sdl bug ?) + SDL_CDClose(cd); + cd = SDL_CDOpen(driveID); + bool success = (SDL_CDStop(cd)==0); + return success; +}; + +bool CDROM_Interface_SDL::LoadUnloadMedia(bool unload) +{ + bool success = (SDL_CDEject(cd)==0); + return success; +}; + +int CDROM_GetMountType(char* path, int forceCD) +// 0 - physical CDROM +// 1 - Iso file +// 2 - subdirectory +{ + // 1. Smells like a real cdrom + // if ((strlen(path)<=3) && (path[2]=='\\') && (strchr(path,'\\')==strrchr(path,'\\')) && (GetDriveType(path)==DRIVE_CDROM)) return 0; + + const char* cdName; + char buffer[512]; + strcpy(buffer,path); +#if defined (WIN32) + upcase(buffer); +#endif + + int num = SDL_CDNumDrives(); + // If cd drive is forced then check if its in range and return 0 + if ((forceCD>=0) && (forceCD1) return false; + start.min = start.fr = 0; + start.sec = 2; + attr = 0x60; // data / permitted + return true; +}; + +bool CDROM_Interface_Fake :: GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) +{ + attr = 0; + track = index = 1; + relPos.min = relPos.fr = 0; relPos.sec = 2; + absPos.min = absPos.fr = 0; absPos.sec = 2; + return true; +} + +bool CDROM_Interface_Fake :: GetAudioStatus (bool& playing, bool& pause) +{ + playing = pause = false; + return true; +} + +bool CDROM_Interface_Fake :: GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) +{ + mediaPresent = true; + mediaChanged = false; + trayOpen = false; + return true; +}; + + diff --git a/src/dos/cdrom.h b/src/dos/cdrom.h new file mode 100644 index 0000000..8dfc97a --- /dev/null +++ b/src/dos/cdrom.h @@ -0,0 +1,183 @@ + +#ifndef __CDROM_INTERFACE__ +#define __CDROM_INTERFACE__ + +#define MAX_ASPI_CDROM 5 + +#include +#include "SDL.h" + +#define RAW_SECTOR_SIZE 2352 +#define COOKED_SECTOR_SIZE 2048 + +enum { CDROM_USE_SDL, CDROM_USE_ASPI, CDROM_USE_IOCTL }; + +typedef struct SMSF { + unsigned char min; + unsigned char sec; + unsigned char fr; +} TMSF; + +extern int CDROM_GetMountType(char* path, int force); + +class CDROM_Interface +{ +public: +// CDROM_Interface (void); + virtual ~CDROM_Interface (void) {}; + + virtual bool SetDevice (char* path, int forceCD) = 0; + + virtual bool GetUPC (unsigned char& attr, char* upc) = 0; + + virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut) = 0; + virtual bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) = 0; + virtual bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) = 0; + virtual bool GetAudioStatus (bool& playing, bool& pause) = 0; + virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0; + + virtual bool PlayAudioSector (unsigned long start,unsigned long len) = 0; + 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 LoadUnloadMedia (bool unload) = 0; +}; + +class CDROM_Interface_SDL : public CDROM_Interface +{ +public: + CDROM_Interface_SDL (void); + ~CDROM_Interface_SDL (void); + + bool SetDevice (char* path, int forceCD); + bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; }; + bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); + bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); + bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); + bool GetAudioStatus (bool& playing, bool& pause); + bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); + bool PlayAudioSector (unsigned long start,unsigned long len); + bool PauseAudio (bool resume); + bool StopAudio (void); + bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num) { return true; }; + bool LoadUnloadMedia (bool unload); + +private: + bool Open (void); + void Close (void); + + SDL_CD* cd; + int driveID; + Uint32 oldLeadOut; +}; + +class CDROM_Interface_Fake : public CDROM_Interface +{ +public: + bool SetDevice (char* path, int forceCD) { return true; }; + bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; }; + bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); + bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); + bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); + bool GetAudioStatus (bool& playing, bool& pause); + bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); + bool PlayAudioSector (unsigned long start,unsigned long len) { return true; }; + bool PauseAudio (bool resume) { return true; }; + bool StopAudio (void) { return true; }; + bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num) { return true; }; + bool LoadUnloadMedia (bool unload) { return true; }; +}; + +#if defined (WIN32) /* Win 32 */ + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +#include "wnaspi32.h" // Aspi stuff + +class CDROM_Interface_Aspi : public CDROM_Interface +{ +public: + CDROM_Interface_Aspi (void); + ~CDROM_Interface_Aspi (void); + + bool SetDevice (char* path, int forceCD); + + bool GetUPC (unsigned char& attr, char* upc); + + bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); + bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); + bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); + bool GetAudioStatus (bool& playing, bool& pause); + bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); + + bool PlayAudioSector (unsigned long start,unsigned long len); + bool PauseAudio (bool resume); + bool StopAudio (void); + + bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num); + + bool LoadUnloadMedia (bool unload); + +private: + DWORD GetTOC (LPTOC toc); + HANDLE OpenIOCTLFile (char cLetter, BOOL bAsync); + void GetIOCTLAdapter (HANDLE hF,int * iDA,int * iDT,int * iDL); + bool ScanRegistryFindKey (HKEY& hKeyBase); + bool ScanRegistry (HKEY& hKeyBase); + BYTE GetHostAdapter (char* hardwareID); + bool GetVendor (BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer); + + // ASPI stuff + BYTE haId; + BYTE target; + BYTE lun; + char letter; + + // Windows stuff + HINSTANCE hASPI; + HANDLE hEvent; // global event + DWORD (*pGetASPI32SupportInfo) (void); // ptrs to aspi funcs + DWORD (*pSendASPI32Command) (LPSRB); + TMSF oldLeadOut; +}; + +class CDROM_Interface_Ioctl : public CDROM_Interface +{ +public: + CDROM_Interface_Ioctl (void); + ~CDROM_Interface_Ioctl (void); + + bool SetDevice (char* path, int forceCD); + + bool GetUPC (unsigned char& attr, char* upc); + + bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); + bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); + bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); + bool GetAudioStatus (bool& playing, bool& pause); + bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); + + bool PlayAudioSector (unsigned long start,unsigned long len); + bool PauseAudio (bool resume); + bool StopAudio (void); + + bool ReadSectors (void* buffer, bool raw, unsigned long sector, unsigned long num); + + bool LoadUnloadMedia (bool unload); + +private: + + bool Open (void); + void Close (void); + + char pathname[32]; + HANDLE hIOCTL; + TMSF oldLeadOut; +}; + +#endif /* WIN 32 */ + +#endif /* __CDROM_INTERFACE__ */ diff --git a/src/dos/cdrom_aspi_win32.cpp b/src/dos/cdrom_aspi_win32.cpp new file mode 100644 index 0000000..33d8c2a --- /dev/null +++ b/src/dos/cdrom_aspi_win32.cpp @@ -0,0 +1,735 @@ +/* + * 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. + */ + +#if defined (WIN32) + +#include + +#include "cdrom.h" +#include "scsidefs.h" // Aspi stuff +#include "dosbox.h" + +// ***************************************************************** +// Windows ASPI functions (should work for all WIN with ASPI layer) +// ***************************************************************** + +CDROM_Interface_Aspi::CDROM_Interface_Aspi(void) +{ + hASPI = NULL; + hEvent = NULL; + pGetASPI32SupportInfo = NULL; + pSendASPI32Command = NULL; + memset(&oldLeadOut,0,sizeof(oldLeadOut)); +}; + +CDROM_Interface_Aspi::~CDROM_Interface_Aspi(void) +{ + // Stop Audio + StopAudio(); + + pGetASPI32SupportInfo = NULL; // clear funcs + pSendASPI32Command = NULL; + + if (hASPI) { // free aspi + FreeLibrary(hASPI); + hASPI=NULL; + } +}; + +bool GetRegistryValue(HKEY& hKey,char* valueName, char* buffer, ULONG bufferSize) +// hKey has to be open +{ + // Read subkey + ULONG valType; + ULONG result; + result = RegQueryValueEx(hKey,valueName,NULL,&valType,(unsigned char*)&buffer[0],&bufferSize); + return (result == ERROR_SUCCESS); +}; + +BYTE CDROM_Interface_Aspi::GetHostAdapter(char* hardwareID) +{ + SRB_HAInquiry sh; + SRB_GDEVBlock sd; + DWORD d = pGetASPI32SupportInfo(); + int cnt = LOBYTE(LOWORD(d)); + int i,j,k,max; + + for(i=0; i4)) { + if (GetDriveType(path)==DRIVE_CDROM) { + // WIN XP/NT/2000 + int iDA,iDT,iDL; + letter = path[0]; + HANDLE hF = OpenIOCTLFile(letter,FALSE); + GetIOCTLAdapter(hF,&iDA,&iDT,&iDL); + CloseHandle(hF); + // Set SCSI IDs + haId = iDA; + target = iDT; + lun = iDL; + return true; + } + } else { + // win 95/98/ME have to scan the registry... + // lets hope the layout is always the same... i dunno... + char key[2048]; + HKEY hKeyBase; + bool found = false; + strcpy(key,"ENUM\\SCSI"); + if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,key,0,KEY_READ,&hKeyBase)==ERROR_SUCCESS) { + found = ScanRegistry(hKeyBase); + }; + RegCloseKey(hKeyBase); + return found; + } + return false; +}; + +bool CDROM_Interface_Aspi::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) +{ + TOC toc; + if (GetTOC((LPTOC)&toc) == SS_COMP) { + stTrack = toc.cFirstTrack; + endTrack = toc.cLastTrack; + leadOut.min = (unsigned char)(toc.tracks[endTrack].lAddr >> 8) &0xFF; + leadOut.sec = (unsigned char)(toc.tracks[endTrack].lAddr >> 16) &0xFF; + leadOut.fr = (unsigned char)(toc.tracks[endTrack].lAddr >> 24) &0xFF; + return true; + } + return false; +}; + +bool CDROM_Interface_Aspi::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) +{ + TOC toc; + if (GetTOC((LPTOC)&toc) == SS_COMP) { + start.min = (unsigned char)(toc.tracks[track-1].lAddr >> 8) &0xFF; + start.sec = (unsigned char)(toc.tracks[track-1].lAddr >> 16) &0xFF; + start.fr = (unsigned char)(toc.tracks[track-1].lAddr >> 24) &0xFF; + attr = toc.tracks[track-1].cAdrCtrl; + return true; + }; + return false; +}; + +HANDLE CDROM_Interface_Aspi::OpenIOCTLFile(char cLetter,BOOL bAsync) +{ + HANDLE hF; + char szFName[16]; + OSVERSIONINFO ov; + DWORD dwFlags; + DWORD dwIOCTLAttr; +// if(bAsync) dwIOCTLAttr=FILE_FLAG_OVERLAPPED; +// else + dwIOCTLAttr=0; + + memset(&ov,0,sizeof(OSVERSIONINFO)); + ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); + GetVersionEx(&ov); + + if ((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && (ov.dwMajorVersion>4)) + dwFlags = GENERIC_READ|GENERIC_WRITE; // add gen write on W2k/XP + else + dwFlags = GENERIC_READ; + + wsprintf(szFName, "\\\\.\\%c:",cLetter); + + hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // open drive + NULL,OPEN_EXISTING,dwIOCTLAttr,NULL); + + if (hF==INVALID_HANDLE_VALUE) { + dwFlags^=GENERIC_WRITE; // mmm... no success + hF=CreateFile(szFName,dwFlags,FILE_SHARE_READ, // -> open drive again + NULL,OPEN_EXISTING,dwIOCTLAttr,NULL); + if (hF==INVALID_HANDLE_VALUE) return NULL; + } + return hF; +} + +void CDROM_Interface_Aspi::GetIOCTLAdapter(HANDLE hF,int * iDA,int * iDT,int * iDL) +{ + char szBuf[1024]; + PSCSI_ADDRESS pSA; + DWORD dwRet; + + *iDA=*iDT=*iDL=-1; + if(hF==NULL) return; + + memset(szBuf,0,1024); + + pSA=(PSCSI_ADDRESS)szBuf; + pSA->Length=sizeof(SCSI_ADDRESS); + + if(!DeviceIoControl(hF,IOCTL_SCSI_GET_ADDRESS,NULL, + 0,pSA,sizeof(SCSI_ADDRESS), + &dwRet,NULL)) + return; + + *iDA = pSA->PortNumber; + *iDT = pSA->TargetId; + *iDL = pSA->Lun; +} + +DWORD CDROM_Interface_Aspi::GetTOC(LPTOC toc) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + + hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = haId; + s.SRB_Target = target; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = sizeof(*toc); + s.SRB_BufPointer = (BYTE FAR *)toc; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 0x0A; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = SCSI_READ_TOC; + s.CDBByte[1] = 0x02; // 0x02 for MSF + s.CDBByte[7] = 0x03; + s.CDBByte[8] = 0x24; + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&s); + + if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000); + + CloseHandle(hEvent); + + return (s.SRB_Status==SS_COMP); +} + +bool CDROM_Interface_Aspi::PlayAudioSector(unsigned long start,unsigned long len) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + + hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + + memset(&s,0,sizeof(s)); + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = haId; + s.SRB_Target = target; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0; + s.SRB_BufPointer = 0; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 12; + s.SRB_PostProc = (LPVOID)hEvent; + + s.CDBByte[0] = SCSI_PLAYAUD_12; + s.CDBByte[1] = lun << 5; + s.CDBByte[2] = (unsigned char)((start >> 24) & 0xFF); + s.CDBByte[3] = (unsigned char)((start >> 16) & 0xFF); + s.CDBByte[4] = (unsigned char)((start >> 8) & 0xFF); + s.CDBByte[5] = (unsigned char)((start & 0xFF)); + s.CDBByte[6] = (unsigned char)((len >> 24) & 0xFF); + s.CDBByte[7] = (unsigned char)((len >> 16) & 0xFF); + s.CDBByte[8] = (unsigned char)((len >> 8) & 0xFF); + s.CDBByte[9] = (unsigned char)(len & 0xFF); + + ResetEvent(hEvent); + + dwStatus = pSendASPI32Command((LPSRB)&s); + + if(dwStatus==SS_PENDING) WaitForSingleObject(hEvent,10000); + + CloseHandle(hEvent); + + return s.SRB_Status==SS_COMP; +} + +bool CDROM_Interface_Aspi::StopAudio(void) +{ + return PauseAudio(false); +}; + +bool CDROM_Interface_Aspi::PauseAudio(bool resume) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + + hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = haId; + s.SRB_Target = target; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_BufLen = 0x00; + s.SRB_SenseLen = SENSE_LEN; + s.SRB_CDBLen = 0x0A; + s.SRB_PostProc = (LPVOID)hEvent; + s.CDBByte[0] = 0x4B; + s.CDBByte[8] = (unsigned char)resume; // Pause + + ResetEvent(hEvent); + dwStatus=pSendASPI32Command((LPSRB)&s); + + if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000); + + CloseHandle(hEvent); + + return (s.SRB_Status==SS_COMP); +}; + +bool CDROM_Interface_Aspi::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) +{ + SUB_Q_CURRENT_POSITION pos; + SRB_ExecSCSICmd s;DWORD dwStatus; + + hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = haId; + s.SRB_Target = target; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_SenseLen = SENSE_LEN; + + s.SRB_BufLen = sizeof(pos); + s.SRB_BufPointer = (BYTE FAR *)&pos; + s.SRB_CDBLen = 10; + s.SRB_PostProc = (LPVOID)hEvent; + + s.CDBByte[0] = SCSI_SUBCHANNEL; + s.CDBByte[1] = (lun<<5)|2; // lun & msf + s.CDBByte[2] = 0x40; // subq + s.CDBByte[3] = 0x01; // curr pos info + s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) + s.CDBByte[7] = 0; // alloc len + s.CDBByte[8] = sizeof(pos); + + ResetEvent(hEvent); + + dwStatus = pSendASPI32Command((LPSRB)&s); + + if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); + + CloseHandle(hEvent); + + if (s.SRB_Status!=SS_COMP) return false; + + attr = (pos.ADR<<4) | pos.Control; + track = pos.TrackNumber; + index = pos.IndexNumber; + absPos.min = pos.AbsoluteAddress[1]; + absPos.sec = pos.AbsoluteAddress[2]; + absPos.fr = pos.AbsoluteAddress[3]; + relPos.min = pos.TrackRelativeAddress[1]; + relPos.sec = pos.TrackRelativeAddress[2]; + relPos.fr = pos.TrackRelativeAddress[3]; + + return true; +}; + +bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata) +{ + SUB_Q_MEDIA_CATALOG_NUMBER upc; + SRB_ExecSCSICmd s;DWORD dwStatus; + + hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = haId; + s.SRB_Target = target; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_SenseLen = SENSE_LEN; + + s.SRB_BufLen = sizeof(upc); + s.SRB_BufPointer = (BYTE FAR *)&upc; + s.SRB_CDBLen = 10; + s.SRB_PostProc = (LPVOID)hEvent; + + s.CDBByte[0] = SCSI_SUBCHANNEL; + s.CDBByte[1] = (lun<<5)|2; // lun & msf + s.CDBByte[2] = 0x40; // subq + s.CDBByte[3] = 0x02; // get upc + s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) + s.CDBByte[7] = 0; // alloc len + s.CDBByte[8] = sizeof(upc); + + ResetEvent(hEvent); + + dwStatus = pSendASPI32Command((LPSRB)&s); + + if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); + + CloseHandle(hEvent); + + if (s.SRB_Status!=SS_COMP) return false; + +// attr = (upc.ADR<<4) | upc.Control; + attr = 0; + int pos = 0; + // Convert to mscdex format +// for (int i=0; i<6; i++) upcdata[i] = (upc.MediaCatalog[pos++]<<4)+(upc.MediaCatalog[pos++]&0x0F); +// upcdata[6] = (upc.MediaCatalog[pos++]<<4); + for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i]; + + return true; +}; + +bool CDROM_Interface_Aspi::GetAudioStatus(bool& playing, bool& pause) +{ + playing = pause = false; + + SUB_Q_HEADER sub; + SRB_ExecSCSICmd s;DWORD dwStatus; + + hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = haId; + s.SRB_Target = target; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_SenseLen = SENSE_LEN; + + s.SRB_BufLen = sizeof(sub); + s.SRB_BufPointer = (BYTE FAR *)⊂ + s.SRB_CDBLen = 10; + s.SRB_PostProc = (LPVOID)hEvent; + + s.CDBByte[0] = SCSI_SUBCHANNEL; + s.CDBByte[1] = (lun<<5)|2; // lun & msf + s.CDBByte[2] = 0x00; // no subq + s.CDBByte[3] = 0x00; // dont care + s.CDBByte[6] = 0; // track number (only in isrc mode, ignored) + s.CDBByte[7] = 0; // alloc len + s.CDBByte[8] = sizeof(sub); + + ResetEvent(hEvent); + + dwStatus = pSendASPI32Command((LPSRB)&s); + + if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); + + CloseHandle(hEvent); + + if (s.SRB_Status!=SS_COMP) return false; + + playing = (sub.AudioStatus==0x11); + pause = (sub.AudioStatus==0x12); + + return true; +}; + +bool CDROM_Interface_Aspi::LoadUnloadMedia(bool unload) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + + hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + + memset(&s,0,sizeof(s)); + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = haId; + s.SRB_Target = target; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_SenseLen = SENSE_LEN; + + s.SRB_BufLen = 0; + s.SRB_BufPointer = 0; + s.SRB_CDBLen = 14; + s.SRB_PostProc = (LPVOID)hEvent; + + s.CDBByte[0] = SCSI_LOAD_UN; + s.CDBByte[1] = (lun<<5)|1; // lun & immediate + s.CDBByte[4] = (unload ? 0x02:0x03); // unload/load media + + ResetEvent(hEvent); + + dwStatus = pSendASPI32Command((LPSRB)&s); + + if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); + + CloseHandle(hEvent); + + if (s.SRB_Status!=SS_COMP) return false; + + return true; +}; + +bool CDROM_Interface_Aspi::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) +{ + // Seems not possible to get this values using ioctl... + int track1,track2; + TMSF leadOut; + // If we can read, there's a media + mediaPresent = GetAudioTracks(track1, track2, leadOut), + trayOpen = !mediaPresent; + mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr); + // Save old values + oldLeadOut.min = leadOut.min; + oldLeadOut.sec = leadOut.sec; + oldLeadOut.fr = leadOut.fr; + // always success + return true; +}; + +bool CDROM_Interface_Aspi::ReadSectors(void* buffer, bool raw, unsigned long sector, unsigned long num) +{ + SRB_ExecSCSICmd s;DWORD dwStatus; + + hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); + + 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; + + s.SRB_Cmd = SC_EXEC_SCSI_CMD; + s.SRB_HaId = haId; + s.SRB_Target = target; + s.SRB_Lun = lun; + s.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; + s.SRB_SenseLen = SENSE_LEN; + + s.SRB_BufLen = 2352*num; //num*(raw?2352:2048); + s.SRB_BufPointer = (BYTE FAR*)inPtr; + s.SRB_CDBLen = 12; + s.SRB_PostProc = (LPVOID)hEvent; + + s.CDBByte[0] = 0xBE; + s.CDBByte[2] = (unsigned char)((sector >> 24) & 0xFF); + s.CDBByte[3] = (unsigned char)((sector >> 16) & 0xFF); + s.CDBByte[4] = (unsigned char)((sector >> 8) & 0xFF); + s.CDBByte[5] = (unsigned char)((sector & 0xFF)); + s.CDBByte[6] = (unsigned char)((num >> 16) & 0xFF); + s.CDBByte[7] = (unsigned char)((num >> 8) & 0xFF); + s.CDBByte[8] = (unsigned char) (num & 0xFF); + s.CDBByte[9] = (raw?0xF0:0x10); + + ResetEvent(hEvent); + + dwStatus = pSendASPI32Command((LPSRB)&s); + + if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,0xFFFFFFFF); + + CloseHandle(hEvent); + + if (s.SRB_Status!=SS_COMP) { + if (!raw) delete[] inPtr; + return false; + } + + 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 "ntddcdrm.h" // Ioctl stuff +#include "cdrom.h" + +CDROM_Interface_Ioctl::CDROM_Interface_Ioctl() +{ + pathname[0] = 0; + hIOCTL = INVALID_HANDLE_VALUE; + memset(&oldLeadOut,0,sizeof(oldLeadOut)); +}; + +CDROM_Interface_Ioctl::~CDROM_Interface_Ioctl() +{ + StopAudio(); +}; + +bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc) +{ + // FIXME : To Do + return true; +} + +bool CDROM_Interface_Ioctl::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) +{ + Open(); + CDROM_TOC toc; + DWORD byteCount; + BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, + &toc, sizeof(toc), &byteCount,NULL); + Close(); + if (!bStat) return false; + + stTrack = toc.FirstTrack; + endTrack = toc.LastTrack; + leadOut.min = toc.TrackData[endTrack].Address[1]; + leadOut.sec = toc.TrackData[endTrack].Address[2]; + leadOut.fr = toc.TrackData[endTrack].Address[3]; + return true; +}; + +bool CDROM_Interface_Ioctl::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) +{ + Open(); + CDROM_TOC toc; + DWORD byteCount; + BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, + &toc, sizeof(toc), &byteCount,NULL); + Close(); + if (!bStat) return false; + + attr = (toc.TrackData[track-1].Adr << 4) | toc.TrackData[track].Control; + start.min = toc.TrackData[track-1].Address[1]; + start.sec = toc.TrackData[track-1].Address[2]; + start.fr = toc.TrackData[track-1].Address[3]; + return true; +}; + +bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) +{ + Open(); + + CDROM_SUB_Q_DATA_FORMAT insub; + SUB_Q_CHANNEL_DATA sub; + DWORD byteCount; + + insub.Format = IOCTL_CDROM_CURRENT_POSITION; + + BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), + &sub, sizeof(sub), &byteCount,NULL); + Close(); + if (!bStat) return false; + + attr = (sub.CurrentPosition.ADR << 4) | sub.CurrentPosition.Control; + track = sub.CurrentPosition.TrackNumber; + index = sub.CurrentPosition.IndexNumber; + relPos.min = sub.CurrentPosition.TrackRelativeAddress[1]; + relPos.sec = sub.CurrentPosition.TrackRelativeAddress[2]; + relPos.fr = sub.CurrentPosition.TrackRelativeAddress[3]; + absPos.min = sub.CurrentPosition.AbsoluteAddress[1]; + absPos.sec = sub.CurrentPosition.AbsoluteAddress[2]; + absPos.fr = sub.CurrentPosition.AbsoluteAddress[3]; + + return true; +}; + +bool CDROM_Interface_Ioctl::GetAudioStatus(bool& playing, bool& pause) +{ + Open(); + + CDROM_SUB_Q_DATA_FORMAT insub; + SUB_Q_CHANNEL_DATA sub; + DWORD byteCount; + + insub.Format = IOCTL_CDROM_CURRENT_POSITION; + + BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), + &sub, sizeof(sub), &byteCount,NULL); + Close(); + if (!bStat) return false; + + playing = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS); + pause = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED); + + return true; +}; + +bool CDROM_Interface_Ioctl::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) +{ + // Seems not possible to get this values using ioctl... + int track1,track2; + TMSF leadOut; + // If we can read, there's a media + mediaPresent = GetAudioTracks(track1, track2, leadOut), + trayOpen = !mediaPresent; + mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr); + // Save old values + oldLeadOut.min = leadOut.min; + oldLeadOut.sec = leadOut.sec; + oldLeadOut.fr = leadOut.fr; + // always success + return true; +}; + +bool CDROM_Interface_Ioctl::PlayAudioSector (unsigned long start,unsigned long len) +{ + Open(); + CDROM_PLAY_AUDIO_MSF audio; + DWORD byteCount; + // Start + unsigned long addr = start + 150; + audio.StartingF = (UCHAR)(addr%75); addr/=75; + audio.StartingS = (UCHAR)(addr%60); + audio.StartingM = (UCHAR)(addr/60); + // End + addr = start + len + 150; + audio.EndingF = (UCHAR)(addr%75); addr/=75; + audio.EndingS = (UCHAR)(addr%60); + audio.EndingM = (UCHAR)(addr/60); + + BOOL bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF, &audio, sizeof(audio), + NULL, 0, &byteCount,NULL); + Close(); + return bStat>0; +}; + +bool CDROM_Interface_Ioctl::PauseAudio(bool resume) +{ + 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(); + return bStat>0; +}; + +bool CDROM_Interface_Ioctl::StopAudio(void) +{ + Open(); + BOOL bStat; + DWORD byteCount; + bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO, NULL, 0, + NULL, 0, &byteCount,NULL); + Close(); + return bStat>0; +}; + +bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) +{ + 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(); + return bStat>0; +}; + +bool CDROM_Interface_Ioctl::ReadSectors(void* 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; + + 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; + + bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in), + inPtr, num*RAW_SECTOR_SIZE, &byteCount,NULL); + + if (!raw) { + char* source = inPtr; + source+=16; // jump 16 bytes + char* outPtr = (char*)buffer; + for (unsigned long i=0; i0); +} + +bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) +{ + if (GetDriveType(path)==DRIVE_CDROM) { + char letter [3] = { 0, ':', 0 }; + letter[0] = path[0]; + strcpy(pathname,"\\\\.\\"); + strcat(pathname,letter); + if (Open()) { + Close(); + return true; + }; + } + return false; +} + +bool CDROM_Interface_Ioctl::Open(void) +{ + hIOCTL = CreateFile(pathname, // drive to open + GENERIC_READ, // read access + FILE_SHARE_READ | // share mode + FILE_SHARE_WRITE, + NULL, // default security attributes + OPEN_EXISTING, // disposition + 0, // file attributes + NULL); // do not copy file attributes + return (hIOCTL!=INVALID_HANDLE_VALUE); +}; + +void CDROM_Interface_Ioctl::Close(void) +{ + CloseHandle(hIOCTL); +}; + +#endif diff --git a/src/dos/dev_con.h b/src/dos/dev_con.h index c262736..6059a86 100644 --- a/src/dos/dev_con.h +++ b/src/dos/dev_con.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 @@ -120,7 +120,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { ansi.esc=true; count++; if(!ansiwarned) { - LOG_WARN("ANSI sequences detected. enabling ansi support"); /* maybe LOG_MSG */ + LOG(LOG_IOCTL,"ANSI sequences detected. enabling ansi support"); /* maybe LOG_MSG */ ansiwarned=true; } continue; @@ -143,7 +143,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { case 'D':/* scrolling DOWN*/ case 'M':/* scrolling UP*/ default: - LOG_DEBUG("ANSI: unknown char %c after a esc",data[count]); /*prob () */ + LOG(LOG_IOCTL,"ANSI: unknown char %c after a esc",data[count]); /*prob () */ ClearAnsi(); break; } @@ -179,13 +179,13 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { ansi.attr|=0x8; break; case 4: /* underline */ - LOG_DEBUG("ANSI:no support for underline yet"); + LOG(LOG_IOCTL,"ANSI:no support for underline yet"); break; case 5: /* blinking */ - LOG_DEBUG("ANSI:no support for blinking yet"); + LOG(LOG_IOCTL,"ANSI:no support for blinking yet"); break; case 7: /* reverse */ - LOG_DEBUG("ANSI:no support for reverse yet"); + LOG(LOG_IOCTL,"ANSI:no support for reverse yet"); break; case 30: /* fg color black */ ansi.attr&=0xf8; @@ -284,7 +284,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { 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_DEBUG("ANSI: esc[%dJ called : not supported",ansi.data[0]); + LOG(LOG_IOCTL,"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); @@ -293,7 +293,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { break; case 'h': /* set MODE (if code =7 enable linewrap) */ case 'I': /*RESET MODE */ - LOG_DEBUG("ANSI: set/reset mode called(not supported)"); + LOG(LOG_IOCTL,"ANSI: set/reset mode called(not supported)"); ClearAnsi(); break; case 'D': /*Cursor Backward */ @@ -320,7 +320,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { case 'p':/* reassign keys (needs strings) */ case 'i':/* printer stuff */ default: - LOG_DEBUG("ANSI: unhandled char %c in esc[",data[count]); + LOG(LOG_IOCTL,"ANSI: unhandled char %c in esc[",data[count]); ClearAnsi(); break; } diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index 4b804a5..97db2f7 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.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 @@ -27,12 +27,15 @@ #include "callback.h" #include "regs.h" #include "dos_inc.h" +#include "setup.h" +#include "cpu.h" DOS_Block dos; DOS_InfoBlock dos_infoblock; Bit8u dos_copybuf[0x10000]; -static Bitu call_20,call_21,call_27,call_28,call_29; +static Bitu call_20,call_21,call_25,call_26,call_27,call_28,call_29; +static Bitu call_casemap; void DOS_SetError(Bit16u code) { dos.errorcode=code; @@ -130,8 +133,8 @@ static Bitu DOS_21Handler(void) { break; }; case 0x0b: /* Get STDIN Status */ - if (DOS_GetSTDINStatus()) reg_al=0xff; - else reg_al=0; + if (!DOS_GetSTDINStatus()) {reg_al=0x00;} + else {reg_al=0xFF;} break; case 0x0c: /* Flush Buffer and read STDIN call */ { @@ -169,7 +172,7 @@ static Bitu DOS_21Handler(void) { }else{ reg_al=0xff; } - LOG_DEBUG("DOS:0x0f FCB-fileopen used, result:al=%d",reg_al); + LOG(LOG_FCB,"DOS:0x0f FCB-fileopen used, result:al=%d",reg_al); break; case 0x10: /* Close File using FCB */ if(DOS_FCBClose(SegValue(ds),reg_dx)){ @@ -177,7 +180,7 @@ static Bitu DOS_21Handler(void) { }else{ reg_al=0xff; } - LOG_DEBUG("DOS:0x10 FCB-fileclose used, result:al=%d",reg_al); + LOG(LOG_FCB,"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)){ @@ -185,7 +188,7 @@ static Bitu DOS_21Handler(void) { }else{ reg_al=0xff; } - LOG_DEBUG("DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al); + LOG(LOG_FCB,"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)){ @@ -193,7 +196,7 @@ static Bitu DOS_21Handler(void) { }else{ reg_al=0xff; } - LOG_DEBUG("DOS:0x12 FCB-FindNext used, result:al=%d",reg_al); + LOG(LOG_FCB,"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; @@ -201,16 +204,16 @@ static Bitu DOS_21Handler(void) { break; case 0x14: /* Sequential read from FCB */ reg_al = DOS_FCBRead(SegValue(ds),reg_dx,0); - LOG_DEBUG("DOS:0x14 FCB-Read used, result:al=%d",reg_al); + LOG(LOG_FCB,"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_DEBUG("DOS:0x15 FCB-Write used, result:al=%d",reg_al); + LOG(LOG_FCB,"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_DEBUG("DOS:0x16 FCB-Create used, result:al=%d",reg_al); + LOG(LOG_FCB,"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; @@ -224,11 +227,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_DEBUG("DOS:0x21 FCB-Random read used, result:al=%d",reg_al); + LOG(LOG_FCB,"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_DEBUG("DOS:0x28 FCB-Random write used, result:al=%d",reg_al); + LOG(LOG_FCB,"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; @@ -239,11 +242,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_DEBUG("DOS:0x27 FCB-Random(block) read used, result:al=%d",reg_al); + LOG(LOG_FCB,"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_DEBUG("DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al); + LOG(LOG_FCB,"DOS:0x28 FCB-Random(block) write used, result:al=%d",reg_al); break; case 0x29: /* Parse filename into FCB */ { Bit8u difference; @@ -252,7 +255,7 @@ static Bitu DOS_21Handler(void) { reg_al=FCB_Parsename(SegValue(es),reg_di,reg_al ,string, &difference); reg_si+=difference; } - LOG_DEBUG("DOS:29:FCB Parse Filename, result:al=%d",reg_al); + LOG(LOG_FCB,"DOS:29:FCB Parse Filename, result:al=%d",reg_al); break; case 0x19: /* Get current default drive */ reg_al=DOS_GetDefaultDrive(); @@ -264,11 +267,6 @@ static Bitu DOS_21Handler(void) { psp.SetDTA(dos.dta); } break; - case 0x1f: /* Get drive parameter block for default drive */ - - case 0x32: /* Get drive parameter block for specific drive */ - E_Exit("DOS:Unhandled call %02X",reg_ah); - break; /* TODO maybe but hardly think a game needs this */ case 0x25: /* Set Interrupt Vector */ RealSetVec(reg_al,RealMakeSeg(ds,reg_dx)); break; @@ -303,11 +301,11 @@ static Bitu DOS_21Handler(void) { reg_ch=(Bit8u)(seconds/3600); reg_cl=(Bit8u)((seconds % 3600)/60); reg_dh=(Bit8u)(seconds % 60); - reg_dl=(Bit8u)((ticks % 20)*5); /* 0-19 ->0-95 */ + reg_dl=(Bit8u)(((ticks * 10) % 182)*100)/182; } break; case 0x2d: /* Set System Time */ - LOG_DEBUG("DOS:Set System Time not supported"); + LOG(LOG_ERROR,"DOS:Set System Time not supported"); reg_al=0; /* Noone is changing system time */ break; case 0x2e: /* Set Verify flag */ @@ -385,18 +383,29 @@ static Bitu DOS_21Handler(void) { case 3: reg_al=0;break; }; - LOG_DEBUG("DOS:0x37:Call for not supported switchchar"); + LOG(LOG_ERROR|LOG_MISC,"DOS:0x37:Call for not supported switchchar"); break; case 0x38: /* Set Country Code */ - LOG_DEBUG("DOS:Setting country code not supported"); - CALLBACK_SCF(true); - break; if (reg_al==0) { /* Get country specidic information */ - + PhysPt pt = SegPhys(ds)+reg_dx; + mem_writew(pt ,0x00); // USA + mem_writeb(pt+ 2, '$'); mem_writeb(pt+ 3,0x00); + mem_writeb(pt+ 7, '.'); mem_writeb(pt+ 8,0x00); + mem_writeb(pt+ 9, '.'); mem_writeb(pt+10,0x00); + mem_writeb(pt+11, '.'); mem_writeb(pt+12,0x00); + mem_writeb(pt+13, '.'); mem_writeb(pt+14,0x00); + mem_writeb(pt+15,0x01); // currency format + mem_writeb(pt+16,0x02); // num digits + mem_writeb(pt+17,0x00); // time format + mem_writed(pt+18,CALLBACK_RealPointer(call_casemap)); + mem_writew(pt+22,0x00); // data list seperator + reg_bx = 0x01; + CALLBACK_SCF(false); + break; } else { /* Set country code */ - - + LOG(LOG_ERROR|LOG_MISC,"DOS:Setting country code not supported"); } + CALLBACK_SCF(true); break; case 0x39: /* MKDIR Create directory */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); @@ -514,7 +523,7 @@ static Bitu DOS_21Handler(void) { } break; case 0x01: /* Set */ - LOG_DEBUG("DOS:Set File Attributes for %s not supported",name1); + LOG(LOG_ERROR|LOG_MISC,"DOS:Set File Attributes for %s not supported",name1); CALLBACK_SCF(false); break; default: @@ -591,7 +600,7 @@ static Bitu DOS_21Handler(void) { case 0x4b: /* EXEC Load and/or execute program */ { MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); - LOG_DEBUG("Execute %s %d",name1,reg_al); + LOG(LOG_ERROR|LOG_MISC,"Execute %s %d",name1,reg_al); if (!DOS_Execute(name1,SegPhys(es)+reg_bx,reg_al)) { reg_ax=dos.errorcode; CALLBACK_SCF(true); @@ -645,7 +654,7 @@ static Bitu DOS_21Handler(void) { RealPt addr=dos_infoblock.GetPointer(); SegSet16(es,RealSeg(addr)); reg_bx=RealOff(addr); - LOG_DEBUG("Call is made for list of lists - let's hope for the best"); + LOG(LOG_MISC,"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 :) @@ -679,19 +688,27 @@ static Bitu DOS_21Handler(void) { } else { reg_cx=0; reg_dx=0; - LOG_DEBUG("DOS:57:Setting File Date is faked",reg_ah); + LOG(LOG_ERROR|LOG_MISC,"DOS:57:Setting File Date is faked",reg_ah); } break; case 0x58: /* Get/Set Memory allocation strategy */ switch (reg_al) { - case 0: /* Get Strategy */ + case 0: /* Get Strategy */ reg_ax=DOS_GetMemAllocStrategy(); break; - case 1: /* Set Strategy */ + case 1: /* Set Strategy */ DOS_SetMemAllocStrategy(reg_bx); break; + case 2: /* Get UMB Link Status */ + reg_ax=1; // no UMB support + CALLBACK_SCF(true); + break; + case 3: /* Set UMB Link Status */ + reg_ax=1; // failure, no support + CALLBACK_SCF(true); + break; default: - LOG_DEBUG("DOS:58:Not Supported Set//Get memory allocation call %X",reg_al); + LOG(LOG_ERROR|LOG_MISC,"DOS:58:Not Supported Set//Get memory allocation call %X",reg_al); } break; case 0x59: /* Get Extended error information */ @@ -733,12 +750,6 @@ static Bitu DOS_21Handler(void) { } break; } - - case 0x5c: /* FLOCK File region locking */ - case 0x5e: /* More Network Functions */ - case 0x5f: /* And Even More Network Functions */ - E_Exit("DOS:Unhandled call %02X",reg_ah); - break; case 0x60: /* Canonicalize filename or path */ MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); if (DOS_Canonicalize(name1,name2)) { @@ -758,7 +769,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_DEBUG("DOS:65:Extended country information call"); + LOG(LOG_ERROR|LOG_MISC,"DOS:65:Extended country information call"); PhysPt data=SegPhys(es)+reg_di; switch (reg_al) { case 1: @@ -769,34 +780,48 @@ static Bitu DOS_21Handler(void) { reg_cx=4; CALLBACK_SCF(false); break; - default: + case 2: // Get pointer to uppercase table + case 3: // Get pointer to lowercase table + case 4: // Get pointer to filename uppercase table + case 5: // Get pointer to filename terminator table + case 6: // Get pointer to collating sequence table + case 7: // Get pointer to double byte char set table + mem_writew(data ,0x0000); // We dont have this table... + mem_writew(data+2,0x0000); // End of table + reg_cx=4; + CALLBACK_SCF(false); + break; + default: E_Exit("DOS:0x65:Unhandled country information call %2X",reg_al); }; break; } case 0x66: /* Get/Set global code page table */ if (reg_al==1) { - LOG_DEBUG("Getting global code page table"); + LOG(LOG_ERROR|LOG_MISC,"Getting global code page table"); reg_bx=reg_dx=437; CALLBACK_SCF(false); break; } - LOG_ERROR("DOS:Setting code page table is not supported"); + LOG(LOG_DOSMISC,"DOS:Setting code page table is not supported"); break; - case 0x67: /* Set handle countr */ + case 0x67: /* Set handle count */ /* Weird call to increase amount of file handles needs to allocate memory if >20 */ - LOG_DEBUG("DOS:67:Set Handle Count not working"); - CALLBACK_SCF(false); - break; + { + DOS_PSP psp(dos.psp); + psp.SetNumFiles(reg_bx); + CALLBACK_SCF(false); + break; + }; case 0x69: /* Get/Set disk serial number */ { switch(reg_al) { case 0x00: /* Get */ - LOG_DEBUG("DOS:Get Disk serial number"); + LOG(LOG_ERROR|LOG_MISC,"DOS:Get Disk serial number"); CALLBACK_SCF(true); break; case 0x01: - LOG_DEBUG("DOS:Set Disk serial number"); + LOG(LOG_ERROR|LOG_MISC,"DOS:Set Disk serial number"); default: E_Exit("DOS:Illegal Get Serial Number call %2X",reg_al); } @@ -808,7 +833,7 @@ static Bitu DOS_21Handler(void) { case 0x71: /* Unknown probably 4dos detection */ reg_ax=0x7100; CALLBACK_SCF(true); - LOG_WARN("DOS:Windows long file name support call %2X",reg_al); + LOG(LOG_DOSMISC,"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 */ @@ -821,9 +846,15 @@ static Bitu DOS_21Handler(void) { case 0x6b: /* NULL Function */ case 0x61: /* UNUSED */ case 0xEF: /* Used in Ancient Art Of War CGA */ - case 0x5d: /* Network Functions */ - default: - LOG_DEBUG("DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al); + case 0x5d: /* Network Functions ||HMMM seems to critical error info and return 1!! Maybe implement it.??*/ + /* al=06 clears cf and leaves al=6 and returns crit error flag location*/ + case 0x1f: /* Get drive parameter block for default drive */ + case 0x32: /* Get drive parameter block for specific drive */ + case 0x5c: /* FLOCK File region locking */ + case 0x5e: /* More Network Functions */ + case 0x5f: /* And Even More Network Functions */ + default: + LOG(LOG_ERROR|LOG_MISC,"DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al); reg_al=0x00; /* default value */ break; }; @@ -847,16 +878,52 @@ static Bitu DOS_27Handler(void) if (DOS_ResizeMemory(dos.psp,¶)) DOS_Terminate(true); return CBRET_NONE; } +static Bitu DOS_25Handler(void) { + flags.type=t_UNKNOWN; + if(Drives[reg_al]==0){ + reg_ax=0x8002; + flags.cf=true; + }else{ + flags.cf=false; + reg_ax=0; + if((reg_cx != 1) ||(reg_dx != 1)) + LOG(LOG_DOSMISC,"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; + if(Drives[reg_al]==0){ + reg_ax=0x8002; + flags.cf=true; + }else{ + flags.cf=false; + reg_ax=0; + } + return CBRET_NONE; +} static Bitu DOS_28Handler(void) { return CBRET_NONE; } static Bitu DOS_29Handler(void) { - LOG_DEBUG("int 29 called"); + LOG(LOG_ERROR|LOG_MISC,"int 29 called"); return CBRET_NONE; } +static Bitu DOS_CaseMapFunc(void) { + //LOG(LOG_ERROR|LOG_MISC,"Case map routine called : %c",reg_al); + return CBRET_NONE; +}; + +void DOS_ShutDown(Section* sec) +{ + for (Bit16u i=0;itm_year+1900; Bit32u ticks=(Bit32u)((loctime->tm_hour*3600+loctime->tm_min*60+loctime->tm_sec)*18.2); mem_writed(BIOS_TIMER,ticks); + + /* shutdown function */ + sec->AddDestroyFunction(&DOS_ShutDown); + + /* case map routine INT 0x21 0x38 */ + call_casemap = CALLBACK_Allocate(); + CALLBACK_Setup(call_casemap,DOS_CaseMapFunc,CB_RETF); } + diff --git a/src/dos/dos_classes.cpp b/src/dos/dos_classes.cpp index 6025b28..00b7cc7 100644 --- a/src/dos/dos_classes.cpp +++ b/src/dos/dos_classes.cpp @@ -145,6 +145,16 @@ Bit16u DOS_PSP::FindFreeFileEntry(void) return 0xff; }; +Bit16u DOS_PSP::FindEntryByHandle(Bit8u handle) +{ + PhysPt files=Real2Phys(sGet(sPSP,file_table)); + Bit16u max = sGet(sPSP,max_files); + for (Bit16u i=0;i20) { + // Allocate needed paragraphs + Bit16u para = (fileNum/16)+((fileNum%16)>0); + RealPt data = RealMake(DOS_GetMemory(para),0); + sSave(sPSP,file_table,data); + sSave(sPSP,max_files,fileNum); + Bit16u i; + for (i=0; i<20; i++) SetFileHandle(i,sGet(sPSP,files[i])); + for (i=20; i=MAXENV - ENV_KEEPFREE) { DOS_SetError(DOSERR_ENVIRONMENT_INVALID); @@ -173,20 +176,28 @@ bool DOS_NewPSP(Bit16u segment, Bit16u size) static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { /* Fix the PSP for psp and environment MCB's */ - MCB * pspmcb=(MCB *)HostMake(pspseg-1,0); - pspmcb->psp_segment=pspseg; - MCB * envmcb=(MCB *)HostMake(envseg-1,0); - envmcb->psp_segment=pspseg; + DOS_MCB mcb((Bit16u)(pspseg-1)); + mcb.SetPSPSeg(pspseg); + mcb.SetPt((Bit16u)(envseg-1)); + mcb.SetPSPSeg(pspseg); DOS_PSP psp(pspseg); psp.MakeNew(memsize); psp.SetEnvironment(envseg); - psp.SetFileHandle(STDIN ,DOS_FindDevice("CON")); - psp.SetFileHandle(STDOUT,DOS_FindDevice("CON")); - psp.SetFileHandle(STDERR,DOS_FindDevice("CON")); - psp.SetFileHandle(STDAUX,DOS_FindDevice("CON")); - psp.SetFileHandle(STDNUL,DOS_FindDevice("CON")); - psp.SetFileHandle(STDPRN,DOS_FindDevice("CON")); + /* Copy file handles */ + if (DOS_PSP::rootpsp!=dos.psp) { + // TODO: Improve this + // If prog wasnt started from commandline copy file table (California Games 2) + DOS_PSP oldpsp(dos.psp); + psp.CopyFileTable(&oldpsp); + } else { + psp.SetFileHandle(STDIN ,DOS_FindDevice("CON")); + psp.SetFileHandle(STDOUT,DOS_FindDevice("CON")); + psp.SetFileHandle(STDERR,DOS_FindDevice("CON")); + psp.SetFileHandle(STDAUX,DOS_FindDevice("CON")); + psp.SetFileHandle(STDNUL,DOS_FindDevice("CON")); + psp.SetFileHandle(STDPRN,DOS_FindDevice("CON")); + } /* Save old DTA in psp */ psp.SetDTA(dos.dta); /* Setup the DTA */ @@ -229,8 +240,14 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true; else { headersize=head.headersize*16; - imagesize=(head.pages)*512-headersize; - if (head.extrabytes) imagesize-=(512-head.extrabytes); + if (head.extrabytes) { + imagesize = (head.pages-1)*512-headersize; + imagesize += head.extrabytes % 512; + } else + imagesize = head.pages*512-headersize; + + // always load st least 512 Bytes (dos cache/dos bug?) + if (imagesize+headersize<512) imagesize = 512-headersize; } if (flags!=OVERLAY) { /* Create an environment block */ @@ -271,12 +288,12 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { pos=headersize;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET); while (imagesize>0x7FFF) { readsize=0x8000;DOS_ReadFile(fhandle,loadaddress,&readsize); - if (readsize!=0x8000) LOG_WARN("Illegal header"); + if (readsize!=0x8000) LOG(LOG_EXEC,"Illegal header"); loadaddress+=0x8000;imagesize-=0x8000; } if (imagesize>0) { readsize=(Bit16u)imagesize;DOS_ReadFile(fhandle,loadaddress,&readsize); - if (readsize!=imagesize) LOG_WARN("Illegal header"); + if (readsize!=imagesize) LOG(LOG_EXEC,"Illegal header"); } /* Relocate the exe image */ Bit16u relocate; @@ -340,8 +357,8 @@ bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(csip)); mem_writew(SegPhys(ss)+reg_sp+4,0x200); /* Setup the rest of the registers */ - reg_ax=0; - reg_cx=reg_dx=reg_bx=reg_si=reg_di=reg_bp=0; + reg_ax=0;reg_si=0x100; + reg_cx=reg_dx=reg_bx=reg_di=reg_bp=0; SegSet16(ds,pspseg);SegSet16(es,pspseg); #if C_DEBUG /* Started from debug.com, then set breakpoint at start */ diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index 3dc25fa..512f0bc 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.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,6 +22,7 @@ #include #include "dosbox.h" +#include "bios.h" #include "mem.h" #include "cpu.h" #include "dos_inc.h" @@ -289,7 +290,7 @@ bool DOS_CloseFile(Bit16u entry) { //TODO Figure this out with devices :) DOS_PSP psp(dos.psp); - psp.SetFileHandle(entry,0xff); + if (entry>STDPRN) psp.SetFileHandle(entry,0xff); /* Devices won't allow themselves to be closed or killed */ if (Files[handle]->Close()) { @@ -332,7 +333,8 @@ 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_DEBUG("Special file open command %X file %s",flags,name); + 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; DOS_PSP psp(dos.psp); Bit8u handle=DOS_FindDevice((char *)name); @@ -342,6 +344,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) { } else { /* First check if the name is correct */ if (!DOS_MakeName(name,fullname,&drive)) return false; + /* Check for a free file handle */ for (i=0;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); + return false; + } + fcb.FileOpen((Bit8u)handle); + return true; + } + } + if (!DOS_OpenFile(shortname,2,&handle)) return false; fcb.FileOpen((Bit8u)handle); return true; @@ -712,7 +736,17 @@ Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u recno) Bit32u size;Bit16u date,time; fcb.GetSizeDateTime(size,date,time); if (pos+towrite>size) size=pos+towrite; - //TODO Set time to current time? + //time doesn't keep track of endofday + date = DOS_PackDate(dos.date.year,dos.date.month,dos.date.day); + Bit32u ticks = mem_readd(BIOS_TIMER); + Bit32u seconds = (ticks*10)/182; + Bit16u hour = (Bit16u)(seconds/3600); + Bit16u min = (Bit16u)((seconds % 3600)/60); + Bit16u sec = (Bit16u)(seconds % 60); + time = DOS_PackTime(hour,min,sec); + Bit8u temp=RealHandle(fhandle); + Files[temp]->time=time; + Files[temp]->date=date; fcb.SetSizeDateTime(size,date,time); if (++cur_rec>127) { cur_block++;cur_rec=0; } fcb.SetRecord(cur_block,cur_rec); diff --git a/src/dos/dos_ioctl.cpp b/src/dos/dos_ioctl.cpp index 2a4a50a..57d4494 100644 --- a/src/dos/dos_ioctl.cpp +++ b/src/dos/dos_ioctl.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 @@ -45,7 +45,7 @@ bool DOS_IOCTL(void) { reg_dx=Files[handle]->GetInformation(); return true; case 0x07: /* Get Output Status */ - LOG_DEBUG("DOS:IOCTL:07:Fakes output status is ready for handle %d",handle); + LOG(LOG_IOCTL,"DOS:IOCTL:07:Fakes output status is ready for handle %d",handle); reg_al=0xff; return true; case 0x08: /* Check if block device removable */ @@ -71,7 +71,7 @@ bool DOS_IOCTL(void) { mem_writeb(ptr+6,0x00); // media type (00=other type) break; default : - 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; @@ -94,7 +94,7 @@ bool DOS_IOCTL(void) { break; } default: - 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_memory.cpp b/src/dos/dos_memory.cpp index 0fb72a3..2feba96 100644 --- a/src/dos/dos_memory.cpp +++ b/src/dos/dos_memory.cpp @@ -27,33 +27,32 @@ static Bit16u memAllocStrategy = 0x00; static void DOS_CompressMemory(void) { - MCB * pmcb;MCB * pmcbnext; - Bit16u mcb_segment; - mcb_segment=dos.firstMCB; - pmcb=(MCB *)HostMake(mcb_segment,0); - while (pmcb->type!=0x5a) { - pmcbnext=pmcbnext=(MCB *)HostMake(mcb_segment+pmcb->size+1,0); - if ((pmcb->psp_segment==0) && (pmcbnext->psp_segment==0)) { - pmcb->size+=pmcbnext->size+1; - pmcb->type=pmcbnext->type; + Bit16u mcb_segment=dos.firstMCB; + DOS_MCB mcb(mcb_segment); + DOS_MCB mcb_next(0); + + while (mcb.GetType()!=0x5a) { + mcb_next.SetPt((Bit16u)(mcb_segment+mcb.GetSize()+1)); + if ((mcb.GetPSPSeg()==0) && (mcb_next.GetPSPSeg()==0)) { + mcb.SetSize(mcb.GetSize()+mcb_next.GetSize()+1); + mcb.SetType(mcb_next.GetType()); } else { - mcb_segment+=pmcb->size+1; - pmcb=(MCB *)HostMake(mcb_segment,0); + mcb_segment+=mcb.GetSize()+1; + mcb.SetPt(mcb_segment); } } } void DOS_FreeProcessMemory(Bit16u pspseg) { - MCB * pmcb; Bit16u mcb_segment=dos.firstMCB; - pmcb=(MCB *)HostMake(mcb_segment,0); + DOS_MCB mcb(mcb_segment); while (true) { - if (pmcb->psp_segment==pspseg) { - pmcb->psp_segment=MCB_FREE; + if (mcb.GetPSPSeg()==pspseg) { + mcb.SetPSPSeg(MCB_FREE); } - mcb_segment+=pmcb->size+1; - if (pmcb->type==0x5a) break; - pmcb=(MCB *)HostMake(mcb_segment,0); + if (mcb.GetType()==0x5a) break; + mcb_segment+=mcb.GetSize()+1; + mcb.SetPt(mcb_segment); } DOS_CompressMemory(); }; @@ -69,60 +68,61 @@ void DOS_SetMemAllocStrategy(Bit16u strat) }; bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { - MCB * pmcb;MCB * pmcbnext; - Bit16u bigsize=0;Bit16u mcb_segment; - bool stop=false;mcb_segment=dos.firstMCB; DOS_CompressMemory(); + Bit16u bigsize=0;Bit16u mcb_segment=dos.firstMCB; + DOS_MCB mcb(0); + DOS_MCB mcb_next(0); + bool stop=false; while(!stop) { - pmcb=(MCB *)HostMake(mcb_segment,0); - if (pmcb->psp_segment==0) { + mcb.SetPt(mcb_segment); + if (mcb.GetPSPSeg()==0) { /* Check for enough free memory in current block */ - if (pmcb->size<(*blocks)) { - if (bigsizesize) { - bigsize=pmcb->size; + Bit16u block_size=mcb.GetSize(); + if (block_size<(*blocks)) { + if (bigsizesize==*blocks) { - pmcb->psp_segment=dos.psp; + } else if (block_size==*blocks) { + mcb.SetPSPSeg(dos.psp); *segment=mcb_segment+1; return true; } else { // TODO: Strategy "1": Best matching block /* If so allocate it */ - if ((memAllocStrategy & 0x03)==0) { - pmcbnext=(MCB *)HostMake(mcb_segment+*blocks+1,0); - pmcbnext->psp_segment=MCB_FREE; - pmcbnext->type=pmcb->type; - pmcbnext->size=pmcb->size-*blocks-1; - pmcb->size=*blocks; - pmcb->type=0x4D; - pmcb->psp_segment=dos.psp; + if ((memAllocStrategy & 0x03)==0) { + mcb_next.SetPt((Bit16u)(mcb_segment+*blocks+1)); + mcb_next.SetPSPSeg(MCB_FREE); + mcb_next.SetType(mcb.GetType()); + mcb_next.SetSize(block_size-*blocks-1); + mcb.SetSize(*blocks); + mcb.SetType(0x4d); + mcb.SetPSPSeg(dos.psp); //TODO Filename *segment=mcb_segment+1; return true; } else { // * Last Block * // New created block - *segment = mcb_segment+1+pmcb->size-*blocks; - pmcbnext=(MCB *)HostMake(*segment-1,0); - pmcbnext->size = *blocks; - pmcbnext->type = pmcb->type; - pmcbnext->psp_segment = dos.psp; + *segment = mcb_segment+1+block_size - *blocks; + mcb_next.SetPt((Bit16u)(*segment-1)); + mcb_next.SetSize(*blocks); + mcb_next.SetType(mcb.GetType()); + mcb_next.SetPSPSeg(dos.psp); // Old Block - pmcb->size = pmcb->size-*blocks-1; - pmcb->psp_segment = MCB_FREE; - pmcb->type = 0x4D; + mcb.SetSize(block_size-*blocks-1); + mcb.SetPSPSeg(MCB_FREE); + mcb.SetType(0x4D); return true; }; } } /* Onward to the next MCB if there is one */ - if (pmcb->type==0x5a) { + if (mcb.GetType()==0x5a) { *blocks=bigsize; DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); return false; } - mcb_segment+=pmcb->size+1; + mcb_segment+=mcb.GetSize()+1; } return false; } @@ -130,32 +130,31 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) { bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) { DOS_CompressMemory(); - MCB * pmcb,* pmcbnext,* pmcbnew; - pmcb=(MCB *)HostMake(segment-1,0); - pmcbnext=(MCB *)HostMake(segment+pmcb->size,0); - Bit16u total=pmcb->size; - if (pmcb->type!=0x5a) { - if (pmcbnext->psp_segment==MCB_FREE) { - total+=pmcbnext->size+1; + DOS_MCB mcb(segment-1); + Bit16u total=mcb.GetSize(); + DOS_MCB mcb_next(segment+total); + if (mcb.GetType()!=0x5a) { + if (mcb_next.GetPSPSeg()==MCB_FREE) { + total+=mcb_next.GetSize()+1; } - }; + } if (*blockstype!=0x5a) { - pmcb->type=pmcbnext->type; + if (mcb.GetType()!=0x5a) { + mcb.SetType(mcb_next.GetType()); } - pmcb->size=*blocks; - pmcbnew=(MCB *)HostMake(segment+*blocks,0); - pmcbnew->size=total-*blocks-1; - pmcbnew->type=pmcb->type; - pmcbnew->psp_segment=MCB_FREE; - pmcb->type=0x4D; + mcb.SetSize(*blocks); + mcb_next.SetPt((Bit16u)(segment+*blocks)); + mcb_next.SetSize(total-*blocks-1); + mcb_next.SetType(mcb.GetType()); + mcb_next.SetPSPSeg(MCB_FREE); + mcb.SetType(0x4d); return true; } if (*blocks==total) { - if (pmcb->type!=0x5a) { - pmcb->type=pmcbnext->type; + if (mcb.GetType()!=0x5a) { + mcb.SetType(mcb_next.GetType()); } - pmcb->size=*blocks; + mcb.SetSize(*blocks); return true; } *blocks=total; @@ -166,9 +165,8 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) { bool DOS_FreeMemory(Bit16u segment) { //TODO Check if allowed to free this segment - MCB * pmcb; - pmcb=(MCB *)HostMake(segment-1,0); - pmcb->psp_segment=MCB_FREE; + DOS_MCB mcb(segment-1); + mcb.SetPSPSeg(MCB_FREE); DOS_CompressMemory(); return true; } @@ -177,10 +175,10 @@ bool DOS_FreeMemory(Bit16u segment) { void DOS_SetupMemory(void) { - MCB * mcb=(MCB *) HostMake(MEM_START,0); - mcb->psp_segment=MCB_FREE; //Free - mcb->size=0x9FFE - MEM_START; - mcb->type=0x5a; //Last Block + DOS_MCB mcb((Bit16u)MEM_START); + mcb.SetPSPSeg(MCB_FREE); //Free + mcb.SetSize(0x9FFE - MEM_START); + mcb.SetType(0x5a); //Last Block dos.firstMCB=MEM_START; dos_infoblock.SetFirstMCB(MEM_START); } diff --git a/src/dos/dos_misc.cpp b/src/dos/dos_misc.cpp index cabfd2a..e054215 100644 --- a/src/dos/dos_misc.cpp +++ b/src/dos/dos_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 @@ -44,7 +44,7 @@ static Bitu INT2F_Handler(void) { if ((*loop_multiplex->handler)()) return CBRET_NONE; loop_multiplex=loop_multiplex->next; } - LOG_WARN("DOS:Multiplex Unhandled call %4X",reg_ax); + LOG(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 new file mode 100644 index 0000000..e4e1383 --- /dev/null +++ b/src/dos/dos_mscdex.cpp @@ -0,0 +1,844 @@ +/* + * 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 "cpu.h" +#include "callback.h" +#include "dos_system.h" +#include "dos_inc.h" +#include "setup.h" + +#include "cdrom.h" + +#define MSCDEX_VERSION_HIGH 2 +#define MSCDEX_VERSION_LOW 23 +#define MSCDEX_MAX_DRIVES 5 + +// Error Codes +#define MSCDEX_ERROR_UNKNOWN_DRIVE 15 +#define MSCDEX_ERROR_DRIVE_NOT_READY 21 + +// Request Status +#define REQUEST_STATUS_DONE 0x0100 +#define REQUEST_STATUS_ERROR 0x8000 + +// Use cdrom Interface +int useCdromInterface = CDROM_USE_SDL; +int forceCD = -1; + +static Bitu MSCDEX_Strategy_Handler(void); +static Bitu MSCDEX_Interrupt_Handler(void); + +class DOS_DeviceHeader:public MemStruct +{ +public: + DOS_DeviceHeader(PhysPt ptr) { pt = ptr; }; + + void SetNextDeviceHeader (RealPt ptr) { sSave(sDeviceHeader,nextDeviceHeader,ptr); }; + RealPt GetNextDeviceHeader (void) { return sGet(sDeviceHeader,nextDeviceHeader); }; + void SetAttribute (Bit16u atr) { sSave(sDeviceHeader,devAttributes,atr); }; + void SetDriveLetter (Bit8u letter) { sSave(sDeviceHeader,driveLetter,letter); }; + void SetNumSubUnits (Bit8u num) { sSave(sDeviceHeader,numSubUnits,num); }; + Bit8u GetNumSubUnits (void) { return sGet(sDeviceHeader,numSubUnits); }; + void SetName (char* _name) { MEM_BlockWrite(pt+offsetof(sDeviceHeader,name),_name,8); }; + void SetInterrupt (Bit16u ofs) { sSave(sDeviceHeader,interrupt,ofs); }; + void SetStrategy (Bit16u ofs) { sSave(sDeviceHeader,strategy,ofs); }; + +public: + #pragma pack(1) + struct sDeviceHeader{ + RealPt nextDeviceHeader; + Bit16u devAttributes; + Bit16u strategy; + Bit16u interrupt; + Bit8u name[8]; + Bit16u wReserved; + Bit8u driveLetter; + Bit8u numSubUnits; + } TDeviceHeader; + #pragma pack() +}; + +class CMscdex +{ +public: + CMscdex (void); + ~CMscdex (void); + + Bit16u GetVersion (void) { return (MSCDEX_VERSION_HIGH<<8)+MSCDEX_VERSION_LOW; }; + Bit16u GetNumDrives (void) { return numDrives; }; + Bit16u GetFirstDrive (void) { return dinfo[0].drive; }; + Bit8u GetSubUnit (Bit16u _drive); + bool GetUPC (Bit8u subUnit, Bit8u& attr, char* upc); + + bool PlayAudioSector (Bit8u subUnit, Bit32u start, Bit32u length); + bool PlayAudioMSF (Bit8u subUnit, Bit32u start, Bit32u length); + bool StopAudio (Bit8u subUnit); + bool GetAudioStatus (Bit8u subUnit, bool& playing, bool& pause, TMSF& start, TMSF& end); + + bool GetSubChannelData (Bit8u subUnit, Bit8u& attr, Bit8u& track, Bit8u &index, TMSF& rel, TMSF& abs); + + 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 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); + bool SendDriverRequest (Bit16u drive, PhysPt data); + bool IsValidDrive (Bit16u drive); + bool GetCDInfo (Bit8u subUnit, Bit8u& tr1, Bit8u& tr2, TMSF& leadOut); + Bit32u GetVolumeSize (Bit8u subUnit); + bool GetTrackInfo (Bit8u subUnit, Bit8u track, Bit8u& attr, TMSF& start); + Bit16u GetStatusWord (Bit8u subUnit); + bool GetCurrentPos (Bit8u subUnit, TMSF& pos); + Bit32u GetDeviceStatus (Bit8u subUnit); + bool GetMediaStatus (Bit8u subUnit, Bit8u& status); + bool LoadUnloadMedia (Bit8u subUnit, bool unload); + bool ResumeAudio (Bit8u subUnit); + bool GetMediaStatus (Bit8u subUnit, bool& media, bool& changed, bool& trayOpen); + +private: + + Bit16u numDrives; + + typedef struct SDriveInfo { + Bit8u drive; // drive letter in dosbox + Bit8u physDrive; // drive letter in system + bool audioPlay; // audio playing active + bool audioPaused; // audio playing paused + Bit32u audioStart; // StartLoc for resume + Bit32u audioEnd; // EndLoc for resume + bool locked; // drive locked ? + bool lastResult; // last operation success ? + Bit32u volumeSize; // for media change + } TDriveInfo; + + TDriveInfo dinfo[MSCDEX_MAX_DRIVES]; + CDROM_Interface* cdrom[MSCDEX_MAX_DRIVES]; + +public: + Bit16u rootDriverHeaderSeg; +}; + +CMscdex::CMscdex(void) +{ + numDrives = 0; + rootDriverHeaderSeg = 0; + + memset(dinfo,0,sizeof(dinfo)); + for (Bit32u i=0; i0)); + DOS_DeviceHeader devHeader(PhysMake(seg,0)); + devHeader.SetNextDeviceHeader (0xFFFFFFFF); + devHeader.SetDriveLetter ('A'+_drive); + devHeader.SetNumSubUnits (1); + devHeader.SetName ("MSCD001 "); + + // Create Callback Strategy + Bit16u off = sizeof(DOS_DeviceHeader::sDeviceHeader); + Bitu call_strategy=CALLBACK_Allocate(); + CallBack_Handlers[call_strategy]=MSCDEX_Strategy_Handler; + real_writeb(seg,off+0,(Bit8u)0xFE); //GRP 4 + real_writeb(seg,off+1,(Bit8u)0x38); //Extra Callback instruction + real_writew(seg,off+2,call_strategy); //The immediate word + real_writeb(seg,off+4,(Bit8u)0xCB); //A RETF Instruction + devHeader.SetStrategy(off); + + // Create Callback Interrupt + off += 5; + Bitu call_interrupt=CALLBACK_Allocate(); + CallBack_Handlers[call_interrupt]=MSCDEX_Interrupt_Handler; + real_writeb(seg,off+0,(Bit8u)0xFE); //GRP 4 + real_writeb(seg,off+1,(Bit8u)0x38); //Extra Callback instruction + real_writew(seg,off+2,call_interrupt); //The immediate word + real_writeb(seg,off+4,(Bit8u)0xCB); //A RETF Instruction + devHeader.SetInterrupt(off); + + rootDriverHeaderSeg = seg; + + } else { + // Error check, driveletter have to be in a row + if (dinfo[numDrives-1].drive+1!=_drive) return 1; + }; + + if (GetNumDrives()+14)) { + // 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) { + cdrom[numDrives] = new CDROM_Interface_Ioctl(); + LOG(LOG_MISC,"MSCDEX: IOCTL Interface."); + break; + } + } else { + // Win 95/98/ME - always use ASPI + cdrom[numDrives] = new CDROM_Interface_Aspi(); + LOG(LOG_MISC,"MSCDEX: ASPI Interface."); + break; + } + #endif + cdrom[numDrives] = new CDROM_Interface_SDL(); + LOG(LOG_MISC,"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); + 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 !"); + result = 5; + break; + default : // weird result + return 6; + }; + if (!cdrom[numDrives]->SetDevice(physicalPath,forceCD)) return 3; + subUnit = numDrives; + // Set drive + DOS_DeviceHeader devHeader(PhysMake(rootDriverHeaderSeg,0)); + devHeader.SetNumSubUnits(devHeader.GetNumSubUnits()+1); + dinfo[numDrives].drive = (Bit8u)_drive; + dinfo[numDrives].physDrive = toupper(physicalPath[0]); + numDrives++; + return result; + } + return 4; +}; + +void CMscdex::GetDriverInfo (PhysPt data) +{ + for (Bit16u i=0; iGetAudioTracks(tr1i,tr2i,leadOut); + if (!dinfo[subUnit].lastResult) { + tr1 = tr2 = 0; + memset(&leadOut,0,sizeof(leadOut)); + } else { + tr1 = (Bit8u) tr1i; + tr2 = (Bit8u) tr2i; + } + return dinfo[subUnit].lastResult; +} + +bool CMscdex::GetTrackInfo(Bit8u subUnit, Bit8u track, Bit8u& attr, TMSF& start) +{ + dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioTrackInfo(track,start,attr); + if (!dinfo[subUnit].lastResult) { + attr = 0; + memset(&start,0,sizeof(start)); + }; + return dinfo[subUnit].lastResult; +}; + +bool CMscdex::PlayAudioSector(Bit8u subUnit, Bit32u sector, Bit32u length) +{ + // 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)) { + dinfo[subUnit].lastResult = cdrom[subUnit]->PauseAudio(true); + } else + dinfo[subUnit].lastResult = cdrom[subUnit]->PlayAudioSector(sector,length); + + if (dinfo[subUnit].lastResult) { + dinfo[subUnit].audioPlay = true; + dinfo[subUnit].audioPaused = false; + dinfo[subUnit].audioStart = sector; + dinfo[subUnit].audioEnd = length; + }; + return dinfo[subUnit].lastResult; +}; + +bool CMscdex::PlayAudioMSF(Bit8u subUnit, Bit32u start, Bit32u length) +{ + 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); +}; + +bool CMscdex::GetSubChannelData(Bit8u subUnit, Bit8u& attr, Bit8u& track, Bit8u &index, TMSF& rel, TMSF& abs) +{ + dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioSub(attr,track,index,rel,abs); + if (!dinfo[subUnit].lastResult) { + attr = track = index = 0; + memset(&rel,0,sizeof(rel)); + memset(&abs,0,sizeof(abs)); + }; + return dinfo[subUnit].lastResult; +}; + +bool CMscdex::GetAudioStatus(Bit8u subUnit, bool& playing, bool& pause, TMSF& start, TMSF& end) +{ + dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioStatus(playing,pause); + if (dinfo[subUnit].lastResult) { + // Start + Bit32u addr = dinfo[subUnit].audioStart + 150; + start.fr = (Bit8u)(addr%75); addr/=75; + start.sec = (Bit8u)(addr%60); + start.min = (Bit8u)(addr/60); + // End + addr = dinfo[subUnit].audioEnd + 150; + end.fr = (Bit8u)(addr%75); addr/=75; + end.sec = (Bit8u)(addr%60); + end.min = (Bit8u)(addr/60); + } else { + playing = false; + pause = false; + memset(&start,0,sizeof(start)); + memset(&end,0,sizeof(end)); + }; + + return dinfo[subUnit].lastResult; +}; + +bool CMscdex::StopAudio(Bit8u subUnit) +{ + if (dinfo[subUnit].audioPlay) dinfo[subUnit].lastResult = cdrom[subUnit]->PauseAudio(false); + else dinfo[subUnit].lastResult = cdrom[subUnit]->StopAudio(); + + if (dinfo[subUnit].lastResult) { + if (dinfo[subUnit].audioPlay) { + TMSF pos; + GetCurrentPos(subUnit,pos); + dinfo[subUnit].audioStart = pos.min*60*76+pos.sec*75+pos.fr - 150; + dinfo[subUnit].audioPaused = true; + } else { + dinfo[subUnit].audioPaused = false; + dinfo[subUnit].audioStart = 0; + dinfo[subUnit].audioEnd = 0; + }; + dinfo[subUnit].audioPlay = false; + }; + return dinfo[subUnit].lastResult; +}; + +bool CMscdex::ResumeAudio(Bit8u subUnit) +{ + return dinfo[subUnit].lastResult = PlayAudioSector(subUnit,dinfo[subUnit].audioStart,dinfo[subUnit].audioEnd); +}; + +Bit32u CMscdex::GetVolumeSize(Bit8u subUnit) +{ + Bit8u tr1,tr2; + TMSF leadOut; + dinfo[subUnit].lastResult = GetCDInfo(subUnit,tr1,tr2,leadOut); + if (dinfo[subUnit].lastResult) return (leadOut.min*60*75)+(leadOut.sec*75)+leadOut.fr; + return 0; +}; + +bool CMscdex::GetUPC(Bit8u subUnit, Bit8u& attr, char* upc) +{ + 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); + return dinfo[subUnit].lastResult; +}; + +bool CMscdex::ReadSectorsMSF(Bit8u subUnit, bool raw, Bit32u start, Bit16u num, PhysPt data) +{ + Bit8u min = (start>>16) & 0xFF; + Bit8u sec = (start>> 8) & 0xFF; + Bit8u fr = (start>> 0) & 0xFF; + Bit32u sector = min*60*76+sec*75+fr - 150; + // TODO: Check, if num has to be converted too ?! + return ReadSectors(subUnit,raw,sector,num,data); +}; + +bool CMscdex::ReadSectors(Bit16u drive, Bit32u sector, Bit16u num, PhysPt data) +// Called from INT 2F +{ + return ReadSectors(GetSubUnit(drive),false,sector,num,data); +}; + +bool CMscdex::GetCurrentPos(Bit8u subUnit, TMSF& pos) +{ + TMSF rel; + Bit8u attr,track,index; + dinfo[subUnit].lastResult = GetSubChannelData(subUnit, attr, track, index, rel, pos); + if (!dinfo[subUnit].lastResult) memset(&pos,0,sizeof(pos)); + return dinfo[subUnit].lastResult; +}; + +bool CMscdex::GetMediaStatus(Bit8u subUnit, bool& media, bool& changed, bool& trayOpen) +{ + dinfo[subUnit].lastResult = cdrom[subUnit]->GetMediaTrayStatus(media,changed,trayOpen); + return dinfo[subUnit].lastResult; +}; + +Bit32u CMscdex::GetDeviceStatus(Bit8u subUnit) +{ + bool media,changed,trayOpen; + + dinfo[subUnit].lastResult = GetMediaStatus(subUnit,media,changed,trayOpen); + Bit32u status = (trayOpen << 0) | // Drive is open ? + (dinfo[subUnit].locked << 1) | // Drive is locked ? + (1<<2) | // raw + cooked sectors + (1<<4) | // Can read sudio + (1<<9) | // Red book & HSG + ((!media) << 11); // Drive is empty ? + return status; +}; + +bool CMscdex::GetMediaStatus(Bit8u subUnit, Bit8u& status) +{ + bool media,changed,open,result; + result = GetMediaStatus(subUnit,media,changed,open); + status = changed ? 0xFF : 0x01; + return result; +}; + +bool CMscdex::LoadUnloadMedia(Bit8u subUnit, bool unload) +{ + dinfo[subUnit].lastResult = cdrom[subUnit]->LoadUnloadMedia(unload); + return dinfo[subUnit].lastResult; +}; + +bool CMscdex::SendDriverRequest(Bit16u drive, PhysPt data) +{ + // Get SubUnit + mem_writeb(data+1,GetSubUnit(drive)); + // Call Strategy / Interrupt + MSCDEX_Strategy_Handler(); + MSCDEX_Interrupt_Handler(); + return true; +}; + +Bit16u CMscdex::GetStatusWord(Bit8u subUnit) +{ + Bit16u status ; + if (dinfo[subUnit].lastResult) status = REQUEST_STATUS_DONE; // ok + else { + status = REQUEST_STATUS_ERROR | 0x02; // error : Drive not ready + } + + if (dinfo[subUnit].audioPlay) { + // Check if audio is still playing.... + TMSF start,end; + bool playing,pause; + if (GetAudioStatus(subUnit,playing,pause,start,end)) { + dinfo[subUnit].audioPlay = playing; + } else + dinfo[subUnit].audioPlay = false; + + status |= (dinfo[subUnit].audioPlay<<9); + } + dinfo[subUnit].lastResult = true; + return status; +}; + +static CMscdex* mscdex = 0; + +static Bitu MSCDEX_Strategy_Handler(void) +{ +// LOG("MSCDEX: Device Strategy Routine called."); + return CBRET_NONE; +} + +static Bitu MSCDEX_Interrupt_Handler(void) +{ +// LOG("MSCDEX: Device Interrupt Routine called."); + + Bit8u subFuncNr = 0xFF; + PhysPt data = PhysMake(SegValue(es),reg_bx); + Bit8u subUnit = mem_readb(data+1); + Bit8u funcNr = mem_readb(data+2); + +// if (funcNr!=0x03) LOG("MSCDEX: Driver Function %02X",funcNr); + + switch (funcNr) { + + case 0x03 : { /* IOCTL INPUT */ + PhysPt buffer = PhysMake(mem_readw(data+0x10),mem_readw(data+0x0E)); + subFuncNr = mem_readb(buffer); + //if (subFuncNr!=0x0B) LOG("MSCDEX: IOCTL INPUT Subfunction %02X",subFuncNr); + switch (subFuncNr) { + case 0x00 : /* Get Device Header address */ + mem_writed(buffer+1,RealMake(mscdex->rootDriverHeaderSeg,0)); + break; + case 0x01 :{/* Get current position */ + TMSF pos; + mscdex->GetCurrentPos(subUnit,pos); + mem_writeb(buffer+1,0x01); // Red book + mem_writeb(buffer+2,pos.fr); + mem_writeb(buffer+3,pos.sec); + mem_writeb(buffer+4,pos.min); + mem_writeb(buffer+5,0x00); + }break; + case 0x06 : /* Get Device status */ + mem_writed(buffer+1,mscdex->GetDeviceStatus(subUnit)); + break; + case 0x07 : /* Get sector size */ + if (mem_readb(buffer+1)==0x01) mem_writed(buffer+2,2352); + else mem_writed(buffer+2,2048); + break; + case 0x08 : /* Get size of current volume */ + mem_writed(buffer+1,mscdex->GetVolumeSize(subUnit)); + break; + case 0x09 : /* Media change ? */ + Bit8u status; + mscdex->GetMediaStatus(subUnit,status); + mem_writeb(buffer+1,status); + break; + case 0x0A : /* Get Audio Disk info */ + Bit8u tr1,tr2; TMSF leadOut; + mscdex->GetCDInfo(subUnit,tr1,tr2,leadOut); + mem_writeb(buffer+1,tr1); + mem_writeb(buffer+2,tr2); + mem_writeb(buffer+3,leadOut.fr); + mem_writeb(buffer+4,leadOut.sec); + mem_writeb(buffer+5,leadOut.min); + mem_writeb(buffer+6,0x00); + break; + case 0x0B :{/* Audio Track Info */ + Bit8u attr; TMSF start; + Bit8u track = mem_readb(buffer+1); + mscdex->GetTrackInfo(subUnit,track,attr,start); + mem_writeb(buffer+2,start.fr); + mem_writeb(buffer+3,start.sec); + mem_writeb(buffer+4,start.min); + mem_writeb(buffer+5,0x00); + mem_writeb(buffer+6,attr); + break; }; + case 0x0C :{/* Get Audio Sub Channel data */ + Bit8u attr,track,index; + TMSF abs,rel; + mscdex->GetSubChannelData(subUnit,attr,track,index,rel,abs); + mem_writeb(buffer+1,attr); + mem_writeb(buffer+2,track); + mem_writeb(buffer+3,index); + mem_writeb(buffer+4,rel.min); + mem_writeb(buffer+5,rel.sec); + mem_writeb(buffer+6,rel.fr); + mem_writeb(buffer+7,0x00); + mem_writeb(buffer+8,abs.min); + mem_writeb(buffer+9,abs.sec); + mem_writeb(buffer+10,abs.fr); + break; + }; + case 0x0E :{ /* Get UPC */ + Bit8u attr; char upc[8]; + mscdex->GetUPC(subUnit,attr,&upc[0]); + mem_writeb(buffer+1,attr); + for (int i=0; i<7; i++) mem_writeb(buffer+2+i,upc[i]); + mem_writeb(buffer+9,0x00); + break; + }; + case 0x0F :{ /* Get Audio Status */ + bool playing,pause; + TMSF resStart,resEnd; + mscdex->GetAudioStatus(subUnit,playing,pause,resStart,resEnd); + mem_writeb(buffer+1,pause); + mem_writeb(buffer+3,resStart.min); + mem_writeb(buffer+4,resStart.sec); + mem_writeb(buffer+5,resStart.fr); + mem_writeb(buffer+6,0x00); + mem_writeb(buffer+7,resEnd.min); + mem_writeb(buffer+8,resEnd.sec); + mem_writeb(buffer+9,resEnd.fr); + mem_writeb(buffer+10,0x00); + break; + }; + default : LOG(LOG_ERROR|LOG_MISC,"MSCDEX: Unsupported IOCTL INPUT Subfunction %02X",subFuncNr); + break; + } + break; + }; + 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); + switch (subFuncNr) { + case 0x00 : // Unload /eject) media + mscdex->LoadUnloadMedia(subUnit,true); + break; + case 0x01 : // (un)Lock door + // do nothing -> report as success + break; + case 0x05 : // load media + mscdex->LoadUnloadMedia(subUnit,false); + break; + default : LOG(LOG_ERROR|LOG_MISC,"MSCDEX: Unsupported IOCTL OUTPUT Subfunction %02X",subFuncNr); + break; + }; + break; + }; + case 0x0D : // device open + case 0x0E : // device close - dont care :) + break; + case 0x80 : // Read long + case 0x82 : { // Read long prefetch -> both the same here :) + PhysPt buff = PhysMake(mem_readw(data+0x10),mem_readw(data+0x0E)); + Bit32u start = mem_readd(data+0x14); + Bit16u len = mem_readw(data+0x12); + bool raw = (mem_readb(data+0x18)==1); + if (mem_readb(data+0x0D)==0x00) // HSG + mscdex->ReadSectors(subUnit,raw,start,len,buff); + else + mscdex->ReadSectorsMSF(subUnit,raw,start,len,buff); + break; + }; + case 0x83 : // Seek - dont care :) + break; + case 0x84 : { /* Play Audio Sectors */ + Bit32u start = mem_readd(data+0x0E); + Bit32u len = mem_readd(data+0x12); + if (mem_readb(data+0x0D)==0x00) // HSG + mscdex->PlayAudioSector(subUnit,start,len); + else // RED BOOK + mscdex->PlayAudioMSF(subUnit,start,len); + break; + }; + case 0x85 : /* Stop Audio */ + mscdex->StopAudio(subUnit); + break; + case 0x88 : /* Resume Audio */ + mscdex->ResumeAudio(subUnit); + break; + default : LOG(LOG_ERROR|LOG_MISC,"MSCDEX: Unsupported Driver Request %02X",funcNr); + break; + + }; + + // Set Statusword + mem_writew(data+3,mscdex->GetStatusWord(subUnit)); + return CBRET_NONE; +} + +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); + switch (reg_ax) { + + case 0x1500: /* Install check */ + reg_bx = mscdex->GetNumDrives(); + if (reg_bx>0) reg_cx = mscdex->GetFirstDrive(); + return true; + case 0x1501: /* Get cdrom driver info */ + mscdex->GetDriverInfo(data); + return true; + case 0x1502: /* Get Copyright filename */ + if (mscdex->GetCopyrightName(reg_cx,data)) { + CALLBACK_SCF(false); + } else { + reg_al = MSCDEX_ERROR_UNKNOWN_DRIVE; + CALLBACK_SCF(true); + }; + return true; + case 0x1503: /* Get Abstract filename */ + if (mscdex->GetAbstractName(reg_cx,data)) { + CALLBACK_SCF(false); + } else { + reg_al = MSCDEX_ERROR_UNKNOWN_DRIVE; + CALLBACK_SCF(true); + }; + return true; + case 0x1504: /* Get Documentation filename */ + if (mscdex->GetDocumentationName(reg_cx,data)) { + CALLBACK_SCF(false); + } else { + reg_al = MSCDEX_ERROR_UNKNOWN_DRIVE; + CALLBACK_SCF(true); + }; + return true; +/* case 0x1505: { // read vtoc + Bit16u error = 0; + if (mscdex->ReadVTOC(reg_cx,reg_dx,data,error)) { + CALLBACK_SCF(false); + } else { + reg_ax = error; + CALLBACK_SCF(true); + }; + }; + return true;*/ + case 0x1508: { // read sectors + Bit32u sector = (reg_si<<16)+reg_di; + if (mscdex->ReadSectors(reg_cx,sector,reg_dx,data)) { + CALLBACK_SCF(false); + } else { + reg_al = MSCDEX_ERROR_UNKNOWN_DRIVE; + CALLBACK_SCF(true); + }; + return true; + }; + case 0x1509: // write sectors - not supported + reg_al = MSCDEX_ERROR_DRIVE_NOT_READY; + CALLBACK_SCF(true); + return true; + case 0x150B: /* Valid CDROM drive ? */ + reg_ax = mscdex->IsValidDrive(reg_cx); + reg_bx = 0xADAD; + return true; + case 0x150C: /* Get MSCDEX Version */ + reg_bx = mscdex->GetVersion(); + return true; + case 0x150D: /* Get drives */ + mscdex->GetDrives(data); + return true; + case 0x1510: /* Device driver request */ + mscdex->SendDriverRequest(reg_cx,data); + return true; + default : LOG(LOG_ERROR|LOG_MISC,"MSCDEX: Unknwon call : %04X",reg_ax); + return true; + + }; + return false; +}; + +class device_MSCDEX : public DOS_Device { +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"); + return false; + } + bool Seek(Bit32u * pos,Bit32u type){return false;} + bool Close(){return false;} + Bit16u GetInformation(void){return 0x8093;} +private: + Bit8u cache; +}; + +int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit) +{ + int result = mscdex->AddDrive(driveLetter-'A',(char*)physicalPath,subUnit); + return result; +}; + +bool MSCDEX_HasMediaChanged(Bit8u subUnit) +{ + static TMSF leadOut[MSCDEX_MAX_DRIVES]; + + TMSF leadnew; + Bit8u tr1,tr2; + if (mscdex->GetCDInfo(subUnit,tr1,tr2,leadnew)) { + bool changed = (leadOut[subUnit].min!=leadnew.min) || (leadOut[subUnit].sec!=leadnew.sec) || (leadOut[subUnit].fr!=leadnew.fr); + leadOut[subUnit].min = leadnew.min; + leadOut[subUnit].sec = leadnew.sec; + leadOut[subUnit].fr = leadnew.fr; + return changed; + }; + if (subUnitAddDestroyFunction(&MSCDEX_ShutDown); + /* Register the mscdex device */ + DOS_Device * newdev = new device_MSCDEX(); + DOS_AddDevice(newdev); + /* Add Multiplexer */ + DOS_AddMultiplexHandler(MSCDEX_Handler); + /* Create MSCDEX */ + mscdex = new CMscdex; +}; + diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 24b1ce8..29d57d6 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -25,14 +25,27 @@ #include "cross.h" #include "regs.h" #include "callback.h" +#include "cdrom.h" #include "../shell/shell_inc.h" +void MSCDEX_SetCDInterface(int intNr, int forceCD); + class MOUNT : public Program { public: void Run(void) { DOS_Drive * newdrive;char drive; + // Show list of cdroms + if (cmd->FindExist("-cd",false)) { + int num = SDL_CDNumDrives(); + WriteOut("CDROMs found: %d\n",num); + for (int i=0; iGetCount()) { @@ -44,9 +57,10 @@ public: } return; } + std::string type="dir"; cmd->FindString("-t",type,true); - if (type=="floppy" || type=="dir") { + if (type=="floppy" || type=="dir" || type=="cdrom") { Bit16u sizes[4]; Bit8u mediaid; std::string str_size; @@ -58,6 +72,10 @@ public: str_size="512,127,16513,1700"; mediaid=0xF8; /* Hard Disk */ } + if (type=="cdrom") { + str_size="650,127,16513,1700"; + mediaid=0xF8; /* Hard Disk */ + } cmd->FindString("-size",str_size,true); char number[20];const char * scan=str_size.c_str(); Bitu index=0;Bitu count=0; @@ -70,7 +88,12 @@ public: scan++; } number[index]=0;sizes[count++]=atoi(number); - + + // get the drive letter + cmd->FindCommand(1,temp_line); + if ((temp_line.size() > 2) || ((temp_line.size()>1) && (temp_line[1]!=':'))) goto showusage; + drive=toupper(temp_line[0]); + if (!isalpha(drive)) goto showusage; if (!cmd->FindCommand(2,temp_line)) goto showusage; if (!temp_line.size()) goto showusage; @@ -86,14 +109,30 @@ public: } if (temp_line[temp_line.size()-1]!=CROSS_FILESPLIT) temp_line+=CROSS_FILESPLIT; Bit8u bit8size=(Bit8u) sizes[1]; - newdrive=new localDrive(temp_line.c_str(),sizes[0],bit8size,sizes[2],sizes[3],mediaid); + if (type=="cdrom") { + int num = -1; + cmd->FindInt("-usecd",num,true); + int error; + if (cmd->FindExist("-aspi",false)) MSCDEX_SetCDInterface(CDROM_USE_ASPI, num); else + if (cmd->FindExist("-ioctl",false)) MSCDEX_SetCDInterface(CDROM_USE_IOCTL, num); + else MSCDEX_SetCDInterface(CDROM_USE_SDL, num); + newdrive = new cdromDrive(drive,temp_line.c_str(),sizes[0],bit8size,sizes[2],0,mediaid,error); + // Check Mscdex, if it worked out... + switch (error) { + case 0 : WriteOut(MSG_Get("MSCDEX_SUCCESS")); break; + case 1 : WriteOut(MSG_Get("MSCDEX_ERROR_MULTIPLE_CDROMS")); break; + case 2 : WriteOut(MSG_Get("MSCDEX_ERROR_NOT_SUPPORTED")); break; + case 3 : WriteOut(MSG_Get("MSCDEX_ERROR_PATH")); break; + case 4 : WriteOut(MSG_Get("MSCDEX_TOO_MANY_DRIVES")); break; + case 5 : WriteOut(MSG_Get("MSCDEX_LIMITED_SUPPORT")); break; + default : WriteOut(MSG_Get("MSCDEX_UNKNOWN_ERROR")); break; + }; + } else { + newdrive=new localDrive(temp_line.c_str(),sizes[0],bit8size,sizes[2],sizes[3],mediaid); + } } - cmd->FindCommand(1,temp_line); - if (temp_line.size()>1) goto showusage; - drive=toupper(temp_line[0]); - if (!isalpha(drive)) goto showusage; if (Drives[drive-'A']) { - WriteOut(MSG_Get("PROGRAM_MOUNT_ALLREADY_MOUNDTED"),drive,Drives[drive-'A']->GetInfo()); + WriteOut(MSG_Get("PROGRAM_MOUNT_ALLREADY_MOUNTED"),drive,Drives[drive-'A']->GetInfo()); if (newdrive) delete newdrive; return; } @@ -149,78 +188,6 @@ static void MEM_ProgramStart(Program * * make) { } -#if !defined (WIN32) /* Unix */ - -class UPCASE : public Program { -public: - void Run(void); - void upcasedir(const char * directory); -}; - -void UPCASE::upcasedir(const char * directory) { - DIR * sdir; - char fullname[512]; - char newname[512]; - struct dirent *tempdata; - struct stat finfo; - - if(!(sdir=opendir(directory))) { - WriteOut(MSG_Get("PROGRAM_UPCASE_ERROR_DIR"),directory); - return; - } - WriteOut(MSG_Get("PROGRAM_UPCASE_SCANNING_DIR"),fullname); - while (tempdata=readdir(sdir)) { - if (strcmp(tempdata->d_name,".")==0) continue; - if (strcmp(tempdata->d_name,"..")==0) continue; - strcpy(fullname,directory); - strcat(fullname,"/"); - strcat(fullname,tempdata->d_name); - strcpy(newname,directory); - strcat(newname,"/"); - upcase(tempdata->d_name); - strcat(newname,tempdata->d_name); - WriteOut(MSG_Get("PROGRAM_UPCASE_RENAME"),fullname,newname); - rename(fullname,newname); - stat(fullname,&finfo); - if(S_ISDIR(finfo.st_mode)) { - upcasedir(fullname); - } - } - closedir(sdir); -} - - -void UPCASE::Run(void) { - /* First check if the directory exists */ - struct stat info; - WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_1")); - if (!cmd->GetCount()) { - WriteOut(MSG_Get("PROGRAM_UPCASE_USAGE")); - return; - } - cmd->FindCommand(1,temp_line); - if (stat(temp_line.c_str(),&info)) { - WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_ERROR_1"),temp_line.c_str()); - return; - } - if(!S_ISDIR(info.st_mode)) { - WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_ERROR_2"),temp_line.c_str()); - return; - } - WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_CHOICE"),temp_line.c_str()); - Bit8u key;Bit16u n=1; - DOS_ReadFile(STDIN,&key,&n); - if (toupper(key)=='Y') { - upcasedir(temp_line.c_str()); - } else { - WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_NO")); - } -} - -static void UPCASE_ProgramStart(Program * * make) { - *make=new UPCASE; -} -#endif // LOADFIX @@ -253,8 +220,8 @@ void LOADFIX::Run(void) Bit16u segment; Bit16u blocks = kb*1024/16; if (DOS_AllocateMemory(&segment,&blocks)) { - MCB* pmcb = (MCB*)HostMake(segment-1,0); - pmcb->psp_segment = 0x40; // use fake segment + DOS_MCB mcb((Bit16u)(segment-1)); + mcb.SetPSPSeg(0x40); // use fake segment WriteOut(MSG_Get("PROGRAM_LOADFIX_ALLOC"),kb); // Prepare commandline... if (cmd->FindCommand(commandNr++,temp_line)) { @@ -285,6 +252,38 @@ static void LOADFIX_ProgramStart(Program * * make) { *make=new LOADFIX; } +// RESCAN + +class RESCAN : public Program { +public: + void Run(void); +}; + +void RESCAN::Run(void) +{ + // Get current drive + Bit8u drive = DOS_GetDefaultDrive(); + if (Drives[drive]) { + Drives[drive]->EmptyCache(); + WriteOut(MSG_Get("PROGRAM_RESCAN_SUCCESS")); + } +}; + +static void RESCAN_ProgramStart(Program * * make) { + *make=new RESCAN; +} + +class INTRO : public Program { +public: + void Run(void) { + WriteOut(MSG_Get("PROGRAM_INTRO")); + } +}; + +static void INTRO_ProgramStart(Program * * make) { + *make=new INTRO; +} + void DOS_SetupPrograms(void) { /*Add Messages */ MSG_Add("PROGRAM_MOUNT_STATUS_2","Drive %c is mounted as %s\n"); @@ -303,22 +302,42 @@ void DOS_SetupPrograms(void) { MSG_Add("PROGRAM_LOADFIX_DEALLOCALL","Used memory freed.\n"); MSG_Add("PROGRAM_LOADFIX_ERROR","Memory allocation error.\n"); -#if !defined (WIN32) /* Unix */ - MSG_Add("PROGRAM_UPCASE_ERROR_DIR","Failed to open directory %s\n"); - MSG_Add("PROGRAM_UPCASE_SCANNING_DIR","Scanning directory %s\n"); - MSG_Add("PROGRAM_UPCASE_RENAME","Renaming %s to %s\n"); - MSG_Add("PROGRAM_UPCASE_RUN_1","UPCASE 0.1 Directory case convertor.\n"); - MSG_Add("PROGRAM_UPCASE_USAGE","Usage UPCASE [local directory]\nThis tool will convert all files and subdirectories in a directory.\nBe VERY sure this directory contains only dos related material.\nOtherwise you might horribly screw up your filesystem.\n"); - MSG_Add("PROGRAM_UPCASE_RUN_ERROR_1","%s doesn't exist\n"); - MSG_Add("PROGRAM_UPCASE_RUN_ERROR_2","%s isn't a directory\n"); - MSG_Add("PROGRAM_UPCASE_RUN_CHOICE","Converting the wrong directories can be very harmfull, please be carefull.\nAre you really really sure you want to convert %s to upcase?Y/N\n"); - MSG_Add("PROGRAM_UPCASE_RUN_NO","Okay better not do it.\n"); -#endif + MSG_Add("MSCDEX_SUCCESS","MSCDEX installed.\n"); + MSG_Add("MSCDEX_ERROR_MULTIPLE_CDROMS","MSCDEX: Failure: Drive-letters of multiple CDRom-drives have to be continuous.\n"); + MSG_Add("MSCDEX_ERROR_NOT_SUPPORTED","MSCDEX: Failure: Not yet supported.\n"); + MSG_Add("MSCDEX_ERROR_PATH","MSCDEX: Failure: Path not valid.\n"); + MSG_Add("MSCDEX_TOO_MANY_DRIVES","MSCDEX: Failure: Too many CDRom-drives (max: 5). MSCDEX Installation failed.\n"); + MSG_Add("MSCDEX_LIMITED_SUPPORT","MSCDEX: Mounted subdirectory: limited support.\n"); + MSG_Add("MSCDEX_UNKNOWN_ERROR","MSCDEX: Failure: Unknown error.\n"); + + MSG_Add("PROGRAM_RESCAN_SUCCESS","Drive cache cleared.\n"); + + MSG_Add("PROGRAM_INTRO", + "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" + "\n" + "For other platfroms:\n" + "mount c /home/user/dosprog 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" + "enter a directory (recognised by the [] in a directory listing).\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" + ); + /*regular setup*/ PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart); PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart); PROGRAMS_MakeFile("LOADFIX.COM",LOADFIX_ProgramStart); -#if !defined (WIN32) /* Unix */ - PROGRAMS_MakeFile("UPCASE.COM",UPCASE_ProgramStart); -#endif + PROGRAMS_MakeFile("RESCAN.COM",RESCAN_ProgramStart); + PROGRAMS_MakeFile("INTRO.COM",INTRO_ProgramStart); } diff --git a/src/dos/drive_cache.cpp b/src/dos/drive_cache.cpp new file mode 100644 index 0000000..01b5530 --- /dev/null +++ b/src/dos/drive_cache.cpp @@ -0,0 +1,635 @@ + +/* + * 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 "drives.h" +#include "dos_inc.h" +#include "dirent.h" +#include "support.h" + +// STL stuff +#include +#include +#include + + +bool SortByName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) +{ + return strcmp(a->shortname,b->shortname)<0; +}; + +bool SortByNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) +{ + return strcmp(a->shortname,b->shortname)>0; +}; + +bool SortByDirName(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) +{ + // Directories first... + if (a->isDir!=b->isDir) return (a->isDir>b->isDir); + return strcmp(a->shortname,b->shortname)<0; +}; + +bool SortByDirNameRev(DOS_Drive_Cache::CFileInfo* const &a, DOS_Drive_Cache::CFileInfo* const &b) +{ + // Directories first... + if (a->isDir!=b->isDir) return (a->isDir>b->isDir); + return strcmp(a->shortname,b->shortname)>0; +}; + +DOS_Drive_Cache::DOS_Drive_Cache(void) +{ + dirBase = new CFileInfo; + save_dir = 0; + srchNr = 0; + for (Bit32u i=0; i=0)) return; + + CreateEntry(dir,file); + // Sort Lists - filelist has to be alphabetically sorted + std::sort(dir->fileList.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); + if (index>=0) { + Bit32u i; + // Check if there are any open search dir that are affected by this... + if (dir) for (i=0; inextEntry)) + dirSearch[i]->nextEntry++; + } + }; + // LOG_DEBUG("DIR: Added Entry %s",path); + } else { +// LOG_DEBUG("DIR: Error: Failed to add %s",path); + }; +}; + +void DOS_Drive_Cache::DeleteEntry(const char* path, bool ignoreLastDir) +{ + CacheOut(path,ignoreLastDir); + if (dirSearch[srchNr]->nextEntry>0) dirSearch[srchNr]->nextEntry--; + + if (!ignoreLastDir) { + // Check if there are any open search dir that are affected by this... + Bit32u i; + char expand [CROSS_LEN]; + CFileInfo* dir = FindDirInfo(path,expand); + if (dir) for (i=0; inextEntry>0)) + dirSearch[i]->nextEntry--; + } + } +}; + +void DOS_Drive_Cache::CacheOut(const char* path, bool ignoreLastDir) +{ + char expand[CROSS_LEN] = { 0 }; + CFileInfo* dir; + + if (ignoreLastDir) { + char tmp[CROSS_LEN] = { 0 }; + Bit32s len = strrchr(path,CROSS_FILESPLIT) - path; + if (len>0) { + strncpy(tmp,path,len); + tmp[len] = 0; + } else { + strcpy(tmp,path); + } + dir = FindDirInfo(tmp,expand); + } else { + dir = FindDirInfo(path,expand); + } + +// LOG_DEBUG("DIR: Caching out %s : dir %s",expand,dir->orgname); + // delete file objects... + for(Bit32u i=0; ifileList.size(); i++) delete dir->fileList[i]; + // clear lists + dir->fileList.clear(); + dir->longNameList.clear(); + dir->outputList.clear(); + dir->shortNr = 0; + save_dir = 0; +}; + +bool DOS_Drive_Cache::IsCachedIn(CFileInfo* curDir) +{ + return (curDir->fileList.size()>0); +}; + + +bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) +{ + // Get Dir Info + char expand[CROSS_LEN] = {0}; + CFileInfo* curDir = FindDirInfo(fullname,expand); + + Bit16s low = 0; + Bit16s high = curDir->longNameList.size()-1; + Bit16s mid, res; + + while (low<=high) { + mid = (low+high)/2; + res = strcmp(fullname,curDir->longNameList[mid]->orgname); + if (res>0) low = mid+1; else + if (res<0) high = mid-1; + else { + strcpy(shortname,curDir->longNameList[mid]->shortname); + return true; + }; + } + return false; +}; + +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; + + while (low<=high) { + mid = (low+high)/2; + res = strncmp(name,curDir->longNameList[mid]->shortname,curDir->longNameList[mid]->compareCount); + if (res>0) low = mid+1; else + if (res<0) high = mid-1; + else { + // any more same x chars in next entries ? + do { + foundNr = curDir->longNameList[mid]->shortNr; + mid++; + } while(midlongNameList.size() && (strncmp(name,curDir->longNameList[mid]->shortname,curDir->longNameList[mid]->compareCount)==0)); + break; + }; + } + return foundNr+1; +}; + +bool DOS_Drive_Cache::RemoveTrailingDot(char* shortname) +// remove trailing '.' if no extension is available (Linux compatibility) +{ + Bitu len = strlen(shortname); + if (len && (shortname[len-1]=='.')) { + if (len==1) return false; + if ((len==2) && (shortname[0]=='.')) return false; + shortname[len-1] = 0; + return true; + } + return false; +}; + +Bit16s 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; + while (low<=high) { + mid = (low+high)/2; + res = strcmp(shortName,curDir->fileList[mid]->shortname); + if (res>0) low = mid+1; else + if (res<0) high = mid-1; else + { // Found + strcpy(shortName,curDir->fileList[mid]->orgname); + return mid; + }; + } + // not available + return -1; +}; + +bool DOS_Drive_Cache::RemoveSpaces(char* str) +// Removes all spaces +{ + char* curpos = str; + char* chkpos = str; + while (*chkpos!=0) { + if (*chkpos==' ') chkpos++; else *curpos++ = *chkpos++; + } + *curpos = 0; + return (curpos!=chkpos); +}; + +void DOS_Drive_Cache::CreateShortName(CFileInfo* curDir, CFileInfo* info) +{ + Bit16s len = 0; + Bit16s lenExt = 0; + bool createShort = false; + + char tmpNameBuffer[CROSS_LEN]; + + char* tmpName = tmpNameBuffer; + + // Remove Spaces + strcpy(tmpName,info->orgname); + upcase(tmpName); + createShort = RemoveSpaces(tmpName); + + // Get Length of filename + char* pos = strchr(tmpName,'.'); + if (pos) { + // Get Length of extension + lenExt = strlen(pos)-1; + // ignore preceding '.' if extension is longer than "3" + if (lenExt>3) { + while (*tmpName=='.') tmpName++; + createShort = true; + }; + pos = strchr(tmpName,'.'); + if (pos) len = (Bit16u)(pos - tmpName); + else len = strlen(tmpName); + + } else + len = strlen(tmpName); + + // Should shortname version be created ? + createShort = createShort || (len>8); + if (!createShort) { + char buffer[CROSS_LEN]; + strcpy(buffer,tmpName); + createShort = (GetLongName(curDir,buffer)>=0); + } + + if (createShort) { + // Create number + char buffer[8]; + info->shortNr = CreateShortNameID(curDir,tmpName); + sprintf(buffer,"%d",info->shortNr); + // Copy first letters + Bit16u tocopy; + if (len+strlen(buffer)+1>8) tocopy = 8 - strlen(buffer) - 1; + else tocopy = len; + strncpy(info->shortname,tmpName,tocopy); + info->shortname[tocopy] = 0; + // Copy number + strcat(info->shortname,"~"); + strcat(info->shortname,buffer); + // Create compare Count + info->compareCount = tocopy; + // Add (and cut) Extension, if available + if (pos) { + // Step to last extension... + pos = strrchr(tmpName, '.'); + // add extension + strncat(info->shortname,pos,4); + info->shortname[DOS_NAMELENGTH] = 0; + }; + // Put it in longname list... + curDir->longNameList.push_back(info); + std::sort(curDir->longNameList.begin(), curDir->longNameList.end(), SortByName); + } else { + strcpy(info->shortname,tmpName); + } + RemoveTrailingDot(info->shortname); +}; + +DOS_Drive_Cache::CFileInfo* DOS_Drive_Cache::FindDirInfo(const char* path, char* expandedPath) +{ + // statics + static char split[2] = { CROSS_FILESPLIT,0 }; + + char dir [CROSS_LEN]; + char work [CROSS_LEN]; + char* start = (char*)path; + char* pos; + CFileInfo* curDir = dirBase; + Bit16u id; + + if (save_dir && (strcmp(path,save_path)==0)) { + strcpy(expandedPath,save_expanded); + return save_dir; + }; + +// LOG_DEBUG("DIR: Find %s",path); + + // Remove base dir path + start += strlen(basePath); + strcpy(expandedPath,basePath); + + // hehe, baseDir should be cached in... + if (!IsCachedIn(curDir)) { + strcpy(work,basePath); + if (OpenDir(curDir,work,id)) { + char buffer[CROSS_LEN]; + char * result; + strcpy(buffer,dirPath); + ReadDir(id,result); + strcpy(dirPath,buffer); + free[id] = true; + }; + }; + + do { +// bool errorcheck = false; + pos = strchr(start,CROSS_FILESPLIT); + if (pos) { strncpy(dir,start,pos-start); dir[pos-start] = 0; /*errorcheck = true;*/ } + else { strcpy(dir,start); }; + + // Path found + Bit16s nextDir = GetLongName(curDir,dir); + strcat(expandedPath,dir); + + // Error check +/* if ((errorcheck) && (nextDir<0)) { + LOG_DEBUG("DIR: Error: %s not found.",expandedPath); + }; +*/ + // Follow Directory + 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)) { + char buffer[CROSS_LEN]; + char * result; + strcpy(buffer,dirPath); + ReadDir(id,result); + strcpy(dirPath,buffer); + free[id] = true; + }; + } + }; + if (pos) { + strcat(expandedPath,split); + start = pos+1; + } + } while (pos); + + // Save last result for faster access next time + strcpy(save_path,path); + strcpy(save_expanded,expandedPath); + save_dir = curDir; + + return curDir; +}; + +bool DOS_Drive_Cache::OpenDir(const char* path, Bit16u& id) +{ + char expand[CROSS_LEN] = {0}; + CFileInfo* dir = FindDirInfo(path,expand); + if (OpenDir(dir,expand,id)) { + dirSearch[id]->nextEntry = 0; + return true; + } + return false; +}; + +bool DOS_Drive_Cache::OpenDir(CFileInfo* dir, char* expand, Bit16u& id) +{ + id = GetFreeID(dir); + dirSearch[id] = dir; + // Add "/" + char end[2]={CROSS_FILESPLIT,0}; + if (expand[strlen(expand)-1]!=CROSS_FILESPLIT) strcat(expand,end); + // open dir + if (dirSearch[id]) { + // open dir + DIR* dirp = opendir(expand); + if (dirp) { + // Reset it.. + closedir(dirp); + strcpy(dirPath,expand); + free[id] = false; + return true; + } + }; + return false; +}; + +void DOS_Drive_Cache::CreateEntry(CFileInfo* dir, const char* name) +{ + struct stat status; + CFileInfo* info = new CFileInfo; + strcpy(info->orgname ,name); + info->shortNr = 0; + // Read and copy file stats + char buffer[CROSS_LEN]; + strcpy(buffer,dirPath); + strcat(buffer,info->orgname); + if (stat(buffer,&status)==0) info->isDir = (S_ISDIR(status.st_mode)>0); + else info->isDir = false; + // Check for long filenames... + 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) +{ + // shouldnt happen... + if (id>MAX_OPENDIRS) return false; + + if (!IsCachedIn(dirSearch[id])) { + // Try to open directory + DIR* dirp = opendir(dirPath); + if (!dirp) { + free[id] = true; + return false; + } + // Read complete directory + struct dirent* tmpres; + while ((tmpres = readdir(dirp))!=NULL) { + CreateEntry(dirSearch[id],tmpres->d_name); + // Sort Lists - filelist has to be alphabetically sorted, even in between (for finding double file names) + // hmpf.. bit slow probably... + std::sort(dirSearch[id]->fileList.begin(), dirSearch[id]->fileList.end(), SortByName); + } + // 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); + return false; + } else { + char buffer[128]; + sprintf(buffer,"DIR: Caching in %s (%d Files)",dirPath,dirSearch[srchNr]->fileList.size()); + LOG_DEBUG(buffer); + };*/ + }; + if (SetResult(dirSearch[id], result, dirSearch[id]->nextEntry)) return true; + free[id] = true; + return false; +}; + +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]; + // copy filename, short version + strcpy(res,info->shortname); + // Set to next Entry + dir->nextEntry = entryNr+1; + return true; +}; + +// **************************************************************************** +// No Dir Cache, +// **************************************************************************** + +static DIR* srch_opendir = 0; + +DOS_No_Drive_Cache::DOS_No_Drive_Cache(const char* path) +{ + SetBaseDir(path); +}; + +void DOS_No_Drive_Cache::SetBaseDir(const char* path) +{ + strcpy(basePath,path); +} + +bool DOS_No_Drive_Cache::OpenDir(const char* path, Bit16u& id) +{ + id = 0; + strcpy(dirPath,path); + if((srch_opendir=opendir(dirPath))==NULL) return false; + return true; +}; + +bool DOS_No_Drive_Cache::ReadDir(Bit16u id, char* &result) +{ + + static char res[CROSS_LEN]; + dirent * ent; + + if (!srch_opendir) return false; + if ((ent=readdir(srch_opendir))==NULL) { + strcpy(res,ent->d_name); + result=res; + closedir(srch_opendir); + srch_opendir=NULL; + return false; + } + return true; +}; diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index a12c504..bf84f43 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "dosbox.h" #include "dos_inc.h" #include "drives.h" @@ -30,7 +31,7 @@ class localFile : public DOS_File { public: - localFile(FILE * handle,Bit16u devinfo); + localFile(const char* name, FILE * handle,Bit16u devinfo); bool Read(Bit8u * data,Bit16u * size); bool Write(Bit8u * data,Bit16u * size); bool Seek(Bit32u * pos,Bit32u type); @@ -49,19 +50,20 @@ bool localDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) { strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); - FILE * hand=fopen(newname,"wb+"); + FILE * hand=fopen(dirCache.GetExpandName(newname),"wb+"); if (!hand) return false; + dirCache.AddEntry(newname, true); /* Make the 16 bit device information */ - *file=new localFile(hand,0x202); + *file=new localFile(name,hand,0x202); return true; }; bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { char * type; switch (flags) { - case OPEN_READ:type="rb";break; - case OPEN_WRITE:type="rb+";break; - case OPEN_READWRITE:type="rb+";break; + case OPEN_READ:type="rb"; break; + case OPEN_WRITE:type="rb+"; break; + case OPEN_READWRITE:type="rb+"; break; default: //TODO FIX IT type="rb+"; @@ -72,10 +74,13 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) { strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); + dirCache.ExpandName(newname); + FILE * hand=fopen(newname,type); - Bit32u err=errno; +// Bit32u err=errno; if (!hand) return false; - *file=new localFile(hand,0x202); + *file=new localFile(name,hand,0x202); +// (*file)->SetFileName(newname); return true; }; @@ -84,54 +89,73 @@ bool localDrive::FileUnlink(char * name) { strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); - if (!unlink(newname)) return true; + if (!unlink(dirCache.GetExpandName(newname))) { + dirCache.DeleteEntry(newname); + return true; + }; return false; }; bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) { - if (srch_opendir) closedir(srch_opendir); - strcpy(srch_dir,basedir); - strcat(srch_dir,_dir); - CROSS_FILENAME(srch_dir); + + char tempDir[CROSS_LEN]; + strcpy(tempDir,basedir); + strcat(tempDir,_dir); + CROSS_FILENAME(tempDir); char end[2]={CROSS_FILESPLIT,0}; - if (srch_dir[strlen(srch_dir)-1]!=CROSS_FILESPLIT) strcat(srch_dir,end); - if((srch_opendir=opendir(srch_dir))==NULL) return false; + if (tempDir[strlen(tempDir)-1]!=CROSS_FILESPLIT) strcat(tempDir,end); + + Bit16u id; + if (!dirCache.OpenDir(tempDir,id)) return false; + strcpy(srchInfo[id].srch_dir,tempDir); + dta.SetDirID(id); return FindNext(dta); } bool localDrive::FindNext(DOS_DTA & dta) { - struct dirent * dir_ent; + + char * dir_ent; struct stat stat_block; char full_name[CROSS_LEN]; + Bit8u srch_attr;char srch_pattern[DOS_NAMELENGTH_ASCII]; Bit8u find_attr; - if(!srch_opendir) return false; - dta.GetSearchParams(srch_attr,srch_pattern); - again: - if((dir_ent=readdir(srch_opendir))==NULL) { - closedir(srch_opendir); - srch_opendir=NULL; + + Bit16u id = dta.GetDirID(); + +again: + if (!dirCache.ReadDir(id,dir_ent)) { return false; } - if(!WildFileCmp(dir_ent->d_name,srch_pattern)) goto again; - strcpy(full_name,srch_dir); - strcat(full_name,dir_ent->d_name); - if(stat(full_name,&stat_block)!=0){ + + if(!WildFileCmp(dir_ent,srch_pattern)) goto again; + + strcpy(full_name,srchInfo[id].srch_dir); + strcat(full_name,dir_ent); + if (stat(dirCache.GetExpandName(full_name),&stat_block)!=0) { goto again; - } + } + if(S_ISDIR(stat_block.st_mode)) find_attr=DOS_ATTR_DIRECTORY; else find_attr=DOS_ATTR_ARCHIVE; if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again; + + if(S_ISDIR(stat_block.st_mode)) find_attr=DOS_ATTR_DIRECTORY; + else find_attr=DOS_ATTR_ARCHIVE; + if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again; + /*file is okay, setup everything to be copied in DTA Block */ char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size; - if(strlen(dir_ent->d_name)d_name); + + if(strlen(dir_ent)0) && (newdir[len-1]!='\\')) { @@ -205,11 +233,14 @@ bool localDrive::Rename(char * oldname,char * newname) { strcpy(newold,basedir); strcat(newold,oldname); CROSS_FILENAME(newold); + dirCache.ExpandName(newold); + char newnew[CROSS_LEN]; strcpy(newnew,basedir); strcat(newnew,newname); CROSS_FILENAME(newnew); - int temp=rename(newold,newnew); + int temp=rename(newold,dirCache.GetExpandName(newnew)); + if (temp==0) dirCache.CacheOut(newnew); return (temp==0); }; @@ -229,6 +260,7 @@ bool localDrive::FileExists(const char* name) { strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); + dirCache.ExpandName(newname); FILE* Temp=fopen(newname,"rb"); if(Temp==NULL) return false; fclose(Temp); @@ -240,13 +272,14 @@ bool localDrive::FileStat(const char* name, FileStat_Block * const stat_block) { strcpy(newname,basedir); strcat(newname,name); CROSS_FILENAME(newname); + dirCache.ExpandName(newname); struct stat temp_stat; if(stat(newname,&temp_stat)!=0) return false; /* Convert the stat to a FileStat */ struct tm *time; if((time=localtime(&temp_stat.st_mtime))!=0) { stat_block->time=DOS_PackTime(time->tm_hour,time->tm_min,time->tm_sec); - stat_block->date=DOS_PackDate(time->tm_year,time->tm_mon,time->tm_mday); + stat_block->date=DOS_PackDate(time->tm_year+1900,time->tm_mon+1,time->tm_mday); } else { } @@ -262,12 +295,13 @@ Bit8u localDrive::GetMediaByte(void) { localDrive::localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid) { strcpy(basedir,startdir); sprintf(info,"local directory %s",startdir); - srch_opendir=NULL; allocation.bytes_sector=_bytes_sector; allocation.sectors_cluster=_sectors_cluster; allocation.total_clusters=_total_clusters; allocation.free_clusters=_free_clusters; allocation.mediaid=_mediaid; + + dirCache.SetBaseDir(basedir); } @@ -301,17 +335,26 @@ bool localFile::Seek(Bit32u * pos,Bit32u type) { //TODO Give some doserrorcode; return false;//ERROR } - fpos_t temppos; int ret=fseek(fhandle,*pos,seektype); + if (ret!=0) { + // Out of file range, pretend everythings ok + // and move file pointer top end of file... ?! (Black Thorne) + fseek(fhandle,0,SEEK_END); + }; +#if 0 + fpos_t temppos; fgetpos(fhandle,&temppos); -//TODO Hope we don't encouter files with 64 bits size Bit32u * fake_pos=(Bit32u*)&temppos; *pos=*fake_pos; +#endif + *pos=(Bit32u)ftell(fhandle); last_action=NONE; return true; } bool localFile::Close() { + + open=false; fclose(fhandle); return true; } @@ -319,9 +362,9 @@ bool localFile::Close() { Bit16u localFile::GetInformation(void) { return info; } + - -localFile::localFile(FILE * handle,Bit16u devinfo) { +localFile::localFile(const char* _name, FILE * handle,Bit16u devinfo) { fhandle=handle; info=devinfo; struct stat temp_stat; @@ -329,13 +372,90 @@ localFile::localFile(FILE * handle,Bit16u devinfo) { struct tm * ltime; if((ltime=localtime(&temp_stat.st_mtime))!=0) { time=DOS_PackTime(ltime->tm_hour,ltime->tm_min,ltime->tm_sec); - date=DOS_PackDate(ltime->tm_year,ltime->tm_mon,ltime->tm_mday); + date=DOS_PackDate(ltime->tm_year+1900,ltime->tm_mon+1,ltime->tm_mday); } else { - time=0;date=0; + time=1;date=1; } size=(Bit32u)temp_stat.st_size; attr=DOS_ATTR_ARCHIVE; last_action=NONE; + + open=true; + name=0; + SetName(_name); } +// ******************************************** +// CDROM DRIVE +// ******************************************** +int MSCDEX_AddDrive(char driveLetter, const char* physicalPath, Bit8u& subUnit); +bool MSCDEX_HasMediaChanged(Bit8u subUnit); + +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) +{ + // Init mscdex + error = MSCDEX_AddDrive(driveLetter,startdir,subUnit); + strcpy(info,"CDRom."); +}; + +bool cdromDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) +{ + if ((flags==OPEN_READWRITE) || (flags==OPEN_WRITE)) { + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; + } + return localDrive::FileOpen(file,name,flags); +}; + +bool cdromDrive::FileCreate(DOS_File * * file,char * name,Bit16u attributes) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +}; + +bool cdromDrive::FileUnlink(char * name) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +}; + +bool cdromDrive::RemoveDir(char * dir) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +}; + +bool cdromDrive::MakeDir(char * dir) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +}; + +bool cdromDrive::Rename(char * oldname,char * newname) +{ + DOS_SetError(DOSERR_ACCESS_DENIED); + return false; +}; + +bool cdromDrive::GetFileAttr(char * name,Bit16u * attr) +{ + bool result = localDrive::GetFileAttr(name,attr); + if (result) *attr |= DOS_ATTR_READ_ONLY; + return result; +}; + +bool cdromDrive::FindFirst(char * _dir,DOS_DTA & dta) +{ + // If media has changed, reInit drivecache. + if (MSCDEX_HasMediaChanged(subUnit)) dirCache.EmptyCache(); + return localDrive::FindFirst(_dir,dta); +}; + +void cdromDrive::SetDir(const char* path) +{ + // If media has changed, reInit drivecache. + if (MSCDEX_HasMediaChanged(subUnit)) dirCache.EmptyCache(); + localDrive::SetDir(path); +}; diff --git a/src/dos/drive_virtual.cpp b/src/dos/drive_virtual.cpp index f697c59..5243d47 100644 --- a/src/dos/drive_virtual.cpp +++ b/src/dos/drive_virtual.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 @@ -30,6 +30,8 @@ struct VFILE_Block { const char * name; Bit8u * data; Bit32u size; + Bit16u date; + Bit16u time; VFILE_Block * next; }; @@ -41,6 +43,8 @@ void VFILE_Register(const char * name,Bit8u * data,Bit32u size) { new_file->name=name; new_file->data=data; new_file->size=size; + new_file->date=DOS_PackDate(2002,10,1); + new_file->time=DOS_PackTime(12,34,56); new_file->next=first_file; first_file=new_file; } @@ -65,6 +69,8 @@ Virtual_File::Virtual_File(Bit8u * in_data,Bit32u in_size) { file_size=in_size; file_data=in_data; file_pos=0; + date=DOS_PackDate(2002,10,1); + time=DOS_PackTime(12,34,56); } bool Virtual_File::Read(Bit8u * data,Bit16u * size) { @@ -159,8 +165,8 @@ bool Virtual_Drive::FileStat(const char* name, FileStat_Block * const stat_block if (strcasecmp(name,cur_file->name)==0) { stat_block->attr=DOS_ATTR_ARCHIVE; stat_block->size=cur_file->size; - stat_block->date=DOS_PackDate(2002,0,0); - stat_block->time=DOS_PackTime(12,12,12); + stat_block->date=DOS_PackDate(2002,10,1); + stat_block->time=DOS_PackTime(12,34,56); return true; } cur_file=cur_file->next; @@ -187,7 +193,7 @@ bool Virtual_Drive::FindNext(DOS_DTA & dta) { dta.GetSearchParams(attr,pattern); while (search_file) { if (WildFileCmp(search_file->name,pattern)) { - dta.SetResult(search_file->name,search_file->size,6,2,DOS_ATTR_ARCHIVE); + dta.SetResult(search_file->name,search_file->size,search_file->date,search_file->time,DOS_ATTR_ARCHIVE); search_file=search_file->next; return true; } diff --git a/src/dos/drives.h b/src/dos/drives.h index 90c8fce..db88226 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -20,34 +20,35 @@ #define _DRIVES_H__ #include -#include #include "dos_system.h" -#include "cross.h" - bool WildFileCmp(const char * file, const char * wild); class localDrive : public DOS_Drive { public: localDrive(const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid); - bool FileOpen(DOS_File * * file,char * name,Bit32u flags); - bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); - bool FileUnlink(char * name); - bool RemoveDir(char * dir); - bool MakeDir(char * dir); - bool TestDir(char * dir); - bool FindFirst(char * _dir,DOS_DTA & dta); - bool FindNext(DOS_DTA & dta); - bool GetFileAttr(char * name,Bit16u * attr); - bool Rename(char * oldname,char * newname); - bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters); - bool FileExists(const char* name); - bool FileStat(const char* name, FileStat_Block * const stat_block); - Bit8u GetMediaByte(void); + virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); + virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); + virtual bool FileUnlink(char * name); + virtual bool RemoveDir(char * dir); + virtual bool MakeDir(char * dir); + virtual bool TestDir(char * dir); + virtual bool FindFirst(char * _dir,DOS_DTA & dta); + virtual bool FindNext(DOS_DTA & dta); + virtual bool GetFileAttr(char * name,Bit16u * attr); + virtual bool Rename(char * oldname,char * newname); + virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters); + virtual bool FileExists(const char* name); + virtual bool FileStat(const char* name, FileStat_Block * const stat_block); + virtual Bit8u GetMediaByte(void); + private: char basedir[CROSS_LEN]; - char srch_dir[CROSS_LEN]; - DIR * srch_opendir; + + struct { + char srch_dir[CROSS_LEN]; + } srchInfo[MAX_OPENDIRS]; + struct { Bit16u bytes_sector; Bit8u sectors_cluster; @@ -57,8 +58,24 @@ private: } allocation; }; -struct VFILE_Block; +class cdromDrive : public localDrive +{ +public: + cdromDrive(const char driveLetter, const char * startdir,Bit16u _bytes_sector,Bit8u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid, int& error); + virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags); + virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); + virtual bool FileUnlink(char * name); + virtual bool RemoveDir(char * dir); + virtual bool MakeDir(char * dir); + virtual bool Rename(char * oldname,char * newname); + virtual bool GetFileAttr(char * name,Bit16u * attr); + virtual bool FindFirst(char * _dir,DOS_DTA & dta); + virtual void SetDir(const char* path); +private: + Bit8u subUnit; +}; +struct VFILE_Block; class Virtual_Drive: public DOS_Drive { public: @@ -81,4 +98,6 @@ private: VFILE_Block * search_file; }; + + #endif diff --git a/src/dos/scsidefs.h b/src/dos/scsidefs.h new file mode 100644 index 0000000..7db5c9e --- /dev/null +++ b/src/dos/scsidefs.h @@ -0,0 +1,579 @@ +//*************************************************************************** +// +// Name: SCSIDEFS.H +// +// Description: SCSI definitions ('C' Language) +// +//*************************************************************************** + +//*************************************************************************** +// %%% TARGET STATUS VALUES %%% +//*************************************************************************** +#define STATUS_GOOD 0x00 // Status Good +#define STATUS_CHKCOND 0x02 // Check Condition +#define STATUS_CONDMET 0x04 // Condition Met +#define STATUS_BUSY 0x08 // Busy +#define STATUS_INTERM 0x10 // Intermediate +#define STATUS_INTCDMET 0x14 // Intermediate-condition met +#define STATUS_RESCONF 0x18 // Reservation conflict +#define STATUS_COMTERM 0x22 // Command Terminated +#define STATUS_QFULL 0x28 // Queue full + +//*************************************************************************** +// %%% SCSI MISCELLANEOUS EQUATES %%% +//*************************************************************************** +#define MAXLUN 7 // Maximum Logical Unit Id +#define MAXTARG 7 // Maximum Target Id +#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs +#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's + +//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// %%% SCSI COMMAND OPCODES %%% +// +///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +//*************************************************************************** +// %%% Commands for all Device Types %%% +//*************************************************************************** +#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_COPY 0x18 // Copy (O) +#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) +#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) +#define SCSI_LOG_SELECT 0x4C // Log Select (O) +#define SCSI_LOG_SENSE 0x4D // Log Sense (O) +#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) +#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) +#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) +#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) +#define SCSI_READ_BUFF 0x3C // Read Buffer (O) +#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) +#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) +#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) + +//*************************************************************************** +// %%% Commands Unique to Direct Access Devices %%% +//*************************************************************************** +#define SCSI_COMPARE 0x39 // Compare (O) +#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) +#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) +#define SCSI_PREFETCH 0x34 // Prefetch (O) +#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) +#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) +#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) +#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) +#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) +#define SCSI_READ_LONG 0x3E // Read Long (O) +#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) +#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) +#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) +#define SCSI_REZERO 0x01 // Rezero Unit (O) +#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) +#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) +#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) +#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) +#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) +#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) +#define SCSI_SET_LIMIT 0x33 // Set Limits (O) +#define SCSI_START_STP 0x1B // Start/Stop Unit (O) +#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) +#define SCSI_VERIFY 0x2F // Verify (O) +#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) +#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) +#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) +#define SCSI_WRITE_LONG 0x3F // Write Long (O) +#define SCSI_WRITE_SAME 0x41 // Write Same (O) + +//*************************************************************************** +// %%% Commands Unique to Sequential Access Devices %%% +//*************************************************************************** +#define SCSI_ERASE 0x19 // Erase (MANDATORY) +#define SCSI_LOAD_UN 0x1B // Load/Unload (O) +#define SCSI_LOCATE 0x2B // Locate (O) +#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) +#define SCSI_READ_POS 0x34 // Read Position (O) +#define SCSI_READ_REV 0x0F // Read Reverse (O) +#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) +#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) +#define SCSI_REWIND 0x01 // Rewind (MANDATORY) +#define SCSI_SPACE 0x11 // Space (MANDATORY) +#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) +#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) + +//*************************************************************************** +// %%% Commands Unique to Printer Devices %%% +//*************************************************************************** +#define SCSI_PRINT 0x0A // Print (MANDATORY) +#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) +#define SCSI_STOP_PNT 0x1B // Stop Print (O) +#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) + +//*************************************************************************** +// %%% Commands Unique to Processor Devices %%% +//*************************************************************************** +#define SCSI_RECEIVE 0x08 // Receive (O) +#define SCSI_SEND 0x0A // Send (O) + +//*************************************************************************** +// %%% Commands Unique to Write-Once Devices %%% +//*************************************************************************** +#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) +#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) +#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) +#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) +#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) +#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) +#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) +#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) +#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) +#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) +#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) +#define SCSI_WRITE12 0xAA // Write 12-Byte (O) +#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) +#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) + +//*************************************************************************** +// %%% Commands Unique to CD-ROM Devices %%% +//*************************************************************************** +#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) +#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) +#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) +#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) +#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) +#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) +#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) +#define SCSI_READHEADER 0x44 // Read Header (O) +#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) +#define SCSI_READ_TOC 0x43 // Read TOC (O) + +//*************************************************************************** +// %%% Commands Unique to Scanner Devices %%% +//*************************************************************************** +#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) +#define SCSI_GETWINDOW 0x25 // Get Window (O) +#define SCSI_OBJECTPOS 0x31 // Object Postion (O) +#define SCSI_SCAN 0x1B // Scan (O) +#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) + +//*************************************************************************** +// %%% Commands Unique to Optical Memory Devices %%% +//*************************************************************************** +#define SCSI_UpdateBlk 0x3D // Update Block (O) + +//*************************************************************************** +// %%% Commands Unique to Medium Changer Devices %%% +//*************************************************************************** +#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) +#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) +#define SCSI_POSTOELEM 0x2B // Position to Element (O) +#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) +#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) + +//*************************************************************************** +// %%% Commands Unique to Communication Devices %%% +//*************************************************************************** +#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) +#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) +#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) +#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) +#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) +#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) + +//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ +// +// %%% END OF SCSI COMMAND OPCODES %%% +// +///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ + +//*************************************************************************** +// %%% Request Sense Data Format %%% +//*************************************************************************** +typedef struct { + + BYTE ErrorCode; // Error Code (70H or 71H) + BYTE SegmentNum; // Number of current segment descriptor + BYTE SenseKey; // Sense Key(See bit definitions too) + BYTE InfoByte0; // Information MSB + BYTE InfoByte1; // Information MID + BYTE InfoByte2; // Information MID + BYTE InfoByte3; // Information LSB + BYTE AddSenLen; // Additional Sense Length + BYTE ComSpecInf0; // Command Specific Information MSB + BYTE ComSpecInf1; // Command Specific Information MID + BYTE ComSpecInf2; // Command Specific Information MID + BYTE ComSpecInf3; // Command Specific Information LSB + BYTE AddSenseCode; // Additional Sense Code + BYTE AddSenQual; // Additional Sense Code Qualifier + BYTE FieldRepUCode; // Field Replaceable Unit Code + BYTE SenKeySpec15; // Sense Key Specific 15th byte + BYTE SenKeySpec16; // Sense Key Specific 16th byte + BYTE SenKeySpec17; // Sense Key Specific 17th byte + BYTE AddSenseBytes; // Additional Sense Bytes + +} SENSE_DATA_FMT; + +//*************************************************************************** +// %%% REQUEST SENSE ERROR CODE %%% +//*************************************************************************** +#define SERROR_CURRENT 0x70 // Current Errors +#define SERROR_DEFERED 0x71 // Deferred Errors + +//*************************************************************************** +// %%% REQUEST SENSE BIT DEFINITIONS %%% +//*************************************************************************** +#define SENSE_VALID 0x80 // Byte 0 Bit 7 +#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 +#define SENSE_EOM 0x40 // Byte 2 Bit 6 +#define SENSE_ILI 0x20 // Byte 2 Bit 5 + +//*************************************************************************** +// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% +//*************************************************************************** +#define KEY_NOSENSE 0x00 // No Sense +#define KEY_RECERROR 0x01 // Recovered Error +#define KEY_NOTREADY 0x02 // Not Ready +#define KEY_MEDIUMERR 0x03 // Medium Error +#define KEY_HARDERROR 0x04 // Hardware Error +#define KEY_ILLGLREQ 0x05 // Illegal Request +#define KEY_UNITATT 0x06 // Unit Attention +#define KEY_DATAPROT 0x07 // Data Protect +#define KEY_BLANKCHK 0x08 // Blank Check +#define KEY_VENDSPEC 0x09 // Vendor Specific +#define KEY_COPYABORT 0x0A // Copy Abort +#define KEY_EQUAL 0x0C // Equal (Search) +#define KEY_VOLOVRFLW 0x0D // Volume Overflow +#define KEY_MISCOMP 0x0E // Miscompare (Search) +#define KEY_RESERVED 0x0F // Reserved + +//*************************************************************************** +// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% +//*************************************************************************** +#define DTYPE_DASD 0x00 // Disk Device +#define DTYPE_SEQD 0x01 // Tape Device +#define DTYPE_PRNT 0x02 // Printer +#define DTYPE_PROC 0x03 // Processor +#define DTYPE_WORM 0x04 // Write-once read-multiple +#define DTYPE_CROM 0x05 // CD-ROM device +#define DTYPE_CDROM 0x05 // CD-ROM device +#define DTYPE_SCAN 0x06 // Scanner device +#define DTYPE_OPTI 0x07 // Optical memory device +#define DTYPE_JUKE 0x08 // Medium Changer device +#define DTYPE_COMM 0x09 // Communications device +#define DTYPE_RESL 0x0A // Reserved (low) +#define DTYPE_RESH 0x1E // Reserved (high) +#define DTYPE_UNKNOWN 0x1F // Unknown or no device type + +//*************************************************************************** +// %%% ANSI APPROVED VERSION DEFINITIONS %%% +//*************************************************************************** +#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand +#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) +#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 +#define ANSI_RESLO 0x3 // Reserved (low) +#define ANSI_RESHI 0x7 // Reserved (high) + + +//////////////////////////////////////////////////////////////// + +typedef struct { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + ULONG DataBufferOffset; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; + + +typedef struct { + USHORT Length; + UCHAR ScsiStatus; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + UCHAR CdbLength; + UCHAR SenseInfoLength; + UCHAR DataIn; + ULONG DataTransferLength; + ULONG TimeOutValue; + PVOID DataBuffer; + ULONG SenseInfoOffset; + UCHAR Cdb[16]; +} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; + + +typedef struct { + SCSI_PASS_THROUGH spt; + ULONG Filler; + UCHAR ucSenseBuf[32]; + UCHAR ucDataBuf[512]; +} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; + + +typedef struct { + SCSI_PASS_THROUGH_DIRECT spt; + ULONG Filler; + UCHAR ucSenseBuf[32]; +} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; + + + +typedef struct { + UCHAR NumberOfLogicalUnits; + UCHAR InitiatorBusId; + ULONG InquiryDataOffset; +} SCSI_BUS_DATA, *PSCSI_BUS_DATA; + + +typedef struct { + UCHAR NumberOfBusses; + SCSI_BUS_DATA BusData[1]; +} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; + + +typedef struct { + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + BOOLEAN DeviceClaimed; + ULONG InquiryDataLength; + ULONG NextInquiryDataOffset; + UCHAR InquiryData[1]; +} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; + + +typedef struct { + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; +} SCSI_ADDRESS, *PSCSI_ADDRESS; + + +/* + * method codes + */ +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +/* + * file access values + */ +#define FILE_ANY_ACCESS 0 +#define FILE_READ_ACCESS (0x0001) +#define FILE_WRITE_ACCESS (0x0002) + + +#define IOCTL_SCSI_BASE 0x00000004 + +/* + * constants for DataIn member of SCSI_PASS_THROUGH* structures + */ +#define SCSI_IOCTL_DATA_OUT 0 +#define SCSI_IOCTL_DATA_IN 1 +#define SCSI_IOCTL_DATA_UNSPECIFIED 2 + +/* + * Standard IOCTL define + */ +#define CTL_CODE( DevType, Function, Method, Access ) ( \ + ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) + +#define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) +#define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) +#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) +#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS ) + +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE + +#define IOCTL_STORAGE_CHECK_VERIFY CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0200, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_MEDIA_REMOVAL CTL_CODE(IOCTL_STORAGE_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_EJECT_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0202, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_LOAD_MEDIA CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_LOAD_MEDIA2 CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_RESERVE CTL_CODE(IOCTL_STORAGE_BASE, 0x0204, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_RELEASE CTL_CODE(IOCTL_STORAGE_BASE, 0x0205, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_FIND_NEW_DEVICES CTL_CODE(IOCTL_STORAGE_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS) + +#define FILE_DEVICE_CD_ROM 0x00000002 +#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#define IOCTL_CDROM_READ_Q_CHANNEL CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_CDROM_SEEK_AUDIO_MSF CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS) + +typedef struct _CDROM_SEEK_AUDIO_MSF { + UCHAR M; + UCHAR S; + UCHAR F; +} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF; + +// +// CD ROM Sub-Q Channel Data Format +// + +#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00 +#define IOCTL_CDROM_CURRENT_POSITION 0x01 +#define IOCTL_CDROM_MEDIA_CATALOG 0x02 +#define IOCTL_CDROM_TRACK_ISRC 0x03 + +typedef struct _CDROM_SUB_Q_DATA_FORMAT { + UCHAR Format; + UCHAR Track; +} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; + +typedef struct _SUB_Q_HEADER { + UCHAR Reserved; + UCHAR AudioStatus; + UCHAR DataLength[2]; +} SUB_Q_HEADER, *PSUB_Q_HEADER; + +typedef struct _SUB_Q_CURRENT_POSITION { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Control : 4; + UCHAR ADR : 4; + UCHAR TrackNumber; + UCHAR IndexNumber; + UCHAR AbsoluteAddress[4]; + UCHAR TrackRelativeAddress[4]; +} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION; + +typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved[3]; + UCHAR Reserved1 : 7; + UCHAR Mcval : 1; + UCHAR MediaCatalog[15]; +} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; + +typedef struct _SUB_Q_TRACK_ISRC { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved0; + UCHAR Track; + UCHAR Reserved1; + UCHAR Reserved2 : 7; + UCHAR Tcval : 1; + UCHAR TrackIsrc[15]; +} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC; + +typedef union _SUB_Q_CHANNEL_DATA { + SUB_Q_CURRENT_POSITION CurrentPosition; + SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog; + SUB_Q_TRACK_ISRC TrackIsrc; +} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA; + + +// IOCTL_DISK_SET_CACHE allows the caller to get or set the state of the disk +// read/write caches. +// +// If the structure is provided as the input buffer for the ioctl the read & +// write caches will be enabled or disabled depending on the parameters +// provided. +// +// If the structure is provided as an output buffer for the ioctl the state +// of the read & write caches will be returned. If both input and outut buffers +// are provided the output buffer will contain the cache state BEFORE any +// changes are made + + +typedef enum { + EqualPriority, + KeepPrefetchedData, + KeepReadData +} DISK_CACHE_RETENTION_PRIORITY; + +#define FILE_DEVICE_DISK 0x00000007 +#define IOCTL_DISK_BASE FILE_DEVICE_DISK +#define IOCTL_DISK_GET_CACHE_INFORMATION CTL_CODE(IOCTL_DISK_BASE, 0x0035, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DISK_SET_CACHE_INFORMATION CTL_CODE(IOCTL_DISK_BASE, 0x0036, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +typedef struct _DISK_CACHE_INFORMATION { + + // + // on return indicates that the device is capable of saving any parameters + // in non-volatile storage. On send indicates that the device should + // save the state in non-volatile storage. + // + + BOOLEAN ParametersSavable; + + // + // Indicates whether the write and read caches are enabled. + // + + BOOLEAN ReadCacheEnabled; + BOOLEAN WriteCacheEnabled; + + // + // Controls the likelyhood of data remaining in the cache depending on how + // it got there. Data cached from a READ or WRITE operation may be given + // higher, lower or equal priority to data entered into the cache for other + // means (like prefetch) + // + + DISK_CACHE_RETENTION_PRIORITY ReadRetentionPriority; + DISK_CACHE_RETENTION_PRIORITY WriteRetentionPriority; + + // + // Requests for a larger number of blocks than this may have prefetching + // disabled. If this value is set to 0 prefetch will be disabled. + // + + USHORT DisablePrefetchTransferLength; + + // + // If TRUE then ScalarPrefetch (below) will be valid. If FALSE then + // the minimum and maximum values should be treated as a block count + // (BlockPrefetch) + // + + BOOLEAN PrefetchScalar; + + // + // Contains the minimum and maximum amount of data which will be + // will be prefetched into the cache on a disk operation. This value + // may either be a scalar multiplier of the transfer length of the request, + // or an abolute number of disk blocks. PrefetchScalar (above) indicates + // which interpretation is used. + // + + union { + struct { + USHORT Minimum; + USHORT Maximum; + + // + // The maximum number of blocks which will be prefetched - useful + // with the scalar limits to set definite upper limits. + // + + USHORT MaximumBlocks; + } ScalarPrefetch; + + struct { + USHORT Minimum; + USHORT Maximum; + } BlockPrefetch; + }; + +} DISK_CACHE_INFORMATION, *PDISK_CACHE_INFORMATION; + diff --git a/src/dos/wnaspi32.h b/src/dos/wnaspi32.h new file mode 100644 index 0000000..92b9921 --- /dev/null +++ b/src/dos/wnaspi32.h @@ -0,0 +1,354 @@ +/****************************************************************************** +** +** Module Name: wnaspi32.h +** +** Description: Header file for ASPI for Win32. This header includes +** macro and type declarations, and can be included without +** modification when using Borland C++ or Microsoft Visual +** C++ with 32-bit compilation. If you are using a different +** compiler then you MUST ensure that structures are packed +** onto byte alignments, and that C++ name mangling is turned +** off. +** +** Notes: This file created using 4 spaces per tab. +** +******************************************************************************/ + +#ifndef __WNASPI32_H__ +#define __WNASPI32_H__ + +/* +** Make sure structures are packed and undecorated. +*/ + +#ifdef __BORLANDC__ +#pragma option -a1 +#endif //__BORLANDC__ + +#ifdef _MSC_VER +#pragma pack(1) +#endif //__MSC_VER + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +//***************************************************************************** +// %%% SCSI MISCELLANEOUS EQUATES %%% +//***************************************************************************** + +#define SENSE_LEN 14 // Default sense buffer length +#define SRB_DIR_SCSI 0x00 // Direction determined by SCSI +#define SRB_POSTING 0x01 // Enable ASPI posting +#define SRB_ENABLE_RESIDUAL_COUNT 0x04 // Enable residual byte count reporting +#define SRB_DIR_IN 0x08 // Transfer from SCSI target to host +#define SRB_DIR_OUT 0x10 // Transfer from host to SCSI target +#define SRB_EVENT_NOTIFY 0x40 // Enable ASPI event notification + +#define RESIDUAL_COUNT_SUPPORTED 0x02 // Extended buffer flag +#define MAX_SRB_TIMEOUT 108000lu // 30 hour maximum timeout in s +#define DEFAULT_SRB_TIMEOUT 108000lu // Max timeout by default + + +//***************************************************************************** +// %%% ASPI Command Definitions %%% +//***************************************************************************** + +#define SC_HA_INQUIRY 0x00 // Host adapter inquiry +#define SC_GET_DEV_TYPE 0x01 // Get device type +#define SC_EXEC_SCSI_CMD 0x02 // Execute SCSI command +#define SC_ABORT_SRB 0x03 // Abort an SRB +#define SC_RESET_DEV 0x04 // SCSI bus device reset +#define SC_SET_HA_PARMS 0x05 // Set HA parameters +#define SC_GET_DISK_INFO 0x06 // Get Disk information +#define SC_RESCAN_SCSI_BUS 0x07 // ReBuild SCSI device map +#define SC_GETSET_TIMEOUTS 0x08 // Get/Set target timeouts + +//***************************************************************************** +// %%% SRB Status %%% +//***************************************************************************** + +#define SS_PENDING 0x00 // SRB being processed +#define SS_COMP 0x01 // SRB completed without error +#define SS_ABORTED 0x02 // SRB aborted +#define SS_ABORT_FAIL 0x03 // Unable to abort SRB +#define SS_ERR 0x04 // SRB completed with error + +#define SS_INVALID_CMD 0x80 // Invalid ASPI command +#define SS_INVALID_HA 0x81 // Invalid host adapter number +#define SS_NO_DEVICE 0x82 // SCSI device not installed + +#define SS_INVALID_SRB 0xE0 // Invalid parameter set in SRB +#define SS_OLD_MANAGER 0xE1 // ASPI manager doesn't support Windows +#define SS_BUFFER_ALIGN 0xE1 // Buffer not aligned (replaces OLD_MANAGER in Win32) +#define SS_ILLEGAL_MODE 0xE2 // Unsupported Windows mode +#define SS_NO_ASPI 0xE3 // No ASPI managers resident +#define SS_FAILED_INIT 0xE4 // ASPI for windows failed init +#define SS_ASPI_IS_BUSY 0xE5 // No resources available to execute cmd +#define SS_BUFFER_TO_BIG 0xE6 // Buffer size to big to handle! +#define SS_MISMATCHED_COMPONENTS 0xE7 // The DLLs/EXEs of ASPI don't version check +#define SS_NO_ADAPTERS 0xE8 // No host adapters to manage +#define SS_INSUFFICIENT_RESOURCES 0xE9 // Couldn't allocate resources needed to init +#define SS_ASPI_IS_SHUTDOWN 0xEA // Call came to ASPI after PROCESS_DETACH +#define SS_BAD_INSTALL 0xEB // The DLL or other components are installed wrong + +//***************************************************************************** +// %%% Host Adapter Status %%% +//***************************************************************************** + +#define HASTAT_OK 0x00 // Host adapter did not detect an // error +#define HASTAT_SEL_TO 0x11 // Selection Timeout +#define HASTAT_DO_DU 0x12 // Data overrun data underrun +#define HASTAT_BUS_FREE 0x13 // Unexpected bus free +#define HASTAT_PHASE_ERR 0x14 // Target bus phase sequence // failure +#define HASTAT_TIMEOUT 0x09 // Timed out while SRB was waiting to beprocessed. +#define HASTAT_COMMAND_TIMEOUT 0x0B // Adapter timed out processing SRB. +#define HASTAT_MESSAGE_REJECT 0x0D // While processing SRB, the // adapter received a MESSAGE +#define HASTAT_BUS_RESET 0x0E // A bus reset was detected. +#define HASTAT_PARITY_ERROR 0x0F // A parity error was detected. +#define HASTAT_REQUEST_SENSE_FAILED 0x10 // The adapter failed in issuing + +//***************************************************************************** +// %%% SRB - HOST ADAPTER INQUIRY - SC_HA_INQUIRY (0) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_HA_INQUIRY + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE HA_Count; // 08/008 Number of host adapters present + BYTE HA_SCSI_ID; // 09/009 SCSI ID of host adapter + BYTE HA_ManagerId[16]; // 0A/010 String describing the manager + BYTE HA_Identifier[16]; // 1A/026 String describing the host adapter + BYTE HA_Unique[16]; // 2A/042 Host Adapter Unique parameters + WORD HA_Rsvd1; // 3A/058 Reserved, MUST = 0 +} +SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry; + +//***************************************************************************** +// %%% SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GET_DEV_TYPE + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + BYTE SRB_DeviceType; // 0A/010 Target's peripheral device type + BYTE SRB_Rsvd1; // 0B/011 Reserved, MUST = 0 +} +SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; + +//***************************************************************************** +// %%% SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_EXEC_SCSI_CMD + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + WORD SRB_Rsvd1; // 0A/010 Reserved for Alignment + DWORD SRB_BufLen; // 0C/012 Data Allocation Length + BYTE FAR *SRB_BufPointer; // 10/016 Data Buffer Pointer + BYTE SRB_SenseLen; // 14/020 Sense Allocation Length + BYTE SRB_CDBLen; // 15/021 CDB Length + BYTE SRB_HaStat; // 16/022 Host Adapter Status + BYTE SRB_TargStat; // 17/023 Target Status + VOID FAR *SRB_PostProc; // 18/024 Post routine + BYTE SRB_Rsvd2[20]; // 1C/028 Reserved, MUST = 0 + BYTE CDBByte[16]; // 30/048 SCSI CDB + BYTE SenseArea[SENSE_LEN+2]; // 50/064 Request Sense buffer +} +SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; + +//***************************************************************************** +// %%% SRB - ABORT AN SRB - SC_ABORT_SRB (3) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_ABORT_SRB + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + VOID FAR *SRB_ToAbort; // 08/008 Pointer to SRB to abort +} +SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort; + +//***************************************************************************** +// %%% SRB - BUS DEVICE RESET - SC_RESET_DEV (4) %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_RESET_DEV + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + BYTE SRB_Rsvd1[12]; // 0A/010 Reserved for Alignment + BYTE SRB_HaStat; // 16/022 Host Adapter Status + BYTE SRB_TargStat; // 17/023 Target Status + VOID FAR *SRB_PostProc; // 18/024 Post routine + BYTE SRB_Rsvd2[36]; // 1C/028 Reserved, MUST = 0 +} +SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset; + +//***************************************************************************** +// %%% SRB - GET DISK INFORMATION - SC_GET_DISK_INFO %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GET_DISK_INFO + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + BYTE SRB_DriveFlags; // 0A/010 Driver flags + BYTE SRB_Int13HDriveInfo; // 0B/011 Host Adapter Status + BYTE SRB_Heads; // 0C/012 Preferred number of heads translation + BYTE SRB_Sectors; // 0D/013 Preferred number of sectors translation + BYTE SRB_Rsvd1[10]; // 0E/014 Reserved, MUST = 0 +} +SRB_GetDiskInfo, *PSRB_GetDiskInfo, FAR *LPSRB_GetDiskInfo; + +//***************************************************************************** +// %%% SRB - RESCAN SCSI BUS(ES) ON SCSIPORT %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_RESCAN_SCSI_BUS + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 Reserved, MUST = 0 + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 +} +SRB_RescanPort, *PSRB_RescanPort, FAR *LPSRB_RescanPort; + +//***************************************************************************** +// %%% SRB - GET/SET TARGET TIMEOUTS %%% +//***************************************************************************** + +typedef struct // Offset +{ // HX/DEC + BYTE SRB_Cmd; // 00/000 ASPI command code = SC_GETSET_TIMEOUTS + BYTE SRB_Status; // 01/001 ASPI command status byte + BYTE SRB_HaId; // 02/002 ASPI host adapter number + BYTE SRB_Flags; // 03/003 ASPI request flags + DWORD SRB_Hdr_Rsvd; // 04/004 Reserved, MUST = 0 + BYTE SRB_Target; // 08/008 Target's SCSI ID + BYTE SRB_Lun; // 09/009 Target's LUN number + DWORD SRB_Timeout; // 0A/010 Timeout in half seconds +} +SRB_GetSetTimeouts, *PSRB_GetSetTimeouts, FAR *LPSRB_GetSetTimeouts; + +//***************************************************************************** +// %%% ASPIBUFF - Structure For Controllng I/O Buffers %%% +//***************************************************************************** + +typedef struct tag_ASPI32BUFF // Offset +{ // HX/DEC + PBYTE AB_BufPointer; // 00/000 Pointer to the ASPI allocated buffer + DWORD AB_BufLen; // 04/004 Length in bytes of the buffer + DWORD AB_ZeroFill; // 08/008 Flag set to 1 if buffer should be zeroed + DWORD AB_Reserved; // 0C/012 Reserved +} +ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF; + +//***************************************************************************** +// %%% TOC structures %%% +//***************************************************************************** + +typedef struct +{ + unsigned char reserved1; + unsigned char cAdrCtrl; + unsigned char cTrackNum; + unsigned char reserved2; + unsigned long lAddr; +} TOC_TRACK; + +typedef struct +{ + unsigned short usTocDataLen; + unsigned char cFirstTrack; + unsigned char cLastTrack; + TOC_TRACK tracks[100]; +} TOC, *PTOC, FAR *LPTOC; + +//***************************************************************************** +// %%% PROTOTYPES - User Callable ASPI for Win32 Functions %%% +//***************************************************************************** + +typedef struct +{ + BYTE SRB_Cmd; + BYTE SRB_Status; + BYTE SRB_HaId; + BYTE SRB_Flags; + DWORD SRB_Hdr_Rsvd; +} SRB, *PSRB, FAR *LPSRB; + + +#if defined(__BORLANDC__) + +DWORD _import GetASPI32SupportInfo( void ); +DWORD _import SendASPI32Command( LPSRB ); +BOOL _import GetASPI32Buffer( PASPI32BUFF ); +BOOL _import FreeASPI32Buffer( PASPI32BUFF ); +BOOL _import TranslateASPI32Address( PDWORD, PDWORD ); + +#elif defined(_MSC_VER) + +__declspec(dllimport) DWORD GetASPI32SupportInfo( void ); +__declspec(dllimport) DWORD SendASPI32Command( LPSRB ); +__declspec(dllimport) BOOL GetASPI32Buffer( PASPI32BUFF ); +__declspec(dllimport) BOOL FreeASPI32Buffer( PASPI32BUFF ); +__declspec(dllimport) BOOL TranslateASPI32Address( PDWORD, PDWORD ); + +#else + +extern DWORD GetASPI32SupportInfo( void ); +extern DWORD GetASPI32Command( LPSRB ); +extern BOOL GetASPI32Buffer( PASPI32BUFF ); +extern BOOL FreeASPI32Buffer( PASPI32BUFF ); +extern BOOL TranslateASPI32Address( PDWORD, PDWORD ); + +#endif + +/* +** Restore compiler default packing and close off the C declarations. +*/ + +#ifdef __BORLANDC__ +#pragma option -a. +#endif //__BORLANDC__ + +#ifdef _MSC_VER +#pragma pack() +#endif //_MSC_VER + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //__WNASPI32_H__ diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 56087e7..5426aa9 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.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 @@ -42,6 +42,7 @@ 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 IO_Init(Section * ); void CALLBACK_Init(Section*); @@ -57,6 +58,7 @@ void CPU_Init(Section*); //void FPU_Init(); void DMA_Init(Section*); void MIXER_Init(Section*); +void MIDI_Init(Section*); void HARDWARE_Init(Section*); @@ -65,20 +67,21 @@ void JOYSTICK_Init(Section*); void MOUSE_Init(Section*); void SBLASTER_Init(Section*); void GUS_Init(Section*); +void MPU401_Init(Section*); void ADLIB_Init(Section*); void PCSPEAKER_Init(Section*); void TANDYSOUND_Init(Section*); void CMS_Init(Section*); void DISNEY_Init(Section*); - - void PIC_Init(Section*); void TIMER_Init(Section*); void BIOS_Init(Section*); void DEBUG_Init(Section*); void CMOS_Init(Section*); +void MSCDEX_Init(Section*); + /* Dos Internal mostly */ void EMS_Init(Section*); void XMS_Init(Section*); @@ -158,6 +161,7 @@ void DOSBOX_Init(void) { secprop->Add_string("language",""); #if C_DEBUG secprop->Add_int("warnings",4); + LOG_StartUp(); #else secprop->Add_int("warnings",0); #endif @@ -172,8 +176,9 @@ void DOSBOX_Init(void) { secprop=control->AddSection_prop("render",&RENDER_Init); secprop->Add_int("frameskip",0); secprop->Add_bool("keepsmall",false); - secprop->Add_string("snapshots","snapshots"); - + secprop->Add_string("snapshots","snaps"); + secprop->Add_string("scaler","none"); + secprop=control->AddSection_prop("cpu",&CPU_Init); secprop->Add_int("cycles",1800); @@ -184,6 +189,17 @@ void DOSBOX_Init(void) { secprop->AddInitFunction(&JOYSTICK_Init); secprop=control->AddSection_prop("mixer",&MIXER_Init); + secprop->Add_bool("nosound",false); + secprop->Add_int("freq",22050); + secprop->Add_int("blocksize",2048); + secprop->Add_string("wavedir","waves"); + + 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",""); + #if C_DEBUG secprop=control->AddSection_prop("debug",&DEBUG_Init); #endif @@ -192,20 +208,23 @@ void DOSBOX_Init(void) { secprop->Add_int("irq",7); secprop->Add_int("dma",1); 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->AddInitFunction(&CMS_Init); - secprop->Add_bool("cms",false); + 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); secprop=control->AddSection_prop("speaker",&PCSPEAKER_Init); secprop->Add_bool("enabled",true); - secprop->Add_bool("sinewave",false); + secprop->Add_int("pcrate",22050); secprop->AddInitFunction(&TANDYSOUND_Init); secprop->Add_bool("tandy",false); @@ -220,8 +239,11 @@ void DOSBOX_Init(void) { secprop->AddInitFunction(&XMS_Init); secprop->Add_int("xmssize",8); + // Mscdex + secprop->AddInitFunction(&MSCDEX_Init); + secline=control->AddSection_line("autoexec",&AUTOEXEC_Init); - + control->SetStartUp(&SHELL_Init); #if C_FPU diff --git a/src/fpu/Makefile.in b/src/fpu/Makefile.in index 370c64f..4f3d7e9 100644 --- a/src/fpu/Makefile.in +++ b/src/fpu/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -205,7 +208,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -250,7 +253,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index ec0a145..83664b6 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -1,5 +1,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libgui.a -libgui_a_SOURCES = sdlmain.cpp render.cpp render_support.h +libgui_a_SOURCES = sdlmain.cpp render.cpp render_normal.h render_scale2x.h \ + midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h diff --git a/src/gui/Makefile.in b/src/gui/Makefile.in index 7ec07b9..1a557b1 100644 --- a/src/gui/Makefile.in +++ b/src/gui/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -84,7 +87,9 @@ install_sh = @install_sh@ AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libgui.a -libgui_a_SOURCES = sdlmain.cpp render.cpp render_support.h +libgui_a_SOURCES = sdlmain.cpp render.cpp render_normal.h render_scale2x.h \ + midi.cpp midi_win32.h midi_oss.h midi_coreaudio.h + subdir = src/gui mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h @@ -93,7 +98,7 @@ LIBRARIES = $(noinst_LIBRARIES) libgui_a_AR = $(AR) cru libgui_a_LIBADD = -am_libgui_a_OBJECTS = sdlmain.$(OBJEXT) render.$(OBJEXT) +am_libgui_a_OBJECTS = sdlmain.$(OBJEXT) render.$(OBJEXT) midi.$(OBJEXT) libgui_a_OBJECTS = $(am_libgui_a_OBJECTS) DEFS = @DEFS@ @@ -103,7 +108,8 @@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/render.Po ./$(DEPDIR)/sdlmain.Po +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/midi.Po ./$(DEPDIR)/render.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/sdlmain.Po CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -144,6 +150,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/midi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdlmain.Po@am__quote@ @@ -205,7 +212,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -250,7 +257,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp new file mode 100644 index 0000000..589a241 --- /dev/null +++ b/src/gui/midi.cpp @@ -0,0 +1,180 @@ +/* + * 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 "cross.h" +#include "support.h" +#include "setup.h" + +#define SYSEX_SIZE 1024 + +Bit8u MIDI_evt_len[256] = { + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x00 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x10 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x20 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x30 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x40 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x50 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x60 + 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x70 + + 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0x80 + 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0x90 + 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xa0 + 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xb0 + + 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, // 0xc0 + 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, // 0xd0 + + 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xe0 + + 0,2,3,2, 0,0,1,1, 1,0,1,1, 1,0,1,1 // 0xf0 +}; + +class MidiHandler; + +MidiHandler * handler_list=0; + +class MidiHandler { +public: + MidiHandler() { + next=handler_list; + handler_list=this; + }; + virtual bool Open(const char * conf) { return true; }; + virtual void Close(void) {}; + virtual void PlayMsg(Bit32u msg) {}; + virtual void PlaySysex(Bit8u * sysex,Bitu len) {}; + virtual char * GetName(void) { return "none"; }; + MidiHandler * next; +}; + +MidiHandler Midi_none; + +/* Include different midi drivers, lowest ones get checked first for default */ + +#if defined(MACOSX) + +#include "midi_coreaudio.h" + +#elif defined (WIN32) + +#include "midi_win32.h" + +#else + +#include "midi_oss.h" + +#endif + +static struct { + Bitu status; + Bitu cmd_len; + Bitu cmd_pos; + + Bit32u cmd_msg; + Bit8u data[4]; + struct { + Bit8u buf[SYSEX_SIZE]; + Bitu used; + bool active; + } sysex; + bool available; + MidiHandler * handler; +} midi; + +void MIDI_RawOutByte(Bit8u data) { + /* Test for a new status byte */ + if (midi.sysex.active && !(data&0x80)) { + if (midi.sysex.used<(SYSEX_SIZE-1)) midi.sysex.buf[midi.sysex.used++]=data; + return; + } else if (data&0x80) { + if (midi.sysex.active) { + /* 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); + midi.sysex.active=false; + if (data==0xf7) return; + } + midi.status=data; + midi.cmd_pos=0; + midi.cmd_msg=0; + if (midi.status==0xf0) { + midi.sysex.active=true; + midi.sysex.buf[0]=0xf0; + midi.sysex.used=1; + return; + } + midi.cmd_len=MIDI_evt_len[data]; + } + midi.cmd_msg|=data << (8 * midi.cmd_pos); + midi.cmd_pos++; + if (midi.cmd_pos >= midi.cmd_len) { + midi.handler->PlayMsg(midi.cmd_msg); + midi.cmd_msg=midi.status; + midi.cmd_pos=1; + } +} + +bool MIDI_Available(void) { + return midi.available; +} + +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 */ + MidiHandler * handler; + if (!strcasecmp(dev,"default")) goto getdefault; + handler=handler_list; + while (handler) { + if (!strcasecmp(dev,handler->GetName())) { + if (!handler->Open(conf)) { + LOG_MSG("MIDI:Can't open device:%s with config:%s.",dev,conf); + goto getdefault; + } + midi.handler=handler; + midi.available=true; + LOG_MSG("MIDI:Opened device:%s",handler->GetName()); + return; + } + handler=handler->next; + } + LOG_MSG("MIDI:Can't find device:%s, finding default handler.",dev); +getdefault: + handler=handler_list; + while (handler) { + if (handler->Open(conf)) { + midi.available=true; + midi.handler=handler; + LOG_MSG("MIDI:Opened device:%s",handler->GetName()); + return; + } + handler=handler->next; + } + /* This shouldn't be possible */ + midi.available=false; +} + diff --git a/src/gui/midi_coreaudio.h b/src/gui/midi_coreaudio.h new file mode 100644 index 0000000..8b95418 --- /dev/null +++ b/src/gui/midi_coreaudio.h @@ -0,0 +1,92 @@ +/* + * 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 + +class MidiHandler_coreaudio : public MidiHandler { +private: + AudioUnit m_musicDevice; + AudioUnit m_outputUnit; +public: + MidiHandler_coreaudio() : m_musicDevice(0), m_outputUnit(0) {} + char * GetName(void) { return "coreaudio"; } + bool Open(const char * conf) { + int err; + AudioUnitConnection auconnect; + ComponentDescription compdesc; + Component compid; + + if (m_outputUnit) + return false; + + // Open the Music Device + compdesc.componentType = kAudioUnitComponentType; + compdesc.componentSubType = kAudioUnitSubType_MusicDevice; + compdesc.componentManufacturer = kAudioUnitID_DLSSynth; + compdesc.componentFlags = 0; + compdesc.componentFlagsMask = 0; + compid = FindNextComponent(NULL, &compdesc); + m_musicDevice = (AudioUnit) OpenComponent(compid); + + // open the output unit + m_outputUnit = (AudioUnit) OpenDefaultComponent(kAudioUnitComponentType, kAudioUnitSubType_Output); + + // connect the units + auconnect.sourceAudioUnit = m_musicDevice; + auconnect.sourceOutputNumber = 0; + auconnect.destInputNumber = 0; + err = + AudioUnitSetProperty(m_outputUnit, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, 0, + (void *)&auconnect, sizeof(AudioUnitConnection)); + + // initialize the units + AudioUnitInitialize(m_musicDevice); + AudioUnitInitialize(m_outputUnit); + + // start the output + AudioOutputUnitStart(m_outputUnit); + + return true; + } + + void Close(void) { + if (m_outputUnit) { + AudioOutputUnitStop(m_outputUnit); + CloseComponent(m_outputUnit); + m_outputUnit = 0; + } + if (m_musicDevice) { + CloseComponent(m_musicDevice); + m_musicDevice = 0; + } + } + + void PlayMsg(Bit32u msg) { + MusicDeviceMIDIEvent(m_musicDevice, + (msg & 0x000000FF), + (msg & 0x0000FF00) >> 8, + (msg & 0x00FF0000) >> 16, + 0); + } + + void PlaySysex(Bit8u * sysex, Bitu len) { + MusicDeviceSysEx(m_musicDevice, sysex, len); + } +}; + +MidiHandler_coreaudio Midi_coreaudio; diff --git a/src/gui/midi_oss.h b/src/gui/midi_oss.h new file mode 100644 index 0000000..65500a6 --- /dev/null +++ b/src/gui/midi_oss.h @@ -0,0 +1,76 @@ +/* + * 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 +#define SEQ_MIDIPUTC 5 + +class MidiHandler_oss: public MidiHandler { +private: + int device; + Bit8u device_num; + bool isOpen; +public: + MidiHandler_oss() : isOpen(false),MidiHandler() {}; + char * GetName(void) { return "oss";}; + bool Open(const char * conf) { + char devname[512]; + if (conf && conf[0]) strncpy(devname,conf,512); + else strcpy(devname,"/dev/sequencer"); + char * devfind=(strrchr(devname,',')); + if (devfind) { + *devfind++=0; + device_num=atoi(devfind); + } else device_num=0; + if (isOpen) return false; + device=open(devname, O_WRONLY, 0); + if (device<0) return false; + return true; + }; + void Close(void) { + if (!isOpen) return; + if (device>0) close(device); + }; + void PlayMsg(Bit32u msg) { + Bit8u buf[128];Bitu pos=0; + Bitu len=MIDI_evt_len[msg & 0xff]; + for (;len>0;len--) { + buf[pos++] = SEQ_MIDIPUTC; + buf[pos++] = msg & 0xff; + buf[pos++] = device_num; + buf[pos++] = 0; + msg >>=8; + } + write(device,buf,pos); + }; + void PlaySysex(Bit8u * sysex,Bitu len) { + Bit8u buf[SYSEX_SIZE*4];Bitu pos=0; + for (;len>0;len--) { + buf[pos++] = SEQ_MIDIPUTC; + buf[pos++] = *sysex++; + buf[pos++] = device_num; + buf[pos++] = 0; + } + write(device,buf,pos); + } +}; + +MidiHandler_oss Midi_oss; + + + + diff --git a/src/gui/midi_win32.h b/src/gui/midi_win32.h new file mode 100644 index 0000000..54d3317 --- /dev/null +++ b/src/gui/midi_win32.h @@ -0,0 +1,73 @@ +/* + * 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 + +class MidiHandler_win32: public MidiHandler { +private: + HMIDIOUT m_out; + MIDIHDR m_hdr; + HANDLE m_event; + bool isOpen; +public: + MidiHandler_win32() : isOpen(false),MidiHandler() {}; + char * GetName(void) { return "win32";}; + bool Open(const char * conf) { + if (isOpen) return false; + m_event = CreateEvent (NULL, true, true, NULL); + MMRESULT res = midiOutOpen(&m_out, MIDI_MAPPER, (DWORD)m_event, 0, CALLBACK_EVENT); + if (res != MMSYSERR_NOERROR) return false; + isOpen=true; + return true; + }; + void Close(void) { + if (!isOpen) return; + isOpen=false; + midiOutClose(m_out); + CloseHandle (m_event); + }; + void PlayMsg(Bit32u msg) { + midiOutShortMsg(m_out, msg); + }; + void PlaySysex(Bit8u * sysex,Bitu len) { + if (WaitForSingleObject (m_event, 2000) == WAIT_TIMEOUT) { + LOG(LOG_MISC|LOG_ERROR,"Can't send midi message"); + return; + } + midiOutUnprepareHeader (m_out, &m_hdr, sizeof (m_hdr)); + + m_hdr.lpData = (char *) sysex; + m_hdr.dwBufferLength = len ; + m_hdr.dwBytesRecorded = len ; + m_hdr.dwUser = 0; + + MMRESULT result = midiOutPrepareHeader (m_out, &m_hdr, sizeof (m_hdr)); + if (result != MMSYSERR_NOERROR) return; + ResetEvent (m_event); + result = midiOutLongMsg (m_out,&m_hdr,sizeof(m_hdr)); + if (result != MMSYSERR_NOERROR) { + SetEvent (m_event); + return; + } + } +}; + +MidiHandler_win32 Midi_win32; + + diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 42235c1..356c628 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.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,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include #include #include "dosbox.h" @@ -25,12 +25,10 @@ #include "setup.h" #include "keyboard.h" #include "cross.h" - +#include "support.h" #define MAX_RES 2048 -typedef void (* RENDER_Part_Handler)(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy); - struct PalData { struct { Bit8u red; @@ -55,17 +53,16 @@ static struct { Bitu pitch; Bitu flags; float ratio; - RENDER_Part_Handler part_handler; + RENDER_Draw_Handler draw_handler; } src; struct { Bitu width; Bitu height; Bitu pitch; - Bitu next_line; - Bitu next_pixel; Bitu bpp; /* The type of BPP the operation requires for input */ - RENDER_Operation want_type; RENDER_Operation type; + RENDER_Operation want_type; + RENDER_Part_Handler part_handler; void * dest; void * buffer; void * pixels; @@ -76,6 +73,13 @@ static struct { } frameskip; Bitu flags; PalData pal; +#if (C_SSHOT) + struct { + RENDER_Operation type; + Bitu pitch; + const char * dir; + } shot; +#endif bool keep_small; bool screenshot; bool active; @@ -85,9 +89,12 @@ static struct { static void RENDER_ResetPal(void); /* Include the different rendering routines */ -#include "render_support.h" +#include "render_normal.h" +#include "render_scale2x.h" -static const char * snapshots_dir; + +#if (C_SSHOT) +#include /* Take a screenshot of the data that should be rendered */ static void TakeScreenShot(Bit8u * bitmap) { @@ -99,18 +106,10 @@ static void TakeScreenShot(Bit8u * bitmap) { png_color palette[256]; Bitu i; -/* First try to alloacte the png structures */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); - if (!png_ptr) return; - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr,(png_infopp)NULL); - return; - } /* Find a filename to open */ - dir=opendir(snapshots_dir); + dir=opendir(render.shot.dir); if (!dir) { - LOG_WARN("Can't open snapshot dir %s",snapshots_dir); + LOG_MSG("Can't open snapshot directory %s",render.shot.dir); return; } while (dir_ent=readdir(dir)) { @@ -125,14 +124,24 @@ static void TakeScreenShot(Bit8u * bitmap) { if (num>=last) last=num+1; } closedir(dir); - sprintf(file_name,"%s%csnap%05d.png",snapshots_dir,CROSS_FILESPLIT,last); -/* Open the actual file */ + sprintf(file_name,"%s%csnap%04d.png",render.shot.dir,CROSS_FILESPLIT,last); + /* Open the actual file */ FILE * fp=fopen(file_name,"wb"); if (!fp) { - LOG_WARN("Can't open snapshot file %s",file_name); + LOG_MSG("Can't open file %s for snapshot",file_name); return; } -/* Finalize the initing of png library */ + + /* First try to alloacte the png structures */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL); + if (!png_ptr) return; + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr,(png_infopp)NULL); + return; + } + + /* Finalize the initing of png library */ png_init_io(png_ptr, fp); png_set_compression_level(png_ptr,Z_BEST_COMPRESSION); @@ -161,7 +170,7 @@ static void TakeScreenShot(Bit8u * bitmap) { /*Allocate an array of scanline pointers*/ row_pointers=(png_bytep*)malloc(render.src.height*sizeof(png_bytep)); for (i=0;i(sec); - snapshots_dir=section->Get_string("snapshots"); 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; - KEYBOARD_AddEvent(KBD_f5,CTRL_PRESSED,EnableScreenShot); - KEYBOARD_AddEvent(KBD_f7,CTRL_PRESSED,DecreaseFrameSkip); - KEYBOARD_AddEvent(KBD_f8,CTRL_PRESSED,IncreaseFrameSkip); +#if (C_SSHOT) + render.shot.dir=section->Get_string("snapshots"); + KEYBOARD_AddEvent(KBD_f5,KBD_MOD_CTRL,EnableScreenShot); +#endif + const char * scaler;std::string cline; + if (control->cmdline->FindString("-scaler",cline,false)) { + scaler=cline.c_str(); + } else { + 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 { + 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); } diff --git a/src/gui/render_normal.h b/src/gui/render_normal.h new file mode 100644 index 0000000..5d4beee --- /dev/null +++ b/src/gui/render_normal.h @@ -0,0 +1,182 @@ +/* + * 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. + */ + +#define LOOPSIZE 4 + +#define SIZE_8 1 +#define SIZE_16 2 +#define SIZE_32 4 + +#define MAKE_8(FROM) Bit8u val=*(Bit8u *)(FROM); +#define MAKE_16(FROM) Bit16u val=render.pal.lookup.bpp16[*(Bit8u *)(FROM)]; +#define MAKE_32(FROM) Bit32u val=render.pal.lookup.bpp32[*(Bit8u *)(FROM)]; + +#define SAVE_8(WHERE) *(Bit8u *)(WHERE)=val; +#define SAVE_16(WHERE) *(Bit16u *)(WHERE)=val; +#define SAVE_32(WHERE) *(Bit32u *)(WHERE)=val; + +#define LINES_DN 1 +#define LINES_DW 1 +#define LINES_DH 2 +#define LINES_DB 2 + +#define PIXELS_DN 1 +#define PIXELS_DW 2 +#define PIXELS_DH 1 +#define PIXELS_DB 2 + +#define NORMAL_DN(BPP,FROM,DEST) \ + MAKE_ ## BPP(FROM); \ + SAVE_ ## BPP(DEST); \ + +#define NORMAL_DW(BPP,FROM,DEST) \ + MAKE_ ## BPP (FROM); \ + SAVE_ ## BPP (DEST); \ + SAVE_ ## BPP (DEST + SIZE_ ## BPP); \ + +#define NORMAL_DH(BPP,FROM,DEST) \ + MAKE_ ## BPP (FROM); \ + SAVE_ ## BPP (DEST); \ + SAVE_ ## BPP ((DEST) + render.op.pitch); \ + + +#define NORMAL_DB(BPP,FROM,DEST) \ + MAKE_ ## BPP (FROM); \ + SAVE_ ## BPP (DEST); \ + SAVE_ ## BPP ((DEST)+SIZE_ ## BPP ); \ + SAVE_ ## BPP ((DEST)+render.op.pitch ); \ + SAVE_ ## BPP ((DEST)+render.op.pitch+SIZE_ ## BPP ); \ + + +#define NORMAL_LOOP(COUNT,FUNC,BPP) \ + if (COUNT>0) {NORMAL_ ## FUNC (BPP,(src+0),(dest+0 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ + if (COUNT>1) {NORMAL_ ## FUNC (BPP,(src+1),(dest+1 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ + if (COUNT>2) {NORMAL_ ## FUNC (BPP,(src+2),(dest+2 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ + if (COUNT>3) {NORMAL_ ## FUNC (BPP,(src+3),(dest+3 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ + if (COUNT>4) {NORMAL_ ## FUNC (BPP,(src+4),(dest+4 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ + if (COUNT>5) {NORMAL_ ## FUNC (BPP,(src+5),(dest+5 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ + if (COUNT>6) {NORMAL_ ## FUNC (BPP,(src+6),(dest+6 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ + if (COUNT>7) {NORMAL_ ## FUNC (BPP,(src+7),(dest+7 * PIXELS_ ## FUNC * SIZE_ ## BPP )) }\ + +#define MAKENORMAL(FUNC,BPP) \ +static void Normal_ ## FUNC ## _ ##BPP(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { \ + Bit8u * dest=(Bit8u *)render.op.pixels+y*LINES_ ## FUNC*render.op.pitch+x*PIXELS_ ## FUNC * SIZE_ ## BPP; \ + Bitu next_src=render.src.pitch-dx; \ + Bitu next_dest=(LINES_ ## FUNC*render.op.pitch) - (dx*PIXELS_ ## FUNC * SIZE_ ## BPP); \ + dx/=LOOPSIZE; \ + dy--; \ + for (;dy>0;dy--) { \ + for (Bitu tempx=dx;tempx>0;tempx--) { \ + NORMAL_LOOP(LOOPSIZE,FUNC,BPP); \ + src+=LOOPSIZE;dest+=LOOPSIZE*PIXELS_ ## FUNC * SIZE_ ## BPP; \ + } \ + src+=next_src;dest+=next_dest; \ + } \ +} + +MAKENORMAL(DW,8); +MAKENORMAL(DB,8); + +MAKENORMAL(DN,16); +MAKENORMAL(DW,16); +MAKENORMAL(DH,16); +MAKENORMAL(DB,16); + +MAKENORMAL(DN,32); +MAKENORMAL(DW,32); +MAKENORMAL(DH,32); +MAKENORMAL(DB,32); + +/* Special versions for the 8-bit ones that can do direct line copying */ + +static void Normal_DN_8(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { + Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x; + Bitu next_src=render.src.pitch-dx; + Bitu next_dest=render.op.pitch-dx; + Bitu rem=dx&3;dx>>=2; + for (;dy>0;dy--) { + Bitu tempx; + for (tempx=dx;tempx>0;tempx--) { + Bit32u temp=*(Bit32u *)src;src+=4; + *(Bit32u *)dest=temp; + dest+=4; + } + for (tempx=rem;tempx>0;tempx--) { + *dest++=*src++; + } + src+=next_src;dest+=next_dest; + } +} + +static void Normal_DH_8(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { + Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch+x; + Bitu next_src=render.src.pitch-dx; + Bitu next_dest=(2*render.op.pitch)-dx; + Bitu rem=dx&3;dx>>=2; + for (;dy>0;dy--) { + Bitu tempx; + for (tempx=dx;tempx>0;tempx--) { + Bit32u temp=*(Bit32u *)src;src+=4; + *(Bit32u *)dest=temp; + *(Bit32u *)(dest+render.op.pitch)=temp; + dest+=4; + } + for (tempx=rem;tempx>0;tempx--) { + *dest=*src; + *(dest+render.op.pitch)=*src; + dest++; + } + src+=next_src;dest+=next_dest; + } +} + +static RENDER_Part_Handler Render_Normal_8_Table[4]= { + Normal_DN_8,Normal_DW_8,Normal_DH_8,Normal_DB_8, +}; + +static RENDER_Part_Handler Render_Normal_16_Table[4]= { + Normal_DN_16,Normal_DW_16,Normal_DH_16,Normal_DB_16, +}; + +static RENDER_Part_Handler Render_Normal_32_Table[4]= { + Normal_DN_32,Normal_DW_32,Normal_DH_32,Normal_DB_32, +}; + +static void Render_Normal_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags) { + if (!(flags & MODE_SET)) return; + render.op.width=width; + render.op.height=height; + render.op.bpp=bpp; + render.op.pitch=pitch; + render.op.type=OP_None; + switch (bpp) { + case 8: + render.op.part_handler=Render_Normal_8_Table[render.src.flags]; + break; + case 16: + render.op.part_handler=Render_Normal_16_Table[render.src.flags]; + break; + case 32: + render.op.part_handler=Render_Normal_32_Table[render.src.flags]; + break; + default: + E_Exit("RENDER:Unsupported display depth of %d",bpp); + break; + } + RENDER_ResetPal(); +} diff --git a/src/gui/render_scale2x.h b/src/gui/render_scale2x.h new file mode 100644 index 0000000..2cc1547 --- /dev/null +++ b/src/gui/render_scale2x.h @@ -0,0 +1,562 @@ +/* + * This file is part of the Scale2x project. + * + * Copyright (C) 2001-2002 Andrea Mazzoleni + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * In addition, as a special exception, Andrea Mazzoleni + * gives permission to link the code of this program with + * the MAME library (or with modified versions of MAME that use the + * same license as MAME), and distribute linked combinations including + * the two. You must obey the GNU General Public License in all + * respects for all of the code used other than MAME. If you modify + * this file, you may extend this exception to your version of the + * file, but you are not obligated to do so. If you do not wish to + * do so, delete this exception statement from your version. + */ + +/* + * This file contains a C and MMX implentation of the Scale2x effect. + * + * You can found an high level description of the effect at : + * + * http://scale2x.sourceforge.net/scale2x.html + * + * Alternatively at the previous license terms, you are allowed to use this + * code in your program with these conditions: + * - the program is not used in commercial activities. + * - the whole source code of the program is released with the binary. + * - derivative works of the program are allowed. + */ + +/* + * Made some changes to only support the 8-bit version. + * Also added mulitple destination bpp targets. + */ + +#ifndef __SCALE2X_H +#define __SCALE2X_H + +#include + +/***************************************************************************/ +/* basic types */ + +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); + + /* first pixel */ + dst0[0] = src1[0]; + dst1[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst0[1] = src0[0]; + else + dst0[1] = src1[0]; + if (src1[1] == src2[0] && src0[0] != src2[0]) + dst1[1] = src2[0]; + else + dst1[1] = src1[0]; + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst0[0] = src0[0]; + else + dst0[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst0[1] = src0[0]; + else + dst0[1] = src1[0]; + + if (src1[-1] == src2[0] && src0[0] != src2[0] && src1[1] != src2[0]) + dst1[0] = src2[0]; + else + dst1[0] = src1[0]; + if (src1[1] == src2[0] && src0[0] != src2[0] && src1[-1] != src2[0]) + dst1[1] = src2[0]; + else + dst1[1] = src1[0]; + + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst0[0] = src0[0]; + else + dst0[0] = src1[0]; + if (src1[-1] == src2[0] && src0[0] != src2[0]) + dst1[0] = src2[0]; + else + dst1[0] = src1[0]; + dst0[1] = src1[0]; + dst1[1] = src1[0]; +} + +static void scale2x_line_16(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +{ + assert(count >= 2); + + /* first pixel */ + dst0[0] = render.pal.lookup.bpp16[src1[0]]; + dst1[0] = render.pal.lookup.bpp16[src1[0]]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst0[1] = render.pal.lookup.bpp16[src0[0]]; + else + dst0[1] = render.pal.lookup.bpp16[src1[0]]; + if (src1[1] == src2[0] && src0[0] != src2[0]) + dst1[1] = render.pal.lookup.bpp16[src2[0]]; + else + dst1[1] = render.pal.lookup.bpp16[src1[0]]; + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst0[0] = render.pal.lookup.bpp16[src0[0]]; + else + dst0[0] = render.pal.lookup.bpp16[src1[0]]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst0[1] = render.pal.lookup.bpp16[src0[0]]; + else + dst0[1] = render.pal.lookup.bpp16[src1[0]]; + + if (src1[-1] == src2[0] && src0[0] != src2[0] && src1[1] != src2[0]) + dst1[0] = render.pal.lookup.bpp16[src2[0]]; + else + dst1[0] = render.pal.lookup.bpp16[src1[0]]; + if (src1[1] == src2[0] && src0[0] != src2[0] && src1[-1] != src2[0]) + dst1[1] = render.pal.lookup.bpp16[src2[0]]; + else + dst1[1] = render.pal.lookup.bpp16[src1[0]]; + + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst0[0] = render.pal.lookup.bpp16[src0[0]]; + else + dst0[0] = render.pal.lookup.bpp16[src1[0]]; + if (src1[-1] == src2[0] && src0[0] != src2[0]) + dst1[0] = render.pal.lookup.bpp16[src2[0]]; + else + dst1[0] = render.pal.lookup.bpp16[src1[0]]; + dst0[1] = render.pal.lookup.bpp16[src1[0]]; + dst1[1] = render.pal.lookup.bpp16[src1[0]]; +} + +static void scale2x_line_32(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +{ + assert(count >= 2); + + /* first pixel */ + dst0[0] = render.pal.lookup.bpp32[src1[0]]; + dst1[0] = render.pal.lookup.bpp32[src1[0]]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst0[1] = render.pal.lookup.bpp32[src0[0]]; + else + dst0[1] = render.pal.lookup.bpp32[src1[0]]; + if (src1[1] == src2[0] && src0[0] != src2[0]) + dst1[1] = render.pal.lookup.bpp32[src2[0]]; + else + dst1[1] = render.pal.lookup.bpp32[src1[0]]; + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src1[-1] == src0[0] && src2[0] != src0[0] && src1[1] != src0[0]) + dst0[0] = render.pal.lookup.bpp32[src0[0]]; + else + dst0[0] = render.pal.lookup.bpp32[src1[0]]; + if (src1[1] == src0[0] && src2[0] != src0[0] && src1[-1] != src0[0]) + dst0[1] = render.pal.lookup.bpp32[src0[0]]; + else + dst0[1] = render.pal.lookup.bpp32[src1[0]]; + + if (src1[-1] == src2[0] && src0[0] != src2[0] && src1[1] != src2[0]) + dst1[0] = render.pal.lookup.bpp32[src2[0]]; + else + dst1[0] = render.pal.lookup.bpp32[src1[0]]; + if (src1[1] == src2[0] && src0[0] != src2[0] && src1[-1] != src2[0]) + dst1[1] = render.pal.lookup.bpp32[src2[0]]; + else + dst1[1] = render.pal.lookup.bpp32[src1[0]]; + + ++src0; + ++src1; + ++src2; + dst0 += 2; + dst1 += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst0[0] = render.pal.lookup.bpp32[src0[0]]; + else + dst0[0] = render.pal.lookup.bpp32[src1[0]]; + if (src1[-1] == src2[0] && src0[0] != src2[0]) + dst1[0] = render.pal.lookup.bpp32[src2[0]]; + else + dst1[0] = render.pal.lookup.bpp32[src1[0]]; + dst0[1] = render.pal.lookup.bpp32[src1[0]]; + dst1[1] = render.pal.lookup.bpp32[src1[0]]; +} + +static void Scale2x_8(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { + if (dy<3) return; + Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch; + /* First line */ + scale2x_line_8(dest,dest+render.op.pitch,src,src,src+render.src.pitch,dx); + dest+=render.op.pitch*2; + src+=render.src.pitch; + dy-=2; + /* Middle part */ + for (;dy>0;dy--) { + scale2x_line_8((Bit8u *)dest,(Bit8u *)(dest+render.op.pitch),src-render.src.pitch,src,src+render.src.pitch,dx); + dest+=render.op.pitch*2; + src+=render.src.pitch; + } + /* Last Line */ + scale2x_line_8((Bit8u *)dest,(Bit8u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); +} + +static void Scale2x_16(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { + if (dy<3) return; + Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch; + /* First line */ + scale2x_line_16((Bit16u *)dest,(Bit16u *)(dest+render.op.pitch),src,src,src+render.src.pitch,dx); + dest+=render.op.pitch*2; + src+=render.src.pitch; + dy-=2; + /* Middle part */ + for (;dy>0;dy--) { + scale2x_line_16((Bit16u *)dest,(Bit16u *)(dest+render.op.pitch),src-render.src.pitch,src,src+render.src.pitch,dx); + dest+=render.op.pitch*2; + src+=render.src.pitch; + } + /* Last Line */ + scale2x_line_16((Bit16u *)dest,(Bit16u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); +} + +static void Scale2x_32(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { + if (dy<3) return; + Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch; + /* First line */ + scale2x_line_32((Bit32u *)dest,(Bit32u *)(dest+render.op.pitch),src,src,src+render.src.pitch,dx); + dest+=render.op.pitch*2; + src+=render.src.pitch; + dy-=2; + /* Middle part */ + for (;dy>0;dy--) { + scale2x_line_32((Bit32u *)dest,(Bit32u *)(dest+render.op.pitch),src-render.src.pitch,src,src+render.src.pitch,dx); + dest+=render.op.pitch*2; + src+=render.src.pitch; + } + /* Last Line */ + scale2x_line_32((Bit32u *)dest,(Bit32u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); +} + +#else + +#define SCALE2X_MMX 1 + +static __inline__ void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +{ + assert(count >= 16); + assert(count % 8 == 0); + + /* always do the first and last run */ + count -= 2*8; + + __asm__ __volatile__( +/* first run */ + /* set the current, current_pre, current_next registers */ + "movq 0(%1),%%mm0\n" + "movq 0(%1),%%mm7\n" + "movq 8(%1),%%mm1\n" + "psllq $56,%%mm0\n" + "psllq $56,%%mm1\n" + "psrlq $56,%%mm0\n" + "movq %%mm7,%%mm2\n" + "movq %%mm7,%%mm3\n" + "psllq $8,%%mm2\n" + "psrlq $8,%%mm3\n" + "por %%mm2,%%mm0\n" + "por %%mm3,%%mm1\n" + + /* current_upper */ + "movq (%0),%%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0,%%mm2\n" + "movq %%mm1,%%mm4\n" + "movq %%mm0,%%mm3\n" + "movq %%mm1,%%mm5\n" + "pcmpeqb %%mm6,%%mm2\n" + "pcmpeqb %%mm6,%%mm4\n" + "pcmpeqb (%2),%%mm3\n" + "pcmpeqb (%2),%%mm5\n" + "pandn %%mm2,%%mm3\n" + "pandn %%mm4,%%mm5\n" + "movq %%mm0,%%mm2\n" + "movq %%mm1,%%mm4\n" + "pcmpeqb %%mm1,%%mm2\n" + "pcmpeqb %%mm0,%%mm4\n" + "pandn %%mm3,%%mm2\n" + "pandn %%mm5,%%mm4\n" + "movq %%mm2,%%mm3\n" + "movq %%mm4,%%mm5\n" + "pand %%mm6,%%mm2\n" + "pand %%mm6,%%mm4\n" + "pandn %%mm7,%%mm3\n" + "pandn %%mm7,%%mm5\n" + "por %%mm3,%%mm2\n" + "por %%mm5,%%mm4\n" + + /* set *dst */ + "movq %%mm2,%%mm3\n" + "punpcklbw %%mm4,%%mm2\n" + "punpckhbw %%mm4,%%mm3\n" + "movq %%mm2,(%3)\n" + "movq %%mm3,8(%3)\n" + + /* next */ + "addl $8,%0\n" + "addl $8,%1\n" + "addl $8,%2\n" + "addl $16,%3\n" + +/* central runs */ + "shrl $3,%4\n" + "jz 1f\n" + + "0:\n" + + /* set the current, current_pre, current_next registers */ + "movq -8(%1),%%mm0\n" + "movq (%1),%%mm7\n" + "movq 8(%1),%%mm1\n" + "psrlq $56,%%mm0\n" + "psllq $56,%%mm1\n" + "movq %%mm7,%%mm2\n" + "movq %%mm7,%%mm3\n" + "psllq $8,%%mm2\n" + "psrlq $8,%%mm3\n" + "por %%mm2,%%mm0\n" + "por %%mm3,%%mm1\n" + + /* current_upper */ + "movq (%0),%%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0,%%mm2\n" + "movq %%mm1,%%mm4\n" + "movq %%mm0,%%mm3\n" + "movq %%mm1,%%mm5\n" + "pcmpeqb %%mm6,%%mm2\n" + "pcmpeqb %%mm6,%%mm4\n" + "pcmpeqb (%2),%%mm3\n" + "pcmpeqb (%2),%%mm5\n" + "pandn %%mm2,%%mm3\n" + "pandn %%mm4,%%mm5\n" + "movq %%mm0,%%mm2\n" + "movq %%mm1,%%mm4\n" + "pcmpeqb %%mm1,%%mm2\n" + "pcmpeqb %%mm0,%%mm4\n" + "pandn %%mm3,%%mm2\n" + "pandn %%mm5,%%mm4\n" + "movq %%mm2,%%mm3\n" + "movq %%mm4,%%mm5\n" + "pand %%mm6,%%mm2\n" + "pand %%mm6,%%mm4\n" + "pandn %%mm7,%%mm3\n" + "pandn %%mm7,%%mm5\n" + "por %%mm3,%%mm2\n" + "por %%mm5,%%mm4\n" + + /* set *dst */ + "movq %%mm2,%%mm3\n" + "punpcklbw %%mm4,%%mm2\n" + "punpckhbw %%mm4,%%mm3\n" + "movq %%mm2,(%3)\n" + "movq %%mm3,8(%3)\n" + + /* next */ + "addl $8,%0\n" + "addl $8,%1\n" + "addl $8,%2\n" + "addl $16,%3\n" + + "decl %4\n" + "jnz 0b\n" + "1:\n" + +/* final run */ + /* set the current, current_pre, current_next registers */ + "movq (%1),%%mm1\n" + "movq (%1),%%mm7\n" + "movq -8(%1),%%mm0\n" + "psrlq $56,%%mm1\n" + "psrlq $56,%%mm0\n" + "psllq $56,%%mm1\n" + "movq %%mm7,%%mm2\n" + "movq %%mm7,%%mm3\n" + "psllq $8,%%mm2\n" + "psrlq $8,%%mm3\n" + "por %%mm2,%%mm0\n" + "por %%mm3,%%mm1\n" + + /* current_upper */ + "movq (%0),%%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0,%%mm2\n" + "movq %%mm1,%%mm4\n" + "movq %%mm0,%%mm3\n" + "movq %%mm1,%%mm5\n" + "pcmpeqb %%mm6,%%mm2\n" + "pcmpeqb %%mm6,%%mm4\n" + "pcmpeqb (%2),%%mm3\n" + "pcmpeqb (%2),%%mm5\n" + "pandn %%mm2,%%mm3\n" + "pandn %%mm4,%%mm5\n" + "movq %%mm0,%%mm2\n" + "movq %%mm1,%%mm4\n" + "pcmpeqb %%mm1,%%mm2\n" + "pcmpeqb %%mm0,%%mm4\n" + "pandn %%mm3,%%mm2\n" + "pandn %%mm5,%%mm4\n" + "movq %%mm2,%%mm3\n" + "movq %%mm4,%%mm5\n" + "pand %%mm6,%%mm2\n" + "pand %%mm6,%%mm4\n" + "pandn %%mm7,%%mm3\n" + "pandn %%mm7,%%mm5\n" + "por %%mm3,%%mm2\n" + "por %%mm5,%%mm4\n" + + /* set *dst */ + "movq %%mm2,%%mm3\n" + "punpcklbw %%mm4,%%mm2\n" + "punpckhbw %%mm4,%%mm3\n" + "movq %%mm2,(%3)\n" + "movq %%mm3,8(%3)\n" + + : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) + : + : "cc" + ); +} + +static void scale2x_line_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) +{ + assert(count >= 16); + assert(count % 8 == 0); + + scale2x_8_mmx_single(dst0, src0, src1, src2, count); + scale2x_8_mmx_single(dst1, src2, src1, src0, count); +} + +static void Scale2x_8_mmx(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { + if (dy<3) return; + Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch; + /* First line */ + scale2x_line_8_mmx(dest,dest+render.op.pitch,src,src,src+render.src.pitch,dx); + dest+=render.op.pitch*2; + src+=render.src.pitch; + dy-=2; + /* Middle part */ + for (;dy>0;dy--) { + scale2x_line_8_mmx((Bit8u *)dest,(Bit8u *)(dest+render.op.pitch),src-render.src.pitch,src,src+render.src.pitch,dx); + dest+=render.op.pitch*2; + src+=render.src.pitch; + } + /* Last Line */ + scale2x_line_8_mmx((Bit8u *)dest,(Bit8u *)(dest+render.op.pitch),src-render.src.pitch,src,src,dx); +} + +#endif + +static void Render_Scale2x_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags) { + if (!(flags & MODE_SET)) return; + render.op.width=width; + render.op.height=height; + render.op.bpp=bpp; + render.op.pitch=pitch; + render.op.type=OP_Scale2x; +#if defined(SCALE2X_NORMAL) + switch (bpp) { + case 8: + render.op.part_handler=Scale2x_8; + break; + case 16: + render.op.part_handler=Scale2x_16;; + break; + case 32: + render.op.part_handler=Scale2x_32; + break; + default: + E_Exit("RENDER:Unsupported display depth of %d",bpp); + break; + } +#elif defined(SCALE2X_MMX) + assert (bpp==8); + render.op.part_handler=Scale2x_8_mmx; +#endif + RENDER_ResetPal(); +} + +#endif diff --git a/src/gui/render_support.h b/src/gui/render_support.h deleted file mode 100644 index 3d91cb0..0000000 --- a/src/gui/render_support.h +++ /dev/null @@ -1,228 +0,0 @@ -static void Render_Normal_8_None(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=render.op.pitch-dx; - Bitu rem=dx&3;dx>>=2; - for (;dy>0;dy--) { - Bitu tempx; - for (tempx=dx;tempx>0;tempx--) { - Bit32u temp=*(Bit32u *)src;src+=4; - *(Bit32u *)dest=temp; - dest+=4; - } - for (tempx=rem;tempx>0;tempx--) { - *dest++=*src++; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_8_DoubleWidth(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x*2; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=render.op.pitch-dx*2; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - *dest=*src;*(dest+1)=*src; - src++;dest+=2; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_8_DoubleHeight(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch+x; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=(2*render.op.pitch)-dx; - Bitu rem=dx&3;dx>>=2; - for (;dy>0;dy--) { - Bitu tempx; - for (tempx=dx;tempx>0;tempx--) { - Bit32u temp=*(Bit32u *)src;src+=4; - *(Bit32u *)dest=temp; - *(Bit32u *)(dest+render.op.pitch)=temp; - dest+=4; - } - for (tempx=rem;tempx>0;tempx--) { - *dest=*src; - *(dest+render.op.pitch)=*src; - dest++; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_8_DoubleBoth(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=(2*render.op.pitch)-dx*2; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit8u val=src[0];src++; - dest[0]=val;dest[1]=val; - dest[render.op.pitch]=val;dest[render.op.pitch+1]=val; - dest+=2; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_16_None(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=render.op.pitch-dx*2; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit16u val=render.pal.lookup.bpp16[src[0]];src++; - *(Bit16u *)dest=val; - dest+=2; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_16_DoubleWidth(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x*4; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=render.op.pitch-dx*4; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit16u val=render.pal.lookup.bpp16[src[0]];src++; - *(Bit16u *)dest=val; - *(Bit16u *)(dest+2)=val; - dest+=4; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_16_DoubleHeight(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch+x*2; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=(2*render.op.pitch)-dx*2; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit16u val=render.pal.lookup.bpp16[src[0]];src++; - *(Bit16u *)dest=val; - *(Bit16u *)(dest+render.op.pitch)=val; - dest+=2; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_16_DoubleBoth(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch+x*4; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=(2*render.op.pitch)-dx*4; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit16u val=render.pal.lookup.bpp16[src[0]];src++; - *(Bit16u *)(dest+0)=val; - *(Bit16u *)(dest+2)=val; - *(Bit16u *)(dest+render.op.pitch)=val; - *(Bit16u *)(dest+render.op.pitch+2)=val; - dest+=4; - } - src+=next_src;dest+=next_dest; - } -} - - -static void Render_Normal_32_None(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x*4; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=render.op.pitch-dx*4; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit32u val=render.pal.lookup.bpp32[src[0]];src++; - *(Bit32u *)dest=val; - dest+=4; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_32_DoubleWidth(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+y*render.op.pitch+x*8; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=render.op.pitch-dx*8; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit32u val=render.pal.lookup.bpp32[src[0]];src++; - *(Bit32u *)dest=val; - *(Bit32u *)(dest+4)=val; - dest+=8; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_32_DoubleHeight(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch+x*4; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=(2*render.op.pitch)-dx*4; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit32u val=render.pal.lookup.bpp32[src[0]];src++; - *(Bit32u *)dest=val; - *(Bit32u *)(dest+render.op.pitch)=val; - dest+=4; - } - src+=next_src;dest+=next_dest; - } -} - -static void Render_Normal_32_DoubleBoth(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) { - Bit8u * dest=(Bit8u *)render.op.pixels+2*y*render.op.pitch+x*8; - Bitu next_src=render.src.pitch-dx; - Bitu next_dest=(2*render.op.pitch)-dx*8; - for (;dy>0;dy--) { - for (Bitu tempx=dx;tempx>0;tempx--) { - Bit32u val=render.pal.lookup.bpp32[src[0]];src++; - *(Bit32u *)(dest+0)=val; - *(Bit32u *)(dest+4)=val; - *(Bit32u *)(dest+render.op.pitch)=val; - *(Bit32u *)(dest+render.op.pitch+4)=val; - dest+=8; - } - src+=next_src;dest+=next_dest; - } -} - - -static RENDER_Part_Handler Render_Normal_8_Table[4]= { - Render_Normal_8_None,Render_Normal_8_DoubleWidth,Render_Normal_8_DoubleHeight,Render_Normal_8_DoubleBoth -}; - -static RENDER_Part_Handler Render_Normal_16_Table[4]= { - Render_Normal_16_None,Render_Normal_16_DoubleWidth,Render_Normal_16_DoubleHeight,Render_Normal_16_DoubleBoth -}; - -static RENDER_Part_Handler Render_Normal_32_Table[4]= { - Render_Normal_32_None,Render_Normal_32_DoubleWidth,Render_Normal_32_DoubleHeight,Render_Normal_32_DoubleBoth -}; - - -static void Render_Normal_CallBack(Bitu width,Bitu height,Bitu bpp,Bitu pitch,Bitu flags) { - if (!(flags & MODE_SET)) return; - render.op.width=width; - render.op.height=height; - render.op.bpp=bpp; - render.op.pitch=pitch; - switch (bpp) { - case 8: - render.src.part_handler=Render_Normal_8_Table[render.src.flags]; - break; - case 16: - render.src.part_handler=Render_Normal_16_Table[render.src.flags]; - break; - case 32: - render.src.part_handler=Render_Normal_32_Table[render.src.flags]; - break; - default: - E_Exit("RENDER:Unsupported display depth of %d",bpp); - break; - } - RENDER_ResetPal(); -} diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 41b81fa..7aeda67 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.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,10 +15,16 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include #include -#include +#include + +#include "SDL.h" +#include "SDL_thread.h" #include "dosbox.h" #include "video.h" @@ -31,17 +37,33 @@ #include "debug.h" //#define DISABLE_JOYSTICK +#define C_GFXTHREADED 1 //Enabled by default + +#if defined(MACOSX) +extern char** environ; +#endif struct SDL_Block { - bool active; //If this isn't set don't draw + volatile bool active; //If this isn't set don't draw + volatile bool drawing; Bitu width; Bitu height; Bitu bpp; Bitu flags; GFX_ModeCallBack mode_callback; bool full_screen; + bool nowait; SDL_Surface * surface; + SDL_Surface * shadow_surface; SDL_Joystick * joy; + SDL_cond *cond; +#if C_GFXTHREADED + SDL_mutex *mutex; + SDL_Thread *thread; + SDL_sem *sem; + volatile bool kill_thread; +#endif + GFX_DrawCallBack draw_callback; struct { bool autolock; bool autoenable; @@ -58,17 +80,22 @@ static void CaptureMouse(void); static void ResetScreen(void) { GFX_Stop(); if (sdl.full_screen) { - /* First get the original resolution */ - sdl.surface=SDL_SetVideoMode(sdl.width,sdl.height,sdl.bpp,SDL_HWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN); + if (sdl.flags & GFX_SHADOW) { + /* 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 { + 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.surface==0) { - E_Exit("SDL:Would be nice if I could get a surface."); + E_Exit("SDL:Can't get a surface error:%s.",SDL_GetError()); } + SDL_WM_SetCaption(VERSION,VERSION); -/* also fill up gfx_info structure */ + Bitu flags=MODE_SET; if (sdl.full_screen) flags|=MODE_FULLSCREEN; if (sdl.mode_callback) sdl.mode_callback(sdl.surface->w,sdl.surface->h,sdl.surface->format->BitsPerPixel,sdl.surface->pitch,flags); @@ -76,20 +103,18 @@ static void ResetScreen(void) { } -void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu flags,GFX_ModeCallBack callback) { +void GFX_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu flags,GFX_ModeCallBack mode_callback, GFX_DrawCallBack draw_callback){ GFX_Stop(); sdl.width=width; sdl.height=height; sdl.bpp=bpp; sdl.flags=flags; - sdl.mode_callback=callback; + sdl.mode_callback=mode_callback; + sdl.draw_callback=draw_callback; ResetScreen(); - GFX_Start(); } - - static void CaptureMouse(void) { sdl.mouse.locked=!sdl.mouse.locked; if (sdl.mouse.locked) { @@ -109,32 +134,63 @@ static void SwitchFullScreen(void) { } else { if (sdl.mouse.locked) CaptureMouse(); } - ResetScreen(); } -//only prototype existed + void GFX_SwitchFullScreen(void) { SwitchFullScreen(); } -void * GFX_StartUpdate(void) { - if (sdl.active) { - if (SDL_MUSTLOCK(sdl.surface)) if (SDL_LockSurface(sdl.surface)) return 0; - return sdl.surface->pixels; - } else { - return 0; - } +static void SDL_DrawScreen(void) { + sdl.drawing=true; + if (SDL_MUSTLOCK(sdl.surface)) { + if (SDL_LockSurface(sdl.surface)) { + sdl.drawing=false; + return; + } + } + sdl.draw_callback(sdl.surface->pixels); + if (SDL_MUSTLOCK(sdl.surface)) { + SDL_UnlockSurface(sdl.surface); + } + SDL_Flip(sdl.surface); + sdl.drawing=false; } -void GFX_EndUpdate(void) { - if (SDL_MUSTLOCK(sdl.surface)) SDL_UnlockSurface(sdl.surface ); - if (sdl.full_screen) SDL_Flip(sdl.surface); - else SDL_UpdateRect(sdl.surface,0,0,0,0); +#if C_GFXTHREADED +int SDL_DisplayThread(void * data) { + while (!SDL_SemWait(sdl.sem)) { + if (sdl.kill_thread) return 0; + if (!sdl.active) continue; + if (sdl.drawing) continue; + SDL_mutexP(sdl.mutex); + SDL_DrawScreen(); + SDL_mutexV(sdl.mutex); + } + return 0; +} +#endif + +void GFX_DoUpdate(void) { + if (!sdl.active) + return; + if (sdl.drawing)return; +#if C_GFXTHREADED + SDL_SemPost(sdl.sem); +#else + SDL_DrawScreen(); +#endif + } void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { -/* I should probably not change the GFX_PalEntry :) */ +#if C_GFXTHREADED + if (SDL_mutexP(sdl.mutex)) { + E_Exit("SDL:Can't lock Mutex"); + }; +#endif + /* I should probably not change the GFX_PalEntry :) */ if (sdl.full_screen) { if (!SDL_SetPalette(sdl.surface,SDL_PHYSPAL,(SDL_Color *)entries,start,count)) { E_Exit("SDL:Can't set palette"); @@ -144,6 +200,11 @@ void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries) { E_Exit("SDL:Can't set palette"); } } +#if C_GFXTHREADED + if (SDL_mutexV(sdl.mutex)) { + E_Exit("SDL:Can't release Mutex"); + }; +#endif } Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) { @@ -151,9 +212,15 @@ Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue) { } void GFX_Stop() { +#if C_GFXTHREADED + SDL_mutexP(sdl.mutex); +#endif sdl.active=false; -} +#if C_GFXTHREADED + SDL_mutexV(sdl.mutex); +#endif +} void GFX_Start() { sdl.active=true; @@ -163,6 +230,18 @@ static void GUI_ShutDown(Section * sec) { GFX_Stop(); if (sdl.mouse.locked) CaptureMouse(); if (sdl.full_screen) SwitchFullScreen(); +#if C_GFXTHREADED + sdl.kill_thread=true; + SDL_SemPost(sdl.sem); + SDL_WaitThread(sdl.thread,0); + SDL_DestroyMutex(sdl.mutex); + SDL_DestroySemaphore(sdl.sem); +#endif + +} + +static void KillSwitch(void){ + throw 1; } static void GUI_StartUp(Section * sec) { @@ -171,23 +250,26 @@ static void GUI_StartUp(Section * sec) { Section_prop * section=static_cast(sec); sdl.active=false; sdl.full_screen=false; + sdl.nowait=section->Get_bool("nowait"); 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"); - GFX_SetSize(640,400,8,0,0); +#if C_GFXTHREADED + sdl.kill_thread=false; + sdl.mutex=SDL_CreateMutex(); + sdl.sem=SDL_CreateSemaphore(0); + sdl.thread=SDL_CreateThread(&SDL_DisplayThread,0); +#endif + /* Initialize screen for first time */ + GFX_SetSize(640,400,8,0,0,0); SDL_EnableKeyRepeat(250,30); - + SDL_EnableUNICODE(1); /* Get some Keybinds */ - KEYBOARD_AddEvent(KBD_f10,CTRL_PRESSED,CaptureMouse); - KEYBOARD_AddEvent(KBD_enter,ALT_PRESSED,SwitchFullScreen); -} - -void GFX_ShutDown() { - if (sdl.full_screen) SwitchFullScreen(); - if (sdl.mouse.locked) CaptureMouse(); - GFX_Stop(); + 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) { @@ -197,7 +279,7 @@ void Mouse_AutoLock(bool enable) { } static void HandleKey(SDL_KeyboardEvent * key) { - Bit32u code; + KBD_KEYS code; switch (key->keysym.sym) { case SDLK_1:code=KBD_1;break; case SDLK_2:code=KBD_2;break; @@ -253,8 +335,6 @@ static void HandleKey(SDL_KeyboardEvent * key) { case SDLK_F11:code=KBD_f11;break; case SDLK_F12:code=KBD_f12;break; -// KBD_esc,KBD_tab,KBD_backspace,KBD_enter,KBD_space, - case SDLK_ESCAPE:code=KBD_esc;break; case SDLK_TAB:code=KBD_tab;break; case SDLK_BACKSPACE:code=KBD_backspace;break; @@ -314,13 +394,19 @@ static void HandleKey(SDL_KeyboardEvent * key) { case SDLK_KP_ENTER:code=KBD_kpenter;break; case SDLK_KP_PERIOD:code=KBD_kpperiod;break; -// case SDLK_:code=key_;break; /* Special Keys */ default: -//TODO maybe give warning for keypress unknown - return; + code=KBD_1; + LOG(LOG_ERROR|LOG_KEYBOARD,"Unhandled SDL keysym %d",key->keysym.sym); + break; } - KEYBOARD_AddKey(code,(key->state==SDL_PRESSED)); + /* Check the modifiers */ + Bitu mod= + ((key->keysym.mod & KMOD_CTRL) ? KBD_MOD_CTRL : 0) | + ((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; + KEYBOARD_AddKey(code,ascii,mod,(key->state==SDL_PRESSED)); } static void HandleMouseMotion(SDL_MouseMotionEvent * motion) { @@ -395,7 +481,10 @@ static void HandleVideoResize(SDL_ResizeEvent * resize) { } +static Bit8u laltstate = SDL_KEYUP; + void GFX_Events() { + SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { @@ -408,6 +497,9 @@ void GFX_Events() { break; case SDL_KEYDOWN: case SDL_KEYUP: + // ignore event lalt+tab + if (event.key.keysym.sym==SDLK_LALT) laltstate = event.key.type; + if ((event.key.keysym.sym==SDLK_TAB) && (laltstate==SDL_KEYDOWN)) break; HandleKey(&event.key); break; case SDL_MOUSEMOTION: @@ -428,7 +520,7 @@ void GFX_Events() { HandleVideoResize(&event.resize); break; case SDL_QUIT: - E_Exit("Closed the SDL Window"); + throw(true); break; } } @@ -442,17 +534,17 @@ void GFX_ShowMsg(char * msg) { }; int main(int argc, char* argv[]) { - -#if C_DEBUG - DEBUG_SetupConsole(); -#endif - + try { CommandLine com_line(argc,argv); Config myconf(&com_line); control=&myconf; + +#if C_DEBUG + DEBUG_SetupConsole(); +#endif - if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER + if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_CDROM #ifndef DISABLE_JOYSTICK |SDL_INIT_JOYSTICK @@ -462,7 +554,7 @@ 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); /* Init all the dosbox subsystems */ DOSBOX_Init(); std::string config_file; @@ -473,6 +565,7 @@ int main(int argc, char* argv[]) { } /* Parse the config file */ control->ParseConfigFile(config_file.c_str()); + control->ParseEnv(environ); /* Init all the sections */ control->Init(); /* Some extra SDL Functions */ @@ -494,8 +587,11 @@ int main(int argc, char* argv[]) { if (sdl.full_screen) SwitchFullScreen(); if (sdl.mouse.locked) CaptureMouse(); LOG_MSG("Exit to error: %sPress enter to continue.",error); - fgetc(stdin); + if(!sdl.nowait) fgetc(stdin); } - GFX_ShutDown(); - return 0; + catch (...){ + if (sdl.full_screen) SwitchFullScreen(); + if (sdl.mouse.locked) CaptureMouse(); + } + return 0; }; diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am index 737c3eb..6fca05e 100644 --- a/src/hardware/Makefile.am +++ b/src/hardware/Makefile.am @@ -8,5 +8,5 @@ libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler 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_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h cmos.cpp disney.cpp \ - gus.cpp + gus.cpp mpu401.cpp diff --git a/src/hardware/Makefile.in b/src/hardware/Makefile.in index 179e9ef..b266eb2 100644 --- a/src/hardware/Makefile.in +++ b/src/hardware/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -91,7 +94,7 @@ libhardware_a_SOURCES = adlib.cpp dma.cpp gameblaster.cpp hardware.cpp iohandler 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_memory.cpp vga_misc.cpp vga_seq.cpp font-switch.h ega-switch.h cmos.cpp disney.cpp \ - gus.cpp + gus.cpp mpu401.cpp subdir = src/hardware mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -109,7 +112,8 @@ am_libhardware_a_OBJECTS = adlib.$(OBJEXT) dma.$(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) + vga_seq.$(OBJEXT) cmos.$(OBJEXT) disney.$(OBJEXT) gus.$(OBJEXT) \ + mpu401.$(OBJEXT) libhardware_a_OBJECTS = $(am_libhardware_a_OBJECTS) DEFS = @DEFS@ @@ -125,14 +129,14 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ ./$(DEPDIR)/hardware.Po ./$(DEPDIR)/iohandler.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/joystick.Po ./$(DEPDIR)/keyboard.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/memory.Po ./$(DEPDIR)/mixer.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/pcspeaker.Po ./$(DEPDIR)/pic.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/sblaster.Po ./$(DEPDIR)/tandy_sound.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/timer.Po ./$(DEPDIR)/vga.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_attr.Po ./$(DEPDIR)/vga_crtc.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_dac.Po ./$(DEPDIR)/vga_draw.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_fonts.Po ./$(DEPDIR)/vga_gfx.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_memory.Po ./$(DEPDIR)/vga_misc.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/vga_seq.Po +@AMDEP_TRUE@ ./$(DEPDIR)/mpu401.Po ./$(DEPDIR)/pcspeaker.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/pic.Po ./$(DEPDIR)/sblaster.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 CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) @@ -185,6 +189,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyboard.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mpu401.Po@am__quote@ @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@ @@ -259,7 +264,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -304,7 +309,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/hardware/cmos.cpp b/src/hardware/cmos.cpp index 9c20f9e..4ce97dc 100644 --- a/src/hardware/cmos.cpp +++ b/src/hardware/cmos.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 @@ -52,7 +52,7 @@ static void cmos_checktimer(void) { 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_DEBUG("RTC Timer at %f hz",1000000.0/cmos.timer.micro); + LOG(LOG_PIT,"RTC Timer at %f hz",1000000.0/cmos.timer.micro); PIC_AddEvent(cmos_timerevent,cmos.timer.micro); } @@ -77,25 +77,25 @@ static void cmos_writereg(Bit32u port,Bit8u val) { break; case 0x0a: /* Status reg A */ cmos.regs[cmos.reg]=val & 0x7f; - if (val & 0x70!=0x20) LOG_DEBUG("CMOS Illegal 22 stage divider value"); + if (val & 0x70!=0x20) LOG(LOG_ERROR|LOG_BIOS,"CMOS Illegal 22 stage divider value"); cmos.timer.div=(val & 0xf); cmos_checktimer(); break; case 0x0b: /* Status reg B */ cmos.regs[cmos.reg]=val & 0x7f; cmos.timer.enabled=(val & 0x40)>0; - if (val&0x10) LOG_DEBUG("CMOS:Updated ended interrupt not supported yet"); + if (val&0x10) LOG(LOG_ERROR|LOG_BIOS,"CMOS:Updated ended interrupt not supported yet"); cmos_checktimer(); break; default: cmos.regs[cmos.reg]=val & 0x7f; - LOG_DEBUG("CMOS:Unhandled register %x",cmos.reg); + LOG(LOG_ERROR|LOG_BIOS,"CMOS:Unhandled register %x",cmos.reg); } } static Bit8u cmos_readreg(Bit32u port) { if (cmos.reg>0x3f) { - LOG_DEBUG("CMOS:Read from illegal register %x",cmos.reg); + LOG(LOG_ERROR|LOG_BIOS,"CMOS:Read from illegal register %x",cmos.reg); return 0xff; } switch (cmos.reg) { @@ -115,4 +115,5 @@ void CMOS_Init(Section* sec) { IO_RegisterWriteHandler(0x71,cmos_writereg,"CMOS"); IO_RegisterReadHandler(0x71,cmos_readreg,"CMOS"); cmos.timer.enabled=false; -} \ No newline at end of file +} + diff --git a/src/hardware/disney.cpp b/src/hardware/disney.cpp index 0e2291c..b03fe52 100644 --- a/src/hardware/disney.cpp +++ b/src/hardware/disney.cpp @@ -1,3 +1,21 @@ +/* + * 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 "inout.h" @@ -20,8 +38,6 @@ static struct { Bit8u control; Bit8u buffer[DISNEY_SIZE]; Bitu used; - bool enabled; - Bit8u delay; MIXER_Channel * chan; } disney; @@ -31,7 +47,7 @@ static void disney_write(Bit32u port,Bit8u val) { disney.data=val; break; case 1: /* Status Port */ - LOG_WARN("DISNEY:Status write %x",val); + LOG(LOG_MISC,"DISNEY:Status write %x",val); break; case 2: /* Control Port */ // LOG_WARN("DISNEY:Control write %x",val); @@ -40,7 +56,7 @@ static void disney_write(Bit32u port,Bit8u val) { disney.buffer[disney.used++]=disney.data; } } - if (val&0x10) LOG_DEBUG("IRQ Enabled"); + if (val&0x10) LOG(LOG_ERROR,"DISNEY:Parallel IRQ Enabled"); disney.control=val; break; } @@ -50,16 +66,16 @@ static Bit8u disney_read(Bit32u port) { switch (port-DISNEY_BASE) { case 0: /* Data Port */ - LOG_WARN("DISNEY:Read from data port"); +// LOG(LOG_MISC,"DISNEY:Read from data port"); return disney.data; break; case 1: /* Status Port */ -// LOG_WARN("DISNEY:Read from status port %X",disney.status); +// LOG(LOG_MISC,"DISNEY:Read from status port %X",disney.status); if (disney.used>=16) return 0x40; else return 0x0; break; case 2: /* Control Port */ - LOG_WARN("DISNEY:Read from control port"); + LOG(LOG_MISC,"DISNEY:Read from control port"); return disney.control; break; } @@ -83,6 +99,10 @@ static void DISNEY_CallBack(Bit8u * stream,Bit32u len) { void DISNEY_Init(Section* sec) { + MSG_Add("DISNEY_CONFIGFILE_HELP","Nothing to setup yet!\n"); + Section_prop * section=static_cast(sec); + if(!section->Get_bool("enabled")) return; + IO_RegisterWriteHandler(DISNEY_BASE,disney_write,"DISNEY"); IO_RegisterWriteHandler(DISNEY_BASE+1,disney_write,"DISNEY"); IO_RegisterWriteHandler(DISNEY_BASE+2,disney_write,"DISNEY"); diff --git a/src/hardware/dma.cpp b/src/hardware/dma.cpp index c2e9aea..9f9e61b 100644 --- a/src/hardware/dma.cpp +++ b/src/hardware/dma.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,10 +21,8 @@ */ /* - Still need to implement reads from dma ports :) - Perhaps sometime also implement dma writes. - DMA transfer that get setup with a size 0 are also done wrong should be 0x10000 probably. - + TODO + Implement 16-bit dma */ #include @@ -32,6 +30,7 @@ #include "mem.h" #include "inout.h" #include "dma.h" +#include "pic.h" #if DEBUG_DMA #define DMA_DEBUG LOG_DEBUG @@ -47,8 +46,8 @@ struct DMA_CHANNEL { struct { Bit8u mode_type; - Bit8u address_decrement; - Bit8u autoinit_enable; + bool address_decrement; + bool autoinit_enable; Bit8u transfer_type; } mode; Bit16u base_address; @@ -59,6 +58,7 @@ struct DMA_CHANNEL { bool masked; PhysPt address; bool addr_changed; + DMA_EnableCallBack enable_callback; }; @@ -96,9 +96,13 @@ static Bit8u read_dma(Bit32u port) { ret=cont->status_reg; cont->status_reg&=0xf; /* Clear lower 4 bits on read */ break; - + case 0x0a: + case 0x0e: + /* Seem to return 0 on a real controller */ + ret=0x0; + break; default: - LOG_WARN("DMA:Unhandled read from %d",port); + LOG(LOG_ERROR,"DMA:Unhandled read from %X",port); } return ret; } @@ -107,9 +111,10 @@ static Bit8u read_dma(Bit32u port) { static void write_dma(Bit32u port,Bit8u val) { /* only use first dma for now */ DMA_CONTROLLER * cont=&dma[0]; - DMA_CHANNEL * chan=&cont->chan[port>>1]; + DMA_CHANNEL * chan; switch (port) { case 0x00:case 0x02:case 0x04:case 0x06: + chan=&cont->chan[port>>1]; if (cont->flipflop) { chan->base_address=(chan->base_address & 0xff00) | val; } else { @@ -119,6 +124,7 @@ static void write_dma(Bit32u port,Bit8u val) { chan->addr_changed=true; break; case 0x01:case 0x03:case 0x05:case 0x07: + chan=&cont->chan[port>>1]; if (cont->flipflop) { chan->base_count=(chan->base_count & 0xff00) | val; } else { @@ -128,7 +134,7 @@ static void write_dma(Bit32u port,Bit8u val) { chan->addr_changed=true; break; case 0x08: /* Command Register */ - if (val != 4) LOG_WARN("DMA1:Illegal command %2X",val); + if (val != 4) LOG(LOG_ERROR,"DMA1:Illegal command %2X",val); cont->command_reg=val; break; case 0x09: /* Request Register */ @@ -142,22 +148,27 @@ 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); break; case 0x0b: /* mode register */ + chan=&cont->chan[val & 0x3]; chan->mode.mode_type = (val >> 6) & 0x03; - chan->mode.address_decrement = (val >> 5) & 0x01; - chan->mode.autoinit_enable = (val >> 4) & 0x01; + chan->mode.address_decrement = (val & 0x20) > 0; + chan->mode.autoinit_enable = (val & 0x10) > 0; chan->mode.transfer_type = (val >> 2) & 0x03; if (chan->mode.address_decrement) { - LOG_WARN("DMA:Address Decrease not supported yet"); + LOG(LOG_ERROR,"DMA:Address Decrease not supported yet"); } break; case 0x0c: /* Clear Flip/Flip */ cont->flipflop=true; break; - }; + default: + LOG(LOG_ERROR,"DMA:Unhandled write %X to %X",val,port); + }; }; @@ -177,21 +188,20 @@ void write_dma_page(Bit32u port,Bit8u val) { dma[0].chan[channel].addr_changed=true; } -Bit16u DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { + +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; +} + + + +Bitu DMA_8_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { DMA_CHANNEL * chan=&dma[0].chan[dmachan]; - - if (chan->masked) return 0; - if (!count) return 0; -/* DMA always does autoinit should work under normal situations */ - if (chan->addr_changed) { - /* Calculate the new starting position for dma read*/ - 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; - DMA_DEBUG("DMA:Transfer from %d size %d",(chan->page << 16)+chan->base_address,chan->current_count); - } + if (chan->masked || !count) return 0; + if (chan->addr_changed) ResetDMA8(chan); if (chan->current_count>count) { MEM_BlockRead(chan->address,buffer,count); chan->address+=count; @@ -204,17 +214,15 @@ Bit16u DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { if (!chan->mode.autoinit_enable) { /* Set the end of counter bit */ dma[0].status_reg|=(1 << dmachan); - count=(Bit16u)chan->current_count; + count=chan->current_count; chan->current_address+=count;; chan->current_count=0; return count; } else { buffer+=chan->current_count; - Bit16u left=count-(Bit16u)chan->current_count; + Bitu left=count-(Bit16u)chan->current_count; /* Autoinit reset the dma channel */ - chan->address=(chan->page << 16)+chan->base_address; - chan->current_count=chan->base_count+1; - chan->current_address=chan->base_address; + ResetDMA8(chan); /* Copy the rest of the buffer */ MEM_BlockRead(chan->address,buffer,left); chan->address+=left; @@ -223,22 +231,52 @@ Bit16u DMA_8_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { return count; } } -}; +} -Bit16u DMA_8_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { - - return 0; -}; +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->addr_changed) ResetDMA8(chan); + if (chan->current_count>count) { + MEM_BlockWrite(chan->address,buffer,count); + chan->address+=count; + chan->current_address+=count; + chan->current_count-=count; + return count; + } else { + /* Copy remaining piece of first buffer */ + MEM_BlockWrite(chan->address,buffer,chan->current_count); + if (!chan->mode.autoinit_enable) { + /* Set the end of counter bit */ + dma[0].status_reg|=(1 << dmachan); + count=chan->current_count; + chan->current_address+=count;; + chan->current_count=0; + return count; + } else { + buffer+=chan->current_count; + Bitu left=count-(Bit16u)chan->current_count; + /* Autoinit reset the dma channel */ + ResetDMA8(chan); + /* Copy the rest of the buffer */ + MEM_BlockWrite(chan->address,buffer,left); + chan->address+=left; + chan->current_address+=left; + chan->current_count-=left; + return count; + } + } +} -Bit16u DMA_16_Read(Bit32u dmachan,Bit8u * buffer,Bit16u count) { +Bitu DMA_16_Read(Bitu dmachan,Bit8u * buffer,Bitu count) { return 0; } -Bit16u DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { +Bitu DMA_16_Write(Bitu dmachan,Bit8u * buffer,Bitu count) { return 0; @@ -247,6 +285,18 @@ Bit16u DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) { +void DMA_SetEnableCallBack(Bitu channel,DMA_EnableCallBack callback) { + 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); + } +} + void DMA_Init(Section* sec) { for (Bit32u i=0;i<0x10;i++) { IO_RegisterWriteHandler(i,write_dma,"DMA1"); diff --git a/src/hardware/gameblaster.cpp b/src/hardware/gameblaster.cpp index c6494f5..3deb674 100644 --- a/src/hardware/gameblaster.cpp +++ b/src/hardware/gameblaster.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 @@ -23,124 +23,389 @@ #include "mem.h" #include "hardware.h" #include "setup.h" +#include "pic.h" +#define LEFT 0x00 +#define RIGHT 0x01 +#define CMS_BUFFER_SIZE 128 #define CMS_RATE 22050 -#define CMS_VOLUME 6000 -#define FREQ_SHIFT 16 -#define SIN_ENT 1024 -#define SIN_MAX (SIN_ENT << FREQ_SHIFT) +typedef Bit8u UINT8; +typedef Bit16s INT16; -#ifndef PI -#define PI 3.14159265358979323846 -#endif +/* this structure defines a channel */ +struct saa1099_channel +{ + int frequency; /* frequency (0x00..0xff) */ + int freq_enable; /* frequency enable */ + int noise_enable; /* noise enable */ + int octave; /* octave (0x00..0x07) */ + int amplitude[2]; /* amplitude (0x00..0x0f) */ + int envelope[2]; /* envelope (0x00..0x0f or 0x10 == off) */ -struct CMS { - struct { - Bit32u freq_pos; - Bit32u freq_add; - Bit16s * vol_left; - Bit16s * vol_right; - Bit8u octave; - Bit8u freq; - } chan[6]; - struct { - Bit32u freq_pos; - Bit32u freq_add; - Bit32u random_val; - } noise[2]; - - Bit8u voice_enabled; - Bit8u noise_enabled; - Bit8u reg; + /* vars to simulate the square wave */ + double counter; + double freq; + int level; }; -static Bit32u freq_table[256][8]; -static Bit32u noise_freq[3]; -static Bit16s vol_table[16]; -static Bit16s sin_table[16][SIN_ENT]; +/* this structure defines a noise channel */ +struct saa1099_noise +{ + /* vars to simulate the noise generator output */ + double counter; + double freq; + int level; /* noise polynomal shifter */ +}; +/* this structure defines a SAA1099 chip */ +struct SAA1099 +{ + int stream; /* our stream */ + int noise_params[2]; /* noise generators parameters */ + int env_enable[2]; /* envelope generators enable */ + int env_reverse_right[2]; /* envelope reversed for right channel */ + int env_mode[2]; /* envelope generators mode */ + int env_bits[2]; /* non zero = 3 bits resolution */ + int env_clock[2]; /* envelope clock mode (non-zero external) */ + int env_step[2]; /* current envelope step */ + int all_ch_enable; /* all channels enable */ + int sync_state; /* sync all channels */ + int selected_reg; /* selected register */ + struct saa1099_channel channels[6]; /* channels */ + struct saa1099_noise noise[2]; /* noise generators */ +}; + +static UINT8 envelope[8][64] = { + /* zero amplitude */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* maximum amplitude */ + {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, }, + /* single decay */ + {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive decay */ + {15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, + /* single triangular */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive triangular */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, + /* single attack */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + /* repetitive attack */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 } +}; + + +static int amplitude_lookup[16] = { + 0*32767/16, 1*32767/16, 2*32767/16, 3*32767/16, + 4*32767/16, 5*32767/16, 6*32767/16, 7*32767/16, + 8*32767/16, 9*32767/16, 10*32767/16, 11*32767/16, + 12*32767/16, 13*32767/16, 14*32767/16, 15*32767/16 +}; + +/* global parameters */ +static double sample_rate; +static SAA1099 saa1099[2]; static MIXER_Channel * cms_chan; -static CMS cms_block[2]; +static Bit16s cms_buffer[2][2][CMS_BUFFER_SIZE]; +static Bit16s * cms_buf_point[4] = { + cms_buffer[0][0],cms_buffer[0][1],cms_buffer[1][0],cms_buffer[1][1] }; -static void write_cms(Bit32u port,Bit8u val) { - Bit32u sel=(port>>1)&1; - CMS * cms=&cms_block[sel]; - switch (port & 1) { - case 1: /* Register Select */ - cms->reg=val; - break; - case 0: /* Write Register */ - switch (cms->reg) { - case 0x00: case 0x01: case 0x02: /* Volume Select */ - case 0x03: case 0x04: case 0x05: - cms->chan[cms->reg].vol_left=sin_table[val & 0xf]; - cms->chan[cms->reg].vol_right=sin_table[(val>>4) & 0xf]; - break; - case 0x08: case 0x09: case 0x0a: /* Frequency Select */ - case 0x0b: case 0x0c: case 0x0d: - { - Bit8u chan=cms->reg-0x08; - cms->chan[chan].freq=val; - /* Get a new entry in the freq table */ - cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave]; - break; - } - case 0x10: case 0x11: case 0x12: /* Octave Select */ - { - Bit8u chan=(cms->reg-0x10)*2; - cms->chan[chan].octave=val&7; - cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave]; - chan++; - cms->chan[chan].octave=(val>>4)&7; - cms->chan[chan].freq_add=freq_table[cms->chan[chan].freq][cms->chan[chan].octave]; - } - break; - case 0x14: /* Frequency enable */ - cms->voice_enabled=val; - //TODO Check for enabling of speaker maybe - break; - case 0x15: /* Noise Enable */ - cms->noise_enabled=val; - //TODO Check for enabling of speaker maybe - break; - case 0x16: /* Noise generator setup */ - cms->noise[0].freq_add=noise_freq[val & 3]; - cms->noise[1].freq_add=noise_freq[(val>>4) & 3]; - break; - default: - LOG_ERROR("CMS %d:Illegal register %X2 Selected for write",sel,cms->reg); - break; - }; - break; +static Bitu last_command; + + +static void saa1099_envelope(int chip, int ch) +{ + struct SAA1099 *saa = &saa1099[chip]; + if (saa->env_enable[ch]) + { + int step, mode, mask; + mode = saa->env_mode[ch]; + /* step from 0..63 and then loop in steps 32..63 */ + step = saa->env_step[ch] = + ((saa->env_step[ch] + 1) & 0x3f) | (saa->env_step[ch] & 0x20); + + mask = 15; + if (saa->env_bits[ch]) + mask &= ~1; /* 3 bit resolution, mask LSB */ + + saa->channels[ch*3+0].envelope[ LEFT] = + saa->channels[ch*3+1].envelope[ LEFT] = + saa->channels[ch*3+2].envelope[ LEFT] = envelope[mode][step] & mask; + if (saa->env_reverse_right[ch] & 0x01) + { + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = (15 - envelope[mode][step]) & mask; + } + else + { + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = envelope[mode][step] & mask; + } + } + else + { + /* envelope mode off, set all envelope factors to 16 */ + saa->channels[ch*3+0].envelope[ LEFT] = + saa->channels[ch*3+1].envelope[ LEFT] = + saa->channels[ch*3+2].envelope[ LEFT] = + saa->channels[ch*3+0].envelope[RIGHT] = + saa->channels[ch*3+1].envelope[RIGHT] = + saa->channels[ch*3+2].envelope[RIGHT] = 16; + } +} + + +static void saa1099_update(int chip, INT16 **buffer, int length) +{ + struct SAA1099 *saa = &saa1099[chip]; + int j, ch; + + /* if the channels are disabled we're done */ + if (!saa->all_ch_enable) + { + /* init output data */ + memset(buffer[LEFT],0,length*sizeof(INT16)); + memset(buffer[RIGHT],0,length*sizeof(INT16)); + return; } -}; + for (ch = 0; ch < 2; ch++) + { + switch (saa->noise_params[ch]) + { + case 0: saa->noise[ch].freq = 31250.0 * 2; break; + case 1: saa->noise[ch].freq = 15625.0 * 2; break; + case 2: saa->noise[ch].freq = 7812.5 * 2; break; + case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break; + } + } -static void CMS_CallBack(Bit8u * stream,Bit32u len) { - /* Generate the CMS wave */ - /* Generate 12 channels of sound data this could be nice */ - for (Bit32u l=0;lnoise_enabled & use_voice) { + /* fill all data needed */ + for( j = 0; j < length; j++ ) + { + int output_l = 0, output_r = 0; - } else if (cms->voice_enabled & use_voice) { - int pos=cms->chan[chan].freq_pos>>FREQ_SHIFT; - left+=cms->chan[chan].vol_left[pos]; - right+=cms->chan[chan].vol_right[pos]; - cms->chan[chan].freq_pos+=cms->chan[chan].freq_add; - if (cms->chan[chan].freq_pos>=SIN_MAX) - cms->chan[chan].freq_pos-=SIN_MAX; + /* for each channel */ + for (ch = 0; ch < 6; ch++) + { + if (saa->channels[ch].freq == 0.0) + saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / + (511.0 - (double)saa->channels[ch].frequency); + + /* check the actual position in the square wave */ + saa->channels[ch].counter -= saa->channels[ch].freq; + while (saa->channels[ch].counter < 0) + { + /* calculate new frequency now after the half wave is updated */ + saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / + (511.0 - (double)saa->channels[ch].frequency); + + saa->channels[ch].counter += sample_rate; + saa->channels[ch].level ^= 1; + + /* eventually clock the envelope counters */ + if (ch == 1 && saa->env_clock[0] == 0) + saa1099_envelope(chip, 0); + if (ch == 4 && saa->env_clock[1] == 0) + saa1099_envelope(chip, 1); + } + + /* if the noise is enabled */ + if (saa->channels[ch].noise_enable) + { + /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */ + if (saa->noise[ch/3].level & 1) + { + /* subtract to avoid overflows, also use only half amplitude */ + output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2; + output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2; + } + } + + /* if the square wave is enabled */ + if (saa->channels[ch].freq_enable) + { + /* if the channel level is high */ + if (saa->channels[ch].level & 1) + { + output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16; + output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16; } - use_voice<<=1; } } + + for (ch = 0; ch < 2; ch++) + { + /* check the actual position in noise generator */ + saa->noise[ch].counter -= saa->noise[ch].freq; + while (saa->noise[ch].counter < 0) + { + saa->noise[ch].counter += sample_rate; + if( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) ) + saa->noise[ch].level = (saa->noise[ch].level << 1) | 1; + else + saa->noise[ch].level <<= 1; + } + } + /* write sound data to the buffer */ + buffer[LEFT][j] = output_l / 6; + buffer[RIGHT][j] = output_r / 6; + } +} + +static void saa1099_write_port_w( int chip, int offset, int data ) +{ + struct SAA1099 *saa = &saa1099[chip]; + int reg = saa->selected_reg; + int ch; + + switch (reg) + { + /* channel i amplitude */ + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: + ch = reg & 7; + saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f]; + saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f]; + break; + /* channel i frequency */ + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: + ch = reg & 7; + saa->channels[ch].frequency = data & 0xff; + break; + /* channel i octave */ + case 0x10: case 0x11: case 0x12: + ch = (reg - 0x10) << 1; + saa->channels[ch + 0].octave = data & 0x07; + saa->channels[ch + 1].octave = (data >> 4) & 0x07; + break; + /* channel i frequency enable */ + case 0x14: + saa->channels[0].freq_enable = data & 0x01; + saa->channels[1].freq_enable = data & 0x02; + saa->channels[2].freq_enable = data & 0x04; + saa->channels[3].freq_enable = data & 0x08; + saa->channels[4].freq_enable = data & 0x10; + saa->channels[5].freq_enable = data & 0x20; + break; + /* channel i noise enable */ + case 0x15: + saa->channels[0].noise_enable = data & 0x01; + saa->channels[1].noise_enable = data & 0x02; + saa->channels[2].noise_enable = data & 0x04; + saa->channels[3].noise_enable = data & 0x08; + saa->channels[4].noise_enable = data & 0x10; + saa->channels[5].noise_enable = data & 0x20; + break; + /* noise generators parameters */ + case 0x16: + saa->noise_params[0] = data & 0x03; + saa->noise_params[1] = (data >> 4) & 0x03; + break; + /* envelope generators parameters */ + case 0x18: case 0x19: + ch = reg - 0x18; + saa->env_reverse_right[ch] = data & 0x01; + saa->env_mode[ch] = (data >> 1) & 0x07; + saa->env_bits[ch] = data & 0x10; + saa->env_clock[ch] = data & 0x20; + saa->env_enable[ch] = data & 0x80; + /* reset the envelope */ + saa->env_step[ch] = 0; + break; + /* channels enable & reset generators */ + case 0x1c: + saa->all_ch_enable = data & 0x01; + saa->sync_state = data & 0x02; + if (data & 0x02) + { + int i; +// logerror("%04x: (SAA1099 #%d) -reg 0x1c- Chip reset\n",activecpu_get_pc(), chip); + /* Synch & Reset generators */ + for (i = 0; i < 6; i++) + { + saa->channels[i].level = 0; + saa->channels[i].counter = 0.0; + } + } + 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); + } +} + + +static void write_cms(Bit32u port,Bit8u val) { + if (last_command + 100 < PIC_Ticks) MIXER_Enable(cms_chan,true); + last_command = PIC_Ticks; + switch (port) { + case 0x0220: + saa1099_write_port_w(0,1,val); + break; + case 0x221: + saa1099[0].selected_reg = val & 0x1f; + if (saa1099[0].selected_reg == 0x18 || saa1099[0].selected_reg == 0x19) { + /* clock the envelope channels */ + if (saa1099[0].env_clock[0]) saa1099_envelope(0,0); + if (saa1099[0].env_clock[1]) saa1099_envelope(0,1); + } + break; + case 0x0222: + saa1099_write_port_w(1,1,val); + break; + case 0x223: + saa1099[1].selected_reg = val & 0x1f; + + if (saa1099[1].selected_reg == 0x18 || saa1099[1].selected_reg == 0x19) { + /* clock the envelope channels */ + if (saa1099[1].env_clock[0]) saa1099_envelope(1,0); + if (saa1099[1].env_clock[1]) saa1099_envelope(1,1); + } + break; + } + if (last_command > PIC_Ticks+1000) MIXER_Enable(cms_chan,true); +} + + static void CMS_CallBack(Bit8u * stream,Bit32u len) { + if (len > CMS_BUFFER_SIZE) return; + + saa1099_update(0, &cms_buf_point[0], (int)len); + saa1099_update(1, &cms_buf_point[2], (int)len); + + /* Mix chip outputs */ + for (Bitu l=0;lMAX_AUDIO) *(Bit16s *)stream=MAX_AUDIO; else if (left(sec); if(!section->Get_bool("cms")) return; - Bits i; + sample_rate=section->Get_int("cmsrate"); + + IO_RegisterWriteHandler(0x220,write_cms,"CMS"); + IO_RegisterWriteHandler(0x221,write_cms,"CMS"); + IO_RegisterWriteHandler(0x222,write_cms,"CMS"); + IO_RegisterWriteHandler(0x223,write_cms,"CMS"); + /* Register the Mixer CallBack */ + cms_chan=MIXER_AddChannel(CMS_CallBack,CMS_RATE,"CMS"); MIXER_SetMode(cms_chan,MIXER_16STEREO); - MIXER_Enable(cms_chan,false); -/* Make the frequency/octave table */ - double log_start=log10(27.34375); - double log_add=(log10(54.609375)-log10(27.34375))/256; - for (i=0;i<256;i++) { - double freq=pow(10,log_start); - for (int k=0;k<8;k++) { - freq_table[i][k]=(Bit32u)((double)SIN_MAX/(CMS_RATE/freq)); - freq*=2; - } - log_start+=log_add; + MIXER_Enable(cms_chan,true); + last_command=PIC_Ticks; + + for (int s=0;s<2;s++) { + struct SAA1099 *saa = &saa1099[s]; + + memset(saa, 0, sizeof(struct SAA1099)); } -// noise_freq[0]=(Bit32u)(FREQ_MAX/((float)CMS_RATE/(float)28000)); -// noise_freq[1]=(Bit32u)(FREQ_MAX/((float)CMS_RATE/(float)14000)); -// noise_freq[2]=(Bit32u)(FREQ_MAX/((float)CMS_RATE/(float)6800)); - for (int s=0;s=0;i--) { - sin_table[i][s]=(Bit16s)out; -// out /= (float)1.258925412; /* = 10 ^ (2/20) = 2dB */ - out /= 1.1; - } - } - CMS_Enable(true); } diff --git a/src/hardware/gus.cpp b/src/hardware/gus.cpp index 160feac..bb71639 100644 --- a/src/hardware/gus.cpp +++ b/src/hardware/gus.cpp @@ -14,7 +14,7 @@ void GUS_Init(Section* sec) { - + MSG_Add("GUS_CONFIGFILE_HELP","Nothing to setup yet!\n"); diff --git a/src/hardware/iohandler.cpp b/src/hardware/iohandler.cpp index 0a499c4..13138f8 100644 --- a/src/hardware/iohandler.cpp +++ b/src/hardware/iohandler.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 @@ -24,12 +24,12 @@ IO_WriteBlock IO_WriteTable[IO_MAX]; void IO_Write(Bitu num,Bit8u val) { if (num=KEYBUFSIZE) keyb.buf_pos=0; +/* Read an entry from the keycode buffer */ +void KEYBOARD_GetCode(void) { + keyb.scheduled=false; + switch (keyb.buf.state) { + case STATE_NORMAL: + /* Check for a next key */ + if (!keyb.buf.used) return; + keyb.buf.used--; + keyb.buf.pos++; + if (keyb.buf.pos>=KEYBUFSIZE) keyb.buf.pos-=KEYBUFSIZE; + keyb.buf.state=keyb.buf.code[keyb.buf.pos].state; + break; + case STATE_EXTEND: + keyb.buf.state=STATE_NORMAL; + break; } - if (keyb.buf_used) { - keyb.read_active=true; - PIC_ActivateIRQ(1); + PIC_ActivateIRQ(1); +} + +void KEYBOARD_AddCode(Bit8u scancode,Bit8u ascii,Bitu mod,KeyStates state) { +// LOG_MSG("Add key scan %d ascii %c",scancode,ascii); + if (keyb.buf.used=KEYBUFSIZE) start-=KEYBUFSIZE; + keyb.buf.code[start].scancode=scancode; + keyb.buf.code[start].ascii=ascii; + keyb.buf.code[start].state=state; + keyb.buf.code[start].mod=mod; + } + /* Start up an event to start the first IRQ */ + if (!keyb.scheduled) { + keyb.scheduled=true; + PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); } } -void KEYBOARD_AddCode(Bit8u code) { - if (keyb.buf_used=KEYBUFSIZE) start-=KEYBUFSIZE; - keyb.buf[start]=code; - keyb.read_active=true; +void KEYBOARD_ReadKey(Bitu & scancode,Bitu & ascii,Bitu & mod) { + switch (keyb.buf.state) { + case STATE_NORMAL: + if (keyb.buf.used && !keyb.scheduled) { + keyb.scheduled=true; + PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); + } + scancode=keyb.buf.code[keyb.buf.pos].scancode; + ascii=keyb.buf.code[keyb.buf.pos].ascii; + mod=keyb.buf.code[keyb.buf.pos].mod; + break; + case STATE_EXTEND: + scancode=224; + mod=0; + ascii=0; + if (!keyb.scheduled) { + keyb.scheduled=true; + PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); + } + break; } - if (keyb.buf_used==1) PIC_AddIRQ(1,0); } static Bit8u read_p60(Bit32u port) { - /* Reading this port signals that IRQ can be lowered */ - Bit8u val=keyb.buf[keyb.buf_pos]; - keyb.read_active=false; - return keyb.buf[keyb.buf_pos]; -} + switch (keyb.buf.state) { + case STATE_NORMAL: + if (keyb.buf.used && !keyb.scheduled) { + keyb.scheduled=true; + PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); + } + return keyb.buf.code[keyb.buf.pos].scancode; + case STATE_EXTEND: + if (!keyb.scheduled) { + keyb.scheduled=true; + PIC_AddEvent(KEYBOARD_GetCode,KEYDELAY); + } + return 224; + } + return 0; +} static void write_p60(Bit32u port,Bit8u val) { switch (keyb.command) { @@ -105,27 +164,27 @@ static void write_p60(Bit32u port,Bit8u val) { switch (val) { case 0xed: /* Set Leds */ keyb.command=CMD_SETLEDS; - KEYBOARD_AddCode(0xfa); /* Acknowledge */ + KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ break; case 0xee: /* Echo */ - KEYBOARD_AddCode(0xee); + KEYBOARD_AddCode(0xee,0,0,STATE_NORMAL); break; case 0xf2: /* Identify keyboard */ /* AT's just send acknowledge */ - KEYBOARD_AddCode(0xfa); /* Acknowledge */ + KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ break; case 0xf3: /* Typematic rate programming */ keyb.command=CMD_SETTYPERATE; - KEYBOARD_AddCode(0xfa); /* Acknowledge */ + KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ break; default: - LOG_DEBUG("KEYB:60:Unhandled command %X",val); + LOG(LOG_ERROR|LOG_KEYBOARD,"60:Unhandled command %X",val); } return; case CMD_SETTYPERATE: case CMD_SETLEDS: keyb.command=CMD_NONE; - KEYBOARD_AddCode(0xfa); /* Acknowledge */ + KEYBOARD_AddCode(0xfa,0,0,STATE_NORMAL); /* Acknowledge */ break; } } @@ -133,21 +192,16 @@ static void write_p60(Bit32u port,Bit8u val) { static Bit8u read_p61(Bit32u port) { port_61_data^=0x20; return port_61_data; - -}; - -static void KEYBOARD_IRQHandler(void) { - if (!keyb.read_active) KEYBOARD_ReadBuffer(); } static void write_p61(Bit32u port,Bit8u val) { - port_61_data=val; +/* if (val & 128) if (!keyb.read_active) KEYBOARD_ReadBuffer(); - if ((val & 3)==3) { - PCSPEAKER_Enable(true); - } else { - PCSPEAKER_Enable(false); - } + Keys should get acknowledged just by reading 0x60. + Perhaps disable controller when bit 7=1 +*/ + if ((port_61_data ^val) & 3) PCSPEAKER_SetType(val & 3); + port_61_data=val; } static void write_p64(Bit32u port,Bit8u val) { @@ -159,21 +213,20 @@ static void write_p64(Bit32u port,Bit8u val) { keyb.active=false; break; default: - LOG_DEBUG("Port 64 write with val %d",val); + LOG(LOG_ERROR|LOG_KEYBOARD,"Port 64 write with val %d",val); break; } } static Bit8u read_p64(Bit32u port) { - return 0x1c | (keyb.read_active ? 0x1 : 0x0); + return 0x1c | (keyb.buf.used ? 0x1 : 0x0); } - 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_ERROR("KEYBOARD:Illegal key %d for handler",keytype); + LOG(LOG_ERROR|LOG_KEYBOARD,"Illegal key %d for handler",keytype); } newevent->next=event_handlers[keytype]; event_handlers[keytype]=newevent; @@ -182,9 +235,9 @@ void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler) newevent->handler=handler; } -void KEYBOARD_AddKey(Bitu keytype,bool pressed) { - bool extend=false; - Bit8u ret=0; + +void KEYBOARD_AddKey(KBD_KEYS keytype,Bitu unicode,Bitu mod,bool pressed) { + Bit8u ret=0;bool extend=false; switch (keytype) { case KBD_esc:ret=1;break; case KBD_1:ret=2;break; @@ -217,9 +270,7 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) { case KBD_leftbracket:ret=26;break; case KBD_rightbracket:ret=27;break; case KBD_enter:ret=28;break; - case KBD_leftctrl:ret=29; - shift_state=(shift_state&~CTRL_PRESSED)|(pressed ? CTRL_PRESSED:0); - break; + case KBD_leftctrl:ret=29;break; case KBD_a:ret=30;break; case KBD_s:ret=31;break; @@ -234,9 +285,7 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) { case KBD_semicolon:ret=39;break; case KBD_quote:ret=40;break; case KBD_grave:ret=41;break; - case KBD_leftshift:ret=42; - shift_state=(shift_state&~SHIFT_PRESSED)|(pressed ? SHIFT_PRESSED:0); - break; + case KBD_leftshift:ret=42;break; case KBD_backslash:ret=43;break; case KBD_z:ret=44;break; case KBD_x:ret=45;break; @@ -251,9 +300,7 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) { case KBD_slash:ret=53;break; case KBD_rightshift:ret=54;break; case KBD_kpmultiply:ret=55;break; - case KBD_leftalt:ret=56; - shift_state=(shift_state&~ALT_PRESSED)|(pressed ? ALT_PRESSED:0); - break; + case KBD_leftalt:ret=56;break; case KBD_space:ret=57;break; case KBD_capslock:ret=58;break; @@ -291,13 +338,9 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) { //The Extended keys case KBD_kpenter:extend=true;ret=28;break; - case KBD_rightctrl:extend=true;ret=29; - shift_state=(shift_state&~CTRL_PRESSED)|(pressed ? CTRL_PRESSED:0); - break; + case KBD_rightctrl:extend=true;ret=29;break; case KBD_kpslash:extend=true;ret=53;break; - case KBD_rightalt:extend=true;ret=56; - shift_state=(shift_state&~ALT_PRESSED)|(pressed ? ALT_PRESSED:0); - break; + case KBD_rightalt:extend=true;ret=56;break; case KBD_home:extend=true;ret=71;break; case KBD_up:extend=true;ret=72;break; case KBD_pageup:extend=true;ret=73;break; @@ -315,7 +358,7 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) { /* check for active key events */ KeyEvent * checkevent=event_handlers[keytype]; while (checkevent) { - if ((shift_state & checkevent->state)==checkevent->state) { + if ((mod & checkevent->state)==checkevent->state) { if (checkevent->type==keytype && pressed) { (*checkevent->handler)(); return; @@ -324,9 +367,9 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) { } checkevent=checkevent->next; } - if (extend) KEYBOARD_AddCode(224); + /* Add the actual key in the keyboard queue */ if (!pressed) ret+=128; - KEYBOARD_AddCode(ret); + KEYBOARD_AddCode(ret,(Bit8u)unicode,mod,extend ? STATE_EXTEND : STATE_NORMAL); } void KEYBOARD_Init(Section* sec) { @@ -337,11 +380,11 @@ void KEYBOARD_Init(Section* sec) { IO_RegisterWriteHandler(0x64,write_p64,"Keyboard"); IO_RegisterReadHandler(0x64,read_p64,"Keyboard"); - port_61_data=1; /* Speaker control through PIT and speaker disabled */ + port_61_data=0; /* Direct Speaker control and output disabled */ // memset(&event_handlers,0,sizeof(event_handlers)); /* Clear the keyb struct */ keyb.enabled=true; keyb.command=CMD_NONE; + keyb.last_index=0; KEYBOARD_ClrBuffer(); - PIC_RegisterIRQ(1,KEYBOARD_IRQHandler,"KEYBOARD"); } diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index 9ce74ac..cec5c27 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -89,11 +89,11 @@ void MEM_StrCopy(PhysPt off,char * data,Bitu size) { } static Bit8u Illegal_ReadHandler(PhysPt pt) { - LOG_ERROR("Illegal read from address %4X",pt); + LOG(LOG_ERROR,"MEM:Illegal read from address %4X",pt); return 0; } static void Illegal_WriteHandler(PhysPt pt,Bit8u val) { - LOG_ERROR("Illegal write val %2X to address %4X",val,pt); + 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 :) */ @@ -129,7 +129,7 @@ void MEM_ClearPageHandlers(Bitu startpage,Bitu pages) { void MEM_SetupMapping(Bitu startpage,Bitu pages,void * data) { if (startpage+pages>=MAX_PAGE_LIMIT) E_Exit("Memory:Illegal page for handler"); HostPt base=(HostPt)(data)-startpage*PAGE_SIZE; - if (!base) LOG_DEBUG("MEMORY:Unlucky memory allocation"); + if (!base) LOG_MSG("MEMORY:Unlucky memory allocation"); for (Bitu i=startpage;i -#include +#include +#include + +#include "SDL.h" +#include "mem.h" #include "dosbox.h" #include "mixer.h" #include "timer.h" +#include "setup.h" +#include "cross.h" +#include "support.h" +#include "keyboard.h" #define MIXER_MAXCHAN 8 -#define MIXER_BLOCKSIZE 1024 -#define MIXER_BUFSIZE MIXER_BLOCKSIZE*8 +#define MIXER_BUFSIZE (16*1024) #define MIXER_SSIZE 4 #define MIXER_SHIFT 16 #define MIXER_REMAIN ((1<MAX_AUDIO) ? (Bit16s)MAX_AUDIO : (SAMPhandler)(((Bit8u*)&mix_temp)+sizeof(mix_temp.TYPE[0]),sample_toread); \ + (chan->handler)(((Bit8u*)&mixer.temp)+sizeof(mixer.temp.TYPE[0]),sample_toread); \ Bitu sample_index=(1 << MIXER_SHIFT) - chan->sample_left; \ Bit32s newsample; \ for (Bitu mix=0;mix> MIXER_SHIFT;sample_index+=chan->sample_add; \ - newsample=mix_buftemp[mix][0]+MAKE_##TYPE( LCHAN ); \ - mix_buftemp[mix][0]=MIXER_CLIP(newsample); \ - newsample=mix_buftemp[mix][1]+MAKE_##TYPE( RCHAN ); \ - mix_buftemp[mix][1]=MIXER_CLIP(newsample); \ + newsample=mixer.work[mix][0]+MAKE_##TYPE( LCHAN ); \ + mixer.work[mix][0]=MIXER_CLIP(newsample); \ + newsample=mixer.work[mix][1]+MAKE_##TYPE( RCHAN ); \ + mixer.work[mix][1]=MIXER_CLIP(newsample); \ } \ - chan->remain.TYPE[LCHAN]=mix_temp.TYPE[sample_index>>MIXER_SHIFT][LCHAN]; \ - if (RCHAN) chan->remain.TYPE[RCHAN]=mix_temp.TYPE[sample_index>>MIXER_SHIFT][RCHAN];\ + chan->remain=*(Bitu *)&mixer.temp.TYPE[sample_index>>MIXER_SHIFT]; \ chan->sample_left=sample_total-sample_index; \ break; \ } -union Sample { - Bit16s m16[1]; - Bit16s s16[2]; - Bit8u m8[1]; - Bit8u s8[2]; - Bit32u full; -}; - struct MIXER_Channel { Bit8u volume; Bit8u mode; @@ -75,29 +73,45 @@ struct MIXER_Channel { MIXER_MixHandler handler; Bitu sample_add; Bitu sample_left; - Sample remain; + Bitu remain; bool playing; MIXER_Channel * next; }; +static Bit8u wavheader[]={ + 'R','I','F','F', 0x0,0x0,0x0,0x0, /* Bit32u Riff Chunk ID / Bit32u riff size */ + 'W','A','V','E', 'f','m','t',' ', /* Bit32u Riff Format / Bit32u fmt chunk id */ + 0x10,0x0,0x0,0x0, 0x1,0x0,0x2,0x0, /* Bit32u fmt size / Bit16u encoding/ Bit16u channels */ + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, /* Bit32u freq / Bit32u byterate */ + 0x4,0x0,0x10,0x0, 'd','a','t','a', /* Bit16u byte-block / Bit16u bits / Bit16u data chunk id */ + 0x0,0x0,0x0,0x0, /* Bit32u data size */ +}; -static MIXER_Channel * first_channel; -static union { - Bit16s m16[MIXER_BUFSIZE][1]; - Bit16s s16[MIXER_BUFSIZE][2]; - Bit8u m8[MIXER_BUFSIZE][1]; - Bit8u s8[MIXER_BUFSIZE][2]; - Bit32u full[MIXER_BUFSIZE]; -} mix_temp; - -static Bit16s mix_bufout[MIXER_BUFSIZE][2]; -static Bit16s mix_buftemp[MIXER_BUFSIZE][2]; -static Bit32s mix_bufextra; -static Bitu mix_writepos; -static Bitu mix_readpos; -static Bitu mix_ticks; -static Bitu mix_add; -static Bitu mix_remain; +static struct { + struct { + Bit16s data[MIXER_BUFSIZE][2]; + Bitu read,write; + } out; + Bit16s work[MIXER_BUFSIZE][2]; + union { + Bit16s m16[MIXER_BUFSIZE][1]; + Bit16s s16[MIXER_BUFSIZE][2]; + Bit8u m8[MIXER_BUFSIZE][1]; + Bit8u s8[MIXER_BUFSIZE][2]; + } temp; + MIXER_Channel * channels; + bool nosound; + Bitu freq; + Bitu blocksize; + Bitu tick_add,tick_remain; + struct { + FILE * handle; + const char * dir; + Bit8u buf[MIXER_WAVESIZE]; + Bitu used; + Bit32u length; + } wave; +} mixer; MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * name) { //TODO Find a free channel @@ -108,10 +122,10 @@ MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * nam chan->mode=MIXER_16STEREO; chan->handler=handler; chan->name=name; - chan->sample_add=(freq<sample_add=(freq<sample_left=0; - chan->next=first_channel; - first_channel=chan; + chan->next=mixer.channels; + mixer.channels=chan; return chan; }; @@ -119,7 +133,7 @@ void MIXER_SetFreq(MIXER_Channel * chan,Bit32u freq) { if (chan) { chan->freq=freq; /* Calculate the new addition value */ - chan->sample_add=(freq<sample_add=(freq<MIXER_BUFSIZE) samples=MIXER_BUFSIZE; - /* 16-bit stereo is 4 bytes per sample */ - memset((void *)&mix_buftemp,0,samples*MIXER_SSIZE); - MIXER_Channel * chan=first_channel; + /* Clear work buffer */ + memset(mixer.work,0,samples*MIXER_SSIZE); + MIXER_Channel * chan=mixer.channels; while (chan) { if (chan->playing) { /* This should always allocate 1 extra sample */ @@ -152,7 +166,7 @@ static void MIXER_MixData(Bit32u samples) { Bitu sample_toread=sample_total >> MIXER_SHIFT; if (sample_total & MIXER_REMAIN) sample_toread++; sample_total=(sample_toread+1)<remain.full; + *(Bitu *)&mixer.temp=chan->remain; switch (chan->mode) { case MIXER_8MONO: MIX_NORMAL(m8,0,0); @@ -173,77 +187,165 @@ static void MIXER_MixData(Bit32u samples) { } chan=chan->next; } - Bit32u buf_remain=MIXER_BUFSIZE-mix_writepos; + Bitu buf_remain=MIXER_BUFSIZE-mixer.out.write; /* Fill the samples size buffer with 0's */ if (buf_remain>samples) { - memcpy(&mix_bufout[mix_writepos][0],&mix_buftemp[0][0],samples*MIXER_SSIZE); - mix_writepos+=samples; + memcpy(&mixer.out.data[mixer.out.write][0],&mixer.work[0][0],samples*MIXER_SSIZE); + mixer.out.write+=samples; } else { - memcpy(&mix_bufout[mix_writepos][0],&mix_buftemp[0][0],buf_remain*MIXER_SSIZE); - memcpy(&mix_bufout[0][0],&mix_buftemp[buf_remain][0],(samples-buf_remain)*MIXER_SSIZE); - mix_writepos=(mix_writepos+samples)-MIXER_BUFSIZE; + memcpy(&mixer.out.data[mixer.out.write][0],&mixer.work[0][0],buf_remain*MIXER_SSIZE); + memcpy(&mixer.out.data[0][0],&mixer.work[buf_remain][0],(samples-buf_remain)*MIXER_SSIZE); + mixer.out.write=(mixer.out.write+samples)-MIXER_BUFSIZE; + } + if (mixer.wave.handle) { + memcpy(&mixer.wave.buf[mixer.wave.used],&mixer.work[0][0],samples*MIXER_SSIZE); + mixer.wave.length+=samples*MIXER_SSIZE; + mixer.wave.used+=samples*MIXER_SSIZE; + if (mixer.wave.used>(MIXER_WAVESIZE-1024)){ + fwrite(mixer.wave.buf,1,mixer.wave.used,mixer.wave.handle); + mixer.wave.used=0; + } } - - } -void MIXER_Mix(Bitu ticks) { -/* Check for 1 ms of sound to mix */ - Bitu count=(ticks*mix_add)+mix_remain; - mix_remain=count&((1<<10)-1); - count>>=10; - Bit32u size=MIXER_BUFSIZE+mix_writepos-mix_readpos; +static void MIXER_Mix(Bitu ticks) { + mixer.tick_remain+=mixer.tick_add; + Bitu count=mixer.tick_remain>>MIXER_SHIFT; + mixer.tick_remain&=((1<=MIXER_BUFSIZE) size-=MIXER_BUFSIZE; - if (size>MIXER_BLOCKSIZE+2048) return; + if (size>mixer.blocksize*2) return; MIXER_MixData(count); - } -static Bit32u last_pos; +static void MIXER_Mix_NoSound(Bitu ticks) { + mixer.tick_remain+=mixer.tick_add; + Bitu count=mixer.tick_remain>>MIXER_SHIFT; + mixer.tick_remain&=((1<=(Bit32u)len/MIXER_SSIZE) { - memcpy((void *)stream,(void *)&mix_bufout[mix_readpos][0],len); - } else { - memcpy((void *)stream,(void *)&mix_bufout[mix_readpos][0],remain*MIXER_SSIZE); - stream+=remain*MIXER_SSIZE; - memcpy((void *)stream,(void *)&mix_bufout[0][0],(len)-remain*MIXER_SSIZE); + /* 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_SSIZE=MIXER_BUFSIZE) mix_readpos-=MIXER_BUFSIZE; + Bitu remain=MIXER_BUFSIZE-mixer.out.read; + if (remain>=(Bitu)len/MIXER_SSIZE) { + memcpy((void *)stream,(void *)&mixer.out.data[mixer.out.read][0],len); + } else { + memcpy((void *)stream,(void *)&mixer.out.data[mixer.out.read][0],remain*MIXER_SSIZE); + stream+=remain*MIXER_SSIZE; + memcpy((void *)stream,(void *)&mixer.out.data[0][0],(len)-remain*MIXER_SSIZE); + } + mixer.out.read+=(len/MIXER_SSIZE); + if (mixer.out.read>=MIXER_BUFSIZE) mixer.out.read-=MIXER_BUFSIZE; } +static void MIXER_WaveEvent(void) { + Bitu last=0;char file_name[CROSS_LEN]; + DIR * dir;struct dirent * dir_ent; + /* Check for previously opened wave file */ + if (mixer.wave.handle) { + LOG_MSG("Stopped recording"); + /* Write last piece of audio in buffer */ + fwrite(mixer.wave.buf,1,mixer.wave.used,mixer.wave.handle); + /* Fill in the header with useful information */ + writed(&wavheader[4],mixer.wave.length+sizeof(wavheader)-8); + writed(&wavheader[0x18],mixer.freq); + writed(&wavheader[0x1C],mixer.freq*4); + writed(&wavheader[0x28],mixer.wave.length); + + fseek(mixer.wave.handle,0,0); + fwrite(wavheader,1,sizeof(wavheader),mixer.wave.handle); + fclose(mixer.wave.handle); + mixer.wave.handle=0; + return; + } + /* Find a filename to open */ + dir=opendir(mixer.wave.dir); + if (!dir) { + LOG_MSG("Can't open waveout dir %s",mixer.wave.dir); + return; + } + while (dir_ent=readdir(dir)) { + char tempname[CROSS_LEN]; + strcpy(tempname,dir_ent->d_name); + char * test=strstr(tempname,".wav"); + if (!test) continue; + *test=0; + if (strlen(tempname)<5) continue; + if (strncmp(tempname,"wave",4)!=0) continue; + Bitu num=atoi(&tempname[4]); + if (num>=last) last=num+1; + } + closedir(dir); + sprintf(file_name,"%s%cwave%04d.wav",mixer.wave.dir,CROSS_FILESPLIT,last); + /* Open the actual file */ + mixer.wave.handle=fopen(file_name,"wb"); + if (!mixer.wave.handle) { + LOG_MSG("Can't open file %s for waveout",file_name); + return; + } + mixer.wave.length=0; + LOG_MSG("Started recording to file %s",file_name); + fwrite(wavheader,1,sizeof(wavheader),mixer.wave.handle); +} + +static void MIXER_Stop(Section* sec) { + if (mixer.wave.handle) MIXER_WaveEvent(); +} void MIXER_Init(Section* sec) { - MSG_Add("MIXER_CONFIGFILE_HELP","Nothing to setup yet!\n"); + 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.nosound=section->Get_bool("nosound"); + mixer.blocksize=section->Get_int("blocksize"); + mixer.wave.dir=section->Get_string("wavedir"); + /* Initialize the internal stuff */ - first_channel=0; - mix_ticks=GetTicks(); - mix_bufextra=0; - mix_writepos=0; - mix_readpos=0; + mixer.channels=0; + mixer.out.write=0; + mixer.out.read=0; + memset(mixer.out.data,0,sizeof(mixer.out.data)); + mixer.wave.handle=0; + mixer.wave.used=0; /* Start the Mixer using SDL Sound at 22 khz */ SDL_AudioSpec spec; SDL_AudioSpec obtained; - mix_add=((MIXER_FREQ) << 10)/1000; - mix_remain=0; - spec.freq=MIXER_FREQ; + + spec.freq=mixer.freq; spec.format=AUDIO_S16SYS; spec.channels=2; spec.callback=MIXER_CallBack; spec.userdata=NULL; - spec.samples=MIXER_BLOCKSIZE; - - TIMER_RegisterTickHandler(MIXER_Mix); + spec.samples=mixer.blocksize; - if ( SDL_OpenAudio(&spec, &obtained) < 0 ) { - LOG_MSG("No sound output device found, starting in no sound mode"); + mixer.tick_remain=0; + if (mixer.nosound) { + LOG_MSG("MIXER:No Sound Mode Selected."); + mixer.tick_add=((mixer.freq) << MIXER_SHIFT)/1000; + TIMER_RegisterTickHandler(MIXER_Mix_NoSound); + } else if (SDL_OpenAudio(&spec, &obtained) <0 ) { + LOG_MSG("MIXER:Can't open audio: %s , running in nosound mode.",SDL_GetError()); + mixer.tick_add=((mixer.freq) << MIXER_SHIFT)/1000; + TIMER_RegisterTickHandler(MIXER_Mix_NoSound); } else { - MIXER_MixData(MIXER_BLOCKSIZE/MIXER_SSIZE); + mixer.freq=obtained.freq; + mixer.blocksize=obtained.samples; + mixer.tick_add=((mixer.freq+100) << MIXER_SHIFT)/1000; + TIMER_RegisterTickHandler(MIXER_Mix); SDL_PauseAudio(0); } + KEYBOARD_AddEvent(KBD_f6,KBD_MOD_CTRL,MIXER_WaveEvent); } diff --git a/src/hardware/mpu401.cpp b/src/hardware/mpu401.cpp new file mode 100644 index 0000000..ff9e9bb --- /dev/null +++ b/src/hardware/mpu401.cpp @@ -0,0 +1,233 @@ +#include +#include "dosbox.h" +#include "inout.h" +#include "mixer.h" +#include "dma.h" +#include "pic.h" +#include "hardware.h" +#include "setup.h" +#include "programs.h" + +void MIDI_RawOutByte(Bit8u data); +bool MIDI_Available(void); + +#define MPU_QUEUE 32 +enum MpuMode { M_UART,M_INTELLIGENT } ; + + +///////////////////////////////////////////////////////////////////////////// +// I/O +///////////////////////////////////////////////////////////////////////////// + +#define MPU_STATUS_DSR (1 << 7) +#define MPU_STATUS_DRR (1 << 6) +#define MPU_STATUS_PAD (0xff & (~(MPU_STATUS_DRR | MPU_STATUS_DSR))) + +#define MK_MPU_STATUS(dsr, drr)\ + (((dsr) ? 0 : MPU_STATUS_DSR) | ((drr) ? 0 : MPU_STATUS_DRR) | MPU_STATUS_PAD) + + +///////////////////////////////////////////////////////////////////////////// +// Commands +///////////////////////////////////////////////////////////////////////////// + +/** Copyright notice for MPU-401 intelligent-mode command constants ********* + + MPU-401 MIDI Interface Module v1.0 + Copyright (c) 1991, Robin Davies. All Rights Reserved. + + Robin Davies + 224 3rd Avenue + Ottawa, Ontario + Canada. K1S 2K3. + + updated by: + + Larry Troxler, Compuserve 73520,1736 + +****************************************************************************/ + +// Start/Stop Commands + +#define CMD_MIDI_STOP 0x01 +#define CMD_MIDI_START 0x02 +#define CMD_MIDI_CONTINUE 0x03 + +#define CMD_PLAY_STOP 0x04 +#define CMD_PLAY_START 0x08 +#define CMD_PLAY_CONTINUE 0x0c + +#define CMD_RECORD_STOP 0x10 +#define CMD_RECORD_START 0x20 + +// Commands + +#define CMD_DISABLE_ALL_NOTES_OFF 0x30 +#define CMD_DISABLE_REAL_TIME_OUT 0x32 +#define CMD_TIMING_BYTE_ALWAYS 0x34 +#define CMD_MODE_MESS_ON 0x35 +#define CMD_EXCLUSIVE_THRU_ON 0x37 +#define CMD_COMMON_TO_HOST_ON 0x38 +#define CMD_REAL_TIME_TO_HOST_ON 0x39 +#define CMD_UART_MODE 0x3f + +#define CMD_INT_CLOCK 0x80 +#define CMD_FSK_CLOCK 0x81 +#define CMD_MIDI_CLOCK 0x82 +#define CMD_METRONOME_ON 0x83 +#define CMD_METRONOME_OFF 0x84 +#define CMD_METRONOME_W_ACCENTS 0x85 +#define CMD_BENDER_OFF 0x86 +#define CMD_BENDER_ON 0x87 +#define CMD_MIDI_THRU_OFF 0x88 +#define CMD_MIDI_THRU_ON 0x89 +#define CMD_DATA_IN_STOP_MODE_OFF 0x8a +#define CMD_DATA_IN_STOP_MODE_ON 0x8b +#define CMD_SEND_MEASURE_END_OFF 0x8c +#define CMD_SEND_MEASURE_END_ON 0x8d +#define CMD_CONDUCTOR_OFF 0x8e +#define CMD_CONDUCTOR_ON 0x8f +#define CMD_REAL_TIME_AFFECTION_OFF 0x90 +#define CMD_REAL_TIME_AFFECTION_ON 0x91 +#define CMD_FSK_TO_INTERNAL 0x92 +#define CMD_FSK_TO_MIDI 0x93 +#define CMD_CLOCK_TO_HOST_OFF 0x94 +#define CMD_CLOCK_TO_HOST_ON 0x95 +#define CMD_EXCLUSIVE_TO_HOST_OFF 0x96 +#define CMD_EXCLUSIVE_TO_HOST_ON 0x97 + +#define CMD_RESET_RELATIVE_TEMPO 0xb1 +#define CMD_CLEAR_PLAY_COUNTERS 0xb8 +#define CMD_CLEAR_PLAY_MAP 0xb9 +#define CMD_CLEAR_RECORD_COUNTER 0xba +#define CMD_TIMEBASE_48 0xc2 +#define CMD_TIMEBASE_72 0xc3 +#define CMD_TIMEBASE_96 0xc4 +#define CMD_TIMEBASE_120 0xc5 +#define CMD_TIMEBASE_144 0xc6 +#define CMD_TIMEBASE_168 0xc7 +#define CMD_TIMEBASE_192 0xc8 + +#define CMD_REQUEST_TO_SEND_DATA 0xd0 /* + track #! */ +#define CMD_REQUEST_TO_SEND_SYSTEM_MSG 0xdf + +#define CMD_SET_TEMPO 0xe0 +#define CMD_RELATIVE_TEMPO 0xe1 +#define CMD_RELATIVE_TEMPO_GRADUATION 0xe2 +#define CMD_MIDI_METRONOME 0xe4 +#define CMD_MEASURE_LENGTH 0xe6 +#define CMD_INTERNAL_CLOCK_LENGTH_TO_HOST /* ? */ +#define CMD_ACTIVE_TRACK_MASK 0xec +#define CMD_SEND_PLAY_COUNTER_MASK 0xed +#define CMD_MIDI_CHANNEL_MASK_LO 0xee +#define CMD_MIDI_CHANNEL_MASK_HI 0xef + +#define CMD_EOX 0xf7 +#define CMD_TIMING_OVERFLOW 0xf8 +#define CMD_MPU_MARK 0xfc +#define CMD_RESET 0xff + +// Commands that return data + +#define CMD_REQUEST_PLAY_COUNTER 0xa0 +#define CMD_REQUEST_AND_CLEAR_PLAY_COUNTER 0xab +#define CMD_REQUEST_VERSION 0xac +#define CMD_REQUEST_REVISION 0xad +#define CMD_REQUEST_TEMPO 0xaf + + +///////////////////////////////////////////////////////////////////////////// +// Messages +///////////////////////////////////////////////////////////////////////////// + +#define MSG_CMD_ACK 0xfe + + + +static struct { + MpuMode mode; + Bit8u queue[MPU_QUEUE]; + Bitu queue_pos,queue_used; + Bitu cmd; + +} mpu; + +static void QueueByte(Bit8u data) { + if (mpu.queue_used=MPU_QUEUE) pos-=MPU_QUEUE; + mpu.queue_used++; + mpu.queue[pos]=data; + } else LOG(LOG_MISC,"MPU401:Data queue full"); +} + +static void ClrQueue(void) { + mpu.queue_used=0; + mpu.queue_pos=0; +} + +static void MPU401_WriteCommand(Bit32u port,Bit8u val) { + switch (val) { + case CMD_UART_MODE: /* Switch to UART Mode */ + mpu.mode=M_UART; + QueueByte(MSG_CMD_ACK); + break; + case CMD_RESET: /* Reset Commmand */ + mpu.mode=M_INTELLIGENT; + ClrQueue(); + QueueByte(MSG_CMD_ACK); + break; + + case CMD_REQUEST_TO_SEND_DATA: + case CMD_REQUEST_TO_SEND_SYSTEM_MSG: + QueueByte(MSG_CMD_ACK); + break; + + default: + LOG(LOG_MISC,"MPU401:Unhandled command %X",val); + QueueByte(MSG_CMD_ACK); + break; + } + +} + +static Bit8u MPU401_ReadStatus(Bit32u port) { + + Bit8u ret=0x3f; /* Bith 6 and 7 clear */ + if (!mpu.queue_used) ret|=0x80; + return ret; +} + + +static void MPU401_WriteData(Bit32u port,Bit8u val) { + MIDI_RawOutByte(val); +} + +static Bit8u MPU401_ReadData(Bit32u port) { + Bit8u ret=MSG_CMD_ACK; + if (mpu.queue_used) { + ret=mpu.queue[mpu.queue_pos]; + mpu.queue_pos++; + if (mpu.queue_pos>=MPU_QUEUE) mpu.queue_pos-=MPU_QUEUE; + mpu.queue_used--; + } + return ret; +} + + +void MPU401_Init(Section* sec) { + Section_prop * section=static_cast(sec); + if(!section->Get_bool("mpu401")) return; + + if (!MIDI_Available()) return; + + IO_RegisterWriteHandler(0x330,&MPU401_WriteData,"MPU401"); + IO_RegisterWriteHandler(0x331,&MPU401_WriteCommand,"MPU401"); + IO_RegisterReadHandler(0x330,&MPU401_ReadData,"MPU401"); + IO_RegisterReadHandler(0x331,&MPU401_ReadStatus,"MPU401"); + + mpu.queue_used=0; + mpu.queue_pos=0; +} + + diff --git a/src/hardware/pcspeaker.cpp b/src/hardware/pcspeaker.cpp index f85f289..85a255a 100644 --- a/src/hardware/pcspeaker.cpp +++ b/src/hardware/pcspeaker.cpp @@ -21,6 +21,7 @@ #include "mixer.h" #include "timer.h" #include "setup.h" +#include "pic.h" #ifndef PI @@ -31,117 +32,199 @@ #define SPKR_RATE 22050 #define SPKR_VOLUME 5000 -#define SPKR_SHIFT 16 +#define SPKR_SHIFT 10 -#define SIN_ENT 1024 -#define SIN_MAX (SIN_ENT << SPKR_SHIFT) - -#define FREQ_MAX (2 << SPKR_SHIFT) -#define FREQ_HALF (FREQ_MAX >> 1) - -struct Speaker { - Bitu freq_add; - Bitu freq_pos; - Bit16s volume; - MIXER_Channel * chan; - bool enabled; - bool realsound; - bool sinewave; - Bitu mode; - Bit16u buffer[SPKR_BUF]; - Bit16s table[SIN_ENT]; - Bitu buf_pos; +enum SPKR_MODE { + MODE_NONE,MODE_WAVE,MODE_DELAY,MODE_ONOFF,MODE_REAL, }; +/* TODO + Maybe interpolate at the moment we switch between on/off + Keep track of postion of speaker conus in ONOFF mode +*/ -static Speaker spkr; +static struct { + Bit16s volume; + MIXER_Channel * chan; + Bit16u buffer[SPKR_BUF]; + SPKR_MODE mode; + SPKR_MODE pit_mode; + struct { + Bit16s buf[SPKR_BUF]; + Bitu used; + } real; + struct { + Bitu index; + struct { + Bitu max,half; + } count,new_count; + } wave; + struct { + Bit16s buf[SPKR_BUF]; + Bitu pos; + } out; + struct { + Bitu index; + Bitu max; + } delay; + struct { + Bitu vol; + Bitu rate; + Bitu rate_conv; + Bitu tick_add; + } hw; + bool onoff,enabled; + Bitu buf_pos; +} spkr; - -void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode) { - spkr.mode=mode; - switch (mode) { - case 0: - if (cntr>72) cntr=72; - spkr.realsound=true; - if (spkr.buf_pos=spkr.wave.count.max) { + *stream++=+spkr.volume; + spkr.wave.index-=spkr.wave.count.max; + spkr.wave.count.max=spkr.wave.new_count.max; + spkr.wave.count.half=spkr.wave.new_count.half; + } else if (spkr.wave.index>spkr.wave.count.half) { + *stream++=-spkr.volume; + } else { + *stream++=+spkr.volume; + } + } + spkr.out.pos+=samples; + } + break; + case MODE_ONOFF: + { + Bit16s val=spkr.onoff ? spkr.volume : -spkr.volume; + for (Bitu i=0;i> 16]; + buf_pos+=buf_add; + } + spkr.out.pos+=samples; + break; + } + case MODE_DELAY: + { + for (Bitu i=0;i>16; + if (spkr.mode==MODE_NONE) MIXER_Enable(spkr.chan,true); + switch (mode) { + case 0: /* Mode 0 one shot, used with realsound */ + if (!spkr.enabled) return; + if (cntr>72) cntr=72; + if (spkr.mode!=MODE_REAL) GenerateSound(len); + spkr.pit_mode=MODE_REAL; + if (spkr.real.used>16; + GenerateSound(len); + if (spkr.mode==MODE_NONE) MIXER_Enable(spkr.chan,true); + switch (mode) { + case 0: + if (spkr.mode==MODE_ONOFF && spkr.onoff) spkr.onoff=false; + else spkr.mode=MODE_NONE; + spkr.enabled=false; + break; + case 1: + spkr.mode=MODE_ONOFF; + spkr.enabled=false; + spkr.onoff=false; + break; + case 2: + spkr.enabled=false; + spkr.onoff=true; + spkr.mode=MODE_ONOFF; + break; + case 3: + spkr.onoff=true; + spkr.enabled=true; + spkr.mode=spkr.pit_mode; + break; + }; } static void PCSPEAKER_CallBack(Bit8u * stream,Bit32u len) { - switch (spkr.mode) { - case 0: - /* Generate the "RealSound" */ - { - Bitu buf_add=(spkr.buf_pos<<16)/len; - Bitu buf_pos=0; - spkr.buf_pos=0;spkr.realsound=0; - while (len-->0) { - *(Bit16s*)(stream)=spkr.buffer[buf_pos >> 16]; - buf_pos+=buf_add; - stream+=2; - } - break; - } - case 3: - if (spkr.sinewave) while (len-->0) { - spkr.freq_pos+=spkr.freq_add; - spkr.freq_pos&=(SIN_MAX-1); - *(Bit16s*)(stream)=spkr.table[spkr.freq_pos>>SPKR_SHIFT]; - stream+=2; - } else while (len-->0) { - spkr.freq_pos+=spkr.freq_add; - if (spkr.freq_pos>=FREQ_MAX) spkr.freq_pos-=FREQ_MAX; - if (spkr.freq_pos>=FREQ_HALF) { - *(Bit16s*)(stream)=spkr.volume; - } else { - *(Bit16s*)(stream)=-spkr.volume; - } - stream+=2; - } - break; - case 4: - while (len-->0) { - if (spkr.freq_pos) { - *(Bit16s*)(stream)=spkr.volume; - spkr.freq_pos--; - } else { - *(Bit16s*)(stream)=-spkr.volume; - } - stream+=2; - } - break; - } + if (spkr.out.pos(sec); if(!section->Get_bool("enabled")) return; - spkr.sinewave=section->Get_bool("sinewave"); - spkr.chan=MIXER_AddChannel(&PCSPEAKER_CallBack,SPKR_RATE,"PC-SPEAKER"); + spkr.volume=SPKR_VOLUME; + spkr.mode=MODE_NONE; + spkr.pit_mode=MODE_WAVE; + spkr.real.used=0; + spkr.out.pos=0; + spkr.onoff=false; +// spkr.hw.vol=section->Get_int("volume"); + spkr.hw.rate=section->Get_int("pcrate"); + spkr.hw.rate_conv=(spkr.hw.rate<<16)/1000000; + spkr.hw.tick_add=(Bitu)((double)PIT_TICK_RATE*(double)(1 << SPKR_SHIFT)/(double)spkr.hw.rate); + spkr.wave.index=0; + spkr.wave.count.max=spkr.wave.new_count.max=0x10000 << SPKR_SHIFT; + spkr.wave.count.half=spkr.wave.new_count.half=(0x10000 << SPKR_SHIFT)/2; + + /* Register the sound channel */ + spkr.chan=MIXER_AddChannel(&PCSPEAKER_CallBack,spkr.hw.rate,"PC-SPEAKER"); MIXER_Enable(spkr.chan,false); MIXER_SetMode(spkr.chan,MIXER_16MONO); - spkr.volume=SPKR_VOLUME; - spkr.enabled=false; - spkr.realsound=false; - spkr.buf_pos=0; - /* Generate the sine wave */ - for (Bitu i=0;i15) E_Exit("PIC:Illegal IRQ"); if (!pic.free_entry) { - LOG_WARN("PIC:No free queue entries"); + LOG(LOG_ERROR|LOG_PIC,"Event queue full"); return; } PICEntry * entry=pic.free_entry; @@ -441,9 +441,6 @@ Bitu PIC_RunQueue(void) { CPU_CycleLeft+=CPU_Cycles; CPU_Cycles=0; } - if (CPU_CycleLeft<=0) { - CPU_CycleLeft=CPU_CycleMax; - } while (CPU_CycleLeft>0) { /* Check the queue for an entry */ Bitu index=PIC_Index(); @@ -482,8 +479,10 @@ Bitu PIC_RunQueue(void) { } if (ret) return ret; } - /* Go through the list of scheduled irq's and lower their index with 1000 */ + /* Prepare everything for next round */ + CPU_CycleLeft=CPU_CycleMax; PIC_Ticks++; + /* Go through the list of scheduled irq's and lower their index with 1000 */ PICEntry * entry=pic.next_entry; while (entry) { if (entry->index>1000) entry->index-=1000; diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index fd9564f..f5af8d9 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.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 @@ -26,9 +26,14 @@ #include "setup.h" #include "programs.h" -#define SB_BASE 0x220 -#define SB_IRQ 5 -#define SB_DMA 1 + +#define SB_PIC_EVENTS 0 + +#define DSP_MAJOR 2 +#define DSP_MINOR 0 + +#define MIXER_INDEX 0x04 +#define MIXER_DATA 0x05 #define DSP_RESET 0x06 #define DSP_READ_DATA 0x0A @@ -38,66 +43,104 @@ #define DSP_NO_COMMAND 0 -#define DSP_MAJOR 2 -#define DSP_MINOR 0 - +#define DMA_BUFSIZE 4096 #define DSP_BUFSIZE 64 #define DSP_DACSIZE 4096 +//Should be enough for sound generated in millisecond blocks +#define SB_BUF_SIZE 8096 + enum {DSP_S_RESET,DSP_S_NORMAL,DSP_S_HIGHSPEED}; -enum { - MODE_NONE,MODE_DAC,MODE_SILENCE, - MODE_PCM_8S,MODE_PCM_8A, - MODE_ADPCM_4S + +enum DSP_MODES { + MODE_NONE,MODE_DAC, + MODE_SILENCE, + MODE_DMA,MODE_DMA_PAUSE,MODE_DMA_WAIT, }; -#if DEBUG_SBLASTER -#define SB_DEBUG LOG_DEBUG -#else -#define SB_DEBUG -#endif +enum DMA_MODES { + DMA_NONE, + DMA_8_SILENCE, + DMA_4_SINGLE, + DMA_8_SINGLE,DMA_8_AUTO, +}; +enum { + PLAY_MONO,PLAY_STEREO, +}; struct SB_INFO { Bit16u freq; - Bitu samples_total; - Bitu samples_left; + struct { + bool active,stereo; + DMA_MODES mode; + Bitu total,left; + Bitu rate,rate_mul; + Bitu index,add_index; + Bit64u start; + union { + Bit8u b8[DMA_BUFSIZE]; + Bit16s b16[DMA_BUFSIZE]; + } buf; + } dma; bool speaker; Bit8u time_constant; bool use_time_constant; - - Bit8u output_mode; - /* DSP Stuff */ - Bit8u mode; - Bit8u state; - Bit8u cmd; - Bit8u cmd_len; - Bit8u cmd_in_pos; - Bit8u cmd_in[DSP_BUFSIZE]; - Bit8u data_out[DSP_BUFSIZE]; - Bit8u data_out_pos; - Bit8u data_out_used; + DSP_MODES mode; struct { - Bit8u data[DSP_DACSIZE]; + Bit8u state; + Bit8u cmd; + Bit8u cmd_len; + Bit8u cmd_in_pos; + Bit8u cmd_in[DSP_BUFSIZE]; + struct { + Bit8u data[DSP_BUFSIZE]; + Bitu pos,used; + } in,out; + Bit8u test_register; + Bitu write_busy; + } dsp; + struct { + Bit16s data[DSP_DACSIZE]; Bitu used; - Bit8u last; + Bit16s last; } dac; - Bit8u test_register; -/*ADPCM Part */ - Bits adpcm_reference; - Bits adpcm_scale; - Bits adpcm_remain; -/* Hardware setup part */ - Bit32u base; - Bit8u irq; - Bit8u dma; - bool enabled; + struct { + Bit8u index; + Bit8u master; + Bit8u mic,voice,fm; + } mixer; + struct { + Bits reference,scale; + } adpcm; + struct { + Bitu base; + Bit8u irq; + Bit8u dma8; + Bitu rate; + Bitu rate_conv; + } hw; + struct { + Bit16s buf[SB_BUF_SIZE][2]; + Bitu pos; + } out; + struct { + union { + Bit16s m[DMA_BUFSIZE]; + Bit16s s[DMA_BUFSIZE][2]; + } buf; + Bitu index,add_index; + } tmp; + struct { + Bits value; + Bitu count; + } e2; MIXER_Channel * chan; }; + + static SB_INFO sb; -static Bit8u e2_value; -static Bit8u e2_count; static char * copyright_string="COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; @@ -137,134 +180,338 @@ static int E2_incr_table[4][9] = { #define min(a,b) ((a)<(b)?(a):(b)) #endif +static void DSP_ChangeMode(DSP_MODES mode); +static void CheckDMAEnd(void); +static void END_DMA_Event(void); + static void DSP_SetSpeaker(bool how) { -/* This should just set the mixer value */ MIXER_Enable(sb.chan,how); sb.speaker=how; } -static void DSP_HaltDMA(void) { - -} - static INLINE void DSP_FlushData(void) { - sb.data_out_used=0; - sb.data_out_pos=0; + sb.dsp.out.used=0; + sb.dsp.out.pos=0; } static void DSP_StopDMA(void) { - sb.mode=MODE_NONE; + DSP_ChangeMode(MODE_NONE); + sb.dma.left=0; } -static void DSP_StartDMATranfser(Bit8u mode) { - sb.samples_left=sb.samples_total; - if (sb.use_time_constant) { - sb.freq=(1000000 / (256 - sb.time_constant)); - }; - switch (mode) { - case MODE_SILENCE: - MIXER_SetFreq(sb.chan,sb.freq); - SB_DEBUG("DSP:PCM 8 bit single cycle rate %d size %d",sb.freq,sb.samples_total); - break; - case MODE_PCM_8S: - MIXER_SetFreq(sb.chan,sb.freq); - SB_DEBUG("DSP:PCM 8 bit single cycle rate %d size %d",sb.freq,sb.samples_total); - break; - case MODE_PCM_8A: - MIXER_SetFreq(sb.chan,sb.freq); - SB_DEBUG("DSP:PCM 8 bit auto init rate %d size %d",sb.freq,sb.samples_total); - break; - case MODE_ADPCM_4S: - MIXER_SetFreq(sb.chan,sb.freq); - SB_DEBUG("DSP:ADPCM 4 bit single cycle rate %d size %X",sb.freq,sb.samples_total); - break; - default: - LOG_ERROR("DSP:Illegal transfer mode %d",mode); - return; +static void DMA_Enable(bool enable) { + sb.dma.active=enable; + if (sb.mode==MODE_DMA_WAIT && enable) { + DSP_ChangeMode(MODE_DMA); + CheckDMAEnd(); } - /* Hack to enable dma transfer when game has speaker disabled */ - DSP_SetSpeaker(true); + if (sb.mode==MODE_DMA && !enable) { + DSP_ChangeMode(MODE_DMA_WAIT); + } +} + +INLINE Bit8u 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) { + reference = max(0x00, reference - ((sample & 0x07) << scale)); + } else { + reference = min(0xff, reference + ((sample & 0x07) << scale)); + } + scale = max(2, min(6, scaleMap[sample & 0x07])); + return (Bit8u)reference; +} + +static void GenerateDMASound(Bitu size) { + //TODO For stereo make sure it's multiple of 2 + if (!size) return; + Bitu read,i; + switch (sb.dma.mode) { + case DMA_4_SINGLE: + if (sb.adpcm.reference<0 && sb.dma.left) { + 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; + } + 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; + } + 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); + } + for (i=0;i(pos=sb.tmp.index>>16)) { + (*stream++)=sb.tmp.buf.m[pos]; + (*stream++)=sb.tmp.buf.m[pos]; + sb.tmp.index+=sb.tmp.add_index; + sb.out.pos++; + } + sb.tmp.index&=0xffff; + } else { + Bitu pos;read<<=1; + while (read>(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++; + } + sb.tmp.index&=0xffff; + } +} + +static void GenerateSound(Bitu size) { + while (sb.out.pos0) { + *(stream++)=sb.dac.data[dac_pos>>16]; + *(stream++)=sb.dac.data[dac_pos>>16]; + dac_pos+=dac_add; + } + dac_pos-=dac_add; + sb.dac.last=sb.dac.data[dac_pos>>16]; + sb.dac.used=0; + } else { + memset(stream,sb.dac.last,samples); + sb.mode=MODE_NONE; + } + sb.out.pos+=samples; + break; + } + case MODE_DMA: + { + Bitu len=size*sb.dma.rate_mul; + if (len & 0xffff) len=1+(len>>16); + else len>>=16; + GenerateDMASound(len); + break; + } + + } + } + if (sb.out.pos>SB_BUF_SIZE) { + LOG(LOG_ERROR|LOG_SB,"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 + PIC_AddEvent(END_DMA_Event,index); +#else + GenerateDMASound(sb.dma.left); +#endif + } +} + +static void DSP_ChangeMode(DSP_MODES mode) { + if (!sb.speaker) DSP_SetSpeaker(true); + if (mode==sb.mode) return; + /* Generate sound until now */ + Bitu index=PIC_Index(); + GenerateSound((sb.hw.rate_conv*index)>>16); sb.mode=mode; } +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) { + case DMA_8_SILENCE: + 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; + break; + case DMA_8_AUTO: + type="8-Bit Auto Init"; + sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + break; + case DMA_4_SINGLE: + type="4-Bit ADPCM Single Cycle"; + sb.tmp.add_index=(sb.dma.rate<<16)/sb.hw.rate; + break; + default: + LOG(LOG_ERROR|LOG_SB,"DSP:Illegal transfer mode %d",mode); + return; + } + //TODO Use the 16-bit dma for 16-bit transfers + DSP_ChangeMode(MODE_DMA_WAIT); + 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); +} + static void DSP_AddData(Bit8u val) { - if (sb.data_out_used=DSP_BUFSIZE) start-=DSP_BUFSIZE; - sb.data_out[start]=val; - sb.data_out_used++; + sb.dsp.out.data[start]=val; + sb.dsp.out.used++; } else { - LOG_ERROR("SB:DSP:Data Output buffer full this is weird"); + LOG(LOG_ERROR|LOG_SB,"DSP:Data Output buffer full"); } } + static void DSP_Reset(void) { - sb.mode=MODE_NONE; - sb.cmd_len=0; - sb.cmd_in_pos=0; - sb.samples_left=0; - sb.samples_total=0; + DSP_ChangeMode(MODE_NONE); + sb.dsp.cmd_len=0; + sb.dsp.in.pos=0; + sb.dsp.write_busy=0; + sb.dma.left=0; + sb.dma.total=0; sb.freq=22050; - sb.use_time_constant=false; + sb.use_time_constant=true; + sb.time_constant=45; sb.dac.used=0; - sb.dac.last=0x80; - e2_value=0xaa; - e2_count=0; - DSP_HaltDMA(); - MIXER_SetFreq(sb.chan,22050); - MIXER_SetMode(sb.chan,MIXER_8MONO); + sb.dac.last=0; + sb.e2.value=0xaa; + sb.e2.count=0; DSP_SetSpeaker(false); } + + static void DSP_DoReset(Bit8u val) { if (val&1!=0) { //TODO Get out of highspeed mode DSP_Reset(); - sb.state=DSP_S_RESET; + sb.dsp.state=DSP_S_RESET; } else { DSP_FlushData(); DSP_AddData(0xaa); - sb.state=DSP_S_NORMAL; + sb.dsp.state=DSP_S_NORMAL; } -}; +} + + +static void DMA_E2_Enable(bool enable) { + if (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 bool dac_warn=false; static void DSP_DoCommand(void) { - switch (sb.cmd) { + switch (sb.dsp.cmd) { case 0x10: /* Direct DAC */ - sb.mode=MODE_DAC; + DSP_ChangeMode(MODE_DAC); if (sb.dac.used> i) & 0x01) m_E2Value += E2_incr_table[m_E2Count % 4][i]; - - m_E2Value += E2_incr_table[m_E2Count % 4][8]; - m_E2Count++; -*/ -//TODO Ofcourse :) + LOG(LOG_SB,"DSP Function 0xe2"); + for (Bitu i = 0; i < 8; i++) + if ((sb.dsp.in.data[0] >> i) & 0x01) sb.e2.value += E2_incr_table[sb.e2.count % 4][i]; + sb.e2.value += E2_incr_table[sb.e2.count % 4][8]; + sb.e2.count++; + DMA_SetEnableCallBack(sb.hw.dma8,DMA_E2_Enable); } break; case 0xe3: /* DSP Copyright */ @@ -302,66 +555,99 @@ static void DSP_DoCommand(void) { } break; case 0xe4: /* Write Test Register */ - sb.test_register=sb.cmd_in[0]; + sb.dsp.test_register=sb.dsp.in.data[0]; break; case 0xe8: /* Read Test Register */ DSP_FlushData(); - DSP_AddData(sb.test_register);; + DSP_AddData(sb.dsp.test_register);; break; - case 0xf2: /* Trigger 8bit IRQ */ DSP_FlushData(); DSP_AddData(0xaa); - PIC_ActivateIRQ(sb.irq); + PIC_AddIRQ(sb.hw.irq,0); break; default: - LOG_WARN("SB:DSP:Unhandled command %2X",sb.cmd); + LOG(LOG_ERROR|LOG_SB,"DSP:Unhandled command %2X",sb.dsp.cmd); + break; } - sb.cmd=DSP_NO_COMMAND; - sb.cmd_len=0; - sb.cmd_in_pos=0; + sb.dsp.cmd=DSP_NO_COMMAND; + sb.dsp.cmd_len=0; + sb.dsp.in.pos=0; } - - static void DSP_DoWrite(Bit8u val) { - switch (sb.cmd) { + switch (sb.dsp.cmd) { case DSP_NO_COMMAND: - sb.cmd=val; - sb.cmd_len=DSP_cmd_len[val]; - sb.cmd_in_pos=0; - if (!sb.cmd_len) DSP_DoCommand(); + sb.dsp.cmd=val; + sb.dsp.cmd_len=DSP_cmd_len[val]; + sb.dsp.in.pos=0; + if (!sb.dsp.cmd_len) DSP_DoCommand(); break; default: - sb.cmd_in[sb.cmd_in_pos]=val; - sb.cmd_in_pos++; - if (sb.cmd_in_pos>=sb.cmd_len) DSP_DoCommand(); + sb.dsp.in.data[sb.dsp.in.pos]=val; + sb.dsp.in.pos++; + if (sb.dsp.in.pos>=sb.dsp.cmd_len) DSP_DoCommand(); } } static Bit8u DSP_ReadData(void) { Bit8u data=0; - if (sb.data_out_used) { - data=sb.data_out[sb.data_out_pos]; - sb.data_out_pos++; - if (sb.data_out_pos>=DSP_BUFSIZE) sb.data_out_pos-=DSP_BUFSIZE; - sb.data_out_used--; + if (sb.dsp.out.used) { + data=sb.dsp.out.data[sb.dsp.out.pos]; + sb.dsp.out.pos++; + if (sb.dsp.out.pos>=DSP_BUFSIZE) sb.dsp.out.pos-=DSP_BUFSIZE; + sb.dsp.out.used--; } return data; } +static void MIXER_Write(Bit8u val) { + switch (sb.mixer.index) { + case 0x0a: /* Mic Level */ + sb.mixer.mic=val; + break; + case 0x22: /* Master Volume */ + sb.mixer.master=val; + break; + default: + LOG(LOG_ERROR|LOG_SB,"MIXER:Write to unhandled index %X",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; + } + return ret; +} + + static Bit8u read_sb(Bit32u port) { - switch (port-sb.base) { + switch (port-sb.hw.base) { + case MIXER_INDEX: + return sb.mixer.index; + case MIXER_DATA: + return MIXER_Read(); case DSP_READ_DATA: return DSP_ReadData(); case DSP_READ_STATUS: //TODO Acknowledge 8bit irq //TODO See for high speed dma :) - if (sb.data_out_used) return 0xff; + if (sb.dsp.out.used) return 0xff; else return 0x7f; case DSP_WRITE_STATUS: - switch (sb.state) { + switch (sb.dsp.state) { case DSP_S_NORMAL: + sb.dsp.write_busy++; + if (sb.dsp.write_busy & 8) return 0xff; return 0x7f; case DSP_S_RESET: return 0xff; @@ -373,20 +659,26 @@ static Bit8u read_sb(Bit32u port) { case DSP_RESET: return 0xff; default: - LOG_WARN("SB:Unhandled read from SB Port %4X",port); + LOG(LOG_SB,"Unhandled read from SB Port %4X",port); break; } return 0xff; } static void write_sb(Bit32u port,Bit8u val) { - switch (port-sb.base) { + switch (port-sb.hw.base) { case DSP_RESET: DSP_DoReset(val); break; case DSP_WRITE_DATA: DSP_DoWrite(val); break; + case MIXER_INDEX: + sb.mixer.index=val; + break; + case MIXER_DATA: + MIXER_Write(val); + break; /* For now loop FM Stuff to 0x388 */ case 0x00: case 0x02: case 0x08: IO_Write(0x388,val); @@ -396,178 +688,47 @@ static void write_sb(Bit32u port,Bit8u val) { break; default: - LOG_WARN("SB:Unhandled write to SB Port %4X",port); + LOG(LOG_SB,"Unhandled write to SB Port %4X",port); break; } } - -INLINE Bit8u decode_ADPCM_4_sample( - Bit8u sample, - Bits& reference, - Bits& scale) -{ - static int scaleMap[8] = { -2, -1, 0, 0, 1, 1, 1, 1 }; - - if (sample & 0x08) { - reference = max(0x00, reference - ((sample & 0x07) << scale)); - } else { - reference = min(0xff, reference + ((sample & 0x07) << scale)); - } - - scale = max(2, min(6, scaleMap[sample & 0x07])); - - return (Bit8u)reference; -} - static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) { - unsigned char tmpbuf[65536]; if (!len) return; - switch (sb.mode) { - case MODE_NONE: - /* If there isn't a mode it's 8 bit mono mode speaker should be disabled normally */ - memset(stream,0x80,len); - break; - case MODE_DAC: - /* Stretch the inputted dac data over len samples */ - { - if (sb.dac.used) { - Bitu dac_add=(sb.dac.used<<16)/len; - Bitu dac_pos=0; - while (len-->0) { - *(stream++)=sb.dac.data[dac_pos>>16]; - dac_pos+=dac_add; - } - dac_pos-=dac_add; - sb.dac.last=sb.dac.data[dac_pos>>16]; - sb.dac.used=0; - } else { - memset(stream,sb.dac.last,len); - } - } - break; - case MODE_SILENCE: - memset(stream,0x80,len); - if (sb.samples_left>len) { - sb.samples_left-=len; - } else { - sb.samples_left=0; - sb.mode=MODE_NONE; - PIC_ActivateIRQ(sb.irq); - } - break; - case MODE_PCM_8A: - { - Bit16u read=DMA_8_Read(sb.dma,stream,(Bit16u)len); - if (sb.samples_left>read) { - sb.samples_left-=read; - } else { - if (read>(sb.samples_total+sb.samples_left)) sb.samples_left=sb.samples_total; - else sb.samples_left=sb.samples_total+sb.samples_left-read; - PIC_ActivateIRQ(sb.irq); - } - if (read=len) { - read=DMA_8_Read(sb.dma,stream,(Bit16u)len); - sb.samples_left-=read; - } else { - read=DMA_8_Read(sb.dma,stream,(Bit16u)sb.samples_left); - sb.samples_left=0; - } - if (read=0) { - *stream++=decode_ADPCM_4_sample((Bit8u)sb.adpcm_remain,sb.adpcm_reference,sb.adpcm_scale); - len--; - } - Bitu dma_size=len/2+(len&1); //Amount of bytes that need to be transferred - Bit8u * decode_pos=tmpbuf; - if (sb.adpcm_reference < 0) { - dma_size++; - } - Bit16u read; - /* Read from the DMA Channel */ - if (sb.samples_left>=dma_size) { - read=DMA_8_Read(sb.dma,decode_pos,(Bit16u)dma_size); - } else if (sb.samples_left0;i--) { - *stream++=decode_ADPCM_4_sample(*decode_pos >> 4,sb.adpcm_reference,sb.adpcm_scale); - *stream++=decode_ADPCM_4_sample(*decode_pos++ ,sb.adpcm_reference,sb.adpcm_scale); - } - if (len & 1) { - *stream++=decode_ADPCM_4_sample(*decode_pos >> 4,sb.adpcm_reference,sb.adpcm_scale); - sb.adpcm_remain=*decode_pos & 0xf; - } else { - sb.adpcm_remain=-1; - } - } - break; - } /* End switch */ -} - - - -static void SB_Enable(bool enable) { - Bitu i; - if (enable) { - sb.enabled=true; - for (i=sb.base+4;i=len) { + memcpy(sb.out.buf,&sb.out.buf[len],(sb.out.pos-len)*4); + sb.out.pos-=len; } + else sb.out.pos=0; + if (sb.mode==MODE_NONE) DSP_SetSpeaker(false); + return; } + 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; sb.chan=MIXER_AddChannel(&SBLASTER_CallBack,22050,"SBLASTER"); MIXER_Enable(sb.chan,false); + sb.dsp.state=DSP_S_NORMAL; + sb.hw.base=section->Get_hex("base"); + sb.hw.irq=section->Get_int("irq"); + sb.hw.dma8=section->Get_int("dma"); + sb.hw.rate=section->Get_int("sbrate"); + sb.hw.rate_conv=(sb.hw.rate<<16)/1000000; + MIXER_SetFreq(sb.chan,sb.hw.rate); + MIXER_SetMode(sb.chan,MIXER_16STEREO); - sb.state=DSP_S_NORMAL; + for (i=sb.hw.base+4;iGet_hex("base"); - sb.irq=section->Get_int("irq"); - sb.dma=section->Get_int("dma"); - SB_Enable(true); - SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d T3",sb.base,sb.irq,sb.dma); + SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d T3",sb.hw.base,sb.hw.irq,sb.hw.dma8); } diff --git a/src/hardware/tandy_sound.cpp b/src/hardware/tandy_sound.cpp index 9e5727d..c71c1db 100644 --- a/src/hardware/tandy_sound.cpp +++ b/src/hardware/tandy_sound.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 @@ -99,7 +99,7 @@ static void write_pc0(Bit32u port,Bit8u val) { // tandy.chan[tandy.reg>>1].freq_pos=0; break; default: - LOG_WARN("TANDY:Illegal dual byte reg %d",tandy.reg); + LOG(0,"TANDY:Illegal dual byte reg %d",tandy.reg); }; } diff --git a/src/hardware/timer.cpp b/src/hardware/timer.cpp index 69cb7d3..4194f53 100644 --- a/src/hardware/timer.cpp +++ b/src/hardware/timer.cpp @@ -49,33 +49,44 @@ static PIT_Block pit[3]; static void PIT0_Event(void) { PIC_ActivateIRQ(0); - PIC_AddEvent(PIT0_Event,pit[0].micro); + if (pit[0].mode!=0) PIC_AddEvent(PIT0_Event,pit[0].micro); } static void counter_latch(Bitu counter) { /* Fill the read_latch of the selected counter with current count */ PIT_Block * p=&pit[counter]; - + Bit64s micro=PIC_MicroCount()-p->start; + switch (p->mode) { - case 0: - if (micro>p->micro) p->read_latch=p->write_latch; - else p->read_latch=(Bit16u)(p->cntr-(((float)micro/(float)p->micro)*(float)p->cntr)); + case 0: /* Interrupt on Terminal Count */ + /* Counter keeps on counting after passing terminal count */ + if (micro>p->micro) { + micro-=p->micro; + micro%=(Bit64u)(1000000/((float)PIT_TICK_RATE/(float)0x10000)); + p->read_latch=(Bit16u)(0x10000-(((double)micro/(double)p->micro)*(double)0x10000)); + } else { + p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); + } break; - case 2: + case 2: /* Rate Generator */ micro%=p->micro; - p->read_latch=(Bit16u)(p->cntr-(((float)micro/(float)p->micro)*(float)p->cntr)); + p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); break; - case 3: + case 3: /* Square Wave Rate Generator */ micro%=p->micro; micro*=2; if (micro>p->micro) micro-=p->micro; - p->read_latch=(Bit16u)(p->cntr-(((float)micro/(float)p->micro)*(float)p->cntr)); + p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); + break; + case 4: /* Software Triggered Strobe */ + if (micro>p->micro) p->read_latch=p->write_latch; + else p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); break; default: - LOG_ERROR("PIT:Illegal Mode %d for reading counter %d",p->mode,counter); + LOG(LOG_ERROR|LOG_PIT,"Illegal Mode %d for reading counter %d",p->mode,counter); micro%=p->micro; - p->read_latch=(Bit16u)(p->cntr-(((float)micro/(float)p->micro)*(float)p->cntr)); + p->read_latch=(Bit16u)(p->cntr-(((double)micro/(double)p->micro)*(double)p->cntr)); break; } } @@ -109,14 +120,14 @@ static void write_latch(Bit32u port,Bit8u val) { case 0x00: /* Timer hooked to IRQ 0 */ PIC_RemoveEvents(PIT0_Event); PIC_AddEvent(PIT0_Event,p->micro); - LOG_DEBUG("PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode); + LOG(LOG_PIT,"PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode); break; case 0x02: /* Timer hooked to PC-Speaker */ -// LOG_DEBUG("PIT 2 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode); +// 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_ERROR("PIT:Illegal timer selected for writing"); + LOG(LOG_ERROR|LOG_PIT,"PIT:Illegal timer selected for writing"); } } } @@ -159,14 +170,12 @@ static Bit8u read_latch(Bit32u port) { static void write_p43(Bit32u port,Bit8u val) { - if (val & 1) { - E_Exit("PIT:BCD Counter not supported"); - } Bitu latch=(val >> 6) & 0x03; switch (latch) { case 0: case 1: case 2: + if (val & 1) E_Exit("PIT:Timer %d set to unsupported bcd mode",latch); if ((val & 0x30) == 0) { /* Counter latch command */ counter_latch(latch); @@ -177,9 +186,13 @@ static void write_p43(Bit32u port,Bit8u val) { } break; case 3: - E_Exit("Special PIT Latch Read out thing"); + if ((val & 0x20)==0) { /* Latch multiple pit counters */ + 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); + break; } - } /* The TIMER Part */ diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index b62dd7e..f07c5aa 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.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 @@ -27,29 +27,36 @@ #include "vga.h" VGA_Type vga; + Bit32u CGAWriteTable[256]; Bit32u ExpandTable[256]; Bit32u Expand16Table[4][16]; Bit32u Expand16BigTable[0x10000]; +Bit32u FillTable[16]; -Bit32u FillTable[16]={ - 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, - 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, - 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, - 0xffff0000,0xffff00ff,0xffffff00,0xffffffff -}; +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_BlankTimer(void) { - PIC_AddEvent(&VGA_BlankTimer,vga.draw.blank); +static void VGA_DrawHandler(RENDER_Part_Handler part_handler) { Bit8u * buf,* bufsplit; /* Draw the current frame */ - if (!vga.draw.resizing && RENDER_StartUpdate()) { + if (!vga.draw.resizing) { if (vga.config.line_compare=vga.draw.height){ - LOG_VGA("Split at %d",stop); + LOG(LOG_VGAGFX,"Split at %d",stop); goto drawnormal; } switch (vga.mode) { @@ -66,11 +73,11 @@ static void VGA_BlankTimer(void) { bufsplit=memory+0xa0000; break; default: - LOG_WARN("VGA:Unhandled split screen mode %d",vga.mode); + LOG(LOG_VGAGFX,"VGA:Unhandled split screen mode %d",vga.mode); goto norender; } - RENDER_Part(buf,0,0,vga.draw.width,stop); - RENDER_Part(bufsplit,0,stop,vga.draw.width,vga.draw.height-stop); + 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) { @@ -96,15 +103,11 @@ drawnormal: buf=&vga.mem.linear[vga.config.real_start*4+vga.config.pel_panning/2]; break; } - RENDER_Part(buf,0,0,vga.draw.width,vga.draw.height); - - + part_handler(buf,0,0,vga.draw.width,vga.draw.height); } -norender: - RENDER_EndUpdate(); - +norender:; } - VGA_StartRetrace(); + } void VGA_FindSettings(void) { @@ -158,8 +161,8 @@ static void VGA_DoResize(void) { /* Check for pixel doubling, master clock/2 */ if (vga.seq.clocking_mode & 0x8) clock/=2; - LOG_VGA("H total %d, V Total %d",htotal,vtotal); - LOG_VGA("H D End %d, V D End %d",hdispend,vdispend); + 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; @@ -218,9 +221,9 @@ static void VGA_DoResize(void) { vga.draw.height=height; vga.draw.pitch=pitch; - LOG_VGA("Width %d, Height %d",width,height); - LOG_VGA("Flags %X, fps %f",flags,fps); - RENDER_SetSize(width,height,8,pitch,((float)width/(float)height),flags); + 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); } @@ -246,15 +249,40 @@ void VGA_Init(Section* sec) { 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); +#else CGAWriteTable[i]=((i>>6)&3) | (((i>>4)&3) << 8)| (((i>>2)&3) <<16) | (((i>>0)&3) << 24); +#endif + } + for (i=0;i<16;i++) { +#ifdef WORDS_BIGENDIAN + FillTable[i]= ((i & 1) ? 0xff000000 : 0) | + ((i & 2) ? 0x00ff0000 : 0) | + ((i & 4) ? 0x0000ff00 : 0) | + ((i & 8) ? 0x000000ff : 0) ; +#else + FillTable[i]= ((i & 1) ? 0x000000ff : 0) | + ((i & 2) ? 0x0000ff00 : 0) | + ((i & 4) ? 0x00ff0000 : 0) | + ((i & 8) ? 0xff000000 : 0) ; +#endif } for (j=0;j<4;j++) { for (i=0;i<16;i++) { +#ifdef WORDS_BIGENDIAN + Expand16Table[j][i] = + ((i & 1) ? 1 << j : 0) | + ((i & 2) ? 1 << (8 + j) : 0) | + ((i & 4) ? 1 << (16 + j) : 0) | + ((i & 8) ? 1 << (24 + j) : 0); +#else Expand16Table[j][i] = ((i & 1) ? 1 << (24 + j) : 0) | ((i & 2) ? 1 << (16 + j) : 0) | ((i & 4) ? 1 << (8 + j) : 0) | ((i & 8) ? 1 << j : 0); +#endif } } for (i=0;i<0x10000;i++) { diff --git a/src/hardware/vga.h b/src/hardware/vga.h index 24537a4..9ce4b99 100644 --- a/src/hardware/vga.h +++ b/src/hardware/vga.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 @@ -266,11 +266,6 @@ extern Bit32u CGAWriteTable[256]; extern Bit32u Expand16Table[4][16]; extern Bit32u Expand16BigTable[0x10000]; -#if DEBUG_VGA -#define LOG_VGA LOG_DEBUG -#else -#define LOG_VGA -#endif #endif diff --git a/src/hardware/vga_attr.cpp b/src/hardware/vga_attr.cpp index 4bd4305..8c5d06a 100644 --- a/src/hardware/vga_attr.cpp +++ b/src/hardware/vga_attr.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 @@ -122,10 +122,10 @@ void write_p3c0(Bit32u port,Bit8u val) { except in 256 color mode. Note: this register does not affect 256 color modes. */ - if (val) LOG_DEBUG("VGA:ATTR:DAC index set to %d",val); + if (val) LOG(LOG_VGAGFX,"VGA:ATTR:DAC index set to %d",val); break; default: - LOG_ERROR("VGA:ATTR:Write to unkown Index %2X",attr(index)); + LOG(LOG_VGAMISC,"VGA:ATTR:Write to unkown Index %2X",attr(index)); break; } } @@ -151,7 +151,7 @@ Bit8u read_p3c1(Bit32u port) { case 0x14: /* Color Select Register */ return attr(color_select); default: - LOG_ERROR("VGA:ATTR:Read from unkown Index %2X",attr(index)); + LOG(LOG_VGAMISC,"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 588f900..56b558b 100644 --- a/src/hardware/vga_crtc.cpp +++ b/src/hardware/vga_crtc.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 @@ -274,7 +274,7 @@ void write_p3d5(Bit32u port,Bit8u val) { break; default: - LOG_ERROR("VGA:CRTC:Write to unknown index %2X",val,crtc(index)); + LOG(LOG_VGAMISC,"VGA:CRTC:Write to unknown index %2X",val,crtc(index)); } } @@ -331,7 +331,7 @@ Bit8u read_p3d5(Bit32u port) { case 0x18: /* Line Compare Register */ return crtc(line_compare); default: - LOG_ERROR("VGA:CRTC:Read from unknown index %X",crtc(index)); + LOG(LOG_VGAMISC,"VGA:CRTC:Read from unknown index %X",crtc(index)); } return 0; } diff --git a/src/hardware/vga_dac.cpp b/src/hardware/vga_dac.cpp index a4b400c..f03db34 100644 --- a/src/hardware/vga_dac.cpp +++ b/src/hardware/vga_dac.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 @@ -54,7 +54,7 @@ enum {DAC_READ,DAC_WRITE}; static void write_p3c6(Bit32u port,Bit8u val) { - if (val!=0xff) LOG_ERROR("VGA:Pel Mask not 0xff"); + if (val!=0xff) LOG(LOG_VGAGFX,"VGA:Pel Mask not 0xff"); vga.dac.pel_mask=val; } @@ -112,7 +112,7 @@ static void write_p3c9(Bit32u port,Bit8u val) { vga.dac.pel_index=0; break; default: - LOG_ERROR("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day + LOG(LOG_VGAGFX,"VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day }; } @@ -133,7 +133,7 @@ static Bit8u read_p3c9(Bit32u port) { vga.dac.pel_index=0; break; default: - LOG_ERROR("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day + LOG(LOG_VGAMISC,"VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day } return ret; } diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 006b1e1..055cefd 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.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 diff --git a/src/hardware/vga_fonts.cpp b/src/hardware/vga_fonts.cpp index bba9b32..f5e7564 100644 --- a/src/hardware/vga_fonts.cpp +++ b/src/hardware/vga_fonts.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 diff --git a/src/hardware/vga_gfx.cpp b/src/hardware/vga_gfx.cpp index a6e00d2..89fdf02 100644 --- a/src/hardware/vga_gfx.cpp +++ b/src/hardware/vga_gfx.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 @@ -70,7 +70,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_WARN("VGA:Data Rotate used %d",val &7); + if (vga.config.data_rotate) LOG(LOG_VGAGFX,"VGA:Data Rotate used %d",val &7); vga.config.raster_op=(val>>3) & 3; /* 0-2 Number of positions to rotate data right before it is written to @@ -171,12 +171,12 @@ void write_p3cf(Bit32u port,Bit8u val) { case 9: /* Unknown */ /* Crystal Dreams seems to like to write tothis register very weird */ if (!index9warned) { - LOG_WARN("VGA:3CF:Write %2X to illegal index 9",val); + LOG(LOG_VGAMISC,"VGA:3CF:Write %2X to illegal index 9",val); index9warned=true; } break; default: - LOG_WARN("VGA:3CF:Write %2X to illegal index %2X",val,gfx(index)); + LOG(LOG_VGAMISC,"VGA:3CF:Write %2X to illegal index %2X",val,gfx(index)); break; } } @@ -202,7 +202,7 @@ switch (gfx(index)) { case 8: /* Bit Mask Register */ return gfx(bit_mask); default: - LOG_WARN("Reading from illegal index %2X in port %4X",gfx(index),port); + LOG(LOG_VGAMISC,"Reading from illegal index %2X in port %4X",gfx(index),port); } return 0; /* Compiler happy */ } diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 32af55b..693d4a3 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_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 @@ -86,7 +86,7 @@ INLINE static Bit32u ModeOperation(Bit8u val) { full=RasterOp(vga.config.full_set_reset,ExpandTable[val] & vga.config.full_bit_mask); break; default: - LOG_ERROR("VGA:Unsupported write mode %d",vga.config.write_mode); + LOG(LOG_VGAMISC,"VGA:Unsupported write mode %d",vga.config.write_mode); } return full; } diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index 9202e91..1f4fcf4 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_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 @@ -21,7 +21,6 @@ #include "pic.h" #include "vga.h" - static Bit8u flip=0; static Bit32u keep_vretrace; static bool keeping=false; @@ -49,7 +48,7 @@ static Bit8u read_p3da(Bit32u port) { static void write_p3d8(Bit32u port,Bit8u val) { - LOG_DEBUG("Write %2X to 3da",val); + LOG(LOG_VGAMISC,"Write %2X to 3da",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. @@ -101,18 +100,6 @@ static Bit8u read_p3cc(Bit32u port) { return p3c2data; } - -static void EndRetrace(void) { - vga.config.retrace=false; -} - -void VGA_StartRetrace(void) { - /* 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; - PIC_AddEvent(EndRetrace,667); -} - void VGA_SetupMisc(void) { IO_RegisterReadHandler(0x3da,read_p3da,"VGA Input Status 1"); IO_RegisterReadHandler(0x3ba,read_p3da,"VGA Input Status 1"); diff --git a/src/hardware/vga_seq.cpp b/src/hardware/vga_seq.cpp index 15f0aa4..2fdaa17 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.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 @@ -91,7 +91,7 @@ void write_p3c5(Bit32u port,Bit8u val) { VGA_FindSettings(); break; default: - LOG_ERROR("VGA:SEQ:Write to illegal index %2X",seq(index)); + LOG(LOG_VGAMISC,"VGA:SEQ:Write to illegal index %2X",seq(index)); }; }; @@ -113,7 +113,7 @@ Bit8u read_p3c5(Bit32u port) { case 4: /* Memory Mode */ return seq(memory_mode); default: - LOG_ERROR("VGA:SEQ:Read from illegal index %2X",seq(index)); + LOG(LOG_VGAMISC,"VGA:SEQ:Read from illegal index %2X",seq(index)); }; return 0; }; diff --git a/src/ints/Makefile.in b/src/ints/Makefile.in index 228ddbd..f5dd55a 100644 --- a/src/ints/Makefile.in +++ b/src/ints/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -230,7 +233,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -275,7 +278,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index 8369786..5f5fa25 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.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 @@ -23,6 +23,7 @@ #include "inout.h" #include "mem.h" #include "pic.h" +#include "joystick.h" static Bitu call_int1a,call_int11,call_int8,call_int17,call_int12,call_int15,call_int1c; static Bitu call_int1; @@ -43,18 +44,18 @@ static Bitu INT1A_Handler(void) { case 0x02: /* GET REAL-TIME CLOCK TIME (AT,XT286,PS) */ reg_dx=reg_cx=0; CALLBACK_SCF(false); - LOG_WARN("INT1A:02:Faked RTC get time call"); + 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_WARN("INT1A:04:Faked RTC get date call"); + LOG(LOG_ERROR|LOG_BIOS,"INT1A:04:Faked RTC get date call"); break; case 0x80: /* Pcjr Setup Sound Multiplexer */ - LOG_WARN("INT1A:80:Setup tandy sound multiplexer to %d",reg_al); + LOG(LOG_ERROR|LOG_BIOS,"INT1A:80:Setup tandy sound multiplexer to %d",reg_al); break; case 0x81: /* Tandy sound system checks */ - LOG_WARN("INT1A:81:Tandy DAC Check failing"); + LOG(LOG_ERROR|LOG_BIOS,"INT1A:81:Tandy DAC Check failing"); break; /* INT 1A - Tandy 2500, Tandy 1000L series - DIGITAL SOUND - INSTALLATION CHECK @@ -67,7 +68,7 @@ static Bitu INT1A_Handler(void) { clear on return, then call AH=84h"Tandy" */ default: - LOG_WARN("INT1A:Undefined call %2X",reg_ah); + LOG(LOG_ERROR|LOG_BIOS,"INT1A:Undefined call %2X",reg_ah); } return CBRET_NONE; } @@ -95,7 +96,8 @@ static Bitu INT11_Handler(void) { internal modem installed (PC/Convertible) 14-15 number of parallel ports installed */ - reg_eax=0x104D; + reg_ax=0x104D; + LOG(LOG_BIOS,"INT11:Equipment list returned %X",reg_ax); return CBRET_NONE; } @@ -131,7 +133,7 @@ static Bitu INT12_Handler(void) { }; static Bitu INT17_Handler(void) { - LOG_ERROR("INT17:Not supported call for bios printer support"); + LOG(LOG_BIOS,"INT17:Function %X",reg_ah); switch(reg_ah) { case 0x00: /* PRINTER: Write Character */ reg_ah=1; /* Report a timeout */ @@ -145,7 +147,7 @@ static Bitu INT17_Handler(void) { 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)); @@ -156,10 +158,10 @@ static void WaitFlagEvent(void) { static Bitu INT15_Handler(void) { switch (reg_ah) { case 0x06: - LOG_WARN("Calling unkown int15 function 6"); + LOG(LOG_BIOS,"INT15 Unkown Function 6"); break; case 0xC0: /* Get Configuration*/ - LOG_WARN("Request BIOS Configuration INT 15 C0"); + LOG(LOG_ERROR|LOG_BIOS,"Request BIOS Configuration INT 15 C0"); CALLBACK_SCF(true); break; case 0x4f: /* BIOS - Keyboard intercept */ @@ -174,9 +176,31 @@ static Bitu INT15_Handler(void) { PIC_AddEvent(&WaitFlagEvent,reg_cx<<16|reg_dx); break; case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */ - //Does anyone even use this? - LOG_WARN("INT15:84:Bios Joystick functionality not done"); - reg_ax=reg_bx=reg_cx=reg_dx=0; + if (reg_dx==0x0000) { + // Get Joystick button status + if (JOYSTICK_IsEnabled(0) || JOYSTICK_IsEnabled(1)) { + reg_al = (JOYSTICK_GetButton(0,0)<<7)|(JOYSTICK_GetButton(0,1)<<6); + reg_al |= (JOYSTICK_GetButton(1,0)<<5)|(JOYSTICK_GetButton(1,1)<<4); + CALLBACK_SCF(false); + } else { + // dos values + reg_ax = 0x00f0; reg_dx = 0x0201; + CALLBACK_SCF(true); + } + } else if (reg_dx==0x0001) { + if (JOYSTICK_IsEnabled(0) || JOYSTICK_IsEnabled(1)) { + reg_ax = (Bit16u)JOYSTICK_GetMove_X(0); + reg_bx = (Bit16u)JOYSTICK_GetMove_Y(0); + reg_cx = (Bit16u)JOYSTICK_GetMove_X(1); + reg_dx = (Bit16u)JOYSTICK_GetMove_Y(1); + CALLBACK_SCF(false); + } else { + reg_ax=reg_bx=reg_cx=reg_dx=0; + CALLBACK_SCF(true); + } + } else { + LOG(LOG_ERROR|LOG_BIOS,"INT15:84:Unknown Bios Joystick functionality."); + } break; case 0x86: /* BIOS - WAIT (AT,PS) */ { @@ -197,18 +221,16 @@ static Bitu INT15_Handler(void) { reg_ah=0; break; case 0xc2: /* BIOS PS2 Pointing Device Support */ + case 0xc4: /* BIOS POS Programma option Select */ /* Damn programs should use the mouse drivers So let's fail these calls */ - CALLBACK_SCF(true); - break; - case 0xc4: /* BIOS POS Programma option Select */ - LOG_WARN("INT15:C4:Call for POS Function %2x",reg_al); + LOG(LOG_BIOS,"INT15:Function %X called,bios mouse not supported",reg_ah); CALLBACK_SCF(true); break; default: - LOG_WARN("INT15:Unknown call %2X",reg_ah); + LOG(LOG_ERROR|LOG_BIOS,"INT15:Unknown call %2X",reg_ah); reg_ah=0x86; CALLBACK_SCF(false); } @@ -219,7 +241,7 @@ static Bitu INT1_Single_Step(void) { static bool warned=false; if (!warned) { warned=true; - LOG_WARN("INT 1:Single Step called"); + LOG(LOG_CPU,"INT 1:Single Step called"); } return CBRET_NONE; } diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index cb53cb2..298ad39 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.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 @@ -34,10 +34,10 @@ static Bitu INT13_SmallHandler(void) { case 0x0: reg_ah=0x00; CALLBACK_SCF(false); - LOG_DEBUG("reset disk return succesfull"); + LOG(LOG_BIOS,"reset disk return succesfull"); break; case 0x02: /* Read Disk Sectors */ - LOG_DEBUG("INT13:02:Read Disk Sectors not supported failing"); + LOG(LOG_BIOS,"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_DEBUG("INT 13:04 Verify sector used on %d, with result %d",reg_dl,reg_ah); + LOG(LOG_BIOS,"INT 13:04 Verify sector used on %d, with result %d",reg_dl,reg_ah); break; case 0x08: /* Get Drive Parameters */ - LOG_DEBUG("INT13:08:Get Drive parameters not supported failing"); + LOG(LOG_BIOS,"INT13:08:Get Drive parameters not supported failing"); reg_ah=0xff; CALLBACK_SCF(true); break; case 0xff: default: - LOG_WARN("Illegal int 13h call %2X Fail it",reg_ah); + LOG(LOG_ERROR|LOG_BIOS,"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 afeaafc..f84a9b5 100644 --- a/src/ints/bios_keyboard.cpp +++ b/src/ints/bios_keyboard.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 @@ -197,17 +197,24 @@ static Bit16u check_key(void) { static Bitu IRQ1_Handler(void) { - //TODO CAPSLOCK NUMLOCK SCROLLLOCK maybe :) - Bit8u code=IO_Read(0x60); + /* Read the code */ + Bitu scancode,ascii,mod; +#if 0 + scancode=IO_Read(0x60); + ascii=0; + mod=0; +#else + KEYBOARD_ReadKey(scancode,ascii,mod); +// LOG(0,"Got code %X ascii %C mod %X",scancode,ascii,mod); +#endif + //TODO maybe implement the int 0x15 ah=4f scancode lookup hook -/* Changed it so the flag handling takes place in here too */ Bit8u flags1=mem_readb(BIOS_KEYBOARD_FLAGS1); Bit8u flags2=mem_readb(BIOS_KEYBOARD_FLAGS2); Bit8u flags3=mem_readb(BIOS_KEYBOARD_FLAGS3); - switch (code) { + switch (scancode) { /* First the hard ones */ - case 0xe0: - //TODO Think of something else maybe + case 0xe0: /* Extended key */ flags3|=2; break; case 29: /* Ctrl Pressed */ @@ -258,17 +265,18 @@ static Bitu IRQ1_Handler(void) { /* Now Handle the releasing of keys and see if they match up for a code */ flags3&=~2; //Reset 0xE0 Flag /* Handle the actual scancode */ - if (code & 0x80) goto irq1_end; - if (code > MAX_SCAN_CODE) goto irq1_end; - if (flags1 & 8) { /* Alt is being pressed */ - asciiscan=scan_to_scanascii[code].alt; - } else if (flags1 & 4) { /* Ctrl is being pressed */ - asciiscan=scan_to_scanascii[code].control; - } else if (flags1 & 3) { /* Either shift is being pressed */ -//TODO Maybe check for Capslock sometime in some bored way - asciiscan=scan_to_scanascii[code].shift; + if (scancode & 0x80) goto irq1_end; + if (scancode > MAX_SCAN_CODE) goto irq1_end; + if (mod & KBD_MOD_ALT) { /* Alt is being pressed */ + asciiscan=scan_to_scanascii[scancode].alt; + } else if (ascii) { + asciiscan=(scancode << 8) | ascii; + } else if (mod & KBD_MOD_CTRL) { /* Ctrl is being pressed */ + asciiscan=scan_to_scanascii[scancode].control; + } else if (mod & KBD_MOD_SHIFT) { /* Either shift is being pressed */ + asciiscan=scan_to_scanascii[scancode].shift; } else { - asciiscan=scan_to_scanascii[code].normal; + asciiscan=scan_to_scanascii[scancode].normal; } add_key(asciiscan); }; @@ -277,10 +285,12 @@ irq1_end: mem_writeb(BIOS_KEYBOARD_FLAGS2,flags2); mem_writeb(BIOS_KEYBOARD_FLAGS3,flags3); IO_Write(0x20,0x20); +#if 0 /* Signal the keyboard for next code */ Bit8u old61=IO_Read(0x61); IO_Write(0x61,old61 | 128); IO_Write(0x61,old61 & 127); +#endif return CBRET_NONE; } @@ -312,8 +322,7 @@ static Bitu INT16_Handler(void) { reg_al=mem_readb(BIOS_KEYBOARD_FLAGS1); break; case 0x03: /* SET TYPEMATIC RATE AND DELAY */ -//Have to implement this trhough SDL - LOG_DEBUG("INT16:Unhandled Typematic Rate Call %2X",reg_al); + LOG(LOG_ERROR|LOG_BIOS,"INT16:Unhandled Typematic Rate Call %2X",reg_al); break; case 0x05: /* STORE KEYSTROKE IN KEYBOARD BUFFER */ //TODO make add_key bool :) @@ -326,10 +335,10 @@ static Bitu INT16_Handler(void) { break; case 0x55: /* Weird call used by some dos apps */ - LOG_DEBUG("INT16:55:Word TSR compatible call"); + LOG(LOG_BIOS,"INT16:55:Word TSR compatible call"); break; default: - LOG_ERROR("INT16:Unhandled call %02X",reg_ah); + LOG(LOG_ERROR|LOG_BIOS,"INT16:Unhandled call %02X",reg_ah); break; }; diff --git a/src/ints/ems.cpp b/src/ints/ems.cpp index 24329d1..78ba177 100644 --- a/src/ints/ems.cpp +++ b/src/ints/ems.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 @@ -67,7 +67,7 @@ public: device_EMM(){name="EMMXXXX0";} bool Read(Bit8u * data,Bit16u * size) { return false;} bool Write(Bit8u * data,Bit16u * size){ - LOG_DEBUG("Write to ems device"); + LOG(LOG_IOCTL,"EMS:Write to device"); return false; } bool Seek(Bit32u * pos,Bit32u type){return false;} @@ -83,7 +83,7 @@ struct EMM_Mapping { }; struct EMM_Page { - HostPt * memory; + HostPt memory; Bit16u handle; Bit16u next; }; @@ -159,7 +159,7 @@ static Bit8u EMM_AllocateMemory(Bit16u pages,Bit16u & handle) { while (pages) { if (emm_pages[page].handle==NULL_HANDLE) { emm_pages[page].handle=handle; - emm_pages[page].memory=(HostPt *)malloc(EMM_PAGE_SIZE); + 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; @@ -209,7 +209,7 @@ static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) { while (pages) { if (emm_pages[page].handle==NULL_HANDLE) { emm_pages[page].handle=handle; - emm_pages[page].memory=(HostPt *)malloc(EMM_PAGE_SIZE); + 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; @@ -367,13 +367,14 @@ static Bit8u EMM_PartialPageMapping(void) { reg_al=2+reg_bx*(2+sizeof(EMM_Mapping)); break; default: - LOG_ERROR("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); + LOG(LOG_ERROR|LOG_MISC,"EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); return EMM_FUNC_NOSUP; } return EMM_NO_ERROR; } static Bit8u HandleNameSearch(void) { + char name[9]; Bit16u handle=0;PhysPt data; switch (reg_al) { case 0x00: /* Get all handle names */ @@ -387,13 +388,47 @@ static Bit8u HandleNameSearch(void) { } } break; + case 0x01: /* Search for a handle name */ + MEM_StrCopy(SegPhys(ds)+reg_si,name,8);name[8]=0; + for (handle=0;handle=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE; + MEM_BlockWrite(SegPhys(es)+reg_di,emm_handles[handle].name,8); + break; + case 0x01: /* Set Handle Name */ + if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE; + 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); + return EMM_FUNC_NOSUP; + } + return EMM_NO_ERROR; + +} + static void LoadMoveRegion(PhysPt data,MoveRegion & region) { region.bytes=mem_readd(data+0x0); @@ -414,7 +449,7 @@ static Bit8u MemoryRegion(void) { Bit8u buf_src[EMM_PAGE_SIZE]; Bit8u buf_dest[EMM_PAGE_SIZE]; if (reg_al>1) { - LOG_ERROR("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); + LOG(LOG_ERROR|LOG_MISC,"EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); return EMM_FUNC_NOSUP; } LoadMoveRegion(SegPhys(ds)+reg_si,region); @@ -548,7 +583,7 @@ static Bitu INT67_Handler(void) { reg_ah=EMM_NO_ERROR; break; case 0x4c: /* Get Pages for one Handle */ - if (!ValidHandle(reg_bx)) {reg_ah=EMM_INVALID_HANDLE;break;} + if (!ValidHandle(reg_dx)) {reg_ah=EMM_INVALID_HANDLE;break;} reg_bx=emm_handles[reg_dx].pages; reg_ah=EMM_NO_ERROR; break; @@ -575,7 +610,7 @@ static Bitu INT67_Handler(void) { reg_ah=EMM_NO_ERROR; break; default: - LOG_ERROR("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); + LOG(LOG_ERROR|LOG_MISC,"EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al); reg_ah=EMM_FUNC_NOSUP; break; } @@ -611,19 +646,14 @@ static Bitu INT67_Handler(void) { reg_ah=EMM_ReallocatePages(reg_dx,reg_bx); break; case 0x53: // Set/Get Handlename - if (reg_al==0x00) { // Get Name not supported - LOG_ERROR("EMS:Get handle name not supported",reg_ah); - reg_ah=EMM_FUNC_NOSUP; - } else { // Set name, not supported but faked - reg_ah=EMM_NO_ERROR; - } + reg_ah=GetSetHandleName(); break; case 0x54: /* Handle Functions */ reg_ah=HandleNameSearch(); break; case 0x57: /* Memory region */ reg_ah=MemoryRegion(); - if (reg_ah) LOG_WARN("ems 57 move failed"); + if (reg_ah) LOG(LOG_ERROR,"EMS:Function 57 move failed"); break; case 0x58: // Get mappable physical array address array if (reg_al==0x00) { @@ -639,11 +669,12 @@ static Bitu INT67_Handler(void) { reg_ah = EMM_NO_ERROR; break; case 0xDE: /* VCPI Functions */ - LOG_ERROR("VCPI Functions %X not supported",reg_al); + errorlevel=1; + E_Exit("Protected mode not supported"); reg_ah=EMM_FUNC_NOSUP; break; default: - LOG_ERROR("EMS:Call %2X not supported",reg_ah); + LOG(LOG_ERROR|LOG_MISC,"EMS:Call %2X not supported",reg_ah); reg_ah=EMM_FUNC_NOSUP; break; } @@ -657,7 +688,7 @@ void EMS_Init(Section* sec) { Bitu size=section->Get_int("emssize"); if (!size) return; if ((size*(1024/16))>EMM_MAX_PAGES) { - LOG_DEBUG("EMS Max size is %d",EMM_MAX_PAGES/(1024/16)); + 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); diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp index 34d40cf..571af94 100644 --- a/src/ints/int10.cpp +++ b/src/ints/int10.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 @@ -32,6 +32,8 @@ static Bitu call_10; static bool warned_ff=false; static bool warned_int10_0b=false; +Int10Data int10; + static Bitu INT10_Handler(void) { switch (reg_ah) { @@ -40,7 +42,7 @@ static Bitu INT10_Handler(void) { break; case 0x01: /* Set TextMode Cursor Shape */ vga.internal.cursor=reg_cx; // maybe write some memory somewhere - LOG_DEBUG("INT10:01:Set textmode cursor shape partially supported: %X",reg_cx); + LOG(LOG_INT10,"INT10:01:Set textmode cursor shape partially supported: %X",reg_cx); break; case 0x02: /* Set Cursor Pos */ //TODO Check some shit but not really usefull @@ -52,17 +54,19 @@ static Bitu INT10_Handler(void) { reg_dh=CURSOR_POS_ROW(reg_bh); break; case 0x04: /* read light pen pos YEAH RIGHT */ - LOG_WARN("INT10:04:Ligthpen not supported"); + /* Light pen is not supported */ + reg_ah=0; break; case 0x05: /* Set Active Page */ - if (reg_al & 0x80) LOG_DEBUG("Func %x",reg_al); + if (reg_al & 0x80) LOG(LOG_INT10,"Func %x",reg_al); else INT10_SetActivePage(reg_al); break; case 0x06: /* Scroll Up */ //TODO Graphics mode scroll INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,-reg_al,reg_bh,0xFF); break; - case 0x07: /* Scroll Down */ + case 0x07: + /* Scroll Down */ INT10_ScrollWindow(reg_ch,reg_cl,reg_dh,reg_dl,reg_al,reg_bh,0xFF); break; case 0x08: /* Read character & attribute at cursor */ @@ -77,12 +81,10 @@ static Bitu INT10_Handler(void) { break; case 0x0B: /* Set Background/Border Colour & Set Palette*/ if(!warned_int10_0b) { - LOG_WARN("INT 10:0B Unsupported: Set Background/border colour & Set Pallete"); + LOG(LOG_ERROR|LOG_INT10,"Function 0B Unsupported: Set Background/border colour & Set Pallete"); warned_int10_0b=true; } break; - E_Exit("Unsupported int 10 call %02X" ,reg_ah); - break; case 0x0C: /* Write Graphics Pixel */ INT10_PutPixel(reg_cx,reg_dx,reg_bh,reg_al); break; @@ -133,7 +135,7 @@ static Bitu INT10_Handler(void) { INT10_GetDACBlock(reg_bx,reg_cx,SegPhys(es)+reg_dx); break; default: - LOG_WARN("INT10:10:Unhandled EGA/VGA Palette Function %2X",reg_al); + LOG(LOG_ERROR|LOG_INT10,"Function 10:Unhandled EGA/VGA Palette Function %2X",reg_al); } break; case 0x11: /* Character generator functions */ @@ -178,12 +180,12 @@ static Bitu INT10_Handler(void) { break; default: reg_cx=16; - LOG_DEBUG("INT10:11:30 Request for font %2X",reg_bh); + LOG(LOG_ERROR|LOG_INT10,"Fucntion 11:30 Request for font %2X",reg_bh); } reg_dl=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS); break; default: - LOG_WARN("INT10:11:Unsupported character generator call %2X",reg_al); + LOG(LOG_ERROR|LOG_INT10,"Function 11:Unsupported character generator call %2X",reg_al); } break; case 0x12: /* alternate function select */ @@ -196,7 +198,7 @@ static Bitu INT10_Handler(void) { break; } default: - LOG_WARN("Alternate functions select %2X not handled",reg_bl); + LOG(LOG_ERROR|LOG_INT10,"Function 12:Call %2X not handled",reg_bl); } break; case 0x13: /* Write String */ @@ -213,7 +215,6 @@ static Bitu INT10_Handler(void) { reg_al=0x1A; break; } - LOG_DEBUG("INT10:1A:Display Combination call %2X",reg_al); break; case 0x1B: /* functionality State Information */ switch (reg_bx) { @@ -222,15 +223,15 @@ static Bitu INT10_Handler(void) { reg_al=0x1B; break; default: - LOG_WARN("INT10:1B:Unhandled call BX %2X",reg_bx); + LOG(LOG_ERROR|LOG_INT10,"Function 1B:Unhandled call BX %2X",reg_bx); } break; case 0xff: - if (!warned_ff) LOG_WARN("INT10:FF:Weird NC call"); + if (!warned_ff) LOG(LOG_INT10,"INT10:FF:Weird NC call"); warned_ff=true; break; default: - LOG_WARN("Unhandled INT 10 call %2X",reg_ah); + LOG(LOG_ERROR|LOG_INT10,"Function %2X not supported",reg_ah); }; return CBRET_NONE; } @@ -269,8 +270,6 @@ void INT10_Init(Section* sec) { INT10_InitVGA(); /* Setup the INT 10 vector */ call_10=CALLBACK_Allocate(); - //TODO ERRORS ERRORS ERRORS - if (call_10==-1) E_Exit("Error can't allocate Video Int 10 CallBack\n"); CALLBACK_Setup(call_10,&INT10_Handler,CB_IRET); RealSetVec(0x10,CALLBACK_RealPointer(call_10)); //Init the 0x40 segment and init the datastructures in the the video rom area diff --git a/src/ints/int10.h b/src/ints/int10.h index 9ccc3a6..de9c92c 100644 --- a/src/ints/int10.h +++ b/src/ints/int10.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 @@ -101,7 +101,7 @@ #define PLANAR2 0x04 #define PLANAR4 0x05 #define LINEAR8 0x06 - +#define CGA2 0x07 // for Tandy #define TANDY16 0x0A @@ -206,3 +206,10 @@ void INT10_SetGfxControllerToDefault(void); /* Sup Groups */ void INT10_SetupRomMemory(void); +struct Int10Data { + Bit8u mode; + VGAMODES * entry; +}; + +extern Int10Data int10; + diff --git a/src/ints/int10_char.cpp b/src/ints/int10_char.cpp index 8244951..abb7d0d 100644 --- a/src/ints/int10_char.cpp +++ b/src/ints/int10_char.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 @@ -89,6 +89,8 @@ static INLINE void PLANAR4_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,B for (Bitu x=0;xtype==GRAPH) page=0xff; BIOS_NCOLS;BIOS_NROWS; if(rul>rlr) return; if(cul>clr) return; if(rlr>=nrows) rlr=(Bit8u)nrows-1; if(clr>=ncols) clr=(Bit8u)ncols-1; clr++; + /* Get the correct page */ if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); - VGAMODES * curmode=GetCurrentMode(); PhysPt base=PhysMake(curmode->sstart,curmode->slength*page); /* See how much lines need to be copies */ @@ -131,18 +135,19 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit nlines=rlr-rul+1; goto filling; } - do { + 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; } - } while (start!=end); + } /* Fill some lines */ filling: if (nlines>0) { @@ -244,7 +249,7 @@ INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u at } break; case GRAPH: - { + { /* Amount of lines */ Bit8u * fontdata; Bit16u x,y; @@ -261,7 +266,7 @@ INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u at fontdata=&int10_font_16[chr*16]; break; default: - LOG_ERROR("INT10:Teletype Illegal Font Height"); + LOG(LOG_ERROR|LOG_INT10,"Teletype Illegal Font Height"); return; } x=8*col; @@ -273,7 +278,7 @@ INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u at Bit16u tx=x; while (bitsel) { if (bitline&bitsel) INT10_PutPixel(tx,y,page,attr); - else INT10_PutPixel(tx,y,page,0); + else INT10_PutPixel(tx,y,page,attr & 0x80); tx++; bitsel>>=1; } @@ -285,6 +290,8 @@ INLINE static void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit8u chr,Bit8u at } void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) { + VGAMODES * curmode=GetCurrentMode(); + if (curmode->type==GRAPH) 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); @@ -302,6 +309,8 @@ 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); BIOS_NCOLS;BIOS_NROWS; Bit8u cur_row=CURSOR_POS_ROW(page); @@ -347,6 +356,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; if(page==0xFF) page=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); BIOS_NCOLS;BIOS_NROWS; diff --git a/src/ints/int10_modes.cpp b/src/ints/int10_modes.cpp index 1f57897..9674f99 100644 --- a/src/ints/int10_modes.cpp +++ b/src/ints/int10_modes.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 @@ -33,7 +33,7 @@ VGAMODES vga_modes[MODE_MAX+1]= {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, CGA, 1, 1, 640, 200, 80, 25, 8, 8, 0xB800, 0x1000, 0x63, 0xFF, 0x03, 0x02, 0x02, 0x03, 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}, {0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x2000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01}, @@ -239,9 +239,11 @@ static Bit8u FindVideoMode(Bit8u mode) { } VGAMODES * GetCurrentMode(void) { - Bit8u ret=FindVideoMode(real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)&127); - if (ret==0xff) return 0; - return &vga_modes[ret]; + 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; } @@ -257,7 +259,7 @@ void INT10_SetVideoMode(Bit8u mode) { mode&=mode & 127; line=FindVideoMode(mode); if (line==0xff) { - LOG_ERROR("INT10:Trying to set non supported video mode %X",mode); + LOG(LOG_ERROR|LOG_INT10,"INT10:Trying to set non supported video mode %X",mode); return; } @@ -312,7 +314,7 @@ void INT10_SetVideoMode(Bit8u mode) { IO_Read(VGAREG_ACTL_RESET); //Set the palette - if ((modeset_ctl&0x08)==0x8) LOG_DEBUG("INT10:Mode set without 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); diff --git a/src/ints/int10_put_pixel.cpp b/src/ints/int10_put_pixel.cpp index eb425c0..934b727 100644 --- a/src/ints/int10_put_pixel.cpp +++ b/src/ints/int10_put_pixel.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,24 +22,37 @@ #include "int10.h" 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: { - Bit16u off=(y>>1)*80+(x>>2); - if (y&1) off+=8*1024; - Bit8u old=real_readb(0xb800,off); - if (color & 0x80) { - color&=3; - old^=color << (2*(3-(x&3))); - } else { - old=old&cga_masks[x&3]|((color&3) << (2*(3-(x&3)))); - } - real_writeb(0xb800,off,old); + Bit16u off=(y>>1)*80+(x>>2); + if (y&1) off+=8*1024; + Bit8u old=real_readb(0xb800,off); + if (color & 0x80) { + color&=3; + old^=color << (2*(3-(x&3))); + } else { + old=old&cga_masks[x&3]|((color&3) << (2*(3-(x&3)))); + } + real_writeb(0xb800,off,old); + } + break; + case CGA2: + { + Bit16u off=(y>>1)*80+(x>>3); + if (y&1) off+=8*1024; + Bit8u old=real_readb(0xb800,off); + if (color & 0x80) { + color&=1; + old^=color << ((7-(x&7))); + } else { + old=old&cga_masks2[x&7]|((color&1) << ((7-(x&7)))); + } + real_writeb(0xb800,off,old); } break; case PLANAR4: @@ -60,6 +73,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { mem_writeb(off,0xff); /* Restore bitmask */ IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff); + IO_Write(0x3ce,0x1);IO_Write(0x3cf,0); /* Restore write operating if changed */ if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); } break; @@ -72,7 +86,7 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { case CTEXT: case MTEXT: default: - LOG_WARN("INT10:PutPixel Unhanled memory model"); + LOG(LOG_ERROR|LOG_INT10,"PutPixel Unhandled memory model %d",curmode->memmodel); break; } } @@ -85,7 +99,15 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { Bit16u off=(y>>1)*80+(x>>2); if (y&1) off+=8*1024; Bit8u val=real_readb(0xb800,off); - *color=val<<((x&3)*2); + *color=(val>>(((3-x&3))*2)) & 3 ; + } + break; + case CGA2: + { + Bit16u off=(y>>1)*80+(x>>3); + if (y&1) off+=8*1024; + Bit8u val=real_readb(0xb800,off); + *color=(val>>(((7-x&7)))) & 1 ; } break; case PLANAR4: @@ -113,7 +135,7 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { case CTEXT: case MTEXT: default: - LOG_WARN("INT10:GetPixel Unhanled memory model"); + LOG(LOG_ERROR|LOG_INT10,"GetPixel Unhandled memory model %d",curmode->memmodel); break; } } diff --git a/src/ints/mouse.cpp b/src/ints/mouse.cpp index 50bcf6a..949dc7f 100644 --- a/src/ints/mouse.cpp +++ b/src/ints/mouse.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 @@ -26,6 +26,7 @@ #include "pic.h" #include "inout.h" #include "int10.h" +#include "bios.h" static Bitu call_int33,call_int74; @@ -93,7 +94,6 @@ static struct { Bit16s clipx,clipy; Bit16s hotx,hoty; Bit16u textAndMask, textXorMask; - Bit16u resy; float mickeysPerPixel_x; float mickeysPerPixel_y; @@ -324,10 +324,10 @@ void Mouse_CursorMoved(float x,float y) { mouse.mickey_y += dy; mouse.x += dx; - if (mouse.x>mouse.max_x) mouse.x=mouse.max_x;; + if (mouse.x>mouse.max_x) mouse.x=mouse.max_x; if (mouse.xmouse.max_y) mouse.y=mouse.max_y;; + if (mouse.y>mouse.max_y) mouse.y=mouse.max_y; if (mouse.y0) mouse.shown=0; DrawCursor(); break; @@ -461,12 +490,10 @@ static Bitu INT33_Handler(void) { case 0x05: /* Return Button Press Data */ { Bit16u but=reg_bx; - if (but>=MOUSE_BUTTONS) break; reg_ax=mouse.buttons; + if (but>=MOUSE_BUTTONS) break; reg_cx=mouse.last_pressed_x[but]; - mouse.last_pressed_x[but]=0; reg_dx=mouse.last_pressed_y[but]; - mouse.last_pressed_y[but]=0; reg_bx=mouse.times_pressed[but]; mouse.times_pressed[but]=0; break; @@ -474,33 +501,35 @@ static Bitu INT33_Handler(void) { case 0x06: /* Return Button Release Data */ { Bit16u but=reg_bx; - if (but>=MOUSE_BUTTONS) break; reg_ax=mouse.buttons; + if (but>=MOUSE_BUTTONS) break; reg_cx=mouse.last_released_x[but]; - mouse.last_released_x[but]=0; reg_dx=mouse.last_released_y[but]; - mouse.last_released_y[but]=0; reg_bx=mouse.times_released[but]; mouse.times_released[but]=0; break; } case 0x07: /* Define horizontal cursor range */ - if (reg_cxGetValue())._string->c_str(); } } - return NULL; + return ""; } int Section_prop::Get_hex(const char* _propname){ for(it tel=properties.begin();tel!=properties.end();tel++){ @@ -222,7 +222,8 @@ void Config::ParseConfigFile(const char* configfilename){ return; } char gegevens[150]; - Section* currentsection; + Section* currentsection = NULL; + Section* testsec = NULL; while (in) { in.getline(gegevens,150); char* temp; @@ -237,7 +238,9 @@ void Config::ParseConfigFile(const char* configfilename){ case '[': temp = strrchr(gegevens,']'); *temp=0; - currentsection=GetSection(&gegevens[1]); + testsec = GetSection(&gegevens[1]); + if(testsec != NULL ) currentsection = testsec; + testsec = NULL; break; default: try{ @@ -251,6 +254,22 @@ void Config::ParseConfigFile(const char* configfilename){ } } +void Config::ParseEnv(char ** envp) { + for(char** env=envp; *env;env++) { + char copy[1024]; + strncpy(copy,*env,1024); + if(strncasecmp(copy,"DOSBOX_",7)) + continue; + char* sec_name = ©[7]; + char* prop_name = strrchr(sec_name,'_'); + *prop_name++=0; + Section* sect = GetSection(sec_name); + if(!sect) + continue; + sect->HandleInputline(prop_name); + } +} + void Config::SetStartUp(void (*_function)(void)) { _start_function=_function; } diff --git a/src/misc/support.cpp b/src/misc/support.cpp index fb16f52..dd9a9bf 100644 --- a/src/misc/support.cpp +++ b/src/misc/support.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 @@ -85,7 +85,7 @@ char *trim(char *str) { bool ScanCMDBool(char * cmd,char * check) { char * scan=cmd;size_t c_len=strlen(check); - while (scan=strchr(scan,'/')) { + 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)) { @@ -101,7 +101,7 @@ bool ScanCMDBool(char * cmd,char * check) { bool ScanCMDHex(char * cmd,char * check,Bits * result) { char * scan=cmd;size_t c_len=strlen(check); - while (scan=strchr(scan,'/')) { + 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)) { @@ -125,7 +125,7 @@ bool ScanCMDHex(char * cmd,char * check,Bits * result) { /* This scans the command line for a remaining switch and reports it else returns 0*/ char * ScanCMDRemain(char * cmd) { char * scan,*found;; - if (scan=found=strchr(cmd,'/')) { + if ((scan=found=strchr(cmd,'/'))) { while (*scan!=' ' && *scan!=0) scan++; *scan=0; return found; @@ -156,7 +156,6 @@ char * StripWord(char * cmd) { } void GFX_ShowMsg(char * msg); -void DEBUG_ShowMsg(char * msg); void S_Warn(char * format,...) { char buf[1024]; @@ -166,7 +165,7 @@ void S_Warn(char * format,...) { vsprintf(buf,format,msg); va_end(msg); #if C_DEBUG - DEBUG_ShowMsg(buf); + DEBUG_ShowMsg(0,buf); #else GFX_ShowMsg(buf); #endif diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in index dd4d25e..c31af00 100644 --- a/src/platform/Makefile.in +++ b/src/platform/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -205,7 +208,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -263,7 +266,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/platform/visualc/Makefile.in b/src/platform/visualc/Makefile.in index 7d59572..fa436d6 100644 --- a/src/platform/visualc/Makefile.in +++ b/src/platform/visualc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -106,7 +109,7 @@ top_distdir = ../../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -151,7 +154,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/platform/visualc/config.h b/src/platform/visualc/config.h index 83fa3b1..811ebc7 100644 --- a/src/platform/visualc/config.h +++ b/src/platform/visualc/config.h @@ -1,6 +1,23 @@ #define INLINE __forceinline -#define VERSION "0.57" +#define VERSION "0.58" + +/* Define to 1 to enable internal debugger, requires libcurses */ +#define C_DEBUG 0 + +/* Define to 1 to enable screenshots, requires libpng */ +#define C_SSHOT 1 + +/* 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 #define GCC_ATTRIBUTE(x) /* attribute not supported */ - diff --git a/src/platform/visualc/dirent.c b/src/platform/visualc/dirent.c index f6be792..cc536bf 100644 --- a/src/platform/visualc/dirent.c +++ b/src/platform/visualc/dirent.c @@ -20,10 +20,14 @@ DIR * opendir(const char *dirname) { static DIR dir; + int len; /* Stash the directory name */ strcpy(dir.pathName,dirname); - strcat(dir.pathName,"*.*"); + + len = strlen(dirname); + if ((len>0) && (dirname[len-1]=='\\')) strcat(dir.pathName,"*.*"); + else strcat(dir.pathName,"\\*.*"); /* set the handle to invalid and set the firstTime flag */ dir.handle = INVALID_HANDLE_VALUE; diff --git a/src/shell/Makefile.in b/src/shell/Makefile.in index f167e5a..d6aa076 100644 --- a/src/shell/Makefile.in +++ b/src/shell/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -209,7 +212,7 @@ top_distdir = ../.. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -254,7 +257,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index 323a79b..455f528 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -67,7 +67,7 @@ Bit32u DOS_Shell::GetRedirection(char *s, char **ifn, char **ofn) { return 1; -} +} @@ -157,14 +157,14 @@ void AUTOEXEC_Init(Section * sec) { if (stat(buffer,&test)) goto nomount; } if (test.st_mode & S_IFDIR) { - SHELL_AddAutoexec("MOUNT C %s",buffer); + SHELL_AddAutoexec("MOUNT C \"%s\"",buffer); SHELL_AddAutoexec("C:"); } else { char * name=strrchr(buffer,CROSS_FILESPLIT); if (!name) goto nomount; *name++=0; if (access(buffer,F_OK)) goto nomount; - SHELL_AddAutoexec("MOUNT C %s",buffer); + SHELL_AddAutoexec("MOUNT C \"%s\"",buffer); SHELL_AddAutoexec("C:"); SHELL_AddAutoexec(name); } @@ -188,7 +188,7 @@ void SHELL_Init() { MSG_Add("SHELL_CMD_CHDIR_ERROR","Unable to change to: %s\n"); MSG_Add("SHELL_CMD_MKDIR_ERROR","Unable to make: %s\n"); MSG_Add("SHELL_CMD_RMDIR_ERROR","Unable to remove: %s\n"); - MSG_Add("SHELL_CMD_DEL_ERROR","Unable to delete: %s\n"); + MSG_Add("SHELL_CMD_DEL_ERROR","Unable to delete: %s\n"); MSG_Add("SHELL_SYNTAXERROR","The syntax of the command is incorrect.\n"); MSG_Add("SHELL_CMD_SET_NOT_SET","Environment variable %s not defined\n"); MSG_Add("SHELL_CMD_SET_OUT_OF_SPACE","Not enough environment space left.\n"); @@ -204,14 +204,15 @@ void SHELL_Init() { MSG_Add("SHELL_CMD_DIR_BYTES_FREE","%5d Dir(s) %17s Bytes free\n"); MSG_Add("SHELL_EXECUTE_DRIVE_NOT_FOUND","Drive %c does not exist!\n"); MSG_Add("SHELL_EXECUTE_ILLEGAL_COMMAND","Illegal command: %s.\n"); + MSG_Add("SHELL_CMD_PAUSE","Press any key to continue.\n"); + MSG_Add("SHELL_CMD_PAUSE_HELP","Waits for 1 keystroke to continue.\n"); + MSG_Add("SHELL_CMD_COPY_FAILURE","Copy failure : %s.\n"); + MSG_Add("SHELL_CMD_COPY_SUCCESS"," %d File(s) copied.\n"); MSG_Add("SHELL_STARTUP","DOSBox Shell v" VERSION "\n" - "DOSBox doesn't not run protected mode games!\n" + "DOSBox does not run protected mode games!\n" "For supported shell commands type: HELP\n" -#if! defined (WIN32) - "DOSBox only works with upcase filenames as dos is case-insensitive.\n" - "You can use the UPCASE command for this, but please be careful.\n" -#endif + "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" ); @@ -232,6 +233,8 @@ void SHELL_Init() { MSG_Add("SHELL_CMD_NO_WILD","This is a simple version of the command, no wildcards allowed!\n"); MSG_Add("SHELL_CMD_RENAME_HELP","Renames files.\n"); MSG_Add("SHELL_CMD_DELETE_HELP","Removes files.\n"); + MSG_Add("SHELL_CMD_COPY_HELP","Copy files.\n"); + MSG_Add("SHELL_CMD_INTRO_HELP","Gives an introduction into dosbox\n"); /* Regular startup */ call_shellstop=CALLBACK_Allocate(); /* Setup the startup CS:IP to kill the last running machine when exitted */ @@ -249,9 +252,10 @@ void SHELL_Init() { SegSet16(ss,stack_seg); reg_sp=2046; /* Setup MCB and the environment */ - MCB * env_mcb=(MCB *)HostMake(env_seg-1,0); - env_mcb->psp_segment=psp_seg; - env_mcb->size=4096/16; + DOS_MCB envmcb((Bit16u)(env_seg-1)); + envmcb.SetPSPSeg(psp_seg); + envmcb.SetSize(4096/16); + PhysPt env_write=PhysMake(env_seg,0); MEM_BlockWrite(env_write,path_string,strlen(path_string)+1); env_write+=strlen(path_string)+1; diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index 5b0004b..7d3fe73 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -26,7 +26,7 @@ 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, "Copy Files.", + "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", @@ -42,6 +42,7 @@ static SHELL_Cmd cmd_list[]={ "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", @@ -301,11 +302,97 @@ void DOS_Shell::CMD_DIR(char * args) { } void DOS_Shell::CMD_COPY(char * args) { + + DOS_DTA dta(dos.dta); + Bit32u size;Bit16u date;Bit16u time;Bit8u attr; + char name[DOS_NAMELENGTH_ASCII]; + char * rem=ScanCMDRemain(args); if (rem) { WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); return; } + // source/target + char* source = args; + char* target = StripWord(source); + + // Target and Source have to be there + if (!source || !strlen(source)) { + WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); + return; + }; + + /* Make a full path in the args */ + char pathSource[DOS_PATHLENGTH]; + char pathTarget[DOS_PATHLENGTH]; + + if (!DOS_Canonicalize(source,pathSource)) { + WriteOut(MSG_Get("SHELL_CMD_ILLEGAL_PATH")); + return; + } + // cut search pattern + char* pos = strrchr(pathSource,'\\'); + if (pos) *(pos+1) = 0; + + if (!DOS_Canonicalize(target,pathTarget)) { + WriteOut(MSG_Get("SHELL_CMD_ILLEGAL_PATH")); + return; + } + // add '\\' if target is a directoy + if (pathTarget[strlen(pathTarget)-1]!='\\') { + if (DOS_FindFirst(pathTarget,0xffff)) { + dta.GetResult(name,size,date,time,attr); + if (attr & DOS_ATTR_DIRECTORY) + strcat(pathTarget,"\\"); + } + }; + + bool ret=DOS_FindFirst(args,0xffff); + if (!ret) { + WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); + return; + } + + Bit32u count = 0; + + Bit16u sourceHandle,targetHandle; + char nameTarget[DOS_PATHLENGTH]; + char nameSource[DOS_PATHLENGTH]; + + while (ret) { + dta.GetResult(name,size,date,time,attr); + + if ((attr & DOS_ATTR_DIRECTORY)==0) { + strcpy(nameSource,pathSource); + strcat(nameSource,name); + // Open Source + if (DOS_OpenFile(nameSource,0,&sourceHandle)) { + // Create Target + strcpy(nameTarget,pathTarget); + if (nameTarget[strlen(nameTarget)-1]=='\\') strcat(nameTarget,name); + + if (DOS_CreateFile(nameTarget,0,&targetHandle)) { + // Copy + Bit8u buffer[0x8000]; + bool failed = false; + Bit16u toread = 0x8000; + do { + failed |= DOS_ReadFile(sourceHandle,buffer,&toread); + failed |= DOS_WriteFile(targetHandle,buffer,&toread); + } while (toread==0x8000); + failed |= DOS_CloseFile(sourceHandle); + failed |= DOS_CloseFile(targetHandle); + WriteOut(" %s\n",name); + count++; + } else { + DOS_CloseFile(sourceHandle); + WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),target); + } + } else WriteOut(MSG_Get("SHELL_CMD_COPY_FAILURE"),source); + }; + ret=DOS_FindNext(); + }; + WriteOut(MSG_Get("SHELL_CMD_COPY_SUCCESS"),count); } void DOS_Shell::CMD_SET(char * args) { @@ -427,4 +514,9 @@ nextfile: 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; + DOS_ReadFile (STDIN,&c,&n); +} diff --git a/src/shell/shell_inc.h b/src/shell/shell_inc.h index e21f323..2194780 100644 --- a/src/shell/shell_inc.h +++ b/src/shell/shell_inc.h @@ -66,7 +66,7 @@ public: void CMD_CLS(char * args); void CMD_COPY(char * args); void CMD_DIR(char * args); - void CMD_DELETE(char * args); + void CMD_DELETE(char * args); void CMD_ECHO(char * args); void CMD_EXIT(char * args); void CMD_MKDIR(char * args); @@ -77,9 +77,9 @@ public: void CMD_GOTO(char * args); void CMD_TYPE(char * args); void CMD_REM(char * args); - void CMD_RENAME(char * args); + void CMD_RENAME(char * args); void SyntaxError(void); - + void CMD_PAUSE(char * args); /* The shell's variables */ Bit16u input_handle; BatchFile * bf; diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index 63a4516..2712a5f 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -61,7 +61,7 @@ void DOS_Shell::InputCommand(char * line) { case 0x3d: /* F3 */ if (strlen(old.buffer)>str_len) { reader=&old.buffer[str_len]; - while (c=*reader++) { + while ((c=*reader++)) { line[str_index]=c; str_len++; str_index++; diff --git a/visualc/Makefile.in b/visualc/Makefile.in index 05885e8..675fd34 100644 --- a/visualc/Makefile.in +++ b/visualc/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.6.1 from Makefile.am. +# Makefile.in generated by automake 1.6.3 from Makefile.am. # @configure_input@ # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 @@ -49,6 +49,7 @@ 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@ @@ -64,6 +65,8 @@ host_triplet = @host@ EXEEXT = @EXEEXT@ OBJEXT = @OBJEXT@ PATH_SEPARATOR = @PATH_SEPARATOR@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ AMTAR = @AMTAR@ AWK = @AWK@ CC = @CC@ @@ -106,7 +109,7 @@ top_distdir = .. distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) distdir: $(DISTFILES) - @for file in $(DISTFILES); do \ + @list='$(DISTFILES)'; for file in $$list; do \ 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 \ @@ -151,7 +154,7 @@ mostlyclean-generic: clean-generic: distclean-generic: - -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]* + -rm -f Makefile $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/visualc/dosbox.dsp b/visualc/dosbox.dsp index 9fd8aed..cb541c3 100644 --- a/visualc/dosbox.dsp +++ b/visualc/dosbox.dsp @@ -20,7 +20,6 @@ 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 "" @@ -50,7 +49,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 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 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" @@ -75,7 +74,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 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 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 @@ -98,10 +97,6 @@ SOURCE=..\src\cpu\core_16\helpers.h # End Source File # Begin Source File -SOURCE=..\src\cpu\core_16\instructions.h -# End Source File -# Begin Source File - SOURCE=..\src\cpu\core_16\main.h # End Source File # Begin Source File @@ -147,6 +142,10 @@ SOURCE=..\src\cpu\flags.cpp # End Source File # Begin Source File +SOURCE=..\src\cpu\instructions.h +# End Source File +# Begin Source File + SOURCE=..\src\cpu\modrm.cpp # End Source File # Begin Source File @@ -202,6 +201,10 @@ SOURCE=..\src\dos\dev_con.h # PROP Default_Filter "" # Begin Source File +SOURCE=..\src\dos\drive_cache.cpp +# End Source File +# Begin Source File + SOURCE=..\src\dos\drive_local.cpp # End Source File # Begin Source File @@ -219,6 +222,22 @@ SOURCE=..\src\dos\drives.h # End Group # Begin Source File +SOURCE=..\src\dos\cdrom.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\cdrom.h +# End Source File +# Begin Source File + +SOURCE=..\src\dos\cdrom_aspi_win32.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\dos\cdrom_ioctl_win32.cpp +# End Source File +# Begin Source File + SOURCE=..\src\dos\dos.cpp # End Source File # Begin Source File @@ -251,18 +270,38 @@ SOURCE=..\src\dos\dos_misc.cpp # End Source File # Begin Source File +SOURCE=..\src\dos\dos_mscdex.cpp +# End Source File +# Begin Source File + SOURCE=..\src\dos\dos_programs.cpp # End Source File # Begin Source File SOURCE=..\src\dos\dos_tables.cpp # End Source File +# Begin Source File + +SOURCE=..\src\dos\scsidefs.h +# End Source File +# Begin Source File + +SOURCE=..\src\dos\wnaspi32.h +# End Source File # End Group # Begin Group "gui" # PROP Default_Filter "" # Begin Source File +SOURCE=..\src\gui\midi.cpp +# End Source File +# Begin Source File + +SOURCE=..\src\gui\midi_win32.h +# End Source File +# Begin Source File + SOURCE=..\src\gui\render.cpp # End Source File # Begin Source File @@ -271,7 +310,11 @@ SOURCE=..\include\render.h # End Source File # Begin Source File -SOURCE=..\src\gui\render_support.h +SOURCE=..\src\gui\render_normal.h +# End Source File +# Begin Source File + +SOURCE=..\src\gui\render_scale2x.h # End Source File # Begin Source File @@ -383,6 +426,10 @@ SOURCE=..\src\hardware\mixer.cpp # End Source File # Begin Source File +SOURCE=..\src\hardware\mpu401.cpp +# End Source File +# Begin Source File + SOURCE=..\src\hardware\pcspeaker.cpp # End Source File # Begin Source File @@ -636,10 +683,6 @@ SOURCE=..\include\regs.h # End Source File # Begin Source File -SOURCE=..\settings.h -# End Source File -# Begin Source File - SOURCE=..\include\setup.h # End Source File # Begin Source File