DOSBox 0.58

This commit is contained in:
Carl.Kenner 2009-05-02 21:35:44 +00:00
parent 0e247f1518
commit d82f029c50
150 changed files with 13398 additions and 2824 deletions

View File

@ -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

13
INSTALL
View File

@ -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.

View File

@ -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

View File

@ -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

22
NEWS
View File

@ -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

155
README
View File

@ -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 <type> specifies the media: Where <type> 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 <Linux Version only>
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:
=================================

3
THANKS
View File

@ -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.

View File

@ -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 <richard-alsa@tartarus.org>
dnl Christopher Lansdown <lansdoct@cs.alfred.edu>
dnl Jaroslav Kysela <perex@suse.cz>
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 <alsa/asoundlib.h>
], [
/* 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
])

177
aclocal.m4 vendored
View File

@ -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 <richard-alsa@tartarus.org>
dnl Christopher Lansdown <lansdoct@cs.alfred.edu>
dnl Jaroslav Kysela <perex@suse.cz>
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 <alsa/asoundlib.h>
], [
/* 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

View File

@ -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"

View File

@ -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 <inttypes.h> 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 <memory.h> header file. */
#undef HAVE_MEMORY_H
@ -53,6 +62,9 @@
/* Define to 1 if you have the <unistd.h> 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

148
config.sub vendored
View File

@ -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*)

1796
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -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
])

215
depcomp
View File

@ -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"

8
docs/Makefile.am Normal file
View File

@ -0,0 +1,8 @@
# Main Makefile for DOSBox
man_MANS = dosbox.1
EXTRA_DIST = $(man_MANS)

262
docs/Makefile.in Normal file
View File

@ -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:

60
docs/dosbox.1 Normal file
View File

@ -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 <H.P.Veenstra@student.rug.nl> and James Oakley <jfunk@funktronics.ca>,
for the Debian system (but may be used by others).

View File

@ -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"

View File

@ -50,7 +50,5 @@
#define ftruncate(blah,blah2) chsize(blah,blah2)
#endif
extern const char * dosbox_datadir;
#endif

View File

@ -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);

View File

@ -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);
}

View File

@ -19,7 +19,10 @@
#ifndef DOSSYSTEM_H_
#define DOSSYSTEM_H_
#include <string.h>
#include <vector>
#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.size(); i++) delete fileList[i];
fileList.clear();
longNameList.clear();
outputList.clear();
};
char orgname [CROSS_LEN];
char shortname [DOS_NAMELENGTH_ASCII];
bool isDir;
Bitu nextEntry;
Bitu shortNr;
Bitu compareCount;
// contents
std::vector<CFileInfo*> fileList;
std::vector<CFileInfo*> longNameList;
std::vector<CFileInfo*> 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 };

View File

@ -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 <stddef.h>
#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 <class type1>
inline void LOG_MSG(char* message,type1 arg1)
{
if(errorlevel>=0) S_Warn(message,arg1);
}
template <class type1,class type2>
inline void LOG_MSG(char* message,type1 arg1,type2 arg2)
{
if(errorlevel>=0) S_Warn(message,arg1,arg2);
}
template <class type1,class type2, class type3>
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 <class type>
inline void LOG_DEBUG(char * message, type type1)
{
if(errorlevel>=2) S_Warn(message,type1);
}
template <class type>
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 <class type>
inline void LOG_ERROR(char * message, type type1)
{
if(errorlevel>=0) S_Warn(message,type1);
}
template <class type1, class type2>
inline void LOG_ERROR(char * message, type1 arg1,type2 arg2)
{
if(errorlevel>=0) S_Warn(message,arg1,arg2);
}
template <class type1, class type2>
inline void LOG_WARN(char * message, type1 arg1,type2 arg2)
{
if(errorlevel>=1) S_Warn(message,arg1,arg2);
}
template <class type1, class type2>
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 */

View File

@ -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);
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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -179,7 +179,8 @@ public:
void StartUp();
void PrintConfig(const char* configfilename);
void ParseConfigFile(const char* configfilename);
void ParseEnv(char ** envp);
std::list<Section*> sectionlist;
typedef std::list<Section*>::iterator it;
typedef std::list<Section*>::reverse_iterator reverse_it;

View File

@ -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

View File

@ -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

10
missing
View File

@ -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 <pinard@iro.umontreal.ca>, 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

View File

@ -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=""

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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
libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h slow_16.cpp instructions.h

View File

@ -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"

View File

@ -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
}

View File

@ -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

View File

@ -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"

View File

@ -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);

View File

