mirror of
https://github.com/retro100/dosbox-wii.git
synced 2024-11-05 01:45:11 +01:00
DOSDOSBox 0.56
This commit is contained in:
parent
0284615f36
commit
44c0450545
22
ChangeLog
22
ChangeLog
@ -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 compilation error on FreeBSD when #disable_joystick was defined
|
||||
- int10_writechar has been updated to move the cursor position.
|
||||
|
15
INSTALL
15
INSTALL
@ -11,8 +11,17 @@ Curses
|
||||
ncurses should be installed on just about every unix distro.
|
||||
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
|
||||
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.
|
||||
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.
|
||||
3. make
|
||||
|
||||
Check the src subdir for the binary and dosbox.lang file.
|
||||
These 2 files should be in the same dir if you want to run dosbox.
|
||||
Check the src subdir for the binary.
|
||||
|
||||
Compiling on FreeBSD might be a problem since SDL has no joystick support there.
|
||||
To get around this edit sdlmain.cpp to enable some #define.
|
||||
@ -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
|
||||
|
||||
Open the workspace in the visualc subdir and build from there.
|
||||
Copy the src/dosbox.lang file to the same dir as your executable.
|
||||
|
||||
|
25
NEWS
25
NEWS
@ -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:
|
||||
- changed basedir handling. (linux/winXP)
|
||||
- added some FCB-calls
|
||||
@ -43,4 +66,4 @@
|
||||
-added the correct time to dir.
|
||||
-bugfixes to batch-file handling.
|
||||
-Lot's of small bugfixes.(Dune1&2,wolf3d, many more).
|
||||
-Released the source.
|
||||
-Released the source.
|
||||
|
49
README
49
README
@ -1,10 +1,11 @@
|
||||
DOSBox v0.55
|
||||
DOSBox v0.56
|
||||
|
||||
Usage:
|
||||
======
|
||||
|
||||
With the new internal shell I've changed the command line a bit, so let's just give some
|
||||
examples of what you can do now.
|
||||
|
||||
dosbox
|
||||
With nothing on the command line you'll end up on the internal drive and from there you
|
||||
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
|
||||
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
|
||||
to start the program.
|
||||
To add commands use the -c command line switch.
|
||||
@ -29,23 +37,49 @@ Internal Programs:
|
||||
==================
|
||||
|
||||
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
|
||||
Utility to setup the emulated hardware running inside DOSBox, only working for emulated sound cards.
|
||||
MEM
|
||||
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>
|
||||
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.
|
||||
|
||||
|
||||
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:
|
||||
=============
|
||||
|
||||
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-F11 Slowdown 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
|
||||
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:
|
||||
=================================
|
||||
|
@ -26,6 +26,9 @@
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `png' library (-lpng). */
|
||||
#undef HAVE_LIBPNG
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
|
91
configure
vendored
91
configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# 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
|
||||
# Free Software Foundation, Inc.
|
||||
@ -272,8 +272,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='dosbox'
|
||||
PACKAGE_TARNAME='dosbox'
|
||||
PACKAGE_VERSION='0.55'
|
||||
PACKAGE_STRING='dosbox 0.55'
|
||||
PACKAGE_VERSION='0.56'
|
||||
PACKAGE_STRING='dosbox 0.56'
|
||||
PACKAGE_BUGREPORT=''
|
||||
|
||||
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.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
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]...
|
||||
|
||||
@ -853,7 +853,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of dosbox 0.55:";;
|
||||
short | recursive ) echo "Configuration of dosbox 0.56:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -946,7 +946,7 @@ fi
|
||||
test -n "$ac_init_help" && exit 0
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
dosbox configure 0.55
|
||||
dosbox configure 0.56
|
||||
generated by GNU Autoconf 2.53a
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
$ $0 $@
|
||||
@ -1579,7 +1579,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=dosbox
|
||||
VERSION=0.55
|
||||
VERSION=0.56
|
||||
|
||||
|
||||
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 $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
|
||||
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
|
||||
@ -4232,6 +4231,76 @@ _ACEOF
|
||||
fi
|
||||
|
||||
|
||||
|
||||
echo "$as_me:$LINENO: checking for png_check_sig in -lpng" >&5
|
||||
echo $ECHO_N "checking for png_check_sig in -lpng... $ECHO_C" >&6
|
||||
if test "${ac_cv_lib_png_png_check_sig+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lpng -lz $LIBS"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
#line $LINENO "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
builtin and then its argument prototype would still apply. */
|
||||
char png_check_sig ();
|
||||
#ifdef F77_DUMMY_MAIN
|
||||
# ifdef __cplusplus
|
||||
extern "C"
|
||||
# endif
|
||||
int F77_DUMMY_MAIN() { return 1; }
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
png_check_sig ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_lib_png_png_check_sig=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
cat conftest.$ac_ext >&5
|
||||
ac_cv_lib_png_png_check_sig=no
|
||||
fi
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_check_sig" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_png_png_check_sig" >&6
|
||||
if test $ac_cv_lib_png_png_check_sig = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBPNG 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lpng $LIBS"
|
||||
|
||||
else
|
||||
{ { echo "$as_me:$LINENO: error: *** libpng not found!" >&5
|
||||
echo "$as_me: error: *** libpng not found!" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
|
||||
#Check if the compiler support attributes
|
||||
echo "$as_me:$LINENO: checking if compiler allows __attribute__" >&5
|
||||
echo $ECHO_N "checking if compiler allows __attribute__... $ECHO_C" >&6
|
||||
@ -4637,7 +4706,7 @@ _ASBOX
|
||||
} >&5
|
||||
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
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -4699,7 +4768,7 @@ _ACEOF
|
||||
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
dosbox config.status 0.55
|
||||
dosbox config.status 0.56
|
||||
configured by $0, generated by GNU Autoconf 2.53a,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
dnl Init.
|
||||
AC_INIT(dosbox,0.55)
|
||||
AC_INIT(dosbox,0.56)
|
||||
AC_CONFIG_SRCDIR(README)
|
||||
|
||||
dnl Detect the canonical host and target build environment
|
||||
@ -10,7 +10,6 @@ dnl Setup for automake
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_CC
|
||||
@ -36,6 +35,9 @@ AC_C_INLINE
|
||||
AC_TYPE_SIZE_T
|
||||
AC_STRUCT_TM
|
||||
|
||||
dnl Checks for libraries.
|
||||
AC_CHECK_LIB(png, png_check_sig, , AC_MSG_ERROR([*** libpng not found!]), -lz)
|
||||
|
||||
#Check if the compiler support attributes
|
||||
AC_MSG_CHECKING(if compiler allows __attribute__)
|
||||
AC_TRY_COMPILE([], [typedef struct { } __attribute__ ((packed)) junk;],
|
||||
|
@ -84,6 +84,11 @@
|
||||
|
||||
#define BIOS_KEYBOARD_FLAGS3 0x496
|
||||
#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_VIDEO_SAVEPTR 0x4a8
|
||||
|
@ -25,9 +25,9 @@
|
||||
|
||||
/* Some common Defines */
|
||||
/* A CPU Handler */
|
||||
typedef Bitu (CPU_Decoder)(Bitu count);
|
||||
typedef Bitu (CPU_Decoder)(Bits count);
|
||||
extern CPU_Decoder * cpudecoder;
|
||||
extern Bit32u cpu_cycles;
|
||||
extern Bitu cpu_cycles;
|
||||
|
||||
//CPU Stuff
|
||||
void SetCPU16bit();
|
||||
|
@ -34,7 +34,7 @@
|
||||
#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_FILESPLIT '\\'
|
||||
#define F_OK 0
|
||||
@ -46,7 +46,7 @@
|
||||
#define CROSS_NONE 0
|
||||
#define CROSS_FILE 1
|
||||
#define CROSS_DIR 2
|
||||
#if defined (_MSC_VER)
|
||||
#if defined (WIN32)
|
||||
#define ftruncate(blah,blah2) chsize(blah,blah2)
|
||||
#endif
|
||||
|
||||
|
@ -16,10 +16,16 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
void DEBUG_SetupConsole(void);
|
||||
void DEBUG_DrawScreen(void);
|
||||
bool DEBUG_BreakPoint(void);
|
||||
bool DEBUG_Breakpoint(void);
|
||||
bool DEBUG_IntBreakpoint(Bit8u intNum);
|
||||
void DEBUG_Enable(void);
|
||||
void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off);
|
||||
bool DEBUG_ExitLoop(void);
|
||||
|
||||
extern Bitu cycle_count;
|
||||
|
||||
#ifdef C_HEAVY_DEBUG
|
||||
bool DEBUG_HeavyIsBreakpoint();
|
||||
#endif
|
||||
|
@ -23,57 +23,11 @@
|
||||
#include <mem.h>
|
||||
|
||||
#pragma pack (1)
|
||||
|
||||
struct CommandTail{
|
||||
Bit8u count; /* number of bytes returned */
|
||||
char buffer[127]; /* the buffer itself */
|
||||
} 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 {
|
||||
Bit8u type;
|
||||
@ -91,7 +45,6 @@ struct DOS_Date {
|
||||
Bit8u day;
|
||||
};
|
||||
|
||||
|
||||
struct DOS_Version {
|
||||
Bit8u major,minor,revision;
|
||||
};
|
||||
@ -107,10 +60,13 @@ struct DOS_Block {
|
||||
RealPt dta;
|
||||
Bit8u return_code,return_mode;
|
||||
|
||||
Bit8u current_drive;
|
||||
bool verify;
|
||||
bool breakcheck;
|
||||
struct {
|
||||
RealPt indosflag;
|
||||
RealPt mediaid;
|
||||
RealPt tempdta;
|
||||
} tables;
|
||||
};
|
||||
|
||||
@ -124,6 +80,7 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
|
||||
extern DOS_Block dos;
|
||||
extern DOS_File * Files[DOS_FILES];
|
||||
extern DOS_Drive * Drives[DOS_DRIVES];
|
||||
extern Bit8u dos_copybuf[0x10000];
|
||||
|
||||
|
||||
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 { HAND_NONE=0,HAND_FILE,HAND_DEVICE};
|
||||
|
||||
|
||||
|
||||
/* Routines for File Class */
|
||||
void DOS_SetupFiles (void);
|
||||
|
||||
bool DOS_ReadFile(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_CloseFile(Bit16u handle);
|
||||
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry);
|
||||
bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry);
|
||||
bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate);
|
||||
|
||||
/* Routines for Drive Class */
|
||||
bool DOS_OpenFile(char * name,Bit8u flags,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_CreateTempFile(char * name,Bit16u * entry);
|
||||
bool DOS_FileExists(char * name);
|
||||
|
||||
/* Drive Handing Routines */
|
||||
Bit8u DOS_GetDefaultDrive(void);
|
||||
void DOS_SetDefaultDrive(Bit8u drive);
|
||||
@ -164,14 +121,16 @@ bool DOS_RemoveDir(char * dir);
|
||||
bool DOS_Rename(char * oldname,char * newname);
|
||||
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
|
||||
bool DOS_GetFileAttr(char * name,Bit16u * attr);
|
||||
|
||||
/* IOCTL Stuff */
|
||||
bool DOS_IOCTL(Bit8u call,Bit16u entry);
|
||||
bool DOS_IOCTL(void);
|
||||
bool DOS_GetSTDINStatus();
|
||||
Bit8u DOS_FindDevice(char * name);
|
||||
void DOS_SetupDevices(void);
|
||||
|
||||
/* Execute and new process creation */
|
||||
bool DOS_NewPSP(Bit16u pspseg);
|
||||
bool DOS_Execute(char * name,ParamBlock * block,Bit8u flags);
|
||||
bool DOS_NewPSP(Bit16u pspseg,Bit16u size);
|
||||
bool DOS_Execute(char * name,PhysPt block,Bit8u flags);
|
||||
bool DOS_Terminate(bool tsr);
|
||||
|
||||
/* Memory Handling Routines */
|
||||
@ -182,33 +141,45 @@ bool DOS_FreeMemory(Bit16u segment);
|
||||
void DOS_FreeProcessMemory(Bit16u pspseg);
|
||||
Bit16u DOS_GetMemory(Bit16u pages);
|
||||
|
||||
|
||||
/* 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_FCBFindFirst(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);
|
||||
bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters);
|
||||
|
||||
/* Extra DOS Interrupts */
|
||||
void DOS_SetupMisc(void);
|
||||
|
||||
/* The DOS Tables */
|
||||
void DOS_SetupTables(void);
|
||||
|
||||
/* Internal DOS Setup Programs */
|
||||
void DOS_SetupPrograms(void);
|
||||
|
||||
|
||||
INLINE Bit16u long2para(Bit32u size) {
|
||||
if (size>0xFFFF0) return 0xffff;
|
||||
if (size&0xf) return (Bit16u)((size>>4)+1);
|
||||
else return (Bit16u)(size>>4);
|
||||
};
|
||||
}
|
||||
|
||||
INLINE Bit8u RealHandle(Bit16u handle) {
|
||||
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||
if (handle>=psp->max_files) return 0xff;
|
||||
return mem_readb(Real2Phys(psp->file_table)+handle);
|
||||
};
|
||||
|
||||
INLINE Bit16u DOS_PackTime(Bit16u hour,Bit16u min,Bit16u sec) {
|
||||
return (hour&0x1f)<<11 | (min&0x3f) << 5 | ((sec/2)&0x1f);
|
||||
}
|
||||
|
||||
INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) {
|
||||
return ((year-1980)&0x7f)<<9 | (mon&0x3f) << 5 | (day&0x1f);
|
||||
}
|
||||
|
||||
/* Dos Error Codes */
|
||||
#define DOSERR_NONE 0
|
||||
@ -233,68 +204,136 @@ INLINE Bit8u RealHandle(Bit16u handle) {
|
||||
#define DOSERR_NO_MORE_FILES 18
|
||||
|
||||
/* 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:
|
||||
DOS_FCB(PhysPt pt){
|
||||
off=pt;
|
||||
INLINE Bit8u GetIt(Bit8u,PhysPt addr) {
|
||||
return mem_readb(pt+addr);
|
||||
}
|
||||
DOS_FCB(Bit16u seg, Bit16u offset){
|
||||
off=PhysMake(seg,offset);
|
||||
INLINE Bit16u GetIt(Bit16u,PhysPt addr) {
|
||||
return mem_readw(pt+addr);
|
||||
}
|
||||
void Set_drive(Bit8u a);
|
||||
void Set_filename(char* a); //writes an the first 8 bytes of a as the filename
|
||||
void Set_ext(char* a);
|
||||
void Set_current_block(Bit16u a);
|
||||
void Set_record_size(Bit16u a);
|
||||
void Set_filesize(Bit32u a);
|
||||
void Set_date(Bit16u a);
|
||||
void Set_time(Bit16u a);
|
||||
// others nog yet handled
|
||||
Bit8u Get_drive(void);
|
||||
void Get_filename(char* a);
|
||||
void Get_ext(char* a);
|
||||
Bit16u Get_current_block(void);
|
||||
Bit16u Get_record_size(void);
|
||||
Bit32u Get_filesize(void);
|
||||
Bit16u Get_date(void);
|
||||
Bit16u Get_time(void);
|
||||
private:
|
||||
PhysPt off;
|
||||
INLINE Bit32u GetIt(Bit32u,PhysPt addr) {
|
||||
return mem_readd(pt+addr);
|
||||
}
|
||||
INLINE void SaveIt(Bit8u,PhysPt addr,Bit8u val) {
|
||||
mem_writeb(pt+addr,val);
|
||||
}
|
||||
INLINE void SaveIt(Bit16u,PhysPt addr,Bit16u val) {
|
||||
mem_writew(pt+addr,val);
|
||||
}
|
||||
INLINE void SaveIt(Bit32u,PhysPt addr,Bit32u val) {
|
||||
mem_writed(pt+addr,val);
|
||||
}
|
||||
INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);}
|
||||
INLINE void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);}
|
||||
INLINE void SetPt(RealPt addr) { pt=Real2Phys(addr);}
|
||||
protected:
|
||||
PhysPt pt;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DOS_ParamBlock {
|
||||
class DOS_PSP :public MemStruct {
|
||||
public:
|
||||
DOS_ParamBlock(PhysPt pt){
|
||||
off=pt;
|
||||
};
|
||||
void InitExec(RealPt cmdtail);
|
||||
Bit16u loadseg(void);
|
||||
Bit16u relocation(void);
|
||||
Bit16u envseg(void);
|
||||
RealPt initsssp(void);
|
||||
RealPt initcsip(void);
|
||||
RealPt fcb1(void);
|
||||
RealPt fcb2(void);
|
||||
RealPt cmdtail(void);
|
||||
DOS_PSP (Bit16u segment) { SetPt(segment);seg=segment;psp=(sPSP *)HostMake(segment,0);};
|
||||
void MakeNew (Bit16u memSize);
|
||||
void CopyFileTable (DOS_PSP* srcpsp);
|
||||
Bit16u FindFreeFileEntry (void);
|
||||
void CloseFiles (void);
|
||||
|
||||
void SaveVectors (void);
|
||||
void RestoreVectors (void);
|
||||
void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); };
|
||||
Bit16u GetSize () { return sGet(sPSP,next_seg); };
|
||||
void SetDTA (RealPt ptdta) { sSave(sPSP,dta,ptdta); };
|
||||
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:
|
||||
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:
|
||||
DOS_InfoBlock (void) { seg=0; dib=0; };
|
||||
DOS_ParamBlock(PhysPt addr) {pt=addr;}
|
||||
void Clear(void);
|
||||
void LoadData(void);
|
||||
void SaveData(void); /* Save it as an exec block */
|
||||
#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;
|
||||
};
|
||||
|
||||
void SetLocation (Bit16u segment);
|
||||
void SetFirstMCB (RealPt pt);
|
||||
void GetDIBPointer (Bit16u& segment, Bit16u& offset);
|
||||
|
||||
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:
|
||||
#pragma pack (push,1)
|
||||
struct SDosInfoBlock {
|
||||
#pragma pack(1)
|
||||
struct sDIB {
|
||||
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 firstFileTable; // first system file table
|
||||
RealPt activeClock; // active clock device header
|
||||
@ -305,13 +344,83 @@ private:
|
||||
RealPt fcbTable; // pointer to system FCB table
|
||||
// some more stuff, hopefully never used.
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#pragma pack (pop)
|
||||
|
||||
SDosInfoBlock* dib;
|
||||
Bit16u seg;
|
||||
#pragma pack ()
|
||||
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
|
||||
|
||||
|
@ -19,11 +19,13 @@
|
||||
#ifndef DOSSYSTEM_H_
|
||||
#define DOSSYSTEM_H_
|
||||
|
||||
#include <dosbox.h>
|
||||
#include "dosbox.h"
|
||||
|
||||
#define DOS_NAMELENGTH 12
|
||||
#define DOS_DIRDEPTH 16
|
||||
#define DOS_PATHLENGTH (DOS_DIRDEPTH+1)*(DOS_NAMELENGTH+2)
|
||||
#define DOS_NAMELENGTH_ASCII (DOS_NAMELENGTH+1)
|
||||
#define DOS_FCBNAME 15
|
||||
#define DOS_DIRDEPTH 8
|
||||
#define DOS_PATHLENGTH 80
|
||||
#define DOS_TEMPSIZE 1024
|
||||
|
||||
enum {
|
||||
@ -35,34 +37,29 @@ enum {
|
||||
DOS_ATTR_ARCHIVE= 0x20
|
||||
};
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#pragma pack(1)
|
||||
#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;
|
||||
struct FileStat_Block {
|
||||
Bit32u size;
|
||||
Bit16u time;
|
||||
Bit16u date;
|
||||
Bit32u size;
|
||||
char name[DOS_NAMELENGTH];
|
||||
}
|
||||
#if defined (_MSC_VER)
|
||||
;
|
||||
#pragma pack()
|
||||
#else
|
||||
__attribute__ ((packed));
|
||||
#endif
|
||||
Bit16u attr;
|
||||
};
|
||||
|
||||
class DOS_DTA;
|
||||
|
||||
class DOS_File {
|
||||
public:
|
||||
virtual ~DOS_File(){};
|
||||
virtual bool Read(Bit8u * data,Bit16u * size)=0;
|
||||
virtual bool Write(Bit8u * data,Bit16u * size)=0;
|
||||
virtual bool Seek(Bit32u * pos,Bit32u type)=0;
|
||||
virtual bool Close()=0;
|
||||
virtual Bit16u GetInformation(void)=0;
|
||||
Bit8u type;Bit32u flags;
|
||||
Bit8u type;
|
||||
Bit32u flags;
|
||||
Bit16u time;
|
||||
Bit16u date;
|
||||
Bit16u attr;
|
||||
Bit32u size;
|
||||
/* Some Device Specific Stuff */
|
||||
};
|
||||
|
||||
@ -73,24 +70,24 @@ public:
|
||||
Bit8u fhandle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DOS_Drive {
|
||||
public:
|
||||
DOS_Drive();
|
||||
virtual ~DOS_Drive(){};
|
||||
virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags)=0;
|
||||
virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes)=0;
|
||||
virtual bool FileUnlink(char * name)=0;
|
||||
virtual bool RemoveDir(char * dir)=0;
|
||||
virtual bool MakeDir(char * dir)=0;
|
||||
virtual bool TestDir(char * dir)=0;
|
||||
virtual bool FindFirst(char * search,DTA_FindBlock * dta)=0;
|
||||
virtual bool FindNext(DTA_FindBlock * dta)=0;
|
||||
virtual bool FileUnlink(char * _name)=0;
|
||||
virtual bool RemoveDir(char * _dir)=0;
|
||||
virtual bool MakeDir(char * _dir)=0;
|
||||
virtual bool TestDir(char * _dir)=0;
|
||||
virtual bool FindFirst(char * _dir,DOS_DTA & dta)=0;
|
||||
virtual bool FindNext(DOS_DTA & dta)=0;
|
||||
virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
|
||||
virtual bool Rename(char * oldname,char * newname)=0;
|
||||
virtual bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free)=0;
|
||||
virtual bool FileExists(const char* name) const=0;
|
||||
virtual bool FileStat(const char* name, struct stat* const stat_block) const=0;
|
||||
virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters)=0;
|
||||
virtual bool FileExists(const char* name)=0;
|
||||
virtual bool FileStat(const char* name, FileStat_Block * const stat_block)=0;
|
||||
virtual Bit8u GetMediaByte(void)=0;
|
||||
char * GetInfo(void);
|
||||
char curdir[DOS_PATHLENGTH];
|
||||
char info[256];
|
||||
@ -109,6 +106,6 @@ typedef bool (MultiplexHandler)(void);
|
||||
void DOS_AddMultiplexHandler(MultiplexHandler * handler);
|
||||
|
||||
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
|
||||
|
||||
|
108
include/dosbox.h
108
include/dosbox.h
@ -24,6 +24,9 @@ void E_Exit(char * message,...);
|
||||
|
||||
void S_Warn(char * message,...);
|
||||
|
||||
void MSG_Add(const char*,const char*); //add messages to the internal langaugefile
|
||||
const char* MSG_Get(char const *); //get messages from the internal langaugafile
|
||||
|
||||
/* The internal types */
|
||||
typedef unsigned char Bit8u;
|
||||
typedef signed char Bit8s;
|
||||
@ -47,14 +50,115 @@ typedef signed int Bits;
|
||||
#include "config.h"
|
||||
#include "../settings.h"
|
||||
|
||||
class Section;
|
||||
|
||||
|
||||
typedef Bitu (LoopHandler)(void);
|
||||
|
||||
void DOSBOX_RunMachine();
|
||||
void DOSBOX_SetLoop(LoopHandler * handler);
|
||||
void DOSBOX_SetNormalLoop();
|
||||
|
||||
void DOSBOX_Init(int argc, char* argv[]);
|
||||
void DOSBOX_StartUp(void);
|
||||
void DOSBOX_Init(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
|
||||
|
@ -19,24 +19,7 @@
|
||||
#ifndef _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
|
||||
|
@ -16,6 +16,9 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _KEYBOARD_H_
|
||||
#define _KEYBOARD_H_
|
||||
|
||||
typedef void(KEYBOARD_EventHandler)(void);
|
||||
void KEYBOARD_AddCode(Bit8u code);
|
||||
void KEYBOARD_AddKey(Bitu keytype,bool pressed);
|
||||
@ -51,4 +54,4 @@ enum {
|
||||
KBD_LAST
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -30,7 +30,7 @@ typedef Bit8u (*MEMORY_ReadHandler)(PhysPt pt);
|
||||
typedef void (*MEMORY_WriteHandler)(PhysPt pt,Bit8u val);
|
||||
|
||||
#define PAGE_KB 16
|
||||
#define PAGE_SIZE PAGE_KB*1024
|
||||
#define PAGE_SIZE (PAGE_KB*1024)
|
||||
#define PAGE_SHIFT 14
|
||||
#define PAGE_COUNT(A) (A & ((1 << PAGE_SHIFT)-1) ? 1+(A >> PAGE_SHIFT) : (A >> PAGE_SHIFT) )
|
||||
#define MAX_PAGES PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024)
|
||||
|
@ -37,6 +37,9 @@ void MIXER_SetFreq(MIXER_Channel * chan,Bit32u freq);
|
||||
void MIXER_SetMode(MIXER_Channel * chan,Bit8u mode);
|
||||
void MIXER_Enable(MIXER_Channel * chan,bool enable);
|
||||
|
||||
void PCSPEAKER_Enable(bool enable);
|
||||
void PCSPEAKER_SetFreq(Bit32u freq);
|
||||
/* PC Speakers functions, tightly related to the timer functions */
|
||||
|
||||
void PCSPEAKER_Enable(bool enable);
|
||||
void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode);
|
||||
|
||||
|
||||
|
@ -25,4 +25,5 @@ void Mouse_CursorSet(float x,float y);
|
||||
void Mouse_ButtonPressed(Bit8u button);
|
||||
void Mouse_ButtonReleased(Bit8u button);
|
||||
|
||||
void Mouse_AutoLock(bool enable);
|
||||
|
||||
|
@ -20,9 +20,14 @@
|
||||
#define __PIC_H
|
||||
|
||||
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);
|
||||
|
||||
@ -33,11 +38,6 @@ void PIC_runIRQs(void);
|
||||
void PIC_RegisterIRQ(Bit32u irq,PIC_EOIHandler handler,char * name);
|
||||
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
|
||||
|
@ -18,32 +18,33 @@
|
||||
|
||||
#ifndef __PROGRAM_H
|
||||
#define __PROGRAM_H
|
||||
#include <dosbox.h>
|
||||
#include <dos_inc.h>
|
||||
#include "dosbox.h"
|
||||
#include "dos_inc.h"
|
||||
#include "setup.h"
|
||||
|
||||
|
||||
char * MSG_Get(char * msg);
|
||||
|
||||
struct PROGRAM_Info {
|
||||
Bit16u psp_seg;
|
||||
PSP psp_copy;
|
||||
char full_name[32]; //Enough space for programs only on the z:\ drive
|
||||
char * cmd_line;
|
||||
};
|
||||
class Program;
|
||||
|
||||
typedef void (PROGRAMS_Main)(PROGRAM_Info * info);
|
||||
typedef void (PROGRAMS_Main)(Program * * make);
|
||||
void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main);
|
||||
|
||||
class Program {
|
||||
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;
|
||||
char * GetEnvStr(char * env_entry);
|
||||
char * GetEnvNum(Bit32u num);
|
||||
Bit32u GetEnvCount(void);
|
||||
bool SetEnv(char * env_entry,char * new_string);
|
||||
void WriteOut(char * format,...); /* Write to standard output */
|
||||
PROGRAM_Info * prog_info;
|
||||
bool Program::GetEnvStr(const char * entry,std::string & result);
|
||||
bool GetEnvNum(Bitu num,std::string & result);
|
||||
Bitu GetEnvCount(void);
|
||||
bool SetEnv(const char * entry,const char * new_string);
|
||||
void WriteOut(const char * format,...); /* Write to standard output */
|
||||
|
||||
};
|
||||
|
||||
|
168
include/setup.h
168
include/setup.h
@ -19,25 +19,171 @@
|
||||
#ifndef _SETUP_H_
|
||||
#define _SETUP_H_
|
||||
|
||||
#pragma warning ( disable : 4786 )
|
||||
|
||||
#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:
|
||||
int argc;
|
||||
char * * argv;
|
||||
typedef std::list<std::string>::iterator cmd_it;
|
||||
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
|
||||
|
@ -39,8 +39,6 @@ char *ltrim(char *str);
|
||||
void rtrim(char * const str);
|
||||
char *trim(char *str);
|
||||
|
||||
bool wildcmp(char *wild, char *string);
|
||||
|
||||
bool ScanCMDBool(char * cmd,char * check);
|
||||
char * ScanCMDRemain(char * cmd);
|
||||
bool ScanCMDHex(char * cmd,char * check,Bits * result);
|
||||
|
@ -19,9 +19,12 @@
|
||||
#ifndef _TIMER_H_
|
||||
#define _TIMER_H_
|
||||
/* underlying clock rate in HZ */
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL.h>
|
||||
|
||||
extern Bit32u LastTicks;
|
||||
|
||||
#define PIT_TICK_RATE 1193182
|
||||
|
||||
#define GetTicks() SDL_GetTicks()
|
||||
|
||||
typedef void (*TIMER_TickHandler)(Bitu ticks);
|
||||
@ -48,6 +51,5 @@ void TIMER_CheckPIT(void);
|
||||
/* This will add ms ticks to support the timer handlers */
|
||||
void TIMER_AddTicks(Bit32u ticks);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef __VIDEO_H
|
||||
#define __VIDEO_H
|
||||
|
||||
|
||||
typedef void (GFX_DrawHandler)(Bit8u * vidstart);
|
||||
/* Used to reply to the renderer what size to set */
|
||||
typedef void (GFX_ResizeHandler)(Bitu * width,Bitu * height);
|
||||
@ -45,6 +46,5 @@ void GFX_Start(void);
|
||||
void GFX_Stop(void);
|
||||
void GFX_SwitchFullScreen(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
13
settings.h
13
settings.h
@ -21,6 +21,7 @@
|
||||
|
||||
/* Enable the debugger, this only seems to work in win32 for now. */
|
||||
#define C_DEBUG 0
|
||||
#define C_HEAVY_DEBUG 0
|
||||
|
||||
/* Enable the logging of extra information for debugging to the console */
|
||||
#define C_LOGGING 0
|
||||
@ -48,16 +49,4 @@
|
||||
#define DEBUG_DMA 0 /* DMA 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
|
||||
|
@ -6,5 +6,5 @@ bin_PROGRAMS = dosbox
|
||||
|
||||
dosbox_SOURCES = dosbox.cpp
|
||||
dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \
|
||||
ints/libints.a misc/libmisc.a shell/libshell.a -lcurses
|
||||
EXTRA_DIST = dosbox.lang
|
||||
ints/libints.a misc/libmisc.a shell/libshell.a -lcurses -lpng
|
||||
|
||||
|
@ -89,9 +89,8 @@ bin_PROGRAMS = dosbox
|
||||
|
||||
dosbox_SOURCES = dosbox.cpp
|
||||
dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \
|
||||
ints/libints.a misc/libmisc.a shell/libshell.a -lcurses
|
||||
ints/libints.a misc/libmisc.a shell/libshell.a -lcurses -lpng
|
||||
|
||||
EXTRA_DIST = dosbox.lang
|
||||
subdir = src
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
|
@ -135,7 +135,7 @@ bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CALLBACK_Init(void) {
|
||||
void CALLBACK_Init(Section* sec) {
|
||||
Bitu i;
|
||||
for (i=0;i<CB_MAX;i++) {
|
||||
CallBack_Handlers[i]=&illegal_handler;
|
||||
|
@ -16,7 +16,6 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
bool repcheck;
|
||||
restart:
|
||||
switch(Fetchb()) {
|
||||
case 0x00: /* ADD Eb,Gb */
|
||||
@ -109,9 +108,12 @@ restart:
|
||||
if ((reg_al > 0x9F) || flags.cf) {
|
||||
reg_al+=0x60;
|
||||
flags.cf=true;
|
||||
} else {
|
||||
flags.cf=false;
|
||||
}
|
||||
flags.sf=(reg_al>>7)>0;
|
||||
flags.zf=(reg_al==0);
|
||||
//TODO Maybe parity
|
||||
flags.type=t_UNKNOWN;
|
||||
break;
|
||||
case 0x28: /* SUB Eb,Gb */
|
||||
@ -545,35 +547,11 @@ restart:
|
||||
}
|
||||
case 0x8d: /* LEA */
|
||||
{
|
||||
GetRMrw;
|
||||
switch (rm & 0xC7) {
|
||||
case 0x00:*rmrw=reg_bx+reg_si;break;
|
||||
case 0x01:*rmrw=reg_bx+reg_di;break;
|
||||
case 0x02:*rmrw=reg_bp+reg_si;break;
|
||||
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");
|
||||
}
|
||||
prefix.segbase=0;
|
||||
prefix.mark|=PREFIX_SEG;
|
||||
lookupEATable=EAPrefixTable[prefix.mark];
|
||||
GetRMrw;GetEAa;
|
||||
*rmrw=(Bit16u)eaa;
|
||||
break;
|
||||
}
|
||||
case 0x8e: /* MOV Sw,Ew */
|
||||
@ -880,7 +858,7 @@ restart:
|
||||
case 0xcc: /* INT3 */
|
||||
INTERRUPT(3);
|
||||
#if C_DEBUG
|
||||
return 0;
|
||||
return 1;
|
||||
#endif
|
||||
break;
|
||||
case 0xcd: /* INT Ib */
|
||||
@ -888,7 +866,7 @@ restart:
|
||||
Bit8u num=Fetchb();
|
||||
#if C_DEBUG
|
||||
SAVEIP;
|
||||
if (DEBUG_IntBreakpoint(num)) return 0;
|
||||
if (DEBUG_IntBreakpoint(num)) return 1;
|
||||
#endif
|
||||
INTERRUPT(num);
|
||||
}
|
||||
@ -936,8 +914,8 @@ restart:
|
||||
reg_al = get_CF() ? 0xFF : 0;
|
||||
break;
|
||||
case 0xd7: /* XLAT */
|
||||
if (prefixes & PREFIX_SEG) {
|
||||
reg_al=LoadMb(segprefix_base+(Bit16u)(reg_bx+reg_al));
|
||||
if (prefix.mark & PREFIX_SEG) {
|
||||
reg_al=LoadMb(prefix.segbase+(Bit16u)(reg_bx+reg_al));
|
||||
PrefixReset;
|
||||
} else {
|
||||
reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
|
||||
@ -1042,174 +1020,15 @@ restart:
|
||||
LOG_ERROR("CPU:LOCK");
|
||||
break;
|
||||
case 0xf1: /* Weird call undocumented */
|
||||
// INTERRUPT(1);
|
||||
E_Exit("CPU:F1:Not Handled");
|
||||
break;
|
||||
case 0xf2: /* REPNZ */
|
||||
repcheck=false;
|
||||
goto repstart;
|
||||
count-=Repeat_Normal(false,false,count);
|
||||
break;
|
||||
case 0xf3: /* REPZ */
|
||||
repcheck=true;
|
||||
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;
|
||||
#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;
|
||||
}
|
||||
count-=Repeat_Normal(true,false,count);
|
||||
break;
|
||||
case 0xf4: /* HLT */
|
||||
break;
|
||||
case 0xf5: /* CMC */
|
||||
@ -1496,5 +1315,9 @@ restart:
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NOTDONE;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ switch(Fetchb()) {
|
||||
RMGdEd(ADDD);break;
|
||||
case 0x05: /* ADD EAX,Id */
|
||||
EAXId(ADDD);break;
|
||||
case 0x09: /* OR Ew,Gw */
|
||||
case 0x09: /* OR Ed,Gd */
|
||||
RMEdGd(ORD);break;
|
||||
case 0x0b: /* OR Gd,Ed */
|
||||
RMGdEd(ORD);break;
|
||||
@ -69,8 +69,6 @@ switch(Fetchb()) {
|
||||
RMGdEd(CMPD);break;
|
||||
case 0x3d: /* CMP EAX,Id */
|
||||
EAXId(CMPD);break;
|
||||
|
||||
|
||||
case 0x26: /* SEG ES: */
|
||||
SegPrefix_66(es);break;
|
||||
case 0x2e: /* SEG CS: */
|
||||
@ -153,6 +151,10 @@ switch(Fetchb()) {
|
||||
break;
|
||||
case 0x68: /* PUSH Id */
|
||||
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 */
|
||||
{
|
||||
GetRMrd;
|
||||
@ -164,12 +166,21 @@ switch(Fetchb()) {
|
||||
if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;}
|
||||
else {flags.cf=true;flags.of=true;}
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
case 0x6a: /* PUSH Ib */
|
||||
Push_32(Fetchbs());break;
|
||||
case 0x6b: /* IMUL Gd,Ed,Ib */
|
||||
{
|
||||
GetRMrd;
|
||||
Bit64s res;
|
||||
if (rm >= 0xc0 ) {GetEArd;res=(Bit64s)(*eards) * (Bit64s)Fetchbs();}
|
||||
else {GetEAa;res=(Bit64s)LoadMds(eaa) * (Bit64s)Fetchbs();}
|
||||
*rmrd=(Bit32s)(res);
|
||||
flags.type=t_MUL;
|
||||
if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {flags.cf=false;flags.of=false;}
|
||||
else {flags.cf=true;flags.of=true;}
|
||||
break;
|
||||
}
|
||||
case 0x81: /* Grpl Ed,Id */
|
||||
{
|
||||
GetRM;
|
||||
@ -186,7 +197,7 @@ switch(Fetchb()) {
|
||||
case 0x38:CMPD(*eard,id,LoadRd,SaveRd);break;
|
||||
}
|
||||
} else {
|
||||
GetEAa;Bit32u id=Fetchb();
|
||||
GetEAa;Bit32u id=Fetchd();
|
||||
switch (rm & 0x38) {
|
||||
case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break;
|
||||
case 0x08: ORD(eaa,id,LoadMd,SaveMd);break;
|
||||
@ -232,14 +243,13 @@ switch(Fetchb()) {
|
||||
break;
|
||||
case 0x85: /* TEST Ed,Gd */
|
||||
RMEdGd(TESTD);break;
|
||||
case 0x8f: /* POP Ed */
|
||||
{
|
||||
GetRM;
|
||||
if (rm >= 0xc0 ) {GetEArd;*eard=Pop_32();}
|
||||
else {GetEAa;SaveMd(eaa,Pop_32());}
|
||||
case 0x87: /* XCHG Ev,Gv */
|
||||
{
|
||||
GetRMrd;Bit32u oldrmrd=*rmrd;
|
||||
if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard=oldrmrd;}
|
||||
else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,oldrmrd);}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x89: /* MOV Ed,Gd */
|
||||
{
|
||||
GetRMrd;
|
||||
@ -247,10 +257,6 @@ switch(Fetchb()) {
|
||||
else {GetEAa;SaveMd(eaa,*rmrd);}
|
||||
break;
|
||||
}
|
||||
case 0x99: /* CDQ */
|
||||
if (reg_eax & 0x80000000) reg_edx=0xffffffff;
|
||||
else reg_edx=0;
|
||||
break;
|
||||
case 0x8b: /* MOV Gd,Ed */
|
||||
{
|
||||
GetRMrd;
|
||||
@ -261,6 +267,42 @@ switch(Fetchb()) {
|
||||
case 0x8c:
|
||||
LOG_WARN("CPU:66:8c looped back");
|
||||
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 */
|
||||
{
|
||||
Bit32u pflags=
|
||||
@ -296,6 +338,9 @@ switch(Fetchb()) {
|
||||
else { reg_si+=4;reg_di+=4;}
|
||||
}
|
||||
break;
|
||||
case 0xa9: /* TEST EAX,Id */
|
||||
EAXId(TESTD);
|
||||
break;
|
||||
case 0xab: /* STOSD */
|
||||
{
|
||||
stringDI;
|
||||
@ -349,6 +394,14 @@ switch(Fetchb()) {
|
||||
GRP2D(1);break;
|
||||
case 0xd3: /* GRP2 Ed,CL */
|
||||
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) */
|
||||
{
|
||||
union { Bit64u u;Bit64s s;} temp;
|
||||
@ -441,12 +494,12 @@ switch(Fetchb()) {
|
||||
{
|
||||
GetRM;
|
||||
switch (rm & 0x38) {
|
||||
case 0x00: /* INC Ew */
|
||||
case 0x00: /* INC Ed */
|
||||
flags.cf=get_CF();flags.type=t_INCd;
|
||||
if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard+=1;}
|
||||
else {GetEAa;flags.result.d=LoadMd(eaa)+1;SaveMd(eaa,flags.result.d);}
|
||||
break;
|
||||
case 0x08: /* DEC Ew */
|
||||
case 0x08: /* DEC Ed */
|
||||
flags.cf=get_CF();flags.type=t_DECd;
|
||||
if (rm >= 0xc0 ) {GetEArd;flags.result.d=*eard-=1;}
|
||||
else {GetEAa;flags.result.d=LoadMd(eaa)-1;SaveMd(eaa,flags.result.d);}
|
||||
|
@ -79,6 +79,8 @@ switch (Fetchb()) {
|
||||
if (flags.cf) *eard&=~mask;
|
||||
else *eard|=mask;
|
||||
break;
|
||||
default:
|
||||
E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38);
|
||||
}
|
||||
} else {
|
||||
GetEAa;Bit32u old=LoadMd(eaa);
|
||||
@ -98,6 +100,8 @@ switch (Fetchb()) {
|
||||
else old|=mask;
|
||||
SaveMd(eaa,old);
|
||||
break;
|
||||
default:
|
||||
E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38);
|
||||
}
|
||||
}
|
||||
if (flags.type!=t_CF) flags.prev_type=flags.type;
|
||||
|
@ -314,6 +314,8 @@ switch(Fetchb()) {
|
||||
case 0x38: /* BTC */
|
||||
*earw^=mask;
|
||||
break;
|
||||
default:
|
||||
E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38);
|
||||
}
|
||||
} else {
|
||||
GetEAa;Bit16u old=LoadMw(eaa);
|
||||
@ -330,6 +332,8 @@ switch(Fetchb()) {
|
||||
case 0x38: /* BTC */
|
||||
SaveMw(eaa,old ^ mask);
|
||||
break;
|
||||
default:
|
||||
E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38);
|
||||
}
|
||||
}
|
||||
if (flags.type!=t_CF) { flags.prev_type=flags.type;flags.type=t_CF; }
|
||||
|
@ -88,8 +88,8 @@ static INLINE Bit32u Pop_32() {
|
||||
|
||||
#define stringSI \
|
||||
EAPoint from; \
|
||||
if (prefixes & PREFIX_SEG) { \
|
||||
from=(segprefix_base+reg_si); \
|
||||
if (prefix.mark & PREFIX_SEG) { \
|
||||
from=(prefix.segbase+reg_si); \
|
||||
PrefixReset; \
|
||||
} else { \
|
||||
from=SegBase(ds)+reg_si; \
|
||||
@ -102,48 +102,265 @@ static INLINE Bit32u Pop_32() {
|
||||
#include "instructions.h"
|
||||
|
||||
|
||||
static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) {
|
||||
bool again;
|
||||
do {
|
||||
again=false;
|
||||
Bit8u repcode=Fetchb();
|
||||
switch (repcode) {
|
||||
case 0x26: /* ES Prefix */
|
||||
again=true;
|
||||
from=SegBase(es);
|
||||
break;
|
||||
case 0x2e: /* CS Prefix */
|
||||
again=true;
|
||||
from=SegBase(cs);
|
||||
break;
|
||||
case 0x36: /* SS Prefix */
|
||||
again=true;
|
||||
from=SegBase(ss);
|
||||
break;
|
||||
case 0x3e: /* DS Prefix */
|
||||
again=true;
|
||||
from=SegBase(ds);
|
||||
break;
|
||||
case 0xa5: /* REP MOVSD */
|
||||
for (;reg_cx>0;reg_cx--) {
|
||||
SaveMd(to+reg_di,LoadMd(from+reg_si));
|
||||
reg_di+=direct*4;
|
||||
reg_si+=direct*4;
|
||||
}
|
||||
break;
|
||||
case 0xab: /* REP STOSW */
|
||||
for (;reg_cx>0;reg_cx--) {
|
||||
SaveMd(to+reg_di,reg_eax);
|
||||
reg_di+=direct*4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
E_Exit("CPU:Opcode 66:Illegal REP prefix %2X",repcode);
|
||||
static Bits Repeat_Normal(bool testz,bool prefix_66,Bits count_remain) {
|
||||
|
||||
Bits count=count_remain;
|
||||
PhysPt base_si,base_di;
|
||||
|
||||
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 */
|
||||
prefix.segbase=SegBase(es);
|
||||
prefix.mark|=PREFIX_SEG;
|
||||
prefix.count++;
|
||||
goto rep_again;
|
||||
case 0x2e: /* CS Prefix */
|
||||
prefix.segbase=SegBase(cs);
|
||||
prefix.mark|=PREFIX_SEG;
|
||||
prefix.count++;
|
||||
goto rep_again;
|
||||
case 0x36: /* SS Prefix */
|
||||
prefix.segbase=SegBase(ss);
|
||||
prefix.mark|=PREFIX_SEG;
|
||||
prefix.count++;
|
||||
goto rep_again;
|
||||
case 0x3e: /* DS Prefix */
|
||||
prefix.segbase=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;
|
||||
}
|
||||
} while (again);
|
||||
if (reg_cx && count<=0) goto countzero;
|
||||
break;
|
||||
case 0x6d: /* REP INSW/D */
|
||||
if (prefix_66) {
|
||||
direct*=4;
|
||||
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));
|
||||
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;
|
||||
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 */
|
||||
if (prefix_66) {
|
||||
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;
|
||||
default:
|
||||
IPPoint--;
|
||||
LOG_DEBUG("Unhandled REP Prefix %X",Fetchb());
|
||||
|
||||
}
|
||||
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
|
||||
#ifdef CPU_386
|
||||
#define Save_Flagsw(FLAGW) \
|
||||
{ \
|
||||
flags.type=t_UNKNOWN; \
|
||||
@ -159,7 +376,25 @@ static INLINE void Rep_66(Bit16s direct,EAPoint from,EAPoint to) {
|
||||
PIC_runIRQs(); \
|
||||
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
|
||||
|
@ -26,38 +26,56 @@ static GetEATable * lookupEATable;
|
||||
#define PREFIX_ADDR 0x2
|
||||
#define PREFIX_SEG_ADDR 0x3
|
||||
|
||||
|
||||
static Bitu prefixes;
|
||||
static EAPoint segprefix_base;
|
||||
static struct {
|
||||
Bitu mark;
|
||||
Bitu count;
|
||||
EAPoint segbase;
|
||||
} prefix;
|
||||
|
||||
/* Gets initialized at the bottem, can't seem to declare forward references */
|
||||
static GetEATable * EAPrefixTable[4];
|
||||
|
||||
|
||||
#define SegPrefix(blah) \
|
||||
segprefix_base=SegBase(blah); \
|
||||
prefixes|=PREFIX_SEG; \
|
||||
lookupEATable=EAPrefixTable[prefixes]; \
|
||||
goto restart; \
|
||||
prefix.segbase=SegBase(blah); \
|
||||
prefix.mark|=PREFIX_SEG; \
|
||||
prefix.count++; \
|
||||
lookupEATable=EAPrefixTable[prefix.mark]; \
|
||||
goto restart;
|
||||
|
||||
#define SegPrefix_66(blah) \
|
||||
segprefix_base=SegBase(blah); \
|
||||
prefixes|=PREFIX_SEG; \
|
||||
lookupEATable=EAPrefixTable[prefixes]; \
|
||||
goto restart_66; \
|
||||
prefix.segbase=SegBase(blah); \
|
||||
prefix.mark|=PREFIX_SEG; \
|
||||
prefix.count++; \
|
||||
lookupEATable=EAPrefixTable[prefix.mark]; \
|
||||
goto restart_66;
|
||||
|
||||
|
||||
#define PrefixReset \
|
||||
prefixes=PREFIX_NONE;lookupEATable=EAPrefixTable[PREFIX_NONE];
|
||||
#define PrefixReset \
|
||||
prefix.mark=PREFIX_NONE; \
|
||||
prefix.count=0; \
|
||||
lookupEATable=EAPrefixTable[PREFIX_NONE];
|
||||
|
||||
#if 1
|
||||
|
||||
#define GetEADirect \
|
||||
EAPoint eaa;switch (prefixes) { \
|
||||
EAPoint eaa;switch (prefix.mark) { \
|
||||
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_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_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
|
||||
};
|
||||
|
||||
static Bit32u SIBZero=0;
|
||||
static Bit32u * SIBIndex[8]= { ®_eax,®_ecx,®_edx,®_ebx,&SIBZero,®_ebp,®_esi,®_edi };
|
||||
|
||||
INLINE EAPoint Sib(Bitu mode) {
|
||||
Bit8u sib=Fetchb();
|
||||
@ -203,7 +223,7 @@ INLINE EAPoint Sib(Bitu mode) {
|
||||
case 3: /* EBX Base */
|
||||
base=SegBase(ds)+reg_ebx;break;
|
||||
case 4: /* ESP Base */
|
||||
base=SegBase(ds)+reg_esp;break;
|
||||
base=SegBase(ss)+reg_esp;break;
|
||||
case 5: /* #1 Base */
|
||||
if (!mode) {
|
||||
base=SegBase(ds)+Fetchd();break;
|
||||
@ -215,25 +235,7 @@ INLINE EAPoint Sib(Bitu mode) {
|
||||
case 7: /* EDI Base */
|
||||
base=SegBase(ds)+reg_edi;break;
|
||||
}
|
||||
Bitu shift=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;
|
||||
};
|
||||
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
|
||||
return base;
|
||||
};
|
||||
|
||||
@ -305,50 +307,31 @@ INLINE EAPoint Sib_s(Bitu mode) {
|
||||
EAPoint base;
|
||||
switch (sib&7) {
|
||||
case 0: /* EAX Base */
|
||||
base=segprefix_base+reg_eax;break;
|
||||
base=prefix.segbase+reg_eax;break;
|
||||
case 1: /* ECX Base */
|
||||
base=segprefix_base+reg_ecx;break;
|
||||
base=prefix.segbase+reg_ecx;break;
|
||||
case 2: /* EDX Base */
|
||||
base=segprefix_base+reg_edx;break;
|
||||
base=prefix.segbase+reg_edx;break;
|
||||
case 3: /* EBX Base */
|
||||
base=segprefix_base+reg_ebx;break;
|
||||
base=prefix.segbase+reg_ebx;break;
|
||||
case 4: /* ESP Base */
|
||||
base=segprefix_base+reg_esp;break;
|
||||
base=prefix.segbase+reg_esp;break;
|
||||
case 5: /* #1 Base */
|
||||
if (!mode) {
|
||||
base=segprefix_base+Fetchd();break;
|
||||
base=prefix.segbase+Fetchd();break;
|
||||
} else {
|
||||
base=segprefix_base+reg_ebp;break;
|
||||
base=prefix.segbase+reg_ebp;break;
|
||||
}
|
||||
case 6: /* ESI Base */
|
||||
base=segprefix_base+reg_esi;break;
|
||||
base=prefix.segbase+reg_esi;break;
|
||||
case 7: /* EDI Base */
|
||||
base=segprefix_base+reg_edi;break;
|
||||
base=prefix.segbase+reg_edi;break;
|
||||
}
|
||||
Bitu shift=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;
|
||||
};
|
||||
PrefixReset;
|
||||
base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6); PrefixReset;
|
||||
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_01_s(void) { segprefixed_32(reg_ecx); }
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "memory.h"
|
||||
#include "debug.h"
|
||||
#include "keyboard.h"
|
||||
#include "setup.h"
|
||||
|
||||
//Regs regs;
|
||||
|
||||
@ -28,27 +29,22 @@ Flag_Info flags;
|
||||
|
||||
CPU_Regs cpu_regs;
|
||||
|
||||
|
||||
|
||||
Segment Segs[6];
|
||||
Bit32u cpu_cycles;
|
||||
Bitu cpu_cycles;
|
||||
|
||||
CPU_Decoder * cpudecoder;
|
||||
|
||||
|
||||
static void CPU_CycleIncrease(void) {
|
||||
Bit32u old_cycles=cpu_cycles;
|
||||
cpu_cycles=(Bit32u)(cpu_cycles*1.2);
|
||||
Bitu old_cycles=cpu_cycles;
|
||||
cpu_cycles=(Bitu)(cpu_cycles*1.2);
|
||||
if (cpu_cycles==old_cycles) cpu_cycles++;
|
||||
LOG_MSG("CPU:%d cycles",cpu_cycles);
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
LOG_MSG("CPU:%d cycles",cpu_cycles);
|
||||
|
||||
}
|
||||
|
||||
Bit8u lastint;
|
||||
@ -87,7 +83,7 @@ void Interrupt(Bit8u num) {
|
||||
E_Exit("Call to interrupt 0xCD this is BAD");
|
||||
case 0x03:
|
||||
#if C_DEBUG
|
||||
if (DEBUG_BreakPoint()) return;
|
||||
if (DEBUG_Breakpoint()) return;
|
||||
#endif
|
||||
break;
|
||||
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_ebx=0;
|
||||
reg_ecx=0;
|
||||
@ -166,11 +163,13 @@ void CPU_Init(void) {
|
||||
flags.io=0;
|
||||
|
||||
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_f12,CTRL_PRESSED,CPU_CycleIncrease);
|
||||
|
||||
reg_al=0;
|
||||
reg_ah=0;
|
||||
MSG_Add("CPU_CONFIGFILE_HELP","The amount of cycles to execute each loop. Lowering this setting will slowdown dosbox\n");
|
||||
}
|
||||
|
||||
|
@ -61,20 +61,24 @@ extern Bitu cycle_count;
|
||||
|
||||
#include "core_16/support.h"
|
||||
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"
|
||||
while (count) {
|
||||
do {
|
||||
#if C_DEBUG
|
||||
cycle_count++;
|
||||
#endif
|
||||
count--;
|
||||
#if C_HEAVY_DEBUG
|
||||
SAVEIP;
|
||||
if (DEBUG_HeavyIsBreakpoint()) return CBRET_NONE;
|
||||
#endif
|
||||
#include "core_16/main.h"
|
||||
}
|
||||
} while (--count>0);
|
||||
#include "core_16/stop.h"
|
||||
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) {
|
||||
if (flags.tf) {
|
||||
Interrupt(3);
|
||||
|
@ -16,6 +16,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "programs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <list>
|
||||
@ -32,16 +33,27 @@
|
||||
#include "inout.h"
|
||||
#include "mixer.h"
|
||||
#include "debug_inc.h"
|
||||
#include "timer.h"
|
||||
#include "..\shell\shell_inc.h"
|
||||
|
||||
#ifdef WIN32
|
||||
void WIN32_Console();
|
||||
#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 {
|
||||
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
|
||||
} oldregs;
|
||||
|
||||
static void DrawCode(void);
|
||||
|
||||
|
||||
static Segment oldsegs[6];
|
||||
static Flag_Info oldflags;
|
||||
@ -77,127 +89,318 @@ static Bit16u dataSeg,dataOfs;
|
||||
/* Breakpoint stuff */
|
||||
/********************/
|
||||
|
||||
enum { BKPNT_REALMODE, BKPNT_PHYSICAL, BKPNT_INTERRUPT };
|
||||
bool skipFirstInstruction = false;
|
||||
|
||||
enum EBreakpoint { BKPNT_UNKNOWN, BKPNT_PHYSICAL, BKPNT_INTERRUPT };
|
||||
|
||||
#define BPINT_ALL 0x100
|
||||
|
||||
typedef struct SBreakPoint {
|
||||
PhysPt location;
|
||||
Bit8u olddata;
|
||||
Bit8u type;
|
||||
Bit16u ahValue;
|
||||
Bit16u segment;
|
||||
Bit32u offset;
|
||||
bool once;
|
||||
bool enabled;
|
||||
bool active;
|
||||
} TBreakpoint;
|
||||
|
||||
static std::list<TBreakpoint> BPoints;
|
||||
|
||||
static bool IsBreakpoint(PhysPt off)
|
||||
class CBreakpoint
|
||||
{
|
||||
// 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;
|
||||
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;
|
||||
Bit8u oldData;
|
||||
Bit16u segment;
|
||||
Bit32u offset;
|
||||
// Int
|
||||
Bit8u intNr;
|
||||
Bit16u ahValue;
|
||||
// Shared
|
||||
bool active;
|
||||
bool once;
|
||||
|
||||
static std::list<CBreakpoint*> BPoints;
|
||||
static CBreakpoint* ignoreOnce;
|
||||
};
|
||||
|
||||
/* This clears all breakpoints by replacing their 0xcc by the original byte */
|
||||
static void ClearBreakpoints(void)
|
||||
void CBreakpoint::Activate(bool _active)
|
||||
{
|
||||
// iterate list and place 0xCC
|
||||
std::list<TBreakpoint>::iterator i;
|
||||
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
||||
if (((*i).type==BKPNT_PHYSICAL) && (*i).active) {
|
||||
if (mem_readb((*i).location)==0xCC) mem_writeb((*i).location,(*i).olddata);
|
||||
(*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 (GetType()==BKPNT_PHYSICAL) {
|
||||
#if !C_HEAVY_DEBUG
|
||||
if (_active) {
|
||||
// Set 0xCC and save old value
|
||||
Bit8u data = mem_readb(location);
|
||||
if (data!=0xCC) {
|
||||
(*i).olddata = data;
|
||||
(*i).active = true;
|
||||
mem_writeb((*i).location,0xCC);
|
||||
}
|
||||
};
|
||||
oldData = data;
|
||||
mem_writeb(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)
|
||||
{
|
||||
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);
|
||||
active = _active;
|
||||
};
|
||||
|
||||
static bool RemoveBreakpoint(PhysPt off)
|
||||
// Statics
|
||||
std::list<CBreakpoint*> CBreakpoint::BPoints;
|
||||
CBreakpoint* CBreakpoint::ignoreOnce = 0;
|
||||
|
||||
CBreakpoint* CBreakpoint::AddBreakpoint(Bit16u seg, Bit32u off, bool once)
|
||||
{
|
||||
// iterate list and remove TBreakpoint
|
||||
std::list<TBreakpoint>::iterator i;
|
||||
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++) {
|
||||
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);
|
||||
|
||||
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 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()
|
||||
{
|
||||
PhysPt start=Segs[cs].phys+reg_eip;
|
||||
char dline[200];Bitu size;
|
||||
size=DasmI386(dline, start, reg_eip, false);
|
||||
|
||||
if (strstr(dline,"call") || strstr(dline,"int")) {
|
||||
AddBreakpoint (SegValue(cs),reg_eip+size, true);
|
||||
SetBreakpoints();
|
||||
if (strstr(dline,"call") || strstr(dline,"int") || strstr(dline,"loop") || strstr(dline,"rep")) {
|
||||
CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip+size, true);
|
||||
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip, true);
|
||||
debugging=false;
|
||||
DrawCode();
|
||||
DOSBOX_SetNormalLoop();
|
||||
@ -206,56 +409,13 @@ static bool StepOver()
|
||||
return false;
|
||||
};
|
||||
|
||||
bool DEBUG_BreakPoint(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)
|
||||
bool DEBUG_ExitLoop(void)
|
||||
{
|
||||
PhysPt where=SegPhys(cs)+reg_eip-2;
|
||||
bool found=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 (exitLoop) {
|
||||
exitLoop = false;
|
||||
return true;
|
||||
}
|
||||
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 false;
|
||||
};
|
||||
|
||||
/********************/
|
||||
@ -338,7 +498,7 @@ static void DrawCode(void)
|
||||
wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY));
|
||||
codeViewData.cursorSeg = codeViewData.useCS;
|
||||
codeViewData.cursorOfs = disEIP;
|
||||
} else if (IsBreakpoint(start)) {
|
||||
} else if (CBreakpoint::IsBreakpointDrawn(start)) {
|
||||
wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED));
|
||||
} else {
|
||||
wattrset(dbg.win_code,0);
|
||||
@ -440,7 +600,7 @@ bool ParseCommand(char* str)
|
||||
found+=3;
|
||||
Bit16u seg = GetHexValue(found,found);found++; // skip ":"
|
||||
Bit32u ofs = GetHexValue(found,found);
|
||||
AddBreakpoint(seg,ofs,false);
|
||||
CBreakpoint::AddBreakpoint(seg,ofs,false);
|
||||
LOG_DEBUG("DEBUG: Set breakpoint at %04X:%04X",seg,ofs);
|
||||
return true;
|
||||
}
|
||||
@ -450,10 +610,10 @@ bool ParseCommand(char* str)
|
||||
Bit8u intNr = GetHexValue(found,found); found++;
|
||||
Bit8u valAH = GetHexValue(found,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);
|
||||
} else {
|
||||
AddIntBreakpoint(intNr,valAH,false);
|
||||
CBreakpoint::AddIntBreakpoint(intNr,valAH,false);
|
||||
LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH);
|
||||
}
|
||||
return true;
|
||||
@ -463,19 +623,7 @@ bool ParseCommand(char* str)
|
||||
wprintw(dbg.win_out,"Breakpoint list:\n");
|
||||
wprintw(dbg.win_out,"-------------------------------------------------------------------------\n");
|
||||
Bit32u nr = 0;
|
||||
// iterate list
|
||||
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);
|
||||
CBreakpoint::ShowList();
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -484,29 +632,11 @@ bool ParseCommand(char* str)
|
||||
found+=5;
|
||||
Bit8u bpNr = GetHexValue(found,found);
|
||||
if ((bpNr==0x00) && (*found=='*')) { // Delete all
|
||||
(BPoints.clear)();
|
||||
CBreakpoint::DeleteAll();
|
||||
LOG_DEBUG("DEBUG: Breakpoints deleted.");
|
||||
} else {
|
||||
// delete single breakpoint
|
||||
Bit16u nr = 0;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
CBreakpoint::DeleteByIndex(bpNr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -528,6 +658,36 @@ bool ParseCommand(char* str)
|
||||
LOG_DEBUG("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs);
|
||||
return true;
|
||||
}
|
||||
found = strstr(str,"LOG ");
|
||||
if (found) { // Create Cpu log file
|
||||
found+=4;
|
||||
LOG_DEBUG("DEBUG: Starting log");
|
||||
DEBUG_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=='?')) {
|
||||
wprintw(dbg.win_out,"Debugger keys:\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,"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,"\n");
|
||||
wprintw(dbg.win_out,"Debugger commands (enter all values in hex or as register):\n");
|
||||
wprintw(dbg.win_out,"--------------------------------------------------------------------------\n");
|
||||
wprintw(dbg.win_out,"BP [segment]:[offset] - Set breakpoint\n");
|
||||
@ -547,6 +706,8 @@ bool ParseCommand(char* str)
|
||||
wprintw(dbg.win_out,"BPLIST - List breakpoints\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,"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");
|
||||
wrefresh(dbg.win_out);
|
||||
return TRUE;
|
||||
@ -621,6 +782,9 @@ Bit32u DEBUG_CheckKeys(void) {
|
||||
case 'H' : strcpy(codeViewData.inputStr,"H ");
|
||||
ParseCommand(codeViewData.inputStr);
|
||||
break;
|
||||
case 'T' : DEBUG_RaiseTimerIrq();
|
||||
LOG_DEBUG("Debug: Timer Int started.");
|
||||
break;
|
||||
|
||||
case 0x0A : // Return : input
|
||||
codeViewData.inputMode = true;
|
||||
@ -636,23 +800,25 @@ Bit32u DEBUG_CheckKeys(void) {
|
||||
break;
|
||||
case KEY_F(5): // Run Programm
|
||||
debugging=false;
|
||||
SetBreakpoints();
|
||||
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
|
||||
DOSBOX_SetNormalLoop();
|
||||
break;
|
||||
case KEY_F(9): // Set/Remove TBreakpoint
|
||||
{ PhysPt ptr = PhysMake(codeViewData.cursorSeg,codeViewData.cursorOfs);
|
||||
if (IsBreakpoint(ptr)) DeleteBreakpoint(ptr);
|
||||
else AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false);
|
||||
if (CBreakpoint::IsBreakpoint(ptr)) CBreakpoint::DeleteBreakpoint(ptr);
|
||||
else CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false);
|
||||
}
|
||||
break;
|
||||
case KEY_F(10): // Step over inst
|
||||
if (StepOver()) return 0;
|
||||
else {
|
||||
skipFirstInstruction = true; // for heavy debugger
|
||||
Bitu ret=(*cpudecoder)(1);
|
||||
SetCodeWinStart();
|
||||
}
|
||||
break;
|
||||
case KEY_F(11): // trace into
|
||||
skipFirstInstruction = true; // for heavy debugger
|
||||
ret = (*cpudecoder)(1);
|
||||
SetCodeWinStart();
|
||||
break;
|
||||
@ -675,8 +841,8 @@ Bitu DEBUG_Loop(void) {
|
||||
Bit32u oldEIP = reg_eip;
|
||||
PIC_runIRQs();
|
||||
if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) {
|
||||
AddBreakpoint(oldCS,oldEIP,true);
|
||||
SetBreakpoints();
|
||||
CBreakpoint::AddBreakpoint(oldCS,oldEIP,true);
|
||||
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
|
||||
debugging=false;
|
||||
DOSBOX_SetNormalLoop();
|
||||
return 0;
|
||||
@ -686,13 +852,13 @@ Bitu DEBUG_Loop(void) {
|
||||
}
|
||||
|
||||
void DEBUG_Enable(void) {
|
||||
|
||||
debugging=true;
|
||||
SetCodeWinStart();
|
||||
DEBUG_DrawScreen();
|
||||
DOSBOX_SetLoop(&DEBUG_Loop);
|
||||
}
|
||||
|
||||
|
||||
void DEBUG_DrawScreen(void) {
|
||||
DrawRegisters();
|
||||
DrawData();
|
||||
@ -702,24 +868,142 @@ static void DEBUG_RaiseTimerIrq(void) {
|
||||
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
|
||||
WIN32_Console();
|
||||
#endif
|
||||
#endif
|
||||
memset((void *)&dbg,0,sizeof(dbg));
|
||||
debugging=false;
|
||||
dbg.active_win=3;
|
||||
input_count=0;
|
||||
/* Start the Debug Gui */
|
||||
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();
|
||||
/* Add some keyhandlers */
|
||||
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable);
|
||||
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
|
||||
/* Clear the TBreakpoint list */
|
||||
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
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
void DEBUG_ShowMsg(char * msg) {
|
||||
char buf[1024];
|
||||
strcpy(buf,msg);
|
||||
strcat(buf,"\n");
|
||||
|
||||
waddstr(dbg.win_out,buf);
|
||||
wprintw(dbg.win_out," %d\n",cycle_count);
|
||||
|
172
src/dos/dos.cpp
172
src/dos/dos.cpp
@ -29,19 +29,17 @@
|
||||
#include "dos_inc.h"
|
||||
|
||||
DOS_Block dos;
|
||||
DOS_InfoBlock dosInfoBlock;
|
||||
DOS_InfoBlock dos_infoblock;
|
||||
|
||||
static Bit8u dos_copybuf[0x10000];
|
||||
static Bitu call_20,call_21,call_theend;
|
||||
Bit8u dos_copybuf[0x10000];
|
||||
static Bitu call_20,call_21;
|
||||
|
||||
void DOS_SetError(Bit16u code) {
|
||||
dos.errorcode=code;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#define DOSNAMEBUF 256
|
||||
static Bitu DOS_21Handler(void) {
|
||||
//TODO KEYBOARD Check for break
|
||||
char name1[DOSNAMEBUF+1];
|
||||
char name2[DOSNAMEBUF+1];
|
||||
switch (reg_ah) {
|
||||
@ -151,7 +149,7 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -166,14 +164,13 @@ static Bitu DOS_21Handler(void) {
|
||||
reg_al=26;
|
||||
break;
|
||||
case 0x0f: /* Open File using FCB */
|
||||
if(DOS_FCBOpen(SegValue(ds),reg_dx)){
|
||||
if(DOS_FCBOpenCreate(SegValue(ds),reg_dx)){
|
||||
reg_al=0;
|
||||
}else{
|
||||
reg_al=0xff;
|
||||
}
|
||||
LOG_DEBUG("DOS:0x0f FCB-fileopen used, result:al=%d",reg_al);
|
||||
break;
|
||||
|
||||
case 0x10: /* Close File using FCB */
|
||||
if(DOS_FCBClose(SegValue(ds),reg_dx)){
|
||||
reg_al=0;
|
||||
@ -182,7 +179,6 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
LOG_DEBUG("DOS:0x10 FCB-fileclose used, result:al=%d",reg_al);
|
||||
break;
|
||||
|
||||
case 0x11: /* Find First Matching File using FCB */
|
||||
if(DOS_FCBFindFirst(SegValue(ds),reg_dx)){
|
||||
reg_al=0;
|
||||
@ -191,7 +187,6 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
LOG_DEBUG("DOS:0x11 FCB-FindFirst used, result:al=%d",reg_al);
|
||||
break;
|
||||
|
||||
case 0x12: /* Find Next Matching File using FCB */
|
||||
if(DOS_FCBFindNext(SegValue(ds),reg_dx)){
|
||||
reg_al=0;
|
||||
@ -200,23 +195,59 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
LOG_DEBUG("DOS:0x12 FCB-FindNext used, result:al=%d",reg_al);
|
||||
break;
|
||||
|
||||
case 0x13: /* Delete File using FCB */
|
||||
case 0x14: /* Sequential read from FCB */
|
||||
case 0x15: /* Sequential write to FCB */
|
||||
case 0x16: /* Create or truncate file using FCB */
|
||||
case 0x17: /* Rename file using FCB */
|
||||
case 0x21: /* Read random record from FCB */
|
||||
case 0x22: /* Write random record to FCB */
|
||||
case 0x23: /* Get file size for FCB */
|
||||
case 0x24: /* Set Random Record number for FCB */
|
||||
case 0x27: /* Random block read from FCB */
|
||||
case 0x28: /* Random Block read to FCB */
|
||||
LOG_ERROR("DOS:Unhandled call %02X, FCB Stuff",reg_ah);
|
||||
reg_al=0xff; /* FCB Calls FAIL */
|
||||
//CALLBACK_SCF(true); not needed.
|
||||
if (DOS_FCBDeleteFile(SegValue(ds),reg_dx)) reg_al = 0x00;
|
||||
else reg_al = 0xFF;
|
||||
break;
|
||||
case 0x14: /* Sequential read from FCB */
|
||||
reg_al = DOS_FCBRead(SegValue(ds),reg_dx,0);
|
||||
LOG_DEBUG("DOS:0x14 FCB-Read used, result:al=%d",reg_al);
|
||||
break;
|
||||
case 0x15: /* Sequential write to FCB */
|
||||
if (DOS_FCBWrite(SegValue(ds),reg_dx,0)) reg_al = 0x00;
|
||||
else reg_al = 0x01;
|
||||
LOG_DEBUG("DOS:0x15 FCB-Write used, result:al=%d",reg_al);
|
||||
break;
|
||||
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,®_cx,®_ax,®_dx)) reg_al=0xff;
|
||||
break;
|
||||
case 0x1c: /* Get allocation info for specific drive */
|
||||
if (!DOS_GetAllocationInfo(reg_dl,®_cx,®_ax,®_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;
|
||||
|
||||
case 0x29: /* Parse filename into FCB */
|
||||
{ Bit8u difference;
|
||||
char string[1024];
|
||||
@ -226,7 +257,6 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
LOG_DEBUG("DOS:29:FCB Parse Filename, result:al=%d",reg_al);
|
||||
break;
|
||||
|
||||
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 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */
|
||||
@ -239,26 +269,11 @@ static Bitu DOS_21Handler(void) {
|
||||
reg_al=DOS_GetDefaultDrive();
|
||||
break;
|
||||
case 0x1a: /* Set Disk Transfer Area Address */
|
||||
dos.dta=RealMakeSeg(ds,reg_dx);
|
||||
break;
|
||||
|
||||
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;
|
||||
{
|
||||
dos.dta=RealMakeSeg(ds,reg_dx);
|
||||
DOS_PSP psp(dos.psp);
|
||||
psp.SetDTA(dos.dta);
|
||||
}
|
||||
break;
|
||||
case 0x1f: /* Get drive parameter block for default 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));
|
||||
break;
|
||||
case 0x26: /* Create new PSP */
|
||||
DOS_NewPSP(reg_dx);
|
||||
DOS_NewPSP(reg_dx,DOS_PSP(dos.psp).GetSize());
|
||||
break;
|
||||
case 0x2a: /* Get System Date */
|
||||
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 */
|
||||
{
|
||||
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)) {
|
||||
MEM_BlockWrite(SegPhys(ds)+reg_dx,dos_copybuf,toread);
|
||||
reg_ax=toread;
|
||||
@ -457,6 +473,7 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x40: /* WRITE Write to file or device */
|
||||
{
|
||||
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);
|
||||
if (DOS_WriteFile(reg_bx,dos_copybuf,&towrite)) {
|
||||
reg_ax=towrite;
|
||||
@ -490,7 +507,6 @@ static Bitu DOS_21Handler(void) {
|
||||
break;
|
||||
}
|
||||
case 0x43: /* Get/Set file attributes */
|
||||
//TODO FIX THIS HACK
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
switch (reg_al)
|
||||
case 0x00: /* Get */
|
||||
@ -511,7 +527,7 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
break;
|
||||
case 0x44: /* IOCTL Functions */
|
||||
if (DOS_IOCTL(reg_al,reg_bx)) {
|
||||
if (DOS_IOCTL()) {
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
@ -535,7 +551,6 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
break;
|
||||
case 0x47: /* CWD Get current directory */
|
||||
//TODO Memory
|
||||
if (DOS_GetCurrentDir(reg_dl,name1)) {
|
||||
MEM_BlockWrite(SegPhys(ds)+reg_si,name1,strlen(name1)+1);
|
||||
reg_ax=0x0100;
|
||||
@ -581,9 +596,8 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x4b: /* EXEC Load and/or execute program */
|
||||
{
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
if (DOS_Execute(name1,(ParamBlock *)Phys2Host(SegPhys(es)+reg_bx),reg_al)) {
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
LOG_DEBUG("Execute %s %d",name1,reg_al);
|
||||
if (!DOS_Execute(name1,SegPhys(es)+reg_bx,reg_al)) {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
}
|
||||
@ -593,9 +607,7 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x4c: /* EXIT Terminate with return code */
|
||||
{
|
||||
if (DOS_Terminate(false)) {
|
||||
dos.return_code=reg_al;
|
||||
dos.return_mode=RETURN_EXIT;
|
||||
CALLBACK_SCF(false);
|
||||
/* This can't ever return false normally */
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
@ -609,7 +621,8 @@ static Bitu DOS_21Handler(void) {
|
||||
case 0x4e: /* FINDFIRST Find first matching file */
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
if (DOS_FindFirst(name1,reg_cx)) {
|
||||
CALLBACK_SCF(false);
|
||||
CALLBACK_SCF(false);
|
||||
reg_ax=0; /* Undocumented */
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
@ -617,7 +630,8 @@ static Bitu DOS_21Handler(void) {
|
||||
break;
|
||||
case 0x4f: /* FINDNEXT Find next matching file */
|
||||
if (DOS_FindNext()) {
|
||||
CALLBACK_SCF(false);
|
||||
CALLBACK_SCF(false);
|
||||
reg_ax=0xffff; /* Undocumented */
|
||||
} else {
|
||||
reg_ax=dos.errorcode;
|
||||
CALLBACK_SCF(true);
|
||||
@ -630,9 +644,9 @@ static Bitu DOS_21Handler(void) {
|
||||
reg_bx=dos.psp;
|
||||
break;
|
||||
case 0x52: { /* Get list of lists */
|
||||
Bit16u seg;
|
||||
dosInfoBlock.GetDIBPointer(seg,reg_bx);
|
||||
SegSet16(es,seg);
|
||||
RealPt addr=dos_infoblock.GetPointer();
|
||||
SegSet16(es,RealSeg(addr));
|
||||
reg_bx=RealOff(addr);
|
||||
LOG_DEBUG("Call is made for list of lists - let's hope for the best");
|
||||
break; }
|
||||
//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 */
|
||||
//YEAH RIGHT
|
||||
case 0x54: /* Get verify flag */
|
||||
case 0x55: /* Create Child PSP*/
|
||||
E_Exit("Unhandled Dos 21 call %02X",reg_ah);
|
||||
break;
|
||||
case 0x55: /* Create Child PSP*/
|
||||
DOS_NewPSP(reg_dx,reg_si);
|
||||
dos.psp = reg_dx;
|
||||
break;
|
||||
case 0x56: /* RENAME Rename file */
|
||||
MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF);
|
||||
MEM_StrCopy(SegPhys(es)+reg_di,name2,DOSNAMEBUF);
|
||||
@ -654,12 +671,28 @@ static Bitu DOS_21Handler(void) {
|
||||
}
|
||||
break;
|
||||
case 0x57: /* Get/Set File's Date and Time */
|
||||
reg_cx=0;
|
||||
reg_dx=0;
|
||||
LOG_DEBUG("DOS:57:Getting/Setting File Date is faked",reg_ah);
|
||||
if (reg_al==0x00) {
|
||||
if (DOS_GetFileDate(reg_bx,®_cx,®_dx)) {
|
||||
CALLBACK_SCF(false);
|
||||
} else {
|
||||
CALLBACK_SCF(true);
|
||||
};
|
||||
} else {
|
||||
reg_cx=0;
|
||||
reg_dx=0;
|
||||
LOG_DEBUG("DOS:57:Setting File Date is faked",reg_ah);
|
||||
}
|
||||
break;
|
||||
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;
|
||||
case 0x59: /* Get Extended error information */
|
||||
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();
|
||||
CALLBACK_Setup(call_20,DOS_20Handler,CB_IRET);
|
||||
RealSetVec(0x20,CALLBACK_RealPointer(call_20));
|
||||
@ -816,8 +850,8 @@ void DOS_Init(void) {
|
||||
|
||||
DOS_SetupFiles(); /* Setup system File tables */
|
||||
DOS_SetupDevices(); /* Setup dos devices */
|
||||
DOS_SetupMemory(); /* Setup first MCB */
|
||||
DOS_SetupTables();
|
||||
DOS_SetupMemory(); /* Setup first MCB */
|
||||
DOS_SetupPrograms();
|
||||
DOS_SetupMisc(); /* Some additional dos interrupts */
|
||||
DOS_SetDefaultDrive(25);
|
||||
|
@ -29,122 +29,73 @@
|
||||
dos work a bit easier.
|
||||
*/
|
||||
|
||||
#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 */
|
||||
void DOS_ParamBlock::Clear(void) {
|
||||
memset(&exec,0,sizeof(exec));
|
||||
memset(&overlay,0,sizeof(overlay));
|
||||
}
|
||||
|
||||
/* 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);
|
||||
void DOS_ParamBlock::LoadData(void) {
|
||||
exec.envseg=sGet(sExec,envseg);
|
||||
exec.cmdtail=sGet(sExec,cmdtail);
|
||||
exec.fcb1=sGet(sExec,fcb1);
|
||||
exec.fcb2=sGet(sExec,fcb2);
|
||||
exec.initsssp=sGet(sExec,initsssp);
|
||||
exec.initcsip=sGet(sExec,initcsip);
|
||||
overlay.loadseg=sGet(sOverlay,loadseg);
|
||||
overlay.relocation=sGet(sOverlay,relocation);
|
||||
}
|
||||
|
||||
union sParamBlock {
|
||||
struct {
|
||||
Bit16u loadseg;
|
||||
Bit16u relocation;
|
||||
} overlay;
|
||||
struct {
|
||||
Bit16u envseg;
|
||||
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)
|
||||
void DOS_ParamBlock::SaveData(void) {
|
||||
sSave(sExec,envseg,exec.envseg);
|
||||
sSave(sExec,cmdtail,exec.cmdtail);
|
||||
sSave(sExec,fcb1,exec.fcb1);
|
||||
sSave(sExec,fcb2,exec.fcb2);
|
||||
sSave(sExec,initsssp,exec.initsssp);
|
||||
sSave(sExec,initcsip,exec.initcsip);
|
||||
}
|
||||
|
||||
|
||||
class MemStruct {
|
||||
public:
|
||||
Bit8u GetIt(Bit8u,PhysPt addr) {
|
||||
return mem_readb(pt+addr);
|
||||
};
|
||||
Bit16u GetIt(Bit16u,PhysPt addr) {
|
||||
return mem_readw(pt+addr);
|
||||
};
|
||||
Bit32u GetIt(Bit32u,PhysPt addr) {
|
||||
return mem_readd(pt+addr);
|
||||
};
|
||||
void SaveIt(Bit8u,PhysPt addr,Bit8u val) {
|
||||
mem_writeb(pt+addr,val);
|
||||
};
|
||||
void SaveIt(Bit16u,PhysPt addr,Bit16u val) {
|
||||
mem_writew(pt+addr,val);
|
||||
};
|
||||
void SaveIt(Bit32u,PhysPt addr,Bit32u val) {
|
||||
mem_writed(pt+addr,val);
|
||||
};
|
||||
|
||||
void DOS_InfoBlock::SetLocation(Bit16u segment)
|
||||
{
|
||||
seg = segment;
|
||||
pt=PhysMake(seg,0);
|
||||
/* Clear the initual Block */
|
||||
for(Bitu i=0;i<sizeof(sDIB);i++) mem_writeb(pt+i,0xff);
|
||||
}
|
||||
|
||||
private:
|
||||
PhysPt pt;
|
||||
void DOS_InfoBlock::SetFirstMCB(Bit16u _firstmcb)
|
||||
{
|
||||
sSave(sDIB,firstMCB,_firstmcb);
|
||||
}
|
||||
|
||||
};
|
||||
void DOS_InfoBlock::SetfirstFileTable(RealPt _first_table){
|
||||
sSave(sDIB,firstFileTable,_first_table);
|
||||
}
|
||||
|
||||
RealPt DOS_InfoBlock::GetPointer(void)
|
||||
{
|
||||
return RealMake(seg,offsetof(sDIB,firstDPB));
|
||||
}
|
||||
|
||||
|
||||
class DOS_PSP :public MemStruct {
|
||||
public:
|
||||
DOS_PSP(Bit16u segment){NewPt(segment);};
|
||||
void NewPt(Bit16u segment);
|
||||
void MakeNew(Bit16u mem_size);
|
||||
Bit8u GetFileHandle(Bitu index);
|
||||
/* program Segment prefix */
|
||||
|
||||
private:
|
||||
Bit16u seg;
|
||||
PhysPt pt;
|
||||
};
|
||||
Bit16u DOS_PSP::rootpsp = 0;
|
||||
|
||||
void DOS_PSP::NewPt(Bit16u segment) {
|
||||
seg=segment;
|
||||
pt=PhysMake(segment,0);
|
||||
};
|
||||
|
||||
|
||||
|
||||
void DOS_PSP::MakeNew(Bit16u mem_size) {
|
||||
void DOS_PSP::MakeNew(Bit16u mem_size)
|
||||
{
|
||||
/* get previous */
|
||||
DOS_PSP prevpsp(dos.psp);
|
||||
/* Clear it first */
|
||||
Bitu i;
|
||||
/* Clear it first */
|
||||
for (i=0;i<256;i++) mem_writeb(pt+i,0);
|
||||
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 */
|
||||
sGet(sPSP,max_files);
|
||||
sSave(sPSP,exit[0],0xcd);
|
||||
sSave(sPSP,exit[1],0x20);
|
||||
sSave(sPSP,service[0],0xcd);
|
||||
@ -154,135 +105,259 @@ void DOS_PSP::MakeNew(Bit16u mem_size) {
|
||||
sSave(sPSP,psp_parent,dos.psp);
|
||||
sSave(sPSP,prev_psp,RealMake(dos.psp,0));
|
||||
/* terminate 22,break 23,crititcal error 24 address stored */
|
||||
sSave(sPSP,int_22,RealGetVec(0x22));
|
||||
sSave(sPSP,int_23,RealGetVec(0x23));
|
||||
sSave(sPSP,int_24,RealGetVec(0x24));
|
||||
/* Memory size */
|
||||
sSave(sPSP,next_seg,seg+mem_size);
|
||||
SaveVectors();
|
||||
/* Process DTA */
|
||||
sSave(sPSP,dta,RealMake(seg,128));
|
||||
/* User Stack pointer */
|
||||
//Copy from previous psp
|
||||
// mem_writed(pt+offsetof(sPSP,stack),
|
||||
|
||||
/* FCBs are filled with 0 */
|
||||
// ....
|
||||
/* Init file pointer and max_files */
|
||||
sSave(sPSP,file_table,RealMake(seg,offsetof(sPSP,files[0])));
|
||||
sSave(sPSP,max_files,20);
|
||||
/* Copy file table from calling process */
|
||||
for (i=0;i<20;i++) {
|
||||
Bit8u handle=0;
|
||||
// Bitu handle=dos.psp.GetFileHandle(i);
|
||||
sSave(sPSP,files[i],handle);
|
||||
}
|
||||
for (i=0;i<20;i++) SetFileHandle(i,0xff);
|
||||
|
||||
/* User Stack pointer */
|
||||
// if (prevpsp.GetSegment()!=0) sSave(sPSP,stack,prevpsp.GetStack());
|
||||
|
||||
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;
|
||||
PhysPt files=Real2Phys(sGet(sPSP,file_table));
|
||||
return mem_readb(files+index);
|
||||
};
|
||||
|
||||
#define FCB_EXTENDED (mem_readb(off)==0xFF ? 7:0)
|
||||
|
||||
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)
|
||||
void DOS_PSP::SetFileHandle(Bit16u index, Bit8u handle)
|
||||
{
|
||||
seg = segment;
|
||||
dib = (SDosInfoBlock*)HostMake(segment,0);
|
||||
Bit16u size = sizeof(SDosInfoBlock);
|
||||
memset(dib,0,sizeof(SDosInfoBlock));
|
||||
if (index<sGet(sPSP,max_files)) {
|
||||
PhysPt files=Real2Phys(sGet(sPSP,file_table));
|
||||
mem_writeb(files+index,handle);
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
offset = offsetof(SDosInfoBlock,firstDPB);
|
||||
/* Copy file table from calling process */
|
||||
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);
|
||||
};
|
||||
|
@ -21,12 +21,11 @@
|
||||
#include "mem.h"
|
||||
#include "dos_inc.h"
|
||||
#include "cpu.h"
|
||||
#if defined (_MSC_VER)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
#include "callback.h"
|
||||
#include "debug.h"
|
||||
|
||||
#pragma pack(1)
|
||||
struct EXE_Header {
|
||||
|
||||
Bit16u signature; /* EXE Signature MZ or ZM */
|
||||
Bit16u extrabytes; /* Bytes on the last page */
|
||||
Bit16u pages; /* Pages in file */
|
||||
@ -41,13 +40,8 @@ struct EXE_Header {
|
||||
Bit16u initCS;
|
||||
Bit16u reloctable;
|
||||
Bit16u overlay;
|
||||
}
|
||||
#if defined (_MSC_VER)
|
||||
;
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#pragma pack()
|
||||
#else
|
||||
__attribute__ ((packed));
|
||||
#endif
|
||||
|
||||
#define MAGIC1 0x5a4d
|
||||
#define MAGIC2 0x4d5a
|
||||
@ -63,32 +57,64 @@ __attribute__ ((packed));
|
||||
#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;
|
||||
}
|
||||
|
||||
@ -97,20 +123,19 @@ bool DOS_Terminate(bool tsr) {
|
||||
static bool MakeEnv(char * name,Bit16u * segment) {
|
||||
|
||||
/* 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;
|
||||
Bit16u envsize=1;
|
||||
bool parentenv=true;
|
||||
|
||||
if (*segment==0) {
|
||||
if (!psp->environment) parentenv=false; //environment seg=0
|
||||
envread=HostMake(psp->environment,0);
|
||||
if (!psp.GetEnvironment()) parentenv=false; //environment seg=0
|
||||
envread=HostMake(psp.GetEnvironment(),0);
|
||||
} else {
|
||||
if (!*segment) parentenv=false; //environment seg=0
|
||||
envread=HostMake(*segment,0);
|
||||
}
|
||||
|
||||
//TODO Make a good DOS first psp
|
||||
if (parentenv) {
|
||||
for (envsize=0; ;envsize++) {
|
||||
if (envsize>=MAXENV - ENV_KEEPFREE) {
|
||||
@ -132,319 +157,189 @@ static bool MakeEnv(char * name,Bit16u * segment) {
|
||||
}
|
||||
*((Bit16u *) envwrite)=1;
|
||||
envwrite+=2;
|
||||
//TODO put the filename here
|
||||
|
||||
return DOS_Canonicalize(name,(char *)envwrite);
|
||||
};
|
||||
|
||||
bool DOS_NewPSP(Bit16u pspseg) {
|
||||
PSP * newpsp=(PSP *)HostMake(pspseg,0);
|
||||
PSP * prevpsp=(PSP *)HostMake(dos.psp,0);
|
||||
|
||||
memset((void *)newpsp,0,sizeof(PSP));
|
||||
newpsp->exit[0]=0xcd;newpsp->exit[1]=0x20;
|
||||
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);
|
||||
bool DOS_NewPSP(Bit16u segment, Bit16u size)
|
||||
{
|
||||
DOS_PSP psp(segment);
|
||||
psp.MakeNew(size);
|
||||
DOS_PSP psp_parent(psp.GetParent());
|
||||
psp.CopyFileTable(&psp_parent);
|
||||
return true;
|
||||
};
|
||||
|
||||
static void SetupPSP(Bit16u pspseg,Bit16u memsize,Bit16u envseg) {
|
||||
|
||||
PSP * psp=(PSP *)HostMake(pspseg,0);
|
||||
/* Fix the PSP index of this MCB */
|
||||
/* Fix the PSP for psp and environment MCB's */
|
||||
MCB * pspmcb=(MCB *)HostMake(pspseg-1,0);
|
||||
pspmcb->psp_segment=pspseg;
|
||||
MCB * envmcb=(MCB *)HostMake(envseg-1,0);
|
||||
envmcb->psp_segment=pspseg;
|
||||
|
||||
memset((void *)psp,0,sizeof(PSP));
|
||||
Bit32u i;
|
||||
|
||||
psp->exit[0]=0xcd;psp->exit[1]=0x20;
|
||||
psp->mem_size=memsize+pspseg;
|
||||
psp->environment=envseg;
|
||||
|
||||
psp->int_22=RealGetVec(0x22);
|
||||
psp->int_23=RealGetVec(0x23);
|
||||
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));
|
||||
DOS_PSP psp(pspseg);
|
||||
psp.MakeNew(memsize);
|
||||
psp.SetEnvironment(envseg);
|
||||
psp.SetFileHandle(STDIN ,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDOUT,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDERR,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDAUX,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDNUL,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDPRN,DOS_FindDevice("CON"));
|
||||
/* Save old DTA in psp */
|
||||
psp->dta=dos.dta;
|
||||
|
||||
psp.SetDTA(dos.dta);
|
||||
/* Setup the DTA */
|
||||
dos.dta=RealMake(pspseg,0x80);
|
||||
}
|
||||
|
||||
static void SetupCMDLine(Bit16u pspseg,ParamBlock * block) {
|
||||
PSP * psp=(PSP *)HostMake(pspseg,0);
|
||||
|
||||
if (block->exec.cmdtail) {
|
||||
memcpy((void *)&psp->cmdtail,(void *)Real2Host(block->exec.cmdtail),128);
|
||||
} else {
|
||||
char temp[]="";
|
||||
psp->cmdtail.count=strlen(temp);
|
||||
strcpy((char *)&psp->cmdtail.buffer,temp);
|
||||
psp->cmdtail.buffer[0]=0x0d;
|
||||
|
||||
}
|
||||
static void SetupCMDLine(Bit16u pspseg,DOS_ParamBlock & block)
|
||||
{
|
||||
DOS_PSP psp(pspseg);
|
||||
// if cmdtail==0 it will inited as empty in SetCommandTail
|
||||
psp.SetCommandTail(block.exec.cmdtail);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static bool COM_Load(char * name,ParamBlock * block,Bit8u flag) {
|
||||
Bit16u fhandle;
|
||||
Bit16u size;Bit16u readsize;
|
||||
Bit16u envseg,comseg;
|
||||
Bit32u pos;
|
||||
|
||||
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;
|
||||
/* 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);
|
||||
} else {
|
||||
comseg=block->overlay.loadseg;
|
||||
bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) {
|
||||
EXE_Header head;Bitu i;
|
||||
Bit16u fhandle;Bit16u len;Bit32u pos;
|
||||
Bit16u pspseg,envseg,loadseg,memsize,readsize;
|
||||
HostPt loadaddress;RealPt relocpt;
|
||||
Bitu headersize,imagesize;
|
||||
DOS_ParamBlock block(block_pt);
|
||||
block.LoadData();
|
||||
if (flags!=LOADNGO && flags!=OVERLAY) {
|
||||
E_Exit("DOS:Not supported execute mode %d for file %s",flags,name);
|
||||
}
|
||||
/* 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;
|
||||
/* Check for EXE or COM File */
|
||||
bool iscom=false;
|
||||
if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false;
|
||||
|
||||
size=sizeof(EXE_Header);
|
||||
if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&size)) {
|
||||
len=sizeof(EXE_Header);
|
||||
if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&len)) {
|
||||
DOS_CloseFile(fhandle);
|
||||
return false;
|
||||
}
|
||||
if (!DOS_CloseFile(fhandle)) return false;
|
||||
if (size<sizeof(EXE_Header)) iscom=true;
|
||||
if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true;
|
||||
|
||||
if (iscom) {
|
||||
return COM_Load(name,block,flags);
|
||||
|
||||
} else {
|
||||
return EXE_Load(name,block,flags);
|
||||
/* Convert the header to correct endian, i hope this works */
|
||||
HostPt endian=(HostPt)&head;
|
||||
for (i=0;i<sizeof(EXE_Header)/2;i++) {
|
||||
*((Bit16u *)endian)=readw(endian);
|
||||
endian+=2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -30,44 +30,46 @@
|
||||
|
||||
#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_Drive * Drives[DOS_DRIVES];
|
||||
static Bit8u CurrentDrive=2; //Init on C:
|
||||
|
||||
|
||||
Bit8u DOS_GetDefaultDrive(void) {
|
||||
return CurrentDrive;
|
||||
return dos.current_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) {
|
||||
//TODO Hope this is ok :)
|
||||
char tempdir[DOS_PATHLENGTH];
|
||||
char upname[DOS_PATHLENGTH];
|
||||
Bit32u r=0;Bit32u w=0;Bit32u namestart=0;
|
||||
bool hasdrive=false;
|
||||
*drive=CurrentDrive;
|
||||
char tempdir[128];
|
||||
//TODO Maybe check for illegal characters
|
||||
Bitu r,w;
|
||||
*drive=dos.current_drive;
|
||||
/* First get the drive */
|
||||
if (name[1]==':') {
|
||||
*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)) {
|
||||
Bit8u c=name[r++];
|
||||
if ((c>='a') && (c<='z')) {upname[w++]=c-32;continue;}
|
||||
if ((c>='A') && (c<='Z')) {upname[w++]=c;continue;}
|
||||
if ((c>='0') && (c<='9')) {upname[w++]=c;continue;}
|
||||
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 '/':
|
||||
upname[w++]='\\';
|
||||
break;
|
||||
@ -83,15 +85,9 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r>=DOS_PATHLENGTH) { DOS_SetError(DOSERR_PATH_NOT_FOUND);return false; }
|
||||
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 */
|
||||
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);
|
||||
else fullname[0]=0;
|
||||
Bit32u lastdir=0;Bit32u t=0;
|
||||
@ -126,8 +122,13 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) {
|
||||
lastdir=strlen(fullname);
|
||||
//TODO Maybe another check for correct type because of .... stuff
|
||||
if (lastdir!=0) strcat(fullname,"\\");
|
||||
char * ext=strchr(tempdir,'.');
|
||||
if (ext) {
|
||||
ext[4]=0;
|
||||
Bitu blah=strlen(tempdir);
|
||||
if (strlen(tempdir)>12) memmove(tempdir+8,ext,5);
|
||||
} else tempdir[8]=0;
|
||||
strcat(fullname,tempdir);
|
||||
|
||||
tempdir[0]=0;
|
||||
w=0;r++;
|
||||
continue;
|
||||
@ -181,21 +182,36 @@ bool DOS_Rename(char * oldname,char * newname) {
|
||||
if (Drives[drivenew]->Rename(fullold,fullnew)) return true;
|
||||
DOS_SetError(DOSERR_FILE_NOT_FOUND);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
bool DOS_FindFirst(char * search,Bit16u attr) {
|
||||
DOS_DTA dta(dos.dta);
|
||||
Bit8u drive;char fullsearch[DOS_PATHLENGTH];
|
||||
char dir[DOS_PATHLENGTH];char pattern[DOS_PATHLENGTH];
|
||||
if (!DOS_MakeName(search,fullsearch,&drive)) return false;
|
||||
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
|
||||
dtablock->sattr=attr | DOS_ATTR_ARCHIVE;
|
||||
dtablock->sdrive=drive;
|
||||
return Drives[drive]->FindFirst(fullsearch,dtablock);
|
||||
};
|
||||
/* Split the search in dir and pattern */
|
||||
char * find_last;
|
||||
find_last=strrchr(fullsearch,'\\');
|
||||
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) {
|
||||
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
|
||||
return Drives[dtablock->sdrive]->FindNext(dtablock);
|
||||
};
|
||||
DOS_DTA dta(dos.dta);
|
||||
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) {
|
||||
@ -269,9 +285,9 @@ bool DOS_CloseFile(Bit16u entry) {
|
||||
};
|
||||
//TODO Figure this out with devices :)
|
||||
|
||||
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||
Bit8u * table=Real2Host(psp->file_table);
|
||||
table[entry]=0xFF;
|
||||
DOS_PSP psp(dos.psp);
|
||||
psp.SetFileHandle(entry,0xff);
|
||||
|
||||
/* Devices won't allow themselves to be closed or killed */
|
||||
if (Files[handle]->Close()) {
|
||||
delete Files[handle];
|
||||
@ -282,7 +298,7 @@ bool DOS_CloseFile(Bit16u entry) {
|
||||
|
||||
bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
|
||||
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;
|
||||
/* Check for a free file handle */
|
||||
Bit8u handle=DOS_FILES;Bit8u i;
|
||||
@ -297,21 +313,14 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
|
||||
return false;
|
||||
}
|
||||
/* We have a position in the main table now find one in the psp table */
|
||||
Bit8u * table=Real2Host(psp->file_table);
|
||||
*entry=0xff;
|
||||
for (i=0;i<psp->max_files;i++) {
|
||||
if (table[i]==0xFF) {
|
||||
*entry=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*entry = psp.FindFreeFileEntry();
|
||||
if (*entry==0xff) {
|
||||
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
|
||||
return false;
|
||||
}
|
||||
bool foundit=Drives[drive]->FileCreate(&Files[handle],fullname,attributes);
|
||||
if (foundit) {
|
||||
table[*entry]=handle;
|
||||
psp.SetFileHandle(*entry,handle);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -320,7 +329,9 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) {
|
||||
|
||||
bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
|
||||
/* 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);
|
||||
bool device=false;char fullname[DOS_PATHLENGTH];Bit8u drive;Bit8u i;
|
||||
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 */
|
||||
Bit8u * table=Real2Host(psp->file_table);
|
||||
*entry=0xff;
|
||||
for (i=0;i<psp->max_files;i++) {
|
||||
if (table[i]==0xFF) {
|
||||
*entry=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*entry = psp.FindFreeFileEntry();
|
||||
if (*entry==0xff) {
|
||||
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
|
||||
return false;
|
||||
@ -356,7 +360,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) {
|
||||
bool exists=false;
|
||||
if (!device) exists=Drives[drive]->FileOpen(&Files[handle],fullname,flags);
|
||||
if (exists || device ) {
|
||||
table[*entry]=handle;
|
||||
psp.SetFileHandle(*entry,handle);
|
||||
return true;
|
||||
} else {
|
||||
DOS_SetError(DOSERR_FILE_NOT_FOUND);
|
||||
@ -391,7 +395,7 @@ bool DOS_Canonicalize(char * name,char * big) {
|
||||
big[2]='\\';
|
||||
strcpy(&big[3],fullname);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free) {
|
||||
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);
|
||||
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) {
|
||||
@ -413,20 +417,13 @@ bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry) {
|
||||
DOS_SetError(DOSERR_INVALID_HANDLE);
|
||||
return false;
|
||||
};
|
||||
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||
Bit8u * table=Real2Host(psp->file_table);
|
||||
*newentry=0xff;
|
||||
for (Bit16u i=0;i<psp->max_files;i++) {
|
||||
if (table[i]==0xFF) {
|
||||
*newentry=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
DOS_PSP psp(dos.psp);
|
||||
*newentry = psp.FindFreeFileEntry();
|
||||
if (*newentry==0xff) {
|
||||
DOS_SetError(DOSERR_TOO_MANY_OPEN_FILES);
|
||||
return false;
|
||||
}
|
||||
table[*newentry]=handle;
|
||||
psp.SetFileHandle(*newentry,handle);
|
||||
return true;
|
||||
};
|
||||
|
||||
@ -449,17 +446,15 @@ bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) {
|
||||
DOS_CloseFile(newentry);
|
||||
return false;
|
||||
};
|
||||
PSP * psp=(PSP *)HostMake(dos.psp,0);
|
||||
Bit8u * table=Real2Host(psp->file_table);
|
||||
table[newentry]=(Bit8u)entry;
|
||||
DOS_PSP psp(dos.psp);
|
||||
psp.SetFileHandle(newentry,(Bit8u)entry);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
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 */
|
||||
char * tempname;
|
||||
tempname=name+strlen(name);
|
||||
@ -472,41 +467,26 @@ bool DOS_CreateTempFile(char * name,Bit16u * entry) {
|
||||
for (i=9;i<12;i++) {
|
||||
tempname[i]=(rand()%26)+'A';
|
||||
}
|
||||
tempname[13]=0;
|
||||
tempname[12]=0;
|
||||
} while (!DOS_CreateFile(name,0,entry));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if 1
|
||||
static bool FCB_MakeName (DOS_FCB* fcb, char* outname, Bit8u* outdrive){
|
||||
char naam[15];
|
||||
Bit8s teller=0;
|
||||
Bit8u drive=fcb->Get_drive();
|
||||
if(drive!=0){
|
||||
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);
|
||||
|
||||
static bool FCB_MakeName2 (DOS_FCB & fcb, char* outname, Bit8u* outdrive){
|
||||
char short_name[DOS_FCBNAME];
|
||||
fcb.GetName(short_name);
|
||||
return DOS_MakeName(short_name,outname, outdrive);
|
||||
}
|
||||
|
||||
#define FCB_SEP ":.;,=+"
|
||||
#define ILLEGAL ":.;,=+ \t/\"[]<>|"
|
||||
|
||||
static bool isvalid(const char* in){
|
||||
|
||||
static bool isvalid(const char in){
|
||||
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){
|
||||
@ -515,218 +495,352 @@ static void vullen (char* veld,char* pveld){
|
||||
}
|
||||
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){
|
||||
char* backup;
|
||||
backup=string;
|
||||
|
||||
char * string_begin=string;Bit8u ret=0;
|
||||
DOS_FCB fcb(seg,offset);
|
||||
Bit8u retwaarde=0;
|
||||
char naam[9]=" ";
|
||||
char ext[4]=" ";
|
||||
if(parser & 1) { //ignore leading seperator
|
||||
char sep[] = FCB_SEP;
|
||||
char a[2];
|
||||
a[0]= *string;a[1]='\0';
|
||||
if (strcspn(a,sep)==0) string++;
|
||||
}
|
||||
if((!(parser &4)) ==true){ // fill name with spaces if no name
|
||||
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++;
|
||||
if( *(string+1)==':') {
|
||||
Bit8u drive=toupper(*string);
|
||||
if( (drive>'Z') | (drive<'A') | (Drives[drive-'A']==NULL)) {
|
||||
*change=string-backup;
|
||||
return 0xFF;
|
||||
}
|
||||
fcb.Set_drive(drive-'A'+1);
|
||||
string+=2;
|
||||
}
|
||||
//startparsing
|
||||
char* pnaam=naam;
|
||||
while(isvalid(string)==true) {
|
||||
if(*string=='*'){
|
||||
vullen(naam,pnaam); //fill with ????
|
||||
string++;
|
||||
retwaarde=1;
|
||||
break;
|
||||
}
|
||||
|
||||
*pnaam=*string;
|
||||
pnaam++;
|
||||
string++;
|
||||
}
|
||||
fcb.Set_filename(naam);
|
||||
if((*string=='.')==false) {
|
||||
*change=string-backup;
|
||||
return retwaarde;
|
||||
}
|
||||
//extension exist
|
||||
string++;
|
||||
char* pext=ext;
|
||||
while(isvalid(string)==true) {
|
||||
if(*string=='*'){
|
||||
vullen(ext,pext); //fill with ????
|
||||
string++;
|
||||
retwaarde=1;
|
||||
break;
|
||||
}
|
||||
|
||||
*pext=*string;
|
||||
pext++;
|
||||
string++;
|
||||
}
|
||||
fcb.Set_ext(ext);
|
||||
*change=string-backup;
|
||||
return retwaarde;
|
||||
|
||||
|
||||
|
||||
bool hasdrive,hasname,hasext;
|
||||
hasdrive=hasname=hasext=false;
|
||||
Bitu index;bool finished;Bit8u fill;
|
||||
/* First get the old data from the fcb */
|
||||
#pragma pack (1)
|
||||
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';
|
||||
if (strcspn(a,sep)==0) string++;
|
||||
}
|
||||
/* strip leading spaces */
|
||||
while((*string==' ')||(*string=='\t')) string++;
|
||||
/* Check for a drive */
|
||||
if (string[1]==':') {
|
||||
fcb_name.part.drive[0]=0;
|
||||
hasdrive=true;
|
||||
if (isalpha(string[0]) && Drives[toupper(string[0])-'A']) {
|
||||
fcb_name.part.drive[0]=toupper(string[0])-'A'+1;
|
||||
} else ret=0xff;
|
||||
string+=2;
|
||||
}
|
||||
/* Special checks for . and .. */
|
||||
if (string[0]=='.') {
|
||||
string++;
|
||||
if (!string[0]) {
|
||||
hasname=true;
|
||||
ret=PARSE_RET_NOWILD;
|
||||
strcpy(fcb_name.part.name,". ");
|
||||
goto savefcb;
|
||||
}
|
||||
if (string[1]=='.' && !string[1]) {
|
||||
string++;
|
||||
hasname=true;
|
||||
ret=PARSE_RET_NOWILD;
|
||||
strcpy(fcb_name.part.name,".. ");
|
||||
goto savefcb;
|
||||
}
|
||||
goto checkext;
|
||||
}
|
||||
/* 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++;
|
||||
} else {
|
||||
fcb_name.part.name[index]=fill;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (!(string[0]=='.')) goto savefcb;
|
||||
string++;
|
||||
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);
|
||||
Bit8u drive;
|
||||
char fullname[DOS_PATHLENGTH];
|
||||
if(!FCB_MakeName (&fcb, fullname, &drive)) return false;
|
||||
if(!Drives[drive]->FileExists(fullname)) return false; //not really needed as stat will error.
|
||||
char shortname[DOS_FCBNAME];Bit16u handle;
|
||||
fcb.GetName(shortname);
|
||||
if (!DOS_OpenFile(shortname,2,&handle)) return false;
|
||||
fcb.FileOpen((Bit8u)handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool DOS_FCBClose(Bit16u seg,Bit16u offset)
|
||||
{ DOS_FCB fcb(seg,offset);
|
||||
Bit8u drive;
|
||||
char fullname[DOS_PATHLENGTH];
|
||||
if(!FCB_MakeName (&fcb, fullname, &drive)) return false;
|
||||
if(!Drives[drive]->FileExists(fullname)) return false;
|
||||
|
||||
return true;}
|
||||
bool DOS_FCBClose(Bit16u seg,Bit16u offset) {
|
||||
DOS_FCB fcb(seg,offset);
|
||||
Bit8u fhandle;
|
||||
fcb.FileClose(fhandle);
|
||||
DOS_CloseFile(fhandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset)
|
||||
{
|
||||
DOS_FCB* fcb = new DOS_FCB(seg,offset);
|
||||
Bit8u drive;
|
||||
Bitu i;
|
||||
char fullname[DOS_PATHLENGTH];
|
||||
FCB_MakeName (fcb, fullname, &drive);
|
||||
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
|
||||
dtablock->sattr=DOS_ATTR_ARCHIVE;
|
||||
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;
|
||||
|
||||
DOS_FCB fcb(seg,offset);
|
||||
RealPt old_dta=dos.dta;dos.dta=dos.tables.tempdta;
|
||||
char name[DOS_FCBNAME];fcb.GetName(name);
|
||||
bool ret=DOS_FindFirst(name,DOS_ATTR_ARCHIVE);
|
||||
dos.dta=old_dta;
|
||||
if (ret) SaveFindResult(fcb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DOS_FCBFindNext(Bit16u seg,Bit16u offset)
|
||||
{
|
||||
DOS_FCB* fcb = new DOS_FCB(seg,offset);
|
||||
Bit8u drive;
|
||||
Bitu i;
|
||||
char fullname[DOS_PATHLENGTH];
|
||||
FCB_MakeName (fcb, fullname, &drive);
|
||||
DTA_FindBlock * dtablock=(DTA_FindBlock *)Real2Host(dos.dta);
|
||||
dtablock->sattr=DOS_ATTR_ARCHIVE;
|
||||
dtablock->sdrive=drive;
|
||||
DOS_FCB fcb(seg,offset);
|
||||
RealPt old_dta=dos.dta;dos.dta=dos.tables.tempdta;
|
||||
bool ret=DOS_FindNext();
|
||||
dos.dta=old_dta;
|
||||
if (ret) SaveFindResult(fcb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if(Drives[dtablock->sdrive]->FindNext(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++;}
|
||||
}
|
||||
Bit8u DOS_FCBRead(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_READ_NODATA;
|
||||
Bit16u toread=rec_size;
|
||||
if (!DOS_ReadFile(fhandle,dos_copybuf,&toread)) return FCB_READ_NODATA;
|
||||
if (toread==0) return FCB_READ_NODATA;
|
||||
if (toread<rec_size) {
|
||||
PhysPt fill=Real2Phys(dos.dta)+toread;
|
||||
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';
|
||||
|
||||
strcpy (naam,dtablock->name);
|
||||
i=strlen(dtablock->name);
|
||||
while(i!=8) {naam[i]=' '; i++;}
|
||||
delete fcb;
|
||||
DOS_FCB* fcbout= new DOS_FCB(Real2Phys(dos.dta));
|
||||
fcbout->Set_drive(drive +1);
|
||||
fcbout->Set_filename(naam);
|
||||
fcbout->Set_ext(ext);
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) {
|
||||
|
||||
DOS_FCB fcb(seg,offset);
|
||||
Bit32u random;Bit16u old_block;Bit8u old_rec;Bit8u error;
|
||||
/* 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));
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
bool DOS_FileExists(char * name) {
|
||||
|
||||
char fullname[DOS_PATHLENGTH];Bit8u drive;
|
||||
if (!DOS_MakeName(name,fullname,&drive)) return false;
|
||||
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) {
|
||||
if (Drives[drive]) {
|
||||
DOS_SetDefaultDrive(drive);
|
||||
return true;
|
||||
|
||||
} else {
|
||||
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) {
|
||||
/* Setup the File Handles */
|
||||
|
@ -26,16 +26,20 @@
|
||||
#define MAX_DEVICE 20
|
||||
static DOS_File * dos_devices[MAX_DEVICE];
|
||||
|
||||
bool DOS_IOCTL(Bit8u call,Bit16u entry) {
|
||||
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;
|
||||
};
|
||||
|
||||
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) {
|
||||
DOS_SetError(DOSERR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
if (!Files[handle]) {
|
||||
DOS_SetError(DOSERR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch(reg_al) {
|
||||
case 0x00: /* Get Device Information */
|
||||
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);
|
||||
reg_al=0xff;
|
||||
return true;
|
||||
case 0x0D: {
|
||||
PhysPt ptr = SegPhys(ds)+reg_dx;
|
||||
Bit8u drive = reg_bl ? reg_bl : DOS_GetDefaultDrive()+1; // A=1, B=2, C=3...
|
||||
switch (reg_cl) {
|
||||
case 0x60 : mem_writeb(ptr ,0x03); // special function
|
||||
mem_writeb(ptr+1,(drive>=3)?0x05:0x14); // fixed disc(5), 1.44 floppy(14)
|
||||
mem_writew(ptr+2,drive>=3); // nonremovable ?
|
||||
mem_writew(ptr+4,0x0000); // num of cylinders
|
||||
mem_writeb(ptr+6,0x00); // media type (00=other type)
|
||||
break;
|
||||
default : LOG_ERROR("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive);
|
||||
return false;
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
case 0x0D: /* Generic block device request */
|
||||
{
|
||||
PhysPt ptr = SegPhys(ds)+reg_dx;
|
||||
drive=reg_bl;if (!drive) drive=dos.current_drive;else drive--;
|
||||
switch (reg_cl) {
|
||||
case 0x60: /* Get Device parameters */
|
||||
mem_writeb(ptr ,0x03); // special function
|
||||
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_writeb(ptr+6,0x00); // media type (00=other type)
|
||||
break;
|
||||
default :
|
||||
LOG_ERROR("DOS:IOCTL Call 0D:%2X Drive %2X unhandled",reg_cl,drive);
|
||||
return false;
|
||||
}
|
||||
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:
|
||||
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;
|
||||
|
@ -99,7 +99,7 @@ bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks) {
|
||||
mcb_segment+=pmcb->size+1;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
|
||||
@ -135,7 +135,7 @@ bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
|
||||
*blocks=total;
|
||||
DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
bool DOS_FreeMemory(Bit16u segment) {
|
||||
@ -151,16 +151,11 @@ bool DOS_FreeMemory(Bit16u segment) {
|
||||
|
||||
|
||||
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->psp_segment=MCB_FREE; //Free
|
||||
mcb->size=0x9FFE - MEM_START;
|
||||
mcb->type=0x5a; //Last Block
|
||||
dos.firstMCB=MEM_START;
|
||||
|
||||
// Create Dos Info Block : maximum size 95 Bytes....
|
||||
dosInfoBlock.SetLocation(DOS_GetMemory(6));
|
||||
dosInfoBlock.SetFirstMCB(RealMake(dos.firstMCB,0));
|
||||
dos_infoblock.SetFirstMCB(MEM_START);
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,16 @@ static Bitu INT2A_Handler(void) {
|
||||
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) {
|
||||
/* Setup the dos multiplex interrupt */
|
||||
@ -61,9 +71,10 @@ void DOS_SetupMisc(void) {
|
||||
call_int2f=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_int2f,&INT2F_Handler,CB_IRET);
|
||||
RealSetVec(0x2f,CALLBACK_RealPointer(call_int2f));
|
||||
DOS_AddMultiplexHandler(DOS_MultiplexFunctions);
|
||||
/* Setup the dos network interrupt */
|
||||
call_int2a=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_int2a,&INT2A_Handler,CB_IRET);
|
||||
RealSetVec(0x2A<<2,CALLBACK_RealPointer(call_int2a));
|
||||
RealSetVec(0x2A,CALLBACK_RealPointer(call_int2a));
|
||||
};
|
||||
|
||||
|
@ -28,69 +28,97 @@
|
||||
|
||||
class MOUNT : public Program {
|
||||
public:
|
||||
MOUNT(PROGRAM_Info * program_info):Program(program_info){};
|
||||
void Run(void){
|
||||
void Run(void)
|
||||
{
|
||||
DOS_Drive * newdrive;char drive;
|
||||
|
||||
/* Parse the command line */
|
||||
/* if the command line is empty show current mounts */
|
||||
if (!*prog_info->cmd_line) {
|
||||
WriteOut("Current mounted drives are\n");
|
||||
if (!cmd->GetCount()) {
|
||||
WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_1"));
|
||||
for (int d=0;d<DOS_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;
|
||||
}
|
||||
std::string type="dir";
|
||||
cmd->FindString("-t",type,true);
|
||||
if (type=="floppy" || type=="dir") {
|
||||
Bit16u sizes[4];
|
||||
Bit8u mediaid;
|
||||
std::string str_size;
|
||||
if (type=="floppy") {
|
||||
str_size="512,1,2847,2847";/* All space free */
|
||||
mediaid=0xF0; /* Floppy 1.44 media */
|
||||
}
|
||||
if (type=="dir") {
|
||||
str_size="512,127,16513,1700";
|
||||
mediaid=0xF8; /* Hard Disk */
|
||||
}
|
||||
cmd->FindString("-size",str_size,true);
|
||||
char number[20];const char * scan=str_size.c_str();
|
||||
Bitu index=0;Bitu count=0;
|
||||
/* 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);
|
||||
|
||||
char drive; drive=toupper(*prog_info->cmd_line);
|
||||
|
||||
char * dir=strchr(prog_info->cmd_line,' '); if (dir) {
|
||||
if (!*dir) dir=0;
|
||||
else dir=trim(dir);
|
||||
}
|
||||
if (!isalpha(drive) || !dir) {
|
||||
WriteOut("Usage MOUNT Drive-Letter Local-Directory\nSo a MOUNT c c:\\windows mounts windows directory as the c: drive in DOSBox\n");
|
||||
return;
|
||||
};
|
||||
struct stat test;
|
||||
if (stat(dir,&test)) {
|
||||
WriteOut("Directory %s Doesn't exist",dir);
|
||||
return;
|
||||
}
|
||||
/* Not a switch so a normal directory/file */
|
||||
if (!(test.st_mode & S_IFDIR)) {
|
||||
WriteOut("%s isn't a directory",dir);
|
||||
return;
|
||||
if (!cmd->FindCommand(2,temp_line)) goto showusage;
|
||||
if (!temp_line.size()) goto showusage;
|
||||
struct stat test;
|
||||
if (stat(temp_line.c_str(),&test)) {
|
||||
WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_1"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
/* Not a switch so a normal directory/file */
|
||||
if (!(test.st_mode & S_IFDIR)) {
|
||||
WriteOut(MSG_Get("PROGRAM_MOUNT_ERROR_2"),temp_line.c_str());
|
||||
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']) {
|
||||
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;
|
||||
}
|
||||
char fulldir[DOS_PATHLENGTH];
|
||||
strcpy(fulldir,dir);
|
||||
static char theend[2]={CROSS_FILESPLIT,0};
|
||||
char * last=strrchr(fulldir,CROSS_FILESPLIT);
|
||||
if (!last || *(++last)) strcat(fulldir,theend);
|
||||
Drives[drive-'A']=new localDrive(fulldir);
|
||||
WriteOut("Mounting drive %c as %s\n",drive,fulldir);
|
||||
if (!newdrive) E_Exit("DOS:Can't create drive");
|
||||
Drives[drive-'A']=newdrive;
|
||||
/* Set the correct media byte in the table */
|
||||
mem_writeb(Real2Phys(dos.tables.mediaid)+drive-'A',newdrive->GetMediaByte());
|
||||
WriteOut("Drive %c mounted as %s\n",drive,newdrive->GetInfo());
|
||||
return;
|
||||
showusage:
|
||||
WriteOut(MSG_Get("PROGRAM_MOUNT_USAGE"));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
static void MOUNT_ProgramStart(PROGRAM_Info * info) {
|
||||
MOUNT * tempmount=new MOUNT(info);
|
||||
tempmount->Run() ;
|
||||
delete tempmount;
|
||||
static void MOUNT_ProgramStart(Program * * make) {
|
||||
*make=new MOUNT;
|
||||
}
|
||||
|
||||
class MEM : public Program {
|
||||
public:
|
||||
MEM(PROGRAM_Info * program_info):Program(program_info){};
|
||||
void Run(void) {
|
||||
/* Show conventional Memory */
|
||||
WriteOut("\n");
|
||||
Bit16u seg,blocks;blocks=0xffff;
|
||||
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 */
|
||||
reg_ax=0x4300;CALLBACK_RunRealInt(0x2f);
|
||||
if (reg_al==0x80) {
|
||||
@ -99,7 +127,7 @@ public:
|
||||
reg_ah=8;
|
||||
CALLBACK_RunRealFar(xms_seg,xms_off);
|
||||
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 */
|
||||
@ -108,34 +136,26 @@ public:
|
||||
DOS_CloseFile(handle);
|
||||
reg_ah=0x42;
|
||||
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_Info * info) {
|
||||
MEM mem(info);
|
||||
mem.Run();
|
||||
static void MEM_ProgramStart(Program * * make) {
|
||||
*make=new MEM;
|
||||
}
|
||||
|
||||
|
||||
#if !defined (WIN32) /* Unix */
|
||||
|
||||
class UPCASE : public Program {
|
||||
public:
|
||||
UPCASE(PROGRAM_Info * program_info);
|
||||
void Run(void);
|
||||
void upcasedir(char * directory);
|
||||
void upcasedir(const char * directory);
|
||||
};
|
||||
|
||||
|
||||
UPCASE::UPCASE(PROGRAM_Info * info):Program(info) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void UPCASE::upcasedir(char * directory) {
|
||||
void UPCASE::upcasedir(const char * directory) {
|
||||
DIR * sdir;
|
||||
char fullname[512];
|
||||
char newname[512];
|
||||
@ -143,10 +163,10 @@ void UPCASE::upcasedir(char * directory) {
|
||||
struct stat finfo;
|
||||
|
||||
if(!(sdir=opendir(directory))) {
|
||||
WriteOut("Failed to open directory %s\n",directory);
|
||||
WriteOut(MSG_Get("PROGRAM_UPCASE_ERROR_DIR"),directory);
|
||||
return;
|
||||
}
|
||||
WriteOut("Scanning directory %s\n",fullname);
|
||||
WriteOut(MSG_Get("PROGRAM_UPCASE_SCANNING_DIR"),fullname);
|
||||
while (tempdata=readdir(sdir)) {
|
||||
if (strcmp(tempdata->d_name,".")==0) continue;
|
||||
if (strcmp(tempdata->d_name,"..")==0) continue;
|
||||
@ -157,7 +177,7 @@ void UPCASE::upcasedir(char * directory) {
|
||||
strcat(newname,"/");
|
||||
upcase(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);
|
||||
stat(fullname,&finfo);
|
||||
if(S_ISDIR(finfo.st_mode)) {
|
||||
@ -171,42 +191,60 @@ void UPCASE::upcasedir(char * directory) {
|
||||
void UPCASE::Run(void) {
|
||||
/* First check if the directory exists */
|
||||
struct stat info;
|
||||
WriteOut("UPCASE 0.1 Directory case convertor.\n");
|
||||
if (!strlen(prog_info->cmd_line)) {
|
||||
WriteOut("Usage UPCASE [local directory]\n");
|
||||
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");
|
||||
WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_1"));
|
||||
if (!cmd->GetCount()) {
|
||||
WriteOut(MSG_Get("PROGRAM_UPCASE_USAGE"));
|
||||
return;
|
||||
}
|
||||
if (stat(prog_info->cmd_line,&info)) {
|
||||
WriteOut("%s doesn't exist\n",prog_info->cmd_line);
|
||||
cmd->FindCommand(1,temp_line);
|
||||
if (stat(temp_line.c_str(),&info)) {
|
||||
WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_ERROR_1"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
if(!S_ISDIR(info.st_mode)) {
|
||||
WriteOut("%s isn't a directory\n",prog_info->cmd_line);
|
||||
WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_ERROR_2"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
WriteOut("Converting the wrong directories can be very harmfull, please be carefull.\n");
|
||||
WriteOut("Are you really really sure you want to convert %s to upcase?Y/N\n",prog_info->cmd_line);
|
||||
WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_CHOICE"),temp_line.c_str());
|
||||
Bit8u key;Bit16u n=1;
|
||||
DOS_ReadFile(STDIN,&key,&n);
|
||||
if (toupper(key)=='Y') {
|
||||
upcasedir(prog_info->cmd_line);
|
||||
upcasedir(temp_line.c_str());
|
||||
} else {
|
||||
WriteOut("Okay better not do it.\n");
|
||||
WriteOut(MSG_Get("PROGRAM_UPCASE_RUN_NO"));
|
||||
}
|
||||
}
|
||||
|
||||
static void UPCASE_ProgramStart(PROGRAM_Info * info) {
|
||||
UPCASE * tempUPCASE=new UPCASE(info);
|
||||
tempUPCASE->Run();
|
||||
delete tempUPCASE;
|
||||
static void UPCASE_ProgramStart(Program * * make) {
|
||||
*make=new UPCASE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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("MEM.COM",MEM_ProgramStart);
|
||||
#if !defined (WIN32) /* Unix */
|
||||
|
@ -20,25 +20,18 @@
|
||||
#include "mem.h"
|
||||
#include "dos_inc.h"
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct DOS_TableCase {
|
||||
Bit16u size;
|
||||
Bit8u chars[256];
|
||||
}
|
||||
#if defined (_MSC_VER)
|
||||
;
|
||||
#pragma pack()
|
||||
#else
|
||||
__attribute__ ((packed));
|
||||
#endif
|
||||
|
||||
GCC_ATTRIBUTE (packed);
|
||||
#pragma pack ()
|
||||
|
||||
RealPt DOS_TableUpCase;
|
||||
RealPt DOS_TableLowCase;
|
||||
|
||||
static Bit16u dos_memseg=0xd000;
|
||||
static Bit16u dos_memseg;
|
||||
Bit16u DOS_GetMemory(Bit16u pages) {
|
||||
if (pages+dos_memseg>=0xe000) {
|
||||
E_Exit("DOS:Not enough memory for internal tables");
|
||||
@ -50,9 +43,21 @@ Bit16u DOS_GetMemory(Bit16u pages) {
|
||||
|
||||
|
||||
void DOS_SetupTables(void) {
|
||||
dos_memseg=0xd000;
|
||||
Bit16u seg;Bitu i;
|
||||
dos.tables.indosflag=RealMake(DOS_GetMemory(1),0);
|
||||
dos.tables.mediaid=RealMake(DOS_GetMemory(2),0);
|
||||
dos.tables.tempdta=RealMake(DOS_GetMemory(4),0);
|
||||
for (i=0;i<DOS_DRIVES;i++) mem_writeb(Real2Phys(dos.tables.mediaid)+i,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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include "dosbox.h"
|
||||
#include "dos_system.h"
|
||||
#include "dos_inc.h"
|
||||
#include "drives.h"
|
||||
#include "support.h"
|
||||
#include "cross.h"
|
||||
@ -38,13 +38,14 @@ public:
|
||||
Bit16u GetInformation(void);
|
||||
private:
|
||||
FILE * fhandle;
|
||||
enum { NONE,READ,WRITE } last_action;
|
||||
Bit16u info;
|
||||
};
|
||||
|
||||
|
||||
bool localDrive:: FileCreate(DOS_File * * file,char * name,Bit16u attributes) {
|
||||
//TODO Maybe care for attributes but not likely
|
||||
char newname[512];
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
@ -67,7 +68,7 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
|
||||
// return false;
|
||||
|
||||
};
|
||||
char newname[512];
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
@ -79,7 +80,7 @@ bool localDrive::FileOpen(DOS_File * * file,char * name,Bit32u flags) {
|
||||
};
|
||||
|
||||
bool localDrive::FileUnlink(char * name) {
|
||||
char newname[512];
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
@ -88,79 +89,64 @@ bool localDrive::FileUnlink(char * name) {
|
||||
};
|
||||
|
||||
|
||||
bool localDrive::FindFirst(char * search,DTA_FindBlock * dta) {
|
||||
//TODO Find some way for lowcase and highcase drives oneday
|
||||
char name[512];
|
||||
strcpy(name,basedir);
|
||||
strcat(name,search);
|
||||
CROSS_FILENAME(name);
|
||||
char * last=strrchr(name, CROSS_FILESPLIT);
|
||||
*last=0;
|
||||
last++;
|
||||
/* 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;
|
||||
bool localDrive::FindFirst(char * _dir,DOS_DTA & dta) {
|
||||
if (srch_opendir) closedir(srch_opendir);
|
||||
strcpy(srch_dir,basedir);
|
||||
strcat(srch_dir,_dir);
|
||||
CROSS_FILENAME(srch_dir);
|
||||
|
||||
char end[2]={CROSS_FILESPLIT,0};
|
||||
if (srch_dir[strlen(srch_dir)-1]!=CROSS_FILESPLIT) strcat(srch_dir,end);
|
||||
if((srch_opendir=opendir(srch_dir))==NULL) return false;
|
||||
return FindNext(dta);
|
||||
}
|
||||
|
||||
bool localDrive::FindNext(DTA_FindBlock * dta) {
|
||||
Bit8u tempattr=0;
|
||||
struct dirent *tempdata;
|
||||
bool localDrive::FindNext(DOS_DTA & dta) {
|
||||
struct dirent * dir_ent;
|
||||
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(!srch_opendir) return false;
|
||||
|
||||
if(pdir==NULL){
|
||||
return false;
|
||||
};
|
||||
start:
|
||||
if((tempdata=readdir(pdir))==NULL) {
|
||||
closedir(pdir);
|
||||
pdir=NULL;
|
||||
dta.GetSearchParams(srch_attr,srch_pattern);
|
||||
again:
|
||||
if((dir_ent=readdir(srch_opendir))==NULL) {
|
||||
closedir(srch_opendir);
|
||||
srch_opendir=NULL;
|
||||
return false;
|
||||
}
|
||||
strcpy(werkbuffer,tempdata->d_name);
|
||||
if (wild_ext) {
|
||||
char * ext=strrchr(werkbuffer,'.');
|
||||
if (!ext) ext="*";
|
||||
else *ext++=0;
|
||||
if(!wildcmp(wild_ext,ext)) goto start;
|
||||
if(!WildFileCmp(dir_ent->d_name,srch_pattern)) goto again;
|
||||
strcpy(full_name,srch_dir);
|
||||
strcat(full_name,dir_ent->d_name);
|
||||
if(stat(full_name,&stat_block)!=0){
|
||||
goto again;
|
||||
}
|
||||
if(!wildcmp(wild_name,werkbuffer)) goto start;
|
||||
werkbuffer[0]='\0';
|
||||
strcpy(werkbuffer,directory);
|
||||
strcat(werkbuffer,tempdata->d_name);
|
||||
if(stat(werkbuffer,&stat_block)!=0){
|
||||
/*nu is er iets fout!*/ exit(1);
|
||||
}
|
||||
if(S_ISDIR(stat_block.st_mode)) tempattr=DOS_ATTR_DIRECTORY;
|
||||
else tempattr=DOS_ATTR_ARCHIVE;
|
||||
if(!(dta->sattr & tempattr)) goto start;
|
||||
/*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;
|
||||
if(S_ISDIR(stat_block.st_mode)) find_attr=DOS_ATTR_DIRECTORY;
|
||||
else find_attr=DOS_ATTR_ARCHIVE;
|
||||
if (~srch_attr & find_attr & (DOS_ATTR_DIRECTORY | DOS_ATTR_HIDDEN | DOS_ATTR_SYSTEM)) goto again;
|
||||
/*file is okay, setup everything to be copied in DTA Block */
|
||||
char find_name[DOS_NAMELENGTH_ASCII];Bit16u find_date,find_time;Bit32u find_size;
|
||||
if(strlen(dir_ent->d_name)<DOS_NAMELENGTH_ASCII){
|
||||
strcpy(find_name,dir_ent->d_name);
|
||||
upcase(find_name);
|
||||
} else strcpy(find_name,"LONGNAME.ERR");
|
||||
find_size=(Bit32u) stat_block.st_size;
|
||||
struct tm *time;
|
||||
if((time=localtime(&stat_block.st_mtime))!=0){
|
||||
|
||||
dta->time=(time->tm_hour<<11)+(time->tm_min<<5)+(time->tm_sec/2); /* standard way. */
|
||||
dta->date=((time->tm_year-80)<<9)+((time->tm_mon+1)<<5)+(time->tm_mday);
|
||||
find_date=DOS_PackDate(time->tm_year+1900,time->tm_mon+1,time->tm_mday);
|
||||
find_time=DOS_PackTime(time->tm_hour,time->tm_min,time->tm_sec);
|
||||
}else {
|
||||
dta->time=6;
|
||||
dta->date=4;
|
||||
find_time=6;
|
||||
find_date=4;
|
||||
}
|
||||
dta.SetResult(find_name,find_size,find_date,find_time,find_attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool localDrive::GetFileAttr(char * name,Bit16u * attr) {
|
||||
char newname[512];
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
@ -175,7 +161,7 @@ bool localDrive::GetFileAttr(char * name,Bit16u * attr) {
|
||||
};
|
||||
|
||||
bool localDrive::MakeDir(char * dir) {
|
||||
char newdir[512];
|
||||
char newdir[CROSS_LEN];
|
||||
strcpy(newdir,basedir);
|
||||
strcat(newdir,dir);
|
||||
CROSS_FILENAME(newdir);
|
||||
@ -189,7 +175,7 @@ bool localDrive::MakeDir(char * dir) {
|
||||
}
|
||||
|
||||
bool localDrive::RemoveDir(char * dir) {
|
||||
char newdir[512];
|
||||
char newdir[CROSS_LEN];
|
||||
strcpy(newdir,basedir);
|
||||
strcat(newdir,dir);
|
||||
CROSS_FILENAME(newdir);
|
||||
@ -198,7 +184,7 @@ bool localDrive::RemoveDir(char * dir) {
|
||||
}
|
||||
|
||||
bool localDrive::TestDir(char * dir) {
|
||||
char newdir[512];
|
||||
char newdir[CROSS_LEN];
|
||||
strcpy(newdir,basedir);
|
||||
strcat(newdir,dir);
|
||||
CROSS_FILENAME(newdir);
|
||||
@ -207,11 +193,11 @@ bool localDrive::TestDir(char * dir) {
|
||||
}
|
||||
|
||||
bool localDrive::Rename(char * oldname,char * newname) {
|
||||
char newold[512];
|
||||
char newold[CROSS_LEN];
|
||||
strcpy(newold,basedir);
|
||||
strcat(newold,oldname);
|
||||
CROSS_FILENAME(newold);
|
||||
char newnew[512];
|
||||
char newnew[CROSS_LEN];
|
||||
strcpy(newnew,basedir);
|
||||
strcat(newnew,newname);
|
||||
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 */
|
||||
/* Total size is always 1 gb */
|
||||
*bytes=512;
|
||||
*sectors=127;
|
||||
*clusters=16513;
|
||||
*free=1700;
|
||||
*_bytes_sector=allocation.bytes_sector;
|
||||
*_sectors_cluster=allocation.sectors_cluster;
|
||||
*_total_clusters=allocation.total_clusters;
|
||||
*_free_clusters=allocation.free_clusters;
|
||||
return true;
|
||||
};
|
||||
|
||||
bool localDrive::FileExists(const char* name) const {
|
||||
char newname[512];
|
||||
bool localDrive::FileExists(const char* name) {
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
@ -241,38 +227,60 @@ bool localDrive::FileExists(const char* name) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool localDrive::FileStat(const char* name, struct stat* const stat_block) const {
|
||||
char newname[512];
|
||||
bool localDrive::FileStat(const char* name, FileStat_Block * const stat_block) {
|
||||
char newname[CROSS_LEN];
|
||||
strcpy(newname,basedir);
|
||||
strcat(newname,name);
|
||||
CROSS_FILENAME(newname);
|
||||
if(stat(newname,stat_block)!=0) return false;
|
||||
return true;
|
||||
struct stat temp_stat;
|
||||
if(stat(newname,&temp_stat)!=0) return false;
|
||||
/* Convert the stat to a FileStat */
|
||||
struct tm *time;
|
||||
if((time=localtime(&temp_stat.st_mtime))!=0) {
|
||||
stat_block->time=DOS_PackTime(time->tm_hour,time->tm_min,time->tm_sec);
|
||||
stat_block->date=DOS_PackDate(time->tm_year,time->tm_mon,time->tm_mday);
|
||||
} 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);
|
||||
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) {
|
||||
if (last_action==WRITE) fseek(fhandle,ftell(fhandle),SEEK_SET);
|
||||
last_action=READ;
|
||||
*size=fread(data,1,*size,fhandle);
|
||||
return true;
|
||||
};
|
||||
|
||||
bool localFile::Write(Bit8u * data,Bit16u * size) {
|
||||
if(*size==0){
|
||||
if (last_action==READ) fseek(fhandle,ftell(fhandle),SEEK_SET);
|
||||
last_action=WRITE;
|
||||
if(*size==0){
|
||||
return (!ftruncate(fileno(fhandle),ftell(fhandle)));
|
||||
}
|
||||
else
|
||||
{
|
||||
*size=fwrite(data,1,*size,fhandle);
|
||||
return true;
|
||||
*size=fwrite(data,1,*size,fhandle);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool localFile::Seek(Bit32u * pos,Bit32u type) {
|
||||
@ -291,7 +299,7 @@ bool localFile::Seek(Bit32u * pos,Bit32u type) {
|
||||
//TODO Hope we don't encouter files with 64 bits size
|
||||
Bit32u * fake_pos=(Bit32u*)&temppos;
|
||||
*pos=*fake_pos;
|
||||
|
||||
last_action=NONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -304,9 +312,22 @@ Bit16u localFile::GetInformation(void) {
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
localFile::localFile(FILE * handle,Bit16u devinfo) {
|
||||
fhandle=handle;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,13 +21,13 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "dosbox.h"
|
||||
#include "dos_system.h"
|
||||
#include "dos_inc.h"
|
||||
#include "drives.h"
|
||||
#include "support.h"
|
||||
#include "cross.h"
|
||||
|
||||
struct VFILE_Block {
|
||||
char * name;
|
||||
const char * name;
|
||||
Bit8u * data;
|
||||
Bit32u size;
|
||||
VFILE_Block * next;
|
||||
@ -36,7 +36,7 @@ struct VFILE_Block {
|
||||
|
||||
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;
|
||||
new_file->name=name;
|
||||
new_file->data=data;
|
||||
@ -153,16 +153,14 @@ bool Virtual_Drive::TestDir(char * dir) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Virtual_Drive::FileStat(const char* name, struct stat* const stat_block) const {
|
||||
VFILE_Block * cur_file=first_file;
|
||||
bool Virtual_Drive::FileStat(const char* name, FileStat_Block * const stat_block){
|
||||
VFILE_Block * cur_file=first_file;
|
||||
while (cur_file) {
|
||||
if (strcasecmp(name,cur_file->name)==0) {
|
||||
stat_block->st_size=cur_file->size;
|
||||
struct tm tijd;
|
||||
tijd.tm_hour=0;tijd.tm_min=0;tijd.tm_sec=0;
|
||||
tijd.tm_year=80;tijd.tm_mday=6;tijd.tm_mon=0;
|
||||
stat_block->st_mtime=mktime(&tijd);
|
||||
/* more not needed at the moment (fcbopen.....)*/
|
||||
stat_block->attr=DOS_ATTR_ARCHIVE;
|
||||
stat_block->size=cur_file->size;
|
||||
stat_block->date=DOS_PackDate(2002,0,0);
|
||||
stat_block->time=DOS_PackTime(12,12,12);
|
||||
return true;
|
||||
}
|
||||
cur_file=cur_file->next;
|
||||
@ -170,7 +168,7 @@ bool Virtual_Drive::FileStat(const char* name, struct stat* const stat_block) co
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Virtual_Drive::FileExists(const char* name) const {
|
||||
bool Virtual_Drive::FileExists(const char* name){
|
||||
VFILE_Block * cur_file=first_file;
|
||||
while (cur_file) {
|
||||
if (strcasecmp(name,cur_file->name)==0) return true;
|
||||
@ -179,32 +177,17 @@ bool Virtual_Drive::FileExists(const char* name) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static void FillDTABlock(DTA_FindBlock * dta,VFILE_Block * fill_file) {
|
||||
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) {
|
||||
bool Virtual_Drive::FindFirst(char * _dir,DOS_DTA & dta) {
|
||||
search_file=first_file;
|
||||
strcpy(search_string,search);
|
||||
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;
|
||||
return FindNext(dta);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (wildcmp(search_string,search_file->name)) {
|
||||
FillDTABlock(dta,search_file);
|
||||
if (WildFileCmp(search_file->name,pattern)) {
|
||||
dta.SetResult(search_file->name,search_file->size,6,2,DOS_ATTR_ARCHIVE);
|
||||
search_file=search_file->next;
|
||||
return true;
|
||||
}
|
||||
@ -221,13 +204,17 @@ bool Virtual_Drive::Rename(char * oldname,char * newname) {
|
||||
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 */
|
||||
/* Total size is always 1 gb */
|
||||
*bytes=512;
|
||||
*sectors=127;
|
||||
*clusters=16513;
|
||||
*free=00;
|
||||
*_bytes_sector=512;
|
||||
*_sectors_cluster=127;
|
||||
*_total_clusters=16513;
|
||||
*_free_clusters=00;
|
||||
return true;
|
||||
}
|
||||
|
||||
Bit8u Virtual_Drive::GetMediaByte(void) {
|
||||
return 0xF8;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,58 @@
|
||||
#include "dosbox.h"
|
||||
#include "dos_system.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() {
|
||||
|
@ -22,30 +22,39 @@
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include "dos_system.h"
|
||||
#include "cross.h"
|
||||
|
||||
|
||||
bool WildFileCmp(const char * file, const char * wild);
|
||||
|
||||
class localDrive : public DOS_Drive {
|
||||
public:
|
||||
localDrive(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 FileCreate(DOS_File * * file,char * name,Bit16u attributes);
|
||||
bool FileUnlink(char * name);
|
||||
bool RemoveDir(char * dir);
|
||||
bool MakeDir(char * dir);
|
||||
bool TestDir(char * dir);
|
||||
bool FindFirst(char * search,DTA_FindBlock * dta);
|
||||
bool FindNext(DTA_FindBlock * dta);
|
||||
bool FindFirst(char * _dir,DOS_DTA & dta);
|
||||
bool FindNext(DOS_DTA & dta);
|
||||
bool GetFileAttr(char * name,Bit16u * attr);
|
||||
bool Rename(char * oldname,char * newname);
|
||||
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
|
||||
bool FileExists(const char* name) const ;
|
||||
bool FileStat(const char* name, struct stat* const stat_block) const;
|
||||
bool AllocationInfo(Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters);
|
||||
bool FileExists(const char* name);
|
||||
bool FileStat(const char* name, FileStat_Block * const stat_block);
|
||||
Bit8u GetMediaByte(void);
|
||||
private:
|
||||
bool FillDTABlock(DTA_FindBlock * dta);
|
||||
char basedir[512];
|
||||
char directory[512];
|
||||
char wild_name[15];
|
||||
char * wild_ext;
|
||||
DIR *pdir;
|
||||
char basedir[CROSS_LEN];
|
||||
char srch_dir[CROSS_LEN];
|
||||
DIR * srch_opendir;
|
||||
struct {
|
||||
Bit16u bytes_sector;
|
||||
Bit16u sectors_cluster;
|
||||
Bit16u total_clusters;
|
||||
Bit16u free_clusters;
|
||||
Bit8u mediaid;
|
||||
} allocation;
|
||||
};
|
||||
|
||||
struct VFILE_Block;
|
||||
@ -60,17 +69,16 @@ public:
|
||||
bool RemoveDir(char * dir);
|
||||
bool MakeDir(char * dir);
|
||||
bool TestDir(char * dir);
|
||||
bool FindFirst(char * search,DTA_FindBlock * dta);
|
||||
bool FindNext(DTA_FindBlock * dta);
|
||||
bool FindFirst(char * _dir,DOS_DTA & dta);
|
||||
bool FindNext(DOS_DTA & dta);
|
||||
bool GetFileAttr(char * name,Bit16u * attr);
|
||||
bool Rename(char * oldname,char * newname);
|
||||
bool FreeSpace(Bit16u * bytes,Bit16u * sectors,Bit16u * clusters,Bit16u * free);
|
||||
bool FileExists(const char* name) const ;
|
||||
bool FileStat(const char* name, struct stat* const stat_block) const;
|
||||
|
||||
bool AllocationInfo(Bit16u * _bytes_sector,Bit16u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters);
|
||||
bool FileExists(const char* name);
|
||||
bool FileStat(const char* name, FileStat_Block* const stat_block);
|
||||
Bit8u GetMediaByte(void);
|
||||
private:
|
||||
VFILE_Block * search_file;
|
||||
char search_string[255];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
344
src/dosbox.cpp
344
src/dosbox.cpp
@ -35,119 +35,53 @@
|
||||
#include "setup.h"
|
||||
#include "cross.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
|
||||
|
||||
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 CPU_Init(Section*);
|
||||
//void FPU_Init();
|
||||
void IO_Init(void);
|
||||
void DMA_Init(void);
|
||||
void MIXER_Init(void);
|
||||
void HARDWARE_Init(void);
|
||||
void DMA_Init(Section*);
|
||||
void MIXER_Init(Section*);
|
||||
void HARDWARE_Init(Section*);
|
||||
|
||||
|
||||
void KEYBOARD_Init(void); //TODO This should setup INT 16 too but ok ;)
|
||||
void JOYSTICK_Init(void);
|
||||
void MOUSE_Init(void);
|
||||
void SBLASTER_Init(void);
|
||||
void ADLIB_Init(void);
|
||||
void PCSPEAKER_Init(void);
|
||||
void TANDY_Init(void);
|
||||
void CMS_Init(void);
|
||||
void KEYBOARD_Init(Section*); //TODO This should setup INT 16 too but ok ;)
|
||||
void JOYSTICK_Init(Section*);
|
||||
void MOUSE_Init(Section*);
|
||||
void SBLASTER_Init(Section*);
|
||||
void ADLIB_Init(Section*);
|
||||
void PCSPEAKER_Init(Section*);
|
||||
void TANDYSOUND_Init(Section*);
|
||||
void CMS_Init(Section*);
|
||||
|
||||
void PIC_Init(void);
|
||||
void TIMER_Init(void);
|
||||
void BIOS_Init(void);
|
||||
void DEBUG_Init(void);
|
||||
|
||||
|
||||
void PLUGIN_Init(void);
|
||||
void PIC_Init(Section*);
|
||||
void TIMER_Init(Section*);
|
||||
void BIOS_Init(Section*);
|
||||
void DEBUG_Init(Section*);
|
||||
|
||||
/* Dos Internal mostly */
|
||||
void EMS_Init(void);
|
||||
void XMS_Init(void);
|
||||
void PROGRAMS_Init(void);
|
||||
void EMS_Init(Section*);
|
||||
void XMS_Init(Section*);
|
||||
void AUTOEXEC_Init(Section*);
|
||||
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 Bitu Normal_Loop(void) {
|
||||
@ -159,30 +93,18 @@ static Bitu Normal_Loop(void) {
|
||||
LastTicks=new_ticks;
|
||||
TIMER_AddTicks(ticks);
|
||||
}
|
||||
TIMER_CheckPIT();
|
||||
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();
|
||||
GFX_Events();
|
||||
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) {
|
||||
@ -200,111 +122,89 @@ void DOSBOX_RunMachine(void){
|
||||
} 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) {
|
||||
MSG_Init();
|
||||
MEM_Init();
|
||||
IO_Init();
|
||||
CALLBACK_Init();
|
||||
PROGRAMS_Init();
|
||||
HARDWARE_Init();
|
||||
TIMER_Init();
|
||||
CPU_Init();
|
||||
void DOSBOX_Init(void) {
|
||||
// Section * sec;
|
||||
Section_prop * secprop;
|
||||
Section_line * secline;
|
||||
|
||||
/* Setup all the different modules making up DOSBox */
|
||||
|
||||
secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit);
|
||||
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
|
||||
FPU_Init();
|
||||
#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();
|
||||
};
|
||||
|
@ -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
|
||||
.
|
@ -16,14 +16,20 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <png.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "video.h"
|
||||
#include "render.h"
|
||||
|
||||
|
||||
#include "setup.h"
|
||||
#include "keyboard.h"
|
||||
#include "cross.h"
|
||||
|
||||
#define MAX_RES 2048
|
||||
|
||||
|
||||
|
||||
struct PalData {
|
||||
struct {
|
||||
Bit8u red;
|
||||
@ -51,8 +57,104 @@ static struct {
|
||||
PalData pal;
|
||||
bool remake;
|
||||
bool enlarge;
|
||||
bool screenshot;
|
||||
} 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 */
|
||||
static void Check_Palette(void) {
|
||||
if (render.pal.first>render.pal.last) return;
|
||||
@ -98,8 +200,11 @@ void RENDER_Draw(Bit8u * bitdata) {
|
||||
render.remake=false;
|
||||
}
|
||||
render.handler(&src_data);
|
||||
if (render.screenshot) {
|
||||
TakeScreenShot(src_data);
|
||||
render.screenshot=false;
|
||||
}
|
||||
Draw_8_Normal(src_data,bitdata);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -151,10 +256,15 @@ void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,Bitu pitch,float ratio,Bitu
|
||||
|
||||
}
|
||||
|
||||
|
||||
void RENDER_Init(void) {
|
||||
static void EnableScreenShot(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.last=0;
|
||||
render.enlarge=false;
|
||||
render.enlarge=false;
|
||||
KEYBOARD_AddEvent(KBD_f5,CTRL_PRESSED,EnableScreenShot);
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,9 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_thread.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
|
||||
#include "dosbox.h"
|
||||
#include "video.h"
|
||||
#include "keyboard.h"
|
||||
@ -27,7 +28,8 @@
|
||||
#include "joystick.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "setup.h"
|
||||
#include "debug.h"
|
||||
|
||||
//#define DISABLE_JOYSTICK
|
||||
|
||||
@ -39,13 +41,23 @@ struct SDL_Block {
|
||||
Bitu bpp;
|
||||
GFX_DrawHandler * draw;
|
||||
GFX_ResizeHandler * resize;
|
||||
bool mouse_grabbed;
|
||||
bool full_screen;
|
||||
SDL_Thread * thread;
|
||||
SDL_mutex * mutex;
|
||||
SDL_Surface * surface;
|
||||
SDL_Joystick * joy;
|
||||
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;
|
||||
@ -98,8 +110,8 @@ void GFX_Resize(Bitu width,Bitu height,Bitu bpp,GFX_ResizeHandler * resize) {
|
||||
}
|
||||
|
||||
static void CaptureMouse() {
|
||||
sdl.mouse_grabbed=!sdl.mouse_grabbed;
|
||||
if (sdl.mouse_grabbed) {
|
||||
sdl.mouse.locked=!sdl.mouse.locked;
|
||||
if (sdl.mouse.locked) {
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
} 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) {
|
||||
GFX_Stop();
|
||||
sdl.full_screen=!sdl.full_screen;
|
||||
@ -120,6 +142,10 @@ static void SwitchFullScreen(void) {
|
||||
ResetScreen();
|
||||
GFX_Start();
|
||||
}
|
||||
//only prototype existed
|
||||
void GFX_SwitchFullScreen(void) {
|
||||
SwitchFullScreen();
|
||||
}
|
||||
|
||||
static void GFX_Redraw() {
|
||||
#if C_THREADED
|
||||
@ -127,6 +153,9 @@ static void GFX_Redraw() {
|
||||
E_Exit("Can't Lock Mutex");
|
||||
};
|
||||
#endif
|
||||
|
||||
if (++sdl.frames.count<sdl.frames.skip) goto skipframe;
|
||||
sdl.frames.count=0;
|
||||
if (sdl.active) {
|
||||
SDL_LockSurface(sdl.surface );
|
||||
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);
|
||||
else SDL_UpdateRect(sdl.surface,0,0,0,0);
|
||||
};
|
||||
skipframe:
|
||||
#if C_THREADED
|
||||
if (SDL_mutexV(sdl.mutex)) {
|
||||
E_Exit("Can't Release Mutex");
|
||||
@ -193,32 +223,53 @@ void GFX_Start() {
|
||||
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.full_screen=false;
|
||||
sdl.frames.skip=0;
|
||||
sdl.frames.count=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
|
||||
sdl.mutex=SDL_CreateMutex();
|
||||
sdl.thread = SDL_CreateThread(&SDLGFX_Thread,0);
|
||||
#else
|
||||
TIMER_RegisterMicroHandler(GFX_Redraw,1000000/70);
|
||||
#endif
|
||||
GFX_Resize(640,400,8,0);
|
||||
SDL_EnableKeyRepeat(250,30);
|
||||
|
||||
/* Get some Keybinds */
|
||||
KEYBOARD_AddEvent(KBD_f9,CTRL_PRESSED,SwitchFullScreen);
|
||||
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);
|
||||
}
|
||||
|
||||
void GFX_ShutDown() {
|
||||
if (sdl.full_screen) SwitchFullScreen();
|
||||
if (sdl.mouse_grabbed) CaptureMouse();
|
||||
if (sdl.mouse.locked) CaptureMouse();
|
||||
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) {
|
||||
Bit32u code;
|
||||
@ -348,16 +399,17 @@ static void HandleKey(SDL_KeyboardEvent * key) {
|
||||
}
|
||||
|
||||
static void HandleMouseMotion(SDL_MouseMotionEvent * motion) {
|
||||
if (!sdl.mouse_grabbed) {
|
||||
Mouse_CursorSet((float)motion->x/(float)sdl.width,(float)motion->y/(float)sdl.height);
|
||||
if (sdl.mouse.locked) {
|
||||
Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100,(float)motion->yrel*sdl.mouse.sensitivity/100);
|
||||
} 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) {
|
||||
switch (button->state) {
|
||||
case SDL_PRESSED:
|
||||
if (sdl.mouse.requestlock && !sdl.mouse.locked) CaptureMouse();
|
||||
switch (button->button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
Mouse_ButtonPressed(0);
|
||||
@ -424,6 +476,13 @@ void GFX_Events() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
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_KEYUP:
|
||||
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) {
|
||||
char buf[1024];
|
||||
@ -478,36 +519,57 @@ void GFX_ShowMsg(char * msg) {
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
try {
|
||||
if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER
|
||||
|
||||
#if C_DEBUG
|
||||
DEBUG_SetupConsole();
|
||||
#endif
|
||||
|
||||
try {
|
||||
CommandLine com_line(argc,argv);
|
||||
Config myconf(&com_line);
|
||||
control=&myconf;
|
||||
|
||||
if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO|SDL_INIT_TIMER
|
||||
#ifndef DISABLE_JOYSTICK
|
||||
|SDL_INIT_JOYSTICK
|
||||
|
||||
#endif
|
||||
) < 0 ) {
|
||||
E_Exit("Can't init SDL %s",SDL_GetError());
|
||||
}
|
||||
GFX_StartUp();
|
||||
/* Init all the dosbox subsystems */
|
||||
DOSBOX_Init(argc,argv);
|
||||
/* Start the systems that SDL should provide */
|
||||
) < 0 ) E_Exit("Can't init SDL %s",SDL_GetError());
|
||||
Section_prop * sdl_sec=control->AddSection_prop("sdl",&GUI_StartUp);
|
||||
sdl_sec->Add_bool("fullscreen",false);
|
||||
sdl_sec->Add_bool("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";
|
||||
}
|
||||
/* Parse the config file */
|
||||
control->ParseConfigFile(config_file.c_str());
|
||||
/* Init all the sections */
|
||||
control->Init();
|
||||
/* Some extra SDL Functions */
|
||||
#ifndef DISABLE_JOYSTICK
|
||||
if (SDL_NumJoysticks()>0) {
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
sdl.joy=SDL_JoystickOpen(0);
|
||||
LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(0),SDL_JoystickNumAxes(sdl.joy),SDL_JoystickNumButtons(sdl.joy));
|
||||
JOYSTICK_Enable(0,true);
|
||||
if (SDL_NumJoysticks()>0) {
|
||||
SDL_JoystickEventState(SDL_ENABLE);
|
||||
sdl.joy=SDL_JoystickOpen(0);
|
||||
LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(0),SDL_JoystickNumAxes(sdl.joy),SDL_JoystickNumButtons(sdl.joy));
|
||||
JOYSTICK_Enable(0,true);
|
||||
}
|
||||
#endif
|
||||
if (control->cmdline->FindExist("-fullscreen") || sdl_sec->Get_bool("fullscreen")) {
|
||||
SwitchFullScreen();
|
||||
}
|
||||
/* Start up main machine */
|
||||
control->StartUp();
|
||||
/* Shutdown everything */
|
||||
} catch (char * error) {
|
||||
LOG_MSG("Exit to error: %sPress enter to continue.",error);
|
||||
fgetc(stdin);
|
||||
}
|
||||
#endif
|
||||
/* Start dosbox up */
|
||||
DOSBOX_StartUp();
|
||||
}
|
||||
catch (Bitu e) {
|
||||
LOG_MSG("Exit to error %d",e);
|
||||
}
|
||||
GFX_Stop();
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
};
|
||||
};
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "mixer.h"
|
||||
#include "timer.h"
|
||||
#include "hardware.h"
|
||||
|
||||
#include "setup.h"
|
||||
/*
|
||||
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 void ADLIB_Enable(bool enable) {
|
||||
@ -153,46 +152,9 @@ static void ADLIB_Enable(bool enable) {
|
||||
}
|
||||
|
||||
|
||||
static void ADLIB_InputHandler(char * line) {
|
||||
bool s_off=ScanCMDBool(line,"OFF");
|
||||
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) {
|
||||
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) {
|
||||
void ADLIB_Init(Section* sec) {
|
||||
Section_prop * section=static_cast<Section_prop *>(sec);
|
||||
if(!section->Get_bool("adlib")) return;
|
||||
|
||||
timer1.isMasked=true;
|
||||
timer1.base=0;
|
||||
@ -211,14 +173,6 @@ void ADLIB_Init(void) {
|
||||
|
||||
adlib_chan=MIXER_AddChannel(ADLIB_CallBack,ADLIB_FREQ,"ADLIB");
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -70,6 +70,32 @@ struct DMA_CONTROLLER {
|
||||
};
|
||||
|
||||
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) {
|
||||
@ -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++) {
|
||||
IO_RegisterWriteHandler(i,write_dma,"DMA1");
|
||||
IO_RegisterReadHandler(i,read_dma,"DMA1");
|
||||
}
|
||||
IO_RegisterWriteHandler(0x81,write_dma_page,"DMA Pages");
|
||||
IO_RegisterWriteHandler(0x82,write_dma_page,"DMA Pages");
|
||||
|
@ -22,11 +22,11 @@
|
||||
#include "mixer.h"
|
||||
#include "mem.h"
|
||||
#include "hardware.h"
|
||||
#include "setup.h"
|
||||
|
||||
#define CMS_RATE 22050
|
||||
#define CMS_VOLUME 6000
|
||||
|
||||
|
||||
#define FREQ_SHIFT 16
|
||||
|
||||
#define SIN_ENT 1024
|
||||
@ -36,8 +36,6 @@
|
||||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
struct CMS {
|
||||
struct {
|
||||
Bit32u freq_pos;
|
||||
@ -157,7 +155,6 @@ static void CMS_CallBack(Bit8u * stream,Bit32u len) {
|
||||
|
||||
}
|
||||
|
||||
static HWBlock hw_cms;
|
||||
static bool cms_enabled;
|
||||
|
||||
static void CMS_Enable(bool enable) {
|
||||
@ -178,56 +175,14 @@ static void CMS_Enable(bool enable) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void CMS_InputHandler(char * line) {
|
||||
bool s_off=ScanCMDBool(line,"OFF");
|
||||
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) {
|
||||
void CMS_Init(Section* sec) {
|
||||
Section_prop * section=static_cast<Section_prop *>(sec);
|
||||
if(!section->Get_bool("cms")) return;
|
||||
Bits i;
|
||||
/* Register the Mixer CallBack */
|
||||
cms_chan=MIXER_AddChannel(CMS_CallBack,CMS_RATE,"CMS");
|
||||
MIXER_SetMode(cms_chan,MIXER_16STEREO);
|
||||
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 */
|
||||
double log_start=log10(27.34375);
|
||||
double log_add=(log10(54.609375)-log10(27.34375))/256;
|
||||
@ -250,7 +205,6 @@ void CMS_Init(void) {
|
||||
out /= 1.1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CMS_Enable(true);
|
||||
}
|
||||
|
||||
|
@ -24,94 +24,10 @@
|
||||
#include "dosbox.h"
|
||||
#include "programs.h"
|
||||
#include "hardware.h"
|
||||
|
||||
static HWBlock * firsthw=0;
|
||||
#include "setup.h"
|
||||
|
||||
|
||||
class HWSET : public Program {
|
||||
public:
|
||||
HWSET(PROGRAM_Info * program_info);
|
||||
void Run(void);
|
||||
|
||||
};
|
||||
|
||||
|
||||
HWSET::HWSET(PROGRAM_Info * info):Program(info) {
|
||||
void HARDWARE_Init(Section * sec) {
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
};
|
||||
|
||||
|
@ -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++) {
|
||||
IO_RegisterReadHandler(i,&IO_ReadDefault,"Default Read");
|
||||
IO_RegisterWriteHandler(i,&IO_WriteDefault,"Default Write");
|
||||
|
@ -50,8 +50,8 @@ static Bit8u read_p201(Bit32u port) {
|
||||
if (stick[0].button[1]) ret&=32;
|
||||
}
|
||||
if (stick[1].enabled) {
|
||||
if (stick[1].xcount) stick[0].xcount--; else ret&=~4;
|
||||
if (stick[1].ycount) stick[0].ycount--; else ret&=~8;
|
||||
if (stick[1].xcount) stick[1].xcount--; else ret&=~4;
|
||||
if (stick[1].ycount) stick[1].ycount--; else ret&=~8;
|
||||
if (stick[1].button[0]) ret&=64;
|
||||
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) {
|
||||
if (stick[0].enabled) {
|
||||
stick[0].xcount=(Bitu)(stick[0].xpos*RANGE+RANGE*2);
|
||||
stick[0].ycount=(Bitu)(stick[0].ypos*RANGE+RANGE*2);
|
||||
stick[0].xcount=(Bitu)((stick[0].xpos*RANGE)+RANGE);
|
||||
stick[0].ycount=(Bitu)((stick[0].ypos*RANGE)+RANGE);
|
||||
}
|
||||
if (stick[1].enabled) {
|
||||
stick[1].xcount=(Bitu)(stick[1].xpos*RANGE+RANGE*2);
|
||||
stick[1].ycount=(Bitu)(stick[1].ypos*RANGE+RANGE*2);
|
||||
stick[1].xcount=(Bitu)((stick[1].xpos*RANGE)+RANGE);
|
||||
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_RegisterWriteHandler(0x201,write_p201,"JOYSTICK");
|
||||
stick[0].enabled=false;
|
||||
|
@ -23,9 +23,14 @@
|
||||
#include "pic.h"
|
||||
#include "mixer.h"
|
||||
|
||||
|
||||
#define KEYBUFSIZE 32
|
||||
|
||||
enum KeyCommands {
|
||||
CMD_NONE,
|
||||
CMD_SETLEDS,
|
||||
CMD_SETTYPERATE
|
||||
};
|
||||
|
||||
|
||||
struct KeyEvent {
|
||||
Bitu type;
|
||||
@ -34,43 +39,109 @@ struct KeyEvent {
|
||||
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 Bit8u cur_scancode;
|
||||
static Bit8u kbuf[KEYBUFSIZE];
|
||||
static Bitu kbuf_pos;
|
||||
static Bitu kbuf_used;
|
||||
static Bit8u port_61_data;
|
||||
//TODO Are these initialized at 0 at startup? Hope so :)
|
||||
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) {
|
||||
if (kbuf_used>0) {
|
||||
cur_scancode=kbuf[kbuf_pos];
|
||||
};
|
||||
return cur_scancode;
|
||||
/* Reading this port signals that IRQ can be lowered */
|
||||
Bit8u val=keyb.buf[keyb.buf_pos];
|
||||
keyb.read_active=false;
|
||||
return keyb.buf[keyb.buf_pos];
|
||||
}
|
||||
|
||||
static void write_p60(Bit32u port,Bit8u val) {
|
||||
//TODO Work this out ;)
|
||||
LOG_DEBUG("Port 60 write with val %d",val);
|
||||
switch (keyb.command) {
|
||||
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) {
|
||||
port_61_data^=0x20;
|
||||
return port_61_data;
|
||||
|
||||
};
|
||||
|
||||
static void KEYBOARD_IRQHandler(void) {
|
||||
if (!keyb.read_active) KEYBOARD_ReadBuffer();
|
||||
}
|
||||
|
||||
static void write_p61(Bit32u port,Bit8u val) {
|
||||
//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;
|
||||
if (val & 128) if (!keyb.read_active) KEYBOARD_ReadBuffer();
|
||||
if ((val & 3)==3) {
|
||||
PCSPEAKER_Enable(true);
|
||||
} else {
|
||||
@ -78,18 +149,17 @@ static void write_p61(Bit32u port,Bit8u val) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KEYBOARD_AddCode(Bit8u code) {
|
||||
//Now Raise the keyboard IRQ
|
||||
//If the buffer is full just drop the scancode :)
|
||||
if (kbuf_used<KEYBUFSIZE) {
|
||||
Bit32u start=kbuf_used+kbuf_pos;
|
||||
kbuf_used++;
|
||||
if (start>=KEYBUFSIZE) start-=KEYBUFSIZE;
|
||||
kbuf[start]=code;
|
||||
static void write_p64(Bit32u port,Bit8u val) {
|
||||
switch (val) {
|
||||
case 0:
|
||||
default:
|
||||
LOG_DEBUG("Port 64 write with val %d",val);
|
||||
break;
|
||||
}
|
||||
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->state=state;
|
||||
newevent->handler=handler;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void KEYBOARD_AddKey(Bitu keytype,bool pressed) {
|
||||
bool extend=false;
|
||||
@ -217,9 +285,13 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) {
|
||||
//The Extended keys
|
||||
|
||||
case KBD_kpenter:extend=true;ret=28;break;
|
||||
case KBD_rightctrl:extend=true;ret=29;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_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_up:extend=true;ret=72;break;
|
||||
case KBD_pageup:extend=true;ret=73;break;
|
||||
@ -233,7 +305,7 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) {
|
||||
default:
|
||||
E_Exit("Unsopperted key press");
|
||||
break;
|
||||
};
|
||||
}
|
||||
/* check for active key events */
|
||||
KeyEvent * checkevent=event_handlers[keytype];
|
||||
while (checkevent) {
|
||||
@ -249,14 +321,21 @@ void KEYBOARD_AddKey(Bitu keytype,bool pressed) {
|
||||
if (extend) KEYBOARD_AddCode(224);
|
||||
if (!pressed) ret+=128;
|
||||
KEYBOARD_AddCode(ret);
|
||||
};
|
||||
}
|
||||
|
||||
void KEYBOARD_Init(void) {
|
||||
kbuf_used=0;kbuf_pos=0;
|
||||
void KEYBOARD_Init(Section* sec) {
|
||||
IO_RegisterWriteHandler(0x60,write_p60,"Keyboard");
|
||||
IO_RegisterReadHandler(0x60,read_p60,"Keyboard");
|
||||
IO_RegisterWriteHandler(0x61,write_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 */
|
||||
// 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");
|
||||
}
|
||||
|
@ -34,28 +34,36 @@ MEMORY_WriteHandler WriteHandlerTable[MAX_PAGES];
|
||||
#define MAX_PAGE_LIMIT PAGE_COUNT(C_MEM_MAX_SIZE*1024*1024)
|
||||
|
||||
void MEM_BlockRead(PhysPt off,void * data,Bitu size) {
|
||||
Bitu c;
|
||||
Bit8u * idata=(Bit8u *)data;
|
||||
for (c=1;c<=(size>>2);c++) {
|
||||
writed(idata,mem_readd(off));
|
||||
idata+=4;off+=4;
|
||||
}
|
||||
for (c=1;c<=(size&3);c++) {
|
||||
writeb(idata,mem_readb(off));
|
||||
idata+=1;off+=1;
|
||||
while (size>0) {
|
||||
Bitu page=off >> PAGE_SHIFT;
|
||||
Bitu start=off & (PAGE_SIZE-1);
|
||||
Bitu tocopy=PAGE_SIZE-start;
|
||||
if (tocopy>size) tocopy=size;
|
||||
size-=tocopy;
|
||||
if (ReadHostTable[page]) {
|
||||
memcpy(idata,ReadHostTable[page]+off,tocopy);
|
||||
idata+=tocopy;off+=tocopy;
|
||||
} else {
|
||||
for (;tocopy>0;tocopy--) *idata++=ReadHandlerTable[page](off++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MEM_BlockWrite(PhysPt off,void * data,Bitu size) {
|
||||
Bitu c;
|
||||
Bit8u * idata=(Bit8u *)data;
|
||||
for (c=1;c<=(size>>2);c++) {
|
||||
mem_writed(off,readd(idata));
|
||||
idata+=4;off+=4;
|
||||
}
|
||||
for (c=1;c<=(size&3);c++) {
|
||||
mem_writeb(off,readb(idata));
|
||||
idata+=1;off+=1;
|
||||
while (size>0) {
|
||||
Bitu page=off >> PAGE_SHIFT;
|
||||
Bitu start=off & (PAGE_SIZE-1);
|
||||
Bitu tocopy=PAGE_SIZE-start;
|
||||
if (tocopy>size) tocopy=size;
|
||||
size-=tocopy;
|
||||
if (WriteHostTable[page]) {
|
||||
memcpy(WriteHostTable[page]+off,idata,tocopy);
|
||||
idata+=tocopy;off+=tocopy;
|
||||
} else {
|
||||
for (;tocopy>0;tocopy--) WriteHandlerTable[page](off++,*idata++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +230,7 @@ Bit32u mem_readd(PhysPt pt){
|
||||
|
||||
|
||||
|
||||
void MEM_Init(void) {
|
||||
void MEM_Init(Section * sect) {
|
||||
/* Init all tables */
|
||||
Bitu i;
|
||||
i=MAX_PAGES;
|
||||
@ -235,8 +243,9 @@ void MEM_Init(void) {
|
||||
/* Allocate the first mb of memory */
|
||||
memory=(Bit8u *)malloc(1024*1024);
|
||||
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 */
|
||||
MEM_SetupMapping(0,PAGE_COUNT(1024*1024),memory);
|
||||
/* Setup tables for HMA Area */
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL.h>
|
||||
#include "dosbox.h"
|
||||
#include "mixer.h"
|
||||
#include "timer.h"
|
||||
@ -35,35 +35,69 @@
|
||||
#define MIXER_REMAIN ((1<<MIXER_SHIFT)-1)
|
||||
#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 {
|
||||
Bit8u volume;
|
||||
Bit8u mode;
|
||||
Bit32u freq;
|
||||
Bitu freq;
|
||||
char * name;
|
||||
MIXER_MixHandler handler;
|
||||
Bit32u sample_add;
|
||||
Bit32u sample_remain;
|
||||
Bit16s sample_data[2];
|
||||
Bitu sample_add;
|
||||
Bitu sample_left;
|
||||
Sample remain;
|
||||
bool playing;
|
||||
MIXER_Channel * next;
|
||||
};
|
||||
|
||||
|
||||
static MIXER_Channel * first_channel;
|
||||
static union {
|
||||
Bit16s temp_m16[MIXER_BUFSIZE][1];
|
||||
Bit16s temp_s16[MIXER_BUFSIZE][2];
|
||||
Bit8u temp_m8[MIXER_BUFSIZE][1];
|
||||
Bit8u temp_s8[MIXER_BUFSIZE][2];
|
||||
};
|
||||
Bit16s m16[MIXER_BUFSIZE][1];
|
||||
Bit16s s16[MIXER_BUFSIZE][2];
|
||||
Bit8u m8[MIXER_BUFSIZE][1];
|
||||
Bit8u s8[MIXER_BUFSIZE][2];
|
||||
Bit32u full[MIXER_BUFSIZE];
|
||||
} mix_temp;
|
||||
|
||||
static Bit16s mix_bufout[MIXER_BUFSIZE][2];
|
||||
static Bit16s mix_buftemp[MIXER_BUFSIZE][2];
|
||||
static Bit32s mix_bufextra;
|
||||
static Bit32u mix_writepos;
|
||||
static Bit32u mix_readpos;
|
||||
static Bit32u mix_ticks;
|
||||
static Bit32u mix_add;
|
||||
static Bit32u mix_remain;
|
||||
static Bitu mix_writepos;
|
||||
static Bitu mix_readpos;
|
||||
static Bitu mix_ticks;
|
||||
static Bitu mix_add;
|
||||
static Bitu mix_remain;
|
||||
|
||||
MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * name) {
|
||||
//TODO Find a free channel
|
||||
@ -75,6 +109,7 @@ MIXER_Channel * MIXER_AddChannel(MIXER_MixHandler handler,Bit32u freq,char * nam
|
||||
chan->handler=handler;
|
||||
chan->name=name;
|
||||
chan->sample_add=(freq<<MIXER_SHIFT)/MIXER_FREQ;
|
||||
chan->sample_left=0;
|
||||
chan->next=first_channel;
|
||||
first_channel=chan;
|
||||
return chan;
|
||||
@ -112,69 +147,28 @@ static void MIXER_MixData(Bit32u samples) {
|
||||
MIXER_Channel * chan=first_channel;
|
||||
while (chan) {
|
||||
if (chan->playing) {
|
||||
Bit32u chan_samples=samples*chan->sample_add;
|
||||
Bit32u real_samples=chan_samples>>MIXER_SHIFT;
|
||||
if (chan_samples & MIXER_REMAIN) real_samples++;
|
||||
(chan->handler)((Bit8u*)&temp_m8,real_samples);
|
||||
/* This should always allocate 1 extra sample */
|
||||
Bitu sample_total=(samples*chan->sample_add)-chan->sample_left;
|
||||
Bitu sample_toread=sample_total >> MIXER_SHIFT;
|
||||
if (sample_total & MIXER_REMAIN) sample_toread++;
|
||||
sample_total=(sample_toread+1)<<MIXER_SHIFT;
|
||||
mix_temp.full[0]=chan->remain.full;
|
||||
switch (chan->mode) {
|
||||
case MIXER_8MONO:
|
||||
/* Mix a 8 bit mono stream into the final 16 bit stereo output stream */
|
||||
{
|
||||
/* Mix the data with output buffer */
|
||||
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]+((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;
|
||||
}
|
||||
MIX_NORMAL(m8,0,0);
|
||||
break;
|
||||
case MIXER_8STEREO:
|
||||
MIX_NORMAL(m8,0,1);
|
||||
break;
|
||||
case MIXER_16MONO:
|
||||
/* Mix a 16 bit mono stream into the final 16 bit stereo output stream */
|
||||
{
|
||||
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;
|
||||
}
|
||||
MIX_NORMAL(m16,0,0);
|
||||
break;
|
||||
case MIXER_16STEREO:
|
||||
/* Mix a 16 bit stereo stream into the final 16 bit stereo output stream */
|
||||
{
|
||||
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;
|
||||
|
||||
}
|
||||
MIX_NORMAL(s16,0,1);
|
||||
break;
|
||||
default:
|
||||
E_Exit("MIXER:Illegal sound mode %2X",chan->mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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 */
|
||||
|
||||
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);
|
||||
} else {
|
||||
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 */
|
||||
first_channel=0;
|
||||
mix_ticks=GetTicks();
|
||||
|
@ -16,16 +16,17 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <dosbox.h>
|
||||
#include <mixer.h>
|
||||
#include <math.h>
|
||||
#include "dosbox.h"
|
||||
#include "mixer.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define SPKR_BUF 4096
|
||||
#define SPKR_RATE 22050
|
||||
#define SPKR_VOLUME 5000
|
||||
|
||||
@ -41,15 +42,26 @@ struct Speaker {
|
||||
Bit16s volume;
|
||||
MIXER_Channel * chan;
|
||||
bool enabled;
|
||||
bool realsound;
|
||||
Bit16u buffer[SPKR_BUF];
|
||||
Bitu buf_pos;
|
||||
};
|
||||
|
||||
|
||||
static Speaker spkr;
|
||||
|
||||
|
||||
void PCSPEAKER_SetFreq(Bit32u freq) {
|
||||
spkr.freq_add=(Bit32u)(FREQ_MAX/((float)SPKR_RATE/(float)freq));
|
||||
spkr.freq_pos=0;
|
||||
void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode) {
|
||||
switch (mode) {
|
||||
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) {
|
||||
@ -58,31 +70,38 @@ void PCSPEAKER_Enable(bool enable) {
|
||||
}
|
||||
|
||||
static void PCSPEAKER_CallBack(Bit8u * stream,Bit32u len) {
|
||||
/* Generate the speaker wave, TODO Improve :) */
|
||||
for (Bit32u c=0;c<len;c++) {
|
||||
spkr.freq_pos+=spkr.freq_add;
|
||||
if (spkr.freq_pos>=FREQ_MAX) spkr.freq_pos-=FREQ_MAX;
|
||||
if (spkr.freq_pos>=FREQ_HALF) {
|
||||
*(Bit16s*)(stream)=spkr.volume;
|
||||
} else {
|
||||
*(Bit16s*)(stream)=-spkr.volume;
|
||||
if (spkr.realsound) {
|
||||
/* 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;
|
||||
if (spkr.freq_pos>=FREQ_MAX) spkr.freq_pos-=FREQ_MAX;
|
||||
if (spkr.freq_pos>=FREQ_HALF) {
|
||||
*(Bit16s*)(stream)=spkr.volume;
|
||||
} else {
|
||||
*(Bit16s*)(stream)=-spkr.volume;
|
||||
}
|
||||
stream+=2;
|
||||
}
|
||||
/*
|
||||
if (spkr.freq_pos>=FREQ_HALF) {
|
||||
spkr.freq_pos-=FREQ_HALF;
|
||||
spkr.volume=-spkr.volume;
|
||||
};
|
||||
*(Bit16s*)(stream)=spkr.volume;
|
||||
*/
|
||||
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");
|
||||
MIXER_Enable(spkr.chan,false);
|
||||
MIXER_SetMode(spkr.chan,MIXER_16MONO);
|
||||
spkr.volume=SPKR_VOLUME;
|
||||
spkr.enabled=false;
|
||||
spkr.realsound=false;
|
||||
spkr.buf_pos=0;
|
||||
}
|
||||
|
@ -31,7 +31,9 @@ struct IRQ_Block {
|
||||
PIC_EOIHandler * handler;
|
||||
};
|
||||
|
||||
Bit32u PIC_IRQCheck;
|
||||
Bitu PIC_IRQCheck;
|
||||
Bitu PIC_IRQActive;
|
||||
bool PIC_IRQAgain;
|
||||
|
||||
static IRQ_Block irqs[16];
|
||||
static Bit8u pic0_icws=0;
|
||||
@ -45,7 +47,6 @@ static bool pic1_request_iisr=0;
|
||||
|
||||
//Pic 0 command port
|
||||
static void write_p20(Bit32u port,Bit8u val) {
|
||||
Bit32u i;
|
||||
switch (val) {
|
||||
case 0x0A: /* select read interrupt request register */
|
||||
pic0_request_iisr=false;
|
||||
@ -56,7 +57,6 @@ static void write_p20(Bit32u port,Bit8u val) {
|
||||
case 0x10: /* ICW1 */
|
||||
pic0_icws=2;
|
||||
pic0_icw_state=1;
|
||||
|
||||
break;
|
||||
case 0x11: /* ICW1 + need for ICW4 */
|
||||
pic0_icws=3;
|
||||
@ -64,13 +64,11 @@ static void write_p20(Bit32u port,Bit8u val) {
|
||||
break;
|
||||
case 0x20: /* end of interrupt command */
|
||||
/* clear highest current in service bit */
|
||||
for (i=0;i<=7;i++) {
|
||||
if (irqs[i].inservice) {
|
||||
irqs[i].inservice=false;
|
||||
if (irqs[i].handler!=0) irqs[i].handler();
|
||||
break;
|
||||
};
|
||||
};
|
||||
if (PIC_IRQActive<8) {
|
||||
irqs[PIC_IRQActive].inservice=false;
|
||||
if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler();
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
}
|
||||
break;
|
||||
case 0x60: /* specific EOI 0 */
|
||||
case 0x61: /* specific EOI 1 */
|
||||
@ -80,10 +78,11 @@ static void write_p20(Bit32u port,Bit8u val) {
|
||||
case 0x65: /* specific EOI 5 */
|
||||
case 0x66: /* specific EOI 6 */
|
||||
case 0x67: /* specific EOI 7 */
|
||||
if (irqs[val-0x60].inservice) {
|
||||
irqs[val-0x60].inservice=false;
|
||||
if (irqs[val-0x60].handler!=0) irqs[val-0x60].handler();
|
||||
};
|
||||
if (PIC_IRQActive==(val-0x60U)) {
|
||||
irqs[PIC_IRQActive].inservice=false;
|
||||
if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler();
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
}
|
||||
break;
|
||||
// IRQ lowest priority commands
|
||||
case 0xC0: // 0 7 6 5 4 3 2 1
|
||||
@ -176,13 +175,11 @@ static void write_pa0(Bit32u port,Bit8u val) {
|
||||
break;
|
||||
case 0x20: /* end of interrupt command */
|
||||
/* clear highest current in service bit */
|
||||
for (i=8;i<=15;i++) {
|
||||
if (irqs[i].inservice) {
|
||||
irqs[i].inservice=false;
|
||||
if (irqs[i].handler!=0) irqs[i].handler();
|
||||
break;
|
||||
};
|
||||
};
|
||||
if (PIC_IRQActive>7 && PIC_IRQActive <16) {
|
||||
irqs[PIC_IRQActive].inservice=false;
|
||||
if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler();
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
}
|
||||
break;
|
||||
case 0x60: /* specific EOI 0 */
|
||||
case 0x61: /* specific EOI 1 */
|
||||
@ -192,9 +189,10 @@ static void write_pa0(Bit32u port,Bit8u val) {
|
||||
case 0x65: /* specific EOI 5 */
|
||||
case 0x66: /* specific EOI 6 */
|
||||
case 0x67: /* specific EOI 7 */
|
||||
if (irqs[val-0x60+8].inservice) {
|
||||
irqs[val-0x60+8].inservice=false;
|
||||
if (irqs[val-0x60+8].handler!=0) irqs[val-0x60+8].handler();
|
||||
if (PIC_IRQActive==(8+val-0x60U)) {
|
||||
irqs[PIC_IRQActive].inservice=false;
|
||||
if (irqs[PIC_IRQActive].handler!=0) irqs[PIC_IRQActive].handler();
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
};
|
||||
break;
|
||||
// IRQ lowest priority commands
|
||||
@ -220,6 +218,7 @@ static void write_pa1(Bit32u port,Bit8u val) {
|
||||
case 0: /* mask register */
|
||||
for (i=0;i<=7;i++) {
|
||||
irqs[i+8].masked=(val&1 <<i)>0;
|
||||
if (!irqs[8].masked) LOG_DEBUG("Someone unmasked RTC irq");
|
||||
};
|
||||
break;
|
||||
case 1: /* icw2 */
|
||||
@ -245,7 +244,7 @@ static Bit8u read_pa0(Bit32u port) {
|
||||
if (irqs[i+8].active) ret|=b;
|
||||
b <<= 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
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) {
|
||||
Bit32u i;
|
||||
if (!flags.intf) goto noirqs;
|
||||
if (!PIC_IRQCheck) goto noirqs;
|
||||
if (!flags.intf) return;
|
||||
if (PIC_IRQActive!=PIC_NOIRQ) return;
|
||||
if (!PIC_IRQCheck) return;
|
||||
for (i=0;i<=15;i++) {
|
||||
if (i!=2) {
|
||||
if (!irqs[i].masked && irqs[i].active /* && !irqs[i].inservice */) {
|
||||
if (!irqs[i].masked && irqs[i].active) {
|
||||
irqs[i].inservice=true;
|
||||
irqs[i].active=false;
|
||||
PIC_IRQCheck&=~(1 << i);
|
||||
Interrupt(irqs[i].vector);
|
||||
break;
|
||||
};
|
||||
};
|
||||
};
|
||||
noirqs:
|
||||
/* This also runs special hardware functions that can queue themselves here */
|
||||
for (;pic_queuesize>0;) {
|
||||
(*pic_queue[--pic_queuesize])();
|
||||
PIC_IRQActive=i;
|
||||
PIC_IRQAgain=true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void PIC_Init(void) {
|
||||
void PIC_Init(Section* sec) {
|
||||
/* Setup pic0 and pic1 with initial values like DOS has normally */
|
||||
PIC_IRQCheck=0;
|
||||
PIC_IRQActive=PIC_NOIRQ;
|
||||
Bit8u i;
|
||||
for (i=0;i<=7;i++) {
|
||||
irqs[i].active=false;
|
||||
@ -351,11 +326,10 @@ void PIC_Init(void) {
|
||||
irqs[i+8].inservice=false;
|
||||
irqs[i].vector=0x8+i;
|
||||
irqs[i+8].vector=0x70+i;
|
||||
};
|
||||
}
|
||||
irqs[0].masked=false; /* Enable system timer */
|
||||
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;
|
||||
irqs[12].masked=false; /* Enable Mouse IRQ */
|
||||
IO_RegisterReadHandler(0x20,read_p20,"Master PIC Command");
|
||||
IO_RegisterReadHandler(0x21,read_p21,"Master PIC Data");
|
||||
IO_RegisterWriteHandler(0x20,write_p20,"Master PIC Command");
|
||||
@ -364,6 +338,6 @@ void PIC_Init(void) {
|
||||
IO_RegisterReadHandler(0xa1,read_pa1,"Slave PIC Data");
|
||||
IO_RegisterWriteHandler(0xa0,write_pa0,"Slave PIC Command");
|
||||
IO_RegisterWriteHandler(0xa1,write_pa1,"Slave PIC Data");
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "dma.h"
|
||||
#include "pic.h"
|
||||
#include "hardware.h"
|
||||
#include "setup.h"
|
||||
#include "programs.h"
|
||||
|
||||
#define SB_BASE 0x220
|
||||
#define SB_IRQ 5
|
||||
@ -44,7 +46,7 @@
|
||||
|
||||
enum {DSP_S_RESET,DSP_S_NORMAL,DSP_S_HIGHSPEED};
|
||||
enum {
|
||||
MODE_NONE,MODE_DAC,
|
||||
MODE_NONE,MODE_DAC,MODE_SILENCE,
|
||||
MODE_PCM_8S,MODE_PCM_8A,
|
||||
MODE_ADPCM_4S
|
||||
};
|
||||
@ -90,7 +92,6 @@ struct SB_INFO {
|
||||
Bit8u irq;
|
||||
Bit8u dma;
|
||||
bool enabled;
|
||||
HWBlock hwblock;
|
||||
MIXER_Channel * chan;
|
||||
};
|
||||
|
||||
@ -143,7 +144,7 @@ static void DSP_SetSpeaker(bool how) {
|
||||
}
|
||||
|
||||
static void DSP_HaltDMA(void) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
static INLINE void DSP_FlushData(void) {
|
||||
@ -151,15 +152,8 @@ static INLINE void DSP_FlushData(void) {
|
||||
sb.data_out_pos=0;
|
||||
}
|
||||
|
||||
static void DSP_SetSampleRate(Bit32u rate) {
|
||||
/* This directly changes the mixer */
|
||||
|
||||
|
||||
}
|
||||
static void DSP_StopDMA(void) {
|
||||
sb.mode=MODE_NONE;
|
||||
// MIXER_SetMode(sb.chan,MIXER_8MONO);
|
||||
// MIXER_SetFreq(sb.chan,22050);
|
||||
}
|
||||
|
||||
static void DSP_StartDMATranfser(Bit8u mode) {
|
||||
@ -168,6 +162,10 @@ static void DSP_StartDMATranfser(Bit8u mode) {
|
||||
sb.freq=(1000000 / (256 - sb.time_constant));
|
||||
};
|
||||
switch (mode) {
|
||||
case MODE_SILENCE:
|
||||
MIXER_SetFreq(sb.chan,sb.freq);
|
||||
SB_DEBUG("DSP:PCM 8 bit single cycle rate %d size %d",sb.freq,sb.samples_total);
|
||||
break;
|
||||
case MODE_PCM_8S:
|
||||
MIXER_SetFreq(sb.chan,sb.freq);
|
||||
SB_DEBUG("DSP:PCM 8 bit single cycle rate %d size %d",sb.freq,sb.samples_total);
|
||||
@ -175,13 +173,11 @@ static void DSP_StartDMATranfser(Bit8u mode) {
|
||||
case MODE_PCM_8A:
|
||||
MIXER_SetFreq(sb.chan,sb.freq);
|
||||
SB_DEBUG("DSP:PCM 8 bit auto init rate %d size %d",sb.freq,sb.samples_total);
|
||||
|
||||
break;
|
||||
case MODE_ADPCM_4S:
|
||||
MIXER_SetFreq(sb.chan,sb.freq);
|
||||
SB_DEBUG("DSP:ADPCM 4 bit single cycle rate %d size %X",sb.freq,sb.samples_total);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR("DSP:Illegal transfer mode %d",mode);
|
||||
return;
|
||||
@ -206,6 +202,9 @@ static void DSP_Reset(void) {
|
||||
sb.mode=MODE_NONE;
|
||||
sb.cmd_len=0;
|
||||
sb.cmd_in_pos=0;
|
||||
sb.samples_left=0;
|
||||
sb.samples_total=0;
|
||||
sb.freq=22050;
|
||||
sb.use_time_constant=false;
|
||||
sb.dac.used=0;
|
||||
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);
|
||||
DSP_StartDMATranfser(MODE_ADPCM_4S);
|
||||
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 */
|
||||
DSP_HaltDMA();
|
||||
break;
|
||||
@ -289,7 +292,6 @@ static void DSP_DoCommand(void) {
|
||||
*/
|
||||
//TODO Ofcourse :)
|
||||
}
|
||||
|
||||
break;
|
||||
case 0xe3: /* DSP Copyright */
|
||||
{
|
||||
@ -444,6 +446,16 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MODE_SILENCE:
|
||||
memset(stream,0x80,len);
|
||||
if (sb.samples_left>len) {
|
||||
sb.samples_left-=len;
|
||||
} else {
|
||||
sb.samples_left=0;
|
||||
sb.mode=MODE_NONE;
|
||||
PIC_ActivateIRQ(sb.irq);
|
||||
}
|
||||
break;
|
||||
case MODE_PCM_8A:
|
||||
{
|
||||
Bit16u read=DMA_8_Read(sb.dma,stream,(Bit16u)len);
|
||||
@ -524,8 +536,6 @@ static void SBLASTER_CallBack(Bit8u * stream,Bit32u len) {
|
||||
|
||||
|
||||
|
||||
static bool SB_enabled;
|
||||
|
||||
static void SB_Enable(bool enable) {
|
||||
Bitu i;
|
||||
if (enable) {
|
||||
@ -542,90 +552,22 @@ static void SB_Enable(bool enable) {
|
||||
for (i=sb.base+4;i<sb.base+0xf;i++){
|
||||
IO_FreeReadHandler(i);
|
||||
IO_FreeWriteHandler(i);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SB_InputHandler(char * line) {
|
||||
bool s_off,s_on,s_base,s_irq,s_dma;
|
||||
Bits n_base,n_irq,n_dma;
|
||||
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) {
|
||||
void SBLASTER_Init(Section* sec) {
|
||||
MSG_Add("SBLASTER_CONFIGFILE_HELP","Sound Blaster related options.\n");
|
||||
Section_prop * section=static_cast<Section_prop *>(sec);
|
||||
if(!section->Get_bool("enabled")) return;
|
||||
sb.chan=MIXER_AddChannel(&SBLASTER_CallBack,22050,"SBLASTER");
|
||||
MIXER_Enable(sb.chan,false);
|
||||
sb.state=DSP_S_NORMAL;
|
||||
/* Setup the hardware handler part */
|
||||
sb.base=SB_BASE;
|
||||
sb.irq=SB_IRQ;
|
||||
sb.dma=SB_DMA;
|
||||
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);
|
||||
|
||||
sb.state=DSP_S_NORMAL;
|
||||
|
||||
sb.base=section->Get_hex("base");
|
||||
sb.irq=section->Get_int("irq");
|
||||
sb.dma=section->Get_int("dma");
|
||||
SB_Enable(true);
|
||||
SHELL_AddAutoexec("SET BLASTER=A%3X I%d D%d T3",sb.base,sb.irq,sb.dma);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "inout.h"
|
||||
#include "mixer.h"
|
||||
#include "mem.h"
|
||||
#include "setup.h"
|
||||
|
||||
#define TANDY_DIV 111860
|
||||
#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");
|
||||
tandy_chan=MIXER_AddChannel(&TANDYSOUND_CallBack,TANDY_RATE,"TANDY");
|
||||
MIXER_Enable(tandy_chan,false);
|
||||
|
@ -42,12 +42,22 @@ struct PIT_Block {
|
||||
Bit32u last_ticks;
|
||||
};
|
||||
|
||||
|
||||
bool TimerAgain;
|
||||
Bit32u LastTicks;
|
||||
static PIT_Block pit[3];
|
||||
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_buildup; /* The amount of pit ticks waiting */
|
||||
#define PIT_TICK_RATE 1193182
|
||||
static Bit32u timer_buildup; /* The amount of pit ticks waiting */
|
||||
|
||||
#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 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) {
|
||||
/* Fill the read_latch of the selected counter with current count */
|
||||
PIT_Block * p=&pit[counter];
|
||||
//TODO Perhaps make it a bit64u for accuracy :)
|
||||
Bit32u ticks=(((LastTicks - p->last_ticks) * pit_ticks) >> PIT_SHIFT) % p->cntr ;
|
||||
timer.req_count++;
|
||||
float pos=timer.req_average*timer.req_count;
|
||||
Bit16u ticks=pos*p->cntr;
|
||||
switch (p->mode) {
|
||||
case 2:
|
||||
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);
|
||||
break;
|
||||
case 0x02: /* Timer hooked to PC-Speaker */
|
||||
PCSPEAKER_SetFreq(PIT_TICK_RATE/p->cntr);
|
||||
PCSPEAKER_SetCounter(p->cntr,p->mode);
|
||||
break;
|
||||
default:
|
||||
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) {
|
||||
/* This will run through registered handlers and handle the PIT ticks */
|
||||
/* Add pit ticks to the counter */
|
||||
timer_buildup+=ticks*pit_ticks;
|
||||
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;
|
||||
for(i=Timers.begin(); i != Timers.end(); ++i) {
|
||||
Timer * timer=(*i);
|
||||
switch (timer->type) {
|
||||
Timer * timers=(*i);
|
||||
switch (timers->type) {
|
||||
case T_TICK:
|
||||
timer->tick.handler(ticks);
|
||||
if (timer.ticks) timers->tick.handler(timer.ticks);
|
||||
break;
|
||||
case T_MICRO:
|
||||
timer->micro.count+=add_micro;
|
||||
if (timer->micro.count>=timer->micro.total) {
|
||||
timer->micro.count-=timer->micro.total;
|
||||
timer->micro.handler();
|
||||
timers->micro.count+=add_micro;
|
||||
if (timers->micro.count>=timers->micro.total) {
|
||||
timers->micro.count-=timers->micro.total;
|
||||
timers->micro.handler();
|
||||
}
|
||||
break;
|
||||
case T_DELAY:
|
||||
/* Also unregister the timer handler from the list */
|
||||
if (LastTicks>timer->delay.end) {
|
||||
if (LastTicks>timers->delay.end) {
|
||||
std::list<Timer *>::iterator remove;
|
||||
timer->delay.handler();
|
||||
timers->delay.handler();
|
||||
remove=i++;
|
||||
Timers.erase(remove);
|
||||
}
|
||||
@ -265,19 +277,28 @@ void TIMER_AddTicks(Bit32u ticks) {
|
||||
};
|
||||
|
||||
};
|
||||
timer.ticks=ticks;
|
||||
}
|
||||
|
||||
|
||||
void TIMER_CheckPIT(void) {
|
||||
if (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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TIMER_Init(void) {
|
||||
void TIMER_Init(Section* sect) {
|
||||
Bitu i;
|
||||
IO_RegisterWriteHandler(0x40,write_latch,"PIT Timer 0");
|
||||
IO_RegisterWriteHandler(0x42,write_latch,"PIT Timer 2");
|
||||
IO_RegisterWriteHandler(0x43,write_p43,"PIT Mode Control");
|
||||
@ -293,7 +314,8 @@ void TIMER_Init(void) {
|
||||
pit[0].mode=3;
|
||||
timer_ticks=pit[0].cntr << PIT_SHIFT;
|
||||
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;
|
||||
PIC_RegisterIRQ(0,&TIMER_CheckPIT,"PIT 0 Timer");
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ void VGA_StartResize(void) {
|
||||
}
|
||||
|
||||
|
||||
void VGA_Init() {
|
||||
void VGA_Init(Section* sec) {
|
||||
vga.draw.resizing=false;
|
||||
VGA_SetupMemory();
|
||||
VGA_SetupMisc();
|
||||
|
@ -176,8 +176,8 @@ void VGA_DrawTEXT(Bit8u * bitdata,Bitu pitch) {
|
||||
vga.config.retrace=true;
|
||||
|
||||
/* Draw a cursor */
|
||||
if ((vga.draw.cursor_col*8)>=vga.draw.width) return;
|
||||
if ((vga.draw.cursor_row*16)>=vga.draw.height) return;
|
||||
if (((Bitu)vga.draw.cursor_col*8)>=vga.draw.width) return;
|
||||
if (((Bitu)vga.draw.cursor_row*16)>=vga.draw.height) return;
|
||||
Bit8u * cursor_draw=bitdata+(vga.draw.cursor_row*16+15)*pitch+vga.draw.cursor_col*8;
|
||||
if (vga.draw.cursor_count>8) {
|
||||
for (Bit8u loop=0;loop<8;loop++) *cursor_draw++=15;
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "callback.h"
|
||||
#include "inout.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include "timer.h"
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
static void WaitFlagEvent(void) {
|
||||
PhysPt where=Real2Phys(mem_readd(BIOS_WAIT_FLAG_POINTER));
|
||||
mem_writeb(where,mem_readb(where)|0x80);
|
||||
mem_writeb(BIOS_WAIT_FLAG_ACTIVE,0);
|
||||
}
|
||||
|
||||
static Bitu INT15_Handler(void) {
|
||||
switch (reg_ah) {
|
||||
case 0x06:
|
||||
@ -149,6 +155,12 @@ static Bitu INT15_Handler(void) {
|
||||
/* Carry should be set but let's just set it just in case */
|
||||
CALLBACK_SCF(true);
|
||||
break;
|
||||
case 0x83: /* BIOS - SET EVENT WAIT INTERVAL */
|
||||
mem_writed(BIOS_WAIT_FLAG_POINTER,RealMake(SegValue(es),reg_bx));
|
||||
mem_writed(BIOS_WAIT_FLAG_COUNT,reg_cx<<16|reg_dx);
|
||||
mem_writeb(BIOS_WAIT_FLAG_ACTIVE,1);
|
||||
TIMER_RegisterDelayHandler(&WaitFlagEvent,reg_cx<<16|reg_dx);
|
||||
break;
|
||||
case 0x84: /* BIOS - JOYSTICK SUPPORT (XT after 11/8/82,AT,XT286,PS) */
|
||||
//Does anyone even use this?
|
||||
LOG_WARN("INT15:84:Bios Joystick functionality not done");
|
||||
@ -181,6 +193,8 @@ static Bitu INT15_Handler(void) {
|
||||
break;
|
||||
default:
|
||||
LOG_WARN("INT15:Unknown call %2X",reg_ah);
|
||||
reg_ah=0x86;
|
||||
CALLBACK_SCF(false);
|
||||
}
|
||||
return CBRET_NONE;
|
||||
};
|
||||
@ -193,7 +207,8 @@ static void INT15_StartUp(void) {
|
||||
void BIOS_SetupKeyboard(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 */
|
||||
for (Bit16u i=0;i<1024;i++) real_writeb(0x40,i,0);
|
||||
/* 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
|
||||
RealSetVec(0x8,CALLBACK_RealPointer(call_int8));
|
||||
/* INT10 Video Bios */
|
||||
INT10_StartUp();
|
||||
|
||||
/* INT 11 Get equipment list */
|
||||
call_int11=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_int11,&INT11_Handler,CB_IRET);
|
||||
|
@ -329,7 +329,7 @@ static Bitu INT16_Handler(void) {
|
||||
LOG_DEBUG("INT16:55:Word TSR compatible call");
|
||||
break;
|
||||
default:
|
||||
E_Exit("INT16:Unhandled call %02X",reg_ah);
|
||||
LOG_ERROR("INT16:Unhandled call %02X",reg_ah);
|
||||
break;
|
||||
|
||||
};
|
||||
|
114
src/ints/ems.cpp
114
src/ints/ems.cpp
@ -27,7 +27,9 @@
|
||||
#include "regs.h"
|
||||
#include "inout.h"
|
||||
#include "dos_inc.h"
|
||||
#include "setup.h"
|
||||
|
||||
#define EMM_USEHANDLER 1
|
||||
|
||||
#define EMM_PAGEFRAME 0xE000
|
||||
#define EMM_MAX_HANDLES 50 /* 255 Max */
|
||||
@ -97,8 +99,23 @@ struct EMM_Handle {
|
||||
static EMM_Handle emm_handles[EMM_MAX_HANDLES];
|
||||
static EMM_Page emm_pages[EMM_MAX_PAGES];
|
||||
static EMM_Mapping emm_mappings[EMM_MAX_PHYS];
|
||||
static HostPt emm_pagebase[EMM_MAX_PHYS];
|
||||
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) {
|
||||
Bit16u count=0;
|
||||
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;}
|
||||
handle=1;
|
||||
/* 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;}
|
||||
}
|
||||
/* Allocate the pages */
|
||||
@ -138,7 +155,7 @@ static Bit8u EMM_AllocateMemory(Bit16u pages,Bit16u & handle) {
|
||||
|
||||
static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) {
|
||||
/* 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 */
|
||||
if ((emm_handles[handle].pages+EMM_GetFreePages())<pages) return EMM_OUT_OF_LOG;
|
||||
Bit16u page=emm_handles[handle].first_page;
|
||||
@ -163,6 +180,7 @@ static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) {
|
||||
page=next_page;page_count--;
|
||||
}
|
||||
pages=emm_handles[handle].pages;
|
||||
if (!pages) emm_handles[handle].first_page=NULL_PAGE;
|
||||
return EMM_NO_ERROR;
|
||||
}
|
||||
if (!page_count && pages) {
|
||||
@ -174,7 +192,8 @@ static Bit8u EMM_ReallocatePages(Bit16u handle,Bit16u & pages) {
|
||||
emm_pages[page].handle=handle;
|
||||
emm_pages[page].memory=malloc(EMM_PAGE_SIZE);
|
||||
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;
|
||||
pages--;
|
||||
} else {
|
||||
@ -193,7 +212,7 @@ static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
|
||||
/* Check for too high physical page */
|
||||
if (phys_page>=EMM_MAX_PHYS) return EMM_ILL_PHYS;
|
||||
/* Check for valid handle */
|
||||
if (handle>=EMM_MAX_HANDLES || emm_handles[handle].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 */
|
||||
if (log_page<emm_handles[handle].pages) {
|
||||
/* Mapping it is */
|
||||
@ -206,13 +225,21 @@ static Bit8u EMM_MapPage(Bitu phys_page,Bit16u handle,Bit16u log_page) {
|
||||
log_page--;
|
||||
}
|
||||
/* 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);
|
||||
#endif
|
||||
return EMM_NO_ERROR;
|
||||
} else if (log_page==NULL_PAGE) {
|
||||
/* Unmapping it is */
|
||||
emm_mappings[phys_page].handle=NULL_HANDLE;
|
||||
emm_mappings[phys_page].page=NULL_PAGE;
|
||||
#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));
|
||||
#endif
|
||||
return EMM_NO_ERROR;
|
||||
} else {
|
||||
/* 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) {
|
||||
/* 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 pages=emm_handles[handle].pages;
|
||||
while (pages) {
|
||||
@ -235,7 +262,7 @@ static Bit8u EMM_ReleaseMemory(Bit16u handle) {
|
||||
}
|
||||
/* Reset handle */
|
||||
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;
|
||||
memset(&emm_handles[handle].name,0,9);
|
||||
return EMM_NO_ERROR;
|
||||
@ -243,7 +270,7 @@ static Bit8u EMM_ReleaseMemory(Bit16u handle) {
|
||||
|
||||
static Bit8u EMM_SavePageMap(Bit16u 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 */
|
||||
if (emm_handles[handle].saved_page_map) return EMM_PAGE_MAP_SAVED;
|
||||
/* Copy the mappings over */
|
||||
@ -255,7 +282,7 @@ static Bit8u EMM_SavePageMap(Bit16u handle) {
|
||||
return EMM_NO_ERROR;
|
||||
}
|
||||
|
||||
static Bitu EMM_RestoreMappingTable(void) {
|
||||
static Bit8u EMM_RestoreMappingTable(void) {
|
||||
Bit8u result;
|
||||
/* Move through the mappings table and setup mapping accordingly */
|
||||
for (Bitu i=0;i<EMM_MAX_PHYS;i++) {
|
||||
@ -265,7 +292,7 @@ static Bitu EMM_RestoreMappingTable(void) {
|
||||
}
|
||||
static Bit8u EMM_RestorePageMap(Bit16u 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 */
|
||||
if (!emm_handles[handle].saved_page_map) return EMM_INVALID_HANDLE;
|
||||
/* Restore the mappings */
|
||||
@ -280,7 +307,7 @@ static Bit8u EMM_RestorePageMap(Bit16u handle) {
|
||||
static Bit8u EMM_GetPagesForAllHandles(PhysPt table,Bit16u & handles) {
|
||||
handles=0;
|
||||
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++;
|
||||
mem_writew(table,i);
|
||||
mem_writew(table+2,emm_handles[i].pages);
|
||||
@ -290,6 +317,44 @@ static Bit8u EMM_GetPagesForAllHandles(PhysPt table,Bit16u & handles) {
|
||||
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) {
|
||||
Bitu i;
|
||||
switch (reg_ah) {
|
||||
@ -326,12 +391,12 @@ static Bitu INT67_Handler(void) {
|
||||
break;
|
||||
case 0x4b: /* Get Handle Count */
|
||||
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;
|
||||
break;
|
||||
case 0x4c: /* Get Pages for one 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_ah=EMM_NO_ERROR;
|
||||
break;
|
||||
@ -339,7 +404,6 @@ static Bitu INT67_Handler(void) {
|
||||
reg_ah=EMM_GetPagesForAllHandles(SegPhys(es)+reg_di,reg_bx);
|
||||
break;
|
||||
case 0x4e: /*Save/Restore Page Map */
|
||||
LOG_WARN("Save/resetore %d",reg_al);
|
||||
switch (reg_al) {
|
||||
case 0x00: /* Save Page Map */
|
||||
MEM_BlockWrite(SegPhys(es)+reg_di,emm_mappings,sizeof(emm_mappings));
|
||||
@ -364,7 +428,11 @@ static Bitu INT67_Handler(void) {
|
||||
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;
|
||||
switch (reg_al) {
|
||||
case 0x00: // use physical page numbers
|
||||
@ -413,7 +481,7 @@ static Bitu INT67_Handler(void) {
|
||||
reg_ah = EMM_NO_ERROR;
|
||||
break;
|
||||
case 0xDE: /* VCPI Functions */
|
||||
LOG_ERROR("VCPI Functions not supported");
|
||||
LOG_ERROR("VCPI Functions %X not supported",reg_al);
|
||||
reg_ah=EMM_FUNC_NOSUP;
|
||||
break;
|
||||
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();
|
||||
CALLBACK_Setup(call_int67,&INT67_Handler,CB_IRET);
|
||||
/* Register the ems device */
|
||||
DOS_Device * newdev = new device_EMM();
|
||||
DOS_AddDevice(newdev);
|
||||
|
||||
|
||||
/* Add a little hack so it appears that there is an actual ems device installed */
|
||||
char * emsname="EMMXXXX0";
|
||||
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++) {
|
||||
emm_handles[i].first_page=NULL_PAGE;
|
||||
emm_handles[i].pages=NULL_HANDLE;
|
||||
memset(&emm_handles[i].name,0,9);
|
||||
}
|
||||
for (i=0;i<EMM_MAX_PHYS;i++) {
|
||||
emm_mappings[i].page=NULL_PAGE;
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,7 @@ static void INT10_InitVGA(void) {
|
||||
IO_Write(0x3c5,0x02);
|
||||
};
|
||||
|
||||
void INT10_StartUp(void) {
|
||||
void INT10_Init(Section* sec) {
|
||||
INT10_InitVGA();
|
||||
/* Setup the INT 10 vector */
|
||||
call_10=CALLBACK_Allocate();
|
||||
|
@ -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,0x0);IO_Write(0x3cf,attr);
|
||||
IO_Write(0x3ce,0x1);IO_Write(0x3cf,0xf);
|
||||
IO_Write(0x3ce,5);IO_Write(0x3cf,0); /* Normal transfer mode */
|
||||
/* Write some bytes */
|
||||
PhysPt dest;
|
||||
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;
|
||||
next=-1;
|
||||
} else if (nlines<0) {
|
||||
start=cul-nlines-1;
|
||||
end=clr;
|
||||
start=rul-nlines-1;
|
||||
end=rlr;
|
||||
next=1;
|
||||
} else {
|
||||
nlines=rlr-rul+1;
|
||||
@ -127,8 +126,8 @@ filling:
|
||||
if (nlines>0) {
|
||||
start=rul;
|
||||
} else {
|
||||
nlines-=nlines;
|
||||
start=rlr-nlines;
|
||||
nlines=-nlines;
|
||||
start=rlr-nlines+1;
|
||||
}
|
||||
for (;nlines>0;nlines--) {
|
||||
switch (curmode->memmodel) {
|
||||
|
@ -23,9 +23,7 @@
|
||||
|
||||
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
struct Dynamic_Functionality {
|
||||
RealPt static_table; /* 00h DWORD address of static functionality table */
|
||||
Bit8u cur_mode; /* 04h BYTE video mode in effect */
|
||||
@ -70,19 +68,10 @@ struct Dynamic_Functionality {
|
||||
7 reserved
|
||||
*/
|
||||
Bit8u reserved2[13]; /* 33h 13 BYTEs reserved (00h) */
|
||||
}
|
||||
#if defined (_MSC_VER)
|
||||
;
|
||||
} GCC_ATTRIBUTE(packed);
|
||||
#pragma pack()
|
||||
#else
|
||||
__attribute__ ((packed));
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void INT10_GetFuncStateInformation(PhysPt save) {
|
||||
|
||||
|
||||
/* set static state pointer */
|
||||
mem_writed(save,int10_romarea.static_state);
|
||||
/* Copy BIOS Segment areas */
|
||||
|
@ -274,6 +274,44 @@ void INT10_SetVideoMode(Bit8u mode) {
|
||||
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) {
|
||||
// Set the PEL mask
|
||||
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);
|
||||
// Set Attribute Ctl
|
||||
for(i=0;i<=ACTL_MAX_REG;i++) {
|
||||
// Set the Low Attribute Ctl
|
||||
for(i=0;i<=0xf;i++) {
|
||||
IO_Write(VGAREG_ACTL_ADDRESS,(Bit8u)i);
|
||||
IO_Write(VGAREG_ACTL_WRITE_DATA,actl_regs[vga_modes[line].actlmodel][i]);
|
||||
}
|
||||
// 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;
|
||||
if(clearmem) {
|
||||
if(vga_modes[line].type==TEXT) {
|
||||
@ -377,6 +388,7 @@ void INT10_SetVideoMode(Bit8u mode) {
|
||||
real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight);
|
||||
real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem << 7)));
|
||||
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);
|
||||
|
||||
// FIXME We nearly have the good tables. to be reworked
|
||||
|
@ -21,12 +21,6 @@
|
||||
#include "inout.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};
|
||||
|
||||
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);
|
||||
if (y&1) off+=8*1024;
|
||||
Bit8u old=real_readb(0xb800,off);
|
||||
old=old&cga_masks[x&3]|((color&3) << (2*(3-(x&3))));
|
||||
if (color & 0x80) {
|
||||
color&=3;
|
||||
old^=color << (2*(3-(x&3)));
|
||||
} else {
|
||||
old=old&cga_masks[x&3]|((color&3) << (2*(3-(x&3))));
|
||||
}
|
||||
real_writeb(0xb800,off,old);
|
||||
}
|
||||
break;
|
||||
@ -51,20 +50,27 @@ void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) {
|
||||
IO_Write(0x3ce,0x0);IO_Write(0x3cf,color);
|
||||
/* Enable all the set/resets */
|
||||
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
|
||||
/* Calculate where the pixel is in video memory */
|
||||
Bit16u base_address=((((curmode->sheight*curmode->swidth)>>3)|0xff)+1)*page;
|
||||
PhysPt off=0xa0000+base_address+((y*curmode->swidth+x)>>3);
|
||||
PhysPt off=0xa0000+curmode->slength*page+((y*curmode->swidth+x)>>3);
|
||||
/* Bitmask and set/reset should do the rest */
|
||||
mem_readb(off);
|
||||
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;
|
||||
}
|
||||
case CTEXT:
|
||||
case MTEXT:
|
||||
case LINEAR8:
|
||||
mem_writeb(Real2Phys(RealMake(0xa000,y*320+x)),color);
|
||||
break;
|
||||
case PLANAR1:
|
||||
case PLANAR2:
|
||||
case LINEAR8:
|
||||
case CTEXT:
|
||||
case MTEXT:
|
||||
default:
|
||||
LOG_WARN("INT10:PutPixel Unhanled memory model");
|
||||
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) {
|
||||
|
||||
VGAMODES * curmode=GetCurrentMode();
|
||||
switch (curmode->memmodel) {
|
||||
case CGA:
|
||||
@ -83,6 +88,30 @@ void INT10_GetPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u * color) {
|
||||
*color=val<<((x&3)*2);
|
||||
}
|
||||
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:
|
||||
LOG_WARN("INT10:GetPixel Unhanled memory model");
|
||||
break;
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "mouse.h"
|
||||
#include "pic.h"
|
||||
#include "inout.h"
|
||||
|
||||
#include "int10.h"
|
||||
|
||||
static Bitu call_int33,call_int74;
|
||||
|
||||
@ -35,24 +35,22 @@ struct button_event {
|
||||
};
|
||||
|
||||
#define QUEUE_SIZE 32
|
||||
//TODO Maybe use :)
|
||||
#define MOUSE_BUTTONS 3
|
||||
#define MOUSE_IRQ 12
|
||||
#define POS_X (Bit16s)(mouse.x*mouse.range_x)
|
||||
#define POS_Y (Bit16s)(mouse.y*mouse.range_y)
|
||||
|
||||
#define POS_X (Bit16s)(mouse.x)
|
||||
#define POS_Y (Bit16s)(mouse.y)
|
||||
|
||||
static struct {
|
||||
Bit16u buttons;
|
||||
Bit16u times_pressed[3];
|
||||
Bit16u times_released[3];
|
||||
Bit16u last_released_x[3];
|
||||
Bit16u last_released_y[3];
|
||||
Bit16u last_pressed_x[3];
|
||||
Bit16u last_pressed_y[3];
|
||||
Bit16u times_pressed[MOUSE_BUTTONS];
|
||||
Bit16u times_released[MOUSE_BUTTONS];
|
||||
Bit16u last_released_x[MOUSE_BUTTONS];
|
||||
Bit16u last_released_y[MOUSE_BUTTONS];
|
||||
Bit16u last_pressed_x[MOUSE_BUTTONS];
|
||||
Bit16u last_pressed_y[MOUSE_BUTTONS];
|
||||
Bit16s shown;
|
||||
float add_x,add_y;
|
||||
Bit16u min_x,max_x,min_y,max_y;
|
||||
float range_x,range_y;
|
||||
float mickey_x,mickey_y;
|
||||
float x,y;
|
||||
button_event event_queue[QUEUE_SIZE];
|
||||
@ -61,8 +59,8 @@ static struct {
|
||||
Bit16u sub_mask;
|
||||
} mouse;
|
||||
|
||||
#define X_MICKEY 500
|
||||
#define Y_MICKEY 500
|
||||
#define X_MICKEY 8
|
||||
#define Y_MICKEY 8
|
||||
|
||||
#define MOUSE_MOVED 1
|
||||
#define MOUSE_LEFT_PRESSED 2
|
||||
@ -72,7 +70,7 @@ static struct {
|
||||
#define MOUSE_MIDDLE_PRESSED 32
|
||||
#define MOUSE_MIDDLE_RELEASED 64
|
||||
|
||||
inline void Mouse_AddEvent(Bit16u type) {
|
||||
INLINE void Mouse_AddEvent(Bit16u type) {
|
||||
if (mouse.events<QUEUE_SIZE) {
|
||||
mouse.event_queue[mouse.events].type=type;
|
||||
mouse.event_queue[mouse.events].buttons=mouse.buttons;
|
||||
@ -81,22 +79,27 @@ inline void Mouse_AddEvent(Bit16u type) {
|
||||
PIC_ActivateIRQ(12);
|
||||
}
|
||||
|
||||
static void DrawCursor() {
|
||||
if (mouse.shown<0) return;
|
||||
}
|
||||
|
||||
void Mouse_CursorMoved(float x,float y) {
|
||||
mouse.mickey_x+=x;
|
||||
mouse.mickey_y+=y;
|
||||
mouse.x+=x;
|
||||
if (mouse.x>1) mouse.x=1;
|
||||
if (mouse.x<0) mouse.x=0;
|
||||
if (mouse.x>mouse.max_x) mouse.x=mouse.max_x;;
|
||||
if (mouse.x<mouse.min_x) mouse.x=mouse.min_x;
|
||||
mouse.y+=y;
|
||||
if (mouse.y>1) mouse.y=1;
|
||||
if (mouse.y<0) mouse.y=0;
|
||||
if (mouse.y>mouse.max_y) mouse.y=mouse.max_y;;
|
||||
if (mouse.y<mouse.min_y) mouse.y=mouse.min_y;
|
||||
Mouse_AddEvent(MOUSE_MOVED);
|
||||
DrawCursor();
|
||||
}
|
||||
|
||||
void Mouse_CursorSet(float x,float y) {
|
||||
|
||||
mouse.x=x;
|
||||
mouse.y=y;
|
||||
DrawCursor();
|
||||
}
|
||||
|
||||
void Mouse_ButtonPressed(Bit8u button) {
|
||||
@ -139,7 +142,6 @@ void Mouse_ButtonReleased(Bit8u button) {
|
||||
mouse.last_released_y[button]=POS_Y;
|
||||
}
|
||||
|
||||
|
||||
static void mouse_reset(void) {
|
||||
real_writed(0,(0x33<<2),CALLBACK_RealPointer(call_int33));
|
||||
real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74));
|
||||
@ -148,8 +150,6 @@ static void mouse_reset(void) {
|
||||
mouse.max_x=639;
|
||||
mouse.min_y=0;
|
||||
mouse.max_y=199;
|
||||
mouse.range_x=639;
|
||||
mouse.range_y=199;
|
||||
mouse.x=0; // civ wont work otherwise
|
||||
mouse.y=100;
|
||||
mouse.events=0;
|
||||
@ -158,15 +158,16 @@ static void mouse_reset(void) {
|
||||
mouse.sub_mask=0;
|
||||
mouse.sub_seg=0;
|
||||
mouse.sub_ofs=0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
static Bitu INT33_Handler(void) {
|
||||
switch (reg_ax) {
|
||||
case 0x00: /* Reset Driver and Read Status */
|
||||
reg_ax=0xffff;
|
||||
reg_bx=0;
|
||||
reg_bx=MOUSE_BUTTONS;
|
||||
mouse_reset();
|
||||
Mouse_AutoLock(true);
|
||||
break;
|
||||
case 0x01: /* Show Mouse */
|
||||
mouse.shown++;
|
||||
@ -181,12 +182,13 @@ static Bitu INT33_Handler(void) {
|
||||
reg_dx=POS_Y;
|
||||
break;
|
||||
case 0x04: /* Position Mouse */
|
||||
mouse.x=((float)reg_cx)/mouse.range_x;
|
||||
mouse.y=((float)reg_dx)/mouse.range_y;
|
||||
mouse.x=(float)reg_cx;
|
||||
mouse.y=(float)reg_dx;
|
||||
break;
|
||||
case 0x05: /* Return Button Press Data */
|
||||
{
|
||||
Bit16u but=reg_bx;
|
||||
if (but>=MOUSE_BUTTONS) break;
|
||||
reg_ax=mouse.buttons;
|
||||
reg_cx=mouse.last_pressed_x[but];
|
||||
mouse.last_pressed_x[but]=0;
|
||||
@ -199,6 +201,7 @@ static Bitu INT33_Handler(void) {
|
||||
case 0x06: /* Return Button Release Data */
|
||||
{
|
||||
Bit16u but=reg_bx;
|
||||
if (but>=MOUSE_BUTTONS) break;
|
||||
reg_ax=mouse.buttons;
|
||||
reg_cx=mouse.last_released_x[but];
|
||||
mouse.last_released_x[but]=0;
|
||||
@ -211,13 +214,10 @@ static Bitu INT33_Handler(void) {
|
||||
case 0x07: /* Define horizontal cursor range */
|
||||
mouse.min_x=reg_cx;
|
||||
mouse.max_x=reg_dx;
|
||||
mouse.range_x=mouse.max_x-mouse.min_x;
|
||||
//TODO Check for range start 0
|
||||
break;
|
||||
case 0x08: /* Define vertical cursor range */
|
||||
mouse.min_y=reg_cx;
|
||||
mouse.max_y=reg_dx;
|
||||
mouse.range_y=mouse.max_y-mouse.min_y;
|
||||
break;
|
||||
case 0x09: /* Define GFX Cursor */
|
||||
LOG_WARN("MOUSE:Define gfx cursor not supported");
|
||||
@ -240,7 +240,8 @@ static Bitu INT33_Handler(void) {
|
||||
mouse.mickey_y=0;
|
||||
break;
|
||||
case 0x14: /* Exchange event-handler */
|
||||
{ Bit16u oldSeg = mouse.sub_seg;
|
||||
{
|
||||
Bit16u oldSeg = mouse.sub_seg;
|
||||
Bit16u oldOfs = mouse.sub_ofs;
|
||||
Bit16u oldMask= mouse.sub_mask;
|
||||
// Set new values
|
||||
@ -251,7 +252,8 @@ static Bitu INT33_Handler(void) {
|
||||
reg_cx = oldMask;
|
||||
reg_dx = oldOfs;
|
||||
SegSet16(es,oldSeg);
|
||||
}; break;
|
||||
}
|
||||
break;
|
||||
case 0x1c: /* Set interrupt rate */
|
||||
/* Can't really set a rate this is host determined */
|
||||
break;
|
||||
@ -267,9 +269,9 @@ static Bitu INT33_Handler(void) {
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Mouse Function %2X",reg_ax);
|
||||
};
|
||||
}
|
||||
return CBRET_NONE;
|
||||
};
|
||||
}
|
||||
|
||||
static Bitu INT74_Handler(void) {
|
||||
if (mouse.events>0) {
|
||||
@ -301,16 +303,13 @@ static Bitu INT74_Handler(void) {
|
||||
}
|
||||
IO_Write(0xa0,0x20);
|
||||
/* Check for more Events if so reactivate IRQ */
|
||||
|
||||
if (mouse.events) {
|
||||
PIC_ActivateIRQ(12);
|
||||
}
|
||||
|
||||
return CBRET_NONE;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void MOUSE_Init(void) {
|
||||
void MOUSE_Init(Section* sec) {
|
||||
call_int33=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET);
|
||||
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);
|
||||
real_writed(0,(0x74<<2),CALLBACK_RealPointer(call_int74));
|
||||
|
||||
memset((void *)&mouse,0,sizeof(mouse));
|
||||
memset(&mouse,0,sizeof(mouse));
|
||||
mouse_reset();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "mem.h"
|
||||
#include "regs.h"
|
||||
#include "dos_system.h"
|
||||
#include "setup.h"
|
||||
|
||||
|
||||
#define XMS_HANDLES 50 /* 50 XMS Memory Blocks */
|
||||
@ -53,6 +54,8 @@
|
||||
#define XMS_OUT_OF_SPACE 0xa0
|
||||
#define XMS_OUT_OF_HANDLES 0xa1
|
||||
#define XMS_INVALID_HANDLE 0xa2
|
||||
#define XMS_BLOCK_NOT_LOCKED 0xaa
|
||||
#define XMS_BLOCK_LOCKED 0xab
|
||||
|
||||
struct XMS_Block {
|
||||
Bit16u prev,next;
|
||||
@ -291,8 +294,13 @@ foundnew:
|
||||
reg_bl=XMS_INVALID_HANDLE;
|
||||
return CBRET_NONE;
|
||||
}
|
||||
if (xms_handles[reg_dx].locked) xms_handles[reg_dx].locked--;
|
||||
reg_ax=1;reg_bl=0;
|
||||
if (xms_handles[reg_dx].locked) {
|
||||
xms_handles[reg_dx].locked--;
|
||||
reg_ax=1;reg_bl=0;
|
||||
} else {
|
||||
reg_ax=0;
|
||||
reg_bl=XMS_BLOCK_NOT_LOCKED;
|
||||
}
|
||||
break;
|
||||
case XMS_GET_EMB_HANDLE_INFORMATION: /* 0e */
|
||||
/* 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);
|
||||
call_xms=CALLBACK_Allocate();
|
||||
CALLBACK_Setup(call_xms,&XMS_Handler,CB_RETF);
|
||||
@ -345,6 +357,6 @@ void XMS_Init(void) {
|
||||
/* Setup the 1st handle */
|
||||
xms_handles[1].active=true;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
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
|
||||
|
@ -84,7 +84,7 @@ install_sh = @install_sh@
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
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
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
@ -93,8 +93,8 @@ LIBRARIES = $(noinst_LIBRARIES)
|
||||
|
||||
libmisc_a_AR = $(AR) cru
|
||||
libmisc_a_LIBADD =
|
||||
am_libmisc_a_OBJECTS = plugins.$(OBJEXT) programs.$(OBJEXT) \
|
||||
messages.$(OBJEXT) support.$(OBJEXT) setup.$(OBJEXT)
|
||||
am_libmisc_a_OBJECTS = programs.$(OBJEXT) messages.$(OBJEXT) \
|
||||
support.$(OBJEXT) setup.$(OBJEXT)
|
||||
libmisc_a_OBJECTS = $(am_libmisc_a_OBJECTS)
|
||||
|
||||
DEFS = @DEFS@
|
||||
@ -104,9 +104,8 @@ LDFLAGS = @LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/messages.Po ./$(DEPDIR)/plugins.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/programs.Po ./$(DEPDIR)/setup.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/support.Po
|
||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/messages.Po ./$(DEPDIR)/programs.Po \
|
||||
@AMDEP_TRUE@ ./$(DEPDIR)/setup.Po ./$(DEPDIR)/support.Po
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
CXXLD = $(CXX)
|
||||
@ -143,7 +142,6 @@ distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@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)/setup.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/support.Po@am__quote@
|
||||
|
@ -23,24 +23,54 @@
|
||||
#include "cross.h"
|
||||
#include "support.h"
|
||||
#include "setup.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
#define LINE_IN_MAXLEN 1024
|
||||
|
||||
struct MessageBlock
|
||||
{
|
||||
char * name;
|
||||
char * string;
|
||||
MessageBlock * next;
|
||||
struct MessageBlock {
|
||||
string name;
|
||||
string val;
|
||||
MessageBlock(const char* _name, const char* _val):
|
||||
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");
|
||||
/* 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) {
|
||||
E_Exit("MSG:Can't load messages: %s",fname);
|
||||
}
|
||||
@ -67,15 +97,8 @@ static void LoadMessageFile(char * fname) {
|
||||
strcpy(name,linein+1);
|
||||
/* End of string marker */
|
||||
} else if (linein[0]=='.') {
|
||||
/* Save the string internally */
|
||||
size_t total=sizeof(MessageBlock)+strlen(name)+1+strlen(string)+1;
|
||||
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;
|
||||
/* Replace/Add the string to the internal langaugefile */
|
||||
MSG_Replace(name,string);
|
||||
} else {
|
||||
/* Normal string to be added */
|
||||
strcat(string,linein);
|
||||
@ -85,23 +108,29 @@ static void LoadMessageFile(char * fname) {
|
||||
fclose(mfile);
|
||||
}
|
||||
|
||||
|
||||
char * MSG_Get(char * msg) {
|
||||
MessageBlock * index=first_message;
|
||||
while (index) {
|
||||
if (!strcmp(msg,index->name)) return index->string;
|
||||
index=index->next;
|
||||
const char * MSG_Get(char const * msg) {
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
|
||||
if((*tel).name==msg)
|
||||
{
|
||||
return (*tel).val.c_str();
|
||||
}
|
||||
}
|
||||
return "Message not found";
|
||||
return "Message not Found!\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MSG_Init(void) {
|
||||
/* Load the messages from "dosbox.lang file" */
|
||||
first_message=0;
|
||||
char filein[CROSS_LEN];
|
||||
strcpy(filein,dosbox_basedir);
|
||||
strcat(filein,"dosbox.lang");
|
||||
LoadMessageFile(filein);
|
||||
void MSG_Write(const char * location) {
|
||||
FILE* out=fopen(location,"w+b");
|
||||
if(out==NULL) return;//maybe an error?
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
|
||||
fprintf(out,":%s\n%s.\n",(*tel).name.c_str(),(*tel).val.c_str());
|
||||
}
|
||||
fclose(out);
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
@ -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");
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "regs.h"
|
||||
#include "support.h"
|
||||
#include "cross.h"
|
||||
#include "setup.h"
|
||||
|
||||
Bitu call_program;
|
||||
|
||||
@ -55,30 +56,19 @@ void PROGRAMS_MakeFile(char * name,PROGRAMS_Main * main) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Bitu PROGRAMS_Handler(void) {
|
||||
/* This sets up everything for a program start up call */
|
||||
/* First get the current psp */
|
||||
PROGRAM_Info * info=new PROGRAM_Info;
|
||||
info->psp_seg=dos.psp;
|
||||
MEM_BlockRead(PhysMake(dos.psp,0),&info->psp_copy,sizeof(PSP));
|
||||
/* Get the file name cmd_line 0 */
|
||||
PhysPt envblock=PhysMake(info->psp_copy.environment,0);
|
||||
do {} while (mem_readw(envblock++));
|
||||
envblock+=3;
|
||||
MEM_StrCopy(envblock,info->full_name,32);
|
||||
info->psp_copy.cmdtail.buffer[info->psp_copy.cmdtail.count]=0;
|
||||
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);
|
||||
PROGRAMS_Main * handler=0; //It will get sneakily itinialized
|
||||
Bitu size=sizeof(PROGRAMS_Main *);
|
||||
/* Read the handler from program code in memory */
|
||||
PhysPt reader=PhysMake(dos.psp,256+sizeof(exe_block));
|
||||
HostPt writer=(HostPt)&handler;
|
||||
for (;size>0;size--) *writer++=mem_readb(reader++);
|
||||
Program * new_program;
|
||||
(*handler)(&new_program);
|
||||
new_program->Run();
|
||||
delete new_program;
|
||||
return CBRET_NONE;
|
||||
};
|
||||
|
||||
@ -86,11 +76,21 @@ static Bitu PROGRAMS_Handler(void) {
|
||||
/* Main functions used in all program */
|
||||
|
||||
|
||||
Program::Program(PROGRAM_Info * program_info) {
|
||||
prog_info=program_info;
|
||||
Program::Program() {
|
||||
/* 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];
|
||||
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 */
|
||||
/* Taking some short cuts here to not fuck around with memory structure */
|
||||
|
||||
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
|
||||
size_t len=strlen(env_str);
|
||||
while (*envstart) {
|
||||
if (strncasecmp(env_str,envstart,len)==0 && envstart[len]=='=') {
|
||||
return envstart;
|
||||
}
|
||||
envstart+=strlen(envstart)+1;
|
||||
}
|
||||
return 0;
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
char env_string[1024];
|
||||
result.erase();
|
||||
if (!entry[0]) return false;
|
||||
do {
|
||||
MEM_StrCopy(env_read,env_string,1024);
|
||||
if (!env_string[0]) return false;
|
||||
env_read+=strlen(env_string)+1;
|
||||
if (!strchr(env_string,'=')) continue;
|
||||
if (strncasecmp(entry,env_string,strlen(entry))!=0) continue;
|
||||
result=env_string;
|
||||
return true;
|
||||
} while (1);
|
||||
return false;
|
||||
};
|
||||
|
||||
char * Program::GetEnvNum(Bit32u num) {
|
||||
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
|
||||
while (*envstart) {
|
||||
if (!num) return envstart;
|
||||
envstart+=strlen(envstart)+1;
|
||||
bool Program::GetEnvNum(Bitu num,std::string & result) {
|
||||
char env_string[1024];
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
do {
|
||||
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--;
|
||||
}
|
||||
return 0;
|
||||
} while (1);
|
||||
return false;
|
||||
}
|
||||
|
||||
Bit32u Program::GetEnvCount(void) {
|
||||
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
|
||||
Bit32u num=0;
|
||||
while (*envstart) {
|
||||
envstart+=strlen(envstart)+1;
|
||||
Bitu Program::GetEnvCount(void) {
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
Bitu num=0;
|
||||
while (mem_readb(env_read)!=0) {
|
||||
for (;mem_readb(env_read);env_read++) {};
|
||||
env_read++;
|
||||
num++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
bool Program::SetEnv(char * env_entry,char * new_string) {
|
||||
MCB * env_mcb=(MCB *)HostMake(prog_info->psp_copy.environment-1,0);
|
||||
upcase(env_entry);
|
||||
Bit32u env_size=env_mcb->size*16;
|
||||
if (!env_size) E_Exit("SHELL:Illegal environment size");
|
||||
/* First try to find the old entry */
|
||||
size_t len=strlen(env_entry);
|
||||
char * envstart=(char *)HostMake(prog_info->psp_copy.environment,0);
|
||||
while (*envstart) {
|
||||
if (strncasecmp(env_entry,envstart,len)==0 && envstart[len]=='=') {
|
||||
/* Now remove this entry */
|
||||
memmove(envstart,envstart+strlen(envstart)+1,env_size);
|
||||
} else {
|
||||
envstart+=strlen(envstart)+1;
|
||||
env_size-=(strlen(envstart)+1);
|
||||
}
|
||||
bool Program::SetEnv(const char * entry,const char * new_string) {
|
||||
PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
|
||||
PhysPt env_write=env_read;
|
||||
char env_string[1024];
|
||||
do {
|
||||
MEM_StrCopy(env_read,env_string,1024);
|
||||
if (!env_string[0]) break;
|
||||
env_read+=strlen(env_string)+1;
|
||||
if (!strchr(env_string,'=')) continue; /* Remove corrupt entry? */
|
||||
if ((strncasecmp(entry,env_string,strlen(entry))==0) &&
|
||||
env_string[strlen(entry)]=='=') continue;
|
||||
MEM_BlockWrite(env_write,env_string,strlen(env_string)+1);
|
||||
env_write+=strlen(env_string)+1;
|
||||
} while (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;
|
||||
}
|
||||
/* Now add the string if there is space available */
|
||||
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;
|
||||
/* Clear out the final piece of the environment */
|
||||
mem_writed(env_write,0);
|
||||
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 */
|
||||
call_program=CALLBACK_Allocate();
|
||||
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");
|
||||
}
|
||||
|
@ -19,11 +19,353 @@
|
||||
#include "dosbox.h"
|
||||
#include "cross.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);
|
||||
}
|
||||
|
@ -82,49 +82,6 @@ char *trim(char *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) {
|
||||
char * scan=cmd;size_t c_len=strlen(check);
|
||||
@ -215,22 +172,17 @@ void S_Warn(char * format,...) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95)
|
||||
void E_Exit(char * format,...) {
|
||||
|
||||
char buf[1024];
|
||||
|
||||
// SysShutDown();
|
||||
va_list msg;
|
||||
strcpy(buf,"EXIT:");
|
||||
va_start(msg,format);
|
||||
vsprintf(buf+strlen(buf),format,msg);
|
||||
va_end(msg);
|
||||
|
||||
strcat(buf,"\n");
|
||||
printf(buf);
|
||||
printf("Press ENTER to stop\n");
|
||||
fgetc(stdin);
|
||||
GFX_Stop();
|
||||
exit(2);
|
||||
|
||||
};
|
||||
if(errorlevel>=1) {
|
||||
va_list msg;
|
||||
va_start(msg,format);
|
||||
vsprintf(buf,format,msg);
|
||||
va_end(msg);
|
||||
|
||||
strcat(buf,"\n");
|
||||
} else {
|
||||
strcpy(buf,"an unsupported feature\n");
|
||||
}
|
||||
throw(buf);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#define INLINE __forceinline
|
||||
|
||||
#define VERSION "0.55"
|
||||
#define VERSION "0.56"
|
||||
|
||||
#define GCC_ATTRIBUTE(x) /* attribute not supported */
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "setup.h"
|
||||
#include "shell_inc.h"
|
||||
|
||||
Bitu call_shellstop;
|
||||
@ -28,10 +28,8 @@ static Bitu shellstop_handler(void) {
|
||||
return CBRET_STOP;
|
||||
}
|
||||
|
||||
static void SHELL_ProgramStart(PROGRAM_Info * info) {
|
||||
DOS_Shell * tempshell=new DOS_Shell(info);
|
||||
tempshell->Run();
|
||||
delete tempshell;
|
||||
static void SHELL_ProgramStart(Program * * make) {
|
||||
*make=new DOS_Shell;
|
||||
}
|
||||
|
||||
#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;
|
||||
echo=true;
|
||||
exit=false;
|
||||
@ -96,16 +94,19 @@ void DOS_Shell::ParseLine(char * line) {
|
||||
|
||||
|
||||
void DOS_Shell::Run(void) {
|
||||
/* Check for a direct Command */
|
||||
if (strncasecmp(prog_info->cmd_line,"/C ",3)==0) {
|
||||
ParseLine(prog_info->cmd_line+3);
|
||||
char input_line[CMD_MAXLINE];
|
||||
std::string line;
|
||||
if (cmd->FindString("/C",line,true)) {
|
||||
strcpy(input_line,line.c_str());
|
||||
line.erase();
|
||||
return;
|
||||
}
|
||||
/* Start a normal shell and check for a first command init */
|
||||
WriteOut(MSG_Get("SHELL_STARTUP"));
|
||||
char input_line[CMD_MAXLINE];
|
||||
if (strncasecmp(prog_info->cmd_line,"/INIT ",6)==0) {
|
||||
ParseLine(prog_info->cmd_line+6);
|
||||
if (cmd->FindString("/INIT",line,true)) {
|
||||
strcpy(input_line,line.c_str());
|
||||
line.erase();
|
||||
ParseLine(input_line);
|
||||
}
|
||||
do {
|
||||
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() {
|
||||
/* 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();
|
||||
|
||||
CALLBACK_Setup(call_shellstop,shellstop_handler,CB_IRET);
|
||||
PROGRAMS_MakeFile("COMMAND.COM",SHELL_ProgramStart);
|
||||
|
||||
/* Now call up the shell for the first time */
|
||||
Bit16u psp_seg=DOS_GetMemory(16);
|
||||
Bit16u env_seg=DOS_GetMemory(1+(4096/16));
|
||||
Bit16u psp_seg=DOS_GetMemory(16+1)+1;
|
||||
Bit16u env_seg=DOS_GetMemory(1+(4096/16))+1;
|
||||
Bit16u stack_seg=DOS_GetMemory(2048/16);
|
||||
SegSet16(ss,stack_seg);
|
||||
reg_sp=2046;
|
||||
/* Setup a fake MCB for the environment */
|
||||
MCB * env_mcb=(MCB *)HostMake(env_seg,0);
|
||||
/* Setup MCB and the environment */
|
||||
MCB * env_mcb=(MCB *)HostMake(env_seg-1,0);
|
||||
env_mcb->psp_segment=psp_seg;
|
||||
env_mcb->size=4096/16;
|
||||
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);
|
||||
Bit32u i;
|
||||
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(psp_seg,offsetof(PSP,files));
|
||||
/* Save old DTA in psp */
|
||||
psp->dta=dos.dta;
|
||||
/* Set the environment and clear it */
|
||||
psp->environment=env_seg+1;
|
||||
mem_writew(Real2Phys(RealMake(env_seg+1,0)),0);
|
||||
DOS_PSP psp(psp_seg);
|
||||
psp.MakeNew(0);
|
||||
psp.SetFileHandle(STDIN ,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDOUT,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDERR,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDAUX,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDNUL,DOS_FindDevice("CON"));
|
||||
psp.SetFileHandle(STDPRN,DOS_FindDevice("CON"));
|
||||
psp.SetParent(psp_seg);
|
||||
/* Set the environment */
|
||||
psp.SetEnvironment(env_seg);
|
||||
/* Set the command line for the shell start up */
|
||||
CommandTail tail;
|
||||
tail.count=strlen(init_line);
|
||||
strcpy(tail.buffer,init_line);
|
||||
MEM_BlockWrite(PhysMake(psp_seg,128),&tail,128);
|
||||
/* Setup internal DOS Variables */
|
||||
dos.dta=RealMake(psp_seg,0x80);
|
||||
dos.dta=psp.GetDTA();
|
||||
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 */
|
||||
VFILE_Register("AUTOEXEC.BAT",(Bit8u *)autoexec_data,strlen(autoexec_data));
|
||||
SHELL_ProgramStart(&info);
|
||||
Program * new_program;
|
||||
SHELL_ProgramStart(&new_program);
|
||||
new_program->Run();
|
||||
delete new_program;
|
||||
}
|
||||
|
@ -24,27 +24,18 @@
|
||||
|
||||
|
||||
BatchFile::BatchFile(DOS_Shell * host,char * name, char * cmd_line) {
|
||||
/* Go through the command line */
|
||||
char * cmd_write=cmd_buffer;
|
||||
prev=host->bf;
|
||||
echo=host->echo;
|
||||
shell=host;
|
||||
cmd_count=0;
|
||||
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++;
|
||||
}
|
||||
cmd=new CommandLine(0,cmd_line);
|
||||
if (!DOS_OpenFile(name,0,&file_handle)) {
|
||||
//TODO Come up with something better
|
||||
E_Exit("SHELL:Can't open BatchFile");
|
||||
}
|
||||
line_count=0;
|
||||
};
|
||||
|
||||
BatchFile::~BatchFile() {
|
||||
delete cmd;
|
||||
DOS_CloseFile(file_handle);
|
||||
shell->bf=prev;
|
||||
shell->echo=echo;
|
||||
@ -63,8 +54,8 @@ emptyline:
|
||||
*cmd_write++=c;
|
||||
}
|
||||
} while (c!='\n' && n);
|
||||
*cmd_write++=0;
|
||||
if (!n) {
|
||||
*cmd_write=0;
|
||||
if (!n && cmd_write==temp) {
|
||||
delete this;
|
||||
return false;
|
||||
}
|
||||
@ -77,29 +68,51 @@ emptyline:
|
||||
while (*cmd_read) {
|
||||
env_write=env_name;
|
||||
if (*cmd_read=='%') {
|
||||
cmd_read++;
|
||||
/* Find the fullstring of this */
|
||||
|
||||
|
||||
continue;
|
||||
|
||||
cmd_read++;
|
||||
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;
|
||||
} 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 {
|
||||
*cmd_write++=*cmd_read++;
|
||||
}
|
||||
*cmd_write=0;
|
||||
}
|
||||
return true;
|
||||
|
||||
*cmd_write=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool BatchFile::Goto(char * where) {
|
||||
Bit32u pos=0;
|
||||
char cmd[CMD_MAXLINE];
|
||||
char * cmd_write;
|
||||
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;
|
||||
again:
|
||||
cmd_write=cmd;
|
||||
|
@ -24,19 +24,21 @@
|
||||
|
||||
|
||||
static SHELL_Cmd cmd_list[]={
|
||||
"CD", 0, &DOS_Shell::CMD_CHDIR, "Change Directory.",
|
||||
"CLS", 0, &DOS_Shell::CMD_CLS, "Clear screen.",
|
||||
"CD", 0, &DOS_Shell::CMD_CHDIR, "SHELL_CMD_CHDIR_HELP",
|
||||
"CLS", 0, &DOS_Shell::CMD_CLS, "SHELL_CMD_CLS_HELP",
|
||||
// "COPY", 0, &DOS_Shell::CMD_COPY, "Copy Files.",
|
||||
"DIR", 0, &DOS_Shell::CMD_DIR, "Directory View.",
|
||||
"ECHO", 0, &DOS_Shell::CMD_ECHO, "Display messages and enable/disable command echoing.",
|
||||
"EXIT", 0, &DOS_Shell::CMD_EXIT, "Exit from the shell.",
|
||||
"HELP", 0, &DOS_Shell::CMD_HELP, "Show help.",
|
||||
"MD", 0, &DOS_Shell::CMD_MKDIR, "Make Directory.",
|
||||
"RD", 0, &DOS_Shell::CMD_RMDIR, "Remove Directory.",
|
||||
"SET", 0, &DOS_Shell::CMD_SET, "Change environment variables.",
|
||||
"IF", 0, &DOS_Shell::CMD_IF, "Performs conditional processing in batch programs.",
|
||||
"GOTO", 0, &DOS_Shell::CMD_GOTO, "Jump to a labeled line in a batch script.",
|
||||
"TYPE", 0, &DOS_Shell::CMD_TYPE, "Display the contents of a text-file.",
|
||||
"DIR", 0, &DOS_Shell::CMD_DIR, "SHELL_CMD_DIR_HELP",
|
||||
"ECHO", 0, &DOS_Shell::CMD_ECHO, "SHELL_CMD_ECHO_HELP",
|
||||
"EXIT", 0, &DOS_Shell::CMD_EXIT, "SHELL_CMD_EXIT_HELP",
|
||||
"HELP", 0, &DOS_Shell::CMD_HELP, "SHELL_CMD_HELP_HELP",
|
||||
"MD", 0, &DOS_Shell::CMD_MKDIR, "SHELL_CMD_MKDIR_HELP",
|
||||
"RD", 0, &DOS_Shell::CMD_RMDIR, "SHELL_CMD_RMDIR_HELP",
|
||||
"SET", 0, &DOS_Shell::CMD_SET, "SHELL_CMD_SET_HELP",
|
||||
"IF", 0, &DOS_Shell::CMD_IF, "SHELL_CMD_IF_HELP",
|
||||
"GOTO", 0, &DOS_Shell::CMD_GOTO, "SHELL_CMD_GOTO_HELP",
|
||||
"TYPE", 0, &DOS_Shell::CMD_TYPE, "SHELL_CMD_TYPE_HELP",
|
||||
"REM", 0, &DOS_Shell::CMD_REM, "SHELL_CMD_REM_HELP",
|
||||
|
||||
/*
|
||||
"CHDIR", 0, &DOS_Shell::CMD_CHDIR, "Change Directory",
|
||||
"MKDIR", 0, &DOS_Shell::CMD_MKDIR, "Make Directory",
|
||||
@ -63,9 +65,8 @@ void DOS_Shell::DoCommand(char * line) {
|
||||
Bit32u cmd_index=0;
|
||||
while (cmd_list[cmd_index].name) {
|
||||
if (strcasecmp(cmd_list[cmd_index].name,cmd)==0) {
|
||||
//TODO CHECK Flags
|
||||
(this->*(cmd_list[cmd_index].handler))(line);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
cmd_index++;
|
||||
}
|
||||
@ -84,7 +85,7 @@ void DOS_Shell::CMD_HELP(char * args){
|
||||
WriteOut(MSG_Get("SHELL_CMD_HELP"));
|
||||
Bit32u cmd_index=0;
|
||||
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++;
|
||||
}
|
||||
|
||||
@ -148,8 +149,8 @@ void DOS_Shell::CMD_RMDIR(char * args) {
|
||||
}
|
||||
};
|
||||
|
||||
static void FormatNumber(Bit32u num,char * buf) {
|
||||
Bit32u numm,numk,numb;
|
||||
static void FormatNumber(Bitu num,char * buf) {
|
||||
Bitu numm,numk,numb;
|
||||
numb=num % 1000;
|
||||
num/=1000;
|
||||
numk=num % 1000;
|
||||
@ -178,7 +179,6 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem);
|
||||
return;
|
||||
}
|
||||
|
||||
Bit32u byte_count,file_count,dir_count;
|
||||
Bit32u w_count=0;
|
||||
byte_count=file_count=dir_count=0;
|
||||
@ -193,48 +193,47 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
*(strrchr(path,'\\')+1)=0;
|
||||
WriteOut(MSG_Get("SHELL_CMD_DIR_INTRO"),path);
|
||||
|
||||
DTA_FindBlock * dta;
|
||||
dta=(DTA_FindBlock *)Real2Host(dos.dta);
|
||||
DOS_DTA dta(dos.dta);
|
||||
bool ret=DOS_FindFirst(args,0xffff);
|
||||
if (!ret) {
|
||||
WriteOut(MSG_Get("SHELL_CMD_FILE_NOT_FOUND"),args);
|
||||
return;
|
||||
}
|
||||
|
||||
while (ret) {
|
||||
|
||||
/* 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="";
|
||||
if (!optW && (*dta->name != '.')) {
|
||||
ext = strrchr(dta->name, '.');
|
||||
if (!optW && (name[0] != '.')) {
|
||||
ext = strrchr(name, '.');
|
||||
if (!ext) ext = "";
|
||||
else *ext++ = '\0';
|
||||
};
|
||||
|
||||
Bit8u day = dta->date & 0x001f;
|
||||
Bit8u month = (dta->date >> 5) & 0x000f;
|
||||
Bit8u hour = dta->time >> 5 >> 6;
|
||||
Bit8u minute = (dta->time >> 5) & 0x003f;
|
||||
Bit16u year = (dta->date >> 9) + 1980;
|
||||
}
|
||||
Bit8u day = date & 0x001f;
|
||||
Bit8u month = (date >> 5) & 0x000f;
|
||||
Bit16u year = (date >> 9) + 1980;
|
||||
Bit8u hour = (time >> 5 ) >> 6;
|
||||
Bit8u minute = (time >> 5) & 0x003f;
|
||||
|
||||
/* output the file */
|
||||
if (dta->attr & DOS_ATTR_DIRECTORY) {
|
||||
if (attr & DOS_ATTR_DIRECTORY) {
|
||||
if (optW) {
|
||||
WriteOut("[%s]",dta->name);
|
||||
for (Bitu i=14-strlen(dta->name);i>0;i--) WriteOut(" ");
|
||||
WriteOut("[%s]",name);
|
||||
for (Bitu i=14-strlen(name);i>0;i--) WriteOut(" ");
|
||||
} 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++;
|
||||
} else {
|
||||
if (optW) {
|
||||
WriteOut("%-16s",dta->name);
|
||||
WriteOut("%-16s",name);
|
||||
} else {
|
||||
FormatNumber(dta->size,numformat);
|
||||
WriteOut("%-8s %-3s %16s %02d-%02d-%04d %2d:%02d\n",dta->name,ext,numformat,day,month,year,hour,minute);
|
||||
FormatNumber(size,numformat);
|
||||
WriteOut("%-8s %-3s %16s %02d-%02d-%04d %2d:%02d\n",name,ext,numformat,day,month,year,hour,minute);
|
||||
}
|
||||
file_count++;
|
||||
byte_count+=dta->size;
|
||||
byte_count+=size;
|
||||
}
|
||||
if (optW) {
|
||||
w_count++;
|
||||
@ -247,8 +246,15 @@ void DOS_Shell::CMD_DIR(char * args) {
|
||||
/* Show the summary of results */
|
||||
FormatNumber(byte_count,numformat);
|
||||
WriteOut(MSG_Get("SHELL_CMD_DIR_BYTES_USED"),file_count,numformat);
|
||||
Bit8u drive=dta.GetSearchDrive();
|
||||
//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,§ors_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);
|
||||
}
|
||||
|
||||
@ -258,23 +264,22 @@ void DOS_Shell::CMD_COPY(char * args) {
|
||||
WriteOut(MSG_Get("SHELL_ILLEGAL_SWITCH"),rem);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DOS_Shell::CMD_SET(char * args) {
|
||||
std::string line;
|
||||
if (!*args) {
|
||||
/* No command line show all environment lines */
|
||||
Bit32u count=GetEnvCount();
|
||||
for (Bit32u a=0;a<count;a++) {
|
||||
WriteOut("%s\n",GetEnvNum(a));
|
||||
Bitu count=GetEnvCount();
|
||||
for (Bitu a=0;a<count;a++) {
|
||||
if (GetEnvNum(a,line)) WriteOut("%s\n",line.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
char * p=strpbrk(args, "=");
|
||||
if (!p) {
|
||||
p=GetEnvStr(args);
|
||||
if (p) WriteOut("%s\n",p);
|
||||
else WriteOut(MSG_Get("SHELL_CMD_SET_NOT_SET"),args);
|
||||
if (!GetEnvStr(args,line)) WriteOut(MSG_Get("SHELL_CMD_SET_NOT_SET"),args);
|
||||
WriteOut("%s\n",line.c_str());
|
||||
} else {
|
||||
*p++=0;
|
||||
if (!SetEnv(args,p)) {
|
||||
@ -377,5 +382,6 @@ nextfile:
|
||||
if (*args) goto nextfile;
|
||||
}
|
||||
|
||||
void DOS_Shell::CMD_REM(char * args) {
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "regs.h"
|
||||
#include "support.h"
|
||||
#include "callback.h"
|
||||
#include "setup.h"
|
||||
|
||||
#define CMD_MAXLINE 4096
|
||||
#define CMD_MAXCMDS 20
|
||||
@ -39,20 +40,17 @@ public:
|
||||
bool ReadLine(char * line);
|
||||
bool Goto(char * where);
|
||||
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;
|
||||
DOS_Shell * shell;
|
||||
BatchFile * prev;
|
||||
CommandLine * cmd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DOS_Shell : public Program {
|
||||
public:
|
||||
DOS_Shell(PROGRAM_Info * program_info);
|
||||
DOS_Shell();
|
||||
void Run(void);
|
||||
/* A load of subfunctions */
|
||||
void ParseLine(char * line);
|
||||
@ -77,6 +75,7 @@ public:
|
||||
void CMD_IF(char * args);
|
||||
void CMD_GOTO(char * args);
|
||||
void CMD_TYPE(char * args);
|
||||
void CMD_REM(char * args);
|
||||
void SyntaxError(void);
|
||||
|
||||
/* The shell's variables */
|
||||
|
@ -29,7 +29,6 @@ void DOS_Shell::ShowPrompt(void) {
|
||||
WriteOut("%c:\\%s>",drive,dir);
|
||||
}
|
||||
|
||||
|
||||
static void outc(Bit8u c) {
|
||||
Bit16u n=1;
|
||||
DOS_WriteFile(STDOUT,&c,&n);
|
||||
@ -119,14 +118,17 @@ void DOS_Shell::InputCommand(char * line) {
|
||||
size_t first_len=strlen(old.buffer)+1;
|
||||
memmove(&old.buffer[first_len],&old.buffer[0],CMD_OLDSIZE-first_len);
|
||||
strcpy(old.buffer,line);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void DOS_Shell::Execute(char * name,char * args) {
|
||||
char * fullname;
|
||||
|
||||
char line[255];
|
||||
if(strlen(args)!=0){
|
||||
line[0]=' ';line[1]=0;
|
||||
strcat(line,args);
|
||||
}else{
|
||||
line[0]=0;
|
||||
};
|
||||
/* check for a drive change */
|
||||
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) {
|
||||
/* Run the .bat file */
|
||||
bf=new BatchFile(this,fullname,args);
|
||||
bf=new BatchFile(this,fullname,line);
|
||||
} else {
|
||||
/* Run the .exe or .com file from the shell */
|
||||
/* Allocate some stack space for tables in physical memory */
|
||||
reg_sp-=0x200;
|
||||
//Add Parameter block
|
||||
DOS_ParamBlock block(SegPhys(ss)+reg_sp);
|
||||
block.Clear();
|
||||
//Add a filename
|
||||
RealPt file_name=RealMakeSeg(ss,reg_sp+0x20);
|
||||
MEM_BlockWrite(Real2Phys(file_name),fullname,strlen(fullname)+1);
|
||||
/* Fill the command line */
|
||||
CommandTail cmd;
|
||||
if (strlen(args)>126) args[126]=0;
|
||||
cmd.count=strlen(args);
|
||||
memcpy(cmd.buffer,args,strlen(args));
|
||||
cmd.buffer[strlen(args)]=0xd;
|
||||
MEM_BlockWrite(PhysMake(prog_info->psp_seg,128),&cmd,128);
|
||||
|
||||
block.InitExec(RealMake(prog_info->psp_seg,128));
|
||||
if (strlen(line)>126) line[126]=0;
|
||||
cmd.count=strlen(line);
|
||||
memcpy(cmd.buffer,line,strlen(line));
|
||||
cmd.buffer[strlen(line)]=0xd;
|
||||
/* Copy command line in stack block too */
|
||||
MEM_BlockWrite(SegPhys(ss)+reg_sp+0x100,&cmd,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 */
|
||||
RealPt newcsip;
|
||||
newcsip=CALLBACK_RealPointer(call_shellstop);
|
||||
RealPt newcsip=CALLBACK_RealPointer(call_shellstop);
|
||||
SegSet16(cs,RealSeg(newcsip));
|
||||
reg_ip=RealOff(newcsip);
|
||||
/* Start up a dos execute interrupt */
|
||||
@ -179,8 +183,6 @@ void DOS_Shell::Execute(char * name,char * args) {
|
||||
CALLBACK_RunRealInt(0x21);
|
||||
reg_sp+=0x200;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -193,34 +195,28 @@ static char which_ret[DOS_PATHLENGTH];
|
||||
|
||||
char * DOS_Shell::Which(char * name) {
|
||||
/* 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 */
|
||||
char * ext=strrchr(name,'.');
|
||||
if (ext) if (strlen(ext)>4) ext=0;
|
||||
if (ext) {
|
||||
if (DOS_FileExists(name)) return name;
|
||||
} else {
|
||||
/* try to find .exe .com .bat */
|
||||
strcpy(which_ret,name);
|
||||
strcat(which_ret,bat_ext);
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
/* try to find .com .exe .bat */
|
||||
strcpy(which_ret,name);
|
||||
strcat(which_ret,com_ext);
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
strcpy(which_ret,name);
|
||||
strcat(which_ret,exe_ext);
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
strcpy(which_ret,name);
|
||||
strcat(which_ret,bat_ext);
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
}
|
||||
|
||||
/* No Path in filename look through %path% */
|
||||
|
||||
static char path[DOS_PATHLENGTH];
|
||||
char * pathenv=GetEnvStr("PATH");
|
||||
/* No Path in filename look through path environment string */
|
||||
static char path[DOS_PATHLENGTH];std::string temp;
|
||||
if (!GetEnvStr("PATH",temp)) return 0;
|
||||
const char * pathenv=temp.c_str();
|
||||
if (!pathenv) return 0;
|
||||
pathenv=strchr(pathenv,'=');
|
||||
if (!pathenv) return 0;
|
||||
@ -238,17 +234,16 @@ char * DOS_Shell::Which(char * name) {
|
||||
if (ext) {
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
} else {
|
||||
strcpy(which_ret,path);
|
||||
strcat(which_ret,bat_ext);
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
strcpy(which_ret,path);
|
||||
strcat(which_ret,com_ext);
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
strcpy(which_ret,path);
|
||||
strcat(which_ret,exe_ext);
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
strcpy(which_ret,path);
|
||||
strcat(which_ret,bat_ext);
|
||||
if (DOS_FileExists(which_ret)) return which_ret;
|
||||
}
|
||||
|
||||
path_write=path;
|
||||
if (*pathenv) pathenv++;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 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"
|
||||
|
||||
@ -75,7 +75,7 @@ BSC32=bscmake.exe
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 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
|
||||
|
||||
@ -459,10 +459,6 @@ SOURCE=..\src\misc\messages.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\misc\plugins.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\src\misc\programs.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
Loading…
Reference in New Issue
Block a user