DOSDOSBox 0.56

This commit is contained in:
Carl.Kenner 2009-05-02 21:20:05 +00:00
parent 0284615f36
commit 44c0450545
96 changed files with 4950 additions and 3462 deletions

View File

@ -1,3 +1,25 @@
0.56
- added support for a configclass/configfile
- added support for writing out the configclass into a configfile
- removed the language file and made it internal
- added support for writing the language file (will override the internal one)
- improved mousesupport
- updated readme
- support for screenshots
- some cpu-bug fixes
- dma changes
- Real Sound support
- EMM fixes and new functions.
- VGA fixes
- new wildcompare
- support for size and disktype at mount.
- added new debugger functionalities: start/trace into INTs, write processor status log,
step over rep and loop instructions, breakpoint support without using INT 03 (heavy debugging switch)
- Added more cpu instructions and changed the string operations.
- Added classes for most of the internal dos structures.
- Rewrote most of the fcb calls to use normal dos calls.
0.55
- fixed the errors/warnings in prefix_66.h and prefix_66_of.h (decimal too large becomming unsigned). - fixed the errors/warnings in prefix_66.h and prefix_66_of.h (decimal too large becomming unsigned).
- fixed compilation error on FreeBSD when #disable_joystick was defined - fixed compilation error on FreeBSD when #disable_joystick was defined
- int10_writechar has been updated to move the cursor position. - int10_writechar has been updated to move the cursor position.

15
INSTALL
View File

@ -11,8 +11,17 @@ Curses
ncurses should be installed on just about every unix distro. ncurses should be installed on just about every unix distro.
For win32 get pdcurses at http://pdcurses.sourceforge.net For win32 get pdcurses at http://pdcurses.sourceforge.net
Libpng
Needed for the screenshots.
For win32 get libpng from http://www.sourceforge.net/projects/gnuwin32
Zlib
Needed by libpng.
For win32 get libz (rename to zlib) from http://www.sourceforge.net/projects/gnuwin32
If you want compile from the CVS under a unix system, you'll also need If you want compile from the CVS under a unix system, you'll also need
automake, autoconf. Should be available at http://www.gnu.org automake (>=1.6), autoconf(>=2.50). Should be available at http://www.gnu.org
For building on unix systems. For building on unix systems.
If you are building from the cvs run ./autogen.sh first before doing the following. If you are building from the cvs run ./autogen.sh first before doing the following.
@ -21,8 +30,7 @@ If you are building from the cvs run ./autogen.sh first before doing the followi
2. Check settings.h for some setup options. 2. Check settings.h for some setup options.
3. make 3. make
Check the src subdir for the binary and dosbox.lang file. Check the src subdir for the binary.
These 2 files should be in the same dir if you want to run dosbox.
Compiling on FreeBSD might be a problem since SDL has no joystick support there. Compiling on FreeBSD might be a problem since SDL has no joystick support there.
To get around this edit sdlmain.cpp to enable some #define. To get around this edit sdlmain.cpp to enable some #define.
@ -32,5 +40,4 @@ Let's hope someday the sdl people will just report 0 joysticks in freebsd or get
Build instructions for VC++6 Build instructions for VC++6
Open the workspace in the visualc subdir and build from there. Open the workspace in the visualc subdir and build from there.
Copy the src/dosbox.lang file to the same dir as your executable.

23
NEWS
View File

@ -1,3 +1,26 @@
0.56:
- added support for a configclass/configfile
- added support for writing out the configclass into a configfile
- removed the language file and made it internal
- added support for writing the language file (will override the internal one)
- improved mousesupport
- updated readme
- support for screenshots
- some cpu-bug fixes
- dma changes
- Real Sound support
- EMM fixes and new functions.
- VGA fixes
- new wildcompare
- support for size and disktype at mount.
- added new debugger functionalities: start/trace into INTs, write processor status log,
step over rep and loop instructions, breakpoint support without using INT 03 (heavy debugging switch)
- Added more cpu instructions and changed the string operations.
- Added classes for most of the internal dos structures.
- Rewrote most of the fcb calls to use normal dos calls.
0.55: 0.55:
- changed basedir handling. (linux/winXP) - changed basedir handling. (linux/winXP)
- added some FCB-calls - added some FCB-calls

47
README
View File

@ -1,10 +1,11 @@
DOSBox v0.55 DOSBox v0.56
Usage: Usage:
====== ======
With the new internal shell I've changed the command line a bit, so let's just give some 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. examples of what you can do now.
dosbox dosbox
With nothing on the command line you'll end up on the internal drive and from there you With nothing on the command line you'll end up on the internal drive and from there you
can mount directories as drives. can mount directories as drives.
@ -14,6 +15,13 @@ dosbox [filename/directory]
.bat .com .exe. Doesn't need to have extension included. Then it'll strip the directory .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. from the filename and mount that as c:\ and then run the file.
dosbox -fullscreen
starts dosbox in fullscreen mode.
dosbox -conf file
loads file as a configfile.
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 You can also add commands to be executed before the main program starts. Or you can use them
to start the program. to start the program.
To add commands use the -c command line switch. To add commands use the -c command line switch.
@ -30,22 +38,48 @@ Internal Programs:
MOUNT MOUNT
Program to mount local directories as drives inside DOSBox. 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
HWSET MEM
Utility to setup the emulated hardware running inside DOSBox, only working for emulated sound cards. Program to display the amount of free memory
CONFIG
Utility for generating a configfile with the current settings and for generating the languagefile.
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> UPCASE <Linux Version only>
Utility to convert all files subdirectories of a local directory into upcase so DOSBox can use that directory 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 mounting. This tool can be quite dangerous if used unproperly. You have been warned.
To get more information about how to use one these programs use the the /? command line switch. To get more information about how to use one these programs use the the /? command line switch.
The Configfile:
===============
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.
# 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:
=================
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.)
Special Keys: Special Keys:
============= =============
ALT-ENTER Go full screen and back. 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-F10 Capture/Release the mouse. CTRL-F10 Capture/Release the mouse.
CTRL-F11 Slowdown emulation. CTRL-F11 Slowdown emulation.
CTRL-F12 Speedup emulation. CTRL-F12 Speedup emulation.
@ -70,7 +104,10 @@ FAQ:
A: When you mouse touches the edges of the DOSBox screen you can click and drag it to A: When you mouse touches the edges of the DOSBox screen you can click and drag it to
the size you prefer. the size you prefer.
3. Check the site/forum. 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.
4. Check the site/forum.
Building your own Version DOSBox: Building your own Version DOSBox:
================================= =================================

View File

@ -26,6 +26,9 @@
/* Define to 1 if you have the <inttypes.h> header file. */ /* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H #undef HAVE_INTTYPES_H
/* Define to 1 if you have the `png' library (-lpng). */
#undef HAVE_LIBPNG
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H #undef HAVE_MEMORY_H

91
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.53a for dosbox 0.55. # Generated by GNU Autoconf 2.53a for dosbox 0.56.
# #
# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 # Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc. # Free Software Foundation, Inc.
@ -272,8 +272,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package. # Identity of this package.
PACKAGE_NAME='dosbox' PACKAGE_NAME='dosbox'
PACKAGE_TARNAME='dosbox' PACKAGE_TARNAME='dosbox'
PACKAGE_VERSION='0.55' PACKAGE_VERSION='0.56'
PACKAGE_STRING='dosbox 0.55' PACKAGE_STRING='dosbox 0.56'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
ac_unique_file="README" ac_unique_file="README"
@ -786,7 +786,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures dosbox 0.55 to adapt to many kinds of systems. \`configure' configures dosbox 0.56 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -853,7 +853,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of dosbox 0.55:";; short | recursive ) echo "Configuration of dosbox 0.56:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -946,7 +946,7 @@ fi
test -n "$ac_init_help" && exit 0 test -n "$ac_init_help" && exit 0
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
dosbox configure 0.55 dosbox configure 0.56
generated by GNU Autoconf 2.53a generated by GNU Autoconf 2.53a
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
@ -961,7 +961,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by dosbox $as_me 0.55, which was It was created by dosbox $as_me 0.56, which was
generated by GNU Autoconf 2.53a. Invocation command line was generated by GNU Autoconf 2.53a. Invocation command line was
$ $0 $@ $ $0 $@
@ -1579,7 +1579,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE=dosbox PACKAGE=dosbox
VERSION=0.55 VERSION=0.56
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -1712,7 +1712,6 @@ INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5 echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \${MAKE}" >&5
echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6 echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
@ -4232,6 +4231,76 @@ _ACEOF
fi fi
echo "$as_me:$LINENO: checking for png_check_sig in -lpng" >&5
echo $ECHO_N "checking for png_check_sig in -lpng... $ECHO_C" >&6
if test "${ac_cv_lib_png_png_check_sig+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpng -lz $LIBS"
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char png_check_sig ();
#ifdef F77_DUMMY_MAIN
# ifdef __cplusplus
extern "C"
# endif
int F77_DUMMY_MAIN() { return 1; }
#endif
int
main ()
{
png_check_sig ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_lib_png_png_check_sig=yes
else
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
ac_cv_lib_png_png_check_sig=no
fi
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_check_sig" >&5
echo "${ECHO_T}$ac_cv_lib_png_png_check_sig" >&6
if test $ac_cv_lib_png_png_check_sig = yes; then
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBPNG 1
_ACEOF
LIBS="-lpng $LIBS"
else
{ { echo "$as_me:$LINENO: error: *** libpng not found!" >&5
echo "$as_me: error: *** libpng not found!" >&2;}
{ (exit 1); exit 1; }; }
fi
#Check if the compiler support attributes #Check if the compiler support attributes
echo "$as_me:$LINENO: checking if compiler allows __attribute__" >&5 echo "$as_me:$LINENO: checking if compiler allows __attribute__" >&5
echo $ECHO_N "checking if compiler allows __attribute__... $ECHO_C" >&6 echo $ECHO_N "checking if compiler allows __attribute__... $ECHO_C" >&6
@ -4637,7 +4706,7 @@ _ASBOX
} >&5 } >&5
cat >&5 <<_CSEOF cat >&5 <<_CSEOF
This file was extended by dosbox $as_me 0.55, which was This file was extended by dosbox $as_me 0.56, which was
generated by GNU Autoconf 2.53a. Invocation command line was generated by GNU Autoconf 2.53a. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -4699,7 +4768,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\ ac_cs_version="\\
dosbox config.status 0.55 dosbox config.status 0.56
configured by $0, generated by GNU Autoconf 2.53a, configured by $0, generated by GNU Autoconf 2.53a,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"

View File

@ -1,5 +1,5 @@
dnl Init. dnl Init.
AC_INIT(dosbox,0.55) AC_INIT(dosbox,0.56)
AC_CONFIG_SRCDIR(README) AC_CONFIG_SRCDIR(README)
dnl Detect the canonical host and target build environment dnl Detect the canonical host and target build environment
@ -10,7 +10,6 @@ dnl Setup for automake
AM_INIT_AUTOMAKE AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
dnl Checks for programs. dnl Checks for programs.
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
AC_PROG_CC AC_PROG_CC
@ -36,6 +35,9 @@ AC_C_INLINE
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
AC_STRUCT_TM 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 #Check if the compiler support attributes
AC_MSG_CHECKING(if compiler allows __attribute__) AC_MSG_CHECKING(if compiler allows __attribute__)
AC_TRY_COMPILE([], [typedef struct { } __attribute__ ((packed)) junk;], AC_TRY_COMPILE([], [typedef struct { } __attribute__ ((packed)) junk;],

View File

@ -84,6 +84,11 @@
#define BIOS_KEYBOARD_FLAGS3 0x496 #define BIOS_KEYBOARD_FLAGS3 0x496
#define BIOS_KEYBOARD_LEDS 0x497 #define BIOS_KEYBOARD_LEDS 0x497
#define BIOS_WAIT_FLAG_POINTER 0x498
#define BIOS_WAIT_FLAG_COUNT 0x49c
#define BIOS_WAIT_FLAG_ACTIVE 0x4a0
#define BIOS_PRINT_SCREEN_FLAG 0x500 #define BIOS_PRINT_SCREEN_FLAG 0x500
#define BIOS_VIDEO_SAVEPTR 0x4a8 #define BIOS_VIDEO_SAVEPTR 0x4a8

View File

@ -25,9 +25,9 @@
/* Some common Defines */ /* Some common Defines */
/* A CPU Handler */ /* A CPU Handler */
typedef Bitu (CPU_Decoder)(Bitu count); typedef Bitu (CPU_Decoder)(Bits count);
extern CPU_Decoder * cpudecoder; extern CPU_Decoder * cpudecoder;
extern Bit32u cpu_cycles; extern Bitu cpu_cycles;
//CPU Stuff //CPU Stuff
void SetCPU16bit(); void SetCPU16bit();

View File

@ -34,7 +34,7 @@
#define CROSS_LEN 512 /* Maximum filename size */ #define CROSS_LEN 512 /* Maximum filename size */
#if defined (_MSC_VER) /* MS Visual C++ */ #if defined (WIN32) /* Win 32 */
#define CROSS_FILENAME(blah) #define CROSS_FILENAME(blah)
#define CROSS_FILESPLIT '\\' #define CROSS_FILESPLIT '\\'
#define F_OK 0 #define F_OK 0
@ -46,7 +46,7 @@
#define CROSS_NONE 0 #define CROSS_NONE 0
#define CROSS_FILE 1 #define CROSS_FILE 1
#define CROSS_DIR 2 #define CROSS_DIR 2
#if defined (_MSC_VER) #if defined (WIN32)
#define ftruncate(blah,blah2) chsize(blah,blah2) #define ftruncate(blah,blah2) chsize(blah,blah2)
#endif #endif

View File

@ -16,10 +16,16 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
void DEBUG_SetupConsole(void);
void DEBUG_DrawScreen(void); void DEBUG_DrawScreen(void);
bool DEBUG_BreakPoint(void); bool DEBUG_Breakpoint(void);
bool DEBUG_IntBreakpoint(Bit8u intNum); bool DEBUG_IntBreakpoint(Bit8u intNum);
void DEBUG_Enable(void); void DEBUG_Enable(void);
void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off);
bool DEBUG_ExitLoop(void);
extern Bitu cycle_count; extern Bitu cycle_count;
#ifdef C_HEAVY_DEBUG
bool DEBUG_HeavyIsBreakpoint();
#endif

View File

@ -23,57 +23,11 @@
#include <mem.h> #include <mem.h>
#pragma pack (1) #pragma pack (1)
struct CommandTail{ struct CommandTail{
Bit8u count; /* number of bytes returned */ Bit8u count; /* number of bytes returned */
char buffer[127]; /* the buffer itself */ char buffer[127]; /* the buffer itself */
} GCC_ATTRIBUTE(packed); } GCC_ATTRIBUTE(packed);
struct PSP {
Bit8u exit[2]; /* CP/M-like exit poimt */
Bit16u mem_size; /* memory size in paragraphs */
Bit8u fill_1; /* single char fill */
/* CPM Stuff dunno what this is*/
//TODO Add some checks for people using this i think
Bit8u far_call; /* far call opcode */
RealPt cpm_entry; /* CPM Service Request address*/
RealPt int_22; /* Terminate Address */
RealPt int_23; /* Break Address */
RealPt int_24; /* Critical Error Address */
Bit16u psp_parent; /* Parent PSP Segment */
Bit8u files[20]; /* File Table - 0xff is unused */
Bit16u environment; /* Segment of evironment table */
RealPt stack; /* SS:SP Save point for int 0x21 calls */
Bit16u max_files; /* Maximum open files */
RealPt file_table; /* Pointer to File Table PSP:0x18 */
RealPt prev_psp; /* Pointer to previous PSP */
RealPt dta; /* Pointer to current Process DTA */
Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */
Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */
Bit8u fill_3[45]; /* This has some blocks with FCB info */
CommandTail cmdtail;
} GCC_ATTRIBUTE(packed);
struct ParamBlock {
union {
struct {
Bit16u loadseg;
Bit16u relocation;
} overlay;
struct {
Bit16u envseg;
RealPt cmdtail;
RealPt fcb1;
RealPt fcb2;
RealPt initsssp;
RealPt initcsip;
} exec;
};
} GCC_ATTRIBUTE(packed);
struct MCB { struct MCB {
Bit8u type; Bit8u type;
@ -91,7 +45,6 @@ struct DOS_Date {
Bit8u day; Bit8u day;
}; };
struct DOS_Version { struct DOS_Version {
Bit8u major,minor,revision; Bit8u major,minor,revision;
}; };
@ -107,10 +60,13 @@ struct DOS_Block {
RealPt dta; RealPt dta;
Bit8u return_code,return_mode; Bit8u return_code,return_mode;
Bit8u current_drive;
bool verify; bool verify;
bool breakcheck; bool breakcheck;
struct { struct {
RealPt indosflag; RealPt indosflag;
RealPt mediaid;
RealPt tempdta;
} tables; } tables;
}; };
@ -124,6 +80,7 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
extern DOS_Block dos; extern DOS_Block dos;
extern DOS_File * Files[DOS_FILES]; extern DOS_File * Files[DOS_FILES];
extern DOS_Drive * Drives[DOS_DRIVES]; extern DOS_Drive * Drives[DOS_DRIVES];
extern Bit8u dos_copybuf[0x10000];
void DOS_SetError(Bit16u code); void DOS_SetError(Bit16u code);
@ -133,17 +90,16 @@ void DOS_SetError(Bit16u code);
enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDNUL=4,STDPRN=5}; enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDNUL=4,STDPRN=5};
enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE}; enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE};
/* Routines for File Class */ /* Routines for File Class */
void DOS_SetupFiles (void); void DOS_SetupFiles (void);
bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount); bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount);
bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount); bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount);
bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type); bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type);
bool DOS_CloseFile(Bit16u handle); bool DOS_CloseFile(Bit16u handle);
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry); bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry);
bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry); bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry);
bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate);
/* Routines for Drive Class */ /* Routines for Drive Class */
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry); bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry);
bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry); bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry);
@ -153,6 +109,7 @@ bool DOS_FindNext(void);
bool DOS_Canonicalize(char * name,char * big); bool DOS_Canonicalize(char * name,char * big);
bool DOS_CreateTempFile(char * name,Bit16u * entry); bool DOS_CreateTempFile(char * name,Bit16u * entry);
bool DOS_FileExists(char * name); bool DOS_FileExists(char * name);
/* Drive Handing Routines */ /* Drive Handing Routines */
Bit8u DOS_GetDefaultDrive(void); Bit8u DOS_GetDefaultDrive(void);
void DOS_SetDefaultDrive(Bit8u drive); void DOS_SetDefaultDrive(Bit8u drive);
@ -164,14 +121,16 @@ bool DOS_RemoveDir(char * dir);
bool DOS_Rename(char * oldname,char * newname); bool DOS_Rename(char * oldname,char * newname);
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free); bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
bool DOS_GetFileAttr(char * name,Bit16u * attr); bool DOS_GetFileAttr(char * name,Bit16u * attr);
/* IOCTL Stuff */ /* IOCTL Stuff */
bool DOS_IOCTL(Bit8u call,Bit16u entry); bool DOS_IOCTL(void);
bool DOS_GetSTDINStatus(); bool DOS_GetSTDINStatus();
Bit8u DOS_FindDevice(char * name); Bit8u DOS_FindDevice(char * name);
void DOS_SetupDevices(void); void DOS_SetupDevices(void);
/* Execute and new process creation */ /* Execute and new process creation */
bool DOS_NewPSP(Bit16u pspseg); bool DOS_NewPSP(Bit16u pspseg,Bit16u size);
bool DOS_Execute(char * name,ParamBlock * block,Bit8u flags); bool DOS_Execute(char * name,PhysPt block,Bit8u flags);
bool DOS_Terminate(bool tsr); bool DOS_Terminate(bool tsr);
/* Memory Handling Routines */ /* Memory Handling Routines */
@ -182,33 +141,45 @@ bool DOS_FreeMemory(Bit16u segment);
void DOS_FreeProcessMemory(Bit16u pspseg); void DOS_FreeProcessMemory(Bit16u pspseg);
Bit16u DOS_GetMemory(Bit16u pages); Bit16u DOS_GetMemory(Bit16u pages);
/* FCB stuff */ /* FCB stuff */
bool DOS_FCBOpen(Bit16u seg,Bit16u offset); bool DOS_FCBOpenCreate(Bit16u seg,Bit16u offset);
bool DOS_FCBClose(Bit16u seg,Bit16u offset); bool DOS_FCBClose(Bit16u seg,Bit16u offset);
bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset); bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset);
bool DOS_FCBFindNext(Bit16u seg,Bit16u offset); bool DOS_FCBFindNext(Bit16u seg,Bit16u offset);
Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset, Bit16u numBlocks);
bool DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u numBlocks);
Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore);
bool DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore);
bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset,Bit16u numRec);
bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset);
bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset);
void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset);
Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change); Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change);
bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters);
/* Extra DOS Interrupts */ /* Extra DOS Interrupts */
void DOS_SetupMisc(void); void DOS_SetupMisc(void);
/* The DOS Tables */ /* The DOS Tables */
void DOS_SetupTables(void); void DOS_SetupTables(void);
/* Internal DOS Setup Programs */ /* Internal DOS Setup Programs */
void DOS_SetupPrograms(void); void DOS_SetupPrograms(void);
INLINE Bit16u long2para(Bit32u size) { INLINE Bit16u long2para(Bit32u size) {
if (size>0xFFFF0) return 0xffff; if (size>0xFFFF0) return 0xffff;
if (size&0xf) return (Bit16u)((size>>4)+1); if (size&0xf) return (Bit16u)((size>>4)+1);
else return (Bit16u)(size>>4); else return (Bit16u)(size>>4);
}; }
INLINE Bit8u RealHandle(Bit16u handle) {
PSP * psp=(PSP *)HostMake(dos.psp,0); INLINE Bit16u DOS_PackTime(Bit16u hour,Bit16u min,Bit16u sec) {
if (handle>=psp->max_files) return 0xff; return (hour&0x1f)<<11 | (min&0x3f) << 5 | ((sec/2)&0x1f);
return mem_readb(Real2Phys(psp->file_table)+handle); }
};
INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) {
return ((year-1980)&0x7f)<<9 | (mon&0x3f) << 5 | (day&0x1f);
}
/* Dos Error Codes */ /* Dos Error Codes */
#define DOSERR_NONE 0 #define DOSERR_NONE 0
@ -233,68 +204,136 @@ INLINE Bit8u RealHandle(Bit16u handle) {
#define DOSERR_NO_MORE_FILES 18 #define DOSERR_NO_MORE_FILES 18
/* Remains some classes used to access certain things */ /* Remains some classes used to access certain things */
class DOS_FCB {
#define sGet(s,m) GetIt(((s *)Phys2Host(pt))->m,(PhysPt)&(((s *)0)->m))
#define sSave(s,m,val) SaveIt(((s *)Phys2Host(pt))->m,(PhysPt)&(((s *)0)->m),val)
class MemStruct {
public: public:
DOS_FCB(PhysPt pt){ INLINE Bit8u GetIt(Bit8u,PhysPt addr) {
off=pt; return mem_readb(pt+addr);
} }
DOS_FCB(Bit16u seg, Bit16u offset){ INLINE Bit16u GetIt(Bit16u,PhysPt addr) {
off=PhysMake(seg,offset); return mem_readw(pt+addr);
} }
void Set_drive(Bit8u a); INLINE Bit32u GetIt(Bit32u,PhysPt addr) {
void Set_filename(char* a); //writes an the first 8 bytes of a as the filename return mem_readd(pt+addr);
void Set_ext(char* a); }
void Set_current_block(Bit16u a); INLINE void SaveIt(Bit8u,PhysPt addr,Bit8u val) {
void Set_record_size(Bit16u a); mem_writeb(pt+addr,val);
void Set_filesize(Bit32u a); }
void Set_date(Bit16u a); INLINE void SaveIt(Bit16u,PhysPt addr,Bit16u val) {
void Set_time(Bit16u a); mem_writew(pt+addr,val);
// others nog yet handled }
Bit8u Get_drive(void); INLINE void SaveIt(Bit32u,PhysPt addr,Bit32u val) {
void Get_filename(char* a); mem_writed(pt+addr,val);
void Get_ext(char* a); }
Bit16u Get_current_block(void); INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);}
Bit16u Get_record_size(void); INLINE void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);}
Bit32u Get_filesize(void); INLINE void SetPt(RealPt addr) { pt=Real2Phys(addr);}
Bit16u Get_date(void); protected:
Bit16u Get_time(void); PhysPt pt;
private:
PhysPt off;
}; };
class DOS_PSP :public MemStruct {
class DOS_ParamBlock {
public: public:
DOS_ParamBlock(PhysPt pt){ DOS_PSP (Bit16u segment) { SetPt(segment);seg=segment;psp=(sPSP *)HostMake(segment,0);};
off=pt; void MakeNew (Bit16u memSize);
}; void CopyFileTable (DOS_PSP* srcpsp);
void InitExec(RealPt cmdtail); Bit16u FindFreeFileEntry (void);
Bit16u loadseg(void); void CloseFiles (void);
Bit16u relocation(void);
Bit16u envseg(void); void SaveVectors (void);
RealPt initsssp(void); void RestoreVectors (void);
RealPt initcsip(void); void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); };
RealPt fcb1(void); Bit16u GetSize () { return sGet(sPSP,next_seg); };
RealPt fcb2(void); void SetDTA (RealPt ptdta) { sSave(sPSP,dta,ptdta); };
RealPt cmdtail(void); RealPt GetDTA (void) { return sGet(sPSP,dta); };
void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); };
Bit16u GetEnvironment (void) { return sGet(sPSP,environment); };
Bit16u GetSegment (void) { return seg; };
void SetFileHandle (Bit16u index, Bit8u handle);
Bit8u GetFileHandle (Bit16u index);
void SetParent (Bit16u parent) { sSave(sPSP,psp_parent,parent); };
Bit16u GetParent (void) { return sGet(sPSP,psp_parent); };
void SetStack (RealPt stackpt) { sSave(sPSP,stack,stackpt); };
RealPt GetStack (void) { return sGet(sPSP,stack); };
void SetInt22 (RealPt int22pt) { sSave(sPSP,int_22,int22pt); };
RealPt GetInt22 (void) { return sGet(sPSP,int_22); };
void SetFCB1 (RealPt src);
void SetFCB2 (RealPt src);
void SetCommandTail (RealPt src);
private: private:
PhysPt off; #pragma pack(1)
struct sPSP {
Bit8u exit[2]; /* CP/M-like exit poimt */
Bit16u next_seg; /* Segment of first byte beyond memory allocated or program */
Bit8u fill_1; /* single char fill */
Bit8u far_call; /* far call opcode */
RealPt cpm_entry; /* CPM Service Request address*/
RealPt int_22; /* Terminate Address */
RealPt int_23; /* Break Address */
RealPt int_24; /* Critical Error Address */
Bit16u psp_parent; /* Parent PSP Segment */
Bit8u files[20]; /* File Table - 0xff is unused */
Bit16u environment; /* Segment of evironment table */
RealPt stack; /* SS:SP Save point for int 0x21 calls */
Bit16u max_files; /* Maximum open files */
RealPt file_table; /* Pointer to File Table PSP:0x18 */
RealPt prev_psp; /* Pointer to previous PSP */
RealPt dta; /* Pointer to current Process DTA */
Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */
Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */
Bit8u fill_3[9]; /* This has some blocks with FCB info */
Bit8u fcb1[16]; /* first FCB */
Bit8u fcb2[16]; /* second FCB */
Bit8u fill_4[4]; /* unused */
CommandTail cmdtail;
} GCC_ATTRIBUTE(packed);
#pragma pack()
Bit16u seg;
sPSP* psp;
public:
static Bit16u rootpsp;
}; };
class DOS_InfoBlock { class DOS_ParamBlock:public MemStruct {
public: public:
DOS_InfoBlock (void) { seg=0; dib=0; }; DOS_ParamBlock(PhysPt addr) {pt=addr;}
void Clear(void);
void SetLocation (Bit16u segment); void LoadData(void);
void SetFirstMCB (RealPt pt); void SaveData(void); /* Save it as an exec block */
void GetDIBPointer (Bit16u& segment, Bit16u& offset); #pragma pack (1)
struct sOverlay {
Bit16u loadseg;
Bit16u relocation;
} GCC_ATTRIBUTE(packed);
struct sExec {
Bit16u envseg;
RealPt cmdtail;
RealPt fcb1;
RealPt fcb2;
RealPt initsssp;
RealPt initcsip;
}GCC_ATTRIBUTE(packed);
#pragma pack()
sExec exec;
sOverlay overlay;
};
class DOS_InfoBlock:public MemStruct {
public:
DOS_InfoBlock () {};
void SetLocation(Bit16u seg);
void SetFirstMCB(Bit16u _first_mcb);
void SetfirstFileTable(RealPt _first_table);
RealPt GetPointer (void);
private: private:
#pragma pack (push,1) #pragma pack(1)
struct SDosInfoBlock { struct sDIB {
Bit8u stuff1[22]; // some stuff, hopefully never used.... Bit8u stuff1[22]; // some stuff, hopefully never used....
RealPt firstMCB; // first memory control block Bit16u firstMCB; // first memory control block
RealPt firstDPB; // first drive parameter block RealPt firstDPB; // first drive parameter block
RealPt firstFileTable; // first system file table RealPt firstFileTable; // first system file table
RealPt activeClock; // active clock device header RealPt activeClock; // active clock device header
@ -305,13 +344,83 @@ private:
RealPt fcbTable; // pointer to system FCB table RealPt fcbTable; // pointer to system FCB table
// some more stuff, hopefully never used. // some more stuff, hopefully never used.
} GCC_ATTRIBUTE(packed); } GCC_ATTRIBUTE(packed);
#pragma pack (pop) #pragma pack ()
SDosInfoBlock* dib;
Bit16u seg; Bit16u seg;
}; };
extern DOS_InfoBlock dosInfoBlock; class DOS_DTA:public MemStruct{
public:
DOS_DTA(RealPt addr) { SetPt(addr); }
void SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * _pattern);
void SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr);
Bit8u GetSearchDrive(void);
void GetSearchParams(Bit8u & _sattr,char * _spattern);
void GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr);
private:
#pragma pack(1)
struct sDTA {
Bit8u sdrive; /* The Drive the search is taking place */
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];
Bit8u attr;
Bit16u time;
Bit16u date;
Bit32u size;
char name[DOS_NAMELENGTH_ASCII];
} GCC_ATTRIBUTE(packed);
#pragma pack()
};
class DOS_FCB: public MemStruct {
public:
DOS_FCB(Bit16u seg,Bit16u off);
void Create(bool _extended);
void SetName(Bit8u _drive,char * _fname,char * _ext);
void SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time);
void GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time);
void GetName(char * fillname);
void FileOpen(Bit8u _fhandle);
void FileClose(Bit8u & _fhandle);
void GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec);
void SetRecord(Bit16u _cur_block,Bit8u _cur_rec);
void GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size);
void GetRandom(Bit32u & _random);
void SetRandom(Bit32u _random);
Bit8u GetDrive(void);
bool Extended(void);
private:
bool extended;
PhysPt real_pt;
#pragma pack (1)
struct sFCB {
Bit8u drive; /* Drive number 0=default, 1=A, etc */
Bit8u filename[8]; /* Space padded name */
Bit8u ext[3]; /* Space padded extension */
Bit16u cur_block; /* Current Block */
Bit16u rec_size; /* Logical record size */
Bit32u filesize; /* File Size */
Bit16u date;
Bit16u time;
/* Reserved Block should be 8 bytes */
Bit8u file_handle;
Bit8u reserved[7];
/* end */
Bit8u cur_rec; /* Current record in current block */
Bit32u rndm; /* Current relative record number */
} GCC_ATTRIBUTE(packed);
#pragma pack ()
};
extern DOS_InfoBlock dos_infoblock;;
INLINE Bit8u RealHandle(Bit16u handle) {
DOS_PSP psp(dos.psp);
return psp.GetFileHandle((Bit8u)handle);
}
#endif #endif

View File

@ -19,11 +19,13 @@
#ifndef DOSSYSTEM_H_ #ifndef DOSSYSTEM_H_
#define DOSSYSTEM_H_ #define DOSSYSTEM_H_
#include <dosbox.h> #include "dosbox.h"
#define DOS_NAMELENGTH 12 #define DOS_NAMELENGTH 12
#define DOS_DIRDEPTH 16 #define DOS_NAMELENGTH_ASCII (DOS_NAMELENGTH+1)
#define DOS_PATHLENGTH (DOS_DIRDEPTH+1)*(DOS_NAMELENGTH+2) #define DOS_FCBNAME 15
#define DOS_DIRDEPTH 8
#define DOS_PATHLENGTH 80
#define DOS_TEMPSIZE 1024 #define DOS_TEMPSIZE 1024
enum { enum {
@ -35,34 +37,29 @@ enum {
DOS_ATTR_ARCHIVE= 0x20 DOS_ATTR_ARCHIVE= 0x20
}; };
#if defined (_MSC_VER) struct FileStat_Block {
#pragma pack(1) Bit32u size;
#endif
struct DTA_FindBlock {
Bit8u sdrive; /* The Drive the search is taking place */
Bit16u sattr; /* The attributes that need to be found */
Bit8u fill[18];
Bit8u attr;
Bit16u time; Bit16u time;
Bit16u date; Bit16u date;
Bit32u size; Bit16u attr;
char name[DOS_NAMELENGTH]; };
}
#if defined (_MSC_VER) class DOS_DTA;
;
#pragma pack()
#else
__attribute__ ((packed));
#endif
class DOS_File { class DOS_File {
public: public:
virtual ~DOS_File(){};
virtual bool Read(Bit8u * data,Bit16u * size)=0; virtual bool Read(Bit8u * data,Bit16u * size)=0;
virtual bool Write(Bit8u * data,Bit16u * size)=0; virtual bool Write(Bit8u * data,Bit16u * size)=0;
virtual bool Seek(Bit32u * pos,Bit32u type)=0; virtual bool Seek(Bit32u * pos,Bit32u type)=0;
virtual bool Close()=0; virtual bool Close()=0;
virtual Bit16u GetInformation(void)=0; virtual Bit16u GetInformation(void)=0;
Bit8u type;Bit32u flags; Bit8u type;
Bit32u flags;
Bit16u time;
Bit16u date;
Bit16u attr;
Bit32u size;
/* Some Device Specific Stuff */ /* Some Device Specific Stuff */
}; };
@ -73,24 +70,24 @@ public:
Bit8u fhandle; Bit8u fhandle;
}; };
class DOS_Drive { class DOS_Drive {
public: public:
DOS_Drive(); DOS_Drive();
virtual ~DOS_Drive(){};
virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags)=0; virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags)=0;
virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes)=0; virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes)=0;
virtual bool FileUnlink(char * name)=0; virtual bool FileUnlink(char * _name)=0;
virtual bool RemoveDir(char * dir)=0; virtual bool RemoveDir(char * _dir)=0;
virtual bool MakeDir(char * dir)=0; virtual bool MakeDir(char * _dir)=0;
virtual bool TestDir(char * dir)=0; virtual bool TestDir(char * _dir)=0;
virtual bool FindFirst(char * search,DTA_FindBlock * dta)=0; virtual bool FindFirst(char * _dir,DOS_DTA & dta)=0;
virtual bool FindNext(DTA_FindBlock * dta)=0; virtual bool FindNext(DOS_DTA & dta)=0;
virtual bool GetFileAttr(char * name,Bit16u * attr)=0; virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
virtual bool Rename(char * oldname,char * newname)=0; virtual bool Rename(char * oldname,char * newname)=0;
virtual bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free)=0; virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters)=0;
virtual bool FileExists(const char* name) const=0; virtual bool FileExists(const char* name)=0;
virtual bool FileStat(const char* name, struct stat* const stat_block) const=0; virtual bool FileStat(const char* name, FileStat_Block * const stat_block)=0;
virtual Bit8u GetMediaByte(void)=0;
char * GetInfo(void); char * GetInfo(void);
char curdir[DOS_PATHLENGTH]; char curdir[DOS_PATHLENGTH];
char info[256]; char info[256];
@ -109,6 +106,6 @@ typedef bool (MultiplexHandler)(void);
void DOS_AddMultiplexHandler(MultiplexHandler * handler); void DOS_AddMultiplexHandler(MultiplexHandler * handler);
void DOS_AddDevice(DOS_Device * adddev); void DOS_AddDevice(DOS_Device * adddev);
void VFILE_Register(char * name,Bit8u * data,Bit32u size); void VFILE_Register(const char * name,Bit8u * data,Bit32u size);
#endif #endif

View File

@ -24,6 +24,9 @@ void E_Exit(char * message,...);
void S_Warn(char * message,...); void S_Warn(char * message,...);
void MSG_Add(const char*,const char*); //add messages to the internal langaugefile
const char* MSG_Get(char const *); //get messages from the internal langaugafile
/* The internal types */ /* The internal types */
typedef unsigned char Bit8u; typedef unsigned char Bit8u;
typedef signed char Bit8s; typedef signed char Bit8s;
@ -47,14 +50,115 @@ typedef signed int Bits;
#include "config.h" #include "config.h"
#include "../settings.h" #include "../settings.h"
class Section;
typedef Bitu (LoopHandler)(void); typedef Bitu (LoopHandler)(void);
void DOSBOX_RunMachine(); void DOSBOX_RunMachine();
void DOSBOX_SetLoop(LoopHandler * handler); void DOSBOX_SetLoop(LoopHandler * handler);
void DOSBOX_SetNormalLoop(); void DOSBOX_SetNormalLoop();
void DOSBOX_Init(int argc, char* argv[]); void DOSBOX_Init(void);
void DOSBOX_StartUp(void);
class Config;
extern Config * control;
extern Bitu errorlevel;
inline void LOG_MSG(char* message)
{
if(errorlevel>=0) S_Warn(message);
}
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);
}
#else
#define LOG_DEBUG
#define LOG_WARN
#define LOG_ERROR
#endif
#endif #endif

View File

@ -19,24 +19,7 @@
#ifndef _HARDWARE_H_ #ifndef _HARDWARE_H_
#define _HARDWARE_H_ #define _HARDWARE_H_
#include <programs.h>
#include <support.h>
#include <stdio.h>
typedef void (* HW_OutputHandler)(char * towrite);
typedef void (* HW_InputHandler)(char * line);
struct HWBlock {
char * dev_name; /* 8 characters max dev name */
char * full_name; /* 60 characters full name */
char * help;
HW_InputHandler get_input;
HW_OutputHandler show_status; /* Supplied with a string to display 50 chars of status info in */
HWBlock * next;
};
void HW_Register(HWBlock * block);
#endif #endif

View File

@ -16,6 +16,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#ifndef _KEYBOARD_H_
#define _KEYBOARD_H_
typedef void(KEYBOARD_EventHandler)(void); typedef void(KEYBOARD_EventHandler)(void);
void KEYBOARD_AddCode(Bit8u code); void KEYBOARD_AddCode(Bit8u code);
void KEYBOARD_AddKey(Bitu keytype,bool pressed); void KEYBOARD_AddKey(Bitu keytype,bool pressed);
@ -51,4 +54,4 @@ enum {
KBD_LAST KBD_LAST
}; };
#endif

View File

@ -30,7 +30,7 @@ typedef Bit8u (*MEMORY_ReadHandler)(PhysPt pt);
typedef void (*MEMORY_WriteHandler)(PhysPt pt,Bit8u val); typedef void (*MEMORY_WriteHandler)(PhysPt pt,Bit8u val);
#define PAGE_KB 16 #define PAGE_KB 16
#define PAGE_SIZE PAGE_KB*1024 #define PAGE_SIZE (PAGE_KB*1024)
#define PAGE_SHIFT 14 #define PAGE_SHIFT 14
#define PAGE_COUNT(A) (A & ((1 << PAGE_SHIFT)-1) ? 1+(A >> PAGE_SHIFT) : (A >> PAGE_SHIFT) ) #define PAGE_COUNT(A) (A & ((1 << PAGE_SHIFT)-1) ? 1+(A >> PAGE_SHIFT) : (A >> PAGE_SHIFT) )
#define MAX_PAGES PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024) #define MAX_PAGES PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024)

View File

@ -37,6 +37,9 @@ void MIXER_SetFreq(MIXER_Channel * chan,Bit32u freq);
void MIXER_SetMode(MIXER_Channel * chan,Bit8u mode); void MIXER_SetMode(MIXER_Channel * chan,Bit8u mode);
void MIXER_Enable(MIXER_Channel * chan,bool enable); void MIXER_Enable(MIXER_Channel * chan,bool enable);
void PCSPEAKER_Enable(bool enable); /* PC Speakers functions, tightly related to the timer functions */
void PCSPEAKER_SetFreq(Bit32u freq);
void PCSPEAKER_Enable(bool enable);
void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode);

View File

@ -25,4 +25,5 @@ void Mouse_CursorSet(float x,float y);
void Mouse_ButtonPressed(Bit8u button); void Mouse_ButtonPressed(Bit8u button);
void Mouse_ButtonReleased(Bit8u button); void Mouse_ButtonReleased(Bit8u button);
void Mouse_AutoLock(bool enable);

View File

@ -20,9 +20,14 @@
#define __PIC_H #define __PIC_H
typedef void (PIC_EOIHandler) (void); typedef void (PIC_EOIHandler) (void);
typedef void (PIC_Function)(void);
extern Bit32u PIC_IRQCheck; #define PIC_MAXIRQ 15
#define PIC_NOIRQ 0xFF
extern Bitu PIC_IRQCheck;
extern Bitu PIC_IRQActive;
extern bool PIC_IRQAgain;
void PIC_ActivateIRQ(Bit32u irq); void PIC_ActivateIRQ(Bit32u irq);
@ -33,11 +38,6 @@ void PIC_runIRQs(void);
void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name); void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name);
void PIC_FreeIRQ(Bit32u irq); void PIC_FreeIRQ(Bit32u irq);
bool PIC_IRQActive(Bit32u irq);
/* A Queued function should never queue itself again this will go horribly wrong */
void PIC_QueueFunction(PIC_Function * function);
#endif #endif

View File

@ -18,32 +18,33 @@
#ifndef __PROGRAM_H #ifndef __PROGRAM_H
#define __PROGRAM_H #define __PROGRAM_H
#include <dosbox.h> #include "dosbox.h"
#include <dos_inc.h> #include "dos_inc.h"
#include "setup.h"
char * MSG_Get(char * msg);
struct PROGRAM_Info { class Program;
Bit16u psp_seg;
PSP psp_copy;
char full_name[32]; //Enough space for programs only on the z:\ drive
char * cmd_line;
};
typedef void (PROGRAMS_Main)(PROGRAM_Info * info); typedef void (PROGRAMS_Main)(Program * * make);
void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main); void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main);
class Program { class Program {
public: public:
Program(PROGRAM_Info * program_info); Program();
virtual ~Program(){
delete cmd;
delete psp;
}
std::string temp_line;
CommandLine * cmd;
DOS_PSP * psp;
virtual void Run(void)=0; virtual void Run(void)=0;
char * GetEnvStr(char * env_entry); bool Program::GetEnvStr(const char * entry,std::string & result);
char * GetEnvNum(Bit32u num); bool GetEnvNum(Bitu num,std::string & result);
Bit32u GetEnvCount(void); Bitu GetEnvCount(void);
bool SetEnv(char * env_entry,char * new_string); bool SetEnv(const char * entry,const char * new_string);
void WriteOut(char * format,...); /* Write to standard output */ void WriteOut(const char * format,...); /* Write to standard output */
PROGRAM_Info * prog_info;
}; };

View File

@ -19,25 +19,171 @@
#ifndef _SETUP_H_ #ifndef _SETUP_H_
#define _SETUP_H_ #define _SETUP_H_
#pragma warning ( disable : 4786 )
#include <cross.h> #include <cross.h>
enum { S_STRING,S_HEX,S_INT,S_BOOL}; #include <string>
#include <list>
typedef char *(String_Handler)(char * input);
typedef char *(Hex_Handler)(Bitu * input);
typedef char *(Int_Handler)(Bits * input);
typedef char *(Bool_Handler)(bool input);
class Setup {
class CommandLine {
public:
CommandLine(int argc,char * argv[]);
CommandLine(char * name,char * cmdline);
const char * GetFileName(){ return file_name.c_str();}
bool FindExist(char * name,bool remove=false);
bool FindHex(char * name,int & value,bool remove=false);
bool FindInt(char * name,int & value,bool remove=false);
bool FindString(char * name,std::string & value,bool remove=false);
bool FindCommand(int which,std::string & value);
bool FindStringBegin(char * begin,std::string & value, bool remove=false);
int GetCount(void);
private: private:
int argc; typedef std::list<std::string>::iterator cmd_it;
char * * argv; std::list<std::string> cmds;
std::string file_name;
bool FindEntry(char * name,cmd_it & it,bool neednext=false);
};
union Value{
int _hex;
bool _bool;
int _int;
std::string* _string;
};
class Property {
public:
Property(const char* _propname):propname(_propname) { }
virtual void SetValue(char* input)=0;
virtual void GetValuestring(char* str)=0;
Value GetValue() { return __value;}
std::string propname;
Value __value;
virtual ~Property(){ }
};
class Prop_int:public Property {
public:
Prop_int(const char* _propname, int _value):Property(_propname) {
__value._int=_value;
}
void SetValue(char* input);
void GetValuestring(char* str);
~Prop_int(){ }
};
class Prop_bool:public Property {
public:
Prop_bool(const char* _propname, bool _value):Property(_propname) {
__value._bool=_value;
}
void SetValue(char* input);
void GetValuestring(char* str);
~Prop_bool(){ }
};
class Prop_string:public Property{
public:
Prop_string(const char* _propname, char* _value):Property(_propname) {
__value._string=new std::string(_value);
}
~Prop_string(){
delete __value._string;
}
void SetValue(char* input);
void GetValuestring(char* str);
};
class Prop_hex:public Property {
public:
Prop_hex(const char* _propname, int _value):Property(_propname) {
__value._hex=_value;
}
void SetValue(char* input);
~Prop_hex(){ }
void GetValuestring(char* str);
};
class Section {
public:
Section(const char* _sectionname) { sectionname=_sectionname; }
virtual ~Section(){ ExecuteDestroy();}
typedef void (*SectionFunction)(Section*);
void AddInitFunction(SectionFunction func) {initfunctions.push_back(func);}
void AddDestroyFunction(SectionFunction func) {destroyfunctions.push_front(func);}
void ExecuteInit() {
typedef std::list<SectionFunction>::iterator func_it;
for (func_it tel=initfunctions.begin(); tel!=initfunctions.end(); tel++){
(*tel)(this);
}
}
void ExecuteDestroy() {
typedef std::list<SectionFunction>::iterator func_it;
for (func_it tel=destroyfunctions.begin(); tel!=destroyfunctions.end(); tel++){
(*tel)(this);
}
}
std::list<SectionFunction> initfunctions;
std::list<SectionFunction> destroyfunctions;
virtual void HandleInputline(char * _line){}
virtual void PrintData(FILE* outfile) {}
std::string sectionname;
}; };
class Section_prop:public Section {
public:
Section_prop(const char* _sectionname):Section(_sectionname){}
extern char dosbox_basedir[CROSS_LEN]; void Add_int(const char* _propname, int _value=0);
void Add_string(const char* _propname, char* _value=NULL);
void Add_bool(const char* _propname, bool _value=false);
void Add_hex(const char* _propname, int _value=0);
int Get_int(const char* _propname);
const char* Get_string(const char* _propname);
bool Get_bool(const char* _propname);
int Get_hex(const char* _propname);
void HandleInputline(char *gegevens);
void PrintData(FILE* outfile);
std::list<Property*> properties;
typedef std::list<Property*>::iterator it;
};
class Section_line: public Section{
public:
Section_line(const char* _sectionname):Section(_sectionname){}
void HandleInputline(char* gegevens);
void PrintData(FILE* outfile);
std::string data;
};
class Config{
public:
Config(CommandLine * cmd){ cmdline=cmd;}
~Config();
CommandLine * cmdline;
Section * AddSection(const char * _name,void (*_initfunction)(Section*));
Section_line * AddSection_line(const char * _name,void (*_initfunction)(Section*));
Section_prop * AddSection_prop(const char * _name,void (*_initfunction)(Section*));
Section* GetSection(const char* _sectionname);
void SetStartUp(void (*_function)(void));
void Init();
void ShutDown();
void StartUp();
void PrintConfig(const char* configfilename);
void ParseConfigFile(const char* configfilename);
std::list<Section*> sectionlist;
typedef std::list<Section*>::iterator it;
typedef std::list<Section*>::reverse_iterator reverse_it;
private:
void (* _start_function)(void);
};
#endif #endif

View File

@ -39,8 +39,6 @@ char *ltrim(char *str);
void rtrim(char * const str); void rtrim(char * const str);
char *trim(char *str); char *trim(char *str);
bool wildcmp(char *wild, char *string);
bool ScanCMDBool(char * cmd,char * check); bool ScanCMDBool(char * cmd,char * check);
char * ScanCMDRemain(char * cmd); char * ScanCMDRemain(char * cmd);
bool ScanCMDHex(char * cmd,char * check,Bits * result); bool ScanCMDHex(char * cmd,char * check,Bits * result);

View File

@ -19,9 +19,12 @@
#ifndef _TIMER_H_ #ifndef _TIMER_H_
#define _TIMER_H_ #define _TIMER_H_
/* underlying clock rate in HZ */ /* underlying clock rate in HZ */
#include <SDL/SDL.h> #include <SDL.h>
extern Bit32u LastTicks; extern Bit32u LastTicks;
#define PIT_TICK_RATE 1193182
#define GetTicks() SDL_GetTicks() #define GetTicks() SDL_GetTicks()
typedef void (*TIMER_TickHandler)(Bitu ticks); typedef void (*TIMER_TickHandler)(Bitu ticks);
@ -48,6 +51,5 @@ void TIMER_CheckPIT(void);
/* This will add ms ticks to support the timer handlers */ /* This will add ms ticks to support the timer handlers */
void TIMER_AddTicks(Bit32u ticks); void TIMER_AddTicks(Bit32u ticks);
#endif #endif

View File

@ -19,6 +19,7 @@
#ifndef __VIDEO_H #ifndef __VIDEO_H
#define __VIDEO_H #define __VIDEO_H
typedef void (GFX_DrawHandler)(Bit8u * vidstart); typedef void (GFX_DrawHandler)(Bit8u * vidstart);
/* Used to reply to the renderer what size to set */ /* Used to reply to the renderer what size to set */
typedef void (GFX_ResizeHandler)(Bitu * width,Bitu * height); typedef void (GFX_ResizeHandler)(Bitu * width,Bitu * height);
@ -45,6 +46,5 @@ void GFX_Start(void);
void GFX_Stop(void); void GFX_Stop(void);
void GFX_SwitchFullScreen(void); void GFX_SwitchFullScreen(void);
#endif #endif

View File

@ -21,6 +21,7 @@
/* Enable the debugger, this only seems to work in win32 for now. */ /* Enable the debugger, this only seems to work in win32 for now. */
#define C_DEBUG 0 #define C_DEBUG 0
#define C_HEAVY_DEBUG 0
/* Enable the logging of extra information for debugging to the console */ /* Enable the logging of extra information for debugging to the console */
#define C_LOGGING 0 #define C_LOGGING 0
@ -48,16 +49,4 @@
#define DEBUG_DMA 0 /* DMA Debugging */ #define DEBUG_DMA 0 /* DMA Debugging */
#define DEBUG_DOS 0 /* DOS Debugging */ #define DEBUG_DOS 0 /* DOS Debugging */
#define LOG_MSG S_Warn
#if C_LOGGING
#define LOG_DEBUG S_Warn
#define LOG_WARN S_Warn
#define LOG_ERROR S_Warn
#else
#define LOG_DEBUG
#define LOG_WARN
#define LOG_ERROR
#endif
#endif #endif

View File

@ -6,5 +6,5 @@ bin_PROGRAMS = dosbox
dosbox_SOURCES = dosbox.cpp dosbox_SOURCES = dosbox.cpp
dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \ 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 ints/libints.a misc/libmisc.a shell/libshell.a -lcurses -lpng
EXTRA_DIST = dosbox.lang

View File

@ -89,9 +89,8 @@ bin_PROGRAMS = dosbox
dosbox_SOURCES = dosbox.cpp dosbox_SOURCES = dosbox.cpp
dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \ 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 ints/libints.a misc/libmisc.a shell/libshell.a -lcurses -lpng
EXTRA_DIST = dosbox.lang
subdir = src subdir = src
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h CONFIG_HEADER = $(top_builddir)/config.h

View File

@ -135,7 +135,7 @@ bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type) {
return true; return true;
} }
void CALLBACK_Init(void) { void CALLBACK_Init(Section* sec) {
Bitu i; Bitu i;
for (i=0;i<CB_MAX;i++) { for (i=0;i<CB_MAX;i++) {
CallBack_Handlers[i]=&illegal_handler; CallBack_Handlers[i]=&illegal_handler;

View File

@ -16,7 +16,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
bool repcheck;
restart: restart:
switch(Fetchb()) { switch(Fetchb()) {
case 0x00: /* ADD Eb,Gb */ case 0x00: /* ADD Eb,Gb */
@ -109,9 +108,12 @@ restart:
if ((reg_al > 0x9F) || flags.cf) { if ((reg_al > 0x9F) || flags.cf) {
reg_al+=0x60; reg_al+=0x60;
flags.cf=true; flags.cf=true;
} else {
flags.cf=false;
} }
flags.sf=(reg_al>>7)>0; flags.sf=(reg_al>>7)>0;
flags.zf=(reg_al==0); flags.zf=(reg_al==0);
//TODO Maybe parity
flags.type=t_UNKNOWN; flags.type=t_UNKNOWN;
break; break;
case 0x28: /* SUB Eb,Gb */ case 0x28: /* SUB Eb,Gb */
@ -545,35 +547,11 @@ restart:
} }
case 0x8d: /* LEA */ case 0x8d: /* LEA */
{ {
GetRMrw; prefix.segbase=0;
switch (rm & 0xC7) { prefix.mark|=PREFIX_SEG;
case 0x00:*rmrw=reg_bx+reg_si;break; lookupEATable=EAPrefixTable[prefix.mark];
case 0x01:*rmrw=reg_bx+reg_di;break; GetRMrw;GetEAa;
case 0x02:*rmrw=reg_bp+reg_si;break; *rmrw=(Bit16u)eaa;
case 0x03:*rmrw=reg_bp+reg_di;break;
case 0x04:*rmrw=reg_si;break;
case 0x05:*rmrw=reg_di;break;
case 0x06:*rmrw=Fetchw();break;
case 0x07:*rmrw=reg_bx;break;
case 0x40:*rmrw=reg_bx+reg_si+Fetchbs();break;
case 0x41:*rmrw=reg_bx+reg_di+Fetchbs();break;
case 0x42:*rmrw=reg_bp+reg_si+Fetchbs();break;
case 0x43:*rmrw=reg_bp+reg_di+Fetchbs();break;
case 0x44:*rmrw=reg_si+Fetchbs();break;
case 0x45:*rmrw=reg_di+Fetchbs();break;
case 0x46:*rmrw=reg_bp+Fetchbs();break;
case 0x47:*rmrw=reg_bx+Fetchbs();break;
case 0x80:*rmrw=reg_bx+reg_si+Fetchw();break;
case 0x81:*rmrw=reg_bx+reg_di+Fetchw();break;
case 0x82:*rmrw=reg_bp+reg_si+Fetchw();break;
case 0x83:*rmrw=reg_bp+reg_di+Fetchw();break;
case 0x84:*rmrw=reg_si+Fetchw();break;
case 0x85:*rmrw=reg_di+Fetchw();break;
case 0x86:*rmrw=reg_bp+Fetchw();break;
case 0x87:*rmrw=reg_bx+Fetchw();break;
default:
E_Exit("CPU:8d:Illegal LEA RM Byte");
}
break; break;
} }
case 0x8e: /* MOV Sw,Ew */ case 0x8e: /* MOV Sw,Ew */
@ -880,7 +858,7 @@ restart:
case 0xcc: /* INT3 */ case 0xcc: /* INT3 */
INTERRUPT(3); INTERRUPT(3);
#if C_DEBUG #if C_DEBUG
return 0; return 1;
#endif #endif
break; break;
case 0xcd: /* INT Ib */ case 0xcd: /* INT Ib */
@ -888,7 +866,7 @@ restart:
Bit8u num=Fetchb(); Bit8u num=Fetchb();
#if C_DEBUG #if C_DEBUG
SAVEIP; SAVEIP;
if (DEBUG_IntBreakpoint(num)) return 0; if (DEBUG_IntBreakpoint(num)) return 1;
#endif #endif
INTERRUPT(num); INTERRUPT(num);
} }
@ -936,8 +914,8 @@ restart:
reg_al = get_CF() ? 0xFF : 0; reg_al = get_CF() ? 0xFF : 0;
break; break;
case 0xd7: /* XLAT */ case 0xd7: /* XLAT */
if (prefixes & PREFIX_SEG) { if (prefix.mark & PREFIX_SEG) {
reg_al=LoadMb(segprefix_base+(Bit16u)(reg_bx+reg_al)); reg_al=LoadMb(prefix.segbase+(Bit16u)(reg_bx+reg_al));
PrefixReset; PrefixReset;
} else { } else {
reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al)); reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
@ -1042,174 +1020,15 @@ restart:
LOG_ERROR("CPU:LOCK"); LOG_ERROR("CPU:LOCK");
break; break;
case 0xf1: /* Weird call undocumented */ case 0xf1: /* Weird call undocumented */
// INTERRUPT(1);
E_Exit("CPU:F1:Not Handled"); E_Exit("CPU:F1:Not Handled");
break; break;
case 0xf2: /* REPNZ */ case 0xf2: /* REPNZ */
repcheck=false; count-=Repeat_Normal(false,false,count);
goto repstart; break;
case 0xf3: /* REPZ */ case 0xf3: /* REPZ */
repcheck=true; count-=Repeat_Normal(true,false,count);
repstart:
{
EAPoint to=SegBase(es);
EAPoint from;
if (prefixes & PREFIX_SEG) {
from=(segprefix_base);
PrefixReset;
} else {
from=SegBase(ds);
}
Bit16s direct;
if (flags.df) direct=-1;
else direct=1;
reploop:
Bit8u repcode=Fetchb();
switch (repcode) {
case 0x26: /* ES Prefix */
from=SegBase(es);
goto reploop;
case 0x2e: /* CS Prefix */
from=SegBase(cs);
goto reploop;
case 0x36: /* SS Prefix */
from=SegBase(ss);
goto reploop;
case 0x3e: /* DS Prefix */
from=SegBase(ds);
goto reploop;
#ifdef CPU_386
case 0x66:
Rep_66(direct,from,to);
break; break;
#endif
case 0x6c: /* REP INSB */
{
for (Bit32u temp=reg_cx;temp>0;temp--) {
SaveMb(to,IO_Read(reg_dx));
to+=direct;
};
reg_di+=Bit16s(reg_cx*direct);reg_cx=0;
break;
}
case 0x6d: /* REP INSW */
{
for (Bit32u temp=reg_cx;temp>0;temp--) {
SaveMb(to,IO_Read(reg_dx));
SaveMb((to+1),IO_Read(reg_dx+1));
to+=direct*2;
}
reg_di+=Bit16s(reg_cx*direct*2);reg_cx=0;
break;
}
case 0x6e: /* REP OUTSB */
for (;reg_cx>0;reg_cx--) {
IO_Write(reg_dx,LoadMb(from+reg_si));
reg_si+=direct;
}
break;
case 0x6f: /* REP OUTSW */
for (;reg_cx>0;reg_cx--) {
IO_Write(reg_dx,LoadMb(from+reg_si));
IO_Write(reg_dx+1,LoadMb(from+reg_si+1));
reg_si+=direct*2;
}
break;
case 0xa4: /* REP MOVSB */
for (;reg_cx>0;reg_cx--) {
SaveMb(to+reg_di,LoadMb(from+reg_si));
reg_di+=direct;
reg_si+=direct;
}
break;
case 0xa5: /* REP MOVSW */
for (;reg_cx>0;reg_cx--) {
SaveMw(to+reg_di,LoadMw(from+reg_si));
reg_di+=direct*2;
reg_si+=direct*2;
}
break;
case 0xa6: /* REP CMPSB */
if (!reg_cx) break;
for (;reg_cx>0;) {
reg_cx--;
if ((LoadMb(from+reg_si)==LoadMb(to+reg_di))!=repcheck) {
reg_di+=direct;
reg_si+=direct;
break;
}
reg_di+=direct;
reg_si+=direct;
}
CMPB(from+(reg_si-direct),LoadMb(to+(reg_di-direct)),LoadMb,0);
break;
case 0xa7: /* REP CMPSW */
if (!reg_cx) break;
for (;reg_cx>0;) {
reg_cx--;
if ((LoadMw(from+reg_si)==LoadMw(to+reg_di))!=repcheck) {
reg_di+=direct*2;
reg_si+=direct*2;
break;
}
reg_di+=direct*2;
reg_si+=direct*2;
}
CMPW(from+(reg_si-direct*2),LoadMw(to+(reg_di-direct*2)),LoadMw,0);
break;
case 0xaa: /* REP STOSB */
for (;reg_cx>0;reg_cx--) {
SaveMb(to+reg_di,reg_al);
reg_di+=direct;
}
break;
case 0xab: /* REP STOSW */
for (;reg_cx>0;reg_cx--) {
SaveMw(to+reg_di,reg_ax);
reg_di+=direct*2;
}
break;
case 0xac: /* REP LODSB */
for (;reg_cx>0;reg_cx--) {
reg_al=LoadMb(from+reg_si);
reg_si+=direct;
}
break;
case 0xad: /* REP LODSW */
for (;reg_cx>0;reg_cx--) {
reg_ax=LoadMw(from+reg_si);
reg_si+=direct*2;
}
break;
case 0xae: /* REP SCASB */
if (!reg_cx) break;
for (;reg_cx>0;) {
reg_cx--;
if ((reg_al==LoadMb(to+reg_di))!=repcheck) {
reg_di+=direct;
break;
}
reg_di+=direct;
}
CMPB(reg_al,LoadMb(to+(reg_di-direct)),LoadRb,0);
break;
case 0xaf: /* REP SCASW */
if (!reg_cx) break;
for (;reg_cx>0;) {
reg_cx--;
if ((reg_ax==LoadMw(to+reg_di))!=repcheck) {
reg_di+=direct*2;
break;
}
reg_di+=direct*2;
}
CMPW(reg_ax,LoadMw(to+(reg_di-direct*2)),LoadRw,0);
break;
default:
E_Exit("Illegal REP prefix %2X",repcode);
}
break;
}
case 0xf4: /* HLT */ case 0xf4: /* HLT */
break; break;
case 0xf5: /* CMC */ case 0xf5: /* CMC */
@ -1496,5 +1315,9 @@ restart:
} }
break; break;
} }
default:
NOTDONE;
break;
} }

View File

@ -24,7 +24,7 @@ switch(Fetchb()) {
RMGdEd(ADDD);break; RMGdEd(ADDD);break;
case 0x05: /* ADD EAX,Id */ case 0x05: /* ADD EAX,Id */
EAXId(ADDD);break; EAXId(ADDD);break;
case 0x09: /* OR Ew,Gw */ case 0x09: /* OR Ed,Gd */
RMEdGd(ORD);break; RMEdGd(ORD);break;
case 0x0b: /* OR Gd,Ed */ case 0x0b: /* OR Gd,Ed */
RMGdEd(ORD);break; RMGdEd(ORD);break;
@ -69,8 +69,6 @@ switch(Fetchb()) {
RMGdEd(CMPD);break; RMGdEd(CMPD);break;
case 0x3d: /* CMP EAX,Id */ case 0x3d: /* CMP EAX,Id */
EAXId(CMPD);break; EAXId(CMPD);break;
case 0x26: /* SEG ES: */ case 0x26: /* SEG ES: */
SegPrefix_66(es);break; SegPrefix_66(es);break;
case 0x2e: /* SEG CS: */ case 0x2e: /* SEG CS: */
@ -153,6 +151,10 @@ switch(Fetchb()) {
break; break;
case 0x68: /* PUSH Id */ case 0x68: /* PUSH Id */
Push_32(Fetchd());break; Push_32(Fetchd());break;
case 0x64: /* SEG FS: */
SegPrefix_66(fs);break;
case 0x65: /* SEG GS: */
SegPrefix_66(gs);break;
case 0x69: /* IMUL Gd,Ed,Id */ case 0x69: /* IMUL Gd,Ed,Id */
{ {
GetRMrd; GetRMrd;
@ -164,12 +166,21 @@ switch(Fetchb()) {
if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;} if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;}
else {flags.cf=true;flags.of=true;} else {flags.cf=true;flags.of=true;}
break; break;
}; }
case 0x6a: /* PUSH Ib */ case 0x6a: /* PUSH Ib */
Push_32(Fetchbs());break; Push_32(Fetchbs());break;
case 0x6b: /* IMUL Gd,Ed,Ib */
{
GetRMrd;
Bit64s res;
if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*eards) * (Bit64s)Fetchbs();}
else {GetEAa;res=(Bit64s)LoadMds(eaa) * (Bit64s)Fetchbs();}
*rmrd=(Bit32s)(res);
flags.type=t_MUL;
if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;}
else {flags.cf=true;flags.of=true;}
break;
}
case 0x81: /* Grpl Ed,Id */ case 0x81: /* Grpl Ed,Id */
{ {
GetRM; GetRM;
@ -186,7 +197,7 @@ switch(Fetchb()) {
case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break; case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break;
} }
} else { } else {
GetEAa;Bit32u id=Fetchb(); GetEAa;Bit32u id=Fetchd();
switch (rm & 0x38) { switch (rm & 0x38) {
case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break; case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break;
case 0x08: ORD(eaa,id,LoadMd,SaveMd);break; case 0x08: ORD(eaa,id,LoadMd,SaveMd);break;
@ -232,14 +243,13 @@ switch(Fetchb()) {
break; break;
case 0x85: /* TEST Ed,Gd */ case 0x85: /* TEST Ed,Gd */
RMEdGd(TESTD);break; RMEdGd(TESTD);break;
case 0x8f: /* POP Ed */ case 0x87: /* XCHG Ev,Gv */
{ {
GetRM; GetRMrd;Bit32u oldrmrd=*rmrd;
if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();} if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard=oldrmrd;}
else {GetEAa;SaveMd(eaa,Pop_32());} else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,oldrmrd);}
break; break;
} }
case 0x89: /* MOV Ed,Gd */ case 0x89: /* MOV Ed,Gd */
{ {
GetRMrd; GetRMrd;
@ -247,10 +257,6 @@ switch(Fetchb()) {
else {GetEAa;SaveMd(eaa,*rmrd);} else {GetEAa;SaveMd(eaa,*rmrd);}
break; break;
} }
case 0x99: /* CDQ */
if (reg_eax & 0x80000000) reg_edx=0xffffffff;
else reg_edx=0;
break;
case 0x8b: /* MOV Gd,Ed */ case 0x8b: /* MOV Gd,Ed */
{ {
GetRMrd; GetRMrd;
@ -261,6 +267,42 @@ switch(Fetchb()) {
case 0x8c: case 0x8c:
LOG_WARN("CPU:66:8c looped back"); LOG_WARN("CPU:66:8c looped back");
break; break;
case 0x8f: /* POP Ed */
{
GetRM;
if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();}
else {GetEAa;SaveMd(eaa,Pop_32());}
break;
}
case 0x90: /* NOP */
break;
case 0x91: /* XCHG CX,AX */
{ Bit32u temp=reg_eax;reg_eax=reg_ecx;reg_ecx=temp; }
break;
case 0x92: /* XCHG DX,AX */
{ Bit32u temp=reg_eax;reg_eax=reg_edx;reg_edx=temp; }
break;
case 0x93: /* XCHG BX,AX */
{ Bit32u temp=reg_eax;reg_eax=reg_ebx;reg_ebx=temp; }
break;
case 0x94: /* XCHG SP,AX */
{ Bit32u temp=reg_eax;reg_eax=reg_esp;reg_esp=temp; }
break;
case 0x95: /* XCHG BP,AX */
{ Bit32u temp=reg_eax;reg_eax=reg_ebp;reg_ebp=temp; }
break;
case 0x96: /* XCHG SI,AX */
{ Bit32u temp=reg_eax;reg_eax=reg_esi;reg_esi=temp; }
break;
case 0x97: /* XCHG DI,AX */
{ Bit32u temp=reg_eax;reg_eax=reg_edi;reg_edi=temp; }
break;
case 0x98: /* CWD */
reg_eax=(Bit16s)reg_ax;break;
case 0x99: /* CDQ */
if (reg_eax & 0x80000000) reg_edx=0xffffffff;
else reg_edx=0;
break;
case 0x9c: /* PUSHFD */ case 0x9c: /* PUSHFD */
{ {
Bit32u pflags= Bit32u pflags=
@ -296,6 +338,9 @@ switch(Fetchb()) {
else { reg_si+=4;reg_di+=4;} else { reg_si+=4;reg_di+=4;}
} }
break; break;
case 0xa9: /* TEST EAX,Id */
EAXId(TESTD);
break;
case 0xab: /* STOSD */ case 0xab: /* STOSD */
{ {
stringDI; stringDI;
@ -349,6 +394,14 @@ switch(Fetchb()) {
GRP2D(1);break; GRP2D(1);break;
case 0xd3: /* GRP2 Ed,CL */ case 0xd3: /* GRP2 Ed,CL */
GRP2D(reg_cl);break; GRP2D(reg_cl);break;
case 0xf2: /* REPNZ */
prefix.count++;
count-=Repeat_Normal(false,true,count);
break;
case 0xf3: /* REPZ */
prefix.count++;
count-=Repeat_Normal(true,true,count);
break;
case 0xf7: /* GRP3 Ed(,Id) */ case 0xf7: /* GRP3 Ed(,Id) */
{ {
union { Bit64u u;Bit64s s;} temp; union { Bit64u u;Bit64s s;} temp;
@ -441,12 +494,12 @@ switch(Fetchb()) {
{ {
GetRM; GetRM;
switch (rm & 0x38) { switch (rm & 0x38) {
case 0x00: /* INC Ew */ case 0x00: /* INC Ed */
flags.cf=get_CF();flags.type=t_INCd; flags.cf=get_CF();flags.type=t_INCd;
if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard+=1;} if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard+=1;}
else {GetEAa;flags.result.d=LoadMd(eaa)+1;SaveMd(eaa,flags.result.d);} else {GetEAa;flags.result.d=LoadMd(eaa)+1;SaveMd(eaa,flags.result.d);}
break; break;
case 0x08: /* DEC Ew */ case 0x08: /* DEC Ed */
flags.cf=get_CF();flags.type=t_DECd; flags.cf=get_CF();flags.type=t_DECd;
if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard-=1;} if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard-=1;}
else {GetEAa;flags.result.d=LoadMd(eaa)-1;SaveMd(eaa,flags.result.d);} else {GetEAa;flags.result.d=LoadMd(eaa)-1;SaveMd(eaa,flags.result.d);}

View File

@ -79,6 +79,8 @@ switch (Fetchb()) {
if (flags.cf) *eard&=~mask; if (flags.cf) *eard&=~mask;
else *eard|=mask; else *eard|=mask;
break; break;
default:
E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38);
} }
} else { } else {
GetEAa;Bit32u old=LoadMd(eaa); GetEAa;Bit32u old=LoadMd(eaa);
@ -98,6 +100,8 @@ switch (Fetchb()) {
else old|=mask; else old|=mask;
SaveMd(eaa,old); SaveMd(eaa,old);
break; break;
default:
E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38);
} }
} }
if (flags.type!=t_CF) flags.prev_type=flags.type; if (flags.type!=t_CF) flags.prev_type=flags.type;

View File

@ -314,6 +314,8 @@ switch(Fetchb()) {
case 0x38: /* BTC */ case 0x38: /* BTC */
*earw^=mask; *earw^=mask;
break; break;
default:
E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38);
} }
} else { } else {
GetEAa;Bit16u old=LoadMw(eaa); GetEAa;Bit16u old=LoadMw(eaa);
@ -330,6 +332,8 @@ switch(Fetchb()) {
case 0x38: /* BTC */ case 0x38: /* BTC */
SaveMw(eaa,old ^ mask); SaveMw(eaa,old ^ mask);
break; break;
default:
E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38);
} }
} }
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; } if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }

View File

@ -88,8 +88,8 @@ static INLINE Bit32u Pop_32() {
#define stringSI \ #define stringSI \
EAPoint from; \ EAPoint from; \
if (prefixes & PREFIX_SEG) { \ if (prefix.mark & PREFIX_SEG) { \
from=(segprefix_base+reg_si); \ from=(prefix.segbase+reg_si); \
PrefixReset; \ PrefixReset; \
} else { \ } else { \
from=SegBase(ds)+reg_si; \ from=SegBase(ds)+reg_si; \
@ -102,48 +102,265 @@ static INLINE Bit32u Pop_32() {
#include "instructions.h" #include "instructions.h"
static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) { static Bits Repeat_Normal(bool testz,bool prefix_66,Bits count_remain) {
bool again;
do { Bits count=count_remain;
again=false; PhysPt base_si,base_di;
Bit8u repcode=Fetchb();
switch (repcode) { Bit16s direct;
if (flags.df) direct=-1;
else direct=1;
base_di=SegBase(es);
rep_again:
if (prefix.mark & PREFIX_SEG) {
base_si=(prefix.segbase);
} else {
base_si=SegBase(ds);
}
switch (Fetchb()) {
case 0x26: /* ES Prefix */ case 0x26: /* ES Prefix */
again=true; prefix.segbase=SegBase(es);
from=SegBase(es); prefix.mark|=PREFIX_SEG;
break; prefix.count++;
goto rep_again;
case 0x2e: /* CS Prefix */ case 0x2e: /* CS Prefix */
again=true; prefix.segbase=SegBase(cs);
from=SegBase(cs); prefix.mark|=PREFIX_SEG;
break; prefix.count++;
goto rep_again;
case 0x36: /* SS Prefix */ case 0x36: /* SS Prefix */
again=true; prefix.segbase=SegBase(ss);
from=SegBase(ss); prefix.mark|=PREFIX_SEG;
break; prefix.count++;
goto rep_again;
case 0x3e: /* DS Prefix */ case 0x3e: /* DS Prefix */
again=true; prefix.segbase=SegBase(ds);
from=SegBase(ds); prefix.mark|=PREFIX_SEG;
prefix.count++;
goto rep_again;
case 0x66: /* Size Prefix */
prefix.count++;
prefix_66=!prefix_66;
goto rep_again;
case 0x6c: /* REP INSB */
for (;(reg_cx && count>0);reg_cx--,count--) {
SaveMb(base_di+reg_di,IO_Read(reg_dx));
reg_di+=direct;
}
if (reg_cx && count<=0) goto countzero;
break; break;
case 0xa5: /* REP MOVSD */ case 0x6d: /* REP INSW/D */
for (;reg_cx>0;reg_cx--) { if (prefix_66) {
SaveMd(to+reg_di,LoadMd(from+reg_si)); direct*=4;
reg_di+=direct*4; for (;(reg_cx && count>0);reg_cx--,count--) {
reg_si+=direct*4; SaveMb(base_di+reg_di+0,IO_Read(reg_dx+0));
SaveMb(base_di+reg_di+1,IO_Read(reg_dx+1));
SaveMb(base_di+reg_di+2,IO_Read(reg_dx+2));
SaveMb(base_di+reg_di+3,IO_Read(reg_dx+3));
reg_di+=direct;
}
} else {
direct*=2;
for (;(reg_cx && count>0);reg_cx--,count--) {
SaveMb(base_di+reg_di+0,IO_Read(reg_dx+0));
SaveMb(base_di+reg_di+1,IO_Read(reg_dx+1));
reg_di+=direct;
}
}
if (reg_cx && count<=0) goto countzero;
break;
case 0x6e: /* REP OUTSB */
for (;(reg_cx && count>0);reg_cx--,count--) {
IO_Write(reg_dx,LoadMb(base_si+reg_si));
reg_si+=direct;
}
if (reg_cx && count<=0) goto countzero;
break;
case 0x6f: /* REP OUTSW/D */
if (prefix_66) {
direct*=4;
for (;(reg_cx && count>0);reg_cx--,count--) {
IO_Write(reg_dx+0,LoadMb(base_si+reg_si+0));
IO_Write(reg_dx+1,LoadMb(base_si+reg_si+1));
IO_Write(reg_dx+2,LoadMb(base_si+reg_si+2));
IO_Write(reg_dx+3,LoadMb(base_si+reg_si+3));
reg_si+=direct;
}
} else {
direct*=2;
for (;(reg_cx && count>0);reg_cx--,count--) {
IO_Write(reg_dx+0,LoadMb(base_si+reg_si+0));
IO_Write(reg_dx+1,LoadMb(base_si+reg_si+1));
reg_si+=direct;
}
}
if (reg_cx && count<=0) goto countzero;
break;
case 0xa4: /* REP MOVSB */
for (;(reg_cx && count>0);reg_cx--,count--) {
SaveMb(base_di+reg_di,LoadMb(base_si+reg_si));
reg_si+=direct;reg_di+=direct;
}
if (reg_cx && count<=0) goto countzero;
break;
case 0xa5: /* REP MOVSW/D */
if (prefix_66) {
direct*=4;
for (;(reg_cx && count>0);reg_cx--,count--) {
SaveMd(base_di+reg_di,LoadMd(base_si+reg_si));
reg_si+=direct;reg_di+=direct;
}
} else {
direct*=2;
for (;(reg_cx && count>0);reg_cx--,count--) {
SaveMw(base_di+reg_di,LoadMw(base_si+reg_si));
reg_si+=direct;reg_di+=direct;
}
}
if (reg_cx && count<=0) goto countzero;
break;
case 0xa6: /* REP CMPSB */
{
if (!reg_cx) goto stopit;Bit8u op1,op2;
for (;(reg_cx && count>0);) {
op1=LoadMb(base_si+reg_si);op2=LoadMb(base_di+reg_di);
reg_cx--,count--;reg_si+=direct;reg_di+=direct;
if ((op1==op2)!=testz) break;
}
CMPB(op1,op2,LoadRb,0);
if ((op1==op2)!=testz) goto stopit;
if (reg_cx && count<=0) goto countzero;
} }
break; break;
case 0xa7: /* REP CMPSW */
{
if (!reg_cx) goto stopit;
if (prefix_66) {
direct*=4;
Bit32u op1,op2;
for (;(reg_cx && count>0);) {
op1=LoadMd(base_si+reg_si);op2=LoadMd(base_di+reg_di);
reg_cx--,count--;reg_si+=direct;reg_di+=direct;
if ((op1==op2)!=testz) break;
}
CMPD(op1,op2,LoadRd,0);
if ((op1==op2)!=testz) goto stopit;
} else {
direct*=2;
Bit16u op1,op2;
for (;(reg_cx && count>0);) {
op1=LoadMw(base_si+reg_si);op2=LoadMw(base_di+reg_di);
reg_cx--,count--;reg_si+=direct;reg_di+=direct;
if ((op1==op2)!=testz) break;
}
CMPW(op1,op2,LoadRw,0);
if ((op1==op2)!=testz) goto stopit;
}
if (reg_cx && count<=0) goto countzero;
}
break;
case 0xaa: /* REP STOSB */
for (;(reg_cx && count>0);reg_cx--,count--) {
SaveMb(base_di+reg_di,reg_al);
reg_di+=direct;
}
if (reg_cx && count<=0) goto countzero;
break;
case 0xab: /* REP STOSW */ case 0xab: /* REP STOSW */
for (;reg_cx>0;reg_cx--) { if (prefix_66) {
SaveMd(to+reg_di,reg_eax); direct*=4;
reg_di+=direct*4; for (;(reg_cx && count>0);reg_cx--,count--) {
SaveMd(base_di+reg_di,reg_eax);
reg_di+=direct;
}
} else {
direct*=2;
for (;(reg_cx && count>0);reg_cx--,count--) {
SaveMw(base_di+reg_di,reg_ax);
reg_di+=direct;
}
}
if (reg_cx && count<=0) goto countzero;
break;
case 0xac: /* REP LODSB */
for (;(reg_cx && count>0);reg_cx--,count--) {
reg_al=LoadMb(base_si+reg_si);
reg_si+=direct;
}
if (reg_cx && count<=0) goto countzero;
break;
case 0xad: /* REP LODSW */
if (prefix_66) {
direct*=4;
for (;(reg_cx && count>0);reg_cx--,count--) {
reg_eax=LoadMd(base_si+reg_si);
reg_si+=direct;
}
} else {
direct*=2;
for (;(reg_cx && count>0);reg_cx--,count--) {
reg_ax=LoadMw(base_si+reg_si);
reg_si+=direct;
}
}
if (reg_cx && count<=0) goto countzero;
break;
case 0xae: /* REP SCASB */
{
if (!reg_cx) goto stopit;Bit8u op2;
for (;(reg_cx && count>0);) {
op2=LoadMb(base_di+reg_di);
reg_cx--,count--;reg_di+=direct;
if ((reg_al==op2)!=testz) break;
}
CMPB(reg_al,op2,LoadRb,0);
if ((reg_al==op2)!=testz) goto stopit;
if (reg_cx && count<=0) goto countzero;
}
break;
case 0xaf: /* REP SCASW */
{
if (!reg_cx) goto stopit;
if (prefix_66) {
direct*=4;
Bit32u op2;
for (;(reg_cx && count>0);) {
op2=LoadMd(base_di+reg_di);
reg_cx--,count--;reg_di+=direct;
if ((reg_eax==op2)!=testz) break;
}
CMPD(reg_eax,op2,LoadRd,0);
if ((reg_eax==op2)!=testz) goto stopit;
} else {
direct*=2;
Bit16u op2;
for (;(reg_cx && count>0);) {
op2=LoadMw(base_di+reg_di);
reg_cx--,count--;reg_di+=direct;
if ((reg_ax==op2)!=testz) break;
}
CMPW(reg_ax,op2,LoadRw,0);
if ((reg_ax==op2)!=testz) goto stopit;
}
if (reg_cx && count<=0) goto countzero;
} }
break; break;
default: default:
E_Exit("CPU:Opcode 66:Illegal REP prefix %2X",repcode); IPPoint--;
LOG_DEBUG("Unhandled REP Prefix %X",Fetchb());
} }
} while (again); stopit:
PrefixReset;
return count_remain-count;
countzero:
IPPoint-=(prefix.count+2); /* Rep instruction and whatever string instruction */
PrefixReset;
return count_remain;
} }
//flags.io and nt shouldn't be compiled for 386 //flags.io and nt shouldn't be compiled for 386
#ifdef CPU_386
#define Save_Flagsw(FLAGW) \ #define Save_Flagsw(FLAGW) \
{ \ { \
flags.type=t_UNKNOWN; \ flags.type=t_UNKNOWN; \
@ -159,7 +376,25 @@ static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) {
PIC_runIRQs(); \ PIC_runIRQs(); \
LOADIP; \ LOADIP; \
} \ } \
if (flags.tf) E_Exit("CPU:Trap Flag not supported"); \ if (flags.tf) LOG_DEBUG("CPU:Trap Flag not supported"); \
} }
#else
#define Save_Flagsw(FLAGW) \
{ \
flags.type=t_UNKNOWN; \
flags.cf =(FLAGW & 0x001)>0;flags.pf =(FLAGW & 0x004)>0; \
flags.af =(FLAGW & 0x010)>0;flags.zf =(FLAGW & 0x040)>0; \
flags.sf =(FLAGW & 0x080)>0;flags.tf =(FLAGW & 0x100)>0; \
flags.intf =(FLAGW & 0x200)>0; \
flags.df =(FLAGW & 0x400)>0;flags.of =(FLAGW & 0x800)>0; \
if (flags.intf && PIC_IRQCheck) { \
SAVEIP; \
PIC_runIRQs(); \
LOADIP; \
} \
if (flags.tf) LOG_DEBUG("CPU:Trap Flag not supported"); \
}
#endif

View File

@ -26,38 +26,56 @@ static GetEATable * lookupEATable;
#define PREFIX_ADDR 0x2 #define PREFIX_ADDR 0x2
#define PREFIX_SEG_ADDR 0x3 #define PREFIX_SEG_ADDR 0x3
static struct {
static Bitu prefixes; Bitu mark;
static EAPoint segprefix_base; Bitu count;
EAPoint segbase;
} prefix;
/* Gets initialized at the bottem, can't seem to declare forward references */ /* Gets initialized at the bottem, can't seem to declare forward references */
static GetEATable * EAPrefixTable[4]; static GetEATable * EAPrefixTable[4];
#define SegPrefix(blah) \ #define SegPrefix(blah) \
segprefix_base=SegBase(blah); \ prefix.segbase=SegBase(blah); \
prefixes|=PREFIX_SEG; \ prefix.mark|=PREFIX_SEG; \
lookupEATable=EAPrefixTable[prefixes]; \ prefix.count++; \
goto restart; \ lookupEATable=EAPrefixTable[prefix.mark]; \
goto restart;
#define SegPrefix_66(blah) \ #define SegPrefix_66(blah) \
segprefix_base=SegBase(blah); \ prefix.segbase=SegBase(blah); \
prefixes|=PREFIX_SEG; \ prefix.mark|=PREFIX_SEG; \
lookupEATable=EAPrefixTable[prefixes]; \ prefix.count++; \
goto restart_66; \ lookupEATable=EAPrefixTable[prefix.mark]; \
goto restart_66;
#define PrefixReset \ #define PrefixReset \
prefixes=PREFIX_NONE;lookupEATable=EAPrefixTable[PREFIX_NONE]; prefix.mark=PREFIX_NONE; \
prefix.count=0; \
lookupEATable=EAPrefixTable[PREFIX_NONE];
#if 1
#define GetEADirect \ #define GetEADirect \
EAPoint eaa;switch (prefixes) { \ EAPoint eaa;switch (prefix.mark) { \
case PREFIX_NONE:eaa=SegBase(ds)+Fetchw();break; \ case PREFIX_NONE:eaa=SegBase(ds)+Fetchw();break; \
case PREFIX_SEG:eaa=segprefix_base+Fetchw();PrefixReset;break; \ case PREFIX_SEG:eaa=prefix.segbase+Fetchw();PrefixReset;break; \
case PREFIX_ADDR:eaa=SegBase(ds)+Fetchd();PrefixReset;break; \ case PREFIX_ADDR:eaa=SegBase(ds)+Fetchd();PrefixReset;break; \
case PREFIX_SEG_ADDR:eaa=segprefix_base+Fetchd();PrefixReset;break; \ case PREFIX_SEG_ADDR:eaa=prefix.segbase+Fetchd();PrefixReset;break; \
} }
#else
#define GetEADirect \
EAPoint eaa; \
if (!prefix.mark) { eaa=SegBase(ds)+Fetchw();} \
else if (prefix.mark == PREFIX_SEG) { eaa=prefix.segbase+Fetchw();PrefixReset;} \
else if (prefix.mark == PREFIX_ADDR) { eaa=SegBase(ds)+Fetchd();PrefixReset;} \
else if (prefix.mark == PREFIX_SEG_ADDR) { eaa=prefix.segbase+Fetchd();PrefixReset;}
#endif
@ -125,7 +143,7 @@ static GetEATable GetEA_16_n={
}; };
#define segprefixed(val) EAPoint ret=segprefix_base+val;PrefixReset;return ret; #define segprefixed(val) EAPoint ret=prefix.segbase+val;PrefixReset;return ret;
static EAPoint EA_16_00_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) } static EAPoint EA_16_00_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_si)) }
static EAPoint EA_16_01_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) } static EAPoint EA_16_01_s(void) { segprefixed((Bit16u)(reg_bx+(Bit16s)reg_di)) }
@ -189,6 +207,8 @@ static GetEATable GetEA_16_s={
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; };
static Bit32u SIBZero=0;
static Bit32u * SIBIndex[8]= { &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&SIBZero,&reg_ebp,&reg_esi,&reg_edi };
INLINE EAPoint Sib(Bitu mode) { INLINE EAPoint Sib(Bitu mode) {
Bit8u sib=Fetchb(); Bit8u sib=Fetchb();
@ -203,7 +223,7 @@ INLINE EAPoint Sib(Bitu mode) {
case 3: /* EBX Base */ case 3: /* EBX Base */
base=SegBase(ds)+reg_ebx;break; base=SegBase(ds)+reg_ebx;break;
case 4: /* ESP Base */ case 4: /* ESP Base */
base=SegBase(ds)+reg_esp;break; base=SegBase(ss)+reg_esp;break;
case 5: /* #1 Base */ case 5: /* #1 Base */
if (!mode) { if (!mode) {
base=SegBase(ds)+Fetchd();break; base=SegBase(ds)+Fetchd();break;
@ -215,25 +235,7 @@ INLINE EAPoint Sib(Bitu mode) {
case 7: /* EDI Base */ case 7: /* EDI Base */
base=SegBase(ds)+reg_edi;break; base=SegBase(ds)+reg_edi;break;
} }
Bitu shift=sib >> 6; base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
switch ((sib >>3) &7) {
case 0: /* EAX Index */
base+=(Bit32s)reg_eax<<shift;break;
case 1: /* ECX Index */
base+=(Bit32s)reg_ecx<<shift;break;
case 2: /* EDX Index */
base+=(Bit32s)reg_edx<<shift;break;
case 3: /* EBX Index */
base+=(Bit32s)reg_ebx<<shift;break;
case 4: /* None */
break;
case 5: /* EBP Index */
base+=(Bit32s)reg_ebp<<shift;break;
case 6: /* ESI Index */
base+=(Bit32s)reg_esi<<shift;break;
case 7: /* EDI Index */
base+=(Bit32s)reg_edi<<shift;break;
};
return base; return base;
}; };
@ -305,50 +307,31 @@ INLINE EAPoint Sib_s(Bitu mode) {
EAPoint base; EAPoint base;
switch (sib&7) { switch (sib&7) {
case 0: /* EAX Base */ case 0: /* EAX Base */
base=segprefix_base+reg_eax;break; base=prefix.segbase+reg_eax;break;
case 1: /* ECX Base */ case 1: /* ECX Base */
base=segprefix_base+reg_ecx;break; base=prefix.segbase+reg_ecx;break;
case 2: /* EDX Base */ case 2: /* EDX Base */
base=segprefix_base+reg_edx;break; base=prefix.segbase+reg_edx;break;
case 3: /* EBX Base */ case 3: /* EBX Base */
base=segprefix_base+reg_ebx;break; base=prefix.segbase+reg_ebx;break;
case 4: /* ESP Base */ case 4: /* ESP Base */
base=segprefix_base+reg_esp;break; base=prefix.segbase+reg_esp;break;
case 5: /* #1 Base */ case 5: /* #1 Base */
if (!mode) { if (!mode) {
base=segprefix_base+Fetchd();break; base=prefix.segbase+Fetchd();break;
} else { } else {
base=segprefix_base+reg_ebp;break; base=prefix.segbase+reg_ebp;break;
} }
case 6: /* ESI Base */ case 6: /* ESI Base */
base=segprefix_base+reg_esi;break; base=prefix.segbase+reg_esi;break;
case 7: /* EDI Base */ case 7: /* EDI Base */
base=segprefix_base+reg_edi;break; base=prefix.segbase+reg_edi;break;
} }
Bitu shift=sib >> 6; base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); PrefixReset;
switch ((sib >>3) &7) {
case 0: /* EAX Index */
base+=(Bit32s)reg_eax<<shift;break;
case 1: /* ECX Index */
base+=(Bit32s)reg_ecx<<shift;break;
case 2: /* EDX Index */
base+=(Bit32s)reg_edx<<shift;break;
case 3: /* EBX Index */
base+=(Bit32s)reg_ebx<<shift;break;
case 4: /* None */
break;
case 5: /* EBP Index */
base+=(Bit32s)reg_ebp<<shift;break;
case 6: /* ESI Index */
base+=(Bit32s)reg_esi<<shift;break;
case 7: /* EDI Index */
base+=(Bit32s)reg_edi<<shift;break;
};
PrefixReset;
return base; return base;
}; };
#define segprefixed_32(val) EAPoint ret=segprefix_base+(Bit32u)(val);PrefixReset;return ret; #define segprefixed_32(val) EAPoint ret=prefix.segbase+(Bit32u)(val);PrefixReset;return ret;
static EAPoint EA_32_00_s(void) { segprefixed_32(reg_eax); } static EAPoint EA_32_00_s(void) { segprefixed_32(reg_eax); }
static EAPoint EA_32_01_s(void) { segprefixed_32(reg_ecx); } static EAPoint EA_32_01_s(void) { segprefixed_32(reg_ecx); }

View File

@ -21,6 +21,7 @@
#include "memory.h" #include "memory.h"
#include "debug.h" #include "debug.h"
#include "keyboard.h" #include "keyboard.h"
#include "setup.h"
//Regs regs; //Regs regs;
@ -28,27 +29,22 @@ Flag_Info flags;
CPU_Regs cpu_regs; CPU_Regs cpu_regs;
Segment Segs[6]; Segment Segs[6];
Bit32u cpu_cycles; Bitu cpu_cycles;
CPU_Decoder * cpudecoder; CPU_Decoder * cpudecoder;
static void CPU_CycleIncrease(void) { static void CPU_CycleIncrease(void) {
Bit32u old_cycles=cpu_cycles; Bitu old_cycles=cpu_cycles;
cpu_cycles=(Bit32u)(cpu_cycles*1.2); cpu_cycles=(Bitu)(cpu_cycles*1.2);
if (cpu_cycles==old_cycles) cpu_cycles++; if (cpu_cycles==old_cycles) cpu_cycles++;
LOG_MSG("CPU:%d cycles",cpu_cycles); LOG_MSG("CPU:%d cycles",cpu_cycles);
} }
static void CPU_CycleDecrease(void) { static void CPU_CycleDecrease(void) {
cpu_cycles=(Bit32u)(cpu_cycles/1.2); cpu_cycles=(Bitu)(cpu_cycles/1.2);
if (!cpu_cycles) cpu_cycles=1; if (!cpu_cycles) cpu_cycles=1;
LOG_MSG("CPU:%d cycles",cpu_cycles); LOG_MSG("CPU:%d cycles",cpu_cycles);
} }
Bit8u lastint; Bit8u lastint;
@ -87,7 +83,7 @@ void Interrupt(Bit8u num) {
E_Exit("Call to interrupt 0xCD this is BAD"); E_Exit("Call to interrupt 0xCD this is BAD");
case 0x03: case 0x03:
#if C_DEBUG #if C_DEBUG
if (DEBUG_BreakPoint()) return; if (DEBUG_Breakpoint()) return;
#endif #endif
break; break;
case 0x05: case 0x05:
@ -137,7 +133,8 @@ void SetCPU16bit()
} }
void CPU_Init(void) { void CPU_Init(Section* sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
reg_eax=0; reg_eax=0;
reg_ebx=0; reg_ebx=0;
reg_ecx=0; reg_ecx=0;
@ -166,11 +163,13 @@ void CPU_Init(void) {
flags.io=0; flags.io=0;
SetCPU16bit(); SetCPU16bit();
cpu_cycles=2000; cpu_cycles=section->Get_int("cycles");
if (!cpu_cycles) cpu_cycles=300;
KEYBOARD_AddEvent(KBD_f11,CTRL_PRESSED,CPU_CycleDecrease); KEYBOARD_AddEvent(KBD_f11,CTRL_PRESSED,CPU_CycleDecrease);
KEYBOARD_AddEvent(KBD_f12,CTRL_PRESSED,CPU_CycleIncrease); KEYBOARD_AddEvent(KBD_f12,CTRL_PRESSED,CPU_CycleIncrease);
reg_al=0; reg_al=0;
reg_ah=0; reg_ah=0;
MSG_Add("CPU_CONFIGFILE_HELP","The amount of cycles to execute each loop. Lowering this setting will slowdown dosbox\n");
} }

View File

@ -61,20 +61,24 @@ extern Bitu cycle_count;
#include "core_16/support.h" #include "core_16/support.h"
static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count); static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count);
static Bitu CPU_Real_16_Slow_Decode(Bitu count) {
static Bitu CPU_Real_16_Slow_Decode(Bits count) {
#include "core_16/start.h" #include "core_16/start.h"
while (count) { do {
#if C_DEBUG #if C_DEBUG
cycle_count++; cycle_count++;
#endif #endif
count--; #if C_HEAVY_DEBUG
SAVEIP;
if (DEBUG_HeavyIsBreakpoint()) return CBRET_NONE;
#endif
#include "core_16/main.h" #include "core_16/main.h"
} } while (--count>0);
#include "core_16/stop.h" #include "core_16/stop.h"
return CBRET_NONE; return CBRET_NONE;
} }
static Bitu CPU_Real_16_Slow_Decode_Special(Bitu count) { static Bitu CPU_Real_16_Slow_Decode_Special(Bits count) {
while (count>0) { while (count>0) {
if (flags.tf) { if (flags.tf) {
Interrupt(3); Interrupt(3);

View File

@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include "programs.h"
#include <string.h> #include <string.h>
#include <list> #include <list>
@ -32,16 +33,27 @@
#include "inout.h" #include "inout.h"
#include "mixer.h" #include "mixer.h"
#include "debug_inc.h" #include "debug_inc.h"
#include "timer.h"
#include "..\shell\shell_inc.h"
#ifdef WIN32 #ifdef WIN32
void WIN32_Console(); void WIN32_Console();
#endif #endif
// Forwards
static void DrawCode(void);
static bool DEBUG_Log_Loop(int count);
static void DEBUG_RaiseTimerIrq(void);
class DEBUG;
DEBUG* pDebugcom = 0;
bool exitLoop = false;
static struct { static struct {
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip; Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
} oldregs; } oldregs;
static void DrawCode(void);
static Segment oldsegs[6]; static Segment oldsegs[6];
static Flag_Info oldflags; static Flag_Info oldflags;
@ -77,127 +89,318 @@ static Bit16u dataSeg,dataOfs;
/* Breakpoint stuff */ /* Breakpoint stuff */
/********************/ /********************/
enum { BKPNT_REALMODE, BKPNT_PHYSICAL, BKPNT_INTERRUPT }; bool skipFirstInstruction = false;
enum EBreakpoint { BKPNT_UNKNOWN, BKPNT_PHYSICAL, BKPNT_INTERRUPT };
#define BPINT_ALL 0x100 #define BPINT_ALL 0x100
typedef struct SBreakPoint { class CBreakpoint
{
public:
CBreakpoint (void) { location = 0; active = once = false; segment = 0; offset = 0; intNr = 0; ahValue = 0; type = BKPNT_UNKNOWN; };
void SetAddress (Bit16u seg, Bit32u off) { location = PhysMake(seg,off); type = BKPNT_PHYSICAL; segment = seg; offset = off; };
void SetAddress (PhysPt adr) { location = adr; type = BKPNT_PHYSICAL; };
void SetInt (Bit8u _intNr, Bit16u ah) { intNr = _intNr, ahValue = ah; type = BKPNT_INTERRUPT; };
void SetOnce (bool _once) { once = _once; };
bool IsActive (void) { return active; };
void Activate (bool _active);
EBreakpoint GetType (void) { return type; };
bool GetOnce (void) { return once; };
PhysPt GetLocation (void) { if (GetType()==BKPNT_PHYSICAL) return location; else return 0; };
Bit16u GetSegment (void) { return segment; };
Bit32u GetOffset (void) { return offset; };
Bit8u GetIntNr (void) { if (GetType()==BKPNT_INTERRUPT) return intNr; else return 0; };
Bit16u GetValue (void) { if (GetType()==BKPNT_INTERRUPT) return ahValue; else return 0; };
// statics
static CBreakpoint* AddBreakpoint (Bit16u seg, Bit32u off, bool once);
static CBreakpoint* AddIntBreakpoint (Bit8u intNum, Bit16u ah, bool once);
static void ActivateBreakpoints (PhysPt adr, bool activate);
static bool CheckBreakpoint (PhysPt adr);
static bool CheckIntBreakpoint (PhysPt adr, Bit8u intNr, Bit16u ahValue);
static bool IsBreakpoint (PhysPt where);
static bool IsBreakpointDrawn (PhysPt where);
static bool DeleteBreakpoint (PhysPt where);
static bool DeleteByIndex (Bit16u index);
static void DeleteAll (void);
static void ShowList (void);
private:
EBreakpoint type;
// Physical
PhysPt location; PhysPt location;
Bit8u olddata; Bit8u oldData;
Bit8u type;
Bit16u ahValue;
Bit16u segment; Bit16u segment;
Bit32u offset; Bit32u offset;
bool once; // Int
bool enabled; Bit8u intNr;
Bit16u ahValue;
// Shared
bool active; bool active;
} TBreakpoint; bool once;
static std::list<TBreakpoint> BPoints; static std::list<CBreakpoint*> BPoints;
static CBreakpoint* ignoreOnce;
static bool IsBreakpoint(PhysPt off)
{
// iterate list and remove TBreakpoint
std::list<TBreakpoint>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
if (((*i).type==BKPNT_PHYSICAL) && ((*i).location==off)) return true;
}
return false;
}; };
/* This clears all breakpoints by replacing their 0xcc by the original byte */ void CBreakpoint::Activate(bool _active)
static void ClearBreakpoints(void)
{ {
// iterate list and place 0xCC if (GetType()==BKPNT_PHYSICAL) {
std::list<TBreakpoint>::iterator i; #if !C_HEAVY_DEBUG
for(i=BPoints.begin(); i != BPoints.end(); i++) { if (_active) {
if (((*i).type==BKPNT_PHYSICAL) && (*i).active) { // Set 0xCC and save old value
if (mem_readb((*i).location)==0xCC) mem_writeb((*i).location,(*i).olddata); Bit8u data = mem_readb(location);
(*i).active = false;
};
}
}
static void DeleteBreakpoint(PhysPt off)
{
// iterate list and place 0xCC
std::list<TBreakpoint>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
if (((*i).type==BKPNT_PHYSICAL) && (off==(*i).location)) {
if ((*i).active && (mem_readb((*i).location)==0xCC)) mem_writeb((*i).location,(*i).olddata);
(BPoints.erase)(i);
break;
};
}
}
static void SetBreakpoints(void)
{
// iterate list and place 0xCC
std::list<TBreakpoint>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
if (((*i).type==BKPNT_PHYSICAL) && (*i).enabled) {
Bit8u data = mem_readb((*i).location);
if (data!=0xCC) { if (data!=0xCC) {
(*i).olddata = data; oldData = data;
(*i).active = true; mem_writeb(location,0xCC);
mem_writeb((*i).location,0xCC); };
} } else {
// Remove 0xCC and set old value
if (mem_readb (location)==0xCC) {
mem_writeb(location,oldData);
}; };
} }
} #endif
}
static void AddBreakpoint(Bit16u seg, Bit32u ofs, bool once) active = _active;
{
TBreakpoint bp;
bp.type = BKPNT_PHYSICAL;
bp.enabled = true;
bp.active = false;
bp.location = PhysMake(seg,ofs);
bp.segment = seg;
bp.offset = ofs;
bp.once = once;
BPoints.push_front(bp);
}
static void AddIntBreakpoint(Bit8u intNum, Bit16u ah, bool once)
{
TBreakpoint bp;
bp.type = BKPNT_INTERRUPT;
bp.olddata = intNum;
bp.ahValue = ah;
bp.enabled = true;
bp.active = true;
bp.once = once;
BPoints.push_front(bp);
}; };
static bool RemoveBreakpoint(PhysPt off) // Statics
{ std::list<CBreakpoint*> CBreakpoint::BPoints;
// iterate list and remove TBreakpoint CBreakpoint* CBreakpoint::ignoreOnce = 0;
std::list<TBreakpoint>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
if (((*i).type==BKPNT_PHYSICAL) && ((*i).location==off)) {
TBreakpoint* bp = &(*i);
if ((*i).active && (mem_readb((*i).location)==0xCC)) mem_writeb((*i).location,(*i).olddata);
(*i).active = false;
if ((*i).once) (BPoints.erase)(i);
CBreakpoint* CBreakpoint::AddBreakpoint(Bit16u seg, Bit32u off, bool once)
{
CBreakpoint* bp = new CBreakpoint();
bp->SetAddress (seg,off);
bp->SetOnce (once);
BPoints.push_front (bp);
return bp;
};
CBreakpoint* CBreakpoint::AddIntBreakpoint(Bit8u intNum, Bit16u ah, bool once)
{
CBreakpoint* bp = new CBreakpoint();
bp->SetInt (intNum,ah);
bp->SetOnce (once);
BPoints.push_front (bp);
return bp;
};
void CBreakpoint::ActivateBreakpoints(PhysPt adr, bool activate)
{
ignoreOnce = 0;
// activate all breakpoints
std::list<CBreakpoint*>::iterator i;
CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
bp = static_cast<CBreakpoint*>(*i);
// Do not activate, when bp is an actual adress
if (activate && (bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
ignoreOnce = bp;
continue;
}
bp->Activate(activate);
};
};
bool CBreakpoint::CheckBreakpoint(PhysPt adr)
// Checks if breakpoint is valid an should stop execution
{
// if breakpoint is same address as started, it's not valid...
if (ignoreOnce) {
ignoreOnce->Activate(true);
ignoreOnce = 0;
}
// Search matching breakpoint
std::list<CBreakpoint*>::iterator i;
CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
bp = static_cast<CBreakpoint*>(*i);
if ((bp->GetType()==BKPNT_PHYSICAL) && bp->IsActive() && (bp->GetLocation()==adr)) {
// Found,
if (bp->GetOnce()) {
// delete it, if it should only be used once
(BPoints.erase)(i);
bp->Activate(false);
delete bp;
}
return true; return true;
}; };
} };
return false; return false;
}; };
bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue)
// Checks if interrupt breakpoint is valid an should stop execution
{
// if breakpoint is same address as started, it's not valid...
if (ignoreOnce) {
ignoreOnce->Activate(true);
ignoreOnce = 0;
}
// Search matching breakpoint
std::list<CBreakpoint*>::iterator i;
CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
bp = static_cast<CBreakpoint*>(*i);
if ((bp->GetType()==BKPNT_INTERRUPT) && bp->IsActive() && (bp->GetIntNr()==intNr)) {
if ((bp->GetValue()==BPINT_ALL) || (bp->GetValue()==ahValue)) {
// Found
if (bp->GetOnce()) {
// delete it, if it should only be used once
(BPoints.erase)(i);
bp->Activate(false);
delete bp;
}
return true;
}
};
};
return false;
};
void CBreakpoint::DeleteAll()
{
std::list<CBreakpoint*>::iterator i;
CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
bp = static_cast<CBreakpoint*>(*i);
bp->Activate(false);
delete bp;
};
(BPoints.clear)();
};
bool CBreakpoint::DeleteByIndex(Bit16u index)
{
// Search matching breakpoint
int nr = 0;
std::list<CBreakpoint*>::iterator i;
CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
if (nr==index) {
bp = static_cast<CBreakpoint*>(*i);
(BPoints.erase)(i);
bp->Activate(false);
delete bp;
return true;
}
};
return false;
};
bool CBreakpoint::DeleteBreakpoint(PhysPt where)
{
// Search matching breakpoint
int nr = 0;
std::list<CBreakpoint*>::iterator i;
CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
bp = static_cast<CBreakpoint*>(*i);
if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==where)) {
(BPoints.erase)(i);
bp->Activate(false);
delete bp;
return true;
}
};
return false;
};
bool CBreakpoint::IsBreakpoint(PhysPt adr)
// is there a breakpoint at address ?
{
// Search matching breakpoint
std::list<CBreakpoint*>::iterator i;
CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
bp = static_cast<CBreakpoint*>(*i);
if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
return true;
};
};
return false;
};
bool CBreakpoint::IsBreakpointDrawn(PhysPt adr)
// valid breakpoint, that should be drawn ?
{
// Search matching breakpoint
std::list<CBreakpoint*>::iterator i;
CBreakpoint* bp;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
bp = static_cast<CBreakpoint*>(*i);
if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
// Only draw, if breakpoint is not only once,
return !bp->GetOnce();
};
};
return false;
};
void CBreakpoint::ShowList(void)
{
// iterate list
int nr = 0;
std::list<CBreakpoint*>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
CBreakpoint* bp = static_cast<CBreakpoint*>(*i);
if (bp->GetType()==BKPNT_PHYSICAL) {
PhysPt adr = bp->GetLocation();
wprintw(dbg.win_out,"%02X. BP %04X:%04X\n",nr,bp->GetSegment(),bp->GetOffset);
nr++;
} else if (bp->GetType()==BKPNT_INTERRUPT) {
if (bp->GetValue()==BPINT_ALL) wprintw(dbg.win_out,"%02X. BPINT %02X\n",nr,bp->GetIntNr());
else wprintw(dbg.win_out,"%02X. BPINT %02X AH=%02X\n",nr,bp->GetIntNr(),bp->GetValue());
nr++;
};
}
wrefresh(dbg.win_out);
};
bool DEBUG_Breakpoint(void)
{
/* First get the phyiscal address and check for a set Breakpoint */
PhysPt where=SegPhys(cs)+reg_eip-1;
if (!CBreakpoint::CheckBreakpoint(where)) return false;
// Found. Breakpoint is valid
reg_eip -= 1;
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,false); // Deactivate all breakpoints
exitLoop = true;
DEBUG_Enable();
return true;
};
bool DEBUG_IntBreakpoint(Bit8u intNum)
{
/* First get the phyiscal address and check for a set Breakpoint */
PhysPt where=SegPhys(cs)+reg_eip-2;
if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false;
// Found. Breakpoint is valid
reg_eip -= 2;
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,false); // Deactivate all breakpoints
exitLoop = true;
DEBUG_Enable();
return true;
};
static bool StepOver() static bool StepOver()
{ {
PhysPt start=Segs[cs].phys+reg_eip; PhysPt start=Segs[cs].phys+reg_eip;
char dline[200];Bitu size; char dline[200];Bitu size;
size=DasmI386(dline, start, reg_eip, false); size=DasmI386(dline, start, reg_eip, false);
if (strstr(dline,"call") || strstr(dline,"int")) { if (strstr(dline,"call") || strstr(dline,"int") || strstr(dline,"loop") || strstr(dline,"rep")) {
AddBreakpoint (SegValue(cs),reg_eip+size, true); CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip+size, true);
SetBreakpoints(); CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip, true);
debugging=false; debugging=false;
DrawCode(); DrawCode();
DOSBOX_SetNormalLoop(); DOSBOX_SetNormalLoop();
@ -206,56 +409,13 @@ static bool StepOver()
return false; return false;
}; };
bool DEBUG_BreakPoint(void) { bool DEBUG_ExitLoop(void)
/* First get the phyiscal address and check for a set TBreakpoint */
PhysPt where=SegPhys(cs)+reg_eip-1;
bool found = false;
std::list<TBreakpoint>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); ++i) {
if ((*i).active && (*i).enabled) {
if ((*i).location==where) {
found=true;
break;
}
}
}
if (!found) return false;
RemoveBreakpoint(where);
ClearBreakpoints();
reg_eip -= 1;
DEBUG_Enable();
return true;
}
bool DEBUG_IntBreakpoint(Bit8u intNum)
{ {
PhysPt where=SegPhys(cs)+reg_eip-2; if (exitLoop) {
bool found=false; exitLoop = false;
std::list<TBreakpoint>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); ++i) {
if ( ((*i).type==BKPNT_INTERRUPT) && (*i).enabled) {
if (((*i).olddata==intNum) && ( ((*i).ahValue==(Bit16u)reg_ah) || ((*i).ahValue==BPINT_ALL)) ) {
if ((*i).active) {
found=true;
(*i).active=false;
//(BPoints.erase)(i);
//break;
} else {
// One step over is ok -> activate for next occurence
(*i).active=true;
//break;
}
}
}
}
if (!found) return false;
// Remove normal breakpoint here, cos otherwise 0xCC wont be removed here
RemoveBreakpoint(where);
ClearBreakpoints();
reg_eip -= 2;
DEBUG_Enable();
return true; return true;
}
return false;
}; };
/********************/ /********************/
@ -338,7 +498,7 @@ static void DrawCode(void)
wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY)); wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY));
codeViewData.cursorSeg = codeViewData.useCS; codeViewData.cursorSeg = codeViewData.useCS;
codeViewData.cursorOfs = disEIP; codeViewData.cursorOfs = disEIP;
} else if (IsBreakpoint(start)) { } else if (CBreakpoint::IsBreakpointDrawn(start)) {
wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED)); wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED));
} else { } else {
wattrset(dbg.win_code,0); wattrset(dbg.win_code,0);
@ -440,7 +600,7 @@ bool ParseCommand(char* str)
found+=3; found+=3;
Bit16u seg = GetHexValue(found,found);found++; // skip ":" Bit16u seg = GetHexValue(found,found);found++; // skip ":"
Bit32u ofs = GetHexValue(found,found); Bit32u ofs = GetHexValue(found,found);
AddBreakpoint(seg,ofs,false); CBreakpoint::AddBreakpoint(seg,ofs,false);
LOG_DEBUG("DEBUG: Set breakpoint at %04X:%04X",seg,ofs); LOG_DEBUG("DEBUG: Set breakpoint at %04X:%04X",seg,ofs);
return true; return true;
} }
@ -450,10 +610,10 @@ bool ParseCommand(char* str)
Bit8u intNr = GetHexValue(found,found); found++; Bit8u intNr = GetHexValue(found,found); found++;
Bit8u valAH = GetHexValue(found,found); Bit8u valAH = GetHexValue(found,found);
if ((valAH==0x00) && (*found=='*')) { if ((valAH==0x00) && (*found=='*')) {
AddIntBreakpoint(intNr,BPINT_ALL,false); CBreakpoint::AddIntBreakpoint(intNr,BPINT_ALL,false);
LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X",intNr); LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X",intNr);
} else { } else {
AddIntBreakpoint(intNr,valAH,false); CBreakpoint::AddIntBreakpoint(intNr,valAH,false);
LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH); LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH);
} }
return true; return true;
@ -463,19 +623,7 @@ bool ParseCommand(char* str)
wprintw(dbg.win_out,"Breakpoint list:\n"); wprintw(dbg.win_out,"Breakpoint list:\n");
wprintw(dbg.win_out,"-------------------------------------------------------------------------\n"); wprintw(dbg.win_out,"-------------------------------------------------------------------------\n");
Bit32u nr = 0; Bit32u nr = 0;
// iterate list CBreakpoint::ShowList();
std::list<TBreakpoint>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
if ((*i).type==BKPNT_PHYSICAL) {
wprintw(dbg.win_out,"%02X. BP %04X:%04X\n",nr,(*i).segment,(*i).offset);
nr++;
} else if ((*i).type==BKPNT_INTERRUPT) {
if ((*i).ahValue==BPINT_ALL) wprintw(dbg.win_out,"%02X. BPINT %02X\n",nr,(*i).olddata);
else wprintw(dbg.win_out,"%02X. BPINT %02X AH=%02X\n",nr,(*i).olddata,(*i).ahValue);
nr++;
};
}
wrefresh(dbg.win_out);
return true; return true;
}; };
@ -484,29 +632,11 @@ bool ParseCommand(char* str)
found+=5; found+=5;
Bit8u bpNr = GetHexValue(found,found); Bit8u bpNr = GetHexValue(found,found);
if ((bpNr==0x00) && (*found=='*')) { // Delete all if ((bpNr==0x00) && (*found=='*')) { // Delete all
(BPoints.clear)(); CBreakpoint::DeleteAll();
LOG_DEBUG("DEBUG: Breakpoints deleted."); LOG_DEBUG("DEBUG: Breakpoints deleted.");
} else { } else {
// delete single breakpoint // delete single breakpoint
Bit16u nr = 0; CBreakpoint::DeleteByIndex(bpNr);
std::list<TBreakpoint>::iterator i;
for(i=BPoints.begin(); i != BPoints.end(); i++) {
if ((*i).type==BKPNT_PHYSICAL) {
if (nr==bpNr) {
DeleteBreakpoint((*i).location);
LOG_DEBUG("DEBUG: Breakpoint %02X deleted.",nr);
break;
}
nr++;
} else if ((*i).type==BKPNT_INTERRUPT) {
if (nr==bpNr) {
(BPoints.erase)(i);
LOG_DEBUG("DEBUG: Breakpoint %02X. deleted.",nr);
break;;
}
nr++;
}
}
} }
return true; return true;
} }
@ -528,6 +658,36 @@ bool ParseCommand(char* str)
LOG_DEBUG("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs); LOG_DEBUG("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs);
return true; return true;
} }
found = strstr(str,"LOG ");
if (found) { // Create Cpu log file
found+=4;
LOG_DEBUG("DEBUG: Starting log");
DEBUG_Log_Loop(GetHexValue(found,found));
LOG_DEBUG("DEBUG: Logfile LOGCPU.TXT created.");
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);
Interrupt(intNr);
SetCodeWinStart();
return true;
}
found = strstr(str,"INT ");
if (found) { // Create Cpu log file
found+=4;
Bit8u intNr = GetHexValue(found,found);
LOG_DEBUG("DEBUG: Starting INT %02X",intNr);
CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip, true);
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip-1,true);
debugging=false;
DrawCode();
DOSBOX_SetNormalLoop();
Interrupt(intNr);
return true;
}
if ((*str=='H') || (*str=='?')) { if ((*str=='H') || (*str=='?')) {
wprintw(dbg.win_out,"Debugger keys:\n"); wprintw(dbg.win_out,"Debugger keys:\n");
wprintw(dbg.win_out,"--------------------------------------------------------------------------\n"); wprintw(dbg.win_out,"--------------------------------------------------------------------------\n");
@ -538,7 +698,6 @@ bool ParseCommand(char* str)
wprintw(dbg.win_out,"Return - Enable command line input\n"); 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,"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,"R/F - Scroll data view\n");
wprintw(dbg.win_out,"\n");
wprintw(dbg.win_out,"Debugger commands (enter all values in hex or as register):\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,"--------------------------------------------------------------------------\n");
wprintw(dbg.win_out,"BP [segment]:[offset] - Set breakpoint\n"); wprintw(dbg.win_out,"BP [segment]:[offset] - Set breakpoint\n");
@ -547,6 +706,8 @@ bool ParseCommand(char* str)
wprintw(dbg.win_out,"BPLIST - List breakpoints\n"); wprintw(dbg.win_out,"BPLIST - List breakpoints\n");
wprintw(dbg.win_out,"BPDEL [bpNr] / * - Delete breakpoint nr / all\n"); wprintw(dbg.win_out,"BPDEL [bpNr] / * - Delete breakpoint nr / all\n");
wprintw(dbg.win_out,"C / D [segment]:[offset] - Set code / data view address\n"); wprintw(dbg.win_out,"C / D [segment]:[offset] - Set code / data view address\n");
wprintw(dbg.win_out,"INT [nr] / INTT [nr] - Execute / Trace into Iinterrupt\n");
wprintw(dbg.win_out,"LOG [num] - Write cpu log file\n");
wprintw(dbg.win_out,"H - Help\n"); wprintw(dbg.win_out,"H - Help\n");
wrefresh(dbg.win_out); wrefresh(dbg.win_out);
return TRUE; return TRUE;
@ -621,6 +782,9 @@ Bit32u DEBUG_CheckKeys(void) {
case 'H' : strcpy(codeViewData.inputStr,"H "); case 'H' : strcpy(codeViewData.inputStr,"H ");
ParseCommand(codeViewData.inputStr); ParseCommand(codeViewData.inputStr);
break; break;
case 'T' : DEBUG_RaiseTimerIrq();
LOG_DEBUG("Debug: Timer Int started.");
break;
case 0x0A : // Return : input case 0x0A : // Return : input
codeViewData.inputMode = true; codeViewData.inputMode = true;
@ -636,23 +800,25 @@ Bit32u DEBUG_CheckKeys(void) {
break; break;
case KEY_F(5): // Run Programm case KEY_F(5): // Run Programm
debugging=false; debugging=false;
SetBreakpoints(); CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
DOSBOX_SetNormalLoop(); DOSBOX_SetNormalLoop();
break; break;
case KEY_F(9): // Set/Remove TBreakpoint case KEY_F(9): // Set/Remove TBreakpoint
{ PhysPt ptr = PhysMake(codeViewData.cursorSeg,codeViewData.cursorOfs); { PhysPt ptr = PhysMake(codeViewData.cursorSeg,codeViewData.cursorOfs);
if (IsBreakpoint(ptr)) DeleteBreakpoint(ptr); if (CBreakpoint::IsBreakpoint(ptr)) CBreakpoint::DeleteBreakpoint(ptr);
else AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false); else CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false);
} }
break; break;
case KEY_F(10): // Step over inst case KEY_F(10): // Step over inst
if (StepOver()) return 0; if (StepOver()) return 0;
else { else {
skipFirstInstruction = true; // for heavy debugger
Bitu ret=(*cpudecoder)(1); Bitu ret=(*cpudecoder)(1);
SetCodeWinStart(); SetCodeWinStart();
} }
break; break;
case KEY_F(11): // trace into case KEY_F(11): // trace into
skipFirstInstruction = true; // for heavy debugger
ret = (*cpudecoder)(1); ret = (*cpudecoder)(1);
SetCodeWinStart(); SetCodeWinStart();
break; break;
@ -675,8 +841,8 @@ Bitu DEBUG_Loop(void) {
Bit32u oldEIP = reg_eip; Bit32u oldEIP = reg_eip;
PIC_runIRQs(); PIC_runIRQs();
if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) { if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) {
AddBreakpoint(oldCS,oldEIP,true); CBreakpoint::AddBreakpoint(oldCS,oldEIP,true);
SetBreakpoints(); CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
debugging=false; debugging=false;
DOSBOX_SetNormalLoop(); DOSBOX_SetNormalLoop();
return 0; return 0;
@ -686,13 +852,13 @@ Bitu DEBUG_Loop(void) {
} }
void DEBUG_Enable(void) { void DEBUG_Enable(void) {
debugging=true; debugging=true;
SetCodeWinStart(); SetCodeWinStart();
DEBUG_DrawScreen(); DEBUG_DrawScreen();
DOSBOX_SetLoop(&DEBUG_Loop); DOSBOX_SetLoop(&DEBUG_Loop);
} }
void DEBUG_DrawScreen(void) { void DEBUG_DrawScreen(void) {
DrawRegisters(); DrawRegisters();
DrawData(); DrawData();
@ -702,7 +868,90 @@ static void DEBUG_RaiseTimerIrq(void) {
PIC_ActivateIRQ(0); PIC_ActivateIRQ(0);
} }
void DEBUG_Init(void) { static bool DEBUG_Log_Loop(int count) {
char buffer[512];
getcwd(buffer,512);
FILE* f = fopen("LOGCPU.TXT","wt");
if (!f) return false;
do {
// PIC_runIRQs();
Bitu ret;
do {
// Get disasm
Bit16u csValue = SegValue(cs);
Bit32u eipValue = reg_eip;
PhysPt start=Segs[cs].phys+reg_eip;
char dline[200];Bitu size;
size = DasmI386(dline, start, reg_eip, false);
Bitu len = strlen(dline);
if (len<30) for (Bitu i=0; i<30-len; i++) strcat(dline," ");
PIC_IRQAgain=false;
ret=(*cpudecoder)(1);
// Get register values
char buffer[512];
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",csValue,eipValue,dline,reg_eax,reg_ebx,reg_ecx,reg_edx,reg_esi,reg_edi,reg_ebp,reg_esp,SegValue(ds),SegValue(ds),SegValue(es),SegValue(fs),SegValue(gs),SegValue(ss),get_CF(),get_ZF(),get_SF(),get_OF(),get_AF(),get_PF());
fprintf(f,"%s",buffer);
count--;
if (count==0) break;
} while (!ret && PIC_IRQAgain);
if (ret) break;
} while (count>0);
fclose(f);
return true;
}
// DEBUG.COM stuff
class DEBUG : public Program {
public:
DEBUG() { pDebugcom = this; active = false; };
~DEBUG() { pDebugcom = 0; };
bool IsActive() { return active; };
void Run(void)
{
char filename[128];
char args[128];
cmd->FindCommand(1,temp_line);
strncpy(filename,temp_line.c_str(),128);
cmd->FindCommand(2,temp_line);
strncpy(args,temp_line.c_str(),128);
// Start new shell and execute prog
active = true;
DOS_Shell shell;
shell.Execute(filename,args);
};
private:
bool active;
};
void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off)
{
if (pDebugcom && pDebugcom->IsActive()) {
CBreakpoint::AddBreakpoint(seg,off,true);
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
pDebugcom = 0;
};
};
static void DEBUG_ProgramStart(Program * * make) {
*make=new DEBUG;
}
// INIT
void DEBUG_SetupConsole(void)
{
#ifdef WIN32 #ifdef WIN32
WIN32_Console(); WIN32_Console();
#endif #endif
@ -712,14 +961,49 @@ void DEBUG_Init(void) {
input_count=0; input_count=0;
/* Start the Debug Gui */ /* Start the Debug Gui */
DBGUI_StartUp(); DBGUI_StartUp();
};
static void DEBUG_ShutDown(Section * sec)
{
CBreakpoint::DeleteAll();
};
void DEBUG_Init(Section* sec) {
MSG_Add("DEBUG_CONFIGFILE_HELP","Nothing to setup yet!\n");
DEBUG_DrawScreen(); DEBUG_DrawScreen();
/* Add some keyhandlers */ /* Add some keyhandlers */
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable); KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable);
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq); KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
/* Clear the TBreakpoint list */ /* Clear the TBreakpoint list */
memset((void*)&codeViewData,0,sizeof(codeViewData)); memset((void*)&codeViewData,0,sizeof(codeViewData));
(BPoints.clear)(); /* setup debug.com */
PROGRAMS_MakeFile("DEBUG.COM",DEBUG_ProgramStart);
/* shutdown function */
sec->AddDestroyFunction(&DEBUG_ShutDown);
} }
#endif // HEAVY DEBUGGING STUFF
#if C_HEAVY_DEBUG
bool DEBUG_HeavyIsBreakpoint(void)
{
if (skipFirstInstruction) {
skipFirstInstruction = false;
return false;
}
PhysPt where = SegPhys(cs)+reg_eip;
if (CBreakpoint::CheckBreakpoint(where)) {
exitLoop = true;
DEBUG_Enable();
return true;
};
return false;
};
#endif // HEAVY DEBUG
#endif // DEBUG

View File

@ -34,7 +34,6 @@
void DEBUG_ShowMsg(char * msg) { void DEBUG_ShowMsg(char * msg) {
char buf[1024]; char buf[1024];
strcpy(buf,msg); strcpy(buf,msg);
strcat(buf,"\n");
waddstr(dbg.win_out,buf); waddstr(dbg.win_out,buf);
wprintw(dbg.win_out," %d\n",cycle_count); wprintw(dbg.win_out," %d\n",cycle_count);

View File

@ -29,19 +29,17 @@
#include "dos_inc.h" #include "dos_inc.h"
DOS_Block dos; DOS_Block dos;
DOS_InfoBlock dosInfoBlock; DOS_InfoBlock dos_infoblock;
static Bit8u dos_copybuf[0x10000]; Bit8u dos_copybuf[0x10000];
static Bitu call_20,call_21,call_theend; static Bitu call_20,call_21;
void DOS_SetError(Bit16u code) { void DOS_SetError(Bit16u code) {
dos.errorcode=code; dos.errorcode=code;
}; }
#define DOSNAMEBUF 256 #define DOSNAMEBUF 256
static Bitu DOS_21Handler(void) { static Bitu DOS_21Handler(void) {
//TODO KEYBOARD Check for break
char name1[DOSNAMEBUF+1]; char name1[DOSNAMEBUF+1];
char name2[DOSNAMEBUF+1]; char name2[DOSNAMEBUF+1];
switch (reg_ah) { switch (reg_ah) {
@ -151,7 +149,7 @@ static Bitu DOS_21Handler(void) {
} }
break; break;
default: default:
LOG_ERROR("DOS:0C:Illegal Flush STDIN Buffer call %d",reg_al); // LOG_ERROR("DOS:0C:Illegal Flush STDIN Buffer call %d",reg_al);
break; break;
} }
} }
@ -166,14 +164,13 @@ static Bitu DOS_21Handler(void) {
reg_al=26; reg_al=26;
break; break;
case 0x0f: /* Open File using FCB */ case 0x0f: /* Open File using FCB */
if(DOS_FCBOpen(SegValue(ds),reg_dx)){ if(DOS_FCBOpenCreate(SegValue(ds),reg_dx)){
reg_al=0; reg_al=0;
}else{ }else{
reg_al=0xff; reg_al=0xff;
} }
LOG_DEBUG("DOS:0x0f FCB-fileopen used, result:al=%d",reg_al); LOG_DEBUG("DOS:0x0f FCB-fileopen used, result:al=%d",reg_al);
break; break;
case 0x10: /* Close File using FCB */ case 0x10: /* Close File using FCB */
if(DOS_FCBClose(SegValue(ds),reg_dx)){ if(DOS_FCBClose(SegValue(ds),reg_dx)){
reg_al=0; reg_al=0;
@ -182,7 +179,6 @@ static Bitu DOS_21Handler(void) {
} }
LOG_DEBUG("DOS:0x10 FCB-fileclose used, result:al=%d",reg_al); LOG_DEBUG("DOS:0x10 FCB-fileclose used, result:al=%d",reg_al);
break; break;
case 0x11: /* Find First Matching File using FCB */ case 0x11: /* Find First Matching File using FCB */
if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){ if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){
reg_al=0; reg_al=0;
@ -191,7 +187,6 @@ static Bitu DOS_21Handler(void) {
} }
LOG_DEBUG("DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al); LOG_DEBUG("DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al);
break; break;
case 0x12: /* Find Next Matching File using FCB */ case 0x12: /* Find Next Matching File using FCB */
if(DOS_FCBFindNext(SegValue(ds),reg_dx)){ if(DOS_FCBFindNext(SegValue(ds),reg_dx)){
reg_al=0; reg_al=0;
@ -200,23 +195,59 @@ static Bitu DOS_21Handler(void) {
} }
LOG_DEBUG("DOS:0x12 FCB-FindNext used, result:al=%d",reg_al); LOG_DEBUG("DOS:0x12 FCB-FindNext used, result:al=%d",reg_al);
break; break;
case 0x13: /* Delete File using FCB */ case 0x13: /* Delete File using FCB */
case 0x14: /* Sequential read from FCB */ if (DOS_FCBDeleteFile(SegValue(ds),reg_dx)) reg_al = 0x00;
case 0x15: /* Sequential write to FCB */ else reg_al = 0xFF;
case 0x16: /* Create or truncate file using FCB */ break;
case 0x17: /* Rename file using FCB */ case 0x14: /* Sequential read from FCB */
case 0x21: /* Read random record from FCB */ reg_al = DOS_FCBRead(SegValue(ds),reg_dx,0);
case 0x22: /* Write random record to FCB */ LOG_DEBUG("DOS:0x14 FCB-Read used, result:al=%d",reg_al);
case 0x23: /* Get file size for FCB */ break;
case 0x24: /* Set Random Record number for FCB */ case 0x15: /* Sequential write to FCB */
case 0x27: /* Random block read from FCB */ if (DOS_FCBWrite(SegValue(ds),reg_dx,0)) reg_al = 0x00;
case 0x28: /* Random Block read to FCB */ else reg_al = 0x01;
LOG_ERROR("DOS:Unhandled call %02X, FCB Stuff",reg_ah); LOG_DEBUG("DOS:0x15 FCB-Write used, result:al=%d",reg_al);
reg_al=0xff; /* FCB Calls FAIL */ break;
//CALLBACK_SCF(true); not needed. case 0x16: /* Create or truncate file using FCB */
if (DOS_FCBOpenCreate(SegValue(ds),reg_dx)) reg_al = 0x00;
else reg_al = 0x01;
LOG_DEBUG("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;
else reg_al = 0xFF;
break;
case 0x1b: /* Get allocation info for default drive */
if (!DOS_GetAllocationInfo(0,&reg_cx,&reg_ax,&reg_dx)) reg_al=0xff;
break;
case 0x1c: /* Get allocation info for specific drive */
if (!DOS_GetAllocationInfo(reg_dl,&reg_cx,&reg_ax,&reg_dx)) reg_al=0xff;
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);
break;
case 0x22: /* Write random record to FCB */
if (DOS_FCBRandomWrite(SegValue(ds),reg_dx,1,true)) reg_al = 0x00;
else reg_al = 0x01;
LOG_DEBUG("DOS:0x28 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;
else reg_al = 0xFF;
break;
case 0x24: /* Set Random Record number for FCB */
DOS_FCBSetRandomRecord(SegValue(ds),reg_dx);
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 read used, result:al=%d",reg_al);
break;
case 0x28: /* Random Block write to FCB */
if (DOS_FCBRandomWrite(SegValue(ds),reg_dx,reg_cx,false)) reg_al = 0x00;
else reg_al = 0x01;
LOG_DEBUG("DOS:0x28 FCB-Random write used, result:al=%d",reg_al);
break; break;
case 0x29: /* Parse filename into FCB */ case 0x29: /* Parse filename into FCB */
{ Bit8u difference; { Bit8u difference;
char string[1024]; char string[1024];
@ -226,7 +257,6 @@ static Bitu DOS_21Handler(void) {
} }
LOG_DEBUG("DOS:29:FCB Parse Filename, result:al=%d",reg_al); LOG_DEBUG("DOS:29:FCB Parse Filename, result:al=%d",reg_al);
break; break;
case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */ case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */ case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */
case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */ case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */
@ -239,26 +269,11 @@ static Bitu DOS_21Handler(void) {
reg_al=DOS_GetDefaultDrive(); reg_al=DOS_GetDefaultDrive();
break; break;
case 0x1a: /* Set Disk Transfer Area Address */ case 0x1a: /* Set Disk Transfer Area Address */
{
dos.dta=RealMakeSeg(ds,reg_dx); dos.dta=RealMakeSeg(ds,reg_dx);
break; DOS_PSP psp(dos.psp);
psp.SetDTA(dos.dta);
case 0x1c: /* Get allocation info for specific drive */ }
LOG_DEBUG("DOS: Allocation Info call not supported correctly");
SegSet16(ds,0xf000);
reg_bx=0;
real_writeb(0xf000,0,0);
reg_al=0x7f;
reg_cx=0x200;
reg_dx=0x1000;
break; /* TODO maybe but hardly think a game needs this */
case 0x1b: /* Get allocation info for default drive */
LOG_DEBUG("DOS: Allocation Info call not supported correctly");
SegSet16(ds,0xf000);
reg_bx=0;
real_writeb(0xf000,0,0);
reg_al=0x7f;
reg_cx=0x200;
reg_dx=0x1000;
break; break;
case 0x1f: /* Get drive parameter block for default drive */ case 0x1f: /* Get drive parameter block for default drive */
case 0x32: /* Get drive parameter block for specific drive */ case 0x32: /* Get drive parameter block for specific drive */
@ -268,7 +283,7 @@ static Bitu DOS_21Handler(void) {
RealSetVec(reg_al,RealMakeSeg(ds,reg_dx)); RealSetVec(reg_al,RealMakeSeg(ds,reg_dx));
break; break;
case 0x26: /* Create new PSP */ case 0x26: /* Create new PSP */
DOS_NewPSP(reg_dx); DOS_NewPSP(reg_dx,DOS_PSP(dos.psp).GetSize());
break; break;
case 0x2a: /* Get System Date */ case 0x2a: /* Get System Date */
reg_al=0; /* It's always sunday TODO find that correct formula */ reg_al=0; /* It's always sunday TODO find that correct formula */
@ -444,6 +459,7 @@ static Bitu DOS_21Handler(void) {
case 0x3f: /* READ Read from file or device */ case 0x3f: /* READ Read from file or device */
{ {
Bit16u toread=reg_cx; Bit16u toread=reg_cx;
if (reg_cx+reg_dx>0xffff) LOG_DEBUG("DOS:READ:Buffer overflow %d",reg_cx+reg_dx);
if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) { if (DOS_ReadFile(reg_bx,dos_copybuf,&toread)) {
MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread); MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread);
reg_ax=toread; reg_ax=toread;
@ -457,6 +473,7 @@ static Bitu DOS_21Handler(void) {
case 0x40: /* WRITE Write to file or device */ case 0x40: /* WRITE Write to file or device */
{ {
Bit16u towrite=reg_cx; Bit16u towrite=reg_cx;
if (reg_cx+reg_dx>0xffff) LOG_DEBUG("DOS:WRITE:Buffer overflow %d",reg_cx+reg_dx);
MEM_BlockRead(SegPhys(ds)+reg_dx,dos_copybuf,towrite); MEM_BlockRead(SegPhys(ds)+reg_dx,dos_copybuf,towrite);
if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) { if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) {
reg_ax=towrite; reg_ax=towrite;
@ -490,7 +507,6 @@ static Bitu DOS_21Handler(void) {
break; break;
} }
case 0x43: /* Get/Set file attributes */ case 0x43: /* Get/Set file attributes */
//TODO FIX THIS HACK
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
switch (reg_al) switch (reg_al)
case 0x00: /* Get */ case 0x00: /* Get */
@ -511,7 +527,7 @@ static Bitu DOS_21Handler(void) {
} }
break; break;
case 0x44: /* IOCTL Functions */ case 0x44: /* IOCTL Functions */
if (DOS_IOCTL(reg_al,reg_bx)) { if (DOS_IOCTL()) {
CALLBACK_SCF(false); CALLBACK_SCF(false);
} else { } else {
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
@ -535,7 +551,6 @@ static Bitu DOS_21Handler(void) {
} }
break; break;
case 0x47: /* CWD Get current directory */ case 0x47: /* CWD Get current directory */
//TODO Memory
if (DOS_GetCurrentDir(reg_dl,name1)) { if (DOS_GetCurrentDir(reg_dl,name1)) {
MEM_BlockWrite(SegPhys(ds)+reg_si,name1,strlen(name1)+1); MEM_BlockWrite(SegPhys(ds)+reg_si,name1,strlen(name1)+1);
reg_ax=0x0100; reg_ax=0x0100;
@ -581,9 +596,8 @@ static Bitu DOS_21Handler(void) {
case 0x4b: /* EXEC Load and/or execute program */ case 0x4b: /* EXEC Load and/or execute program */
{ {
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
if (DOS_Execute(name1,(ParamBlock *)Phys2Host(SegPhys(es)+reg_bx),reg_al)) { LOG_DEBUG("Execute %s %d",name1,reg_al);
CALLBACK_SCF(false); if (!DOS_Execute(name1,SegPhys(es)+reg_bx,reg_al)) {
} else {
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
CALLBACK_SCF(true); CALLBACK_SCF(true);
} }
@ -593,9 +607,7 @@ static Bitu DOS_21Handler(void) {
case 0x4c: /* EXIT Terminate with return code */ case 0x4c: /* EXIT Terminate with return code */
{ {
if (DOS_Terminate(false)) { if (DOS_Terminate(false)) {
dos.return_code=reg_al; /* This can't ever return false normally */
dos.return_mode=RETURN_EXIT;
CALLBACK_SCF(false);
} else { } else {
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
CALLBACK_SCF(true); CALLBACK_SCF(true);
@ -610,6 +622,7 @@ static Bitu DOS_21Handler(void) {
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
if (DOS_FindFirst(name1,reg_cx)) { if (DOS_FindFirst(name1,reg_cx)) {
CALLBACK_SCF(false); CALLBACK_SCF(false);
reg_ax=0; /* Undocumented */
} else { } else {
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
CALLBACK_SCF(true); CALLBACK_SCF(true);
@ -618,6 +631,7 @@ static Bitu DOS_21Handler(void) {
case 0x4f: /* FINDNEXT Find next matching file */ case 0x4f: /* FINDNEXT Find next matching file */
if (DOS_FindNext()) { if (DOS_FindNext()) {
CALLBACK_SCF(false); CALLBACK_SCF(false);
reg_ax=0xffff; /* Undocumented */
} else { } else {
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
CALLBACK_SCF(true); CALLBACK_SCF(true);
@ -630,9 +644,9 @@ static Bitu DOS_21Handler(void) {
reg_bx=dos.psp; reg_bx=dos.psp;
break; break;
case 0x52: { /* Get list of lists */ case 0x52: { /* Get list of lists */
Bit16u seg; RealPt addr=dos_infoblock.GetPointer();
dosInfoBlock.GetDIBPointer(seg,reg_bx); SegSet16(es,RealSeg(addr));
SegSet16(es,seg); reg_bx=RealOff(addr);
LOG_DEBUG("Call is made for list of lists - let's hope for the best"); LOG_DEBUG("Call is made for list of lists - let's hope for the best");
break; } break; }
//TODO Think hard how shit this is gonna be //TODO Think hard how shit this is gonna be
@ -640,9 +654,12 @@ static Bitu DOS_21Handler(void) {
case 0x53: /* Translate BIOS parameter block to drive parameter block */ case 0x53: /* Translate BIOS parameter block to drive parameter block */
//YEAH RIGHT //YEAH RIGHT
case 0x54: /* Get verify flag */ case 0x54: /* Get verify flag */
case 0x55: /* Create Child PSP*/
E_Exit("Unhandled Dos 21 call %02X",reg_ah); E_Exit("Unhandled Dos 21 call %02X",reg_ah);
break; break;
case 0x55: /* Create Child PSP*/
DOS_NewPSP(reg_dx,reg_si);
dos.psp = reg_dx;
break;
case 0x56: /* RENAME Rename file */ case 0x56: /* RENAME Rename file */
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
MEM_StrCopy(SegPhys(es)+reg_di,name2,DOSNAMEBUF); MEM_StrCopy(SegPhys(es)+reg_di,name2,DOSNAMEBUF);
@ -654,12 +671,28 @@ static Bitu DOS_21Handler(void) {
} }
break; break;
case 0x57: /* Get/Set File's Date and Time */ case 0x57: /* Get/Set File's Date and Time */
if (reg_al==0x00) {
if (DOS_GetFileDate(reg_bx,&reg_cx,&reg_dx)) {
CALLBACK_SCF(false);
} else {
CALLBACK_SCF(true);
};
} else {
reg_cx=0; reg_cx=0;
reg_dx=0; reg_dx=0;
LOG_DEBUG("DOS:57:Getting/Setting File Date is faked",reg_ah); LOG_DEBUG("DOS:57:Setting File Date is faked",reg_ah);
}
break; break;
case 0x58: /* Get/Set Memory allocation strategy */ case 0x58: /* Get/Set Memory allocation strategy */
LOG_DEBUG("DOS:58:Not Supported Set//Get memory allocation"); switch (reg_al) {
case 0: /* Get Strategy */
reg_ax=0; //Low memory first fit
break;
case 1: /* Set Strategy */
break;
default:
LOG_DEBUG("DOS:58:Not Supported Set//Get memory allocation call %X",reg_al);
}
break; break;
case 0x59: /* Get Extended error information */ case 0x59: /* Get Extended error information */
reg_ax=dos.errorcode; reg_ax=dos.errorcode;
@ -805,7 +838,8 @@ static Bitu DOS_20Handler(void) {
} }
void DOS_Init(void) { void DOS_Init(Section* sec) {
MSG_Add("DOS_CONFIGFILE_HELP","Setting a memory size to 0 will disable it.\n");
call_20=CALLBACK_Allocate(); call_20=CALLBACK_Allocate();
CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET); CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET);
RealSetVec(0x20,CALLBACK_RealPointer(call_20)); RealSetVec(0x20,CALLBACK_RealPointer(call_20));
@ -816,8 +850,8 @@ void DOS_Init(void) {
DOS_SetupFiles(); /* Setup system File tables */ DOS_SetupFiles(); /* Setup system File tables */
DOS_SetupDevices(); /* Setup dos devices */ DOS_SetupDevices(); /* Setup dos devices */
DOS_SetupMemory(); /* Setup first MCB */
DOS_SetupTables(); DOS_SetupTables();
DOS_SetupMemory(); /* Setup first MCB */
DOS_SetupPrograms(); DOS_SetupPrograms();
DOS_SetupMisc(); /* Some additional dos interrupts */ DOS_SetupMisc(); /* Some additional dos interrupts */
DOS_SetDefaultDrive(25); DOS_SetDefaultDrive(25);

View File

@ -29,122 +29,73 @@
dos work a bit easier. dos work a bit easier.
*/ */
#pragma pack (1)
struct sPSP { void DOS_ParamBlock::Clear(void) {
Bit8u exit[2]; /* CP/M-like exit poimt */ memset(&exec,0,sizeof(exec));
Bit16u next_seg; /* Segment of first byte beyond memory allocated or program */ memset(&overlay,0,sizeof(overlay));
Bit8u fill_1; /* single char fill */ }
/* CPM Stuff dunno what this is*/ void DOS_ParamBlock::LoadData(void) {
//TODO Add some checks for people using this i think exec.envseg=sGet(sExec,envseg);
Bit8u far_call; /* far call opcode */ exec.cmdtail=sGet(sExec,cmdtail);
RealPt cpm_entry; /* CPM Service Request address*/ exec.fcb1=sGet(sExec,fcb1);
RealPt int_22; /* Terminate Address */ exec.fcb2=sGet(sExec,fcb2);
RealPt int_23; /* Break Address */ exec.initsssp=sGet(sExec,initsssp);
RealPt int_24; /* Critical Error Address */ exec.initcsip=sGet(sExec,initcsip);
Bit16u psp_parent; /* Parent PSP Segment */ overlay.loadseg=sGet(sOverlay,loadseg);
Bit8u files[20]; /* File Table - 0xff is unused */ overlay.relocation=sGet(sOverlay,relocation);
Bit16u environment; /* Segment of evironment table */ }
RealPt stack; /* SS:SP Save point for int 0x21 calls */
Bit16u max_files; /* Maximum open files */
RealPt file_table; /* Pointer to File Table PSP:0x18 */
RealPt prev_psp; /* Pointer to previous PSP */
RealPt dta; /* Pointer to current Process DTA */
Bit8u fill_2[16]; /* Lot's of unused stuff i can't care aboue */
Bit8u service[3]; /* INT 0x21 Service call int 0x21;retf; */
Bit8u fill_3[45]; /* This has some blocks with FCB info */
CommandTail cmdtail;
} GCC_ATTRIBUTE(packed);
union sParamBlock { void DOS_ParamBlock::SaveData(void) {
struct { sSave(sExec,envseg,exec.envseg);
Bit16u loadseg; sSave(sExec,cmdtail,exec.cmdtail);
Bit16u relocation; sSave(sExec,fcb1,exec.fcb1);
} overlay; sSave(sExec,fcb2,exec.fcb2);
struct { sSave(sExec,initsssp,exec.initsssp);
Bit16u envseg; sSave(sExec,initcsip,exec.initcsip);
RealPt cmdtail; }
RealPt fcb1;
RealPt fcb2;
RealPt initsssp;
RealPt initcsip;
} exec;
} GCC_ATTRIBUTE(packed);
struct sFCB {
Bit8u drive; //0 is current drive. when opened 0 is replaced by drivenumber
Bit8u filename[8]; //spacepadded to fit
Bit8u ext[3]; //spacepadded to fit
Bit16u current_block; // set to 0 by open
Bit16u record_size; // used by reads Set to 80h by OPEN function
Bit32u filesize; //in bytes In this field, the first word is the low-order part of the size
Bit16u date;
Bit16u time;
Bit8u reserved[8];
Bit8u current_relative_record_number; //open doesn't set this
Bit32u rel_record; //open does not handle this
} GCC_ATTRIBUTE(packed);
#pragma pack ()
#define sGet(s,m) GetIt(((s *)0)->m,(PhysPt)&(((s *)0)->m))
#define sSave(s,m,val) SaveIt(((s *)0)->m,(PhysPt)&(((s *)0)->m),val)
class MemStruct { void DOS_InfoBlock::SetLocation(Bit16u segment)
public: {
Bit8u GetIt(Bit8u,PhysPt addr) { seg = segment;
return mem_readb(pt+addr); pt=PhysMake(seg,0);
}; /* Clear the initual Block */
Bit16u GetIt(Bit16u,PhysPt addr) { for(Bitu i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff);
return mem_readw(pt+addr); }
};
Bit32u GetIt(Bit32u,PhysPt addr) { void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb)
return mem_readd(pt+addr); {
}; sSave(sDIB,firstMCB,_firstmcb);
void SaveIt(Bit8u,PhysPt addr,Bit8u val) { }
mem_writeb(pt+addr,val);
}; void DOS_InfoBlock::SetfirstFileTable(RealPt _first_table){
void SaveIt(Bit16u,PhysPt addr,Bit16u val) { sSave(sDIB,firstFileTable,_first_table);
mem_writew(pt+addr,val); }
};
void SaveIt(Bit32u,PhysPt addr,Bit32u val) { RealPt DOS_InfoBlock::GetPointer(void)
mem_writed(pt+addr,val); {
}; return RealMake(seg,offsetof(sDIB,firstDPB));
}
private: /* program Segment prefix */
PhysPt pt;
}; Bit16u DOS_PSP::rootpsp = 0;
void DOS_PSP::MakeNew(Bit16u mem_size)
class DOS_PSP :public MemStruct { {
public: /* get previous */
DOS_PSP(Bit16u segment){NewPt(segment);}; DOS_PSP prevpsp(dos.psp);
void NewPt(Bit16u segment);
void MakeNew(Bit16u mem_size);
Bit8u GetFileHandle(Bitu index);
private:
Bit16u seg;
PhysPt pt;
};
void DOS_PSP::NewPt(Bit16u segment) {
seg=segment;
pt=PhysMake(segment,0);
};
void DOS_PSP::MakeNew(Bit16u mem_size) {
Bitu i;
/* Clear it first */ /* Clear it first */
for (i=0;i<256;i++) mem_writeb(pt+i,0); Bitu i;
for (i=0;i<sizeof(sPSP);i++) mem_writeb(pt+i,0);
// Set size
sSave(sPSP,next_seg,seg+mem_size);
/* far call opcode */
sSave(sPSP,far_call,0xea);
// sSave(sPSP,cmp_entry
/* Standard blocks,int 20 and int21 retf */ /* Standard blocks,int 20 and int21 retf */
sGet(sPSP,max_files);
sSave(sPSP,exit[0],0xcd); sSave(sPSP,exit[0],0xcd);
sSave(sPSP,exit[1],0x20); sSave(sPSP,exit[1],0x20);
sSave(sPSP,service[0],0xcd); sSave(sPSP,service[0],0xcd);
@ -154,135 +105,259 @@ void DOS_PSP::MakeNew(Bit16u mem_size) {
sSave(sPSP,psp_parent,dos.psp); sSave(sPSP,psp_parent,dos.psp);
sSave(sPSP,prev_psp,RealMake(dos.psp,0)); sSave(sPSP,prev_psp,RealMake(dos.psp,0));
/* terminate 22,break 23,crititcal error 24 address stored */ /* terminate 22,break 23,crititcal error 24 address stored */
sSave(sPSP,int_22,RealGetVec(0x22)); SaveVectors();
sSave(sPSP,int_23,RealGetVec(0x23));
sSave(sPSP,int_24,RealGetVec(0x24));
/* Memory size */
sSave(sPSP,next_seg,seg+mem_size);
/* Process DTA */ /* Process DTA */
sSave(sPSP,dta,RealMake(seg,128)); sSave(sPSP,dta,RealMake(seg,128));
/* User Stack pointer */ /* FCBs are filled with 0 */
//Copy from previous psp // ....
// mem_writed(pt+offsetof(sPSP,stack),
/* Init file pointer and max_files */ /* Init file pointer and max_files */
sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files[0]))); sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files[0])));
sSave(sPSP,max_files,20); sSave(sPSP,max_files,20);
/* Copy file table from calling process */ for (i=0;i<20;i++) SetFileHandle(i,0xff);
for (i=0;i<20;i++) {
Bit8u handle=0; /* User Stack pointer */
// Bitu handle=dos.psp.GetFileHandle(i); // if (prevpsp.GetSegment()!=0) sSave(sPSP,stack,prevpsp.GetStack());
sSave(sPSP,files[i],handle);
} if (rootpsp==0) rootpsp = seg;
} }
Bit8u DOS_PSP::GetFileHandle(Bitu index) { Bit8u DOS_PSP::GetFileHandle(Bit16u index)
{
if (index>=sGet(sPSP,max_files)) return 0xff; if (index>=sGet(sPSP,max_files)) return 0xff;
PhysPt files=Real2Phys(sGet(sPSP,file_table)); PhysPt files=Real2Phys(sGet(sPSP,file_table));
return mem_readb(files+index); return mem_readb(files+index);
}; };
#define FCB_EXTENDED (mem_readb(off)==0xFF ? 7:0) void DOS_PSP::SetFileHandle(Bit16u index, Bit8u handle)
void DOS_FCB::Set_drive(Bit8u a){
mem_writeb(off+offsetof(sFCB,drive)+FCB_EXTENDED,a);
}
void DOS_FCB::Set_filename(char * a){
MEM_BlockWrite(off+offsetof(sFCB,filename)+FCB_EXTENDED,a,8);
}
void DOS_FCB::Set_ext(char * a) {
MEM_BlockWrite(off+offsetof(sFCB,ext)+FCB_EXTENDED,a,3);
}
void DOS_FCB::Set_current_block(Bit16u a){
mem_writew(off+offsetof(sFCB,current_block)+FCB_EXTENDED,a);
}
void DOS_FCB::Set_record_size(Bit16u a){
mem_writew(off+offsetof(sFCB,record_size)+FCB_EXTENDED,a);
}
void DOS_FCB::Set_filesize(Bit32u a){
mem_writed(off+offsetof(sFCB,filesize)+FCB_EXTENDED,a);
}
void DOS_FCB::Set_date(Bit16u a){
mem_writew(off+offsetof(sFCB,date)+FCB_EXTENDED,a);
}
void DOS_FCB::Set_time(Bit16u a){
mem_writew(off+offsetof(sFCB,time)+FCB_EXTENDED,a);
}
Bit8u DOS_FCB::Get_drive(void){
return mem_readb(off+offsetof(sFCB,drive)+FCB_EXTENDED);
}
void DOS_FCB::Get_filename(char * a){
MEM_BlockRead(off+offsetof(sFCB,filename)+FCB_EXTENDED,a,8);
}
void DOS_FCB::Get_ext(char * a){
MEM_BlockRead(off+offsetof(sFCB,ext)+FCB_EXTENDED,a,3);
}
Bit16u DOS_FCB::Get_current_block(void){
return mem_readw(off+offsetof(sFCB,current_block)+FCB_EXTENDED);
}
Bit16u DOS_FCB::Get_record_size(void){
return mem_readw(off+offsetof(sFCB,record_size)+FCB_EXTENDED);
}
Bit32u DOS_FCB::Get_filesize(void){
return mem_readd(off+offsetof(sFCB,filesize)+FCB_EXTENDED);
}
Bit16u DOS_FCB::Get_date(void){
return mem_readw(off+offsetof(sFCB,date)+FCB_EXTENDED);
}
Bit16u DOS_FCB::Get_time(void){
return mem_readw(off+offsetof(sFCB,time)+FCB_EXTENDED);
}
void DOS_ParamBlock::InitExec(RealPt cmdtail) {
mem_writew(off+offsetof(sParamBlock,exec.envseg),0);
mem_writed(off+offsetof(sParamBlock,exec.fcb1),0);
mem_writed(off+offsetof(sParamBlock,exec.fcb2),0);
mem_writed(off+offsetof(sParamBlock,exec.cmdtail),cmdtail);
}
Bit16u DOS_ParamBlock::loadseg(void) {
return mem_readw(off+offsetof(sParamBlock,overlay.loadseg));
}
Bit16u DOS_ParamBlock::relocation(void){
return mem_readw(off+offsetof(sParamBlock,overlay.loadseg));
}
Bit16u DOS_ParamBlock::envseg(void){
return mem_readw(off+offsetof(sParamBlock,exec.envseg));
}
RealPt DOS_ParamBlock::initsssp(void){
return mem_readd(off+offsetof(sParamBlock,exec.initsssp));
}
RealPt DOS_ParamBlock::initcsip(void){
return mem_readd(off+offsetof(sParamBlock,exec.initcsip));
}
RealPt DOS_ParamBlock::fcb1(void){
return mem_readd(off+offsetof(sParamBlock,exec.fcb1));
}
RealPt DOS_ParamBlock::fcb2(void){
return mem_readd(off+offsetof(sParamBlock,exec.fcb2));
}
RealPt DOS_ParamBlock::cmdtail(void){
return mem_readd(off+offsetof(sParamBlock,exec.cmdtail));
}
// * Dos Info Block (list of lists) *
void DOS_InfoBlock::SetLocation(Bit16u segment)
{ {
seg = segment; if (index<sGet(sPSP,max_files)) {
dib = (SDosInfoBlock*)HostMake(segment,0); PhysPt files=Real2Phys(sGet(sPSP,file_table));
Bit16u size = sizeof(SDosInfoBlock); mem_writeb(files+index,handle);
memset(dib,0,sizeof(SDosInfoBlock)); }
}; };
void DOS_InfoBlock::SetFirstMCB(RealPt pt) Bit16u DOS_PSP::FindFreeFileEntry(void)
{ {
dib->firstMCB = pt; PhysPt files=Real2Phys(sGet(sPSP,file_table));
for (Bit16u i=0;i<sGet(sPSP,max_files);i++) {
if (mem_readb(files+i)==0xff) return i;
}
return 0xff;
}; };
void DOS_InfoBlock::GetDIBPointer(Bit16u& segment, Bit16u& offset) void DOS_PSP::CopyFileTable(DOS_PSP* srcpsp)
{ {
segment = seg; /* Copy file table from calling process */
offset = offsetof(SDosInfoBlock,firstDPB); for (Bit16u i=0;i<20;i++) {
Bit8u handle = srcpsp->GetFileHandle(i);
SetFileHandle(i,handle);
}
};
void DOS_PSP::CloseFiles(void)
{
for (Bit16u i=0;i<sGet(sPSP,max_files);i++) {
DOS_CloseFile(i);
}
}
void DOS_PSP::SaveVectors(void)
{
/* Save interrupt 22,23,24 */
sSave(sPSP,int_22,RealGetVec(0x22));
sSave(sPSP,int_23,RealGetVec(0x23));
sSave(sPSP,int_24,RealGetVec(0x24));
};
void DOS_PSP::RestoreVectors(void)
{
/* Restore interrupt 22,23,24 */
RealSetVec(0x22,sGet(sPSP,int_22));
RealSetVec(0x23,sGet(sPSP,int_23));
RealSetVec(0x24,sGet(sPSP,int_24));
};
void DOS_PSP::SetCommandTail(RealPt src)
{
if (src) { // valid source
MEM_BlockCopy(pt+offsetof(sPSP,cmdtail),Real2Phys(src),128);
} else { // empty
sSave(sPSP,cmdtail.count,0x00);
mem_writeb(pt+offsetof(sPSP,cmdtail.buffer[0]),0x0d);
};
};
void DOS_PSP::SetFCB1(RealPt src)
{
if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb1)),Real2Phys(src),16);
};
void DOS_PSP::SetFCB2(RealPt src)
{
if (src) MEM_BlockCopy(PhysMake(seg,offsetof(sPSP,fcb2)),Real2Phys(src),16);
};
void DOS_DTA::SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * pattern) {
sSave(sDTA,sdrive,_sdrive);
sSave(sDTA,sattr,_sattr);
/* Fill with spaces */
Bitu i;
for (i=0;i<12;i++) mem_writeb(pt+offsetof(sDTA,sname)+i,' ');
char * find_ext;
find_ext=strchr(pattern,'.');
if (find_ext) {
Bitu size=find_ext-pattern;if (size>8) size=8;
MEM_BlockWrite(pt+offsetof(sDTA,sname),pattern,size);
find_ext++;
MEM_BlockWrite(pt+offsetof(sDTA,sext),find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext));
} else {
MEM_BlockWrite(pt+offsetof(sDTA,sname),pattern,(strlen(pattern) > 8) ? 8 : strlen(pattern));
}
}
void DOS_DTA::SetResult(const char * _name,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr) {
MEM_BlockWrite(pt+offsetof(sDTA,name),(void *)_name,DOS_NAMELENGTH_ASCII);
sSave(sDTA,size,_size);
sSave(sDTA,date,_date);
sSave(sDTA,time,_time);
sSave(sDTA,attr,_attr);
}
void DOS_DTA::GetResult(char * _name,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr) {
MEM_BlockRead(pt+offsetof(sDTA,name),_name,DOS_NAMELENGTH_ASCII);
_size=sGet(sDTA,size);
_date=sGet(sDTA,date);
_time=sGet(sDTA,time);
_attr=sGet(sDTA,attr);
}
Bit8u DOS_DTA::GetSearchDrive(void) {
return sGet(sDTA,sdrive);
}
void DOS_DTA::GetSearchParams(Bit8u & attr,char * pattern) {
attr=sGet(sDTA,sattr);
char temp[11];
MEM_BlockRead(pt+offsetof(sDTA,sname),temp,11);
memcpy(pattern,temp,8);
pattern[8]='.';
memcpy(&pattern[9],&temp[8],3);
pattern[12]=0;
}
DOS_FCB::DOS_FCB(Bit16u seg,Bit16u off) {
SetPt(seg,off);
real_pt=pt;
if (sGet(sFCB,drive)==0xff) {
pt+=7;
extended=true;
} else extended=false;
}
bool DOS_FCB::Extended(void) {
return extended;
}
void DOS_FCB::Create(bool _extended) {
Bitu fill;
if (_extended) fill=36+7;
else fill=36;
Bitu i;
for (i=0;i<fill;i++) mem_writeb(real_pt+i,0);
pt=real_pt;
if (_extended) {
mem_writeb(real_pt,0xff);
pt+=7;
extended=true;
} else extended=false;
}
void DOS_FCB::SetName(Bit8u _drive,char * _fname,char * _ext) {
sSave(sFCB,drive,_drive);
MEM_BlockWrite(pt+offsetof(sFCB,filename),_fname,8);
MEM_BlockWrite(pt+offsetof(sFCB,ext),_ext,3);
}
void DOS_FCB::SetSizeDateTime(Bit32u _size,Bit16u _date,Bit16u _time) {
sSave(sFCB,filesize,_size);
sSave(sFCB,date,_date);
sSave(sFCB,time,_time);
}
void DOS_FCB::GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time) {
_size=sGet(sFCB,filesize);
}
void DOS_FCB::GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec) {
_cur_block=sGet(sFCB,cur_block);
_cur_rec=sGet(sFCB,cur_rec);
}
void DOS_FCB::SetRecord(Bit16u _cur_block,Bit8u _cur_rec) {
sSave(sFCB,cur_block,_cur_block);
sSave(sFCB,cur_rec,_cur_rec);
}
void DOS_FCB::GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size) {
_fhandle=sGet(sFCB,file_handle);
_rec_size=sGet(sFCB,rec_size);
}
void DOS_FCB::GetRandom(Bit32u & _random) {
_random=sGet(sFCB,rndm);
}
void DOS_FCB::SetRandom(Bit32u _random) {
sSave(sFCB,rndm,_random);
}
void DOS_FCB::FileOpen(Bit8u _fhandle) {
sSave(sFCB,drive,GetDrive());
sSave(sFCB,file_handle,_fhandle);
sSave(sFCB,cur_block,0);
sSave(sFCB,rec_size,128);
sSave(sFCB,rndm,0);
Bit8u temp=RealHandle(_fhandle);
sSave(sFCB,filesize,Files[temp]->size);
sSave(sFCB,time,Files[temp]->time);
sSave(sFCB,date,Files[temp]->date);
}
void DOS_FCB::FileClose(Bit8u & _fhandle) {
_fhandle=sGet(sFCB,file_handle);
sSave(sFCB,file_handle,0xff);
}
Bit8u DOS_FCB::GetDrive(void) {
Bit8u drive=sGet(sFCB,drive);
if (!drive) return dos.current_drive;
else return drive-1;
}
void DOS_FCB::GetName(char * fillname) {
fillname[0]=GetDrive()+'A';
fillname[1]=':';
MEM_BlockRead(pt+offsetof(sFCB,filename),&fillname[2],8);
fillname[10]='.';
MEM_BlockRead(pt+offsetof(sFCB,ext),&fillname[11],3);
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

@ -21,12 +21,11 @@
#include "mem.h" #include "mem.h"
#include "dos_inc.h" #include "dos_inc.h"
#include "cpu.h" #include "cpu.h"
#if defined (_MSC_VER) #include "callback.h"
#include "debug.h"
#pragma pack(1) #pragma pack(1)
#endif
struct EXE_Header { struct EXE_Header {
Bit16u signature; /* EXE Signature MZ or ZM */ Bit16u signature; /* EXE Signature MZ or ZM */
Bit16u extrabytes; /* Bytes on the last page */ Bit16u extrabytes; /* Bytes on the last page */
Bit16u pages; /* Pages in file */ Bit16u pages; /* Pages in file */
@ -41,13 +40,8 @@ struct EXE_Header {
Bit16u initCS; Bit16u initCS;
Bit16u reloctable; Bit16u reloctable;
Bit16u overlay; Bit16u overlay;
} } GCC_ATTRIBUTE(packed);
#if defined (_MSC_VER)
;
#pragma pack() #pragma pack()
#else
__attribute__ ((packed));
#endif
#define MAGIC1 0x5a4d #define MAGIC1 0x5a4d
#define MAGIC2 0x4d5a #define MAGIC2 0x4d5a
@ -63,32 +57,64 @@ __attribute__ ((packed));
#define OVERLAY 3 #define OVERLAY 3
bool DOS_Terminate(bool tsr) {
PSP * psp=(PSP *)HostMake(dos.psp,0);
if (!tsr) {
/* Free Files owned by process */
for (Bit16u i=0;i<psp->max_files;i++) {
DOS_CloseFile(i);
}
DOS_FreeProcessMemory(dos.psp);
};
dos.psp=psp->psp_parent;
PSP * oldpsp=(PSP *)HostMake(dos.psp,0);
/* Restore the DTA */
dos.dta=psp->dta;
/* Restore the old CS:IP from int 22h */
RealPt old22;
old22=RealGetVec(0x22);
SegSet16(cs,RealSeg(old22));
reg_ip=RealOff(old22);
/* Restore the SS:SP to the previous one */
SegSet16(ss,RealSeg(oldpsp->stack));
reg_sp=RealOff(oldpsp->stack);
/* Restore interrupt 22,23,24 */
RealSetVec(0x22,psp->int_22);
RealSetVec(0x23,psp->int_23);
RealSetVec(0x24,psp->int_24);
static void SaveRegisters(void) {
reg_sp-=20;
mem_writew(SegPhys(ss)+reg_sp+ 0,reg_ax);
mem_writew(SegPhys(ss)+reg_sp+ 2,reg_cx);
mem_writew(SegPhys(ss)+reg_sp+ 4,reg_dx);
mem_writew(SegPhys(ss)+reg_sp+ 6,reg_bx);
mem_writew(SegPhys(ss)+reg_sp+ 8,reg_si);
mem_writew(SegPhys(ss)+reg_sp+10,reg_di);
mem_writew(SegPhys(ss)+reg_sp+12,reg_bp);
mem_writew(SegPhys(ss)+reg_sp+14,SegValue(ds));
mem_writew(SegPhys(ss)+reg_sp+16,SegValue(es));
}
static void RestoreRegisters(void) {
reg_ax=mem_readw(SegPhys(ss)+reg_sp+ 0);
reg_cx=mem_readw(SegPhys(ss)+reg_sp+ 2);
reg_dx=mem_readw(SegPhys(ss)+reg_sp+ 4);
reg_bx=mem_readw(SegPhys(ss)+reg_sp+ 6);
reg_si=mem_readw(SegPhys(ss)+reg_sp+ 8);
reg_di=mem_readw(SegPhys(ss)+reg_sp+10);
reg_bp=mem_readw(SegPhys(ss)+reg_sp+12);
SegSet16(ds,mem_readw(SegPhys(ss)+reg_sp+14));
SegSet16(es,mem_readw(SegPhys(ss)+reg_sp+16));
reg_sp+=20;
}
bool DOS_Terminate(bool tsr) {
dos.return_code=reg_al;
dos.return_mode=RETURN_EXIT;
Bit16u mempsp = dos.psp;
DOS_PSP curpsp(dos.psp);
if (dos.psp==curpsp.GetParent()) return true;
/* Free Files owned by process */
if (!tsr) curpsp.CloseFiles();
/* Get the termination address */
RealPt old22 = curpsp.GetInt22();
/* Restore vector 22,23,24 */
curpsp.RestoreVectors();
/* Set the parent PSP */
dos.psp = curpsp.GetParent();
DOS_PSP parentpsp(curpsp.GetParent());
/* Restore the DTA of the parent psp */
dos.dta = parentpsp.GetDTA();
/* Restore the SS:SP to the previous one */
SegSet16(ss,RealSeg(parentpsp.GetStack()));
reg_sp = RealOff(parentpsp.GetStack());
/* Restore the old CS:IP from int 22h */
RestoreRegisters();
/* Set the CS:IP stored in int 0x22 back on the stack */
mem_writew(SegPhys(ss)+reg_sp+0,RealOff(old22));
mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(old22));
// Free memory owned by process
if (!tsr) DOS_FreeProcessMemory(mempsp);
return true; return true;
} }
@ -97,20 +123,19 @@ bool DOS_Terminate(bool tsr) {
static bool MakeEnv(char * name,Bit16u * segment) { static bool MakeEnv(char * name,Bit16u * segment) {
/* If segment to copy environment is 0 copy the caller's environment */ /* If segment to copy environment is 0 copy the caller's environment */
PSP * psp=(PSP *)HostMake(dos.psp,0); DOS_PSP psp(dos.psp);
Bit8u * envread,*envwrite; Bit8u * envread,*envwrite;
Bit16u envsize=1; Bit16u envsize=1;
bool parentenv=true; bool parentenv=true;
if (*segment==0) { if (*segment==0) {
if (!psp->environment) parentenv=false; //environment seg=0 if (!psp.GetEnvironment()) parentenv=false; //environment seg=0
envread=HostMake(psp->environment,0); envread=HostMake(psp.GetEnvironment(),0);
} else { } else {
if (!*segment) parentenv=false; //environment seg=0 if (!*segment) parentenv=false; //environment seg=0
envread=HostMake(*segment,0); envread=HostMake(*segment,0);
} }
//TODO Make a good DOS first psp
if (parentenv) { if (parentenv) {
for (envsize=0; ;envsize++) { for (envsize=0; ;envsize++) {
if (envsize>=MAXENV - ENV_KEEPFREE) { if (envsize>=MAXENV - ENV_KEEPFREE) {
@ -132,319 +157,189 @@ static bool MakeEnv(char * name,Bit16u * segment) {
} }
*((Bit16u *) envwrite)=1; *((Bit16u *) envwrite)=1;
envwrite+=2; envwrite+=2;
//TODO put the filename here
return DOS_Canonicalize(name,(char *)envwrite); return DOS_Canonicalize(name,(char *)envwrite);
}; };
bool DOS_NewPSP(Bit16u pspseg) { bool DOS_NewPSP(Bit16u segment, Bit16u size)
PSP * newpsp=(PSP *)HostMake(pspseg,0); {
PSP * prevpsp=(PSP *)HostMake(dos.psp,0); DOS_PSP psp(segment);
psp.MakeNew(size);
memset((void *)newpsp,0,sizeof(PSP)); DOS_PSP psp_parent(psp.GetParent());
newpsp->exit[0]=0xcd;newpsp->exit[1]=0x20; psp.CopyFileTable(&psp_parent);
newpsp->service[0]=0xcd;newpsp->service[0]=0x21;newpsp->service[0]=0xcb;
newpsp->mem_size=prevpsp->mem_size;
newpsp->environment=0;
newpsp->int_22=RealGetVec(0x22);
newpsp->int_23=RealGetVec(0x23);
newpsp->int_24=RealGetVec(0x24);
newpsp->psp_parent=dos.psp;
newpsp->prev_psp=0xFFFFFFFF;
Bit32u i;
Bit8u * prevfile=Real2Host(prevpsp->file_table);
for (i=0;i<20;i++) newpsp->files[i]=prevfile[i];
newpsp->max_files=20;
newpsp->file_table=RealMake(pspseg,offsetof(PSP,files));
/* Save the old DTA in this psp */
newpsp->dta=dos.dta;
/* Setup the DTA */
dos.dta=RealMake(pspseg,0x80);
return true; return true;
}; };
static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) { static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
PSP * psp=(PSP *)HostMake(pspseg,0); /* Fix the PSP for psp and environment MCB's */
/* Fix the PSP index of this MCB */
MCB * pspmcb=(MCB *)HostMake(pspseg-1,0); MCB * pspmcb=(MCB *)HostMake(pspseg-1,0);
pspmcb->psp_segment=pspseg; pspmcb->psp_segment=pspseg;
MCB * envmcb=(MCB *)HostMake(envseg-1,0); MCB * envmcb=(MCB *)HostMake(envseg-1,0);
envmcb->psp_segment=pspseg; envmcb->psp_segment=pspseg;
memset((void *)psp,0,sizeof(PSP)); DOS_PSP psp(pspseg);
Bit32u i; psp.MakeNew(memsize);
psp.SetEnvironment(envseg);
psp->exit[0]=0xcd;psp->exit[1]=0x20; psp.SetFileHandle(STDIN ,DOS_FindDevice("CON"));
psp->mem_size=memsize+pspseg; psp.SetFileHandle(STDOUT,DOS_FindDevice("CON"));
psp->environment=envseg; psp.SetFileHandle(STDERR,DOS_FindDevice("CON"));
psp.SetFileHandle(STDAUX,DOS_FindDevice("CON"));
psp->int_22=RealGetVec(0x22); psp.SetFileHandle(STDNUL,DOS_FindDevice("CON"));
psp->int_23=RealGetVec(0x23); psp.SetFileHandle(STDPRN,DOS_FindDevice("CON"));
psp->int_24=RealGetVec(0x24);
psp->service[0]=0xcd;psp->service[0]=0x21;psp->service[0]=0xcb;
psp->psp_parent=dos.psp;
psp->prev_psp=RealMake(dos.psp,0);
for (i=0;i<20;i++) psp->files[i]=0xff;
psp->files[STDIN]=DOS_FindDevice("CON");
psp->files[STDOUT]=DOS_FindDevice("CON");
psp->files[STDERR]=DOS_FindDevice("CON");
psp->files[STDAUX]=DOS_FindDevice("CON");
psp->files[STDNUL]=DOS_FindDevice("CON");
psp->files[STDPRN]=DOS_FindDevice("CON");
psp->max_files=20;
psp->file_table=RealMake(pspseg,offsetof(PSP,files));
/* Save old DTA in psp */ /* Save old DTA in psp */
psp->dta=dos.dta; psp.SetDTA(dos.dta);
/* Setup the DTA */ /* Setup the DTA */
dos.dta=RealMake(pspseg,0x80); dos.dta=RealMake(pspseg,0x80);
} }
static void SetupCMDLine(Bit16u pspseg,ParamBlock * block) { static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block)
PSP * psp=(PSP *)HostMake(pspseg,0); {
DOS_PSP psp(pspseg);
if (block->exec.cmdtail) { // if cmdtail==0 it will inited as empty in SetCommandTail
memcpy((void *)&psp->cmdtail,(void *)Real2Host(block->exec.cmdtail),128); psp.SetCommandTail(block.exec.cmdtail);
} else {
char temp[]="";
psp->cmdtail.count=strlen(temp);
strcpy((char *)&psp->cmdtail.buffer,temp);
psp->cmdtail.buffer[0]=0x0d;
}
} }
bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
EXE_Header head;Bitu i;
Bit16u fhandle;Bit16u len;Bit32u pos;
static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) { Bit16u pspseg,envseg,loadseg,memsize,readsize;
Bit16u fhandle; HostPt loadaddress;RealPt relocpt;
Bit16u size;Bit16u readsize; Bitu headersize,imagesize;
Bit16u envseg,comseg; DOS_ParamBlock block(block_pt);
Bit32u pos; block.LoadData();
if (flags!=LOADNGO && flags!=OVERLAY) {
PSP * callpsp=(PSP *)HostMake(dos.psp,0); E_Exit("DOS:Not supported execute mode %d for file %s",flags,name);
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
if (flag!=OVERLAY) {
/* Allocate a new Environment */
envseg=block->exec.envseg;
if (!MakeEnv(name,&envseg)) return false;
/* Allocate max memory for COM file and PSP */
size=0xffff;
DOS_AllocateMemory(&comseg,&size);
//TODO Errors check for minimun of 64kb in pages
if (Bit32u(size <<4)<0x1000) {
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
} }
DOS_AllocateMemory(&comseg,&size); /* Check for EXE or COM File */
} else {
comseg=block->overlay.loadseg;
}
/* Memory allocated now load the program */
/* Now copy the File into allocated memory */
pos=0;
DOS_SeekFile(fhandle,&pos,0);
readsize=0xffff-256;
if (flag==OVERLAY) {
DOS_ReadFile(fhandle,HostMake(comseg,0),&readsize);
} else {
DOS_ReadFile(fhandle,HostMake(comseg,256),&readsize);
}
DOS_CloseFile(fhandle);
if (flag==OVERLAY) /* Everything what should be done for Overlays */
return true;
SetupPSP(comseg,size,envseg);
SetupCMDLine(comseg,block);
/* Setup termination Address */
RealSetVec(0x22,RealMakeSeg(cs,reg_ip));
/* Everything setup somewhat setup CS:IP and SS:SP */
/* First save the SS:SP of program that called execute */
callpsp->stack=RealMakeSeg(ss,reg_sp);
/* Clear out first Stack entry to point to int 20h at psp:0 */
real_writew(comseg,0xfffe,0);
dos.psp=comseg;
switch (flag) {
case LOADNGO:
SegSet16(cs,comseg);
SegSet16(ss,comseg);
SegSet16(ds,comseg);
SegSet16(es,comseg);
flags.intf=true;
reg_ip=0x100;
reg_sp=0xFFFE;
reg_ax=0;
reg_bx=reg_cx=reg_dx=reg_si=reg_di=reg_bp=0;
return true;
case LOAD:
block->exec.initsssp=RealMake(comseg,0xfffe);
block->exec.initcsip=RealMake(comseg,0x100);
return true;
}
return false;
}
static bool EXE_Load(char * name,ParamBlock* _block,Bit8u flag) {
EXE_Header header;
Bit16u fhandle;Bit32u i;
Bit16u size,minsize,maxsize,freesize;Bit16u readsize;
Bit16u envseg,pspseg,exeseg;
Bit32u imagesize,headersize;
// During loading process, th param-block-mem might be overwritten (HostPt!) and
// therefore change the relocation address, so save these values.
ParamBlock block;
memcpy(&block,_block,sizeof(ParamBlock));
PSP * callpsp=(PSP *)HostMake(dos.psp,0);
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
if (flag!=OVERLAY) {
/* Allocate a new Environment */
envseg=block.exec.envseg;
if (!MakeEnv(name,&envseg)) return false;
};
/* First Read the EXE Header */
readsize=sizeof(EXE_Header);
DOS_ReadFile(fhandle,(Bit8u*)&header,&readsize);
/* Calculate the size of the image to load */
headersize=header.headersize*16;
imagesize=header.pages*512-headersize;
if (flag!=OVERLAY) {
minsize=long2para(imagesize+(header.minmemory<<4)+256);
if (header.maxmemory!=0) maxsize=long2para(imagesize+(header.maxmemory<<4)+256);
else maxsize=0xffff;
freesize=0xffff;
/* Check for enough free memory */
DOS_AllocateMemory(&exeseg,&freesize);
if (minsize>freesize) {
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
}
if (maxsize>freesize) {
size=freesize;
} else size=maxsize;
if ((header.minmemory|header.maxmemory)==0) {
size=freesize;
E_Exit("Special case exe header max and min=0");
}
if (!DOS_AllocateMemory(&pspseg,&size)) {
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
}
SetupPSP(pspseg,size,envseg);
SetupCMDLine(pspseg,&block);
exeseg=pspseg+16;
} else {
/* For OVERLAY */
exeseg=block.overlay.loadseg;
}
/* Load the image in 32k blocks */
DOS_SeekFile(fhandle,&headersize,0);
Bit8u * imageoff=HostMake(exeseg,0);
//TODO File size checking and remove size
// Remove psp size
// imagesize=256;
// Maybe remove final page and add last bytes on page
if (header.extrabytes) {
imagesize-=512;
imagesize+=header.extrabytes;
};
while (imagesize>0x7FFF) {
readsize=0x8000;
DOS_ReadFile(fhandle,imageoff,&readsize);
if (readsize!=0x8000) {
E_Exit("Illegal header");
}
imageoff+=0x8000;
imagesize-=0x8000;
}
if (imagesize>0) {
readsize=(Bit16u) imagesize;
DOS_ReadFile(fhandle,imageoff,&readsize);
}
headersize=header.reloctable;
DOS_SeekFile(fhandle,&headersize,0);
RealPt reloc;
for (i=0;i<header.relocations;i++) {
readsize=4;
DOS_ReadFile(fhandle,(Bit8u *)&reloc,&readsize);
PhysPt address=Real2Phys(RealMake(RealSeg(reloc)+exeseg,RealOff(reloc)));
Bit16u change=mem_readw(address);
if (flag==OVERLAY) {
change+=block.overlay.relocation;
} else {
change+=exeseg;
};
mem_writew(address,change);
};
DOS_CloseFile(fhandle);
if (flag==OVERLAY) return true;
/* Setup termination Address */
RealSetVec(0x22,RealMakeSeg(cs,reg_ip));
/* Start up the actual EXE if we need to */
//TODO check for load and return
callpsp->stack=RealMakeSeg(ss,reg_sp);
dos.psp=pspseg;
SegSet16(cs,exeseg+header.initCS);
SegSet16(ss,exeseg+header.initSS);
SegSet16(ds,pspseg);
SegSet16(es,pspseg);
reg_ip=header.initIP;
reg_sp=header.initSP;
reg_ax=0;
reg_bx=reg_cx=reg_dx=reg_si=reg_di=reg_bp=0;
flags.intf=true;
return true;
};
bool DOS_Execute(char * name,ParamBlock * block,Bit8u flags) {
EXE_Header head;
Bit16u fhandle;
Bit16u size;
bool iscom=false; bool iscom=false;
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false; if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
len=sizeof(EXE_Header);
size=sizeof(EXE_Header); if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&len)) {
if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&size)) {
DOS_CloseFile(fhandle); DOS_CloseFile(fhandle);
return false; return false;
} }
if (!DOS_CloseFile(fhandle)) return false; /* Convert the header to correct endian, i hope this works */
if (size<sizeof(EXE_Header)) iscom=true; HostPt endian=(HostPt)&head;
if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true; for (i=0;i<sizeof(EXE_Header)/2;i++) {
*((Bit16u *)endian)=readw(endian);
if (iscom) { endian+=2;
return COM_Load(name,block,flags);
} else {
return EXE_Load(name,block,flags);
} }
if (len<sizeof(EXE_Header)) iscom=true;
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 (flags!=OVERLAY) {
/* Create an environment block */
envseg=block.exec.envseg;
if (!MakeEnv(name,&envseg)) {
DOS_CloseFile(fhandle);
return false;
}
/* Get Memory */
Bit16u minsize,maxsize;Bit16u maxfree=0xffff;DOS_AllocateMemory(&pspseg,&maxfree);
if (iscom) {
minsize=0x1000;maxsize=0xffff;
} else { /* Exe size calculated from header */
minsize=long2para(imagesize+(head.minmemory<<4)+256);
if (head.maxmemory!=0) maxsize=long2para(imagesize+(head.maxmemory<<4)+256);
else maxsize=0xffff;
}
if (maxfree<minsize) {
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
DOS_FreeMemory(envseg);
return false;
}
if (maxfree<maxsize) memsize=maxfree;
else memsize=maxsize;
if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory");
loadseg=pspseg+16;
/* Setup a psp */
SetupPSP(pspseg,memsize,envseg);
SetupCMDLine(pspseg,block);
} else loadseg=block.overlay.loadseg;
/* Load the executable */
loadaddress=HostMake(loadseg,0);
if (iscom) { /* COM Load 64k - 256 bytes max */
pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
readsize=0xffff-256;
DOS_ReadFile(fhandle,loadaddress,&readsize);
} else { /* EXE Load in 32kb blocks and then relocate */
pos=headersize;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET);
while (imagesize>0x7FFF) {
readsize=0x8000;DOS_ReadFile(fhandle,loadaddress,&readsize);
if (readsize!=0x8000) E_Exit("Illegal header");
loadaddress+=0x8000;imagesize-=0x8000;
}
if (imagesize>0) {
readsize=(Bit16u)imagesize;DOS_ReadFile(fhandle,loadaddress,&readsize);
if (readsize!=imagesize) E_Exit("Illegal header");
}
/* Relocate the exe image */
Bit16u relocate;
if (flags==OVERLAY) relocate=block.overlay.relocation;
else relocate=loadseg;
pos=head.reloctable;DOS_SeekFile(fhandle,&pos,0);
for (i=0;i<head.relocations;i++) {
readsize=4;DOS_ReadFile(fhandle,(Bit8u *)&relocpt,&readsize);
relocpt=readd((Bit8u *)&relocpt); //Endianize
PhysPt address=PhysMake(RealSeg(relocpt)+loadseg,RealOff(relocpt));
mem_writew(address,mem_readw(address)+relocate);
}
}
DOS_CloseFile(fhandle);
CALLBACK_SCF(false); /* Carry flag cleared for caller if successfull */
if (flags==OVERLAY) return true; /* Everything done for overlays */
RealPt csip,sssp;
if (iscom) {
csip=RealMake(pspseg,0x100);
sssp=RealMake(pspseg,0xfffe);
mem_writew(PhysMake(pspseg,0xfffe),0);
} else {
csip=RealMake(loadseg+head.initCS,head.initIP);
sssp=RealMake(loadseg+head.initSS,head.initSP);
}
if (flags==LOADNGO) {
/* Get Caller's program CS:IP of the stack and set termination address to that */
RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp)));
SaveRegisters();
DOS_PSP callpsp(dos.psp);
/* Save the SS:SP on the PSP of calling program */
callpsp.SetStack(RealMakeSeg(ss,reg_sp));
/* Switch the psp's and set new DTA */
dos.psp=pspseg;
DOS_PSP newpsp(dos.psp);
dos.dta=newpsp.GetDTA();
/* save vectors */
newpsp.SaveVectors();
/* copy fcbs */
newpsp.SetFCB1(block.exec.fcb1);
newpsp.SetFCB2(block.exec.fcb2);
/* Set the stack for new program */
SegSet16(ss,RealSeg(sssp));reg_sp=RealOff(sssp);
/* Add some flags and CS:IP on the stack for the IRET */
reg_sp-=6;
mem_writew(SegPhys(ss)+reg_sp+0,RealOff(csip));
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;
SegSet16(ds,pspseg);SegSet16(es,pspseg);
#if C_DEBUG
/* Started from debug.com, then set breakpoint at start */
DEBUG_CheckExecuteBreakpoint(RealSeg(csip),RealOff(csip));
#endif
return true;
}
return false;
} }

View File

@ -30,44 +30,46 @@
#define DOS_FILESTART 4 #define DOS_FILESTART 4
#define FCB_SUCCESS 0
#define FCB_READ_NODATA 1
#define FCB_READ_PARTIAL 3
#define FCB_ERR_NODATA 1
#define FCB_ERR_EOF 3
#define FCB_ERR_WRITE 1
DOS_File * Files[DOS_FILES]; DOS_File * Files[DOS_FILES];
DOS_Drive * Drives[DOS_DRIVES]; DOS_Drive * Drives[DOS_DRIVES];
static Bit8u CurrentDrive=2; //Init on C:
Bit8u DOS_GetDefaultDrive(void) { Bit8u DOS_GetDefaultDrive(void) {
return CurrentDrive; return dos.current_drive;
} }
void DOS_SetDefaultDrive(Bit8u drive) { void DOS_SetDefaultDrive(Bit8u drive) {
if (drive<=DOS_DRIVES) CurrentDrive=drive; if (drive<=DOS_DRIVES) dos.current_drive=drive;
} }
bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
//TODO Hope this is ok :) char tempdir[DOS_PATHLENGTH];
char upname[DOS_PATHLENGTH]; char upname[DOS_PATHLENGTH];
Bit32u r=0;Bit32u w=0;Bit32u namestart=0; Bitu r,w;
bool hasdrive=false; *drive=dos.current_drive;
*drive=CurrentDrive; /* First get the drive */
char tempdir[128]; if (name[1]==':') {
//TODO Maybe check for illegal characters *drive=(name[0] | 0x20)-'a';
name+=2;
}
if (*drive>=DOS_DRIVES || !Drives[*drive]) {
DOS_SetError(DOSERR_PATH_NOT_FOUND);
return false;
}
r=0;w=0;
while (name[r]!=0 && (r<DOS_PATHLENGTH)) { while (name[r]!=0 && (r<DOS_PATHLENGTH)) {
Bit8u c=name[r++]; Bit8u c=name[r++];
if ((c>='a') && (c<='z')) {upname[w++]=c-32;continue;} if ((c>='a') && (c<='z')) {upname[w++]=c-32;continue;}
if ((c>='A') && (c<='Z')) {upname[w++]=c;continue;} if ((c>='A') && (c<='Z')) {upname[w++]=c;continue;}
if ((c>='0') && (c<='9')) {upname[w++]=c;continue;} if ((c>='0') && (c<='9')) {upname[w++]=c;continue;}
switch (c) { switch (c) {
case ':':
if (hasdrive) { DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; }
else hasdrive=true;
if ((upname[0]>='A') && (upname[0]<='Z')) {
*drive=upname[0]-'A';
w=0;
} else {
DOS_SetError(DOSERR_PATH_NOT_FOUND);return false;
}
break;
case '/': case '/':
upname[w++]='\\'; upname[w++]='\\';
break; break;
@ -83,15 +85,9 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
break; break;
} }
} }
if (r>=DOS_PATHLENGTH) { DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; }
upname[w]=0; upname[w]=0;
/* This should get us an upcase filename and no incorrect chars */
/* Now parse the new file name to make the final filename */ /* Now parse the new file name to make the final filename */
if ((*drive>=26)) {
DOS_SetError(DOSERR_INVALID_DRIVE);return false;
};
if (!Drives[*drive]) {
DOS_SetError(DOSERR_INVALID_DRIVE);return false;
};
if (upname[0]!='\\') strcpy(fullname,Drives[*drive]->curdir); if (upname[0]!='\\') strcpy(fullname,Drives[*drive]->curdir);
else fullname[0]=0; else fullname[0]=0;
Bit32u lastdir=0;Bit32u t=0; Bit32u lastdir=0;Bit32u t=0;
@ -126,8 +122,13 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
lastdir=strlen(fullname); lastdir=strlen(fullname);
//TODO Maybe another check for correct type because of .... stuff //TODO Maybe another check for correct type because of .... stuff
if (lastdir!=0) strcat(fullname,"\\"); if (lastdir!=0) strcat(fullname,"\\");
char * ext=strchr(tempdir,'.');
if (ext) {
ext[4]=0;
Bitu blah=strlen(tempdir);
if (strlen(tempdir)>12) memmove(tempdir+8,ext,5);
} else tempdir[8]=0;
strcat(fullname,tempdir); strcat(fullname,tempdir);
tempdir[0]=0; tempdir[0]=0;
w=0;r++; w=0;r++;
continue; continue;
@ -181,21 +182,36 @@ bool DOS_Rename(char * oldname,char * newname) {
if (Drives[drivenew]->Rename(fullold,fullnew)) return true; if (Drives[drivenew]->Rename(fullold,fullnew)) return true;
DOS_SetError(DOSERR_FILE_NOT_FOUND); DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false; return false;
}; }
bool DOS_FindFirst(char * search,Bit16u attr) { bool DOS_FindFirst(char * search,Bit16u attr) {
DOS_DTA dta(dos.dta);
Bit8u drive;char fullsearch[DOS_PATHLENGTH]; Bit8u drive;char fullsearch[DOS_PATHLENGTH];
char dir[DOS_PATHLENGTH];char pattern[DOS_PATHLENGTH];
if (!DOS_MakeName(search,fullsearch,&drive)) return false; if (!DOS_MakeName(search,fullsearch,&drive)) return false;
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); /* Split the search in dir and pattern */
dtablock->sattr=attr | DOS_ATTR_ARCHIVE; char * find_last;
dtablock->sdrive=drive; find_last=strrchr(fullsearch,'\\');
return Drives[drive]->FindFirst(fullsearch,dtablock); if (!find_last) { /*No dir */
}; strcpy(pattern,fullsearch);
dir[0]=0;
} else {
*find_last=0;
strcpy(pattern,find_last+1);
strcpy(dir,fullsearch);
}
dta.SetupSearch(drive,(Bit8u)attr,pattern);
if (Drives[drive]->FindFirst(dir,dta)) return true;
DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false;
}
bool DOS_FindNext(void) { bool DOS_FindNext(void) {
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); DOS_DTA dta(dos.dta);
return Drives[dtablock->sdrive]->FindNext(dtablock); if (Drives[dta.GetSearchDrive()]->FindNext(dta)) return true;
}; DOS_SetError(DOSERR_FILE_NOT_FOUND);
return false;
}
bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount) { bool DOS_ReadFile(Bit16u entry,Bit8u * data,Bit16u * amount) {
@ -269,9 +285,9 @@ bool DOS_CloseFile(Bit16u entry) {
}; };
//TODO Figure this out with devices :) //TODO Figure this out with devices :)
PSP * psp=(PSP *)HostMake(dos.psp,0); DOS_PSP psp(dos.psp);
Bit8u * table=Real2Host(psp->file_table); psp.SetFileHandle(entry,0xff);
table[entry]=0xFF;
/* Devices won't allow themselves to be closed or killed */ /* Devices won't allow themselves to be closed or killed */
if (Files[handle]->Close()) { if (Files[handle]->Close()) {
delete Files[handle]; delete Files[handle];
@ -282,7 +298,7 @@ bool DOS_CloseFile(Bit16u entry) {
bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) { bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
char fullname[DOS_PATHLENGTH];Bit8u drive; char fullname[DOS_PATHLENGTH];Bit8u drive;
PSP * psp=(PSP *)HostMake(dos.psp,0); DOS_PSP psp(dos.psp);
if (!DOS_MakeName(name,fullname,&drive)) return false; if (!DOS_MakeName(name,fullname,&drive)) return false;
/* Check for a free file handle */ /* Check for a free file handle */
Bit8u handle=DOS_FILES;Bit8u i; Bit8u handle=DOS_FILES;Bit8u i;
@ -297,21 +313,14 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
return false; return false;
} }
/* We have a position in the main table now find one in the psp table */ /* We have a position in the main table now find one in the psp table */
Bit8u * table=Real2Host(psp->file_table); *entry = psp.FindFreeFileEntry();
*entry=0xff;
for (i=0;i<psp->max_files;i++) {
if (table[i]==0xFF) {
*entry=i;
break;
}
}
if (*entry==0xff) { if (*entry==0xff) {
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
return false; return false;
} }
bool foundit=Drives[drive]->FileCreate(&Files[handle],fullname,attributes); bool foundit=Drives[drive]->FileCreate(&Files[handle],fullname,attributes);
if (foundit) { if (foundit) {
table[*entry]=handle; psp.SetFileHandle(*entry,handle);
return true; return true;
} else { } else {
return false; return false;
@ -320,7 +329,9 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) { bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
/* First check for devices */ /* First check for devices */
PSP * psp=(PSP *)HostMake(dos.psp,0); if (flags>2) LOG_DEBUG("Special file open command %X file %s",flags,name);
flags&=3;
DOS_PSP psp(dos.psp);
Bit8u handle=DOS_FindDevice((char *)name); Bit8u handle=DOS_FindDevice((char *)name);
bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i; bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i;
if (handle!=255) { if (handle!=255) {
@ -341,14 +352,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
} }
} }
/* We have a position in the main table now find one in the psp table */ /* We have a position in the main table now find one in the psp table */
Bit8u * table=Real2Host(psp->file_table); *entry = psp.FindFreeFileEntry();
*entry=0xff;
for (i=0;i<psp->max_files;i++) {
if (table[i]==0xFF) {
*entry=i;
break;
}
}
if (*entry==0xff) { if (*entry==0xff) {
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
return false; return false;
@ -356,7 +360,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
bool exists=false; bool exists=false;
if (!device) exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags); if (!device) exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags);
if (exists || device ) { if (exists || device ) {
table[*entry]=handle; psp.SetFileHandle(*entry,handle);
return true; return true;
} else { } else {
DOS_SetError(DOSERR_FILE_NOT_FOUND); DOS_SetError(DOSERR_FILE_NOT_FOUND);
@ -391,7 +395,7 @@ bool DOS_Canonicalize(char * name,char * big) {
big[2]='\\'; big[2]='\\';
strcpy(&big[3],fullname); strcpy(&big[3],fullname);
return true; return true;
}; }
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) { bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) {
if (drive==0) drive=DOS_GetDefaultDrive(); if (drive==0) drive=DOS_GetDefaultDrive();
@ -400,7 +404,7 @@ bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * c
DOS_SetError(DOSERR_INVALID_DRIVE); DOS_SetError(DOSERR_INVALID_DRIVE);
return false; return false;
} }
return Drives[drive]->FreeSpace(bytes,sectors,clusters,free); return Drives[drive]->AllocationInfo(bytes,sectors,clusters,free);
} }
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) { bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) {
@ -413,20 +417,13 @@ bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) {
DOS_SetError(DOSERR_INVALID_HANDLE); DOS_SetError(DOSERR_INVALID_HANDLE);
return false; return false;
}; };
PSP * psp=(PSP *)HostMake(dos.psp,0); DOS_PSP psp(dos.psp);
Bit8u * table=Real2Host(psp->file_table); *newentry = psp.FindFreeFileEntry();
*newentry=0xff;
for (Bit16u i=0;i<psp->max_files;i++) {
if (table[i]==0xFF) {
*newentry=i;
break;
}
}
if (*newentry==0xff) { if (*newentry==0xff) {
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES); DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
return false; return false;
} }
table[*newentry]=handle; psp.SetFileHandle(*newentry,handle);
return true; return true;
}; };
@ -449,17 +446,15 @@ bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) {
DOS_CloseFile(newentry); DOS_CloseFile(newentry);
return false; return false;
}; };
PSP * psp=(PSP *)HostMake(dos.psp,0); DOS_PSP psp(dos.psp);
Bit8u * table=Real2Host(psp->file_table); psp.SetFileHandle(newentry,(Bit8u)entry);
table[newentry]=(Bit8u)entry;
return true; return true;
}; };
bool DOS_CreateTempFile(char * name,Bit16u * entry) { bool DOS_CreateTempFile(char * name,Bit16u * entry) {
/* First add random crap to the end of the name and try to open */
/* First add random crap to the end of the name and try to open */
/* Todo maybe check for euhm existence of the path name */ /* Todo maybe check for euhm existence of the path name */
char * tempname; char * tempname;
tempname=name+strlen(name); tempname=name+strlen(name);
@ -472,41 +467,26 @@ bool DOS_CreateTempFile(char * name,Bit16u * entry) {
for (i=9;i<12;i++) { for (i=9;i<12;i++) {
tempname[i]=(rand()%26)+'A'; tempname[i]=(rand()%26)+'A';
} }
tempname[13]=0; tempname[12]=0;
} while (!DOS_CreateFile(name,0,entry)); } while (!DOS_CreateFile(name,0,entry));
return true; return true;
} }
#if 1 #if 1
static bool FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){
char naam[15]; static bool FCB_MakeName2 (DOS_FCB & fcb, char* outname, Bit8u* outdrive){
Bit8s teller=0; char short_name[DOS_FCBNAME];
Bit8u drive=fcb->Get_drive(); fcb.GetName(short_name);
if(drive!=0){ return DOS_MakeName(short_name,outname, outdrive);
naam[0]=(drive-1)+'A';
naam[1]=':';
naam[2]='\0';}
else{
naam[0]='\0';
};
char temp[10];
fcb->Get_filename(temp);
temp[8]='.';
temp[9]='\0';
strcat(naam,temp);
char ext[4];
fcb->Get_ext(ext);
ext[3]='\0';
strcat(naam,ext);
return DOS_MakeName(naam,outname, outdrive);
} }
#define FCB_SEP ":.;,=+" #define FCB_SEP ":.;,=+"
#define ILLEGAL ":.;,=+ \t/\"[]<>|" #define ILLEGAL ":.;,=+ \t/\"[]<>|"
static bool isvalid(const char* in){ static bool isvalid(const char in){
const char ill[]=ILLEGAL; const char ill[]=ILLEGAL;
return (Bit8u(*in)>0x1F) && (strchr(ill,*in)==0); return (Bit8u(in)>0x1F) && (!strchr(ill,in));
} }
static void vullen (char* veld,char* pveld){ static void vullen (char* veld,char* pveld){
@ -515,218 +495,352 @@ static void vullen (char* veld,char* pveld){
} }
return; return;
} }
#define PARSE_SEP_STOP 0x01
#define PARSE_DFLT_DRIVE 0x02
#define PARSE_BLNK_FNAME 0x04
#define PARSE_BLNK_FEXT 0x08
#define PARSE_RET_NOWILD 0
#define PARSE_RET_WILD 1
#define PARSE_RET_BADDRIVE 0xff
Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change){ Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change){
char* backup;
backup=string; char * string_begin=string;Bit8u ret=0;
DOS_FCB fcb(seg,offset); DOS_FCB fcb(seg,offset);
Bit8u retwaarde=0; bool hasdrive,hasname,hasext;
char naam[9]=" "; hasdrive=hasname=hasext=false;
char ext[4]=" "; Bitu index;bool finished;Bit8u fill;
if(parser & 1) { //ignore leading seperator /* First get the old data from the fcb */
char sep[] = FCB_SEP; #pragma pack (1)
char a[2]; union {
struct {
char drive[2];
char name[9];
char ext[4];
} part GCC_ATTRIBUTE (packed) ;
char full[DOS_FCBNAME];
} fcb_name;
#pragma pack()
/* Get the old information from the previous fcb */
fcb.GetName(fcb_name.full);fcb_name.part.drive[1]=0;fcb_name.part.name[8]=0;fcb_name.part.ext[3]=0;
/* Strip of the leading sepetaror */
if((parser & PARSE_SEP_STOP) && *string) { //ignore leading seperator
char sep[] = FCB_SEP;char a[2];
a[0]= *string;a[1]='\0'; a[0]= *string;a[1]='\0';
if (strcspn(a,sep)==0) string++; if (strcspn(a,sep)==0) string++;
} }
if((!(parser &4)) ==true){ // fill name with spaces if no name /* strip leading spaces */
fcb.Set_filename(naam);
}
if((!(parser &8)) ==true){ // fill ext with spaces if no ext
fcb.Set_ext(ext);
}
if((parser & 2)==false) fcb.Set_drive(0); //Set allready the defaultdrive (Will stay set when it's not specified)
// strip leading spaces
while((*string==' ')||(*string=='\t')) string++; while((*string==' ')||(*string=='\t')) string++;
if( *(string+1)==':') { /* Check for a drive */
Bit8u drive=toupper(*string); if (string[1]==':') {
if( (drive>'Z') | (drive<'A') | (Drives[drive-'A']==NULL)) { fcb_name.part.drive[0]=0;
*change=string-backup; hasdrive=true;
return 0xFF; if (isalpha(string[0]) && Drives[toupper(string[0])-'A']) {
} fcb_name.part.drive[0]=toupper(string[0])-'A'+1;
fcb.Set_drive(drive-'A'+1); } else ret=0xff;
string+=2; string+=2;
} }
//startparsing /* Special checks for . and .. */
char* pnaam=naam; if (string[0]=='.') {
while(isvalid(string)==true) {
if(*string=='*'){
vullen(naam,pnaam); //fill with ????
string++; string++;
retwaarde=1; if (!string[0]) {
break; hasname=true;
ret=PARSE_RET_NOWILD;
strcpy(fcb_name.part.name,". ");
goto savefcb;
} }
if (string[1]=='.' && !string[1]) {
*pnaam=*string;
pnaam++;
string++; string++;
hasname=true;
ret=PARSE_RET_NOWILD;
strcpy(fcb_name.part.name,".. ");
goto savefcb;
} }
fcb.Set_filename(naam); goto checkext;
if((*string=='.')==false) {
*change=string-backup;
return retwaarde;
} }
//extension exist /* Copy the name */
hasname=true;finished=false;fill=' ';index=0;
while (index<8) {
if (!finished) {
if (string[0]=='*') {fill='?';fcb_name.part.name[index]='?';if (!ret) ret=1;finished=true;}
else if (string[0]=='?') {fcb_name.part.name[index]='?';if (!ret) ret=1;}
else if (isvalid(string[0])) {fcb_name.part.name[index]=toupper(string[0]);}
else { finished=true;continue; }
string++; string++;
char* pext=ext; } else {
while(isvalid(string)==true) { fcb_name.part.name[index]=fill;
if(*string=='*'){
vullen(ext,pext); //fill with ????
string++;
retwaarde=1;
break;
} }
index++;
*pext=*string;
pext++;
string++;
} }
fcb.Set_ext(ext); if (!(string[0]=='.')) goto savefcb;
*change=string-backup; string++;
return retwaarde; checkext:
/* Copy the extension */
hasext=true;finished=false;fill=' ';index=0;
while (index<3) {
if (!finished) {
if (string[0]=='*') {fill='?';fcb_name.part.ext[index]='?';finished=true;}
else if (string[0]=='?') {fcb_name.part.ext[index]='?';if (!ret) ret=1;}
else if (isvalid(string[0])) {fcb_name.part.ext[index]=toupper(string[0]);}
else { finished=true;continue; }
string++;
} else {
fcb_name.part.ext[index]=fill;
}
index++;
}
savefcb:
if (!hasdrive & !(parser & PARSE_DFLT_DRIVE)) fcb_name.part.drive[0]=dos.current_drive+1;
if (!hasname & !(parser & PARSE_BLNK_FNAME)) strcpy(fcb_name.part.name," ");
if (!hasext & !(parser & PARSE_BLNK_FEXT)) strcpy(fcb_name.part.ext," ");
fcb.SetName(fcb_name.part.drive[0],fcb_name.part.name,fcb_name.part.ext);
*change=(Bit8u)(string-string_begin);
return ret;
} }
bool DOS_FCBOpen(Bit16u seg,Bit16u offset) {
static void DTAExtendName(char * name,char * filename,char * ext) {
char * find=strchr(name,'.');
if (find) {
strcpy(ext,find+1);
*find=0;
} else ext[0]=0;
strcpy(filename,name);
Bitu i;
for (i=strlen(name);i<8;i++) filename[i]=' ';filename[8]=0;
for (i=strlen(ext);i<3;i++) ext[i]=' ';ext[3]=0;
}
static void SaveFindResult(DOS_FCB & find_fcb) {
DOS_DTA find_dta(dos.tables.tempdta);
char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;Bit8u drive;
char file_name[9];char ext[4];
find_dta.GetResult(name,size,date,time,attr);
drive=find_fcb.GetDrive();
/* Create a correct file and extention */
DTAExtendName(name,file_name,ext);
DOS_FCB fcb(RealSeg(dos.dta),RealOff(dos.dta));
fcb.Create(find_fcb.Extended());
fcb.SetName(drive,file_name,ext);
fcb.SetSizeDateTime(size,date,time);
}
bool DOS_FCBOpenCreate(Bit16u seg,Bit16u offset) {
DOS_FCB fcb(seg,offset); DOS_FCB fcb(seg,offset);
Bit8u drive; char shortname[DOS_FCBNAME];Bit16u handle;
char fullname[DOS_PATHLENGTH]; fcb.GetName(shortname);
if(!FCB_MakeName (&fcb, fullname, &drive)) return false; if (!DOS_OpenFile(shortname,2,&handle)) return false;
if(!Drives[drive]->FileExists(fullname)) return false; //not really needed as stat will error. fcb.FileOpen((Bit8u)handle);
struct stat stat_block;
if(!Drives[drive]->FileStat(fullname, &stat_block)) return false;
fcb.Set_filesize((Bit32u)stat_block.st_size);
Bit16u constant = 0;
fcb.Set_current_block(constant);
constant=0x80;
fcb.Set_record_size(constant);
struct tm *time;
if((time=localtime(&stat_block.st_mtime))!=0){
constant=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */
fcb.Set_time(constant);
constant=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
fcb.Set_date(constant);
}
else{
constant=6;
fcb.Set_time(constant);
constant=4;
fcb.Set_date(constant);
}
fcb.Set_drive(drive +1);
return true; return true;
} }
bool DOS_FCBClose(Bit16u seg,Bit16u offset) bool DOS_FCBClose(Bit16u seg,Bit16u offset) {
{ DOS_FCB fcb(seg,offset); DOS_FCB fcb(seg,offset);
Bit8u drive; Bit8u fhandle;
char fullname[DOS_PATHLENGTH]; fcb.FileClose(fhandle);
if(!FCB_MakeName (&fcb, fullname, &drive)) return false; DOS_CloseFile(fhandle);
if(!Drives[drive]->FileExists(fullname)) return false; return true;
}
return true;}
bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset) bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset)
{ {
DOS_FCB* fcb = new DOS_FCB(seg,offset); DOS_FCB fcb(seg,offset);
Bit8u drive; RealPt old_dta=dos.dta;dos.dta=dos.tables.tempdta;
Bitu i; char name[DOS_FCBNAME];fcb.GetName(name);
char fullname[DOS_PATHLENGTH]; bool ret=DOS_FindFirst(name,DOS_ATTR_ARCHIVE);
FCB_MakeName (fcb, fullname, &drive); dos.dta=old_dta;
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); if (ret) SaveFindResult(fcb);
dtablock->sattr=DOS_ATTR_ARCHIVE; return ret;
dtablock->sdrive=drive;
if(Drives[drive]->FindFirst(fullname,dtablock)==false) return false;
char naam[9];
char ext[4];
char * point=strrchr(dtablock->name,'.');
if(point==NULL|| *(point+1)=='\0') {
ext[0]=' ';
ext[1]=' ';
ext[2]=' ';
}else{
strcpy(ext,(point+1));
i=strlen((point+1));
while(i!=3) {ext[i]=' ';i++;}
}
if(point!=NULL) *point='\0';
strcpy (naam,dtablock->name);
i=strlen(dtablock->name);
while(i!=8) {naam[i]=' '; i++;}
delete fcb;
DOS_FCB* fcbout= new DOS_FCB((PhysPt)Real2Phys(dos.dta));
fcbout->Set_drive(drive +1);
fcbout->Set_filename(naam);
fcbout->Set_ext(ext);
return true;
} }
bool DOS_FCBFindNext(Bit16u seg,Bit16u offset) bool DOS_FCBFindNext(Bit16u seg,Bit16u offset)
{ {
DOS_FCB* fcb = new DOS_FCB(seg,offset); DOS_FCB fcb(seg,offset);
Bit8u drive; RealPt old_dta=dos.dta;dos.dta=dos.tables.tempdta;
Bitu i; bool ret=DOS_FindNext();
char fullname[DOS_PATHLENGTH]; dos.dta=old_dta;
FCB_MakeName (fcb, fullname, &drive); if (ret) SaveFindResult(fcb);
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta); return ret;
dtablock->sattr=DOS_ATTR_ARCHIVE; }
dtablock->sdrive=drive;
if(Drives[dtablock->sdrive]->FindNext(dtablock)==false) return false; Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset,Bit16u recno) {
char naam[9]; DOS_FCB fcb(seg,offset);
char ext[4]; Bit8u fhandle,cur_rec;Bit16u cur_block,rec_size;
char * point=strrchr(dtablock->name,'.'); fcb.GetSeqData(fhandle,rec_size);
if(point==NULL|| *(point+1)=='\0') { fcb.GetRecord(cur_block,cur_rec);
ext[0]=' '; Bit32u pos=((cur_block*128)+cur_rec)*rec_size;
ext[1]=' '; if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET)) return FCB_READ_NODATA;
ext[2]=' '; Bit16u toread=rec_size;
}else if (!DOS_ReadFile(fhandle,dos_copybuf,&toread)) return FCB_READ_NODATA;
{ if (toread==0) return FCB_READ_NODATA;
strcpy(ext,point+1); if (toread<rec_size) {
i=strlen(point+1); PhysPt fill=Real2Phys(dos.dta)+toread;
while(i!=3) {ext[i]=' ';i++;} Bitu i=rec_size-toread;
for (;i>0;i--) mem_writeb(fill++,0);
} }
MEM_BlockWrite(Real2Phys(dos.dta)+recno*rec_size,dos_copybuf,rec_size);
if (++cur_rec>127) { cur_block++;cur_rec=0; }
fcb.SetRecord(cur_block,cur_rec);
if (toread==rec_size) return FCB_SUCCESS;
if (toread==0) return FCB_READ_NODATA;
return FCB_READ_PARTIAL;
}
if(point!=NULL) *point='\0'; bool DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u recno)
{
DOS_FCB fcb(seg,offset);
Bit8u fhandle,cur_rec;Bit16u cur_block,rec_size;
fcb.GetSeqData(fhandle,rec_size);
fcb.GetRecord(cur_block,cur_rec);
Bit32u pos=((cur_block*128)+cur_rec)*rec_size;
if (!DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET)) return FCB_ERR_WRITE;
MEM_BlockRead(Real2Phys(dos.dta)+recno*rec_size,dos_copybuf,rec_size);
Bit16u towrite=rec_size;
if (!DOS_WriteFile(fhandle,dos_copybuf,&towrite)) return FCB_ERR_WRITE;
Bit32u size;Bit16u date,time;
fcb.GetSizeDateTime(size,date,time);
if (pos+towrite>size) size=pos+towrite;
//TODO Set time to current time?
fcb.SetSizeDateTime(size,date,time);
if (++cur_rec>127) { cur_block++;cur_rec=0; }
fcb.SetRecord(cur_block,cur_rec);
return FCB_SUCCESS;
}
strcpy (naam,dtablock->name); Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) {
i=strlen(dtablock->name);
while(i!=8) {naam[i]=' '; i++;} DOS_FCB fcb(seg,offset);
delete fcb; Bit32u random;Bit16u old_block;Bit8u old_rec;Bit8u error;
DOS_FCB* fcbout= new DOS_FCB(Real2Phys(dos.dta)); /* Set the correct record from the random data */
fcbout->Set_drive(drive +1); fcb.GetRandom(random);
fcbout->Set_filename(naam); if (restore) fcb.GetRecord(old_block,old_rec);
fcbout->Set_ext(ext); fcb.SetRecord((Bit16u)(random / 128),(Bit8u)(random & 127));
// Read records
for (int i=0; i<numRec; i++) {
error = DOS_FCBRead(seg,offset,i);
if (error!=0x00) break;
}
Bit16u new_block;Bit8u new_rec;
fcb.GetRecord(new_block,new_rec);
if (restore) fcb.SetRecord(old_block,old_rec);
/* Update the random record pointer with new position */
fcb.SetRandom(new_block*128+new_rec);
return error;
}
bool DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) {
DOS_FCB fcb(seg,offset);
Bit32u random;Bit16u old_block;Bit8u old_rec;bool noerror;
/* Set the correct record from the random data */
fcb.GetRandom(random);
if (restore) fcb.GetRecord(old_block,old_rec);
fcb.SetRecord((Bit16u)(random / 128),(Bit8u)(random & 127));
/* Write records */
for (int i=0; i<numRec; i++) {
noerror = DOS_FCBWrite(seg,offset,i);
if (!noerror) break;
}
Bit16u new_block;Bit8u new_rec;
fcb.GetRecord(new_block,new_rec);
if (restore) fcb.SetRecord(old_block,old_rec);
/* Update the random record pointer with new position */
fcb.SetRandom(new_block*128+new_rec);
return noerror;
}
bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset,Bit16u numRec) {
char shortname[DOS_PATHLENGTH];Bit16u entry;Bit8u handle;Bit16u rec_size;
DOS_FCB fcb(seg,offset);
fcb.GetName(shortname);
if (!DOS_OpenFile(shortname,0,&entry)) return false;
handle=RealHandle(entry);
Bit32u size=Files[handle]->size;
DOS_CloseFile(entry);fcb.GetSeqData(handle,rec_size);
Bit32u random=(size/rec_size);
if (size % rec_size) random++;
fcb.SetRandom(random);
return true; return true;
} }
bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset){
DOS_FCB fcb(seg,offset);
char shortname[DOS_FCBNAME];
fcb.GetName(shortname);
return DOS_UnlinkFile(shortname);
}
bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset){
DOS_FCB fcbold(seg,offset);
DOS_FCB fcbnew(seg,offset+16);
char oldname[DOS_FCBNAME];
char newname[DOS_FCBNAME];
fcbold.GetName(oldname);fcbnew.GetName(newname);
return DOS_Rename(oldname,newname);
}
void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset) {
DOS_FCB fcb(seg,offset);
Bit16u block;Bit8u rec;
fcb.GetRecord(block,rec);
fcb.SetRandom(block*128+rec);
}
#endif #endif
bool DOS_FileExists(char * name) { bool DOS_FileExists(char * name) {
char fullname[DOS_PATHLENGTH];Bit8u drive; char fullname[DOS_PATHLENGTH];Bit8u drive;
if (!DOS_MakeName(name,fullname,&drive)) return false; if (!DOS_MakeName(name,fullname,&drive)) return false;
return Drives[drive]->FileExists(fullname); return Drives[drive]->FileExists(fullname);
} }
bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters) {
if (!drive) drive=dos.current_drive;
else drive--;
if (!Drives[drive]) return false;
Bit16u _free_clusters;
Drives[drive]->AllocationInfo(_bytes_sector,_sectors_cluster,_total_clusters,&_free_clusters);
SegSet16(ds,RealSeg(dos.tables.mediaid));
reg_bx=RealOff(dos.tables.mediaid+drive);
return true;
}
bool DOS_SetDrive(Bit8u drive) { bool DOS_SetDrive(Bit8u drive) {
if (Drives[drive]) { if (Drives[drive]) {
DOS_SetDefaultDrive(drive); DOS_SetDefaultDrive(drive);
return true; return true;
} else { } else {
return false; return false;
} }
}; };
bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate)
{
Bit32u handle=RealHandle(entry);
if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
if (!Files[handle]) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
};
struct stat stat_block;
if (fstat(handle, &stat_block)!=0) {
DOS_SetError(DOSERR_INVALID_HANDLE);
return false;
}
struct tm *time;
if ((time=localtime(&stat_block.st_mtime))!=0) {
*otime = (time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */
*odate = ((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
} else {
*otime = 6;
*odate = 4;
}
return true;
};
void DOS_SetupFiles (void) { void DOS_SetupFiles (void) {
/* Setup the File Handles */ /* Setup the File Handles */

View File

@ -26,16 +26,20 @@
#define MAX_DEVICE 20 #define MAX_DEVICE 20
static DOS_File * dos_devices[MAX_DEVICE]; static DOS_File * dos_devices[MAX_DEVICE];
bool DOS_IOCTL(Bit8u call,Bit16u entry) {
Bit32u handle=RealHandle(entry); bool DOS_IOCTL(void) {
Bitu handle;Bit8u drive;
if (reg_al<8) { /* call 0-7 use a file handle */
handle=RealHandle(reg_bx);
if (handle>=DOS_FILES) { if (handle>=DOS_FILES) {
DOS_SetError(DOSERR_INVALID_HANDLE); DOS_SetError(DOSERR_INVALID_HANDLE);
return false; return false;
}; }
if (!Files[handle]) { if (!Files[handle]) {
DOS_SetError(DOSERR_INVALID_HANDLE); DOS_SetError(DOSERR_INVALID_HANDLE);
return false; return false;
}; }
}
switch(reg_al) { switch(reg_al) {
case 0x00: /* Get Device Information */ case 0x00: /* Get Device Information */
reg_dx=Files[handle]->GetInformation(); reg_dx=Files[handle]->GetInformation();
@ -44,23 +48,46 @@ bool DOS_IOCTL(Bit8u call,Bit16u entry) {
LOG_DEBUG("DOS:IOCTL:07:Fakes output status is ready for handle %d",handle); LOG_DEBUG("DOS:IOCTL:07:Fakes output status is ready for handle %d",handle);
reg_al=0xff; reg_al=0xff;
return true; return true;
case 0x0D: { case 0x08: /* Check if block device removable */
drive=reg_bl;if (!drive) drive=dos.current_drive;else drive--;
if (Drives[drive]) {
if (drive<2) reg_ax=0; /* Drive a,b are removable if mounted */
else reg_ax=1;
return true;
} else {
DOS_SetError(DOSERR_INVALID_DRIVE);
return false;
}
case 0x0D: /* Generic block device request */
{
PhysPt ptr = SegPhys(ds)+reg_dx; PhysPt ptr = SegPhys(ds)+reg_dx;
Bit8u drive = reg_bl ? reg_bl : DOS_GetDefaultDrive()+1; // A=1, B=2, C=3... drive=reg_bl;if (!drive) drive=dos.current_drive;else drive--;
switch (reg_cl) { switch (reg_cl) {
case 0x60 : mem_writeb(ptr ,0x03); // special function case 0x60: /* Get Device parameters */
mem_writeb(ptr+1,(drive>=3)?0x05:0x14); // fixed disc(5), 1.44 floppy(14) mem_writeb(ptr ,0x03); // special function
mem_writew(ptr+2,drive>=3); // nonremovable ? mem_writeb(ptr+1,(drive>=2)?0x05:0x14); // fixed disc(5), 1.44 floppy(14)
mem_writew(ptr+2,drive>=2); // nonremovable ?
mem_writew(ptr+4,0x0000); // num of cylinders mem_writew(ptr+4,0x0000); // num of cylinders
mem_writeb(ptr+6,0x00); // media type (00=other type) mem_writeb(ptr+6,0x00); // media type (00=other type)
break; break;
default : LOG_ERROR("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive); default :
LOG_ERROR("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive);
return false; return false;
} }
return true; return true;
} }
case 0xE: /* Get Logical Drive Map */
drive=reg_bl;if (!drive) drive=dos.current_drive;else drive--;
if (Drives[drive]) {
reg_al=0; /* Only 1 logical drive assigned */
return true;
} else {
DOS_SetError(DOSERR_INVALID_DRIVE);
return false;
}
break;
default: default:
LOG_ERROR("DOS:IOCTL Call %2X Handle %2X unhandled",reg_al,handle); LOG_ERROR("DOS:IOCTL Call %2X unhandled",reg_al);
return false; return false;
}; };
return false; return false;

View File

@ -99,7 +99,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
mcb_segment+=pmcb->size+1; mcb_segment+=pmcb->size+1;
} }
return false; return false;
}; }
bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) { bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
@ -135,7 +135,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
*blocks=total; *blocks=total;
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
return false; return false;
}; }
bool DOS_FreeMemory(Bit16u segment) { bool DOS_FreeMemory(Bit16u segment) {
@ -151,16 +151,11 @@ bool DOS_FreeMemory(Bit16u segment) {
void DOS_SetupMemory(void) { void DOS_SetupMemory(void) {
//TODO Maybe allocate some memory for dos transfer buffers
//Although i could use bios regions for that for max free low memory
MCB * mcb=(MCB *) HostMake(MEM_START,0); MCB * mcb=(MCB *) HostMake(MEM_START,0);
mcb->psp_segment=MCB_FREE; //Free mcb->psp_segment=MCB_FREE; //Free
mcb->size=0x9FFE - MEM_START; mcb->size=0x9FFE - MEM_START;
mcb->type=0x5a; //Last Block mcb->type=0x5a; //Last Block
dos.firstMCB=MEM_START; dos.firstMCB=MEM_START;
dos_infoblock.SetFirstMCB(MEM_START);
// Create Dos Info Block : maximum size 95 Bytes....
dosInfoBlock.SetLocation(DOS_GetMemory(6));
dosInfoBlock.SetFirstMCB(RealMake(dos.firstMCB,0));
} }

View File

@ -54,6 +54,16 @@ static Bitu INT2A_Handler(void) {
return CBRET_NONE; return CBRET_NONE;
}; };
static bool DOS_MultiplexFunctions(void) {
switch (reg_ax) {
case 0x1680: /* RELEASE CURRENT VIRTUAL MACHINE TIME-SLICE */
//TODO Maybe do some idling but could screw up other systems :)
reg_al=0;
return true;
}
return false;
}
void DOS_SetupMisc(void) { void DOS_SetupMisc(void) {
/* Setup the dos multiplex interrupt */ /* Setup the dos multiplex interrupt */
@ -61,9 +71,10 @@ void DOS_SetupMisc(void) {
call_int2f=CALLBACK_Allocate(); call_int2f=CALLBACK_Allocate();
CALLBACK_Setup(call_int2f,&INT2F_Handler,CB_IRET); CALLBACK_Setup(call_int2f,&INT2F_Handler,CB_IRET);
RealSetVec(0x2f,CALLBACK_RealPointer(call_int2f)); RealSetVec(0x2f,CALLBACK_RealPointer(call_int2f));
DOS_AddMultiplexHandler(DOS_MultiplexFunctions);
/* Setup the dos network interrupt */ /* Setup the dos network interrupt */
call_int2a=CALLBACK_Allocate(); call_int2a=CALLBACK_Allocate();
CALLBACK_Setup(call_int2a,&INT2A_Handler,CB_IRET); CALLBACK_Setup(call_int2a,&INT2A_Handler,CB_IRET);
RealSetVec(0x2A<<2,CALLBACK_RealPointer(call_int2a)); RealSetVec(0x2A,CALLBACK_RealPointer(call_int2a));
}; };

View File

@ -28,69 +28,97 @@
class MOUNT : public Program { class MOUNT : public Program {
public: public:
MOUNT(PROGRAM_Info * program_info):Program(program_info){}; void Run(void)
void Run(void){ {
DOS_Drive * newdrive;char drive;
/* Parse the command line */ /* Parse the command line */
/* if the command line is empty show current mounts */ /* if the command line is empty show current mounts */
if (!*prog_info->cmd_line) { if (!cmd->GetCount()) {
WriteOut("Current mounted drives are\n"); WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1"));
for (int d=0;d<DOS_DRIVES;d++) { for (int d=0;d<DOS_DRIVES;d++) {
if (Drives[d]) { if (Drives[d]) {
WriteOut("Drive %c is mounted as %s\n",d+'A',Drives[d]->GetInfo()); WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"),d+'A',Drives[d]->GetInfo());
} }
} }
return; return;
} }
std::string type="dir";
char drive; drive=toupper(*prog_info->cmd_line); cmd->FindString("-t",type,true);
if (type=="floppy" || type=="dir") {
char * dir=strchr(prog_info->cmd_line,' '); if (dir) { Bit16u sizes[4];
if (!*dir) dir=0; Bit8u mediaid;
else dir=trim(dir); std::string str_size;
if (type=="floppy") {
str_size="512,1,2847,2847";/* All space free */
mediaid=0xF0; /* Floppy 1.44 media */
} }
if (!isalpha(drive) || !dir) { if (type=="dir") {
WriteOut("Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n"); str_size="512,127,16513,1700";
return; 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;
/* Parse the str_size string */
while (*scan) {
if (*scan==',') {
number[index]=0;sizes[count++]=atoi(number);
index=0;
} else number[index++]=*scan;
scan++;
}
number[index]=0;sizes[count++]=atoi(number);
if (!cmd->FindCommand(2,temp_line)) goto showusage;
if (!temp_line.size()) goto showusage;
struct stat test; struct stat test;
if (stat(dir,&test)) { if (stat(temp_line.c_str(),&test)) {
WriteOut("Directory %s Doesn't exist",dir); WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_1"),temp_line.c_str());
return; return;
} }
/* Not a switch so a normal directory/file */ /* Not a switch so a normal directory/file */
if (!(test.st_mode & S_IFDIR)) { if (!(test.st_mode & S_IFDIR)) {
WriteOut("%s isn't a directory",dir); WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_2"),temp_line.c_str());
return; return;
} }
if (temp_line[temp_line.size()-1]!=CROSS_FILESPLIT) temp_line+=CROSS_FILESPLIT;
newdrive=new localDrive(temp_line.c_str(),sizes[0],sizes[1],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']) { if (Drives[drive-'A']) {
WriteOut("Drive %c already mounted with %s\n",drive,Drives[drive-'A']->GetInfo()); WriteOut(MSG_Get("PROGRAM_MOUNT_ALLREADY_MOUNDTED"),drive,Drives[drive-'A']->GetInfo());
if (newdrive) delete newdrive;
return; return;
} }
char fulldir[DOS_PATHLENGTH]; if (!newdrive) E_Exit("DOS:Can't create drive");
strcpy(fulldir,dir); Drives[drive-'A']=newdrive;
static char theend[2]={CROSS_FILESPLIT,0}; /* Set the correct media byte in the table */
char * last=strrchr(fulldir,CROSS_FILESPLIT); mem_writeb(Real2Phys(dos.tables.mediaid)+drive-'A',newdrive->GetMediaByte());
if (!last || *(++last)) strcat(fulldir,theend); WriteOut("Drive %c mounted as %s\n",drive,newdrive->GetInfo());
Drives[drive-'A']=new localDrive(fulldir); return;
WriteOut("Mounting drive %c as %s\n",drive,fulldir); showusage:
WriteOut(MSG_Get("PROGRAM_MOUNT_USAGE"));
return;
} }
}; };
static void MOUNT_ProgramStart(PROGRAM_Info * info) { static void MOUNT_ProgramStart(Program * * make) {
MOUNT * tempmount=new MOUNT(info); *make=new MOUNT;
tempmount->Run() ;
delete tempmount;
} }
class MEM : public Program { class MEM : public Program {
public: public:
MEM(PROGRAM_Info * program_info):Program(program_info){};
void Run(void) { void Run(void) {
/* Show conventional Memory */ /* Show conventional Memory */
WriteOut("\n"); WriteOut("\n");
Bit16u seg,blocks;blocks=0xffff; Bit16u seg,blocks;blocks=0xffff;
DOS_AllocateMemory(&seg,&blocks); DOS_AllocateMemory(&seg,&blocks);
WriteOut("%10d Kb free conventional memory\n",blocks*16/1024); WriteOut(MSG_Get("PROGRAM_MEM_CONVEN"),blocks*16/1024);
/* Test for and show free XMS */ /* Test for and show free XMS */
reg_ax=0x4300;CALLBACK_RunRealInt(0x2f); reg_ax=0x4300;CALLBACK_RunRealInt(0x2f);
if (reg_al==0x80) { if (reg_al==0x80) {
@ -99,7 +127,7 @@ public:
reg_ah=8; reg_ah=8;
CALLBACK_RunRealFar(xms_seg,xms_off); CALLBACK_RunRealFar(xms_seg,xms_off);
if (!reg_bl) { if (!reg_bl) {
WriteOut("%10d Kb free extended memory\n",reg_dx); WriteOut(MSG_Get("PROGRAM_MEM_EXTEND"),reg_dx);
} }
} }
/* Test for and show free EMS */ /* Test for and show free EMS */
@ -108,34 +136,26 @@ public:
DOS_CloseFile(handle); DOS_CloseFile(handle);
reg_ah=0x42; reg_ah=0x42;
CALLBACK_RunRealInt(0x67); CALLBACK_RunRealInt(0x67);
WriteOut("%10d Kb free expanded memory\n",reg_bx*16); WriteOut(MSG_Get("PROGRAM_MEM_EXPAND"),reg_bx*16);
} }
} }
}; };
static void MEM_ProgramStart(Program * * make) {
static void MEM_ProgramStart(PROGRAM_Info * info) { *make=new MEM;
MEM mem(info);
mem.Run();
} }
#if !defined (WIN32) /* Unix */ #if !defined (WIN32) /* Unix */
class UPCASE : public Program { class UPCASE : public Program {
public: public:
UPCASE(PROGRAM_Info * program_info);
void Run(void); void Run(void);
void upcasedir(char * directory); void upcasedir(const char * directory);
}; };
void UPCASE::upcasedir(const char * directory) {
UPCASE::UPCASE(PROGRAM_Info * info):Program(info) {
}
void UPCASE::upcasedir(char * directory) {
DIR * sdir; DIR * sdir;
char fullname[512]; char fullname[512];
char newname[512]; char newname[512];
@ -143,10 +163,10 @@ void UPCASE::upcasedir(char * directory) {
struct stat finfo; struct stat finfo;
if(!(sdir=opendir(directory))) { if(!(sdir=opendir(directory))) {
WriteOut("Failed to open directory %s\n",directory); WriteOut(MSG_Get("PROGRAM_UPCASE_ERROR_DIR"),directory);
return; return;
} }
WriteOut("Scanning directory %s\n",fullname); WriteOut(MSG_Get("PROGRAM_UPCASE_SCANNING_DIR"),fullname);
while (tempdata=readdir(sdir)) { while (tempdata=readdir(sdir)) {
if (strcmp(tempdata->d_name,".")==0) continue; if (strcmp(tempdata->d_name,".")==0) continue;
if (strcmp(tempdata->d_name,"..")==0) continue; if (strcmp(tempdata->d_name,"..")==0) continue;
@ -157,7 +177,7 @@ void UPCASE::upcasedir(char * directory) {
strcat(newname,"/"); strcat(newname,"/");
upcase(tempdata->d_name); upcase(tempdata->d_name);
strcat(newname,tempdata->d_name); strcat(newname,tempdata->d_name);
WriteOut("Renaming %s to %s\n",fullname,newname); WriteOut(MSG_Get("PROGRAM_UPCASE_RENAME"),fullname,newname);
rename(fullname,newname); rename(fullname,newname);
stat(fullname,&finfo); stat(fullname,&finfo);
if(S_ISDIR(finfo.st_mode)) { if(S_ISDIR(finfo.st_mode)) {
@ -171,42 +191,60 @@ void UPCASE::upcasedir(char * directory) {
void UPCASE::Run(void) { void UPCASE::Run(void) {
/* First check if the directory exists */ /* First check if the directory exists */
struct stat info; struct stat info;
WriteOut("UPCASE 0.1 Directory case convertor.\n"); WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_1"));
if (!strlen(prog_info->cmd_line)) { if (!cmd->GetCount()) {
WriteOut("Usage UPCASE [local directory]\n"); WriteOut(MSG_Get("PROGRAM_UPCASE_USAGE"));
WriteOut("This tool will convert all files and subdirectories in a directory.\n");
WriteOut("Be VERY sure this directory contains only dos related material.\n");
WriteOut("Otherwise you might horribly screw up your filesystem.\n");
return; return;
} }
if (stat(prog_info->cmd_line,&info)) { cmd->FindCommand(1,temp_line);
WriteOut("%s doesn't exist\n",prog_info->cmd_line); if (stat(temp_line.c_str(),&info)) {
WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_ERROR_1"),temp_line.c_str());
return; return;
} }
if(!S_ISDIR(info.st_mode)) { if(!S_ISDIR(info.st_mode)) {
WriteOut("%s isn't a directory\n",prog_info->cmd_line); WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_ERROR_2"),temp_line.c_str());
return; return;
} }
WriteOut("Converting the wrong directories can be very harmfull, please be carefull.\n"); WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_CHOICE"),temp_line.c_str());
WriteOut("Are you really really sure you want to convert %s to upcase?Y/N\n",prog_info->cmd_line);
Bit8u key;Bit16u n=1; Bit8u key;Bit16u n=1;
DOS_ReadFile(STDIN,&key,&n); DOS_ReadFile(STDIN,&key,&n);
if (toupper(key)=='Y') { if (toupper(key)=='Y') {
upcasedir(prog_info->cmd_line); upcasedir(temp_line.c_str());
} else { } else {
WriteOut("Okay better not do it.\n"); WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_NO"));
} }
} }
static void UPCASE_ProgramStart(PROGRAM_Info * info) { static void UPCASE_ProgramStart(Program * * make) {
UPCASE * tempUPCASE=new UPCASE(info); *make=new UPCASE;
tempUPCASE->Run();
delete tempUPCASE;
} }
#endif #endif
void DOS_SetupPrograms(void) { void DOS_SetupPrograms(void) {
/*Add Messages */
MSG_Add("PROGRAM_MOUNT_STATUS_2","Drive %c is mounted as %s\n");
MSG_Add("PROGRAM_MOUNT_STATUS_1","Current mounted drives are:\n");
MSG_Add("PROGRAM_MOUNT_ERROR_1","Directory %s doesn't exist.\n");
MSG_Add("PROGRAM_MOUNT_ERROR_2","%s isn't a directory\n");
MSG_Add("PROGRAM_MOUNT_ALLREADY_MOUNTED","Drive %c already mounted with %s\n");
MSG_Add("PROGRAM_MOUNT_USAGE","Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n");
MSG_Add("PROGRAM_MEM_CONVEN","%10d Kb free conventional memory\n");
MSG_Add("PROGRAM_MEM_EXTEND","%10d Kb free extended memory\n");
MSG_Add("PROGRAM_MEM_EXPAND","%10d Kb free expanded memory\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
/*regular setup*/
PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart); PROGRAMS_MakeFile("MOUNT.COM",MOUNT_ProgramStart);
PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart); PROGRAMS_MakeFile("MEM.COM",MEM_ProgramStart);
#if !defined (WIN32) /* Unix */ #if !defined (WIN32) /* Unix */

View File

@ -20,25 +20,18 @@
#include "mem.h" #include "mem.h"
#include "dos_inc.h" #include "dos_inc.h"
#if defined (_MSC_VER)
#pragma pack(1) #pragma pack(1)
#endif
struct DOS_TableCase { struct DOS_TableCase {
Bit16u size; Bit16u size;
Bit8u chars[256]; Bit8u chars[256];
} }
#if defined (_MSC_VER) GCC_ATTRIBUTE (packed);
; #pragma pack ()
#pragma pack()
#else
__attribute__ ((packed));
#endif
RealPt DOS_TableUpCase; RealPt DOS_TableUpCase;
RealPt DOS_TableLowCase; RealPt DOS_TableLowCase;
static Bit16u dos_memseg=0xd000; static Bit16u dos_memseg;
Bit16u DOS_GetMemory(Bit16u pages) { Bit16u DOS_GetMemory(Bit16u pages) {
if (pages+dos_memseg>=0xe000) { if (pages+dos_memseg>=0xe000) {
E_Exit("DOS:Not enough memory for internal tables"); E_Exit("DOS:Not enough memory for internal tables");
@ -50,9 +43,21 @@ Bit16u DOS_GetMemory(Bit16u pages) {
void DOS_SetupTables(void) { void DOS_SetupTables(void) {
dos_memseg=0xd000;
Bit16u seg;Bitu i;
dos.tables.indosflag=RealMake(DOS_GetMemory(1),0); dos.tables.indosflag=RealMake(DOS_GetMemory(1),0);
dos.tables.mediaid=RealMake(DOS_GetMemory(2),0);
dos.tables.tempdta=RealMake(DOS_GetMemory(4),0);
for (i=0;i<DOS_DRIVES;i++) mem_writeb(Real2Phys(dos.tables.mediaid)+i,0);
mem_writeb(Real2Phys(dos.tables.indosflag),0); mem_writeb(Real2Phys(dos.tables.indosflag),0);
}; /* Create the DOS Info Block */
dos_infoblock.SetLocation(DOS_GetMemory(6));
/* Create a fake SFT, so programs think there are 100 file handles */
seg=DOS_GetMemory(1);
real_writed(seg,0,0xffffffff); //Last File Table
real_writew(seg,4,100); //File Table supports 100 files
dos_infoblock.SetfirstFileTable(RealMake(seg,0));
}

View File

@ -22,7 +22,7 @@
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include "dosbox.h" #include "dosbox.h"
#include "dos_system.h" #include "dos_inc.h"
#include "drives.h" #include "drives.h"
#include "support.h" #include "support.h"
#include "cross.h" #include "cross.h"
@ -38,13 +38,14 @@ public:
Bit16u GetInformation(void); Bit16u GetInformation(void);
private: private:
FILE * fhandle; FILE * fhandle;
enum { NONE,READ,WRITE } last_action;
Bit16u info; Bit16u info;
}; };
bool localDrive:: FileCreate(DOS_File * * file,char * name,Bit16u attributes) { bool localDrive:: FileCreate(DOS_File * * file,char * name,Bit16u attributes) {
//TODO Maybe care for attributes but not likely //TODO Maybe care for attributes but not likely
char newname[512]; char newname[CROSS_LEN];
strcpy(newname,basedir); strcpy(newname,basedir);
strcat(newname,name); strcat(newname,name);
CROSS_FILENAME(newname); CROSS_FILENAME(newname);
@ -67,7 +68,7 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
// return false; // return false;
}; };
char newname[512]; char newname[CROSS_LEN];
strcpy(newname,basedir); strcpy(newname,basedir);
strcat(newname,name); strcat(newname,name);
CROSS_FILENAME(newname); CROSS_FILENAME(newname);
@ -79,7 +80,7 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
}; };
bool localDrive::FileUnlink(char * name) { bool localDrive::FileUnlink(char * name) {
char newname[512]; char newname[CROSS_LEN];
strcpy(newname,basedir); strcpy(newname,basedir);
strcat(newname,name); strcat(newname,name);
CROSS_FILENAME(newname); CROSS_FILENAME(newname);
@ -88,79 +89,64 @@ bool localDrive::FileUnlink(char * name) {
}; };
bool localDrive::FindFirst(char * search,DTA_FindBlock * dta) { bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) {
//TODO Find some way for lowcase and highcase drives oneday if (srch_opendir) closedir(srch_opendir);
char name[512]; strcpy(srch_dir,basedir);
strcpy(name,basedir); strcat(srch_dir,_dir);
strcat(name,search); CROSS_FILENAME(srch_dir);
CROSS_FILENAME(name);
char * last=strrchr(name, CROSS_FILESPLIT); char end[2]={CROSS_FILESPLIT,0};
*last=0; if (srch_dir[strlen(srch_dir)-1]!=CROSS_FILESPLIT) strcat(srch_dir,end);
last++; if((srch_opendir=opendir(srch_dir))==NULL) return false;
/* Check the wildcard string for an extension */
strcpy(wild_name,last);
wild_ext=strrchr(wild_name,'.');
if (wild_ext) {
*wild_ext++=0;
}
strcpy(directory,name);
/* make sure / is last sign */
if (pdir) closedir(pdir);
if(directory[(strlen(directory)-1)]!=CROSS_FILESPLIT) strcat(directory, "/");
if((pdir=opendir(directory))==NULL) return false;
return FindNext(dta); return FindNext(dta);
} }
bool localDrive::FindNext(DTA_FindBlock * dta) { bool localDrive::FindNext(DOS_DTA & dta) {
Bit8u tempattr=0; struct dirent * dir_ent;
struct dirent *tempdata;
struct stat stat_block; struct stat stat_block;
char werkbuffer[512]; char full_name[CROSS_LEN];
Bit8u srch_attr;char srch_pattern[DOS_NAMELENGTH_ASCII];
Bit8u find_attr;
if(pdir==NULL){ if(!srch_opendir) return false;
return false;
}; dta.GetSearchParams(srch_attr,srch_pattern);
start: again:
if((tempdata=readdir(pdir))==NULL) { if((dir_ent=readdir(srch_opendir))==NULL) {
closedir(pdir); closedir(srch_opendir);
pdir=NULL; srch_opendir=NULL;
return false; return false;
} }
strcpy(werkbuffer,tempdata->d_name); if(!WildFileCmp(dir_ent->d_name,srch_pattern)) goto again;
if (wild_ext) { strcpy(full_name,srch_dir);
char * ext=strrchr(werkbuffer,'.'); strcat(full_name,dir_ent->d_name);
if (!ext) ext="*"; if(stat(full_name,&stat_block)!=0){
else *ext++=0; goto again;
if(!wildcmp(wild_ext,ext)) goto start;
} }
if(!wildcmp(wild_name,werkbuffer)) goto start; if(S_ISDIR(stat_block.st_mode)) find_attr=DOS_ATTR_DIRECTORY;
werkbuffer[0]='\0'; else find_attr=DOS_ATTR_ARCHIVE;
strcpy(werkbuffer,directory); if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again;
strcat(werkbuffer,tempdata->d_name); /*file is okay, setup everything to be copied in DTA Block */
if(stat(werkbuffer,&stat_block)!=0){ char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size;
/*nu is er iets fout!*/ exit(1); if(strlen(dir_ent->d_name)<DOS_NAMELENGTH_ASCII){
} strcpy(find_name,dir_ent->d_name);
if(S_ISDIR(stat_block.st_mode)) tempattr=DOS_ATTR_DIRECTORY; upcase(find_name);
else tempattr=DOS_ATTR_ARCHIVE; } else strcpy(find_name,"LONGNAME.ERR");
if(!(dta->sattr & tempattr)) goto start; find_size=(Bit32u) stat_block.st_size;
/*file is oke so filldtablok */
if(strlen(tempdata->d_name)<=DOS_NAMELENGTH) strcpy(dta->name,upcase(tempdata->d_name));
dta->attr=tempattr;
dta->size=(Bit32u) stat_block.st_size;
struct tm *time; struct tm *time;
if((time=localtime(&stat_block.st_mtime))!=0){ if((time=localtime(&stat_block.st_mtime))!=0){
find_date=DOS_PackDate(time->tm_year+1900,time->tm_mon+1,time->tm_mday);
dta->time=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */ find_time=DOS_PackTime(time->tm_hour,time->tm_min,time->tm_sec);
dta->date=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
}else { }else {
dta->time=6; find_time=6;
dta->date=4; find_date=4;
} }
dta.SetResult(find_name,find_size,find_date,find_time,find_attr);
return true; return true;
} }
bool localDrive::GetFileAttr(char * name,Bit16u * attr) { bool localDrive::GetFileAttr(char * name,Bit16u * attr) {
char newname[512]; char newname[CROSS_LEN];
strcpy(newname,basedir); strcpy(newname,basedir);
strcat(newname,name); strcat(newname,name);
CROSS_FILENAME(newname); CROSS_FILENAME(newname);
@ -175,7 +161,7 @@ bool localDrive::GetFileAttr(char * name,Bit16u * attr) {
}; };
bool localDrive::MakeDir(char * dir) { bool localDrive::MakeDir(char * dir) {
char newdir[512]; char newdir[CROSS_LEN];
strcpy(newdir,basedir); strcpy(newdir,basedir);
strcat(newdir,dir); strcat(newdir,dir);
CROSS_FILENAME(newdir); CROSS_FILENAME(newdir);
@ -189,7 +175,7 @@ bool localDrive::MakeDir(char * dir) {
} }
bool localDrive::RemoveDir(char * dir) { bool localDrive::RemoveDir(char * dir) {
char newdir[512]; char newdir[CROSS_LEN];
strcpy(newdir,basedir); strcpy(newdir,basedir);
strcat(newdir,dir); strcat(newdir,dir);
CROSS_FILENAME(newdir); CROSS_FILENAME(newdir);
@ -198,7 +184,7 @@ bool localDrive::RemoveDir(char * dir) {
} }
bool localDrive::TestDir(char * dir) { bool localDrive::TestDir(char * dir) {
char newdir[512]; char newdir[CROSS_LEN];
strcpy(newdir,basedir); strcpy(newdir,basedir);
strcat(newdir,dir); strcat(newdir,dir);
CROSS_FILENAME(newdir); CROSS_FILENAME(newdir);
@ -207,11 +193,11 @@ bool localDrive::TestDir(char * dir) {
} }
bool localDrive::Rename(char * oldname,char * newname) { bool localDrive::Rename(char * oldname,char * newname) {
char newold[512]; char newold[CROSS_LEN];
strcpy(newold,basedir); strcpy(newold,basedir);
strcat(newold,oldname); strcat(newold,oldname);
CROSS_FILENAME(newold); CROSS_FILENAME(newold);
char newnew[512]; char newnew[CROSS_LEN];
strcpy(newnew,basedir); strcpy(newnew,basedir);
strcat(newnew,newname); strcat(newnew,newname);
CROSS_FILENAME(newnew); CROSS_FILENAME(newnew);
@ -220,18 +206,18 @@ bool localDrive::Rename(char * oldname,char * newname) {
}; };
bool localDrive::FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) { bool localDrive::AllocationInfo(Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters) {
/* Always report 100 mb free should be enough */ /* Always report 100 mb free should be enough */
/* Total size is always 1 gb */ /* Total size is always 1 gb */
*bytes=512; *_bytes_sector=allocation.bytes_sector;
*sectors=127; *_sectors_cluster=allocation.sectors_cluster;
*clusters=16513; *_total_clusters=allocation.total_clusters;
*free=1700; *_free_clusters=allocation.free_clusters;
return true; return true;
}; };
bool localDrive::FileExists(const char* name) const { bool localDrive::FileExists(const char* name) {
char newname[512]; char newname[CROSS_LEN];
strcpy(newname,basedir); strcpy(newname,basedir);
strcat(newname,name); strcat(newname,name);
CROSS_FILENAME(newname); CROSS_FILENAME(newname);
@ -241,31 +227,53 @@ bool localDrive::FileExists(const char* name) const {
return true; return true;
} }
bool localDrive::FileStat(const char* name, struct stat* const stat_block) const { bool localDrive::FileStat(const char* name, FileStat_Block * const stat_block) {
char newname[512]; char newname[CROSS_LEN];
strcpy(newname,basedir); strcpy(newname,basedir);
strcat(newname,name); strcat(newname,name);
CROSS_FILENAME(newname); CROSS_FILENAME(newname);
if(stat(newname,stat_block)!=0) return false; struct stat temp_stat;
return true; 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);
} else {
}
stat_block->size=(Bit32u)temp_stat.st_size;
return true;
} }
Bit8u localDrive::GetMediaByte(void) {
return allocation.mediaid;
}
localDrive::localDrive(char * startdir) { localDrive::localDrive(const char * startdir,Bit16u _bytes_sector,Bit16u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid) {
strcpy(basedir,startdir); strcpy(basedir,startdir);
sprintf(info,"local directory %s",startdir); sprintf(info,"local directory %s",startdir);
pdir=NULL; 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;
} }
//TODO Maybe use fflush, but that seemed to fuck up in visual c
bool localFile::Read(Bit8u * data,Bit16u * size) { bool localFile::Read(Bit8u * data,Bit16u * size) {
if (last_action==WRITE) fseek(fhandle,ftell(fhandle),SEEK_SET);
last_action=READ;
*size=fread(data,1,*size,fhandle); *size=fread(data,1,*size,fhandle);
return true; return true;
}; };
bool localFile::Write(Bit8u * data,Bit16u * size) { bool localFile::Write(Bit8u * data,Bit16u * size) {
if (last_action==READ) fseek(fhandle,ftell(fhandle),SEEK_SET);
last_action=WRITE;
if(*size==0){ if(*size==0){
return (!ftruncate(fileno(fhandle),ftell(fhandle))); return (!ftruncate(fileno(fhandle),ftell(fhandle)));
} }
@ -291,7 +299,7 @@ bool localFile::Seek(Bit32u * pos,Bit32u type) {
//TODO Hope we don't encouter files with 64 bits size //TODO Hope we don't encouter files with 64 bits size
Bit32u * fake_pos=(Bit32u*)&temppos; Bit32u * fake_pos=(Bit32u*)&temppos;
*pos=*fake_pos; *pos=*fake_pos;
last_action=NONE;
return true; return true;
} }
@ -304,9 +312,22 @@ Bit16u localFile::GetInformation(void) {
return info; return info;
} }
localFile::localFile(FILE * handle,Bit16u devinfo) { localFile::localFile(FILE * handle,Bit16u devinfo) {
fhandle=handle; fhandle=handle;
info=devinfo; info=devinfo;
struct stat temp_stat;
fstat(fileno(handle),&temp_stat);
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);
} else {
time=0;date=0;
}
size=(Bit32u)temp_stat.st_size;
attr=DOS_ATTR_ARCHIVE;
last_action=NONE;
} }

View File

@ -21,13 +21,13 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include "dosbox.h" #include "dosbox.h"
#include "dos_system.h" #include "dos_inc.h"
#include "drives.h" #include "drives.h"
#include "support.h" #include "support.h"
#include "cross.h" #include "cross.h"
struct VFILE_Block { struct VFILE_Block {
char * name; const char * name;
Bit8u * data; Bit8u * data;
Bit32u size; Bit32u size;
VFILE_Block * next; VFILE_Block * next;
@ -36,7 +36,7 @@ struct VFILE_Block {
static VFILE_Block * first_file; static VFILE_Block * first_file;
void VFILE_Register(char * name,Bit8u * data,Bit32u size) { void VFILE_Register(const char * name,Bit8u * data,Bit32u size) {
VFILE_Block * new_file=new VFILE_Block; VFILE_Block * new_file=new VFILE_Block;
new_file->name=name; new_file->name=name;
new_file->data=data; new_file->data=data;
@ -153,16 +153,14 @@ bool Virtual_Drive::TestDir(char * dir) {
return false; return false;
} }
bool Virtual_Drive::FileStat(const char* name, struct stat* const stat_block) const { bool Virtual_Drive::FileStat(const char* name, FileStat_Block * const stat_block){
VFILE_Block * cur_file=first_file; VFILE_Block * cur_file=first_file;
while (cur_file) { while (cur_file) {
if (strcasecmp(name,cur_file->name)==0) { if (strcasecmp(name,cur_file->name)==0) {
stat_block->st_size=cur_file->size; stat_block->attr=DOS_ATTR_ARCHIVE;
struct tm tijd; stat_block->size=cur_file->size;
tijd.tm_hour=0;tijd.tm_min=0;tijd.tm_sec=0; stat_block->date=DOS_PackDate(2002,0,0);
tijd.tm_year=80;tijd.tm_mday=6;tijd.tm_mon=0; stat_block->time=DOS_PackTime(12,12,12);
stat_block->st_mtime=mktime(&tijd);
/* more not needed at the moment (fcbopen.....)*/
return true; return true;
} }
cur_file=cur_file->next; cur_file=cur_file->next;
@ -170,7 +168,7 @@ bool Virtual_Drive::FileStat(const char* name, struct stat* const stat_block) co
return false; return false;
} }
bool Virtual_Drive::FileExists(const char* name) const { bool Virtual_Drive::FileExists(const char* name){
VFILE_Block * cur_file=first_file; VFILE_Block * cur_file=first_file;
while (cur_file) { while (cur_file) {
if (strcasecmp(name,cur_file->name)==0) return true; if (strcasecmp(name,cur_file->name)==0) return true;
@ -179,32 +177,17 @@ bool Virtual_Drive::FileExists(const char* name) const {
return false; return false;
} }
static void FillDTABlock(DTA_FindBlock * dta,VFILE_Block * fill_file) { bool Virtual_Drive::FindFirst(char * _dir,DOS_DTA & dta) {
strcpy(dta->name,fill_file->name);
dta->size=fill_file->size;
dta->attr=DOS_ATTR_ARCHIVE;
dta->time=2;
dta->date=6;
}
bool Virtual_Drive::FindFirst(char * search,DTA_FindBlock * dta) {
search_file=first_file; search_file=first_file;
strcpy(search_string,search); return FindNext(dta);
while (search_file) {
if (wildcmp(search_string,search_file->name)) {
FillDTABlock(dta,search_file);
search_file=search_file->next;
return true;
}
search_file=search_file->next;
}
return false;
} }
bool Virtual_Drive::FindNext(DTA_FindBlock * dta) { bool Virtual_Drive::FindNext(DOS_DTA & dta) {
Bit8u attr;char pattern[DOS_NAMELENGTH_ASCII];
dta.GetSearchParams(attr,pattern);
while (search_file) { while (search_file) {
if (wildcmp(search_string,search_file->name)) { if (WildFileCmp(search_file->name,pattern)) {
FillDTABlock(dta,search_file); dta.SetResult(search_file->name,search_file->size,6,2,DOS_ATTR_ARCHIVE);
search_file=search_file->next; search_file=search_file->next;
return true; return true;
} }
@ -221,13 +204,17 @@ bool Virtual_Drive::Rename(char * oldname,char * newname) {
return false; return false;
} }
bool Virtual_Drive::FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) { bool Virtual_Drive::AllocationInfo(Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters) {
/* Always report 100 mb free should be enough */ /* Always report 100 mb free should be enough */
/* Total size is always 1 gb */ /* Total size is always 1 gb */
*bytes=512; *_bytes_sector=512;
*sectors=127; *_sectors_cluster=127;
*clusters=16513; *_total_clusters=16513;
*free=00; *_free_clusters=00;
return true; return true;
} }
Bit8u Virtual_Drive::GetMediaByte(void) {
return 0xF8;
}

View File

@ -19,6 +19,58 @@
#include "dosbox.h" #include "dosbox.h"
#include "dos_system.h" #include "dos_system.h"
#include "drives.h" #include "drives.h"
#include "support.h"
bool WildFileCmp(const char * file, const char * wild)
{
char file_name[9];
char file_ext[4];
char wild_name[9];
char wild_ext[4];
char * find_ext;
Bitu r;
strcpy(file_name," ");
strcpy(file_ext," ");
strcpy(wild_name," ");
strcpy(wild_ext," ");
find_ext=strchr(file,'.');
if (find_ext) {
Bitu size=find_ext-file;if (size>8) size=8;
memcpy(file_name,file,size);
find_ext++;
memcpy(file_ext,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext));
} else {
memcpy(file_name,file,(strlen(file) > 8) ? 8 : strlen(file));
}
upcase(file_name);upcase(file_ext);
find_ext=strchr(wild,'.');
if (find_ext) {
Bitu size=find_ext-wild;if (size>8) size=8;
memcpy(wild_name,wild,size);
find_ext++;
memcpy(wild_ext,find_ext,(strlen(find_ext)>3) ? 3 : strlen(find_ext));
} else {
memcpy(wild_name,wild,(strlen(wild) > 8) ? 8 : strlen(wild));
}
upcase(wild_name);upcase(wild_ext);
/* Names are right do some checking */
r=0;
while (r<8) {
if (wild_name[r]=='*') goto checkext;
if (wild_name[r]!='?' && wild_name[r]!=file_name[r]) return false;
r++;
}
checkext:
while (r<3) {
if (wild_ext[r]=='*') return true;
if (wild_ext[r]!='?' && wild_ext[r]!=file_ext[r]) return false;
r++;
}
return true;
}
DOS_Drive::DOS_Drive() { DOS_Drive::DOS_Drive() {

View File

@ -22,30 +22,39 @@
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> #include <dirent.h>
#include "dos_system.h" #include "dos_system.h"
#include "cross.h"
bool WildFileCmp(const char * file, const char * wild);
class localDrive : public DOS_Drive { class localDrive : public DOS_Drive {
public: public:
localDrive(char * startdir); localDrive(const char * startdir,Bit16u _bytes_sector,Bit16u _sectors_cluster,Bit16u _total_clusters,Bit16u _free_clusters,Bit8u _mediaid);
bool FileOpen(DOS_File * * file,char * name,Bit32u flags); bool FileOpen(DOS_File * * file,char * name,Bit32u flags);
bool FileCreate(DOS_File * * file,char * name,Bit16u attributes); bool FileCreate(DOS_File * * file,char * name,Bit16u attributes);
bool FileUnlink(char * name); bool FileUnlink(char * name);
bool RemoveDir(char * dir); bool RemoveDir(char * dir);
bool MakeDir(char * dir); bool MakeDir(char * dir);
bool TestDir(char * dir); bool TestDir(char * dir);
bool FindFirst(char * search,DTA_FindBlock * dta); bool FindFirst(char * _dir,DOS_DTA & dta);
bool FindNext(DTA_FindBlock * dta); bool FindNext(DOS_DTA & dta);
bool GetFileAttr(char * name,Bit16u * attr); bool GetFileAttr(char * name,Bit16u * attr);
bool Rename(char * oldname,char * newname); bool Rename(char * oldname,char * newname);
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free); bool AllocationInfo(Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters);
bool FileExists(const char* name) const ; bool FileExists(const char* name);
bool FileStat(const char* name, struct stat* const stat_block) const; bool FileStat(const char* name, FileStat_Block * const stat_block);
Bit8u GetMediaByte(void);
private: private:
bool FillDTABlock(DTA_FindBlock * dta); char basedir[CROSS_LEN];
char basedir[512]; char srch_dir[CROSS_LEN];
char directory[512]; DIR * srch_opendir;
char wild_name[15]; struct {
char * wild_ext; Bit16u bytes_sector;
DIR *pdir; Bit16u sectors_cluster;
Bit16u total_clusters;
Bit16u free_clusters;
Bit8u mediaid;
} allocation;
}; };
struct VFILE_Block; struct VFILE_Block;
@ -60,17 +69,16 @@ public:
bool RemoveDir(char * dir); bool RemoveDir(char * dir);
bool MakeDir(char * dir); bool MakeDir(char * dir);
bool TestDir(char * dir); bool TestDir(char * dir);
bool FindFirst(char * search,DTA_FindBlock * dta); bool FindFirst(char * _dir,DOS_DTA & dta);
bool FindNext(DTA_FindBlock * dta); bool FindNext(DOS_DTA & dta);
bool GetFileAttr(char * name,Bit16u * attr); bool GetFileAttr(char * name,Bit16u * attr);
bool Rename(char * oldname,char * newname); bool Rename(char * oldname,char * newname);
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free); bool AllocationInfo(Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters);
bool FileExists(const char* name) const ; bool FileExists(const char* name);
bool FileStat(const char* name, struct stat* const stat_block) const; bool FileStat(const char* name, FileStat_Block* const stat_block);
Bit8u GetMediaByte(void);
private: private:
VFILE_Block * search_file; VFILE_Block * search_file;
char search_string[255];
}; };
#endif #endif

View File

@ -35,119 +35,53 @@
#include "setup.h" #include "setup.h"
#include "cross.h" #include "cross.h"
#include "programs.h" #include "programs.h"
#include "support.h"
char dosbox_basedir[CROSS_LEN]; Config * control;
Bitu errorlevel=1;
/* The whole load of startups for all the subfunctions */
void MSG_Init(Section_prop *);
void MEM_Init(Section *);
void IO_Init(Section * );
void CALLBACK_Init(Section*);
void PROGRAMS_Init(Section*);
void RENDER_Init(Section*);
void VGA_Init(Section*);
void DOS_Init(Section*);
#if 0 void CPU_Init(Section*);
int main(int argc, char* argv[]) {
/* Strip out the dosbox startup directory */
/* Handle the command line for new stuff to add to autoexec.bat */
int argl=1;
if (argc>1) {
if (*argv[1]!='-') {
struct stat test;
if (stat(argv[1],&test)) {
E_Exit("%s Doesn't exist",argv[1]);
}
/* Not a switch so a normal directory/file */
if (test.st_mode & S_IFDIR) {
SHELL_AddAutoexec("MOUNT C %s",argv[1]);
SHELL_AddAutoexec("C:");
} else {
char * name=strrchr(argv[1],CROSS_FILESPLIT);
if (!name) E_Exit("This is weird %s",argv[1]);
*name++=0;
if (access(argv[1],F_OK)) E_Exit("Illegal Directory %s",argv[1]);
SHELL_AddAutoexec("MOUNT C %s",argv[1]);
SHELL_AddAutoexec("C:");
SHELL_AddAutoexec(name);
}
argl++;
}
}
bool sw_c=false;
while (argl<argc) {
if (*argv[argl]=='-') {
sw_c=false;
if (strcmp(argv[argl],"-c")==0) sw_c=true;
else E_Exit("Illegal switch %s",argv[argl]);
argl++;
continue;
}
SHELL_AddAutoexec(argv[argl]);
if (sw_c) {
}
argl++;
}
SysShutDown();
SDL_Quit();
return 0;
}
#endif
//The whole load of startups for all the subfunctions
void MSG_Init(void);
void MEM_Init(void);
void VGA_Init(void);
void CALLBACK_Init();
void DOS_Init();
void RENDER_Init(void);
void CPU_Init();
//void FPU_Init(); //void FPU_Init();
void IO_Init(void); void DMA_Init(Section*);
void DMA_Init(void); void MIXER_Init(Section*);
void MIXER_Init(void); void HARDWARE_Init(Section*);
void HARDWARE_Init(void);
void KEYBOARD_Init(void); //TODO This should setup INT 16 too but ok ;) void KEYBOARD_Init(Section*); //TODO This should setup INT 16 too but ok ;)
void JOYSTICK_Init(void); void JOYSTICK_Init(Section*);
void MOUSE_Init(void); void MOUSE_Init(Section*);
void SBLASTER_Init(void); void SBLASTER_Init(Section*);
void ADLIB_Init(void); void ADLIB_Init(Section*);
void PCSPEAKER_Init(void); void PCSPEAKER_Init(Section*);
void TANDY_Init(void); void TANDYSOUND_Init(Section*);
void CMS_Init(void); void CMS_Init(Section*);
void PIC_Init(void); void PIC_Init(Section*);
void TIMER_Init(void); void TIMER_Init(Section*);
void BIOS_Init(void); void BIOS_Init(Section*);
void DEBUG_Init(void); void DEBUG_Init(Section*);
void PLUGIN_Init(void);
/* Dos Internal mostly */ /* Dos Internal mostly */
void EMS_Init(void); void EMS_Init(Section*);
void XMS_Init(void); void XMS_Init(Section*);
void PROGRAMS_Init(void); void AUTOEXEC_Init(Section*);
void SHELL_Init(void); void SHELL_Init(void);
void INT10_Init(Section*);
void CALLBACK_ShutDown(void);
void PIC_ShutDown(void);
void KEYBOARD_ShutDown(void);
void CPU_ShutDown(void);
void VGA_ShutDown(void);
void BIOS_ShutDown(void);
void MEMORY_ShutDown(void);
Bit32u LastTicks;
static LoopHandler * loop; static LoopHandler * loop;
static Bitu Normal_Loop(void) { static Bitu Normal_Loop(void) {
@ -159,30 +93,18 @@ static Bitu Normal_Loop(void) {
LastTicks=new_ticks; LastTicks=new_ticks;
TIMER_AddTicks(ticks); TIMER_AddTicks(ticks);
} }
TIMER_CheckPIT();
GFX_Events(); GFX_Events();
PIC_runIRQs();
return (*cpudecoder)(cpu_cycles);
};
static Bitu Speed_Loop(void) {
Bit32u new_ticks;
new_ticks=GetTicks();
Bitu ret=0;
Bitu cycles=1;
if (new_ticks>LastTicks) {
Bit32u ticks=new_ticks-LastTicks;
if (ticks>20) ticks=20;
// if (ticks>3) LOG_DEBUG("Ticks %d",ticks);
LastTicks=new_ticks;
TIMER_AddTicks(ticks);
cycles+=cpu_cycles*ticks;
}
TIMER_CheckPIT(); TIMER_CheckPIT();
GFX_Events();
PIC_runIRQs(); PIC_runIRQs();
return (*cpudecoder)(cycles); Bitu ret;
do {
PIC_IRQAgain=false;
ret=(*cpudecoder)(cpu_cycles);
} while (!ret && PIC_IRQAgain);
#if C_DEBUG
if (DEBUG_ExitLoop()) return 0;
#endif
return ret;
} }
void DOSBOX_SetLoop(LoopHandler * handler) { void DOSBOX_SetLoop(LoopHandler * handler) {
@ -200,111 +122,89 @@ void DOSBOX_RunMachine(void){
} while (!ret); } while (!ret);
} }
static void DOSBOX_RealInit(Section * sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
/* Initialize some dosbox internals */
errorlevel=section->Get_int("warnings");
MSG_Add("DOSBOX_CONFIGFILE_HELP","General Dosbox settings\n");
LastTicks=GetTicks();
DOSBOX_SetLoop(&Normal_Loop);
MSG_Init(section);
}
static void InitSystems(void) { void DOSBOX_Init(void) {
MSG_Init(); // Section * sec;
MEM_Init(); Section_prop * secprop;
IO_Init(); Section_line * secline;
CALLBACK_Init();
PROGRAMS_Init(); /* Setup all the different modules making up DOSBox */
HARDWARE_Init();
TIMER_Init(); secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit);
CPU_Init(); secprop->Add_string("language","");
#if C_DEBUG
secprop->Add_int("warnings",4);
#else
secprop->Add_int("warnings",0);
#endif
secprop->AddInitFunction(&MEM_Init);
secprop->AddInitFunction(&IO_Init);
secprop->AddInitFunction(&CALLBACK_Init);
secprop->AddInitFunction(&PIC_Init);
secprop->AddInitFunction(&PROGRAMS_Init);
secprop->AddInitFunction(&TIMER_Init);
secprop->AddInitFunction(&RENDER_Init);
secprop->Add_string("snapshots","snapshots");
secprop=control->AddSection_prop("cpu",&CPU_Init);
secprop->Add_int("cycles",4000);
secprop->AddInitFunction(&DMA_Init);
secprop->AddInitFunction(&VGA_Init);
secprop->AddInitFunction(&KEYBOARD_Init);
secprop->AddInitFunction(&MOUSE_Init);
secprop->AddInitFunction(&JOYSTICK_Init);
secprop=control->AddSection_prop("mixer",&MIXER_Init);
#if C_DEBUG
secprop=control->AddSection_prop("debug",&DEBUG_Init);
#endif
secprop=control->AddSection_prop("sblaster",&SBLASTER_Init);
secprop->Add_hex("base",0x220);
secprop->Add_int("irq",7);
secprop->Add_int("dma",1);
secprop->Add_int("hdma",5);
secprop->Add_bool("enabled",true);
secprop->AddInitFunction(&ADLIB_Init);
secprop->Add_bool("adlib",true);
secprop->AddInitFunction(&CMS_Init);
secprop->Add_bool("cms",false);
secprop=control->AddSection_prop("speaker",&PCSPEAKER_Init);
secprop->Add_bool("sinewave",false);
secprop->AddInitFunction(&TANDYSOUND_Init);
secprop->Add_bool("tandy",false);
secprop=control->AddSection_prop("bios",&BIOS_Init);
secprop->AddInitFunction(&INT10_Init);
/* All the DOS Related stuff, which will eventually start up in the shell */
//TODO Maybe combine most of the dos stuff in one section like ems,xms
secprop=control->AddSection_prop("dos",&DOS_Init);
secprop->AddInitFunction(&EMS_Init);
secprop->Add_int("emssize",4);
secprop->AddInitFunction(&XMS_Init);
secprop->Add_int("xmssize",8);
secline=control->AddSection_line("autoexec",&AUTOEXEC_Init);
control->SetStartUp(&SHELL_Init);
#if C_FPU #if C_FPU
FPU_Init(); FPU_Init();
#endif #endif
MIXER_Init();
#if C_DEBUG
DEBUG_Init();
#endif
//Start up individual hardware
DMA_Init();
PIC_Init();
VGA_Init();
KEYBOARD_Init();
MOUSE_Init();
JOYSTICK_Init();
SBLASTER_Init();
TANDY_Init();
PCSPEAKER_Init();
ADLIB_Init();
CMS_Init();
PLUGIN_Init();
/* Most of teh interrupt handlers */
BIOS_Init();
DOS_Init();
EMS_Init(); //Needs dos first
XMS_Init(); //Needs dos first
/* Setup the normal system loop */
LastTicks=GetTicks();
DOSBOX_SetLoop(&Normal_Loop);
// DOSBOX_SetLoop(&Speed_Loop);
} }
void DOSBOX_Init(int argc, char* argv[]) {
/* Find the base directory */
SHELL_AddAutoexec("SET PATH=Z:\\");
SHELL_AddAutoexec("SET COMSPEC=Z:\\COMMAND.COM");
strcpy(dosbox_basedir,argv[0]);
char * last=strrchr(dosbox_basedir,CROSS_FILESPLIT); //if windowsversion fails:
if (!last){
getcwd(dosbox_basedir,CROSS_LEN);
char a[2];
a[0]=CROSS_FILESPLIT;
a[1]='\0';
strcat(dosbox_basedir,a);
} else {
*++last=0;
}
/* Parse the command line with a setup function */
int argl=1;
if (argc>1) {
if (*argv[1]!='-') {
struct stat test;
if (stat(argv[1],&test)) {
E_Exit("%s Doesn't exist",argv[1]);
}
/* Not a switch so a normal directory/file */
if (test.st_mode & S_IFDIR) {
SHELL_AddAutoexec("MOUNT C %s",argv[1]);
SHELL_AddAutoexec("C:");
} else {
char * name=strrchr(argv[1],CROSS_FILESPLIT);
if (!name) E_Exit("This is weird %s",argv[1]);
*name++=0;
if (access(argv[1],F_OK)) E_Exit("Illegal Directory %s",argv[1]);
SHELL_AddAutoexec("MOUNT C %s",argv[1]);
SHELL_AddAutoexec("C:");
SHELL_AddAutoexec(name);
}
argl++;
}
}
bool sw_c=false;
while (argl<argc) {
if (*argv[argl]=='-') {
sw_c=false;
if (strcmp(argv[argl],"-c")==0) sw_c=true;
else E_Exit("Illegal switch %s",argv[argl]);
argl++;
continue;
}
SHELL_AddAutoexec(argv[argl]);
if (sw_c) {
}
argl++;
}
InitSystems();
}
void DOSBOX_StartUp(void) {
SHELL_Init();
};

View File

@ -1,75 +0,0 @@
:SHELL_CMD_HELP
supported commands are:
.
:SHELL_ILLEGAL_SWITCH
Illegal switch: %s
.
:SHELL_CMD_ECHO_ON
ECHO is on
.
:SHELL_CMD_ECHO_OFF
ECHO is off
.
:SHELL_CMD_CHDIR_ERROR
Unable to change to: %s
.
:SHELL_CMD_MKDIR_ERROR
Unable to make: %s
.
:SHELL_CMD_RMDIR_ERROR
Unable to remove: %s
.
:SHELL_SYNTAXERROR
The syntax of the command is incorrect
.
:SHELL_CMD_SET_NOT_SET
Environment variable %s not defined
.
:SHELL_CMD_SET_OUT_OF_SPACE
Not enough environment space left
.
:SHELL_CMD_IF_EXIST_MISSING_FILENAME
IF EXIST: Missing filename
.
:SHELL_CMD_IF_ERRORLEVEL_MISSING_NUMBER
IF ERRORLEVEL: Missing number
.
:SHELL_CMD_IF_ERRORLEVEL_INVALID_NUMBER
IF ERRORLEVEL: Invalid number
.
:SHELL_CMD_GOTO_MISSING_LABEL
No label supplied to GOTO command
.
:SHELL_CMD_GOTO_LABEL_NOT_FOUND
Label %s not found
.
:SHELL_CMD_FILE_NOT_FOUND
File %s not found
.
:SHELL_CMD_DIR_INTRO
Directory of %s
.
:SHELL_CMD_DIR_PATH_ERROR
Illegal Path
.
:SHELL_CMD_DIR_BYTES_USED
%16d File(s) %16s Bytes
.
:SHELL_CMD_DIR_BYTES_FREE
%16d Dir(s) %16s Bytes free
.
:SHELL_STARTUP
DOSBox Shell v0.35
For Help and supported commands type: HELP
For information about the hardware setup manager type: HWSET /?
HAVE FUN!
The DOSBox Team
.
:SHELL_EXECUTE_DRIVE_NOT_FOUND
Drive %c does not exist!
.
:SHELL_EXECUTE_ILLEGAL_COMMAND
Illegal command: %s
.

View File

@ -16,14 +16,20 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <png.h>
#include <dirent.h>
#include "dosbox.h" #include "dosbox.h"
#include "video.h" #include "video.h"
#include "render.h" #include "render.h"
#include "setup.h"
#include "keyboard.h"
#include "cross.h"
#define MAX_RES 2048 #define MAX_RES 2048
struct PalData { struct PalData {
struct { struct {
Bit8u red; Bit8u red;
@ -51,8 +57,104 @@ static struct {
PalData pal; PalData pal;
bool remake; bool remake;
bool enlarge; bool enlarge;
bool screenshot;
} render; } render;
static const char * snapshots_dir;
/* Take a screenshot of the data that should be rendered */
static void TakeScreenShot(Bit8u * bitmap) {
Bitu last=0;char file_name[CROSS_LEN];
DIR * dir;struct dirent * dir_ent;
png_structp png_ptr;
png_infop info_ptr;
png_bytep * row_pointers;
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);
if (!dir) {
LOG_WARN("Can't open snapshot dir %s",snapshots_dir);
return;
}
while (dir_ent=readdir(dir)) {
char tempname[CROSS_LEN];
strcpy(tempname,dir_ent->d_name);
char * test=strstr(tempname,".png");
if (!test) continue;
*test=0;
if (strlen(tempname)<5) continue;
if (strncmp(tempname,"snap",4)!=0) continue;
Bitu num=atoi(&tempname[4]);
if (num>=last) last=num+1;
}
closedir(dir);
sprintf(file_name,"%s%csnap%05d.png",snapshots_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);
return;
}
/* Finalize the initing of png library */
png_init_io(png_ptr, fp);
png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
/* set other zlib parameters */
png_set_compression_mem_level(png_ptr, 8);
png_set_compression_strategy(png_ptr,Z_DEFAULT_STRATEGY);
png_set_compression_window_bits(png_ptr, 15);
png_set_compression_method(png_ptr, 8);
png_set_compression_buffer_size(png_ptr, 8192);
if (render.src.bpp==8) {
png_set_IHDR(png_ptr, info_ptr, render.src.width, render.src.height,
8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
for (i=0;i<256;i++) {
palette[i].red=render.pal.rgb[i].red;
palette[i].green=render.pal.rgb[i].green;
palette[i].blue=render.pal.rgb[i].blue;
}
png_set_PLTE(png_ptr, info_ptr, palette,256);
} else {
png_set_IHDR(png_ptr, info_ptr, render.src.width, render.src.height,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
}
/*Allocate an array of scanline pointers*/
row_pointers=(png_bytep*)malloc(render.src.height*sizeof(png_bytep));
for (i=0;i<render.src.height;i++) {
row_pointers[i]=(bitmap+i*render.src.pitch);
}
/*tell the png library what to encode.*/
png_set_rows(png_ptr, info_ptr, row_pointers);
/*Write image to file*/
png_write_png(png_ptr, info_ptr, 0, NULL);
/*close file*/
fclose(fp);
/*Destroy PNG structs*/
png_destroy_write_struct(&png_ptr, &info_ptr);
/*clean up dynamically allocated RAM.*/
free(row_pointers);
}
/* This could go kinda bad with multiple threads */ /* This could go kinda bad with multiple threads */
static void Check_Palette(void) { static void Check_Palette(void) {
if (render.pal.first>render.pal.last) return; if (render.pal.first>render.pal.last) return;
@ -98,8 +200,11 @@ void RENDER_Draw(Bit8u * bitdata) {
render.remake=false; render.remake=false;
} }
render.handler(&src_data); render.handler(&src_data);
if (render.screenshot) {
TakeScreenShot(src_data);
render.screenshot=false;
}
Draw_8_Normal(src_data,bitdata); Draw_8_Normal(src_data,bitdata);
} }
@ -151,10 +256,15 @@ void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu
} }
static void EnableScreenShot(void) {
void RENDER_Init(void) { render.screenshot=true;
}
void RENDER_Init(Section * sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
snapshots_dir=section->Get_string("snapshots");
render.pal.first=256; render.pal.first=256;
render.pal.last=0; render.pal.last=0;
render.enlarge=false; render.enlarge=false;
KEYBOARD_AddEvent(KBD_f5,CTRL_PRESSED,EnableScreenShot);
} }

View File

@ -18,8 +18,9 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <SDL/SDL.h> #include <SDL.h>
#include <SDL/SDL_thread.h> #include <SDL_thread.h>
#include "dosbox.h" #include "dosbox.h"
#include "video.h" #include "video.h"
#include "keyboard.h" #include "keyboard.h"
@ -27,7 +28,8 @@
#include "joystick.h" #include "joystick.h"
#include "pic.h" #include "pic.h"
#include "timer.h" #include "timer.h"
#include "setup.h"
#include "debug.h"
//#define DISABLE_JOYSTICK //#define DISABLE_JOYSTICK
@ -39,13 +41,23 @@ struct SDL_Block {
Bitu bpp; Bitu bpp;
GFX_DrawHandler * draw; GFX_DrawHandler * draw;
GFX_ResizeHandler * resize; GFX_ResizeHandler * resize;
bool mouse_grabbed;
bool full_screen; bool full_screen;
SDL_Thread * thread; SDL_Thread * thread;
SDL_mutex * mutex; SDL_mutex * mutex;
SDL_Surface * surface; SDL_Surface * surface;
SDL_Joystick * joy; SDL_Joystick * joy;
SDL_Color pal[256]; SDL_Color pal[256];
struct {
bool autolock;
bool autoenable;
bool requestlock;
bool locked;
Bitu sensitivity;
} mouse;
struct {
Bitu skip;
Bitu count;
} frames ;
}; };
static SDL_Block sdl; static SDL_Block sdl;
@ -98,8 +110,8 @@ void GFX_Resize(Bitu width,Bitu height,Bitu bpp,GFX_ResizeHandler * resize) {
} }
static void CaptureMouse() { static void CaptureMouse() {
sdl.mouse_grabbed=!sdl.mouse_grabbed; sdl.mouse.locked=!sdl.mouse.locked;
if (sdl.mouse_grabbed) { if (sdl.mouse.locked) {
SDL_WM_GrabInput(SDL_GRAB_ON); SDL_WM_GrabInput(SDL_GRAB_ON);
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
} else { } else {
@ -108,6 +120,16 @@ static void CaptureMouse() {
} }
} }
static void DecreaseSkip() {
if (sdl.frames.skip>0) sdl.frames.skip--;
LOG_MSG("Frame Skip %d",sdl.frames.skip);
}
static void IncreaseSkip() {
if (sdl.frames.skip<10) sdl.frames.skip++;
LOG_MSG("Frame Skip %d",sdl.frames.skip);
}
static void SwitchFullScreen(void) { static void SwitchFullScreen(void) {
GFX_Stop(); GFX_Stop();
sdl.full_screen=!sdl.full_screen; sdl.full_screen=!sdl.full_screen;
@ -120,6 +142,10 @@ static void SwitchFullScreen(void) {
ResetScreen(); ResetScreen();
GFX_Start(); GFX_Start();
} }
//only prototype existed
void GFX_SwitchFullScreen(void) {
SwitchFullScreen();
}
static void GFX_Redraw() { static void GFX_Redraw() {
#if C_THREADED #if C_THREADED
@ -127,6 +153,9 @@ static void GFX_Redraw() {
E_Exit("Can't Lock Mutex"); E_Exit("Can't Lock Mutex");
}; };
#endif #endif
if (++sdl.frames.count<sdl.frames.skip) goto skipframe;
sdl.frames.count=0;
if (sdl.active) { if (sdl.active) {
SDL_LockSurface(sdl.surface ); SDL_LockSurface(sdl.surface );
if (sdl.surface->pixels && sdl.draw) (*sdl.draw)((Bit8u *)sdl.surface->pixels); if (sdl.surface->pixels && sdl.draw) (*sdl.draw)((Bit8u *)sdl.surface->pixels);
@ -134,6 +163,7 @@ static void GFX_Redraw() {
if (sdl.full_screen) SDL_Flip(sdl.surface); if (sdl.full_screen) SDL_Flip(sdl.surface);
else SDL_UpdateRect(sdl.surface,0,0,0,0); else SDL_UpdateRect(sdl.surface,0,0,0,0);
}; };
skipframe:
#if C_THREADED #if C_THREADED
if (SDL_mutexV(sdl.mutex)) { if (SDL_mutexV(sdl.mutex)) {
E_Exit("Can't Release Mutex"); E_Exit("Can't Release Mutex");
@ -193,32 +223,53 @@ void GFX_Start() {
sdl.active=true; sdl.active=true;
} }
static void GUI_ShutDown(Section * sec) {
GFX_Stop();
if (sdl.mouse.locked) CaptureMouse();
if (sdl.full_screen) SwitchFullScreen();
}
void GFX_StartUp() { static void GUI_StartUp(Section * sec) {
MSG_Add("SDL_CONFIGFILE_HELP","SDL related options.\n");
sec->AddDestroyFunction(&GUI_ShutDown);
Section_prop * section=static_cast<Section_prop *>(sec);
sdl.active=false; sdl.active=false;
sdl.full_screen=false; sdl.full_screen=false;
sdl.frames.skip=0;
sdl.frames.count=0;
sdl.draw=0; sdl.draw=0;
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_Resize(640,400,8,0);
#if C_THREADED #if C_THREADED
sdl.mutex=SDL_CreateMutex(); sdl.mutex=SDL_CreateMutex();
sdl.thread = SDL_CreateThread(&SDLGFX_Thread,0); sdl.thread = SDL_CreateThread(&SDLGFX_Thread,0);
#else #else
TIMER_RegisterMicroHandler(GFX_Redraw,1000000/70); TIMER_RegisterMicroHandler(GFX_Redraw,1000000/70);
#endif #endif
GFX_Resize(640,400,8,0);
SDL_EnableKeyRepeat(250,30); SDL_EnableKeyRepeat(250,30);
/* Get some Keybinds */ /* Get some Keybinds */
KEYBOARD_AddEvent(KBD_f9,CTRL_PRESSED,SwitchFullScreen);
KEYBOARD_AddEvent(KBD_f10,CTRL_PRESSED,CaptureMouse); KEYBOARD_AddEvent(KBD_f10,CTRL_PRESSED,CaptureMouse);
KEYBOARD_AddEvent(KBD_f7,CTRL_PRESSED,DecreaseSkip);
KEYBOARD_AddEvent(KBD_f8,CTRL_PRESSED,IncreaseSkip);
KEYBOARD_AddEvent(KBD_enter,ALT_PRESSED,SwitchFullScreen); KEYBOARD_AddEvent(KBD_enter,ALT_PRESSED,SwitchFullScreen);
} }
void GFX_ShutDown() { void GFX_ShutDown() {
if (sdl.full_screen) SwitchFullScreen(); if (sdl.full_screen) SwitchFullScreen();
if (sdl.mouse_grabbed) CaptureMouse(); if (sdl.mouse.locked) CaptureMouse();
GFX_Stop(); GFX_Stop();
} }
void Mouse_AutoLock(bool enable) {
sdl.mouse.autolock=enable;
if (enable && sdl.mouse.autoenable) sdl.mouse.requestlock=true;
else sdl.mouse.requestlock=false;
}
static void HandleKey(SDL_KeyboardEvent * key) { static void HandleKey(SDL_KeyboardEvent * key) {
Bit32u code; Bit32u code;
@ -348,16 +399,17 @@ static void HandleKey(SDL_KeyboardEvent * key) {
} }
static void HandleMouseMotion(SDL_MouseMotionEvent * motion) { static void HandleMouseMotion(SDL_MouseMotionEvent * motion) {
if (!sdl.mouse_grabbed) { if (sdl.mouse.locked) {
Mouse_CursorSet((float)motion->x/(float)sdl.width,(float)motion->y/(float)sdl.height); Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100,(float)motion->yrel*sdl.mouse.sensitivity/100);
} else { } else {
Mouse_CursorMoved((float)motion->xrel/(float)sdl.width,(float)motion->yrel/(float)sdl.height); // Mouse_CursorSet((float)motion->x/(float)sdl.width,(float)motion->y/(float)sdl.height);
} }
} }
static void HandleMouseButton(SDL_MouseButtonEvent * button) { static void HandleMouseButton(SDL_MouseButtonEvent * button) {
switch (button->state) { switch (button->state) {
case SDL_PRESSED: case SDL_PRESSED:
if (sdl.mouse.requestlock && !sdl.mouse.locked) CaptureMouse();
switch (button->button) { switch (button->button) {
case SDL_BUTTON_LEFT: case SDL_BUTTON_LEFT:
Mouse_ButtonPressed(0); Mouse_ButtonPressed(0);
@ -424,6 +476,13 @@ void GFX_Events() {
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
switch (event.type) { switch (event.type) {
case SDL_ACTIVEEVENT:
if (event.active.state & SDL_APPINPUTFOCUS) {
if (!event.active.gain && sdl.mouse.locked) {
CaptureMouse();
}
}
break;
case SDL_KEYDOWN: case SDL_KEYDOWN:
case SDL_KEYUP: case SDL_KEYUP:
HandleKey(&event.key); HandleKey(&event.key);
@ -451,24 +510,6 @@ void GFX_Events() {
} }
} }
} }
#if 0
void E_Exit(char * format,...) {
char buf[1024];
va_list msg;
strcpy(buf,"EXIT:");
va_start(msg,format);
vsprintf(buf+strlen(buf),format,msg);
va_end(msg);
waddstr(dbg.win_out,buf);
wprintw(dbg.win_out," %d\n",cycle_count);
wrefresh(dbg.win_out);
throw ((Bitu)1);
}
#endif
void GFX_ShowMsg(char * msg) { void GFX_ShowMsg(char * msg) {
char buf[1024]; char buf[1024];
@ -478,19 +519,40 @@ void GFX_ShowMsg(char * msg) {
}; };
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#if C_DEBUG
DEBUG_SetupConsole();
#endif
try { try {
CommandLine com_line(argc,argv);
Config myconf(&com_line);
control=&myconf;
if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER
#ifndef DISABLE_JOYSTICK #ifndef DISABLE_JOYSTICK
|SDL_INIT_JOYSTICK |SDL_INIT_JOYSTICK
#endif #endif
) < 0 ) { ) < 0 ) E_Exit("Can't init SDL %s",SDL_GetError());
E_Exit("Can't init SDL %s",SDL_GetError()); Section_prop * sdl_sec=control->AddSection_prop("sdl",&GUI_StartUp);
sdl_sec->Add_bool("fullscreen",false);
sdl_sec->Add_bool("autolock",true);
sdl_sec->Add_int("sensitivity",100);
/* Init all the dosbox subsystems */
DOSBOX_Init();
std::string config_file;
if (control->cmdline->FindString("-conf",config_file,true)) {
} else {
config_file="dosbox.conf";
} }
GFX_StartUp(); /* Parse the config file */
/* Init all the dosbox subsystems */ control->ParseConfigFile(config_file.c_str());
DOSBOX_Init(argc,argv); /* Init all the sections */
/* Start the systems that SDL should provide */ control->Init();
/* Some extra SDL Functions */
#ifndef DISABLE_JOYSTICK #ifndef DISABLE_JOYSTICK
if (SDL_NumJoysticks()>0) { if (SDL_NumJoysticks()>0) {
SDL_JoystickEventState(SDL_ENABLE); SDL_JoystickEventState(SDL_ENABLE);
@ -499,15 +561,15 @@ int main(int argc, char* argv[]) {
JOYSTICK_Enable(0,true); JOYSTICK_Enable(0,true);
} }
#endif #endif
/* Start dosbox up */ if (control->cmdline->FindExist("-fullscreen") || sdl_sec->Get_bool("fullscreen")) {
DOSBOX_StartUp(); SwitchFullScreen();
} }
catch (Bitu e) { /* Start up main machine */
LOG_MSG("Exit to error %d",e); control->StartUp();
/* Shutdown everything */
} catch (char * error) {
LOG_MSG("Exit to error: %sPress enter to continue.",error);
fgetc(stdin);
} }
GFX_Stop();
return 0; return 0;
}; };

View File

@ -24,7 +24,7 @@
#include "mixer.h" #include "mixer.h"
#include "timer.h" #include "timer.h"
#include "hardware.h" #include "hardware.h"
#include "setup.h"
/* /*
Thanks to vdmsound for nice simple way to implement this Thanks to vdmsound for nice simple way to implement this
*/ */
@ -126,7 +126,6 @@ static void write_p389(Bit32u port,Bit8u val) {
} }
static HWBlock hw_adlib;
static bool adlib_enabled; static bool adlib_enabled;
static void ADLIB_Enable(bool enable) { static void ADLIB_Enable(bool enable) {
@ -153,46 +152,9 @@ static void ADLIB_Enable(bool enable) {
} }
static void ADLIB_InputHandler(char * line) { void ADLIB_Init(Section* sec) {
bool s_off=ScanCMDBool(line,"OFF"); Section_prop * section=static_cast<Section_prop *>(sec);
bool s_on=ScanCMDBool(line,"ON"); if(!section->Get_bool("adlib")) return;
char * rem=ScanCMDRemain(line);
if (rem) {
sprintf(line,"Illegal Switch");
return;
}
if (s_on && s_off) {
sprintf(line,"Can't use /ON and /OFF at the same time");
return;
}
if (s_on) {
ADLIB_Enable(true);
sprintf(line,"Adlib has been enabled");
return;
}
if (s_off) {
ADLIB_Enable(false);
sprintf(line,"Adlib has been disabled");
return;
}
return;
}
static void ADLIB_OutputHandler (char * towrite) {
if(adlib_enabled) {
sprintf(towrite,"IO %X",0x388);
} else {
sprintf(towrite,"Disabled");
}
};
void ADLIB_Init(void) {
timer1.isMasked=true; timer1.isMasked=true;
timer1.base=0; timer1.base=0;
@ -211,14 +173,6 @@ void ADLIB_Init(void) {
adlib_chan=MIXER_AddChannel(ADLIB_CallBack,ADLIB_FREQ,"ADLIB"); adlib_chan=MIXER_AddChannel(ADLIB_CallBack,ADLIB_FREQ,"ADLIB");
MIXER_SetMode(adlib_chan,MIXER_16MONO); MIXER_SetMode(adlib_chan,MIXER_16MONO);
hw_adlib.dev_name="ADLIB";
hw_adlib.full_name="Adlib FM Synthesizer";
hw_adlib.next=0;
hw_adlib.help="/ON Enables Adlib\n/OFF Disables Adlib\n";
hw_adlib.get_input=ADLIB_InputHandler;
hw_adlib.show_status=ADLIB_OutputHandler;
HW_Register(&hw_adlib);
ADLIB_Enable(true); ADLIB_Enable(true);
}; };

View File

@ -70,6 +70,32 @@ struct DMA_CONTROLLER {
}; };
static DMA_CONTROLLER dma[2]; static DMA_CONTROLLER dma[2];
static Bit8u read_dma(Bit32u port) {
/* only use first dma for now */
DMA_CONTROLLER * cont=&dma[0];
DMA_CHANNEL * chan=&cont->chan[port>>1];
Bit8u ret;
switch (port) {
case 0x00:case 0x02:case 0x04:case 0x06:
if (cont->flipflop) {
ret=chan->current_address & 0xff;
} else {
ret=(chan->current_address>>8)&0xff;
}
cont->flipflop=!cont->flipflop;
case 0x01:case 0x03:case 0x05:case 0x07:
if (cont->flipflop) {
ret=(chan->current_count-1) & 0xff;
} else {
ret=((chan->current_count-1)>>8)&0xff;
}
cont->flipflop=!cont->flipflop;
break;
default:
LOG_WARN("DMA:Unhandled read from %d",port);
}
return ret;
}
static void write_dma(Bit32u port,Bit8u val) { static void write_dma(Bit32u port,Bit8u val) {
@ -203,9 +229,10 @@ Bit16u DMA_16_Write(Bit32u dmachan,Bit8u * buffer,Bit16u count) {
void DMA_Init(void) { void DMA_Init(Section* sec) {
for (Bit32u i=0;i<0x10;i++) { for (Bit32u i=0;i<0x10;i++) {
IO_RegisterWriteHandler(i,write_dma,"DMA1"); IO_RegisterWriteHandler(i,write_dma,"DMA1");
IO_RegisterReadHandler(i,read_dma,"DMA1");
} }
IO_RegisterWriteHandler(0x81,write_dma_page,"DMA Pages"); IO_RegisterWriteHandler(0x81,write_dma_page,"DMA Pages");
IO_RegisterWriteHandler(0x82,write_dma_page,"DMA Pages"); IO_RegisterWriteHandler(0x82,write_dma_page,"DMA Pages");

View File

@ -22,11 +22,11 @@
#include "mixer.h" #include "mixer.h"
#include "mem.h" #include "mem.h"
#include "hardware.h" #include "hardware.h"
#include "setup.h"
#define CMS_RATE 22050 #define CMS_RATE 22050
#define CMS_VOLUME 6000 #define CMS_VOLUME 6000
#define FREQ_SHIFT 16 #define FREQ_SHIFT 16
#define SIN_ENT 1024 #define SIN_ENT 1024
@ -36,8 +36,6 @@
#define PI 3.14159265358979323846 #define PI 3.14159265358979323846
#endif #endif
struct CMS { struct CMS {
struct { struct {
Bit32u freq_pos; Bit32u freq_pos;
@ -157,7 +155,6 @@ static void CMS_CallBack(Bit8u * stream,Bit32u len) {
} }
static HWBlock hw_cms;
static bool cms_enabled; static bool cms_enabled;
static void CMS_Enable(bool enable) { static void CMS_Enable(bool enable) {
@ -178,56 +175,14 @@ static void CMS_Enable(bool enable) {
} }
} }
void CMS_Init(Section* sec) {
static void CMS_InputHandler(char * line) { Section_prop * section=static_cast<Section_prop *>(sec);
bool s_off=ScanCMDBool(line,"OFF"); if(!section->Get_bool("cms")) return;
bool s_on=ScanCMDBool(line,"ON");
char * rem=ScanCMDRemain(line);
if (rem) {
sprintf(line,"Illegal Switch");
return;
}
if (s_on && s_off) {
sprintf(line,"Can't use /ON and /OFF at the same time");
return;
}
if (s_on) {
CMS_Enable(true);
sprintf(line,"Creative Music System has been enabled");
return;
}
if (s_off) {
CMS_Enable(false);
sprintf(line,"Creative Music System has been disabled");
return;
}
return;
}
static void CMS_OutputHandler (char * towrite) {
if(cms_enabled) {
sprintf(towrite,"IO %X",0x220);
} else {
sprintf(towrite,"Disabled");
}
};
void CMS_Init(void) {
Bits i; Bits i;
/* Register the Mixer CallBack */ /* Register the Mixer CallBack */
cms_chan=MIXER_AddChannel(CMS_CallBack,CMS_RATE,"CMS"); cms_chan=MIXER_AddChannel(CMS_CallBack,CMS_RATE,"CMS");
MIXER_SetMode(cms_chan,MIXER_16STEREO); MIXER_SetMode(cms_chan,MIXER_16STEREO);
MIXER_Enable(cms_chan,false); MIXER_Enable(cms_chan,false);
/* Register with the hardware setup tool */
hw_cms.dev_name="CMS";
hw_cms.full_name="Creative Music System";
hw_cms.next=0;
hw_cms.help="/ON Enables CMS\n/OFF Disables CMS\n";
hw_cms.get_input=CMS_InputHandler;
hw_cms.show_status=CMS_OutputHandler;
HW_Register(&hw_cms);
CMS_Enable(false);
/* Make the frequency/octave table */ /* Make the frequency/octave table */
double log_start=log10(27.34375); double log_start=log10(27.34375);
double log_add=(log10(54.609375)-log10(27.34375))/256; double log_add=(log10(54.609375)-log10(27.34375))/256;
@ -250,7 +205,6 @@ void CMS_Init(void) {
out /= 1.1; out /= 1.1;
} }
} }
CMS_Enable(true);
} }

View File

@ -24,94 +24,10 @@
#include "dosbox.h" #include "dosbox.h"
#include "programs.h" #include "programs.h"
#include "hardware.h" #include "hardware.h"
#include "setup.h"
static HWBlock * firsthw=0;
class HWSET : public Program { void HARDWARE_Init(Section * sec) {
public:
HWSET(PROGRAM_Info * program_info);
void Run(void);
};
HWSET::HWSET(PROGRAM_Info * info):Program(info) {
} }
void HW_Register(HWBlock * block) {
block->next=firsthw;
firsthw=block;
}
void HWSET::Run(void) {
/* Hopefull enough space */
char buf[1024];
HWBlock * loopblock;
if (!*prog_info->cmd_line) {
/* No command line given give overview of hardware */
loopblock=firsthw;
WriteOut("ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿");
WriteOut("³Device ³Full Name ³Status ³");
WriteOut("ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´");
while (loopblock) {
if (loopblock->show_status) {
loopblock->show_status(buf);
} else {
strcpy(buf,"No Status Handler");
}
WriteOut("³%-8s³%-25s³%-43s³",loopblock->dev_name,loopblock->full_name,buf);
loopblock=loopblock->next;
}
WriteOut("ÀÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ");
WriteOut("If you want to setup specific hardware use \"HWSET Device\" for information.\n");
return;
}
/* Command line given */
if (strcmp(prog_info->cmd_line,"/?")==0) {
WriteOut("Hardware setup tool for DOSBox.\n");
WriteOut("This program can be used to change the settings of internal hardware.\n\n"
"HWSET [device] [switches]\n\n"
"Using an empty command line gives you a list of hardware.\n"
"You can get list of switches for a device with HWSET device.\n"
);
return;
}
char * rest=strchr(prog_info->cmd_line,' ');
if (rest) *rest++=0;
loopblock=firsthw;
while (loopblock) {
if (strcasecmp(loopblock->dev_name,prog_info->cmd_line)==0) goto founddev;
loopblock=loopblock->next;
}
WriteOut("Device %s not found\n",prog_info->cmd_line);
return;
founddev:
/* Check for rest of line */
if (rest) {
strcpy(buf,rest);
loopblock->get_input(buf);
WriteOut(buf);
} else {
WriteOut("Command overview for %s\n%s",loopblock->full_name,loopblock->help);
}
return;
}
static void HWSET_ProgramStart(PROGRAM_Info * info) {
HWSET * tempHWSET=new HWSET(info);
tempHWSET->Run();
delete tempHWSET;
}
void HARDWARE_Init(void) {
PROGRAMS_MakeFile("HWSET.COM",HWSET_ProgramStart);
};

View File

@ -80,7 +80,7 @@ void IO_FreeWriteHandler(Bit32u port) {
} }
void IO_Init(void) { void IO_Init(Section * sect) {
for (Bitu i=0;i<IO_MAX;i++) { for (Bitu i=0;i<IO_MAX;i++) {
IO_RegisterReadHandler(i,&IO_ReadDefault,"Default Read"); IO_RegisterReadHandler(i,&IO_ReadDefault,"Default Read");
IO_RegisterWriteHandler(i,&IO_WriteDefault,"Default Write"); IO_RegisterWriteHandler(i,&IO_WriteDefault,"Default Write");

View File

@ -50,8 +50,8 @@ static Bit8u read_p201(Bit32u port) {
if (stick[0].button[1]) ret&=32; if (stick[0].button[1]) ret&=32;
} }
if (stick[1].enabled) { if (stick[1].enabled) {
if (stick[1].xcount) stick[0].xcount--; else ret&=~4; if (stick[1].xcount) stick[1].xcount--; else ret&=~4;
if (stick[1].ycount) stick[0].ycount--; else ret&=~8; if (stick[1].ycount) stick[1].ycount--; else ret&=~8;
if (stick[1].button[0]) ret&=64; if (stick[1].button[0]) ret&=64;
if (stick[1].button[1]) ret&=128; if (stick[1].button[1]) ret&=128;
} }
@ -60,12 +60,12 @@ static Bit8u read_p201(Bit32u port) {
static void write_p201(Bit32u port,Bit8u val) { static void write_p201(Bit32u port,Bit8u val) {
if (stick[0].enabled) { if (stick[0].enabled) {
stick[0].xcount=(Bitu)(stick[0].xpos*RANGE+RANGE*2); stick[0].xcount=(Bitu)((stick[0].xpos*RANGE)+RANGE);
stick[0].ycount=(Bitu)(stick[0].ypos*RANGE+RANGE*2); stick[0].ycount=(Bitu)((stick[0].ypos*RANGE)+RANGE);
} }
if (stick[1].enabled) { if (stick[1].enabled) {
stick[1].xcount=(Bitu)(stick[1].xpos*RANGE+RANGE*2); stick[1].xcount=(Bitu)((stick[1].xpos*RANGE)+RANGE);
stick[1].ycount=(Bitu)(stick[1].ypos*RANGE+RANGE*2); stick[1].ycount=(Bitu)((stick[1].ypos*RANGE)+RANGE);
} }
} }
@ -91,7 +91,7 @@ void JOYSTICK_Move_Y(Bitu which,float y) {
} }
void JOYSTICK_Init(void) { void JOYSTICK_Init(Section* sec) {
IO_RegisterReadHandler(0x201,read_p201,"JOYSTICK"); IO_RegisterReadHandler(0x201,read_p201,"JOYSTICK");
IO_RegisterWriteHandler(0x201,write_p201,"JOYSTICK"); IO_RegisterWriteHandler(0x201,write_p201,"JOYSTICK");
stick[0].enabled=false; stick[0].enabled=false;

View File

@ -23,9 +23,14 @@
#include "pic.h" #include "pic.h"
#include "mixer.h" #include "mixer.h"
#define KEYBUFSIZE 32 #define KEYBUFSIZE 32
enum KeyCommands {
CMD_NONE,
CMD_SETLEDS,
CMD_SETTYPERATE
};
struct KeyEvent { struct KeyEvent {
Bitu type; Bitu type;
@ -34,43 +39,109 @@ struct KeyEvent {
KeyEvent * next; KeyEvent * next;
}; };
struct KeyBlock {
Bit8u buf[KEYBUFSIZE];
Bitu buf_pos;
Bitu buf_used;
Bitu write_state;
KeyCommands command;
bool read_active;
bool enabled;
};
static KeyBlock keyb;
static Bitu shift_state=0; static Bitu shift_state=0;
static Bit8u cur_scancode; static Bit8u cur_scancode;
static Bit8u kbuf[KEYBUFSIZE];
static Bitu kbuf_pos;
static Bitu kbuf_used;
static Bit8u port_61_data; static Bit8u port_61_data;
//TODO Are these initialized at 0 at startup? Hope so :) //TODO Are these initialized at 0 at startup? Hope so :)
static KeyEvent * event_handlers[KBD_LAST]; static KeyEvent * event_handlers[KBD_LAST];
void KEYBOARD_ClrBuffer(void) {
keyb.buf_used=0;
keyb.buf_pos=0;
keyb.read_active=false;
PIC_DeActivateIRQ(1);
}
void KEYBOARD_ReadBuffer(void) {
if (keyb.read_active) return;
if (keyb.buf_used) {
keyb.buf_used--;
keyb.buf_pos++;
if (keyb.buf_pos>=KEYBUFSIZE) keyb.buf_pos=0;
}
if (keyb.buf_used) {
keyb.read_active=true;
PIC_ActivateIRQ(1);
}
}
void KEYBOARD_AddCode(Bit8u code) {
if (keyb.buf_used<KEYBUFSIZE) {
Bitu start=keyb.buf_pos+keyb.buf_used;
keyb.buf_used++;
if (start>=KEYBUFSIZE) start-=KEYBUFSIZE;
keyb.buf[start]=code;
keyb.read_active=true;
}
if (keyb.buf_used>0) PIC_ActivateIRQ(1);
}
static Bit8u read_p60(Bit32u port) { static Bit8u read_p60(Bit32u port) {
if (kbuf_used>0) { /* Reading this port signals that IRQ can be lowered */
cur_scancode=kbuf[kbuf_pos]; Bit8u val=keyb.buf[keyb.buf_pos];
}; keyb.read_active=false;
return cur_scancode; return keyb.buf[keyb.buf_pos];
} }
static void write_p60(Bit32u port,Bit8u val) { static void write_p60(Bit32u port,Bit8u val) {
//TODO Work this out ;) switch (keyb.command) {
LOG_DEBUG("Port 60 write with val %d",val); case CMD_NONE: /* None */
KEYBOARD_ClrBuffer();
switch (val) {
case 0xed: /* Set Leds */
keyb.command=CMD_SETLEDS;
KEYBOARD_AddCode(0xfa); /* Acknowledge */
break;
case 0xee: /* Echo */
KEYBOARD_AddCode(0xee);
break;
case 0xf2: /* Identify keyboard */
/* AT's just send acknowledge */
KEYBOARD_AddCode(0xfa); /* Acknowledge */
break;
case 0xf3: /* Typematic rate programming */
keyb.command=CMD_SETTYPERATE;
KEYBOARD_AddCode(0xfa); /* Acknowledge */
break;
default:
LOG_DEBUG("KEYB:60:Unhandled command %X",val);
}
return;
case CMD_SETTYPERATE:
case CMD_SETLEDS:
keyb.command=CMD_NONE;
KEYBOARD_AddCode(0xfa); /* Acknowledge */
break;
}
} }
static Bit8u read_p61(Bit32u port) { static Bit8u read_p61(Bit32u port) {
port_61_data^=0x20;
return port_61_data; return port_61_data;
}; };
static void KEYBOARD_IRQHandler(void) {
if (!keyb.read_active) KEYBOARD_ReadBuffer();
}
static void write_p61(Bit32u port,Bit8u val) { static void write_p61(Bit32u port,Bit8u val) {
//TODO Enable spreaker through here :)
if ((val&128)) { /* Keyboard acknowledge */
if (kbuf_used) {
kbuf_used--;
kbuf_pos++;
if (kbuf_pos>=KEYBUFSIZE) kbuf_pos=0;
if (kbuf_used) PIC_ActivateIRQ(1);
}
}
port_61_data=val; port_61_data=val;
if (val & 128) if (!keyb.read_active) KEYBOARD_ReadBuffer();
if ((val & 3)==3) { if ((val & 3)==3) {
PCSPEAKER_Enable(true); PCSPEAKER_Enable(true);
} else { } else {
@ -78,18 +149,17 @@ static void write_p61(Bit32u port,Bit8u val) {
} }
} }
static void write_p64(Bit32u port,Bit8u val) {
switch (val) {
void KEYBOARD_AddCode(Bit8u code) { case 0:
//Now Raise the keyboard IRQ default:
//If the buffer is full just drop the scancode :) LOG_DEBUG("Port 64 write with val %d",val);
if (kbuf_used<KEYBUFSIZE) { break;
Bit32u start=kbuf_used+kbuf_pos;
kbuf_used++;
if (start>=KEYBUFSIZE) start-=KEYBUFSIZE;
kbuf[start]=code;
} }
PIC_ActivateIRQ(1); }
static Bit8u read_p64(Bit32u port) {
return 0x1c | (keyb.read_active ? 0x1 : 0x0);
} }
@ -104,9 +174,7 @@ void KEYBOARD_AddEvent(Bitu keytype,Bitu state,KEYBOARD_EventHandler * handler)
newevent->type=keytype; newevent->type=keytype;
newevent->state=state; newevent->state=state;
newevent->handler=handler; newevent->handler=handler;
}
};
void KEYBOARD_AddKey(Bitu keytype,bool pressed) { void KEYBOARD_AddKey(Bitu keytype,bool pressed) {
bool extend=false; bool extend=false;
@ -217,9 +285,13 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) {
//The Extended keys //The Extended keys
case KBD_kpenter:extend=true;ret=28;break; case KBD_kpenter:extend=true;ret=28;break;
case KBD_rightctrl:extend=true;ret=29;break; case KBD_rightctrl:extend=true;ret=29;
shift_state=(shift_state&~CTRL_PRESSED)|(pressed ? CTRL_PRESSED:0);
break;
case KBD_kpslash:extend=true;ret=53;break; case KBD_kpslash:extend=true;ret=53;break;
case KBD_rightalt:extend=true;ret=56;break; case KBD_rightalt:extend=true;ret=56;
shift_state=(shift_state&~ALT_PRESSED)|(pressed ? ALT_PRESSED:0);
break;
case KBD_home:extend=true;ret=71;break; case KBD_home:extend=true;ret=71;break;
case KBD_up:extend=true;ret=72;break; case KBD_up:extend=true;ret=72;break;
case KBD_pageup:extend=true;ret=73;break; case KBD_pageup:extend=true;ret=73;break;
@ -233,7 +305,7 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) {
default: default:
E_Exit("Unsopperted key press"); E_Exit("Unsopperted key press");
break; break;
}; }
/* check for active key events */ /* check for active key events */
KeyEvent * checkevent=event_handlers[keytype]; KeyEvent * checkevent=event_handlers[keytype];
while (checkevent) { while (checkevent) {
@ -249,14 +321,21 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) {
if (extend) KEYBOARD_AddCode(224); if (extend) KEYBOARD_AddCode(224);
if (!pressed) ret+=128; if (!pressed) ret+=128;
KEYBOARD_AddCode(ret); KEYBOARD_AddCode(ret);
}; }
void KEYBOARD_Init(void) { void KEYBOARD_Init(Section* sec) {
kbuf_used=0;kbuf_pos=0;
IO_RegisterWriteHandler(0x60,write_p60,"Keyboard"); IO_RegisterWriteHandler(0x60,write_p60,"Keyboard");
IO_RegisterReadHandler(0x60,read_p60,"Keyboard"); IO_RegisterReadHandler(0x60,read_p60,"Keyboard");
IO_RegisterWriteHandler(0x61,write_p61,"Keyboard"); IO_RegisterWriteHandler(0x61,write_p61,"Keyboard");
IO_RegisterReadHandler(0x61,read_p61,"Keyboard"); IO_RegisterReadHandler(0x61,read_p61,"Keyboard");
IO_RegisterWriteHandler(0x64,write_p64,"Keyboard");
IO_RegisterReadHandler(0x64,read_p64,"Keyboard");
port_61_data=1; /* Speaker control through PIT and speaker disabled */ port_61_data=1; /* Speaker control through PIT and speaker disabled */
// memset(&event_handlers,0,sizeof(event_handlers)); // memset(&event_handlers,0,sizeof(event_handlers));
}; /* Clear the keyb struct */
keyb.enabled=true;
keyb.command=CMD_NONE;
KEYBOARD_ClrBuffer();
PIC_RegisterIRQ(1,KEYBOARD_IRQHandler,"KEYBOARD");
}

View File

@ -34,28 +34,36 @@ MEMORY_WriteHandler WriteHandlerTable[MAX_PAGES];
#define MAX_PAGE_LIMIT PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024) #define MAX_PAGE_LIMIT PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024)
void MEM_BlockRead(PhysPt off,void * data,Bitu size) { void MEM_BlockRead(PhysPt off,void * data,Bitu size) {
Bitu c;
Bit8u * idata=(Bit8u *)data; Bit8u * idata=(Bit8u *)data;
for (c=1;c<=(size>>2);c++) { while (size>0) {
writed(idata,mem_readd(off)); Bitu page=off >> PAGE_SHIFT;
idata+=4;off+=4; Bitu start=off & (PAGE_SIZE-1);
Bitu tocopy=PAGE_SIZE-start;
if (tocopy>size) tocopy=size;
size-=tocopy;
if (ReadHostTable[page]) {
memcpy(idata,ReadHostTable[page]+off,tocopy);
idata+=tocopy;off+=tocopy;
} else {
for (;tocopy>0;tocopy--) *idata++=ReadHandlerTable[page](off++);
} }
for (c=1;c<=(size&3);c++) {
writeb(idata,mem_readb(off));
idata+=1;off+=1;
} }
} }
void MEM_BlockWrite(PhysPt off,void * data,Bitu size) { void MEM_BlockWrite(PhysPt off,void * data,Bitu size) {
Bitu c;
Bit8u * idata=(Bit8u *)data; Bit8u * idata=(Bit8u *)data;
for (c=1;c<=(size>>2);c++) { while (size>0) {
mem_writed(off,readd(idata)); Bitu page=off >> PAGE_SHIFT;
idata+=4;off+=4; Bitu start=off & (PAGE_SIZE-1);
Bitu tocopy=PAGE_SIZE-start;
if (tocopy>size) tocopy=size;
size-=tocopy;
if (WriteHostTable[page]) {
memcpy(WriteHostTable[page]+off,idata,tocopy);
idata+=tocopy;off+=tocopy;
} else {
for (;tocopy>0;tocopy--) WriteHandlerTable[page](off++,*idata++);
} }
for (c=1;c<=(size&3);c++) {
mem_writeb(off,readb(idata));
idata+=1;off+=1;
} }
} }
@ -222,7 +230,7 @@ Bit32u mem_readd(PhysPt pt){
void MEM_Init(void) { void MEM_Init(Section * sect) {
/* Init all tables */ /* Init all tables */
Bitu i; Bitu i;
i=MAX_PAGES; i=MAX_PAGES;
@ -235,8 +243,9 @@ void MEM_Init(void) {
/* Allocate the first mb of memory */ /* Allocate the first mb of memory */
memory=(Bit8u *)malloc(1024*1024); memory=(Bit8u *)malloc(1024*1024);
if (!memory) { if (!memory) {
E_Exit("Can't allocate memory for memory"); throw("Can't allocate memory for memory");
} }
memset(memory,0xcd,1024*1024);
/* Setup tables for first mb */ /* Setup tables for first mb */
MEM_SetupMapping(0,PAGE_COUNT(1024*1024),memory); MEM_SetupMapping(0,PAGE_COUNT(1024*1024),memory);
/* Setup tables for HMA Area */ /* Setup tables for HMA Area */

View File

@ -22,7 +22,7 @@
*/ */
#include <string.h> #include <string.h>
#include <SDL/SDL.h> #include <SDL.h>
#include "dosbox.h" #include "dosbox.h"
#include "mixer.h" #include "mixer.h"
#include "timer.h" #include "timer.h"
@ -35,35 +35,69 @@
#define MIXER_REMAIN ((1<<MIXER_SHIFT)-1) #define MIXER_REMAIN ((1<<MIXER_SHIFT)-1)
#define MIXER_FREQ 22050 #define MIXER_FREQ 22050
#define MIXER_CLIP(SAMP) (SAMP>MAX_AUDIO) ? (Bit16s)MAX_AUDIO : (SAMP<MIN_AUDIO) ? (Bit16s)MIN_AUDIO : ((Bit16s)SAMP)
#define MAKE_m8(CHAN) ((Bit8s)(mix_temp.m8[pos][CHAN]^0x80) << 8)
#define MAKE_s8(CHAN) ((Bit8s)(mix_temp.s8[pos][CHAN]^0x80) << 8)
#define MAKE_m16(CHAN) mix_temp.m16[pos][CHAN]
#define MAKE_s16(CHAN) mix_temp.s16[pos][CHAN]
#define MIX_NORMAL(TYPE, LCHAN,RCHAN) { \
(chan->handler)(((Bit8u*)&mix_temp)+sizeof(mix_temp.TYPE[0]),sample_toread); \
Bitu sample_index=(1 << MIXER_SHIFT) - chan->sample_left; \
Bit32s newsample; \
for (Bitu mix=0;mix<samples;mix++) { \
Bitu pos=sample_index >> MIXER_SHIFT;sample_index+=chan->sample_add; \
newsample=mix_buftemp[mix][0]+MAKE_##TYPE( LCHAN ); \
mix_buftemp[mix][0]=MIXER_CLIP(newsample); \
newsample=mix_buftemp[mix][1]+MAKE_##TYPE( RCHAN ); \
mix_buftemp[mix][1]=MIXER_CLIP(newsample); \
} \
chan->remain.TYPE[LCHAN]=mix_temp.TYPE[sample_index>>MIXER_SHIFT][LCHAN]; \
if (RCHAN) chan->remain.TYPE[RCHAN]=mix_temp.TYPE[sample_index>>MIXER_SHIFT][RCHAN];\
chan->sample_left=sample_total-sample_index; \
break; \
}
union Sample {
Bit16s m16[1];
Bit16s s16[2];
Bit8u m8[1];
Bit8u s8[2];
Bit32u full;
};
struct MIXER_Channel { struct MIXER_Channel {
Bit8u volume; Bit8u volume;
Bit8u mode; Bit8u mode;
Bit32u freq; Bitu freq;
char * name; char * name;
MIXER_MixHandler handler; MIXER_MixHandler handler;
Bit32u sample_add; Bitu sample_add;
Bit32u sample_remain; Bitu sample_left;
Bit16s sample_data[2]; Sample remain;
bool playing; bool playing;
MIXER_Channel * next; MIXER_Channel * next;
}; };
static MIXER_Channel * first_channel; static MIXER_Channel * first_channel;
static union { static union {
Bit16s temp_m16[MIXER_BUFSIZE][1]; Bit16s m16[MIXER_BUFSIZE][1];
Bit16s temp_s16[MIXER_BUFSIZE][2]; Bit16s s16[MIXER_BUFSIZE][2];
Bit8u temp_m8[MIXER_BUFSIZE][1]; Bit8u m8[MIXER_BUFSIZE][1];
Bit8u temp_s8[MIXER_BUFSIZE][2]; Bit8u s8[MIXER_BUFSIZE][2];
}; Bit32u full[MIXER_BUFSIZE];
} mix_temp;
static Bit16s mix_bufout[MIXER_BUFSIZE][2]; static Bit16s mix_bufout[MIXER_BUFSIZE][2];
static Bit16s mix_buftemp[MIXER_BUFSIZE][2]; static Bit16s mix_buftemp[MIXER_BUFSIZE][2];
static Bit32s mix_bufextra; static Bit32s mix_bufextra;
static Bit32u mix_writepos; static Bitu mix_writepos;
static Bit32u mix_readpos; static Bitu mix_readpos;
static Bit32u mix_ticks; static Bitu mix_ticks;
static Bit32u mix_add; static Bitu mix_add;
static Bit32u mix_remain; static Bitu mix_remain;
MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * name) { MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * name) {
//TODO Find a free channel //TODO Find a free channel
@ -75,6 +109,7 @@ MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * nam
chan->handler=handler; chan->handler=handler;
chan->name=name; chan->name=name;
chan->sample_add=(freq<<MIXER_SHIFT)/MIXER_FREQ; chan->sample_add=(freq<<MIXER_SHIFT)/MIXER_FREQ;
chan->sample_left=0;
chan->next=first_channel; chan->next=first_channel;
first_channel=chan; first_channel=chan;
return chan; return chan;
@ -112,69 +147,28 @@ static void MIXER_MixData(Bit32u samples) {
MIXER_Channel * chan=first_channel; MIXER_Channel * chan=first_channel;
while (chan) { while (chan) {
if (chan->playing) { if (chan->playing) {
Bit32u chan_samples=samples*chan->sample_add; /* This should always allocate 1 extra sample */
Bit32u real_samples=chan_samples>>MIXER_SHIFT; Bitu sample_total=(samples*chan->sample_add)-chan->sample_left;
if (chan_samples & MIXER_REMAIN) real_samples++; Bitu sample_toread=sample_total >> MIXER_SHIFT;
(chan->handler)((Bit8u*)&temp_m8,real_samples); if (sample_total & MIXER_REMAIN) sample_toread++;
sample_total=(sample_toread+1)<<MIXER_SHIFT;
mix_temp.full[0]=chan->remain.full;
switch (chan->mode) { switch (chan->mode) {
case MIXER_8MONO: case MIXER_8MONO:
/* Mix a 8 bit mono stream into the final 16 bit stereo output stream */ MIX_NORMAL(m8,0,0);
{ break;
/* Mix the data with output buffer */ case MIXER_8STEREO:
Bit32s newsample;Bit32u sample_read=0;Bit32u sample_add=chan->sample_add; MIX_NORMAL(m8,0,1);
for (Bit32u mix=0;mix<samples;mix++) {
Bit32u pos=sample_read >> MIXER_SHIFT;
sample_read+=sample_add;
newsample=mix_buftemp[mix][0]+((Bit8s)(temp_m8[pos][0]^0x80) << 8);
if (newsample>MAX_AUDIO) mix_buftemp[mix][0]=MAX_AUDIO;
else if (newsample<MIN_AUDIO) mix_buftemp[mix][0]=MIN_AUDIO;
else mix_buftemp[mix][0]=(Bit16s)newsample;
newsample=mix_buftemp[mix][1]+((Bit8s)(temp_m8[pos][0]^0x80) << 8);
if (newsample>MAX_AUDIO) mix_buftemp[mix][1]=MAX_AUDIO;
else if (newsample<MIN_AUDIO) mix_buftemp[mix][1]=MIN_AUDIO;
else mix_buftemp[mix][1]=(Bit16s)newsample;
}
break; break;
}
case MIXER_16MONO: case MIXER_16MONO:
/* Mix a 16 bit mono stream into the final 16 bit stereo output stream */ MIX_NORMAL(m16,0,0);
{
Bit32s newsample;Bit32u sample_read=0;Bit32u sample_add=chan->sample_add;
for (Bit32u mix=0;mix<samples;mix++) {
Bit32u pos=sample_read >> MIXER_SHIFT;
sample_read+=sample_add;
newsample=mix_buftemp[mix][0]+temp_m16[pos][0];
if (newsample>MAX_AUDIO) mix_buftemp[mix][0]=MAX_AUDIO;
else if (newsample<MIN_AUDIO) mix_buftemp[mix][0]=MIN_AUDIO;
else mix_buftemp[mix][0]=(Bit16s)newsample;
newsample=mix_buftemp[mix][1]+temp_m16[pos][0];
if (newsample>MAX_AUDIO) mix_buftemp[mix][1]=MAX_AUDIO;
else if (newsample<MIN_AUDIO) mix_buftemp[mix][1]=MIN_AUDIO;
else mix_buftemp[mix][1]=(Bit16s)newsample;
}
break; break;
}
case MIXER_16STEREO: case MIXER_16STEREO:
/* Mix a 16 bit stereo stream into the final 16 bit stereo output stream */ MIX_NORMAL(s16,0,1);
{
Bit32s newsample;Bit32u sample_read=0;Bit32u sample_add=chan->sample_add;
for (Bit32u mix=0;mix<samples;mix++) {
Bit32u pos=sample_read >> MIXER_SHIFT;
sample_read+=sample_add;
newsample=mix_buftemp[mix][0]+temp_s16[pos][0];
if (newsample>MAX_AUDIO) mix_buftemp[mix][0]=MAX_AUDIO;
else if (newsample<MIN_AUDIO) mix_buftemp[mix][0]=MIN_AUDIO;
else mix_buftemp[mix][0]=(Bit16s)newsample;
newsample=mix_buftemp[mix][1]+temp_s16[pos][1];
if (newsample>MAX_AUDIO) mix_buftemp[mix][1]=MAX_AUDIO;
else if (newsample<MIN_AUDIO) mix_buftemp[mix][1]=MIN_AUDIO;
else mix_buftemp[mix][1]=(Bit16s)newsample;
}
break; break;
}
default: default:
E_Exit("MIXER:Illegal sound mode %2X",chan->mode); E_Exit("MIXER:Illegal sound mode %2X",chan->mode);
break;
} }
} }
chan=chan->next; chan=chan->next;
@ -210,7 +204,7 @@ static void MIXER_CallBack(void * userdata, Uint8 *stream, int len) {
/* Copy data from buf_out to the stream */ /* Copy data from buf_out to the stream */
Bit32u remain=MIXER_BUFSIZE-mix_readpos; Bit32u remain=MIXER_BUFSIZE-mix_readpos;
if (remain>=len/MIXER_SSIZE) { if (remain>=(Bit32u)len/MIXER_SSIZE) {
memcpy((void *)stream,(void *)&mix_bufout[mix_readpos][0],len); memcpy((void *)stream,(void *)&mix_bufout[mix_readpos][0],len);
} else { } else {
memcpy((void *)stream,(void *)&mix_bufout[mix_readpos][0],remain*MIXER_SSIZE); memcpy((void *)stream,(void *)&mix_bufout[mix_readpos][0],remain*MIXER_SSIZE);
@ -223,7 +217,8 @@ static void MIXER_CallBack(void * userdata, Uint8 *stream, int len) {
void MIXER_Init(void) { void MIXER_Init(Section* sec) {
MSG_Add("MIXER_CONFIGFILE_HELP","Nothing to setup yet!\n");
/* Initialize the internal stuff */ /* Initialize the internal stuff */
first_channel=0; first_channel=0;
mix_ticks=GetTicks(); mix_ticks=GetTicks();

View File

@ -16,16 +16,17 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <dosbox.h>
#include <mixer.h>
#include <math.h> #include <math.h>
#include "dosbox.h"
#include "mixer.h"
#include "timer.h"
#ifndef PI #ifndef PI
#define PI 3.14159265358979323846 #define PI 3.14159265358979323846
#endif #endif
#define SPKR_BUF 4096
#define SPKR_RATE 22050 #define SPKR_RATE 22050
#define SPKR_VOLUME 5000 #define SPKR_VOLUME 5000
@ -41,15 +42,26 @@ struct Speaker {
Bit16s volume; Bit16s volume;
MIXER_Channel * chan; MIXER_Channel * chan;
bool enabled; bool enabled;
bool realsound;
Bit16u buffer[SPKR_BUF];
Bitu buf_pos;
}; };
static Speaker spkr; static Speaker spkr;
void PCSPEAKER_SetFreq(Bit32u freq) { void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode) {
spkr.freq_add=(Bit32u)(FREQ_MAX/((float)SPKR_RATE/(float)freq)); switch (mode) {
spkr.freq_pos=0; case 0:
if (cntr>72) cntr=72;
spkr.realsound=true;
if (spkr.buf_pos<SPKR_BUF) spkr.buffer[spkr.buf_pos++]=(cntr-36)*600;
break;
case 3:
spkr.freq_add=(Bit32u)(FREQ_MAX/((float)SPKR_RATE/(PIT_TICK_RATE/(float)cntr)));
break;
}
} }
void PCSPEAKER_Enable(bool enable) { void PCSPEAKER_Enable(bool enable) {
@ -58,8 +70,19 @@ void PCSPEAKER_Enable(bool enable) {
} }
static void PCSPEAKER_CallBack(Bit8u * stream,Bit32u len) { static void PCSPEAKER_CallBack(Bit8u * stream,Bit32u len) {
/* Generate the speaker wave, TODO Improve :) */ if (spkr.realsound) {
for (Bit32u c=0;c<len;c++) { /* Generate the "RealSound" */
Bitu buf_add=(spkr.buf_pos<<16)/len;
Bitu buf_pos=0;
spkr.buf_pos=0;spkr.realsound=0;
while (len-->0) {
*(Bit16s*)(stream)=spkr.buffer[buf_pos >> 16];
buf_pos+=buf_add;
stream+=2;
}
} else {
/* Generate a square wave */
while (len-->0) {
spkr.freq_pos+=spkr.freq_add; spkr.freq_pos+=spkr.freq_add;
if (spkr.freq_pos>=FREQ_MAX) spkr.freq_pos-=FREQ_MAX; if (spkr.freq_pos>=FREQ_MAX) spkr.freq_pos-=FREQ_MAX;
if (spkr.freq_pos>=FREQ_HALF) { if (spkr.freq_pos>=FREQ_HALF) {
@ -67,22 +90,18 @@ static void PCSPEAKER_CallBack(Bit8u * stream,Bit32u len) {
} else { } else {
*(Bit16s*)(stream)=-spkr.volume; *(Bit16s*)(stream)=-spkr.volume;
} }
/*
if (spkr.freq_pos>=FREQ_HALF) {
spkr.freq_pos-=FREQ_HALF;
spkr.volume=-spkr.volume;
};
*(Bit16s*)(stream)=spkr.volume;
*/
stream+=2; stream+=2;
} }
}
} }
void PCSPEAKER_Init(void) { void PCSPEAKER_Init(Section* sec) {
MSG_Add("SPEAKER_CONFIGFILE_HELP","pcspeaker related options.\n");
spkr.chan=MIXER_AddChannel(&PCSPEAKER_CallBack,SPKR_RATE,"PC-SPEAKER"); spkr.chan=MIXER_AddChannel(&PCSPEAKER_CallBack,SPKR_RATE,"PC-SPEAKER");
MIXER_Enable(spkr.chan,false); MIXER_Enable(spkr.chan,false);
MIXER_SetMode(spkr.chan,MIXER_16MONO); MIXER_SetMode(spkr.chan,MIXER_16MONO);
spkr.volume=SPKR_VOLUME; spkr.volume=SPKR_VOLUME;
spkr.enabled=false; spkr.enabled=false;
spkr.realsound=false;
spkr.buf_pos=0;
} }

View File

@ -31,7 +31,9 @@ struct IRQ_Block {
PIC_EOIHandler * handler; PIC_EOIHandler * handler;
}; };
Bit32u PIC_IRQCheck; Bitu PIC_IRQCheck;
Bitu PIC_IRQActive;
bool PIC_IRQAgain;
static IRQ_Block irqs[16]; static IRQ_Block irqs[16];
static Bit8u pic0_icws=0; static Bit8u pic0_icws=0;
@ -45,7 +47,6 @@ static bool pic1_request_iisr=0;
//Pic 0 command port //Pic 0 command port
static void write_p20(Bit32u port,Bit8u val) { static void write_p20(Bit32u port,Bit8u val) {
Bit32u i;
switch (val) { switch (val) {
case 0x0A: /* select read interrupt request register */ case 0x0A: /* select read interrupt request register */
pic0_request_iisr=false; pic0_request_iisr=false;
@ -56,7 +57,6 @@ static void write_p20(Bit32u port,Bit8u val) {
case 0x10: /* ICW1 */ case 0x10: /* ICW1 */
pic0_icws=2; pic0_icws=2;
pic0_icw_state=1; pic0_icw_state=1;
break; break;
case 0x11: /* ICW1 + need for ICW4 */ case 0x11: /* ICW1 + need for ICW4 */
pic0_icws=3; pic0_icws=3;
@ -64,13 +64,11 @@ static void write_p20(Bit32u port,Bit8u val) {
break; break;
case 0x20: /* end of interrupt command */ case 0x20: /* end of interrupt command */
/* clear highest current in service bit */ /* clear highest current in service bit */
for (i=0;i<=7;i++) { if (PIC_IRQActive<8) {
if (irqs[i].inservice) { irqs[PIC_IRQActive].inservice=false;
irqs[i].inservice=false; if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler();
if (irqs[i].handler!=0) irqs[i].handler(); PIC_IRQActive=PIC_NOIRQ;
break; }
};
};
break; break;
case 0x60: /* specific EOI 0 */ case 0x60: /* specific EOI 0 */
case 0x61: /* specific EOI 1 */ case 0x61: /* specific EOI 1 */
@ -80,10 +78,11 @@ static void write_p20(Bit32u port,Bit8u val) {
case 0x65: /* specific EOI 5 */ case 0x65: /* specific EOI 5 */
case 0x66: /* specific EOI 6 */ case 0x66: /* specific EOI 6 */
case 0x67: /* specific EOI 7 */ case 0x67: /* specific EOI 7 */
if (irqs[val-0x60].inservice) { if (PIC_IRQActive==(val-0x60U)) {
irqs[val-0x60].inservice=false; irqs[PIC_IRQActive].inservice=false;
if (irqs[val-0x60].handler!=0) irqs[val-0x60].handler(); if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler();
}; PIC_IRQActive=PIC_NOIRQ;
}
break; break;
// IRQ lowest priority commands // IRQ lowest priority commands
case 0xC0: // 0 7 6 5 4 3 2 1 case 0xC0: // 0 7 6 5 4 3 2 1
@ -176,13 +175,11 @@ static void write_pa0(Bit32u port,Bit8u val) {
break; break;
case 0x20: /* end of interrupt command */ case 0x20: /* end of interrupt command */
/* clear highest current in service bit */ /* clear highest current in service bit */
for (i=8;i<=15;i++) { if (PIC_IRQActive>7 && PIC_IRQActive <16) {
if (irqs[i].inservice) { irqs[PIC_IRQActive].inservice=false;
irqs[i].inservice=false; if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler();
if (irqs[i].handler!=0) irqs[i].handler(); PIC_IRQActive=PIC_NOIRQ;
break; }
};
};
break; break;
case 0x60: /* specific EOI 0 */ case 0x60: /* specific EOI 0 */
case 0x61: /* specific EOI 1 */ case 0x61: /* specific EOI 1 */
@ -192,9 +189,10 @@ static void write_pa0(Bit32u port,Bit8u val) {
case 0x65: /* specific EOI 5 */ case 0x65: /* specific EOI 5 */
case 0x66: /* specific EOI 6 */ case 0x66: /* specific EOI 6 */
case 0x67: /* specific EOI 7 */ case 0x67: /* specific EOI 7 */
if (irqs[val-0x60+8].inservice) { if (PIC_IRQActive==(8+val-0x60U)) {
irqs[val-0x60+8].inservice=false; irqs[PIC_IRQActive].inservice=false;
if (irqs[val-0x60+8].handler!=0) irqs[val-0x60+8].handler(); if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler();
PIC_IRQActive=PIC_NOIRQ;
}; };
break; break;
// IRQ lowest priority commands // IRQ lowest priority commands
@ -220,6 +218,7 @@ static void write_pa1(Bit32u port,Bit8u val) {
case 0: /* mask register */ case 0: /* mask register */
for (i=0;i<=7;i++) { for (i=0;i<=7;i++) {
irqs[i+8].masked=(val&1 <<i)>0; irqs[i+8].masked=(val&1 <<i)>0;
if (!irqs[8].masked) LOG_DEBUG("Someone unmasked RTC irq");
}; };
break; break;
case 1: /* icw2 */ case 1: /* icw2 */
@ -245,7 +244,7 @@ static Bit8u read_pa0(Bit32u port) {
if (irqs[i+8].active) ret|=b; if (irqs[i+8].active) ret|=b;
b <<= 1; b <<= 1;
} }
}; }
return ret; return ret;
} }
@ -292,55 +291,31 @@ void PIC_DeActivateIRQ(Bit32u irq) {
} }
} }
bool PIC_IRQActive(Bit32u irq) {
if (irq<16) {
return irqs[irq].active;
}
return true;
}
#define PIC_MAXQUEUE 16
static PIC_Function * pic_queue[PIC_MAXQUEUE];
static Bit32u pic_queuesize;
void PIC_QueueFunction(PIC_Function * function) {
if (pic_queuesize<PIC_MAXQUEUE) {
pic_queue[pic_queuesize]=function;
pic_queuesize++;
} else {
E_Exit("PIC Queue OverFlow");
}
}
//TODO check for IRQ 2 being masked before checking 8-15 but then again do i need so many irqs
void PIC_runIRQs(void) { void PIC_runIRQs(void) {
Bit32u i; Bit32u i;
if (!flags.intf) goto noirqs; if (!flags.intf) return;
if (!PIC_IRQCheck) goto noirqs; if (PIC_IRQActive!=PIC_NOIRQ) return;
if (!PIC_IRQCheck) return;
for (i=0;i<=15;i++) { for (i=0;i<=15;i++) {
if (i!=2) { if (i!=2) {
if (!irqs[i].masked && irqs[i].active /* && !irqs[i].inservice */) { if (!irqs[i].masked && irqs[i].active) {
irqs[i].inservice=true; irqs[i].inservice=true;
irqs[i].active=false; irqs[i].active=false;
PIC_IRQCheck&=~(1 << i); PIC_IRQCheck&=~(1 << i);
Interrupt(irqs[i].vector); Interrupt(irqs[i].vector);
break; PIC_IRQActive=i;
}; PIC_IRQAgain=true;
}; return;
};
noirqs:
/* This also runs special hardware functions that can queue themselves here */
for (;pic_queuesize>0;) {
(*pic_queue[--pic_queuesize])();
} }
}; }
}
}
void PIC_Init(void) { void PIC_Init(Section* sec) {
/* Setup pic0 and pic1 with initial values like DOS has normally */ /* Setup pic0 and pic1 with initial values like DOS has normally */
PIC_IRQCheck=0; PIC_IRQCheck=0;
PIC_IRQActive=PIC_NOIRQ;
Bit8u i; Bit8u i;
for (i=0;i<=7;i++) { for (i=0;i<=7;i++) {
irqs[i].active=false; irqs[i].active=false;
@ -351,11 +326,10 @@ void PIC_Init(void) {
irqs[i+8].inservice=false; irqs[i+8].inservice=false;
irqs[i].vector=0x8+i; irqs[i].vector=0x8+i;
irqs[i+8].vector=0x70+i; irqs[i+8].vector=0x70+i;
}; }
irqs[0].masked=false; /* Enable system timer */ irqs[0].masked=false; /* Enable system timer */
irqs[1].masked=false; /* Enable Keyboard IRQ */ irqs[1].masked=false; /* Enable Keyboard IRQ */
irqs[2].masked=false; /* Enable 2nd PIC Although i can't care if this is masked */ irqs[12].masked=false; /* Enable Mouse IRQ */
irqs[12].masked=false;
IO_RegisterReadHandler(0x20,read_p20,"Master PIC Command"); IO_RegisterReadHandler(0x20,read_p20,"Master PIC Command");
IO_RegisterReadHandler(0x21,read_p21,"Master PIC Data"); IO_RegisterReadHandler(0x21,read_p21,"Master PIC Data");
IO_RegisterWriteHandler(0x20,write_p20,"Master PIC Command"); IO_RegisterWriteHandler(0x20,write_p20,"Master PIC Command");
@ -364,6 +338,6 @@ void PIC_Init(void) {
IO_RegisterReadHandler(0xa1,read_pa1,"Slave PIC Data"); IO_RegisterReadHandler(0xa1,read_pa1,"Slave PIC Data");
IO_RegisterWriteHandler(0xa0,write_pa0,"Slave PIC Command"); IO_RegisterWriteHandler(0xa0,write_pa0,"Slave PIC Command");
IO_RegisterWriteHandler(0xa1,write_pa1,"Slave PIC Data"); IO_RegisterWriteHandler(0xa1,write_pa1,"Slave PIC Data");
}; }

View File

@ -23,6 +23,8 @@
#include "dma.h" #include "dma.h"
#include "pic.h" #include "pic.h"
#include "hardware.h" #include "hardware.h"
#include "setup.h"
#include "programs.h"
#define SB_BASE 0x220 #define SB_BASE 0x220
#define SB_IRQ 5 #define SB_IRQ 5
@ -44,7 +46,7 @@
enum {DSP_S_RESET,DSP_S_NORMAL,DSP_S_HIGHSPEED}; enum {DSP_S_RESET,DSP_S_NORMAL,DSP_S_HIGHSPEED};
enum { enum {
MODE_NONE,MODE_DAC, MODE_NONE,MODE_DAC,MODE_SILENCE,
MODE_PCM_8S,MODE_PCM_8A, MODE_PCM_8S,MODE_PCM_8A,
MODE_ADPCM_4S MODE_ADPCM_4S
}; };
@ -90,7 +92,6 @@ struct SB_INFO {
Bit8u irq; Bit8u irq;
Bit8u dma; Bit8u dma;
bool enabled; bool enabled;
HWBlock hwblock;
MIXER_Channel * chan; MIXER_Channel * chan;
}; };
@ -151,15 +152,8 @@ static INLINE void DSP_FlushData(void) {
sb.data_out_pos=0; sb.data_out_pos=0;
} }
static void DSP_SetSampleRate(Bit32u rate) {
/* This directly changes the mixer */
}
static void DSP_StopDMA(void) { static void DSP_StopDMA(void) {
sb.mode=MODE_NONE; sb.mode=MODE_NONE;
// MIXER_SetMode(sb.chan,MIXER_8MONO);
// MIXER_SetFreq(sb.chan,22050);
} }
static void DSP_StartDMATranfser(Bit8u mode) { static void DSP_StartDMATranfser(Bit8u mode) {
@ -168,6 +162,10 @@ static void DSP_StartDMATranfser(Bit8u mode) {
sb.freq=(1000000 / (256 - sb.time_constant)); sb.freq=(1000000 / (256 - sb.time_constant));
}; };
switch (mode) { switch (mode) {
case MODE_SILENCE:
MIXER_SetFreq(sb.chan,sb.freq);
SB_DEBUG("DSP:PCM 8 bit single cycle rate %d size %d",sb.freq,sb.samples_total);
break;
case MODE_PCM_8S: case MODE_PCM_8S:
MIXER_SetFreq(sb.chan,sb.freq); MIXER_SetFreq(sb.chan,sb.freq);
SB_DEBUG("DSP:PCM 8 bit single cycle rate %d size %d",sb.freq,sb.samples_total); SB_DEBUG("DSP:PCM 8 bit single cycle rate %d size %d",sb.freq,sb.samples_total);
@ -175,13 +173,11 @@ static void DSP_StartDMATranfser(Bit8u mode) {
case MODE_PCM_8A: case MODE_PCM_8A:
MIXER_SetFreq(sb.chan,sb.freq); MIXER_SetFreq(sb.chan,sb.freq);
SB_DEBUG("DSP:PCM 8 bit auto init rate %d size %d",sb.freq,sb.samples_total); SB_DEBUG("DSP:PCM 8 bit auto init rate %d size %d",sb.freq,sb.samples_total);
break; break;
case MODE_ADPCM_4S: case MODE_ADPCM_4S:
MIXER_SetFreq(sb.chan,sb.freq); MIXER_SetFreq(sb.chan,sb.freq);
SB_DEBUG("DSP:ADPCM 4 bit single cycle rate %d size %X",sb.freq,sb.samples_total); SB_DEBUG("DSP:ADPCM 4 bit single cycle rate %d size %X",sb.freq,sb.samples_total);
break; break;
default: default:
LOG_ERROR("DSP:Illegal transfer mode %d",mode); LOG_ERROR("DSP:Illegal transfer mode %d",mode);
return; return;
@ -206,6 +202,9 @@ static void DSP_Reset(void) {
sb.mode=MODE_NONE; sb.mode=MODE_NONE;
sb.cmd_len=0; sb.cmd_len=0;
sb.cmd_in_pos=0; sb.cmd_in_pos=0;
sb.samples_left=0;
sb.samples_total=0;
sb.freq=22050;
sb.use_time_constant=false; sb.use_time_constant=false;
sb.dac.used=0; sb.dac.used=0;
sb.dac.last=0x80; sb.dac.last=0x80;
@ -260,6 +259,10 @@ static void DSP_DoCommand(void) {
sb.samples_total=1+sb.cmd_in[0]+(sb.cmd_in[1] << 8); sb.samples_total=1+sb.cmd_in[0]+(sb.cmd_in[1] << 8);
DSP_StartDMATranfser(MODE_ADPCM_4S); DSP_StartDMATranfser(MODE_ADPCM_4S);
break; break;
case 0x80: /* Silence DAC */
sb.samples_total=1+sb.cmd_in[0]+(sb.cmd_in[1] << 8);
DSP_StartDMATranfser(MODE_SILENCE);
break;
case 0xd0: /* Halt 8-bit DMA */ case 0xd0: /* Halt 8-bit DMA */
DSP_HaltDMA(); DSP_HaltDMA();
break; break;
@ -289,7 +292,6 @@ static void DSP_DoCommand(void) {
*/ */
//TODO Ofcourse :) //TODO Ofcourse :)
} }
break; break;
case 0xe3: /* DSP Copyright */ case 0xe3: /* DSP Copyright */
{ {
@ -444,6 +446,16 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) {
} }
} }
break; break;
case MODE_SILENCE:
memset(stream,0x80,len);
if (sb.samples_left>len) {
sb.samples_left-=len;
} else {
sb.samples_left=0;
sb.mode=MODE_NONE;
PIC_ActivateIRQ(sb.irq);
}
break;
case MODE_PCM_8A: case MODE_PCM_8A:
{ {
Bit16u read=DMA_8_Read(sb.dma,stream,(Bit16u)len); Bit16u read=DMA_8_Read(sb.dma,stream,(Bit16u)len);
@ -524,8 +536,6 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) {
static bool SB_enabled;
static void SB_Enable(bool enable) { static void SB_Enable(bool enable) {
Bitu i; Bitu i;
if (enable) { if (enable) {
@ -542,90 +552,22 @@ static void SB_Enable(bool enable) {
for (i=sb.base+4;i<sb.base+0xf;i++){ for (i=sb.base+4;i<sb.base+0xf;i++){
IO_FreeReadHandler(i); IO_FreeReadHandler(i);
IO_FreeWriteHandler(i); IO_FreeWriteHandler(i);
}; }
} }
} }
void SBLASTER_Init(Section* sec) {
static void SB_InputHandler(char * line) { MSG_Add("SBLASTER_CONFIGFILE_HELP","Sound Blaster related options.\n");
bool s_off,s_on,s_base,s_irq,s_dma; Section_prop * section=static_cast<Section_prop *>(sec);
Bits n_base,n_irq,n_dma; if(!section->Get_bool("enabled")) return;
s_off=ScanCMDBool(line,"OFF");
s_on=ScanCMDBool(line,"ON");
s_base=ScanCMDHex(line,"BASE",&n_base);
s_irq=ScanCMDHex(line,"IRQ",&n_irq);
s_dma=ScanCMDHex(line,"DMA",&n_dma);
char * rem=ScanCMDRemain(line);
if (rem) {
sprintf(line,"Illegal Switch");
return;
}
if (s_on && s_off) {
sprintf(line,"Can't use /ON and /OFF at the same time");
return;
}
bool was_enabled=sb.enabled;
if (sb.enabled) SB_Enable(false);
if (s_base) {
sb.base=n_base;
}
if (s_irq) {
sb.irq=n_irq;
}
if (s_dma) {
sb.dma=n_dma;
}
if (s_on) {
SB_Enable(true);
}
if (s_off) {
SB_Enable(false);
sprintf(line,"Sound Blaster has been disabled");
return;
}
if (was_enabled) SB_Enable(true);
sprintf(line,"Sound Blaster enabled with IO %X IRQ %X DMA %X",sb.base,sb.irq,sb.dma);
return;
}
static void SB_OutputHandler (char * towrite) {
if(sb.enabled) {
sprintf(towrite,"IO %X IRQ %X DMA %X",sb.base,sb.irq,sb.dma);
} else {
sprintf(towrite,"Disabled");
}
};
void SBLASTER_Init(void) {
sb.chan=MIXER_AddChannel(&SBLASTER_CallBack,22050,"SBLASTER"); sb.chan=MIXER_AddChannel(&SBLASTER_CallBack,22050,"SBLASTER");
MIXER_Enable(sb.chan,false); MIXER_Enable(sb.chan,false);
sb.state=DSP_S_NORMAL; sb.state=DSP_S_NORMAL;
/* Setup the hardware handler part */
sb.base=SB_BASE; sb.base=section->Get_hex("base");
sb.irq=SB_IRQ; sb.irq=section->Get_int("irq");
sb.dma=SB_DMA; sb.dma=section->Get_int("dma");
SB_Enable(true); SB_Enable(true);
sb.hwblock.dev_name="SB";
sb.hwblock.full_name="Sound Blaster 1.5";
sb.hwblock.next=0;
sb.hwblock.help=
"/ON Enables SB\n"
"/OFF Disables SB\n"
"/BASE XXX Set Base Addres 200-260\n"
"/IRQ X Set IRQ 1-9\n"
"/DMA X Set 8-Bit DMA Channel 0-3\n";
sb.hwblock.get_input=SB_InputHandler;
sb.hwblock.show_status=SB_OutputHandler;
HW_Register(&sb.hwblock);
SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d T3",sb.base,sb.irq,sb.dma); SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d T3",sb.base,sb.irq,sb.dma);
} }

View File

@ -25,6 +25,7 @@
#include "inout.h" #include "inout.h"
#include "mixer.h" #include "mixer.h"
#include "mem.h" #include "mem.h"
#include "setup.h"
#define TANDY_DIV 111860 #define TANDY_DIV 111860
#define TANDY_RATE 22050 #define TANDY_RATE 22050
@ -125,7 +126,9 @@ static void TANDYSOUND_CallBack(Bit8u * stream,Bit32u len) {
} }
}; };
void TANDY_Init(void) { void TANDYSOUND_Init(Section* sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
if(!section->Get_bool("tandy")) return;
IO_RegisterWriteHandler(0xc0,write_pc0,"Tandy Sound"); IO_RegisterWriteHandler(0xc0,write_pc0,"Tandy Sound");
tandy_chan=MIXER_AddChannel(&TANDYSOUND_CallBack,TANDY_RATE,"TANDY"); tandy_chan=MIXER_AddChannel(&TANDYSOUND_CallBack,TANDY_RATE,"TANDY");
MIXER_Enable(tandy_chan,false); MIXER_Enable(tandy_chan,false);

View File

@ -42,12 +42,22 @@ struct PIT_Block {
Bit32u last_ticks; Bit32u last_ticks;
}; };
bool TimerAgain;
Bit32u LastTicks;
static PIT_Block pit[3]; static PIT_Block pit[3];
static Bit32u pit_ticks; /* The amount of pit ticks one host tick is bit shifted */ static Bit32u pit_ticks; /* The amount of pit ticks one host tick is bit shifted */
static Bit32u timer_ticks; /* The amount of pit ticks bitshifted one timer cycle needs */ static Bit32u timer_ticks; /* The amount of pit ticks bitshifted one timer cycle needs */
static Bit32u timer_buildup; /* The amount of pit ticks waiting */ static Bit32u timer_buildup; /* The amount of pit ticks waiting */
#define PIT_TICK_RATE 1193182
#define TIMER_AVERAGE 5
static struct TimerBlock {
float req[TIMER_AVERAGE];
Bitu req_index;
Bitu req_count;
float req_average;
Bitu ticks;
} timer;
#define PIT_SHIFT 9 #define PIT_SHIFT 9
#define MAX_PASSED ((PIT_TICK_RATE/4) << PIT_SHIFT) /* Alow 1/4 second of timer build up */ #define MAX_PASSED ((PIT_TICK_RATE/4) << PIT_SHIFT) /* Alow 1/4 second of timer build up */
@ -55,8 +65,9 @@ static Bit32u timer_buildup; /* The amount of pit ticks waiting */
static void counter_latch(Bitu counter) { static void counter_latch(Bitu counter) {
/* Fill the read_latch of the selected counter with current count */ /* Fill the read_latch of the selected counter with current count */
PIT_Block * p=&pit[counter]; PIT_Block * p=&pit[counter];
//TODO Perhaps make it a bit64u for accuracy :) timer.req_count++;
Bit32u ticks=(((LastTicks - p->last_ticks) * pit_ticks) >> PIT_SHIFT) % p->cntr ; float pos=timer.req_average*timer.req_count;
Bit16u ticks=pos*p->cntr;
switch (p->mode) { switch (p->mode) {
case 2: case 2:
case 3: case 3:
@ -102,7 +113,7 @@ static void write_latch(Bit32u port,Bit8u val) {
LOG_DEBUG("PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode); LOG_DEBUG("PIT 0 Timer at %.3g Hz mode %d",PIT_TICK_RATE/(double)p->cntr,p->mode);
break; break;
case 0x02: /* Timer hooked to PC-Speaker */ case 0x02: /* Timer hooked to PC-Speaker */
PCSPEAKER_SetFreq(PIT_TICK_RATE/p->cntr); PCSPEAKER_SetCounter(p->cntr,p->mode);
break; break;
default: default:
LOG_ERROR("PIT:Illegal timer selected for writing"); LOG_ERROR("PIT:Illegal timer selected for writing");
@ -233,29 +244,30 @@ void TIMER_SetNewMicro(TIMER_Block * block,Bitu micro) {
} }
void TIMER_AddTicks(Bit32u ticks) { void TIMER_AddTicks(Bit32u ticks) {
/* This will run through registered handlers and handle the PIT ticks */ /* Add pit ticks to the counter */
timer_buildup+=ticks*pit_ticks; timer_buildup+=ticks*pit_ticks;
if (timer_buildup>MAX_PASSED) timer_buildup=MAX_PASSED; if (timer_buildup>MAX_PASSED) timer_buildup=MAX_PASSED;
Bitu add_micro=ticks*1000; /* Check if there are timer handlers that need to be called */
Bitu add_micro=timer.ticks*1000;
std::list<Timer *>::iterator i; std::list<Timer *>::iterator i;
for(i=Timers.begin(); i != Timers.end(); ++i) { for(i=Timers.begin(); i != Timers.end(); ++i) {
Timer * timer=(*i); Timer * timers=(*i);
switch (timer->type) { switch (timers->type) {
case T_TICK: case T_TICK:
timer->tick.handler(ticks); if (timer.ticks) timers->tick.handler(timer.ticks);
break; break;
case T_MICRO: case T_MICRO:
timer->micro.count+=add_micro; timers->micro.count+=add_micro;
if (timer->micro.count>=timer->micro.total) { if (timers->micro.count>=timers->micro.total) {
timer->micro.count-=timer->micro.total; timers->micro.count-=timers->micro.total;
timer->micro.handler(); timers->micro.handler();
} }
break; break;
case T_DELAY: case T_DELAY:
/* Also unregister the timer handler from the list */ /* Also unregister the timer handler from the list */
if (LastTicks>timer->delay.end) { if (LastTicks>timers->delay.end) {
std::list<Timer *>::iterator remove; std::list<Timer *>::iterator remove;
timer->delay.handler(); timers->delay.handler();
remove=i++; remove=i++;
Timers.erase(remove); Timers.erase(remove);
} }
@ -265,19 +277,28 @@ void TIMER_AddTicks(Bit32u ticks) {
}; };
}; };
timer.ticks=ticks;
} }
void TIMER_CheckPIT(void) { void TIMER_CheckPIT(void) {
if (timer_buildup>timer_ticks) { if (timer_buildup>timer_ticks) {
timer_buildup-=timer_ticks; timer_buildup-=timer_ticks;
/* Calculate amount of times the time index was requested */
timer.req[timer.req_index]=timer.req_count;
timer.req_index++;if (timer.req_index>=TIMER_AVERAGE) timer.req_index=0;
timer.req_count=0;
Bitu l;float total=0;
for (l=0;l<TIMER_AVERAGE;l++) total+=timer.req[l];
timer.req_average=1/(total/TIMER_AVERAGE);
PIC_ActivateIRQ(0); PIC_ActivateIRQ(0);
return; return;
} }
} }
void TIMER_Init(void) { void TIMER_Init(Section* sect) {
Bitu i;
IO_RegisterWriteHandler(0x40,write_latch,"PIT Timer 0"); IO_RegisterWriteHandler(0x40,write_latch,"PIT Timer 0");
IO_RegisterWriteHandler(0x42,write_latch,"PIT Timer 2"); IO_RegisterWriteHandler(0x42,write_latch,"PIT Timer 2");
IO_RegisterWriteHandler(0x43,write_p43,"PIT Mode Control"); IO_RegisterWriteHandler(0x43,write_p43,"PIT Mode Control");
@ -293,7 +314,8 @@ void TIMER_Init(void) {
pit[0].mode=3; pit[0].mode=3;
timer_ticks=pit[0].cntr << PIT_SHIFT; timer_ticks=pit[0].cntr << PIT_SHIFT;
timer_buildup=0; timer_buildup=0;
// first_timer=0; timer.req_index=0;
for (i=0;i<TIMER_AVERAGE;i++) timer.req[i]=0;
pit_ticks=(PIT_TICK_RATE << PIT_SHIFT)/1000; pit_ticks=(PIT_TICK_RATE << PIT_SHIFT)/1000;
PIC_RegisterIRQ(0,&TIMER_CheckPIT,"PIT 0 Timer"); PIC_RegisterIRQ(0,&TIMER_CheckPIT,"PIT 0 Timer");
} }

View File

@ -146,7 +146,7 @@ void VGA_StartResize(void) {
} }
void VGA_Init() { void VGA_Init(Section* sec) {
vga.draw.resizing=false; vga.draw.resizing=false;
VGA_SetupMemory(); VGA_SetupMemory();
VGA_SetupMisc(); VGA_SetupMisc();

View File

@ -176,8 +176,8 @@ void VGA_DrawTEXT(Bit8u * bitdata,Bitu pitch) {
vga.config.retrace=true; vga.config.retrace=true;
/* Draw a cursor */ /* Draw a cursor */
if ((vga.draw.cursor_col*8)>=vga.draw.width) return; if (((Bitu)vga.draw.cursor_col*8)>=vga.draw.width) return;
if ((vga.draw.cursor_row*16)>=vga.draw.height) return; if (((Bitu)vga.draw.cursor_row*16)>=vga.draw.height) return;
Bit8u * cursor_draw=bitdata+(vga.draw.cursor_row*16+15)*pitch+vga.draw.cursor_col*8; Bit8u * cursor_draw=bitdata+(vga.draw.cursor_row*16+15)*pitch+vga.draw.cursor_col*8;
if (vga.draw.cursor_count>8) { if (vga.draw.cursor_count>8) {
for (Bit8u loop=0;loop<8;loop++) *cursor_draw++=15; for (Bit8u loop=0;loop<8;loop++) *cursor_draw++=15;

View File

@ -22,7 +22,7 @@
#include "callback.h" #include "callback.h"
#include "inout.h" #include "inout.h"
#include "mem.h" #include "mem.h"
#include "timer.h"
static Bitu call_int1a,call_int11,call_int8,call_int17,call_int12,call_int15,call_int1c; static Bitu call_int1a,call_int11,call_int8,call_int17,call_int12,call_int15,call_int1c;
@ -136,6 +136,12 @@ static Bitu INT17_Handler(void) {
return CBRET_NONE; return CBRET_NONE;
}; };
static void WaitFlagEvent(void) {
PhysPt where=Real2Phys(mem_readd(BIOS_WAIT_FLAG_POINTER));
mem_writeb(where,mem_readb(where)|0x80);
mem_writeb(BIOS_WAIT_FLAG_ACTIVE,0);
}
static Bitu INT15_Handler(void) { static Bitu INT15_Handler(void) {
switch (reg_ah) { switch (reg_ah) {
case 0x06: case 0x06:
@ -149,6 +155,12 @@ static Bitu INT15_Handler(void) {
/* Carry should be set but let's just set it just in case */ /* Carry should be set but let's just set it just in case */
CALLBACK_SCF(true); CALLBACK_SCF(true);
break; break;
case 0x83: /* BIOS - SET EVENT WAIT INTERVAL */
mem_writed(BIOS_WAIT_FLAG_POINTER,RealMake(SegValue(es),reg_bx));
mem_writed(BIOS_WAIT_FLAG_COUNT,reg_cx<<16|reg_dx);
mem_writeb(BIOS_WAIT_FLAG_ACTIVE,1);
TIMER_RegisterDelayHandler(&WaitFlagEvent,reg_cx<<16|reg_dx);
break;
case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */ case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */
//Does anyone even use this? //Does anyone even use this?
LOG_WARN("INT15:84:Bios Joystick functionality not done"); LOG_WARN("INT15:84:Bios Joystick functionality not done");
@ -181,6 +193,8 @@ static Bitu INT15_Handler(void) {
break; break;
default: default:
LOG_WARN("INT15:Unknown call %2X",reg_ah); LOG_WARN("INT15:Unknown call %2X",reg_ah);
reg_ah=0x86;
CALLBACK_SCF(false);
} }
return CBRET_NONE; return CBRET_NONE;
}; };
@ -193,7 +207,8 @@ static void INT15_StartUp(void) {
void BIOS_SetupKeyboard(void); void BIOS_SetupKeyboard(void);
void BIOS_SetupDisks(void); void BIOS_SetupDisks(void);
void BIOS_Init(void) { void BIOS_Init(Section* sec) {
MSG_Add("BIOS_CONFIGFILE_HELP","Nothing to setup yet!\n");
/* Clear the Bios Data Area */ /* Clear the Bios Data Area */
for (Bit16u i=0;i<1024;i++) real_writeb(0x40,i,0); for (Bit16u i=0;i<1024;i++) real_writeb(0x40,i,0);
/* Setup all the interrupt handlers the bios controls */ /* Setup all the interrupt handlers the bios controls */
@ -205,7 +220,7 @@ void BIOS_Init(void) {
mem_writed(BIOS_TIMER,0); //Calculate the correct time mem_writed(BIOS_TIMER,0); //Calculate the correct time
RealSetVec(0x8,CALLBACK_RealPointer(call_int8)); RealSetVec(0x8,CALLBACK_RealPointer(call_int8));
/* INT10 Video Bios */ /* INT10 Video Bios */
INT10_StartUp();
/* INT 11 Get equipment list */ /* INT 11 Get equipment list */
call_int11=CALLBACK_Allocate(); call_int11=CALLBACK_Allocate();
CALLBACK_Setup(call_int11,&INT11_Handler,CB_IRET); CALLBACK_Setup(call_int11,&INT11_Handler,CB_IRET);

View File

@ -329,7 +329,7 @@ static Bitu INT16_Handler(void) {
LOG_DEBUG("INT16:55:Word TSR compatible call"); LOG_DEBUG("INT16:55:Word TSR compatible call");
break; break;
default: default:
E_Exit("INT16:Unhandled call %02X",reg_ah); LOG_ERROR("INT16:Unhandled call %02X",reg_ah);
break; break;
}; };

View File

@ -27,7 +27,9 @@
#include "regs.h" #include "regs.h"
#include "inout.h" #include "inout.h"
#include "dos_inc.h" #include "dos_inc.h"
#include "setup.h"
#define EMM_USEHANDLER 1
#define EMM_PAGEFRAME 0xE000 #define EMM_PAGEFRAME 0xE000
#define EMM_MAX_HANDLES 50 /* 255 Max */ #define EMM_MAX_HANDLES 50 /* 255 Max */
@ -97,8 +99,23 @@ struct EMM_Handle {
static EMM_Handle emm_handles[EMM_MAX_HANDLES]; static EMM_Handle emm_handles[EMM_MAX_HANDLES];
static EMM_Page emm_pages[EMM_MAX_PAGES]; static EMM_Page emm_pages[EMM_MAX_PAGES];
static EMM_Mapping emm_mappings[EMM_MAX_PHYS]; static EMM_Mapping emm_mappings[EMM_MAX_PHYS];
static HostPt emm_pagebase[EMM_MAX_PHYS];
Bitu call_int67; Bitu call_int67;
#if EMM_USEHANDLER
Bit8u EMM_ReadHandler(PhysPt start) {
start-=EMM_PAGEFRAME * 16;
Bitu page=start>>14;
return readb(emm_pagebase[page]+(start&0x3fff));
}
void EMM_WriteHandler(PhysPt start,Bit8u val) {
start-=EMM_PAGEFRAME * 16;
Bitu page=start>>14;
writeb(emm_pagebase[page]+(start&0x3fff),val);
}
#endif
static Bit16u EMM_GetFreePages(void) { static Bit16u EMM_GetFreePages(void) {
Bit16u count=0; Bit16u count=0;
for (Bitu index=0;index<EMM_MAX_PAGES;index++) { for (Bitu index=0;index<EMM_MAX_PAGES;index++) {
@ -114,7 +131,7 @@ static Bit8u EMM_AllocateMemory(Bit16u pages,Bit16u & handle) {
if (EMM_GetFreePages()<pages){ handle=NULL_HANDLE; return EMM_OUT_OF_LOG;} if (EMM_GetFreePages()<pages){ handle=NULL_HANDLE; return EMM_OUT_OF_LOG;}
handle=1; handle=1;
/* Check for a free handle */ /* Check for a free handle */
while (emm_handles[handle].first_page!=NULL_PAGE) { while (emm_handles[handle].pages!=NULL_HANDLE) {
if (++handle>=EMM_MAX_HANDLES) {handle=NULL_HANDLE;return EMM_OUT_OF_HANDLES;} if (++handle>=EMM_MAX_HANDLES) {handle=NULL_HANDLE;return EMM_OUT_OF_HANDLES;}
} }
/* Allocate the pages */ /* Allocate the pages */
@ -138,7 +155,7 @@ static Bit8u EMM_AllocateMemory(Bit16u pages,Bit16u & handle) {
static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) { static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) {
/* Check for valid handle */ /* Check for valid handle */
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE; if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE;
/* Check for enough pages */ /* Check for enough pages */
if ((emm_handles[handle].pages+EMM_GetFreePages())<pages) return EMM_OUT_OF_LOG; if ((emm_handles[handle].pages+EMM_GetFreePages())<pages) return EMM_OUT_OF_LOG;
Bit16u page=emm_handles[handle].first_page; Bit16u page=emm_handles[handle].first_page;
@ -163,6 +180,7 @@ static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) {
page=next_page;page_count--; page=next_page;page_count--;
} }
pages=emm_handles[handle].pages; pages=emm_handles[handle].pages;
if (!pages) emm_handles[handle].first_page=NULL_PAGE;
return EMM_NO_ERROR; return EMM_NO_ERROR;
} }
if (!page_count && pages) { if (!page_count && pages) {
@ -174,7 +192,8 @@ static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) {
emm_pages[page].handle=handle; emm_pages[page].handle=handle;
emm_pages[page].memory=malloc(EMM_PAGE_SIZE); emm_pages[page].memory=malloc(EMM_PAGE_SIZE);
if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory"); if (!emm_pages[page].memory) E_Exit("EMM:Cannont allocate memory");
emm_pages[last].next=page; if (last!=NULL_PAGE) emm_pages[last].next=page;
else emm_handles[handle].first_page=page;
last=page; last=page;
pages--; pages--;
} else { } else {
@ -193,7 +212,7 @@ static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
/* Check for too high physical page */ /* Check for too high physical page */
if (phys_page>=EMM_MAX_PHYS) return EMM_ILL_PHYS; if (phys_page>=EMM_MAX_PHYS) return EMM_ILL_PHYS;
/* Check for valid handle */ /* Check for valid handle */
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE; if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE;
/* Check to do unmapping or mappning */ /* Check to do unmapping or mappning */
if (log_page<emm_handles[handle].pages) { if (log_page<emm_handles[handle].pages) {
/* Mapping it is */ /* Mapping it is */
@ -206,13 +225,21 @@ static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
log_page--; log_page--;
} }
/* Do the actual mapping */ /* Do the actual mapping */
#if EMM_USEHANDLER
emm_pagebase[phys_page]=(HostPt) emm_pages[index].memory;
#else
MEM_SetupMapping(PAGE_COUNT(PhysMake(EMM_PAGEFRAME,phys_page*EMM_PAGE_SIZE)),PAGE_COUNT(PAGE_SIZE),emm_pages[index].memory); MEM_SetupMapping(PAGE_COUNT(PhysMake(EMM_PAGEFRAME,phys_page*EMM_PAGE_SIZE)),PAGE_COUNT(PAGE_SIZE),emm_pages[index].memory);
#endif
return EMM_NO_ERROR; return EMM_NO_ERROR;
} else if (log_page==NULL_PAGE) { } else if (log_page==NULL_PAGE) {
/* Unmapping it is */ /* Unmapping it is */
emm_mappings[phys_page].handle=NULL_HANDLE; emm_mappings[phys_page].handle=NULL_HANDLE;
emm_mappings[phys_page].page=NULL_PAGE; emm_mappings[phys_page].page=NULL_PAGE;
#if EMM_USEHANDLER
emm_pagebase[phys_page]=memory+EMM_PAGEFRAME*16+phys_page*16*1024;
#else
MEM_ClearMapping(PAGE_COUNT(PhysMake(EMM_PAGEFRAME,phys_page*EMM_PAGE_SIZE)),PAGE_COUNT(PAGE_SIZE)); MEM_ClearMapping(PAGE_COUNT(PhysMake(EMM_PAGEFRAME,phys_page*EMM_PAGE_SIZE)),PAGE_COUNT(PAGE_SIZE));
#endif
return EMM_NO_ERROR; return EMM_NO_ERROR;
} else { } else {
/* Illegal logical page it is */ /* Illegal logical page it is */
@ -222,7 +249,7 @@ static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
static Bit8u EMM_ReleaseMemory(Bit16u handle) { static Bit8u EMM_ReleaseMemory(Bit16u handle) {
/* Check for valid handle */ /* Check for valid handle */
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE; if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE;
Bit16u page=emm_handles[handle].first_page; Bit16u page=emm_handles[handle].first_page;
Bit16u pages=emm_handles[handle].pages; Bit16u pages=emm_handles[handle].pages;
while (pages) { while (pages) {
@ -235,7 +262,7 @@ static Bit8u EMM_ReleaseMemory(Bit16u handle) {
} }
/* Reset handle */ /* Reset handle */
emm_handles[handle].first_page=NULL_PAGE; emm_handles[handle].first_page=NULL_PAGE;
emm_handles[handle].pages=0; emm_handles[handle].pages=NULL_HANDLE;
emm_handles[handle].saved_page_map=false; emm_handles[handle].saved_page_map=false;
memset(&emm_handles[handle].name,0,9); memset(&emm_handles[handle].name,0,9);
return EMM_NO_ERROR; return EMM_NO_ERROR;
@ -243,7 +270,7 @@ static Bit8u EMM_ReleaseMemory(Bit16u handle) {
static Bit8u EMM_SavePageMap(Bit16u handle) { static Bit8u EMM_SavePageMap(Bit16u handle) {
/* Check for valid handle */ /* Check for valid handle */
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE; if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE;
/* Check for previous save */ /* Check for previous save */
if (emm_handles[handle].saved_page_map) return EMM_PAGE_MAP_SAVED; if (emm_handles[handle].saved_page_map) return EMM_PAGE_MAP_SAVED;
/* Copy the mappings over */ /* Copy the mappings over */
@ -255,7 +282,7 @@ static Bit8u EMM_SavePageMap(Bit16u handle) {
return EMM_NO_ERROR; return EMM_NO_ERROR;
} }
static Bitu EMM_RestoreMappingTable(void) { static Bit8u EMM_RestoreMappingTable(void) {
Bit8u result; Bit8u result;
/* Move through the mappings table and setup mapping accordingly */ /* Move through the mappings table and setup mapping accordingly */
for (Bitu i=0;i<EMM_MAX_PHYS;i++) { for (Bitu i=0;i<EMM_MAX_PHYS;i++) {
@ -265,7 +292,7 @@ static Bitu EMM_RestoreMappingTable(void) {
} }
static Bit8u EMM_RestorePageMap(Bit16u handle) { static Bit8u EMM_RestorePageMap(Bit16u handle) {
/* Check for valid handle */ /* Check for valid handle */
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].first_page==NULL_PAGE) return EMM_INVALID_HANDLE; if (handle>=EMM_MAX_HANDLES || emm_handles[handle].pages==NULL_HANDLE) return EMM_INVALID_HANDLE;
/* Check for previous save */ /* Check for previous save */
if (!emm_handles[handle].saved_page_map) return EMM_INVALID_HANDLE; if (!emm_handles[handle].saved_page_map) return EMM_INVALID_HANDLE;
/* Restore the mappings */ /* Restore the mappings */
@ -280,7 +307,7 @@ static Bit8u EMM_RestorePageMap(Bit16u handle) {
static Bit8u EMM_GetPagesForAllHandles(PhysPt table,Bit16u & handles) { static Bit8u EMM_GetPagesForAllHandles(PhysPt table,Bit16u & handles) {
handles=0; handles=0;
for (Bit16u i=0;i<EMM_MAX_HANDLES;i++) { for (Bit16u i=0;i<EMM_MAX_HANDLES;i++) {
if (emm_handles[i].first_page!=NULL_PAGE) { if (emm_handles[i].pages!=NULL_HANDLE) {
handles++; handles++;
mem_writew(table,i); mem_writew(table,i);
mem_writew(table+2,emm_handles[i].pages); mem_writew(table+2,emm_handles[i].pages);
@ -290,6 +317,44 @@ static Bit8u EMM_GetPagesForAllHandles(PhysPt table,Bit16u & handles) {
return EMM_NO_ERROR; return EMM_NO_ERROR;
} }
static Bit8u EMM_PartialPageMapping(void) {
PhysPt list,data;Bit16u count;
switch (reg_al) {
case 0x00: /* Save Partial Page Map */
list = SegPhys(ds)+reg_si;
data = SegPhys(es)+reg_di;
count=mem_readw(list);list+=2;
mem_writew(data,count);data+=2;
for (;count>0;count--) {
Bit16u page=mem_readw(list);list+=2;
if (page>=EMM_MAX_PHYS) return EMM_ILL_PHYS;
mem_writew(data,page);data+=2;
MEM_BlockWrite(data,&emm_mappings[page],sizeof(EMM_Mapping));
data+=sizeof(EMM_Mapping);
}
break;
case 0x01: /* Restore Partial Page Map */
data = SegPhys(ds)+reg_si;
count= mem_readw(data);data+=2;
for (;count>0;count--) {
Bit16u page=mem_readw(data);data+=2;
if (page>=EMM_MAX_PHYS) return EMM_ILL_PHYS;
MEM_BlockRead(data,&emm_mappings[page],sizeof(EMM_Mapping));
data+=sizeof(EMM_Mapping);
}
return EMM_RestoreMappingTable();
break;
case 0x02: /* Get Partial Page Map Array Size */
reg_al=2+reg_bx*(2+sizeof(EMM_Mapping));
break;
default:
LOG_ERROR("EMS:Call %2X Subfunction %2X not supported",reg_ah,reg_al);
return EMM_FUNC_NOSUP;
}
return 0;
}
static Bitu INT67_Handler(void) { static Bitu INT67_Handler(void) {
Bitu i; Bitu i;
switch (reg_ah) { switch (reg_ah) {
@ -326,12 +391,12 @@ static Bitu INT67_Handler(void) {
break; break;
case 0x4b: /* Get Handle Count */ case 0x4b: /* Get Handle Count */
reg_bx=0; reg_bx=0;
for (i=0;i<EMM_MAX_HANDLES;i++) if (emm_handles[i].first_page!=NULL_PAGE) reg_bx++; for (i=0;i<EMM_MAX_HANDLES;i++) if (emm_handles[i].pages!=NULL_HANDLE) reg_bx++;
reg_ah=EMM_NO_ERROR; reg_ah=EMM_NO_ERROR;
break; break;
case 0x4c: /* Get Pages for one Handle */ case 0x4c: /* Get Pages for one Handle */
/* Check for valid handle */ /* Check for valid handle */
if (reg_bx>=EMM_MAX_HANDLES || emm_handles[reg_bx].first_page==NULL_PAGE) {reg_ah=EMM_INVALID_HANDLE;break;} if (reg_bx>=EMM_MAX_HANDLES || emm_handles[reg_bx].pages==NULL_HANDLE) {reg_ah=EMM_INVALID_HANDLE;break;}
reg_bx=emm_handles[reg_dx].pages; reg_bx=emm_handles[reg_dx].pages;
reg_ah=EMM_NO_ERROR; reg_ah=EMM_NO_ERROR;
break; break;
@ -339,7 +404,6 @@ static Bitu INT67_Handler(void) {
reg_ah=EMM_GetPagesForAllHandles(SegPhys(es)+reg_di,reg_bx); reg_ah=EMM_GetPagesForAllHandles(SegPhys(es)+reg_di,reg_bx);
break; break;
case 0x4e: /*Save/Restore Page Map */ case 0x4e: /*Save/Restore Page Map */
LOG_WARN("Save/resetore %d",reg_al);
switch (reg_al) { switch (reg_al) {
case 0x00: /* Save Page Map */ case 0x00: /* Save Page Map */
MEM_BlockWrite(SegPhys(es)+reg_di,emm_mappings,sizeof(emm_mappings)); MEM_BlockWrite(SegPhys(es)+reg_di,emm_mappings,sizeof(emm_mappings));
@ -364,7 +428,11 @@ static Bitu INT67_Handler(void) {
break; break;
} }
break; break;
case 0x50: // Map/Unmap multiple handle pages case 0x4f: /* Save/Restore Partial Page Map */
reg_ah=EMM_PartialPageMapping();
break;
case 0x50: /* Map/Unmap multiple handle pages */
reg_ah = EMM_NO_ERROR; reg_ah = EMM_NO_ERROR;
switch (reg_al) { switch (reg_al) {
case 0x00: // use physical page numbers case 0x00: // use physical page numbers
@ -413,7 +481,7 @@ static Bitu INT67_Handler(void) {
reg_ah = EMM_NO_ERROR; reg_ah = EMM_NO_ERROR;
break; break;
case 0xDE: /* VCPI Functions */ case 0xDE: /* VCPI Functions */
LOG_ERROR("VCPI Functions not supported"); LOG_ERROR("VCPI Functions %X not supported",reg_al);
reg_ah=EMM_FUNC_NOSUP; reg_ah=EMM_FUNC_NOSUP;
break; break;
default: default:
@ -426,14 +494,16 @@ static Bitu INT67_Handler(void) {
void EMS_Init(void) { void EMS_Init(Section* sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
Bitu size=section->Get_int("emssize");
if (!size) return;
call_int67=CALLBACK_Allocate(); call_int67=CALLBACK_Allocate();
CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET); CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET);
/* Register the ems device */ /* Register the ems device */
DOS_Device * newdev = new device_EMM(); DOS_Device * newdev = new device_EMM();
DOS_AddDevice(newdev); DOS_AddDevice(newdev);
/* Add a little hack so it appears that there is an actual ems device installed */ /* Add a little hack so it appears that there is an actual ems device installed */
char * emsname="EMMXXXX0"; char * emsname="EMMXXXX0";
Bit16u seg=DOS_GetMemory(2); //We have 32 bytes Bit16u seg=DOS_GetMemory(2); //We have 32 bytes
@ -452,12 +522,20 @@ void EMS_Init(void) {
} }
for (i=0;i<EMM_MAX_HANDLES;i++) { for (i=0;i<EMM_MAX_HANDLES;i++) {
emm_handles[i].first_page=NULL_PAGE; emm_handles[i].first_page=NULL_PAGE;
emm_handles[i].pages=NULL_HANDLE;
memset(&emm_handles[i].name,0,9); memset(&emm_handles[i].name,0,9);
} }
for (i=0;i<EMM_MAX_PHYS;i++) { for (i=0;i<EMM_MAX_PHYS;i++) {
emm_mappings[i].page=NULL_PAGE; emm_mappings[i].page=NULL_PAGE;
emm_mappings[i].handle=NULL_HANDLE; emm_mappings[i].handle=NULL_HANDLE;
} }
#if EMM_USEHANDLER
/* Setup page handler */
MEM_SetupPageHandlers(PAGE_COUNT(EMM_PAGEFRAME*16),PAGE_COUNT(64*1024),EMM_ReadHandler,EMM_WriteHandler);
emm_pagebase[0]=memory+EMM_PAGEFRAME*16;
emm_pagebase[1]=memory+EMM_PAGEFRAME*16+16*1024;
emm_pagebase[2]=memory+EMM_PAGEFRAME*16+32*1024;
emm_pagebase[3]=memory+EMM_PAGEFRAME*16+48*1024;
#endif
} }

View File

@ -259,7 +259,7 @@ static void INT10_InitVGA(void) {
IO_Write(0x3c5,0x02); IO_Write(0x3c5,0x02);
}; };
void INT10_StartUp(void) { void INT10_Init(Section* sec) {
INT10_InitVGA(); INT10_InitVGA();
/* Setup the INT 10 vector */ /* Setup the INT 10 vector */
call_10=CALLBACK_Allocate(); call_10=CALLBACK_Allocate();

View File

@ -57,7 +57,6 @@ static INLINE void PLANAR4_FillRow(VGAMODES * curmode,Bit8u cleft,Bit8u cright,B
IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff); IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff);
IO_Write(0x3ce,0x0);IO_Write(0x3cf,attr); IO_Write(0x3ce,0x0);IO_Write(0x3cf,attr);
IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf); IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf);
IO_Write(0x3ce,5);IO_Write(0x3cf,0); /* Normal transfer mode */
/* Write some bytes */ /* Write some bytes */
PhysPt dest; PhysPt dest;
dest=base+(curmode->twidth*row)*curmode->cheight+cleft; dest=base+(curmode->twidth*row)*curmode->cheight+cleft;
@ -104,8 +103,8 @@ void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit
end=cul; end=cul;
next=-1; next=-1;
} else if (nlines<0) { } else if (nlines<0) {
start=cul-nlines-1; start=rul-nlines-1;
end=clr; end=rlr;
next=1; next=1;
} else { } else {
nlines=rlr-rul+1; nlines=rlr-rul+1;
@ -127,8 +126,8 @@ filling:
if (nlines>0) { if (nlines>0) {
start=rul; start=rul;
} else { } else {
nlines-=nlines; nlines=-nlines;
start=rlr-nlines; start=rlr-nlines+1;
} }
for (;nlines>0;nlines--) { for (;nlines>0;nlines--) {
switch (curmode->memmodel) { switch (curmode->memmodel) {

View File

@ -23,9 +23,7 @@
#if defined (_MSC_VER)
#pragma pack(1) #pragma pack(1)
#endif
struct Dynamic_Functionality { struct Dynamic_Functionality {
RealPt static_table; /* 00h DWORD address of static functionality table */ RealPt static_table; /* 00h DWORD address of static functionality table */
Bit8u cur_mode; /* 04h BYTE video mode in effect */ Bit8u cur_mode; /* 04h BYTE video mode in effect */
@ -70,19 +68,10 @@ struct Dynamic_Functionality {
7 reserved 7 reserved
*/ */
Bit8u reserved2[13]; /* 33h 13 BYTEs reserved (00h) */ Bit8u reserved2[13]; /* 33h 13 BYTEs reserved (00h) */
} } GCC_ATTRIBUTE(packed);
#if defined (_MSC_VER)
;
#pragma pack() #pragma pack()
#else
__attribute__ ((packed));
#endif
void INT10_GetFuncStateInformation(PhysPt save) { void INT10_GetFuncStateInformation(PhysPt save) {
/* set static state pointer */ /* set static state pointer */
mem_writed(save,int10_romarea.static_state); mem_writed(save,int10_romarea.static_state);
/* Copy BIOS Segment areas */ /* Copy BIOS Segment areas */

View File

@ -274,6 +274,44 @@ void INT10_SetVideoMode(Bit8u mode) {
modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
/* Reset Attribute ctl into address mode just to be safe */
IO_Read(VGAREG_ACTL_RESET);
// Set the High Attribute Ctl
for(i=0x10;i<=ACTL_MAX_REG;i++) {
IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
}
// Set Sequencer Ctl
for(i=0;i<=SEQU_MAX_REG;i++) {
IO_Write(VGAREG_SEQU_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
}
// Set Grafx Ctl
for(i=0;i<=GRDC_MAX_REG;i++) {
IO_Write(VGAREG_GRDC_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
}
// Set CRTC address VGA or MDA
crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
// Set CRTC regs
for(i=0;i<=CRTC_MAX_REG;i++) {
IO_Write(crtc_addr,(Bit8u)i);
IO_Write(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
}
// Set the misc register
IO_Write(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
// Enable video
IO_Write(VGAREG_ACTL_ADDRESS,0x20);
IO_Read(VGAREG_ACTL_RESET);
//Set the palette
if ((modeset_ctl&0x08)==0x8) LOG_DEBUG("INT10:Mode set without palette");
if((modeset_ctl&0x08)==0) { if((modeset_ctl&0x08)==0) {
// Set the PEL mask // Set the PEL mask
IO_Write(VGAREG_PEL_MASK,vga_modes[line].pelmask); IO_Write(VGAREG_PEL_MASK,vga_modes[line].pelmask);
@ -312,40 +350,13 @@ void INT10_SetVideoMode(Bit8u mode) {
} }
} }
/* Reset Attribute ctl into address mode just to be safe */
IO_Read(VGAREG_ACTL_RESET); IO_Read(VGAREG_ACTL_RESET);
// Set Attribute Ctl // Set the Low Attribute Ctl
for(i=0;i<=ACTL_MAX_REG;i++) { for(i=0;i<=0xf;i++) {
IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i); IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]); IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
} }
// Set Sequencer Ctl
for(i=0;i<=SEQU_MAX_REG;i++) {
IO_Write(VGAREG_SEQU_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_SEQU_DATA,sequ_regs[vga_modes[line].sequmodel][i]);
}
// Set Grafx Ctl
for(i=0;i<=GRDC_MAX_REG;i++) {
IO_Write(VGAREG_GRDC_ADDRESS,(Bit8u)i);
IO_Write(VGAREG_GRDC_DATA,grdc_regs[vga_modes[line].grdcmodel][i]);
}
// Set CRTC address VGA or MDA
crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS;
// Set CRTC regs
for(i=0;i<=CRTC_MAX_REG;i++) {
IO_Write(crtc_addr,(Bit8u)i);
IO_Write(crtc_addr+1,crtc_regs[vga_modes[line].crtcmodel][i]);
}
// Set the misc register
IO_Write(VGAREG_WRITE_MISC_OUTPUT,vga_modes[line].miscreg);
// Enable video
IO_Write(VGAREG_ACTL_ADDRESS,0x20);
IO_Read(VGAREG_ACTL_RESET);
Bit32u tel; Bit32u tel;
if(clearmem) { if(clearmem) {
if(vga_modes[line].type==TEXT) { if(vga_modes[line].type==TEXT) {
@ -377,6 +388,7 @@ void INT10_SetVideoMode(Bit8u mode) {
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight); real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem << 7))); real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem << 7)));
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9); real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9);
real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0);
real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f); real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f);
// FIXME We nearly have the good tables. to be reworked // FIXME We nearly have the good tables. to be reworked

View File

@ -21,12 +21,6 @@
#include "inout.h" #include "inout.h"
#include "int10.h" #include "int10.h"
union VGA_Memory {
Bit8u linear[64*1024*4];
Bit8u paged[64*1024][4];
};
extern VGA_Memory vga_mem;
static Bit8u cga_masks[4]={~192,~48,~12,~3}; static Bit8u cga_masks[4]={~192,~48,~12,~3};
void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
@ -39,7 +33,12 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
Bit16u off=(y>>1)*80+(x>>2); Bit16u off=(y>>1)*80+(x>>2);
if (y&1) off+=8*1024; if (y&1) off+=8*1024;
Bit8u old=real_readb(0xb800,off); Bit8u old=real_readb(0xb800,off);
if (color & 0x80) {
color&=3;
old^=color << (2*(3-(x&3)));
} else {
old=old&cga_masks[x&3]|((color&3) << (2*(3-(x&3)))); old=old&cga_masks[x&3]|((color&3) << (2*(3-(x&3))));
}
real_writeb(0xb800,off,old); real_writeb(0xb800,off,old);
} }
break; break;
@ -51,20 +50,27 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
IO_Write(0x3ce,0x0);IO_Write(0x3cf,color); IO_Write(0x3ce,0x0);IO_Write(0x3cf,color);
/* Enable all the set/resets */ /* Enable all the set/resets */
IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf); IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf);
/* test for xorring */
if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x18); }
//Perhaps also set mode 1 //Perhaps also set mode 1
/* Calculate where the pixel is in video memory */ /* Calculate where the pixel is in video memory */
Bit16u base_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page; PhysPt off=0xa0000+curmode->slength*page+((y*curmode->swidth+x)>>3);
PhysPt off=0xa0000+base_address+((y*curmode->swidth+x)>>3);
/* Bitmask and set/reset should do the rest */ /* Bitmask and set/reset should do the rest */
mem_readb(off); mem_readb(off);
mem_writeb(off,0xff); mem_writeb(off,0xff);
/* Restore bitmask */
IO_Write(0x3ce,0x8);IO_Write(0x3cf,0xff);
/* Restore write operating if changed */
if (color & 0x80) { IO_Write(0x3ce,0x3);IO_Write(0x3cf,0x0); }
break; break;
} }
case CTEXT: case LINEAR8:
case MTEXT: mem_writeb(Real2Phys(RealMake(0xa000,y*320+x)),color);
break;
case PLANAR1: case PLANAR1:
case PLANAR2: case PLANAR2:
case LINEAR8: case CTEXT:
case MTEXT:
default: default:
LOG_WARN("INT10:PutPixel Unhanled memory model"); LOG_WARN("INT10:PutPixel Unhanled memory model");
break; break;
@ -72,7 +78,6 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
} }
void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) { void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
VGAMODES * curmode=GetCurrentMode(); VGAMODES * curmode=GetCurrentMode();
switch (curmode->memmodel) { switch (curmode->memmodel) {
case CGA: case CGA:
@ -83,6 +88,30 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
*color=val<<((x&3)*2); *color=val<<((x&3)*2);
} }
break; break;
case PLANAR4:
{
/* Calculate where the pixel is in video memory */
PhysPt off=0xa0000+curmode->slength*page+((y*curmode->swidth+x)>>3);
Bitu shift=7-(x & 7);
/* Set the read map */
*color=0;
IO_Write(0x3ce,0x4);IO_Write(0x3cf,0);
*color|=((mem_readb(off)>>shift) & 1) << 0;
IO_Write(0x3ce,0x4);IO_Write(0x3cf,1);
*color|=((mem_readb(off)>>shift) & 1) << 1;
IO_Write(0x3ce,0x4);IO_Write(0x3cf,2);
*color|=((mem_readb(off)>>shift) & 1) << 2;
IO_Write(0x3ce,0x4);IO_Write(0x3cf,3);
*color|=((mem_readb(off)>>shift) & 1) << 3;
break;
}
case LINEAR8:
*color=mem_readb(PhysMake(0xa000,320*y+x));
break;
case PLANAR1:
case PLANAR2:
case CTEXT:
case MTEXT:
default: default:
LOG_WARN("INT10:GetPixel Unhanled memory model"); LOG_WARN("INT10:GetPixel Unhanled memory model");
break; break;

View File

@ -25,7 +25,7 @@
#include "mouse.h" #include "mouse.h"
#include "pic.h" #include "pic.h"
#include "inout.h" #include "inout.h"
#include "int10.h"
static Bitu call_int33,call_int74; static Bitu call_int33,call_int74;
@ -35,24 +35,22 @@ struct button_event {
}; };
#define QUEUE_SIZE 32 #define QUEUE_SIZE 32
//TODO Maybe use :) #define MOUSE_BUTTONS 3
#define MOUSE_IRQ 12 #define MOUSE_IRQ 12
#define POS_X (Bit16s)(mouse.x*mouse.range_x) #define POS_X (Bit16s)(mouse.x)
#define POS_Y (Bit16s)(mouse.y*mouse.range_y) #define POS_Y (Bit16s)(mouse.y)
static struct { static struct {
Bit16u buttons; Bit16u buttons;
Bit16u times_pressed[3]; Bit16u times_pressed[MOUSE_BUTTONS];
Bit16u times_released[3]; Bit16u times_released[MOUSE_BUTTONS];
Bit16u last_released_x[3]; Bit16u last_released_x[MOUSE_BUTTONS];
Bit16u last_released_y[3]; Bit16u last_released_y[MOUSE_BUTTONS];
Bit16u last_pressed_x[3]; Bit16u last_pressed_x[MOUSE_BUTTONS];
Bit16u last_pressed_y[3]; Bit16u last_pressed_y[MOUSE_BUTTONS];
Bit16s shown; Bit16s shown;
float add_x,add_y; float add_x,add_y;
Bit16u min_x,max_x,min_y,max_y; Bit16u min_x,max_x,min_y,max_y;
float range_x,range_y;
float mickey_x,mickey_y; float mickey_x,mickey_y;
float x,y; float x,y;
button_event event_queue[QUEUE_SIZE]; button_event event_queue[QUEUE_SIZE];
@ -61,8 +59,8 @@ static struct {
Bit16u sub_mask; Bit16u sub_mask;
} mouse; } mouse;
#define X_MICKEY 500 #define X_MICKEY 8
#define Y_MICKEY 500 #define Y_MICKEY 8
#define MOUSE_MOVED 1 #define MOUSE_MOVED 1
#define MOUSE_LEFT_PRESSED 2 #define MOUSE_LEFT_PRESSED 2
@ -72,7 +70,7 @@ static struct {
#define MOUSE_MIDDLE_PRESSED 32 #define MOUSE_MIDDLE_PRESSED 32
#define MOUSE_MIDDLE_RELEASED 64 #define MOUSE_MIDDLE_RELEASED 64
inline void Mouse_AddEvent(Bit16u type) { INLINE void Mouse_AddEvent(Bit16u type) {
if (mouse.events<QUEUE_SIZE) { if (mouse.events<QUEUE_SIZE) {
mouse.event_queue[mouse.events].type=type; mouse.event_queue[mouse.events].type=type;
mouse.event_queue[mouse.events].buttons=mouse.buttons; mouse.event_queue[mouse.events].buttons=mouse.buttons;
@ -81,22 +79,27 @@ inline void Mouse_AddEvent(Bit16u type) {
PIC_ActivateIRQ(12); PIC_ActivateIRQ(12);
} }
static void DrawCursor() {
if (mouse.shown<0) return;
}
void Mouse_CursorMoved(float x,float y) { void Mouse_CursorMoved(float x,float y) {
mouse.mickey_x+=x; mouse.mickey_x+=x;
mouse.mickey_y+=y; mouse.mickey_y+=y;
mouse.x+=x; mouse.x+=x;
if (mouse.x>1) mouse.x=1; if (mouse.x>mouse.max_x) mouse.x=mouse.max_x;;
if (mouse.x<0) mouse.x=0; if (mouse.x<mouse.min_x) mouse.x=mouse.min_x;
mouse.y+=y; mouse.y+=y;
if (mouse.y>1) mouse.y=1; if (mouse.y>mouse.max_y) mouse.y=mouse.max_y;;
if (mouse.y<0) mouse.y=0; if (mouse.y<mouse.min_y) mouse.y=mouse.min_y;
Mouse_AddEvent(MOUSE_MOVED); Mouse_AddEvent(MOUSE_MOVED);
DrawCursor();
} }
void Mouse_CursorSet(float x,float y) { void Mouse_CursorSet(float x,float y) {
mouse.x=x; mouse.x=x;
mouse.y=y; mouse.y=y;
DrawCursor();
} }
void Mouse_ButtonPressed(Bit8u button) { void Mouse_ButtonPressed(Bit8u button) {
@ -139,7 +142,6 @@ void Mouse_ButtonReleased(Bit8u button) {
mouse.last_released_y[button]=POS_Y; mouse.last_released_y[button]=POS_Y;
} }
static void mouse_reset(void) { static void mouse_reset(void) {
real_writed(0,(0x33<<2),CALLBACK_RealPointer(call_int33)); real_writed(0,(0x33<<2),CALLBACK_RealPointer(call_int33));
real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74));
@ -148,8 +150,6 @@ static void mouse_reset(void) {
mouse.max_x=639; mouse.max_x=639;
mouse.min_y=0; mouse.min_y=0;
mouse.max_y=199; mouse.max_y=199;
mouse.range_x=639;
mouse.range_y=199;
mouse.x=0; // civ wont work otherwise mouse.x=0; // civ wont work otherwise
mouse.y=100; mouse.y=100;
mouse.events=0; mouse.events=0;
@ -158,15 +158,16 @@ static void mouse_reset(void) {
mouse.sub_mask=0; mouse.sub_mask=0;
mouse.sub_seg=0; mouse.sub_seg=0;
mouse.sub_ofs=0; mouse.sub_ofs=0;
}; }
static Bitu INT33_Handler(void) { static Bitu INT33_Handler(void) {
switch (reg_ax) { switch (reg_ax) {
case 0x00: /* Reset Driver and Read Status */ case 0x00: /* Reset Driver and Read Status */
reg_ax=0xffff; reg_ax=0xffff;
reg_bx=0; reg_bx=MOUSE_BUTTONS;
mouse_reset(); mouse_reset();
Mouse_AutoLock(true);
break; break;
case 0x01: /* Show Mouse */ case 0x01: /* Show Mouse */
mouse.shown++; mouse.shown++;
@ -181,12 +182,13 @@ static Bitu INT33_Handler(void) {
reg_dx=POS_Y; reg_dx=POS_Y;
break; break;
case 0x04: /* Position Mouse */ case 0x04: /* Position Mouse */
mouse.x=((float)reg_cx)/mouse.range_x; mouse.x=(float)reg_cx;
mouse.y=((float)reg_dx)/mouse.range_y; mouse.y=(float)reg_dx;
break; break;
case 0x05: /* Return Button Press Data */ case 0x05: /* Return Button Press Data */
{ {
Bit16u but=reg_bx; Bit16u but=reg_bx;
if (but>=MOUSE_BUTTONS) break;
reg_ax=mouse.buttons; reg_ax=mouse.buttons;
reg_cx=mouse.last_pressed_x[but]; reg_cx=mouse.last_pressed_x[but];
mouse.last_pressed_x[but]=0; mouse.last_pressed_x[but]=0;
@ -199,6 +201,7 @@ static Bitu INT33_Handler(void) {
case 0x06: /* Return Button Release Data */ case 0x06: /* Return Button Release Data */
{ {
Bit16u but=reg_bx; Bit16u but=reg_bx;
if (but>=MOUSE_BUTTONS) break;
reg_ax=mouse.buttons; reg_ax=mouse.buttons;
reg_cx=mouse.last_released_x[but]; reg_cx=mouse.last_released_x[but];
mouse.last_released_x[but]=0; mouse.last_released_x[but]=0;
@ -211,13 +214,10 @@ static Bitu INT33_Handler(void) {
case 0x07: /* Define horizontal cursor range */ case 0x07: /* Define horizontal cursor range */
mouse.min_x=reg_cx; mouse.min_x=reg_cx;
mouse.max_x=reg_dx; mouse.max_x=reg_dx;
mouse.range_x=mouse.max_x-mouse.min_x;
//TODO Check for range start 0
break; break;
case 0x08: /* Define vertical cursor range */ case 0x08: /* Define vertical cursor range */
mouse.min_y=reg_cx; mouse.min_y=reg_cx;
mouse.max_y=reg_dx; mouse.max_y=reg_dx;
mouse.range_y=mouse.max_y-mouse.min_y;
break; break;
case 0x09: /* Define GFX Cursor */ case 0x09: /* Define GFX Cursor */
LOG_WARN("MOUSE:Define gfx cursor not supported"); LOG_WARN("MOUSE:Define gfx cursor not supported");
@ -240,7 +240,8 @@ static Bitu INT33_Handler(void) {
mouse.mickey_y=0; mouse.mickey_y=0;
break; break;
case 0x14: /* Exchange event-handler */ case 0x14: /* Exchange event-handler */
{ Bit16u oldSeg = mouse.sub_seg; {
Bit16u oldSeg = mouse.sub_seg;
Bit16u oldOfs = mouse.sub_ofs; Bit16u oldOfs = mouse.sub_ofs;
Bit16u oldMask= mouse.sub_mask; Bit16u oldMask= mouse.sub_mask;
// Set new values // Set new values
@ -251,7 +252,8 @@ static Bitu INT33_Handler(void) {
reg_cx = oldMask; reg_cx = oldMask;
reg_dx = oldOfs; reg_dx = oldOfs;
SegSet16(es,oldSeg); SegSet16(es,oldSeg);
}; break; }
break;
case 0x1c: /* Set interrupt rate */ case 0x1c: /* Set interrupt rate */
/* Can't really set a rate this is host determined */ /* Can't really set a rate this is host determined */
break; break;
@ -267,9 +269,9 @@ static Bitu INT33_Handler(void) {
break; break;
default: default:
LOG_ERROR("Mouse Function %2X",reg_ax); LOG_ERROR("Mouse Function %2X",reg_ax);
}; }
return CBRET_NONE; return CBRET_NONE;
}; }
static Bitu INT74_Handler(void) { static Bitu INT74_Handler(void) {
if (mouse.events>0) { if (mouse.events>0) {
@ -301,16 +303,13 @@ static Bitu INT74_Handler(void) {
} }
IO_Write(0xa0,0x20); IO_Write(0xa0,0x20);
/* Check for more Events if so reactivate IRQ */ /* Check for more Events if so reactivate IRQ */
if (mouse.events) { if (mouse.events) {
PIC_ActivateIRQ(12); PIC_ActivateIRQ(12);
} }
return CBRET_NONE; return CBRET_NONE;
}; }
void MOUSE_Init(Section* sec) {
void MOUSE_Init(void) {
call_int33=CALLBACK_Allocate(); call_int33=CALLBACK_Allocate();
CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET); CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET);
real_writed(0,(0x33<<2),CALLBACK_RealPointer(call_int33)); real_writed(0,(0x33<<2),CALLBACK_RealPointer(call_int33));
@ -319,7 +318,7 @@ void MOUSE_Init(void) {
CALLBACK_Setup(call_int74,&INT74_Handler,CB_IRET); CALLBACK_Setup(call_int74,&INT74_Handler,CB_IRET);
real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74)); real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74));
memset((void *)&mouse,0,sizeof(mouse)); memset(&mouse,0,sizeof(mouse));
mouse_reset(); mouse_reset();
}; }

View File

@ -23,6 +23,7 @@
#include "mem.h" #include "mem.h"
#include "regs.h" #include "regs.h"
#include "dos_system.h" #include "dos_system.h"
#include "setup.h"
#define XMS_HANDLES 50 /* 50 XMS Memory Blocks */ #define XMS_HANDLES 50 /* 50 XMS Memory Blocks */
@ -53,6 +54,8 @@
#define XMS_OUT_OF_SPACE 0xa0 #define XMS_OUT_OF_SPACE 0xa0
#define XMS_OUT_OF_HANDLES 0xa1 #define XMS_OUT_OF_HANDLES 0xa1
#define XMS_INVALID_HANDLE 0xa2 #define XMS_INVALID_HANDLE 0xa2
#define XMS_BLOCK_NOT_LOCKED 0xaa
#define XMS_BLOCK_LOCKED 0xab
struct XMS_Block { struct XMS_Block {
Bit16u prev,next; Bit16u prev,next;
@ -291,8 +294,13 @@ foundnew:
reg_bl=XMS_INVALID_HANDLE; reg_bl=XMS_INVALID_HANDLE;
return CBRET_NONE; return CBRET_NONE;
} }
if (xms_handles[reg_dx].locked) xms_handles[reg_dx].locked--; if (xms_handles[reg_dx].locked) {
xms_handles[reg_dx].locked--;
reg_ax=1;reg_bl=0; reg_ax=1;reg_bl=0;
} else {
reg_ax=0;
reg_bl=XMS_BLOCK_NOT_LOCKED;
}
break; break;
case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */ case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */
/* Check for a valid handle */ /* Check for a valid handle */
@ -324,7 +332,11 @@ foundnew:
void XMS_Init(void) { void XMS_Init(Section* sec) {
Section_prop * section=static_cast<Section_prop *>(sec);
Bitu size=section->Get_int("xmssize");
if (!size) return;
if (size>C_MEM_MAX_SIZE-1) size=C_MEM_MAX_SIZE-1;
DOS_AddMultiplexHandler(multiplex_xms); DOS_AddMultiplexHandler(multiplex_xms);
call_xms=CALLBACK_Allocate(); call_xms=CALLBACK_Allocate();
CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF); CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF);
@ -345,6 +357,6 @@ void XMS_Init(void) {
/* Setup the 1st handle */ /* Setup the 1st handle */
xms_handles[1].active=true; xms_handles[1].active=true;
xms_handles[1].phys=1088*1024; /* right behind the hma area */ xms_handles[1].phys=1088*1024; /* right behind the hma area */
xms_handles[1].size=C_MEM_XMS_SIZE*1024-64; xms_handles[1].size=size*1024-64;
} }

View File

@ -1,4 +1,4 @@
AM_CPPFLAGS = -I$(top_srcdir)/include AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libmisc.a noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = plugins.cpp programs.cpp messages.cpp support.cpp setup.cpp libmisc_a_SOURCES = programs.cpp messages.cpp support.cpp setup.cpp

View File

@ -84,7 +84,7 @@ install_sh = @install_sh@
AM_CPPFLAGS = -I$(top_srcdir)/include AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_LIBRARIES = libmisc.a noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = plugins.cpp programs.cpp messages.cpp support.cpp setup.cpp libmisc_a_SOURCES = programs.cpp messages.cpp support.cpp setup.cpp
subdir = src/misc subdir = src/misc
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h CONFIG_HEADER = $(top_builddir)/config.h
@ -93,8 +93,8 @@ LIBRARIES = $(noinst_LIBRARIES)
libmisc_a_AR = $(AR) cru libmisc_a_AR = $(AR) cru
libmisc_a_LIBADD = libmisc_a_LIBADD =
am_libmisc_a_OBJECTS = plugins.$(OBJEXT) programs.$(OBJEXT) \ am_libmisc_a_OBJECTS = programs.$(OBJEXT) messages.$(OBJEXT) \
messages.$(OBJEXT) support.$(OBJEXT) setup.$(OBJEXT) support.$(OBJEXT) setup.$(OBJEXT)
libmisc_a_OBJECTS = $(am_libmisc_a_OBJECTS) libmisc_a_OBJECTS = $(am_libmisc_a_OBJECTS)
DEFS = @DEFS@ DEFS = @DEFS@
@ -104,9 +104,8 @@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@ LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/depcomp depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/messages.Po ./$(DEPDIR)/plugins.Po \ @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/messages.Po ./$(DEPDIR)/programs.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/programs.Po ./$(DEPDIR)/setup.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/setup.Po ./$(DEPDIR)/support.Po
@AMDEP_TRUE@ ./$(DEPDIR)/support.Po
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
CXXLD = $(CXX) CXXLD = $(CXX)
@ -143,7 +142,6 @@ distclean-compile:
-rm -f *.tab.c -rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messages.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messages.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugins.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/programs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/programs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Po@am__quote@

View File

@ -23,24 +23,54 @@
#include "cross.h" #include "cross.h"
#include "support.h" #include "support.h"
#include "setup.h" #include "setup.h"
#include <list>
#include <string>
using namespace std;
#define LINE_IN_MAXLEN 1024 #define LINE_IN_MAXLEN 1024
struct MessageBlock struct MessageBlock {
{ string name;
char * name; string val;
char * string; MessageBlock(const char* _name, const char* _val):
MessageBlock * next; name(_name),val(_val){}
}; };
static MessageBlock * first_message; static list<MessageBlock> Lang;
typedef list<MessageBlock>::iterator itmb;
void MSG_Add(const char * _name, const char* _val) {
/* Find the message */
for(itmb tel=Lang.begin();tel!=Lang.end();tel++) {
if((*tel).name==_name) {
return;
}
}
/* Even if the message doesn't exist add it */
Lang.push_back(MessageBlock(_name,_val));
}
static void LoadMessageFile(char * fname) { void MSG_Replace(const char * _name, const char* _val) {
/* Find the message */
for(itmb tel=Lang.begin();tel!=Lang.end();tel++) {
if((*tel).name==_name) {
itmb teln=tel;
teln++;
Lang.erase(tel,teln);
break;
}
}
/* Even if the message doesn't exist add it */
Lang.push_back(MessageBlock(_name,_val));
}
static void LoadMessageFile(const char * fname) {
if (!fname) return;
if(*fname=='\0') return;//empty string=no languagefile
FILE * mfile=fopen(fname,"rb"); FILE * mfile=fopen(fname,"rb");
/* This should never happen and since other modules depend on this use a normal printf */ /* This should never happen and since other modules depend on this use a normal printf */
if (!mfile) { if (!mfile) {
E_Exit("MSG:Can't load messages: %s",fname); E_Exit("MSG:Can't load messages: %s",fname);
} }
@ -67,15 +97,8 @@ static void LoadMessageFile(char * fname) {
strcpy(name,linein+1); strcpy(name,linein+1);
/* End of string marker */ /* End of string marker */
} else if (linein[0]=='.') { } else if (linein[0]=='.') {
/* Save the string internally */ /* Replace/Add the string to the internal langaugefile */
size_t total=sizeof(MessageBlock)+strlen(name)+1+strlen(string)+1; MSG_Replace(name,string);
MessageBlock * newblock=(MessageBlock *)malloc(total);
newblock->name=((char *)newblock)+sizeof(MessageBlock);
newblock->string=newblock->name+strlen(name)+1;
strcpy(newblock->name,name);
strcpy(newblock->string,string);
newblock->next=first_message;
first_message=newblock;
} else { } else {
/* Normal string to be added */ /* Normal string to be added */
strcat(string,linein); strcat(string,linein);
@ -85,23 +108,29 @@ static void LoadMessageFile(char * fname) {
fclose(mfile); fclose(mfile);
} }
const char * MSG_Get(char const * msg) {
char * MSG_Get(char * msg) { for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
MessageBlock * index=first_message; if((*tel).name==msg)
while (index) { {
if (!strcmp(msg,index->name)) return index->string; return (*tel).val.c_str();
index=index->next;
} }
return "Message not found"; }
return "Message not Found!\n";
} }
void MSG_Write(const char * location) {
void MSG_Init(void) { FILE* out=fopen(location,"w+b");
/* Load the messages from "dosbox.lang file" */ if(out==NULL) return;//maybe an error?
first_message=0; for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
char filein[CROSS_LEN]; fprintf(out,":%s\n%s.\n",(*tel).name.c_str(),(*tel).val.c_str());
strcpy(filein,dosbox_basedir); }
strcat(filein,"dosbox.lang"); fclose(out);
LoadMessageFile(filein); }
void MSG_Init(Section_prop * section) {
std::string file_name;
if (control->cmdline->FindString("-lang",file_name)) {
LoadMessageFile(file_name.c_str());
} else LoadMessageFile(section->Get_string("language"));
} }

View File

@ -1,159 +0,0 @@
/*
* Copyright (C) 2002 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <string.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#endif
#include "dosbox.h"
#include "regs.h"
#include "mem.h"
#include "inout.h"
#include "pic.h"
#include "modules.h"
#include "programs.h"
#include "timer.h"
#include "dma.h"
#include "mixer.h"
struct PLUGIN_Function {
char * name;
void * function;
};
struct PLUGIN_Module {
#ifdef WIN32
HINSTANCE handle;
#endif
PLUGIN_Module * next;
};
static PLUGIN_Function functions[]={
"IO_RegisterReadHandler", (void *)IO_RegisterReadHandler,
"IO_RegisterWriteHandler", (void *)IO_RegisterWriteHandler,
"IO_FreeReadHandler", (void *)IO_FreeReadHandler,
"IO_FreeWriteHandler", (void *)IO_FreeWriteHandler,
"IRQ_RegisterEOIHandler", (void *)PIC_RegisterIRQ,
"IRQ_FreeEOIHandler", (void *)PIC_FreeIRQ,
"IRQ_Activate", (void *)PIC_ActivateIRQ,
"IRQ_Deactivate", (void *)PIC_DeActivateIRQ,
"TIMER_RegisterMicroHandler", (void *)TIMER_RegisterMicroHandler,
"TIMER_RegisterTickHandler", (void *)TIMER_RegisterTickHandler,
"DMA_8_Read", (void *)DMA_8_Read,
"DMA_16_Read", (void *)DMA_16_Read,
"DMA_8_Write", (void *)DMA_8_Write,
"DMA_16_Write", (void *)DMA_16_Write,
"MIXER_AddChannel", (void *)MIXER_AddChannel,
"MIXER_SetVolume", (void *)MIXER_SetVolume,
"MIXER_SetFreq", (void *)MIXER_SetFreq,
"MIXER_SetMode", (void *)MIXER_SetMode,
"MIXER_Enable", (void *)MIXER_Enable,
0,0
};
class PLUGIN : public Program {
public:
PLUGIN(PROGRAM_Info * program_info);
void Run(void);
};
PLUGIN::PLUGIN(PROGRAM_Info * info):Program(info) {
}
void PLUGIN::Run(void) {
}
static void PLUGIN_ProgramStart(PROGRAM_Info * info) {
PLUGIN * tempPLUGIN=new PLUGIN(info);
tempPLUGIN->Run();
delete tempPLUGIN;
}
bool PLUGIN_FindFunction(char * name,void * * function) {
/* Run through table and hope to find a match */
Bitu index=0;
while (functions[index].name) {
if (strcmp(functions[index].name,name)==0) {
*function=functions[index].function;
return true;
};
index++;
}
return false;
}
bool PLUGIN_LoadModule(char * name) {
MODULE_StartHandler starter;
#ifdef WIN32
HMODULE module;
module=LoadLibrary(name);
if (!module) return false;
/* Look for the module start functions */
FARPROC address;
address=GetProcAddress(module,MODULE_START_PROC);
starter=(MODULE_StartHandler)address;
#else
//TODO LINUX
#endif
starter(PLUGIN_FindFunction);
return false;
}
void PLUGIN_Init(void) {
PROGRAMS_MakeFile("PLUGIN.COM",PLUGIN_ProgramStart);
// PLUGIN_LoadModule("c:\\dosbox\\testmod.dll");
};

View File

@ -25,6 +25,7 @@
#include "regs.h" #include "regs.h"
#include "support.h" #include "support.h"
#include "cross.h" #include "cross.h"
#include "setup.h"
Bitu call_program; Bitu call_program;
@ -55,30 +56,19 @@ void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main) {
} }
static Bitu PROGRAMS_Handler(void) { static Bitu PROGRAMS_Handler(void) {
/* This sets up everything for a program start up call */ /* This sets up everything for a program start up call */
/* First get the current psp */ PROGRAMS_Main * handler=0; //It will get sneakily itinialized
PROGRAM_Info * info=new PROGRAM_Info; Bitu size=sizeof(PROGRAMS_Main *);
info->psp_seg=dos.psp; /* Read the handler from program code in memory */
MEM_BlockRead(PhysMake(dos.psp,0),&info->psp_copy,sizeof(PSP)); PhysPt reader=PhysMake(dos.psp,256+sizeof(exe_block));
/* Get the file name cmd_line 0 */ HostPt writer=(HostPt)&handler;
PhysPt envblock=PhysMake(info->psp_copy.environment,0); for (;size>0;size--) *writer++=mem_readb(reader++);
do {} while (mem_readw(envblock++)); Program * new_program;
envblock+=3; (*handler)(&new_program);
MEM_StrCopy(envblock,info->full_name,32); new_program->Run();
info->psp_copy.cmdtail.buffer[info->psp_copy.cmdtail.count]=0; delete new_program;
info->cmd_line=info->psp_copy.cmdtail.buffer;
/* Find the program handler somewhere reference in the file */
Bit16u handle;
DOS_OpenFile(info->full_name,0,&handle);
Bit32u pos=sizeof(PROGRAMS_Main *);
DOS_SeekFile(handle,&pos,DOS_SEEK_END);
PROGRAMS_Main * handler;
Bit16u size=sizeof(PROGRAMS_Main *);
DOS_ReadFile(handle,(Bit8u *)&handler,&size);
DOS_CloseFile(handle);
(*handler)(info);
free(info);
return CBRET_NONE; return CBRET_NONE;
}; };
@ -86,11 +76,21 @@ static Bitu PROGRAMS_Handler(void) {
/* Main functions used in all program */ /* Main functions used in all program */
Program::Program(PROGRAM_Info * program_info) { Program::Program() {
prog_info=program_info; /* Find the command line and setup the PSP */
psp = new DOS_PSP(dos.psp);
/* Scan environment for filename */
char * envscan=(char *)HostMake(psp->GetEnvironment(),0);
while (*envscan) envscan+=strlen(envscan)+1;
envscan+=3;
CommandTail tail;
MEM_BlockRead(PhysMake(dos.psp,128),&tail,128);
if (tail.count<127) tail.buffer[tail.count]=0;
else tail.buffer[126]=0;
cmd = new CommandLine(envscan,tail.buffer);
} }
void Program::WriteOut(char * format,...) { void Program::WriteOut(const char * format,...) {
char buf[1024]; char buf[1024];
va_list msg; va_list msg;
@ -103,72 +103,118 @@ void Program::WriteOut(char * format,...) {
} }
char * Program::GetEnvStr(char * env_str) { bool Program::GetEnvStr(const char * entry,std::string & result) {
/* Walk through the internal environment and see for a match */ /* Walk through the internal environment and see for a match */
/* Taking some short cuts here to not fuck around with memory structure */ PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
char env_string[1024];
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0); result.erase();
size_t len=strlen(env_str); if (!entry[0]) return false;
while (*envstart) { do {
if (strncasecmp(env_str,envstart,len)==0 && envstart[len]=='=') { MEM_StrCopy(env_read,env_string,1024);
return envstart; if (!env_string[0]) return false;
} env_read+=strlen(env_string)+1;
envstart+=strlen(envstart)+1; if (!strchr(env_string,'=')) continue;
} if (strncasecmp(entry,env_string,strlen(entry))!=0) continue;
return 0; result=env_string;
return true;
} while (1);
return false;
}; };
char * Program::GetEnvNum(Bit32u num) { bool Program::GetEnvNum(Bitu num,std::string & result) {
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0); char env_string[1024];
while (*envstart) { PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
if (!num) return envstart; do {
envstart+=strlen(envstart)+1; MEM_StrCopy(env_read,env_string,1024);
if (!env_string[0]) break;
if (!num) { result=env_string;return true;}
env_read+=strlen(env_string)+1;
num--; num--;
} } while (1);
return 0; return false;
} }
Bit32u Program::GetEnvCount(void) { Bitu Program::GetEnvCount(void) {
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0); PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
Bit32u num=0; Bitu num=0;
while (*envstart) { while (mem_readb(env_read)!=0) {
envstart+=strlen(envstart)+1; for (;mem_readb(env_read);env_read++) {};
env_read++;
num++; num++;
} }
return num; return num;
} }
bool Program::SetEnv(char * env_entry,char * new_string) { bool Program::SetEnv(const char * entry,const char * new_string) {
MCB * env_mcb=(MCB *)HostMake(prog_info->psp_copy.environment-1,0); PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
upcase(env_entry); PhysPt env_write=env_read;
Bit32u env_size=env_mcb->size*16; char env_string[1024];
if (!env_size) E_Exit("SHELL:Illegal environment size"); do {
/* First try to find the old entry */ MEM_StrCopy(env_read,env_string,1024);
size_t len=strlen(env_entry); if (!env_string[0]) break;
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0); env_read+=strlen(env_string)+1;
while (*envstart) { if (!strchr(env_string,'=')) continue; /* Remove corrupt entry? */
if (strncasecmp(env_entry,envstart,len)==0 && envstart[len]=='=') { if ((strncasecmp(entry,env_string,strlen(entry))==0) &&
/* Now remove this entry */ env_string[strlen(entry)]=='=') continue;
memmove(envstart,envstart+strlen(envstart)+1,env_size); MEM_BlockWrite(env_write,env_string,strlen(env_string)+1);
} else { env_write+=strlen(env_string)+1;
envstart+=strlen(envstart)+1; } while (1);
env_size-=(strlen(envstart)+1); /* TODO Maybe save the program name sometime. not really needed though */
/* Save the new entry */
if (new_string[0]) {
sprintf(env_string,"%s=%s",entry,new_string);
MEM_BlockWrite(env_write,env_string,strlen(env_string)+1);
env_write+=strlen(env_string)+1;
} }
} /* Clear out the final piece of the environment */
/* Now add the string if there is space available */ mem_writed(env_write,0);
if (env_size<(strlen(env_entry)+strlen(new_string)+2)) return false;
if (!*new_string) return true;
sprintf(envstart,"%s=%s",env_entry,new_string);
envstart+=strlen(envstart)+1;
*envstart++=0;*envstart++=0;*envstart++=0;
return true; return true;
} }
//TODO Hash table :) class CONFIG : public Program {
public:
void Run(void);
};
void MSG_Write(const char *);
void CONFIG::Run(void) {
FILE * f;
if (cmd->FindString("-writeconf",temp_line,true)) {
f=fopen(temp_line.c_str(),"wb+");
if (!f) {
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
return;
}
fclose(f);
control->PrintConfig(temp_line.c_str());
return;
}
if (cmd->FindString("-writelang",temp_line,true)) {
f=fopen(temp_line.c_str(),"wb+");
if (!f) {
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
return;
}
fclose(f);
MSG_Write(temp_line.c_str());
return;
}
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
}
void PROGRAMS_Init(void) { static void CONFIG_ProgramStart(Program * * make) {
*make=new CONFIG;
}
void PROGRAMS_Init(Section* sec) {
/* Setup a special callback to start virtual programs */ /* Setup a special callback to start virtual programs */
call_program=CALLBACK_Allocate(); call_program=CALLBACK_Allocate();
CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF); CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF);
PROGRAMS_MakeFile("CONFIG.COM",CONFIG_ProgramStart);
MSG_Add("PROGRAM_CONFIG_FILE_ERROR","Can't open file %s\n");
MSG_Add("PROGRAM_CONFIG_USAGE","Config tool:\nUse -writeconf filename to write the current config.\nUse -writelang filename to write the current language strings.\n");
} }

View File

@ -19,11 +19,353 @@
#include "dosbox.h" #include "dosbox.h"
#include "cross.h" #include "cross.h"
#include "setup.h" #include "setup.h"
#include <fstream>
#include <string>
#include <list>
#include <stdlib.h>
#include <stdio.h>
#include "support.h"
void SETUP_AddBoolHandler() { using namespace std;
}; void Prop_int::SetValue(char* input){
input=trim(input);
__value._int= atoi(input);
}
void Prop_string::SetValue(char* input){
input=trim(input);
__value._string->assign(input);
}
void Prop_bool::SetValue(char* input){
input=trim(input);
if((input[0]=='0') ||(input[0]=='D')||( (input[0]=='O') && (input[0]=='F'))||(input[0]=='f')){
__value._bool=false;
}else{
__value._bool=true;
}
}
void Prop_hex::SetValue(char* input){
input=trim(input);
if(!sscanf(input,"%X",&(__value._hex))) __value._hex=0;
}
void Prop_int::GetValuestring(char* str){
sprintf(str,"%d",__value._int);
}
void Prop_string::GetValuestring(char* str){
sprintf(str,"%s",__value._string->c_str());
}
void Prop_bool::GetValuestring(char* str){
sprintf(str,"%s",__value._bool?"true":"false");
}
void Prop_hex::GetValuestring(char* str){
sprintf(str,"%X",__value._hex);
}
void Section_prop::Add_int(const char* _propname, int _value) {
Property* test=new Prop_int(_propname,_value);
properties.push_back(test);
}
void Section_prop::Add_string(const char* _propname, char* _value) {
Property* test=new Prop_string(_propname,_value);
properties.push_back(test);
}
void Section_prop::Add_bool(const char* _propname, bool _value) {
Property* test=new Prop_bool(_propname,_value);
properties.push_back(test);
}
void Section_prop::Add_hex(const char* _propname, int _value) {
Property* test=new Prop_hex(_propname,_value);
properties.push_back(test);
}
int Section_prop::Get_int(const char* _propname){
for(it tel=properties.begin();tel!=properties.end();tel++){
if((*tel)->propname==_propname){
return ((*tel)->GetValue())._int;
}
}
return 0;
}
bool Section_prop::Get_bool(const char* _propname){
for(it tel=properties.begin();tel!=properties.end();tel++){
if((*tel)->propname==_propname){
return ((*tel)->GetValue())._bool;
}
}
return false;
}
const char* Section_prop::Get_string(const char* _propname){
for(it tel=properties.begin();tel!=properties.end();tel++){
if((*tel)->propname==_propname){
return ((*tel)->GetValue())._string->c_str();
}
}
return NULL;
}
int Section_prop::Get_hex(const char* _propname){
for(it tel=properties.begin();tel!=properties.end();tel++){
if((*tel)->propname==_propname){
return ((*tel)->GetValue())._hex;
}
}
return 0;
}
void Section_prop::HandleInputline(char *gegevens){
char * rest=strrchr(gegevens,'=');
*rest=0;
gegevens=trim(gegevens);
for(it tel=properties.begin();tel!=properties.end();tel++){
if(!strcasecmp((*tel)->propname.c_str(),gegevens)){
(*tel)->SetValue(rest+1);
return;
}
}
}
void Section_prop::PrintData(FILE* outfile){
char temp[1000]; /* Should be enough for the properties */
/* Now print out the individual section entries */
for(it tel=properties.begin();tel!=properties.end();tel++){
(*tel)->GetValuestring(temp);
fprintf(outfile,"%s=%s\n",(*tel)->propname.c_str(),temp);
}
}
void Section_line::HandleInputline(char* line){
data+=line;
data+="\n";
}
void Section_line::PrintData(FILE* outfile) {
fprintf(outfile,"%s",data.c_str());
}
void Config::PrintConfig(const char* configfilename){
char temp[50];
FILE* outfile=fopen(configfilename,"w+b");
if(outfile==NULL) return;
for (it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){
/* Print out the Section header */
strcpy(temp,(*tel)->sectionname.c_str());
lowcase(temp);
fprintf(outfile,"[%s]\n",temp);
upcase(temp);
strcat(temp,"_CONFIGFILE_HELP");
fprintf(outfile,"# %s",MSG_Get(temp));
(*tel)->PrintData(outfile);
fprintf(outfile,"\n"); /* Always an empty line between sections */
}
fclose(outfile);
}
Section* Config::AddSection(const char* _name,void (*_initfunction)(Section*)){
Section* blah = new Section(_name);
blah->AddInitFunction(_initfunction);
sectionlist.push_back(blah);
return blah;
}
Section_prop* Config::AddSection_prop(const char* _name,void (*_initfunction)(Section*)){
Section_prop* blah = new Section_prop(_name);
blah->AddInitFunction(_initfunction);
sectionlist.push_back(blah);
return blah;
}
Section_line* Config::AddSection_line(const char* _name,void (*_initfunction)(Section*)){
Section_line* blah = new Section_line(_name);
blah->AddInitFunction(_initfunction);
sectionlist.push_back(blah);
return blah;
}
void Config::Init(){
for (it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){
(*tel)->ExecuteInit();
}
}
Config::~Config() {
reverse_it cnt=sectionlist.rbegin();
while (cnt!=sectionlist.rend()) {
delete (*cnt);
cnt++;
}
}
Section* Config::GetSection(const char* _sectionname){
for (it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){
if (!strcasecmp((*tel)->sectionname.c_str(),_sectionname)) return (*tel);
}
return NULL;
}
void Config::ParseConfigFile(const char* configfilename){
ifstream in(configfilename);
if (!in) {
LOG_MSG("CONFIG:Can't find config file %s, using default settings",configfilename);
return;
}
char gegevens[150];
Section* currentsection;
while (in) {
in.getline(gegevens,150);
char* temp;
switch(gegevens[0]){
case '%':
case '\0':
case '\n':
case '#':
case ' ':
continue;
break;
case '[':
temp = strrchr(gegevens,']');
*temp=0;
currentsection=GetSection(&gegevens[1]);
break;
default:
try{
currentsection->HandleInputline(gegevens);
}catch(const char* message){
message=0;
//EXIT with message
}
break;
}
}
}
void Config::SetStartUp(void (*_function)(void)) {
_start_function=_function;
}
void Config::StartUp(void) {
(*_start_function)();
}
bool CommandLine::FindExist(char * name,bool remove) {
cmd_it it;
if (!(FindEntry(name,it,false))) return false;
if (remove) cmds.erase(it);
return true;
}
bool CommandLine::FindHex(char * name,int & value,bool remove) {
cmd_it it,it_next;
if (!(FindEntry(name,it,true))) return false;
it_next=it;it_next++;
sscanf((*it_next).c_str(),"%X",&value);
if (remove) cmds.erase(it,++it_next);
return true;
}
bool CommandLine::FindInt(char * name,int & value,bool remove) {
cmd_it it,it_next;
if (!(FindEntry(name,it,true))) return false;
it_next=it;it_next++;
value=atoi((*it_next).c_str());
if (remove) cmds.erase(it,++it_next);
return true;
}
bool CommandLine::FindString(char * name,std::string & value,bool remove) {
cmd_it it,it_next;
if (!(FindEntry(name,it,true))) return false;
it_next=it;it_next++;
value=*it_next;
if (remove) cmds.erase(it,++it_next);
return true;
}
bool CommandLine::FindCommand(int which,std::string & value) {
if (which<1) return false;
if (which>cmds.size()) return false;
cmd_it it=cmds.begin();
for (;which>1;which--) it++;
value=(*it);
return true;
}
bool CommandLine::FindEntry(char * name,cmd_it & it,bool neednext) {
for (it=cmds.begin();it!=cmds.end();it++) {
if (!strcasecmp((*it).c_str(),name)) {
cmd_it itnext=it;itnext++;
if (neednext && (itnext==cmds.end())) return false;
return true;
}
}
return false;
}
bool CommandLine::FindStringBegin(char * begin,std::string & value, bool remove) {
cmd_it it;
for (it=cmds.begin();it!=cmds.end();it++) {
if (strncmp(begin,(*it).c_str(),strlen(begin))==0) {
value=((*it).c_str()+strlen(begin));
return true;
}
}
return false;
}
int CommandLine::GetCount(void) {
return cmds.size();
}
CommandLine::CommandLine(int argc,char * argv[]) {
if (argc>0) {
file_name=argv[0];
}
int i=1;
while (i<argc) {
cmds.push_back(argv[i]);
i++;
}
}
CommandLine::CommandLine(char * name,char * cmdline) {
if (name) file_name=name;
/* Parse the cmds and put them in the list */
bool inword,inquote;char c;
inword=false;inquote=false;
std::string str;
while ((c=*cmdline)!=0) {
if (inquote) {
if (c!='"') str+=c;
else {
inquote=false;
cmds.push_back(str);
str.erase();
}
}else if (inword) {
if (c!=' ') str+=c;
else {
inword=false;
cmds.push_back(str);
str.erase();
}
}
else if (c=='"') { inquote=true;}
else if (c!=' ') { str+=c;inword=true;}
cmdline++;
}
if (inword || inquote) cmds.push_back(str);
}

View File

@ -82,49 +82,6 @@ char *trim(char *str) {
return ltrim(str); return ltrim(str);
} }
bool wildcmp(char *wild, char *string)
{
// special case - Everything goes through
if (strcmp(wild,"*")==0) return true;
while (*wild) {
if (*wild=='*') {
// Any other chars after that ?
if ((wild[1]!=0) && (wild[1]!='.')) {
// search string
while ((*string) && (*string!='.')) {
// thats the char ? then exit
if (toupper(*string)==toupper(wild[1])) break;
string++;
};
} else {
// skip to extension or end
while (*string && (*string!='.')) string++;
}
wild++;
} else if (*string=='.') {
// only valid : '?' & '*'
while (*wild && (*wild!='.')) {
if ((*wild!='?') && (*wild!='*')) return false;
wild++;
}
if (*wild) wild++;
string++;
} else if ((*wild!='?') && (toupper(*string)!=toupper(*wild))) {
// no match
return false;
} else {
wild++;
string++;
}
}
return ((*string==0) && (*wild==0));
};
bool ScanCMDBool(char * cmd,char * check) { bool ScanCMDBool(char * cmd,char * check) {
char * scan=cmd;size_t c_len=strlen(check); char * scan=cmd;size_t c_len=strlen(check);
@ -215,22 +172,17 @@ void S_Warn(char * format,...) {
#endif #endif
} }
static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95)
void E_Exit(char * format,...) { void E_Exit(char * format,...) {
if(errorlevel>=1) {
char buf[1024];
// SysShutDown();
va_list msg; va_list msg;
strcpy(buf,"EXIT:");
va_start(msg,format); va_start(msg,format);
vsprintf(buf+strlen(buf),format,msg); vsprintf(buf,format,msg);
va_end(msg); va_end(msg);
strcat(buf,"\n"); strcat(buf,"\n");
printf(buf); } else {
printf("Press ENTER to stop\n"); strcpy(buf,"an unsupported feature\n");
fgetc(stdin); }
GFX_Stop(); throw(buf);
exit(2); }
};

View File

@ -1,6 +1,6 @@
#define INLINE __forceinline #define INLINE __forceinline
#define VERSION "0.55" #define VERSION "0.56"
#define GCC_ATTRIBUTE(x) /* attribute not supported */ #define GCC_ATTRIBUTE(x) /* attribute not supported */

View File

@ -19,7 +19,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include "setup.h"
#include "shell_inc.h" #include "shell_inc.h"
Bitu call_shellstop; Bitu call_shellstop;
@ -28,10 +28,8 @@ static Bitu shellstop_handler(void) {
return CBRET_STOP; return CBRET_STOP;
} }
static void SHELL_ProgramStart(PROGRAM_Info * info) { static void SHELL_ProgramStart(Program * * make) {
DOS_Shell * tempshell=new DOS_Shell(info); *make=new DOS_Shell;
tempshell->Run();
delete tempshell;
} }
#define AUTOEXEC_SIZE 4096 #define AUTOEXEC_SIZE 4096
@ -53,7 +51,7 @@ void SHELL_AddAutoexec(char * line,...) {
} }
DOS_Shell::DOS_Shell(PROGRAM_Info * info):Program(info) { DOS_Shell::DOS_Shell():Program(){
input_handle=STDIN; input_handle=STDIN;
echo=true; echo=true;
exit=false; exit=false;
@ -96,16 +94,19 @@ void DOS_Shell::ParseLine(char * line) {
void DOS_Shell::Run(void) { void DOS_Shell::Run(void) {
/* Check for a direct Command */ char input_line[CMD_MAXLINE];
if (strncasecmp(prog_info->cmd_line,"/C ",3)==0) { std::string line;
ParseLine(prog_info->cmd_line+3); if (cmd->FindString("/C",line,true)) {
strcpy(input_line,line.c_str());
line.erase();
return; return;
} }
/* Start a normal shell and check for a first command init */ /* Start a normal shell and check for a first command init */
WriteOut(MSG_Get("SHELL_STARTUP")); WriteOut(MSG_Get("SHELL_STARTUP"));
char input_line[CMD_MAXLINE]; if (cmd->FindString("/INIT",line,true)) {
if (strncasecmp(prog_info->cmd_line,"/INIT ",6)==0) { strcpy(input_line,line.c_str());
ParseLine(prog_info->cmd_line+6); line.erase();
ParseLine(input_line);
} }
do { do {
if (bf && bf->ReadLine(input_line)) { if (bf && bf->ReadLine(input_line)) {
@ -132,51 +133,138 @@ void DOS_Shell::SyntaxError(void) {
void AUTOEXEC_Init(Section * sec) {
MSG_Add("AUTOEXEC_CONFIGFILE_HELP","Add here the lines you want to execute on startup.\n");
/* Register a virtual AUOEXEC.BAT file */
Section_line * section=static_cast<Section_line *>(sec);
char * extra=(char *)section->data.c_str();
if (extra) SHELL_AddAutoexec(extra);
/* Check to see for extra command line options to be added */
std::string line;
while (control->cmdline->FindString("-c",line,true)) {
SHELL_AddAutoexec((char *)line.c_str());
}
/* Check for first command being a directory or file */
char buffer[CROSS_LEN];
if (control->cmdline->FindCommand(1,line)) {
struct stat test;
strcpy(buffer,line.c_str());
if (stat(buffer,&test)) {
getcwd(buffer,CROSS_LEN);
strcat(buffer,line.c_str());
if (stat(buffer,&test)) goto nomount;
}
if (test.st_mode & S_IFDIR) {
SHELL_AddAutoexec("MOUNT C %s",buffer);
SHELL_AddAutoexec("C:");
} else {
char * name=strrchr(buffer,CROSS_FILESPLIT);
if (!name) goto nomount;
*name++=0;
if (access(buffer,F_OK)) goto nomount;
SHELL_AddAutoexec("MOUNT C %s",buffer);
SHELL_AddAutoexec("C:");
SHELL_AddAutoexec(name);
}
}
nomount:
VFILE_Register("AUTOEXEC.BAT",(Bit8u *)autoexec_data,strlen(autoexec_data));
}
static char * path_string="PATH=Z:\\";
static char * comspec_string="COMSPEC=Z:\\COMMAND.COM";
static char * full_name="Z:\\COMMAND.COM";
static char * init_line="/INIT AUTOEXEC.BAT";
void SHELL_Init() { void SHELL_Init() {
/* Add messages */
MSG_Add("SHELL_CMD_HELP","supported commands are:\n");
MSG_Add("SHELL_CMD_ECHO_ON","ECHO is on\n");
MSG_Add("SHELL_CMD_ECHO_OFF","ECHO is off\n");
MSG_Add("SHELL_ILLEGAL_SWITCH","Illegal switch: %s\n");
MSG_Add("SHELL_CMD_CHDIR_ERROR","Unable to change to: %s\n");
MSG_Add("SHELL_CMD_MKDIR_ERROR","Unable to make: %s\n");
MSG_Add("SHELL_CMD_RMDIR_ERROR","Unable to remove: %\n");
MSG_Add("SHELL_SYNTAXERROR","The syntax of the command is incorrect.\n");
MSG_Add("SHELL_CMD_SET_NOT_SET","Environment variable %s not defined\n");
MSG_Add("SHELL_CMD_SET_OUT_OF_SPACE","Not enough environment space left.\n");
MSG_Add("SHELL_CMD_IF_EXIST_MISSING_FILENAME","IF EXIST: Missing filename.\n");
MSG_Add("SHELL_CMD_IF_ERRORLEVEL_MISSING_NUMBER","IF ERRORLEVEL: Missing number.\n");
MSG_Add("SHELL_CMD_IF_ERRORLEVEL_INVALID_NUMBER","IF ERRORLEVEL: Invalid number.\n");
MSG_Add("SHELL_CMD_GOTO_MISSING_LABEL","No label supplied to GOTO command.\n");
MSG_Add("SHELL_CMD_GOTO_LABEL_NOT_FOUND","GOTO: Label %s not found.\n");
MSG_Add("SHELL_CMD_FILE_NOT_FOUND","File %s not found.\n");
MSG_Add("SHELL_CMD_FILE_EXISTS","File %s already exists.\n");
MSG_Add("SHELL_CMD_DIR_INTRO","Directory of %s.\n");
MSG_Add("SHELL_CMD_DIR_PATH_ERROR","Illegal Path\n");
MSG_Add("SHELL_CMD_DIR_BYTES_USED","%5d File(s) %17s Bytes\n");
MSG_Add("SHELL_CMD_DIR_BYTES_FREE","%5d Dir(s) %17s Bytes free\n");
MSG_Add("SHELL_EXECUTE_DRIVE_NOT_FOUND","Drive %c does not exist!\n");
MSG_Add("SHELL_EXECUTE_ILLEGAL_COMMAND","Illegal command: %s.\n");
MSG_Add("SHELL_STARTUP","DOSBox Shell v" VERSION "\nFor Help and supported commands type: HELP\n\nHAVE FUN!\nThe DOSBox Team\n\n");
MSG_Add("SHELL_CMD_CHDIR_HELP","Change Directory.\n");
MSG_Add("SHELL_CMD_CLS_HELP","Clear screen.\n");
MSG_Add("SHELL_CMD_DIR_HELP","Directory View.\n");
MSG_Add("SHELL_CMD_ECHO_HELP","Display messages and enable/disable command echoing.\n");
MSG_Add("SHELL_CMD_EXIT_HELP","Exit from the shell.\n");
MSG_Add("SHELL_CMD_HELP_HELP","Show help.\n");
MSG_Add("SHELL_CMD_MKDIR_HELP","Make Directory.\n");
MSG_Add("SHELL_CMD_RMDIR_HELP","Remove Directory.\n");
MSG_Add("SHELL_CMD_SET_HELP","Change environment variables.\n");
MSG_Add("SHELL_CMD_IF_HELP","Performs conditional processing in batch programs.\n");
MSG_Add("SHELL_CMD_GOTO_HELP","Jump to a labeled line in a batch script.\n");
MSG_Add("SHELL_CMD_TYPE_HELP","Display the contents of a text-file.\n");
MSG_Add("SHELL_CMD_REM_HELP","Add comments in a batch file.\n");
/* Regular startup */
call_shellstop=CALLBACK_Allocate(); call_shellstop=CALLBACK_Allocate();
CALLBACK_Setup(call_shellstop,shellstop_handler,CB_IRET); CALLBACK_Setup(call_shellstop,shellstop_handler,CB_IRET);
PROGRAMS_MakeFile("COMMAND.COM",SHELL_ProgramStart); PROGRAMS_MakeFile("COMMAND.COM",SHELL_ProgramStart);
/* Now call up the shell for the first time */ /* Now call up the shell for the first time */
Bit16u psp_seg=DOS_GetMemory(16); Bit16u psp_seg=DOS_GetMemory(16+1)+1;
Bit16u env_seg=DOS_GetMemory(1+(4096/16)); Bit16u env_seg=DOS_GetMemory(1+(4096/16))+1;
Bit16u stack_seg=DOS_GetMemory(2048/16); Bit16u stack_seg=DOS_GetMemory(2048/16);
SegSet16(ss,stack_seg); SegSet16(ss,stack_seg);
reg_sp=2046; reg_sp=2046;
/* Setup a fake MCB for the environment */ /* Setup MCB and the environment */
MCB * env_mcb=(MCB *)HostMake(env_seg,0); MCB * env_mcb=(MCB *)HostMake(env_seg-1,0);
env_mcb->psp_segment=psp_seg; env_mcb->psp_segment=psp_seg;
env_mcb->size=4096/16; env_mcb->size=4096/16;
real_writed(env_seg+1,0,0); PhysPt env_write=PhysMake(env_seg,0);
MEM_BlockWrite(env_write,path_string,strlen(path_string)+1);
env_write+=strlen(path_string)+1;
MEM_BlockWrite(env_write,comspec_string,strlen(comspec_string)+1);
env_write+=strlen(comspec_string)+1;
mem_writeb(env_write++,0);
mem_writew(env_write,1);
env_write+=2;
MEM_BlockWrite(env_write,full_name,strlen(full_name)+1);
PSP * psp=(PSP *)HostMake(psp_seg,0); DOS_PSP psp(psp_seg);
Bit32u i; psp.MakeNew(0);
for (i=0;i<20;i++) psp->files[i]=0xff; psp.SetFileHandle(STDIN ,DOS_FindDevice("CON"));
psp->files[STDIN]=DOS_FindDevice("CON"); psp.SetFileHandle(STDOUT,DOS_FindDevice("CON"));
psp->files[STDOUT]=DOS_FindDevice("CON"); psp.SetFileHandle(STDERR,DOS_FindDevice("CON"));
psp->files[STDERR]=DOS_FindDevice("CON"); psp.SetFileHandle(STDAUX,DOS_FindDevice("CON"));
psp->files[STDAUX]=DOS_FindDevice("CON"); psp.SetFileHandle(STDNUL,DOS_FindDevice("CON"));
psp->files[STDNUL]=DOS_FindDevice("CON"); psp.SetFileHandle(STDPRN,DOS_FindDevice("CON"));
psp->files[STDPRN]=DOS_FindDevice("CON"); psp.SetParent(psp_seg);
psp->max_files=20; /* Set the environment */
psp->file_table=RealMake(psp_seg,offsetof(PSP,files)); psp.SetEnvironment(env_seg);
/* Save old DTA in psp */ /* Set the command line for the shell start up */
psp->dta=dos.dta; CommandTail tail;
/* Set the environment and clear it */ tail.count=strlen(init_line);
psp->environment=env_seg+1; strcpy(tail.buffer,init_line);
mem_writew(Real2Phys(RealMake(env_seg+1,0)),0); MEM_BlockWrite(PhysMake(psp_seg,128),&tail,128);
/* Setup internal DOS Variables */ /* Setup internal DOS Variables */
dos.dta=RealMake(psp_seg,0x80); dos.dta=psp.GetDTA();
dos.psp=psp_seg; dos.psp=psp_seg;
PROGRAM_Info info;
strcpy(info.full_name,"Z:\\COMMAND.COM");
info.psp_seg=psp_seg;
MEM_BlockRead(PhysMake(dos.psp,0),&info.psp_copy,sizeof(PSP));
char line[256];
strcpy(line,"/INIT Z:\\AUTOEXEC.BAT");
info.cmd_line=line;
/* Handle the last AUTOEXEC.BAT Setup stuff */ Program * new_program;
VFILE_Register("AUTOEXEC.BAT",(Bit8u *)autoexec_data,strlen(autoexec_data)); SHELL_ProgramStart(&new_program);
SHELL_ProgramStart(&info); new_program->Run();
delete new_program;
} }

View File

@ -24,27 +24,18 @@
BatchFile::BatchFile(DOS_Shell * host,char * name, char * cmd_line) { BatchFile::BatchFile(DOS_Shell * host,char * name, char * cmd_line) {
/* Go through the command line */
char * cmd_write=cmd_buffer;
prev=host->bf; prev=host->bf;
echo=host->echo; echo=host->echo;
shell=host; shell=host;
cmd_count=0; cmd=new CommandLine(0,cmd_line);
while (*cmd_line || (cmd_count<CMD_MAXCMDS)) {
cmd_words[cmd_count]=cmd_write;
for (;(*cmd_line!=' ' && *cmd_line!=0);*cmd_write++=*cmd_line++);
*cmd_write++=0;
cmd_line=trim(cmd_line);
cmd_count++;
}
if (!DOS_OpenFile(name,0,&file_handle)) { if (!DOS_OpenFile(name,0,&file_handle)) {
//TODO Come up with something better //TODO Come up with something better
E_Exit("SHELL:Can't open BatchFile"); E_Exit("SHELL:Can't open BatchFile");
} }
line_count=0;
}; };
BatchFile::~BatchFile() { BatchFile::~BatchFile() {
delete cmd;
DOS_CloseFile(file_handle); DOS_CloseFile(file_handle);
shell->bf=prev; shell->bf=prev;
shell->echo=echo; shell->echo=echo;
@ -63,8 +54,8 @@ emptyline:
*cmd_write++=c; *cmd_write++=c;
} }
} while (c!='\n' && n); } while (c!='\n' && n);
*cmd_write++=0; *cmd_write=0;
if (!n) { if (!n && cmd_write==temp) {
delete this; delete this;
return false; return false;
} }
@ -78,28 +69,50 @@ emptyline:
env_write=env_name; env_write=env_name;
if (*cmd_read=='%') { if (*cmd_read=='%') {
cmd_read++; cmd_read++;
/* Find the fullstring of this */ if (cmd_read[0]=='%') {
cmd_read++;
*cmd_write++='%';
}
size_t len=strspn(cmd_read,"0123456789");
if (len) {
memcpy(env_name,cmd_read,len);
env_name[len]=0;cmd_read+=len;
len=atoi(env_name);
if (cmd->GetCount()<len) continue;
std::string word;
if (!cmd->FindCommand(len,word)) continue;
strcpy(cmd_write,word.c_str());
cmd_write+=strlen(word.c_str());
continue; continue;
} else {
/* Not a command line number has to be an environment */
char * first=strchr(cmd_read,'%');
if (!first) continue; *first++=0;
std::string temp;
if (shell->GetEnvStr(cmd_read,temp)) {
char * equals=strchr(temp.c_str(),'=');
if (!equals) continue;
equals++;
strcpy(cmd_write,equals);
cmd_write+=strlen(equals);
}
cmd_read=first;
}
} else { } else {
*cmd_write++=*cmd_read++; *cmd_write++=*cmd_read++;
} }
*cmd_write=0;
} }
*cmd_write=0;
return true; return true;
} }
bool BatchFile::Goto(char * where) { bool BatchFile::Goto(char * where) {
Bit32u pos=0; Bit32u pos=0;
char cmd[CMD_MAXLINE]; char cmd[CMD_MAXLINE];
char * cmd_write; char * cmd_write;
DOS_SeekFile(file_handle,&pos,DOS_SEEK_SET); DOS_SeekFile(file_handle,&pos,DOS_SEEK_SET);
/* Scan till we have a match or return false*/ /* Scan till we have a match or return false */
Bit8u c;Bit16u n; Bit8u c;Bit16u n;
again: again:
cmd_write=cmd; cmd_write=cmd;

View File

@ -24,19 +24,21 @@
static SHELL_Cmd cmd_list[]={ static SHELL_Cmd cmd_list[]={
"CD", 0, &DOS_Shell::CMD_CHDIR, "Change Directory.", "CD", 0, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP",
"CLS", 0, &DOS_Shell::CMD_CLS, "Clear screen.", "CLS", 0, &DOS_Shell::CMD_CLS, "SHELL_CMD_CLS_HELP",
// "COPY", 0, &DOS_Shell::CMD_COPY, "Copy Files.", // "COPY", 0, &DOS_Shell::CMD_COPY, "Copy Files.",
"DIR", 0, &DOS_Shell::CMD_DIR, "Directory View.", "DIR", 0, &DOS_Shell::CMD_DIR, "SHELL_CMD_DIR_HELP",
"ECHO", 0, &DOS_Shell::CMD_ECHO, "Display messages and enable/disable command echoing.", "ECHO", 0, &DOS_Shell::CMD_ECHO, "SHELL_CMD_ECHO_HELP",
"EXIT", 0, &DOS_Shell::CMD_EXIT, "Exit from the shell.", "EXIT", 0, &DOS_Shell::CMD_EXIT, "SHELL_CMD_EXIT_HELP",
"HELP", 0, &DOS_Shell::CMD_HELP, "Show help.", "HELP", 0, &DOS_Shell::CMD_HELP, "SHELL_CMD_HELP_HELP",
"MD", 0, &DOS_Shell::CMD_MKDIR, "Make Directory.", "MD", 0, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP",
"RD", 0, &DOS_Shell::CMD_RMDIR, "Remove Directory.", "RD", 0, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP",
"SET", 0, &DOS_Shell::CMD_SET, "Change environment variables.", "SET", 0, &DOS_Shell::CMD_SET, "SHELL_CMD_SET_HELP",
"IF", 0, &DOS_Shell::CMD_IF, "Performs conditional processing in batch programs.", "IF", 0, &DOS_Shell::CMD_IF, "SHELL_CMD_IF_HELP",
"GOTO", 0, &DOS_Shell::CMD_GOTO, "Jump to a labeled line in a batch script.", "GOTO", 0, &DOS_Shell::CMD_GOTO, "SHELL_CMD_GOTO_HELP",
"TYPE", 0, &DOS_Shell::CMD_TYPE, "Display the contents of a text-file.", "TYPE", 0, &DOS_Shell::CMD_TYPE, "SHELL_CMD_TYPE_HELP",
"REM", 0, &DOS_Shell::CMD_REM, "SHELL_CMD_REM_HELP",
/* /*
"CHDIR", 0, &DOS_Shell::CMD_CHDIR, "Change Directory", "CHDIR", 0, &DOS_Shell::CMD_CHDIR, "Change Directory",
"MKDIR", 0, &DOS_Shell::CMD_MKDIR, "Make Directory", "MKDIR", 0, &DOS_Shell::CMD_MKDIR, "Make Directory",
@ -63,7 +65,6 @@ void DOS_Shell::DoCommand(char * line) {
Bit32u cmd_index=0; Bit32u cmd_index=0;
while (cmd_list[cmd_index].name) { while (cmd_list[cmd_index].name) {
if (strcasecmp(cmd_list[cmd_index].name,cmd)==0) { if (strcasecmp(cmd_list[cmd_index].name,cmd)==0) {
//TODO CHECK Flags
(this->*(cmd_list[cmd_index].handler))(line); (this->*(cmd_list[cmd_index].handler))(line);
return; return;
} }
@ -84,7 +85,7 @@ void DOS_Shell::CMD_HELP(char * args){
WriteOut(MSG_Get("SHELL_CMD_HELP")); WriteOut(MSG_Get("SHELL_CMD_HELP"));
Bit32u cmd_index=0; Bit32u cmd_index=0;
while (cmd_list[cmd_index].name) { while (cmd_list[cmd_index].name) {
if (!cmd_list[cmd_index].flags) WriteOut("%-8s %s\n",cmd_list[cmd_index].name,cmd_list[cmd_index].help); if (!cmd_list[cmd_index].flags) WriteOut("%-8s %s",cmd_list[cmd_index].name,MSG_Get(cmd_list[cmd_index].help));
cmd_index++; cmd_index++;
} }
@ -148,8 +149,8 @@ void DOS_Shell::CMD_RMDIR(char * args) {
} }
}; };
static void FormatNumber(Bit32u num,char * buf) { static void FormatNumber(Bitu num,char * buf) {
Bit32u numm,numk,numb; Bitu numm,numk,numb;
numb=num % 1000; numb=num % 1000;
num/=1000; num/=1000;
numk=num % 1000; numk=num % 1000;
@ -178,7 +179,6 @@ void DOS_Shell::CMD_DIR(char * args) {
WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem);
return; return;
} }
Bit32u byte_count,file_count,dir_count; Bit32u byte_count,file_count,dir_count;
Bit32u w_count=0; Bit32u w_count=0;
byte_count=file_count=dir_count=0; byte_count=file_count=dir_count=0;
@ -193,48 +193,47 @@ void DOS_Shell::CMD_DIR(char * args) {
*(strrchr(path,'\\')+1)=0; *(strrchr(path,'\\')+1)=0;
WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path); WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path);
DTA_FindBlock * dta; DOS_DTA dta(dos.dta);
dta=(DTA_FindBlock *)Real2Host(dos.dta);
bool ret=DOS_FindFirst(args,0xffff); bool ret=DOS_FindFirst(args,0xffff);
if (!ret) { if (!ret) {
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args); WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args);
return; return;
} }
while (ret) { while (ret) {
/* File name and extension */ /* File name and extension */
char name[DOS_NAMELENGTH_ASCII];Bit32u size;Bit16u date;Bit16u time;Bit8u attr;
dta.GetResult(name,size,date,time,attr);
char * ext=""; char * ext="";
if (!optW && (*dta->name != '.')) { if (!optW && (name[0] != '.')) {
ext = strrchr(dta->name, '.'); ext = strrchr(name, '.');
if (!ext) ext = ""; if (!ext) ext = "";
else *ext++ = '\0'; else *ext++ = '\0';
}; }
Bit8u day = date & 0x001f;
Bit8u day = dta->date & 0x001f; Bit8u month = (date >> 5) & 0x000f;
Bit8u month = (dta->date >> 5) & 0x000f; Bit16u year = (date >> 9) + 1980;
Bit8u hour = dta->time >> 5 >> 6; Bit8u hour = (time >> 5 ) >> 6;
Bit8u minute = (dta->time >> 5) & 0x003f; Bit8u minute = (time >> 5) & 0x003f;
Bit16u year = (dta->date >> 9) + 1980;
/* output the file */ /* output the file */
if (dta->attr & DOS_ATTR_DIRECTORY) { if (attr & DOS_ATTR_DIRECTORY) {
if (optW) { if (optW) {
WriteOut("[%s]",dta->name); WriteOut("[%s]",name);
for (Bitu i=14-strlen(dta->name);i>0;i--) WriteOut(" "); for (Bitu i=14-strlen(name);i>0;i--) WriteOut(" ");
} else { } else {
WriteOut("%-8s %-3s %-16s %02d-%02d-%04d %2d:%02d\n",dta->name,ext,"<DIR>",day,month,year,hour,minute); WriteOut("%-8s %-3s %-16s %02d-%02d-%04d %2d:%02d\n",name,ext,"<DIR>",day,month,year,hour,minute);
} }
dir_count++; dir_count++;
} else { } else {
if (optW) { if (optW) {
WriteOut("%-16s",dta->name); WriteOut("%-16s",name);
} else { } else {
FormatNumber(dta->size,numformat); FormatNumber(size,numformat);
WriteOut("%-8s %-3s %16s %02d-%02d-%04d %2d:%02d\n",dta->name,ext,numformat,day,month,year,hour,minute); WriteOut("%-8s %-3s %16s %02d-%02d-%04d %2d:%02d\n",name,ext,numformat,day,month,year,hour,minute);
} }
file_count++; file_count++;
byte_count+=dta->size; byte_count+=size;
} }
if (optW) { if (optW) {
w_count++; w_count++;
@ -247,8 +246,15 @@ void DOS_Shell::CMD_DIR(char * args) {
/* Show the summary of results */ /* Show the summary of results */
FormatNumber(byte_count,numformat); FormatNumber(byte_count,numformat);
WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_USED"),file_count,numformat); WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_USED"),file_count,numformat);
Bit8u drive=dta.GetSearchDrive();
//TODO Free Space //TODO Free Space
FormatNumber(1024*1024*100,numformat); Bitu free_space=1024*1024*100;
if (Drives[drive]) {
Bit16u bytes_sector;Bit16u sectors_cluster;Bit16u total_clusters;Bit16u free_clusters;
Drives[drive]->AllocationInfo(&bytes_sector,&sectors_cluster,&total_clusters,&free_clusters);
free_space=bytes_sector*sectors_cluster*free_clusters;
}
FormatNumber(free_space,numformat);
WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_FREE"),dir_count,numformat); WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_FREE"),dir_count,numformat);
} }
@ -258,23 +264,22 @@ void DOS_Shell::CMD_COPY(char * args) {
WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem); WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem);
return; return;
} }
} }
void DOS_Shell::CMD_SET(char * args) { void DOS_Shell::CMD_SET(char * args) {
std::string line;
if (!*args) { if (!*args) {
/* No command line show all environment lines */ /* No command line show all environment lines */
Bit32u count=GetEnvCount(); Bitu count=GetEnvCount();
for (Bit32u a=0;a<count;a++) { for (Bitu a=0;a<count;a++) {
WriteOut("%s\n",GetEnvNum(a)); if (GetEnvNum(a,line)) WriteOut("%s\n",line.c_str());
} }
return; return;
} }
char * p=strpbrk(args, "="); char * p=strpbrk(args, "=");
if (!p) { if (!p) {
p=GetEnvStr(args); if (!GetEnvStr(args,line)) WriteOut(MSG_Get("SHELL_CMD_SET_NOT_SET"),args);
if (p) WriteOut("%s\n",p); WriteOut("%s\n",line.c_str());
else WriteOut(MSG_Get("SHELL_CMD_SET_NOT_SET"),args);
} else { } else {
*p++=0; *p++=0;
if (!SetEnv(args,p)) { if (!SetEnv(args,p)) {
@ -377,5 +382,6 @@ nextfile:
if (*args) goto nextfile; if (*args) goto nextfile;
} }
void DOS_Shell::CMD_REM(char * args) {
}

View File

@ -24,6 +24,7 @@
#include "regs.h" #include "regs.h"
#include "support.h" #include "support.h"
#include "callback.h" #include "callback.h"
#include "setup.h"
#define CMD_MAXLINE 4096 #define CMD_MAXLINE 4096
#define CMD_MAXCMDS 20 #define CMD_MAXCMDS 20
@ -39,20 +40,17 @@ public:
bool ReadLine(char * line); bool ReadLine(char * line);
bool Goto(char * where); bool Goto(char * where);
Bit16u file_handle; Bit16u file_handle;
Bit32u line_count;
char * cmd_words[CMD_MAXCMDS];
char cmd_buffer[128]; //Command line can only be 128 chars
Bit32u cmd_count;
bool echo; bool echo;
DOS_Shell * shell; DOS_Shell * shell;
BatchFile * prev; BatchFile * prev;
CommandLine * cmd;
}; };
class DOS_Shell : public Program { class DOS_Shell : public Program {
public: public:
DOS_Shell(PROGRAM_Info * program_info); DOS_Shell();
void Run(void); void Run(void);
/* A load of subfunctions */ /* A load of subfunctions */
void ParseLine(char * line); void ParseLine(char * line);
@ -77,6 +75,7 @@ public:
void CMD_IF(char * args); void CMD_IF(char * args);
void CMD_GOTO(char * args); void CMD_GOTO(char * args);
void CMD_TYPE(char * args); void CMD_TYPE(char * args);
void CMD_REM(char * args);
void SyntaxError(void); void SyntaxError(void);
/* The shell's variables */ /* The shell's variables */

View File

@ -29,7 +29,6 @@ void DOS_Shell::ShowPrompt(void) {
WriteOut("%c:\\%s>",drive,dir); WriteOut("%c:\\%s>",drive,dir);
} }
static void outc(Bit8u c) { static void outc(Bit8u c) {
Bit16u n=1; Bit16u n=1;
DOS_WriteFile(STDOUT,&c,&n); DOS_WriteFile(STDOUT,&c,&n);
@ -119,14 +118,17 @@ void DOS_Shell::InputCommand(char * line) {
size_t first_len=strlen(old.buffer)+1; size_t first_len=strlen(old.buffer)+1;
memmove(&old.buffer[first_len],&old.buffer[0],CMD_OLDSIZE-first_len); memmove(&old.buffer[first_len],&old.buffer[0],CMD_OLDSIZE-first_len);
strcpy(old.buffer,line); strcpy(old.buffer,line);
} }
void DOS_Shell::Execute(char * name,char * args) { void DOS_Shell::Execute(char * name,char * args) {
char * fullname; char * fullname;
char line[255];
if(strlen(args)!=0){
line[0]=' ';line[1]=0;
strcat(line,args);
}else{
line[0]=0;
};
/* check for a drive change */ /* check for a drive change */
if ((strcmp(name + 1, ":") == 0) && isalpha(*name)) if ((strcmp(name + 1, ":") == 0) && isalpha(*name))
{ {
@ -143,28 +145,30 @@ void DOS_Shell::Execute(char * name,char * args) {
} }
if (strcasecmp(strrchr(fullname, '.'), ".bat") == 0) { if (strcasecmp(strrchr(fullname, '.'), ".bat") == 0) {
/* Run the .bat file */ /* Run the .bat file */
bf=new BatchFile(this,fullname,args); bf=new BatchFile(this,fullname,line);
} else { } else {
/* Run the .exe or .com file from the shell */ /* Run the .exe or .com file from the shell */
/* Allocate some stack space for tables in physical memory */ /* Allocate some stack space for tables in physical memory */
reg_sp-=0x200; reg_sp-=0x200;
//Add Parameter block //Add Parameter block
DOS_ParamBlock block(SegPhys(ss)+reg_sp); DOS_ParamBlock block(SegPhys(ss)+reg_sp);
block.Clear();
//Add a filename //Add a filename
RealPt file_name=RealMakeSeg(ss,reg_sp+0x20); RealPt file_name=RealMakeSeg(ss,reg_sp+0x20);
MEM_BlockWrite(Real2Phys(file_name),fullname,strlen(fullname)+1); MEM_BlockWrite(Real2Phys(file_name),fullname,strlen(fullname)+1);
/* Fill the command line */ /* Fill the command line */
CommandTail cmd; CommandTail cmd;
if (strlen(args)>126) args[126]=0; if (strlen(line)>126) line[126]=0;
cmd.count=strlen(args); cmd.count=strlen(line);
memcpy(cmd.buffer,args,strlen(args)); memcpy(cmd.buffer,line,strlen(line));
cmd.buffer[strlen(args)]=0xd; cmd.buffer[strlen(line)]=0xd;
MEM_BlockWrite(PhysMake(prog_info->psp_seg,128),&cmd,128); /* Copy command line in stack block too */
MEM_BlockWrite(SegPhys(ss)+reg_sp+0x100,&cmd,128);
block.InitExec(RealMake(prog_info->psp_seg,128)); /* Set the command line in the block and save it */
block.exec.cmdtail=RealMakeSeg(ss,reg_sp+0x100);
block.SaveData();
/* Save CS:IP to some point where i can return them from */ /* Save CS:IP to some point where i can return them from */
RealPt newcsip; RealPt newcsip=CALLBACK_RealPointer(call_shellstop);
newcsip=CALLBACK_RealPointer(call_shellstop);
SegSet16(cs,RealSeg(newcsip)); SegSet16(cs,RealSeg(newcsip));
reg_ip=RealOff(newcsip); reg_ip=RealOff(newcsip);
/* Start up a dos execute interrupt */ /* Start up a dos execute interrupt */
@ -179,8 +183,6 @@ void DOS_Shell::Execute(char * name,char * args) {
CALLBACK_RunRealInt(0x21); CALLBACK_RunRealInt(0x21);
reg_sp+=0x200; reg_sp+=0x200;
} }
} }
@ -193,34 +195,28 @@ static char which_ret[DOS_PATHLENGTH];
char * DOS_Shell::Which(char * name) { char * DOS_Shell::Which(char * name) {
/* Parse through the Path to find the correct entry */ /* Parse through the Path to find the correct entry */
// if (which_result) free(which_result);
/* Check for extension */
/* Check if name is already ok but just misses an extension */ /* Check if name is already ok but just misses an extension */
char * ext=strrchr(name,'.'); char * ext=strrchr(name,'.');
if (ext) if (strlen(ext)>4) ext=0; if (ext) if (strlen(ext)>4) ext=0;
if (ext) { if (ext) {
if (DOS_FileExists(name)) return name; if (DOS_FileExists(name)) return name;
} else { } else {
/* try to find .exe .com .bat */ /* try to find .com .exe .bat */
strcpy(which_ret,name);
strcat(which_ret,bat_ext);
if (DOS_FileExists(which_ret)) return which_ret;
strcpy(which_ret,name); strcpy(which_ret,name);
strcat(which_ret,com_ext); strcat(which_ret,com_ext);
if (DOS_FileExists(which_ret)) return which_ret; if (DOS_FileExists(which_ret)) return which_ret;
strcpy(which_ret,name); strcpy(which_ret,name);
strcat(which_ret,exe_ext); strcat(which_ret,exe_ext);
if (DOS_FileExists(which_ret)) return which_ret; if (DOS_FileExists(which_ret)) return which_ret;
strcpy(which_ret,name);
strcat(which_ret,bat_ext);
if (DOS_FileExists(which_ret)) return which_ret;
} }
/* No Path in filename look through %path% */ /* No Path in filename look through path environment string */
static char path[DOS_PATHLENGTH];std::string temp;
static char path[DOS_PATHLENGTH]; if (!GetEnvStr("PATH",temp)) return 0;
char * pathenv=GetEnvStr("PATH"); const char * pathenv=temp.c_str();
if (!pathenv) return 0; if (!pathenv) return 0;
pathenv=strchr(pathenv,'='); pathenv=strchr(pathenv,'=');
if (!pathenv) return 0; if (!pathenv) return 0;
@ -238,17 +234,16 @@ char * DOS_Shell::Which(char * name) {
if (ext) { if (ext) {
if (DOS_FileExists(which_ret)) return which_ret; if (DOS_FileExists(which_ret)) return which_ret;
} else { } else {
strcpy(which_ret,path);
strcat(which_ret,bat_ext);
if (DOS_FileExists(which_ret)) return which_ret;
strcpy(which_ret,path); strcpy(which_ret,path);
strcat(which_ret,com_ext); strcat(which_ret,com_ext);
if (DOS_FileExists(which_ret)) return which_ret; if (DOS_FileExists(which_ret)) return which_ret;
strcpy(which_ret,path); strcpy(which_ret,path);
strcat(which_ret,exe_ext); strcat(which_ret,exe_ext);
if (DOS_FileExists(which_ret)) return which_ret; if (DOS_FileExists(which_ret)) return which_ret;
strcpy(which_ret,path);
strcat(which_ret,bat_ext);
if (DOS_FileExists(which_ret)) return which_ret;
} }
path_write=path; path_write=path;
if (*pathenv) pathenv++; if (*pathenv) pathenv++;
} }

View File

@ -50,7 +50,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 zlib.lib libpng.lib sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "dosbox - Win32 Debug" !ELSEIF "$(CFG)" == "dosbox - Win32 Debug"
@ -75,7 +75,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 zlib.lib libpng.lib sdlmain.lib sdl.lib curses.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF !ENDIF
@ -459,10 +459,6 @@ SOURCE=..\src\misc\messages.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\src\misc\plugins.cpp
# End Source File
# Begin Source File
SOURCE=..\src\misc\programs.cpp SOURCE=..\src\misc\programs.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File