@ -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 */
{

View File

@ -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) */

View File

@ -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 */

View File

@ -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(); }

View File

@ -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");;

View File

@ -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;
}

View File

@ -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;

View File

@ -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"

View File

@ -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 <termios.h>
#include <unistd.h>
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<CDebugVar*> varList;
};
std::list<CDebugVar*> 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;c++) wprintw(dbg.win_code,"%02X",mem_readb(start+c));
for (c=20;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<CDebugVar*>::iterator i;
CDebugVar* bp;
for(i=varList.begin(); i != varList.end(); i++) {
bp = static_cast<CDebugVar*>(*i);
delete bp;
};
(varList.clear)();
};
CDebugVar* CDebugVar::FindVar(PhysPt pt)
{
std::list<CDebugVar*>::iterator i;
CDebugVar* bp;
for(i=varList.begin(); i != varList.end(); i++) {
bp = static_cast<CDebugVar*>(*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<CDebugVar*>::iterator i;
CDebugVar* bp;
for(i=varList.begin(); i != varList.end(); i++) {
bp = static_cast<CDebugVar*>(*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; i<num; i++) {
char name[16];
// name
fread(name,1,16,f);
// adr
PhysPt adr;
fread(&adr,1,sizeof(adr),f);
// insert
InsertVariable(name,adr);
};
fclose(f);
return true;
};
void SaveMemory(Bit16u seg, Bit16u ofs1, Bit32s num)
{
FILE* f = fopen("MEMDUMP.TXT","wt");
if (!f) {
DEBUG_ShowMsg(0,"DEBUG: Memory dump failed.");
return;
}
char buffer[128];
char temp[16];
while(num>0) {
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

View File

@ -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

View File

@ -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 <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <curses.h>
#include <string.h>
#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<Section_prop *>(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;i<LOG_MAX;i++) {
strcpy(buf,loggrp[i].front);
buf[strlen(buf)-1]=0;
loggrp[i].enabled=sect->Get_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;i<LOG_MAX;i++) {
strcpy(buf,loggrp[i].front);
buf[strlen(buf)-1]=0;
lowcase(buf);
sect->Add_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

View File

@ -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);

View File

@ -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

View File

@ -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"

548
src/dos/Ntddcdrm.h Normal file
View File

@ -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

313
src/dos/Ntddscsi.h Normal file
View File

@ -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 <ntddscsi.h> in precompiled header
// #include <initguid.h> in a single source file
// #include <ntddscsi.h> 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

746
src/dos/Ntddstor.h Normal file
View File

@ -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 <ntddstor.h> in precompiled header
// #include <initguid.h> in a single source file
// #include <ntddstor.h> 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

229
src/dos/cdrom.cpp Normal file
View File

@ -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) && (forceCD<num)) {
driveID = forceCD;
return true;
};
const char* cdname = 0;
for (int i=0; i<num; i++) {
cdname = SDL_CDName(i);
if (strcmp(buffer,cdname)==0) {
cd = SDL_CDOpen(i);
SDL_CDStatus(cd);
driveID = i;
return true;
};
};
return false;
};
bool CDROM_Interface_SDL::GetAudioTracks (int& stTrack, int& end, TMSF& leadOut)
{
SDL_CDStatus(cd);
if (CD_INDRIVE(cd->status)) {
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) && (forceCD<num)) {
LOG(LOG_ERROR,"CDROM: Using drive %d",forceCD);
return 0;
}
// compare names
for (int i=0; i<num; i++) {
cdName = SDL_CDName(i);
if (strcmp(buffer,cdName)==0) return 0;
};
// TODO: Detect ISO
return 2;
};
// ******************************************************
// Fake CDROM
// ******************************************************
bool CDROM_Interface_Fake :: GetAudioTracks (int& stTrack, int& end, TMSF& leadOut)
{
stTrack = end = 1;
leadOut.min = 60;
leadOut.sec = leadOut.fr = 0;
return true;
};
bool CDROM_Interface_Fake :: GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr)
{
if (track>1) 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;
};

183
src/dos/cdrom.h Normal file
View File

@ -0,0 +1,183 @@
#ifndef __CDROM_INTERFACE__
#define __CDROM_INTERFACE__
#define MAX_ASPI_CDROM 5
#include <string.h>
#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 <windows.h>
#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__ */

View File

@ -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 <ctype.h>
#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; i<cnt; i++) {
memset(&sh, 0, sizeof(sh));
sh.SRB_Cmd = SC_HA_INQUIRY;
sh.SRB_HaId = i;
pSendASPI32Command((LPSRB)&sh);
if (sh.SRB_Status!=SS_COMP) continue;
// Indicates the maximum number of targets the adapter supports
// If the value is not 8 or 16, then it should be assumed max target is 8
max = (int)sh.HA_Unique[3];
if ((max!=8) && (max!=16)) max = 8;
for(j=0; j<max; j++) {
for(k=0; k<8; k++) {
memset(&sd, 0, sizeof(sd));
sd.SRB_Cmd = SC_GET_DEV_TYPE;
sd.SRB_HaId = i;
sd.SRB_Target = j;
sd.SRB_Lun = k;
pSendASPI32Command((LPSRB)&sd);
if (sd.SRB_Status == SS_COMP) {
if (sd.SRB_DeviceType == DTYPE_CDROM) {
if ((target==j) && (lun==k)) {
LOG(LOG_MISC,"SCSI: Getting Hardware vendor.");
// "Hardware ID = vendor" match ?
char vendor[64];
if (GetVendor(i,target,lun,vendor)) {
LOG(LOG_MISC,"SCSI: Vendor : %s",vendor);
if (strstr(strupr(hardwareID),strupr(vendor))) {
LOG(LOG_MISC,"SCSI: Host Adapter found: %d",i);
return i;
}
};
}
}
}
}
}
}
LOG(LOG_ERROR,"SCSI: Host Adapter not found: %d",i);
return 0;
};
bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase)
// hKey has to be open
{
FILETIME time;
ULONG result,newKeyResult;
char subKey[256];
char buffer[256];
ULONG bufferSize = 256;
ULONG subKeySize = 256;
HKEY hNewKey;
ULONG index = 0;
do {
result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
if (result==ERROR_SUCCESS) {
// Open Key...
newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
if (newKeyResult==ERROR_SUCCESS) {
if (GetRegistryValue(hNewKey,"CurrentDriveLetterAssignment",buffer,256)) {
LOG(LOG_MISC,"SCSI: Drive Letter found: %s",buffer);
// aha, something suspicious...
if (buffer[0]==letter) {
char hardwareID[256];
// found it... lets see if we can get the scsi values
bool v1 = GetRegistryValue(hNewKey,"SCSILUN",buffer,256);
LOG(LOG_MISC,"SCSI: SCSILUN found: %s",buffer);
lun = buffer[0]-'0';
bool v2 = GetRegistryValue(hNewKey,"SCSITargetID",buffer,256);
LOG(LOG_MISC,"SCSI: SCSITargetID found: %s",buffer);
target = buffer[0]-'0';
bool v3 = GetRegistryValue(hNewKey,"HardwareID",hardwareID,256);
RegCloseKey(hNewKey);
if (v1 && v2 && v3) {
haId = GetHostAdapter(hardwareID);
return true;
};
}
};
};
RegCloseKey(hNewKey);
};
index++;
} while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
return false;
};
bool CDROM_Interface_Aspi::GetVendor(BYTE HA_num, BYTE SCSI_Id, BYTE SCSI_Lun, char* szBuffer)
{
SRB_ExecSCSICmd srbExec;
memset ( &srbExec, 0, sizeof ( SRB_ExecSCSICmd ) );
hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
srbExec.SRB_Cmd = SC_EXEC_SCSI_CMD ;
srbExec.SRB_HaId = HA_num;
srbExec.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
srbExec.SRB_Target = SCSI_Id;
srbExec.SRB_Lun = SCSI_Lun;
srbExec.SRB_BufLen = 36;
srbExec.SRB_BufPointer = (unsigned char*)szBuffer;
srbExec.SRB_SenseLen = SENSE_LEN;
srbExec.SRB_CDBLen = 6;
srbExec.SRB_PostProc = (LPVOID)hEvent;
srbExec.CDBByte [ 0 ] = SCSI_INQUIRY;
srbExec.CDBByte [ 4 ] = 36; // allocation length per szBuffer [ ]
ResetEvent(hEvent);
int dwStatus = pSendASPI32Command ((LPSRB)&srbExec);
// LOG(LOG_MISC|LOG_ERROR,"SCSI: Get vendor command send");
if (dwStatus==SS_PENDING) WaitForSingleObject(hEvent,30000);
// LOG(LOG_MISC|LOG_ERROR,"SCSI: Pending done.");
CloseHandle(hEvent);
if (srbExec.SRB_Status != SS_COMP) {
strcpy (szBuffer, "error" );
return false;
} else {
strncpy(szBuffer,szBuffer+8,25);
szBuffer[25] = 0;
int len = strlen(szBuffer);
for (int i=0; i<len; i++) if (szBuffer[i]<=32) szBuffer[i]='_';
};
return true;
}
bool CDROM_Interface_Aspi::ScanRegistry(HKEY& hKeyBase)
// hKey has to be open
{
FILETIME time;
ULONG result,newKeyResult;
char subKey[256];
ULONG subKeySize= 256;
HKEY hNewKey;
ULONG index = 0;
do {
result = RegEnumKeyEx (hKeyBase,index,&subKey[0],&subKeySize,NULL,NULL,0,&time);
if ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA)) {
// Open Key...
newKeyResult = RegOpenKeyEx (hKeyBase,subKey,0,KEY_READ,&hNewKey);
if (newKeyResult==ERROR_SUCCESS) {
bool found = ScanRegistryFindKey(hNewKey);
RegCloseKey(hNewKey);
if (found) return true;
};
RegCloseKey(hNewKey);
};
index++;
} while ((result==ERROR_SUCCESS) || (result==ERROR_MORE_DATA));
return false;
};
bool CDROM_Interface_Aspi::SetDevice(char* path, int forceCD)
{
// load WNASPI32.DLL
hASPI = LoadLibrary ( "WNASPI32.DLL" );
if (!hASPI) return false;
// Get Pointer to ASPI funcs
pGetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress(hASPI,"GetASPI32SupportInfo");
pSendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress(hASPI,"SendASPI32Command");
if (!pGetASPI32SupportInfo || !pSendASPI32Command) return false;
// Letter
letter = toupper(path[0]);
// Check OS
OSVERSIONINFO osi;
osi.dwOSVersionInfoSize = sizeof(osi);
GetVersionEx(&osi);
if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) {
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 *)&sub;
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<num; i++) {
memcpy(outPtr,source,2048);
outPtr+=COOKED_SECTOR_SIZE;
source+=RAW_SECTOR_SIZE;
};
delete[] inPtr;
};
return true;
};
#endif

View File

@ -0,0 +1,275 @@
/*
* 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)
// *****************************************************************
// Windows IOCTL functions (not suitable for 95/98/Me)
// *****************************************************************
#include <windows.h>
#include <winioctl.h> // 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; i<num; i++) {
memcpy(outPtr,source,COOKED_SECTOR_SIZE);
outPtr+=COOKED_SECTOR_SIZE;
source+=RAW_SECTOR_SIZE;
};
delete[] inPtr;
};
return (byteCount!=num*RAW_SECTOR_SIZE) && (bStat>0);
}
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

View File

@ -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;
}

View File

@ -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,&para)) 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;i<DOS_DRIVES;i++) delete Drives[i];
};
void DOS_Init(Section* sec) {
MSG_Add("DOS_CONFIGFILE_HELP","Setting a memory size to 0 will disable it.\n");
call_20=CALLBACK_Allocate();
@ -867,6 +934,14 @@ void DOS_Init(Section* sec) {
CALLBACK_Setup(call_21,DOS_21Handler,CB_IRET_STI);
RealSetVec(0x21,CALLBACK_RealPointer(call_21));
call_25=CALLBACK_Allocate();
CALLBACK_Setup(call_25,DOS_25Handler,CB_RETF);
RealSetVec(0x25,CALLBACK_RealPointer(call_25));
call_26=CALLBACK_Allocate();
CALLBACK_Setup(call_26,DOS_26Handler,CB_RETF);
RealSetVec(0x26,CALLBACK_RealPointer(call_26));
call_27=CALLBACK_Allocate();
CALLBACK_Setup(call_27,DOS_27Handler,CB_IRET);
RealSetVec(0x27,CALLBACK_RealPointer(call_27));
@ -889,6 +964,7 @@ void DOS_Init(Section* sec) {
dos.version.major=5;
dos.version.minor=0;
/* Setup time and date */
time_t curtime;struct tm *loctime;
curtime = time (NULL);loctime = localtime (&curtime);
@ -898,4 +974,12 @@ void DOS_Init(Section* sec) {
dos.date.year=(Bit16u)loctime->tm_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);
}

View File

@ -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;i<sGet(sPSP,max_files);i++) {
if (mem_readb(files+i)==handle) return i;
}
return 0xFF;
};
void DOS_PSP::CopyFileTable(DOS_PSP* srcpsp)
{
/* Copy file table from calling process */
@ -197,6 +207,23 @@ void DOS_PSP::SetFCB2(RealPt src)
if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb2)),Real2Phys(src),16);
};
bool DOS_PSP::SetNumFiles(Bit16u fileNum)
{
if (fileNum>20) {
// 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<fileNum; i++) SetFileHandle(i,0xFF);
} else {
sSave(sPSP,max_files,fileNum);
};
return true;
};
void DOS_DTA::SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * pattern) {
sSave(sDTA,sdrive,_sdrive);
@ -289,7 +316,8 @@ void DOS_FCB::SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time) {
void DOS_FCB::GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time) {
_size=sGet(sFCB,filesize);
_date=sGet(sFCB,date);
_time=sGet(sFCB,time);
}
void DOS_FCB::GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec) {
@ -349,15 +377,3 @@ void DOS_FCB::GetName(char * fillname) {
fillname[14]=0;
}
class DOS_MCB : public MemStruct{
public:
DOS_MCB(Bit16u seg) { SetPt(seg); }
private:
struct sMCB {
Bit8u type;
Bit16u psp_segment;
Bit16u size;
Bit8u unused[3];
Bit8u filename[8];
} GCC_ATTRIBUTE(packed);
};

View File

@ -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
@ -137,6 +137,9 @@ static bool MakeEnv(char * name,Bit16u * segment) {
}
if (parentenv) {
// hack to allow creation from envblock in unused mem (0xCD)
if (readw(envread)==0xCDCD) writew(envread,0x0000);
for (envsize=0; ;envsize++) {
if (envsize>=MAXENV - ENV_KEEPFREE) {
DOS_SetError(DOSERR_ENVIRONMENT_INVALID);
@ -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 */

View File

@ -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 <ctype.h>
#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;i<DOS_FILES;i++) {
if (!Files[i]) {
@ -641,6 +644,27 @@ bool DOS_FCBOpen(Bit16u seg,Bit16u offset) {
DOS_FCB fcb(seg,offset);
char shortname[DOS_FCBNAME];Bit16u handle;
fcb.GetName(shortname);
/* First check if the name is correct */
Bit8u drive;
char fullname[DOS_PATHLENGTH];
if (!DOS_MakeName(shortname,fullname,&drive)) return false;
/* Check, if file is already opened */
for (Bit16u i=0;i<DOS_FILES;i++) {
DOS_PSP psp(dos.psp);
if (Files[i] && Files[i]->IsOpen() && 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);

View File

@ -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;

View File

@ -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 (bigsize<pmcb->size) {
bigsize=pmcb->size;
Bit16u block_size=mcb.GetSize();
if (block_size<(*blocks)) {
if (bigsize<block_size) {
bigsize=block_size;
}
} else if (pmcb->size==*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 (*blocks<total) {
if (pmcb->type!=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);
}

View File

@ -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;
};

844
src/dos/dos_mscdex.cpp Normal file
View File

@ -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 <string.h>
#include <ctype.h>
#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; i<MSCDEX_MAX_DRIVES; i++) cdrom[i] = 0;
};
CMscdex::~CMscdex(void)
{
for (Bit16u i=0; i<GetNumDrives(); i++) {
delete (cdrom)[i];
cdrom[i] = 0;
};
};
void CMscdex::GetDrives(PhysPt data)
{
for (Bit16u i=0; i<GetNumDrives(); i++) mem_writeb(data+i,dinfo[i].drive);
};
bool CMscdex::IsValidDrive(Bit16u _drive)
{
for (Bit16u i=0; i<GetNumDrives(); i++) if (dinfo[i].drive==_drive) return true;
return false;
};
Bit8u CMscdex::GetSubUnit(Bit16u _drive)
{
for (Bit16u i=0; i<GetNumDrives(); i++) if (dinfo[i].drive==_drive) return (Bit8u)i;
return 0xff;
};
int CMscdex::AddDrive(Bit16u _drive, char* physicalPath, Bit8u& subUnit)
{
subUnit = 0;
if (GetNumDrives()==0) {
Bit16u driverSize = sizeof(DOS_DeviceHeader::sDeviceHeader) + 10; // 10 = Bytes for 3 callbacks
// Create Device Header
Bit16u seg = DOS_GetMemory(driverSize/16+((driverSize%16)>0));
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()+1<MSCDEX_MAX_DRIVES) {
// Set return type to ok
int result = 0;
// Get Mounttype and init needed cdrom interface
switch (CDROM_GetMountType(physicalPath,forceCD)) {
case 0x00 : {
LOG(LOG_MISC,"MSCDEX: Mounting physical cdrom: %s" ,physicalPath);
#if defined (WIN32)
// Check OS
OSVERSIONINFO osi;
osi.dwOSVersionInfoSize = sizeof(osi);
GetVersionEx(&osi);
if ((osi.dwPlatformId==VER_PLATFORM_WIN32_NT) && (osi.dwMajorVersion>4)) {
// WIN NT/200/XP
if (useCdromInterface==CDROM_USE_ASPI) {
cdrom[numDrives] = new CDROM_Interface_Aspi();
LOG(LOG_MISC,"MSCDEX: ASPI Interface.");
break;
} else if (useCdromInterface==CDROM_USE_IOCTL) {
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; i<GetNumDrives(); i++) {
mem_writeb(data ,0x00);
mem_writed(data+1,RealMake(rootDriverHeaderSeg,0));
data+=5;
};
};
bool CMscdex::GetCDInfo(Bit8u subUnit, Bit8u& tr1, Bit8u& tr2, TMSF& leadOut)
{
int tr1i,tr2i;
dinfo[subUnit].lastResult = cdrom[subUnit]->GetAudioTracks(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 (subUnit<MSCDEX_MAX_DRIVES) {
leadOut[subUnit].min = 0;
leadOut[subUnit].sec = 0;
leadOut[subUnit].fr = 0;
}
return true;
};
void MSCDEX_SetCDInterface(int intNr, int numCD)
{
useCdromInterface = intNr;
forceCD = numCD;
};
void MSCDEX_ShutDown(Section* sec)
{
delete mscdex; mscdex = 0;
};
void MSCDEX_Init(Section* sec)
{
// AddDestroy func
sec->AddDestroyFunction(&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;
};

View File

@ -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; i<num; i++) {
WriteOut("%2d. %s\n",i,SDL_CDName(i));
};
return;
}
/* Parse the command line */
/* if the command line is empty show current mounts */
if (!cmd->GetCount()) {
@ -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);
}

635
src/dos/drive_cache.cpp Normal file
View File

@ -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 <vector>
#include <iterator>
#include <algorithm>
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<MAX_OPENDIRS; i++) { dirSearch[i] = 0; free[i] = true; };
SetDirSort(DIRALPHABETICAL);
};
DOS_Drive_Cache::DOS_Drive_Cache(const char* path)
{
dirBase = new CFileInfo;
save_dir = 0;
srchNr = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) { dirSearch[i] = 0; free[i] = true; };
SetDirSort(DIRALPHABETICAL);
SetBaseDir(path);
};
DOS_Drive_Cache::~DOS_Drive_Cache(void)
{
Clear();
};
void DOS_Drive_Cache::Clear(void)
{
delete dirBase; dirBase = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) dirSearch[i] = 0;
};
void DOS_Drive_Cache::EmptyCache(void)
{
// Empty Cache and reinit
Clear();
dirBase = new CFileInfo;
save_dir = 0;
srchNr = 0;
for (Bit32u i=0; i<MAX_OPENDIRS; i++) free[i] = true;
SetBaseDir(basePath);
};
Bit16u DOS_Drive_Cache::GetFreeID(CFileInfo* dir)
{
for (Bit32u i=0; i<MAX_OPENDIRS; i++) if (free[i] || (dir==dirSearch[i])) return i;
LOG(LOG_FILES,"DIRCACHE: Too many open directories!");
return 0;
};
void DOS_Drive_Cache::SetBaseDir(const char* baseDir)
{
Bit16u id;
strcpy(basePath,baseDir);
if (OpenDir(baseDir,id)) {
char * result;
ReadDir(id,result);
};
};
void DOS_Drive_Cache::ExpandName(char* path)
{
strcpy(path,GetExpandName(path));
};
char* DOS_Drive_Cache::GetExpandName(const char* path)
{
static char work [CROSS_LEN];
char dir [CROSS_LEN];
work[0] = 0;
strcpy (dir,path);
char* pos = strrchr(path,CROSS_FILESPLIT);
if (pos) dir[pos-path+1] = 0;
CFileInfo* dirInfo = FindDirInfo(dir, work);
if (pos) {
// Last Entry = File
strcpy(dir,pos+1);
GetLongName(dirInfo, dir);
strcat(work,dir);
}
return work;
};
void DOS_Drive_Cache::AddEntry(const char* path, bool checkExists)
{
// Get Last part...
char file [CROSS_LEN];
char expand [CROSS_LEN];
CFileInfo* dir = FindDirInfo(path,expand);
char* pos = strrchr(path,CROSS_FILESPLIT);
if (pos) {
strcpy(file,pos+1);
// Check if file already exists, then dont add new entry...
if (checkExists && (GetLongName(dir,file)>=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; i<MAX_OPENDIRS; i++) {
if ((dirSearch[i]==dir) && (index<=dirSearch[i]->nextEntry))
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; i<MAX_OPENDIRS; i++) {
if ((dirSearch[i]==dir) && (dirSearch[i]->nextEntry>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; i<dir->fileList.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(mid<curDir->longNameList.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;
};

View File

@ -21,6 +21,7 @@
#include <string.h>
#include <time.h>
#include <errno.h>
#include <dirent.h>
#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)<DOS_NAMELENGTH_ASCII){
strcpy(find_name,dir_ent->d_name);
if(strlen(dir_ent)<DOS_NAMELENGTH_ASCII){
strcpy(find_name,dir_ent);
upcase(find_name);
} else strcpy(find_name,"LONGNAME.ERR");
}
find_size=(Bit32u) stat_block.st_size;
struct tm *time;
if((time=localtime(&stat_block.st_mtime))!=0){
@ -150,9 +174,10 @@ bool localDrive::GetFileAttr(char * name,Bit16u * attr) {
strcpy(newname,basedir);
strcat(newname,name);
CROSS_FILENAME(newname);
FILE * hand=fopen(newname,"rb");
if (hand) {
fclose(hand);
dirCache.ExpandName(newname);
struct stat status;
if (stat(newname,&status)==0) {
*attr=DOS_ATTR_ARCHIVE;
return true;
}
@ -166,10 +191,11 @@ bool localDrive::MakeDir(char * dir) {
strcat(newdir,dir);
CROSS_FILENAME(newdir);
#if defined (WIN32) /* MS Visual C++ */
int temp=mkdir(newdir);
int temp=mkdir(dirCache.GetExpandName(newdir));
#else
int temp=mkdir(newdir,0700);
int temp=mkdir(dirCache.GetExpandName(newdir),0700);
#endif
if (temp==0) dirCache.CacheOut(newdir,true);
// if dir already exists, return success too.
return (temp==0) || ((temp!=0) && (errno==EEXIST));
}
@ -179,7 +205,8 @@ bool localDrive::RemoveDir(char * dir) {
strcpy(newdir,basedir);
strcat(newdir,dir);
CROSS_FILENAME(newdir);
int temp=rmdir(newdir);
int temp=rmdir(dirCache.GetExpandName(newdir));
if (temp==0) dirCache.DeleteEntry(newdir,true);
return (temp==0);
}
@ -188,6 +215,7 @@ bool localDrive::TestDir(char * dir) {
strcpy(newdir,basedir);
strcat(newdir,dir);
CROSS_FILENAME(newdir);
dirCache.ExpandName(newdir);
// Skip directory test, if "\"
Bit16u len = strlen(newdir);
if ((len>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);
};

View File

@ -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;
}

View File

@ -20,34 +20,35 @@
#define _DRIVES_H__
#include <sys/types.h>
#include <dirent.h>
#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

579
src/dos/scsidefs.h Normal file
View File

@ -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;

354
src/dos/wnaspi32.h Normal file
View File

@ -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__

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

180
src/gui/midi.cpp Normal file
View File

@ -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 <assert.h>
#include <string.h>
#include <stdlib.h>
#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<Section_prop *>(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;
}

92
src/gui/midi_coreaudio.h Normal file
View File

@ -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 <AudioUnit/AudioUnit.h>
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;

76
src/gui/midi_oss.h Normal file
View File

@ -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 <fcntl.h>
#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;

73
src/gui/midi_win32.h Normal file
View File

@ -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 <windows.h>
#include <mmsystem.h>
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;

View File

@ -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 <png.h>
#include <sys/types.h>
#include <dirent.h>
#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 <png.h>
/* 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<render.src.height;i++) {
row_pointers[i]=(bitmap+i*render.src.pitch);
row_pointers[i]=(bitmap+i*render.src.width);
}
/*tell the png library what to encode.*/
png_set_rows(png_ptr, info_ptr, row_pointers);
@ -177,8 +186,15 @@ static void TakeScreenShot(Bit8u * bitmap) {
/*clean up dynamically allocated RAM.*/
free(row_pointers);
LOG_MSG("Took snapshot in file %s",file_name);
}
static void EnableScreenShot(void) {
render.shot.type=render.op.type;
render.op.type=OP_Shot;
}
#endif
/* This could go kinda bad with multiple threads */
@ -224,36 +240,40 @@ void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue) {
if (render.pal.last<entry) render.pal.last=entry;
}
bool RENDER_StartUpdate(void) {
void RENDER_DoUpdate(void) {
if (render.frameskip.count<render.frameskip.max) {
render.frameskip.count++;
return false;
return;
}
render.frameskip.count=0;
if (render.src.bpp==8) Check_Palette();
switch (render.op.type) {
case OP_None:
render.op.dest=render.op.pixels=GFX_StartUpdate();
break;
}
if (render.op.dest) return true;
else return false;
GFX_DoUpdate();
}
void RENDER_EndUpdate(void) {
static void RENDER_DrawScreen(void * data) {
switch (render.op.type) {
doagain:
case OP_None:
/* Nothing to be done */
render.op.pixels=0;
render.op.dest=render.op.pixels=data;
render.src.draw_handler(render.op.part_handler);
break;
case OP_Scale2x:
render.op.dest=render.op.pixels=data;
render.src.draw_handler(render.op.part_handler);
break;
#if (C_SSHOT)
case OP_Shot:
render.shot.pitch=render.op.pitch;
render.op.pitch=render.src.width;
render.op.pixels=malloc(render.src.width*render.src.height);
render.src.draw_handler(Normal_DN_8);
TakeScreenShot((Bit8u *)render.op.pixels);
free(render.op.pixels);
render.op.pitch=render.shot.pitch;
render.op.type=render.shot.type;
goto doagain;
#endif
}
GFX_EndUpdate();
}
/* Update the data ready to be sent out for blitting onto the screen */
void RENDER_Part(Bit8u * src,Bitu x,Bitu y,Bitu dx,Bitu dy) {
(render.src.part_handler)(src,x,y,dx,dy);
return;
}
static void RENDER_Resize(Bitu * width,Bitu * height) {
@ -268,46 +288,71 @@ static void RENDER_Resize(Bitu * width,Bitu * height) {
}
}
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags) {
void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu flags,RENDER_Draw_Handler draw_handler) {
if ((!width) || (!height) || (!pitch)) {
render.active=false;return;
}
GFX_Stop();
render.src.width=width;
render.src.height=height;
render.src.bpp=bpp;
render.src.pitch=pitch;
render.src.ratio=ratio;
render.src.flags=flags;
render.src.draw_handler=draw_handler;
GFX_ModeCallBack callback;
GFX_ModeCallBack mode_callback=0;
switch (render.op.want_type) {
case OP_None:
normalop:
switch (render.src.flags) {
case DoubleNone:break;
case DoubleWidth:width*=2;break;
case DoubleHeight:height*=2;break;
case DoubleNone:
flags=0;
break;
case DoubleWidth:
width*=2;
flags=GFX_SHADOW;
break;
case DoubleHeight:
height*=2;
flags=0;
break;
case DoubleBoth:
if (render.keep_small) {
render.src.flags=0;
flags=0;
} else {
width*=2;height*=2;
flags=GFX_SHADOW;
}
break;
}
flags=0;
callback=Render_Normal_CallBack;
mode_callback=Render_Normal_CallBack;
break;
case OP_Scale2x:
switch (render.src.flags) {
case DoubleBoth:
if (render.keep_small) goto normalop;
mode_callback=Render_Scale2x_CallBack;
width*=2;height*=2;
#if defined (SCALE2X_NORMAL)
flags=GFX_SHADOW;
#elif defined (SCALE2X_MMX)
flags=GFX_FIXED_BPP;
#endif
break;
default:
goto normalop;
}
break;
default:
goto normalop;
}
GFX_SetSize(width,height,bpp,flags,callback);
}
static void EnableScreenShot(void) {
render.screenshot=true;
GFX_SetSize(width,height,bpp,flags,mode_callback,RENDER_DrawScreen);
GFX_Start();
}
static void IncreaseFrameSkip(void) {
@ -320,18 +365,32 @@ static void DecreaseFrameSkip(void) {
LOG_MSG("Frame Skip at %d",render.frameskip.max);
}
void RENDER_Init(Section * sec) {
MSG_Add("RENDER_CONFIGFILE_HELP","Available scalers: scale2x, none\n");
Section_prop * section=static_cast<Section_prop *>(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);
}

182
src/gui/render_normal.h Normal file
View File

@ -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();
}

562
src/gui/render_scale2x.h Normal file
View File

@ -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 <assert.h>
/***************************************************************************/
/* 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

View File

@ -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();
}

View File

@ -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 <string.h>
#include <stdio.h>
#include <SDL.h>
#include <unistd.h>
#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<Section_prop *>(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;
};

View File

@ -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

View File

@ -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"

View File

@ -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;
}
}

View File

@ -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 <string.h>
#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<Section_prop *>(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");

View File

@ -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 <string.h>
@ -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");

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